밀버스 하이브리드 서치 리트리버
개요
Milvus는 임베딩 유사도 검색 및 AI 애플리케이션을 강화하기 위해 구축된 오픈 소스 벡터 데이터베이스입니다. Milvus는 비정형 데이터 검색의 접근성을 높이고 배포 환경에 관계없이 일관된 사용자 경험을 제공합니다.
밀도 검색과 희소 벡터 검색의 강점을 결합한 Milvus 하이브리드 검색 리트리버를 시작하는 데 도움이 될 것입니다. 모든 MilvusCollectionHybridSearchRetriever
기능 및 구성에 대한 자세한 설명서는 API 참조를 참조하세요.
Milvus 멀티-벡터 검색 문서도 참조하세요.
통합 세부 정보
리트리버 | 자체 호스트 | 클라우드 제공 | 패키지 |
---|---|---|---|
밀버스컬렉션하이브리드검색리트리버 | ✅ | ❌ | langchain_milvus |
설정
개별 쿼리에서 자동화된 추적을 원한다면, 아래에 댓글을 달지 않고 LangSmith API 키를 설정할 수도 있습니다:
# os.environ["LANGSMITH_API_KEY"] = getpass.getpass("Enter your LangSmith API key: ")
# os.environ["LANGSMITH_TRACING"] = "true"
설치
이 리트리버는 langchain-milvus
패키지에 있습니다. 이 가이드를 사용하려면 다음 종속성이 필요합니다:
%pip install --upgrade --quiet pymilvus[model] langchain-milvus langchain-openai
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_milvus.retrievers import MilvusCollectionHybridSearchRetriever
from langchain_milvus.utils.sparse import BM25SparseEmbedding
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from pymilvus import (
Collection,
CollectionSchema,
DataType,
FieldSchema,
WeightedRanker,
connections,
)
Milvus 서비스 시작
밀버스 서비스를 시작하려면 밀버스 문서를 참조하세요.
밀버스를 시작한 후에는 밀버스 연결 URI를 지정해야 합니다.
CONNECTION_URI = "http://localhost:19530"
OpenAI API 키 준비
OpenAI 설명서를 참고하여 OpenAI API 키를 발급받은 후 환경 변수로 설정합니다.
export OPENAI_API_KEY=<your_api_key>
조밀하고 희박한 임베딩 함수 준비하기
소설에 대한 10개의 가짜 설명을 가상으로 만들어 봅시다. 실제 제작에서는 대량의 텍스트 데이터가 될 수 있습니다.
texts = [
"In 'The Whispering Walls' by Ava Moreno, a young journalist named Sophia uncovers a decades-old conspiracy hidden within the crumbling walls of an ancient mansion, where the whispers of the past threaten to destroy her own sanity.",
"In 'The Last Refuge' by Ethan Blackwood, a group of survivors must band together to escape a post-apocalyptic wasteland, where the last remnants of humanity cling to life in a desperate bid for survival.",
"In 'The Memory Thief' by Lila Rose, a charismatic thief with the ability to steal and manipulate memories is hired by a mysterious client to pull off a daring heist, but soon finds themselves trapped in a web of deceit and betrayal.",
"In 'The City of Echoes' by Julian Saint Clair, a brilliant detective must navigate a labyrinthine metropolis where time is currency, and the rich can live forever, but at a terrible cost to the poor.",
"In 'The Starlight Serenade' by Ruby Flynn, a shy astronomer discovers a mysterious melody emanating from a distant star, which leads her on a journey to uncover the secrets of the universe and her own heart.",
"In 'The Shadow Weaver' by Piper Redding, a young orphan discovers she has the ability to weave powerful illusions, but soon finds herself at the center of a deadly game of cat and mouse between rival factions vying for control of the mystical arts.",
"In 'The Lost Expedition' by Caspian Grey, a team of explorers ventures into the heart of the Amazon rainforest in search of a lost city, but soon finds themselves hunted by a ruthless treasure hunter and the treacherous jungle itself.",
"In 'The Clockwork Kingdom' by Augusta Wynter, a brilliant inventor discovers a hidden world of clockwork machines and ancient magic, where a rebellion is brewing against the tyrannical ruler of the land.",
"In 'The Phantom Pilgrim' by Rowan Welles, a charismatic smuggler is hired by a mysterious organization to transport a valuable artifact across a war-torn continent, but soon finds themselves pursued by deadly assassins and rival factions.",
"In 'The Dreamwalker's Journey' by Lyra Snow, a young dreamwalker discovers she has the ability to enter people's dreams, but soon finds herself trapped in a surreal world of nightmares and illusions, where the boundaries between reality and fantasy blur.",
]
고밀도 벡터를 생성하기 위해 OpenAI 임베딩을 사용하고, 스파스 벡터를 생성하기 위해 BM25 알고리즘을 사용합니다.
고밀도 임베딩 함수 초기화 및 차원 가져오기
dense_embedding_func = OpenAIEmbeddings()
dense_dim = len(dense_embedding_func.embed_query(texts[1]))
dense_dim
1536
스파스 임베딩 함수를 초기화합니다.
스파스 임베딩의 출력은 입력 텍스트의 키워드의 인덱스와 가중치를 나타내는 스파스 벡터 집합입니다.
sparse_embedding_func = BM25SparseEmbedding(corpus=texts)
sparse_embedding_func.embed_query(texts[1])
{0: 0.4270424944042204,
21: 1.845826690498331,
22: 1.845826690498331,
23: 1.845826690498331,
24: 1.845826690498331,
25: 1.845826690498331,
26: 1.845826690498331,
27: 1.2237754316221157,
28: 1.845826690498331,
29: 1.845826690498331,
30: 1.845826690498331,
31: 1.845826690498331,
32: 1.845826690498331,
33: 1.845826690498331,
34: 1.845826690498331,
35: 1.845826690498331,
36: 1.845826690498331,
37: 1.845826690498331,
38: 1.845826690498331,
39: 1.845826690498331}
밀버스 컬렉션 생성 및 데이터 로드
연결 URI 초기화 및 연결 설정
connections.connect(uri=CONNECTION_URI)
필드 이름 및 해당 데이터 유형 정의
pk_field = "doc_id"
dense_field = "dense_vector"
sparse_field = "sparse_vector"
text_field = "text"
fields = [
FieldSchema(
name=pk_field,
dtype=DataType.VARCHAR,
is_primary=True,
auto_id=True,
max_length=100,
),
FieldSchema(name=dense_field, dtype=DataType.FLOAT_VECTOR, dim=dense_dim),
FieldSchema(name=sparse_field, dtype=DataType.SPARSE_FLOAT_VECTOR),
FieldSchema(name=text_field, dtype=DataType.VARCHAR, max_length=65_535),
]
정의된 스키마로 컬렉션 생성
schema = CollectionSchema(fields=fields, enable_dynamic_field=False)
collection = Collection(
name="IntroductionToTheNovels", schema=schema, consistency_level="Strong"
)
밀도 및 희소 벡터에 대한 인덱스 정의
dense_index = {"index_type": "FLAT", "metric_type": "IP"}
collection.create_index("dense_vector", dense_index)
sparse_index = {"index_type": "SPARSE_INVERTED_INDEX", "metric_type": "IP"}
collection.create_index("sparse_vector", sparse_index)
collection.flush()
컬렉션에 엔티티를 삽입하고 컬렉션 로드하기
entities = []
for text in texts:
entity = {
dense_field: dense_embedding_func.embed_documents([text])[0],
sparse_field: sparse_embedding_func.embed_documents([text])[0],
text_field: text,
}
entities.append(entity)
collection.insert(entities)
collection.load()
인스턴스화
이제 리트리버를 인스턴스화하여 희소 및 고밀도 필드에 대한 검색 매개변수를 정의할 수 있습니다:
sparse_search_params = {"metric_type": "IP"}
dense_search_params = {"metric_type": "IP", "params": {}}
retriever = MilvusCollectionHybridSearchRetriever(
collection=collection,
rerank=WeightedRanker(0.5, 0.5),
anns_fields=[dense_field, sparse_field],
field_embeddings=[dense_embedding_func, sparse_embedding_func],
field_search_params=[dense_search_params, sparse_search_params],
top_k=3,
text_field=text_field,
)
이 리트리버의 입력 매개변수에서는 밀도 임베딩과 희소 임베딩을 사용하여 이 컬렉션의 두 필드에 대해 하이브리드 검색을 수행하고 가중치 순위 재지정을 위해 WeightedRanker를 사용합니다. 마지막으로 상위 K 문서 3개가 반환됩니다.
사용법
retriever.invoke("What are the story about ventures?")
[Document(page_content="In 'The Lost Expedition' by Caspian Grey, a team of explorers ventures into the heart of the Amazon rainforest in search of a lost city, but soon finds themselves hunted by a ruthless treasure hunter and the treacherous jungle itself.", metadata={'doc_id': '449281835035545843'}),
Document(page_content="In 'The Phantom Pilgrim' by Rowan Welles, a charismatic smuggler is hired by a mysterious organization to transport a valuable artifact across a war-torn continent, but soon finds themselves pursued by deadly assassins and rival factions.", metadata={'doc_id': '449281835035545845'}),
Document(page_content="In 'The Dreamwalker's Journey' by Lyra Snow, a young dreamwalker discovers she has the ability to enter people's dreams, but soon finds herself trapped in a surreal world of nightmares and illusions, where the boundaries between reality and fantasy blur.", metadata={'doc_id': '449281835035545846'})]
체인 내에서 사용
ChatOpenAI 초기화 및 프롬프트 템플릿 정의하기
llm = ChatOpenAI()
PROMPT_TEMPLATE = """
Human: You are an AI assistant, and provides answers to questions by using fact based and statistical information when possible.
Use the following pieces of information to provide a concise answer to the question enclosed in <question> tags.
<context>
{context}
</context>
<question>
{question}
</question>
Assistant:"""
prompt = PromptTemplate(
template=PROMPT_TEMPLATE, input_variables=["context", "question"]
)
문서 서식 지정 함수 정의하기
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
리트리버 및 기타 구성 요소를 사용하여 체인 정의하기
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
정의된 체인을 사용하여 쿼리 수행하기
rag_chain.invoke("What novels has Lila written and what are their contents?")
"Lila Rose has written 'The Memory Thief,' which follows a charismatic thief with the ability to steal and manipulate memories as they navigate a daring heist and a web of deceit and betrayal."
컬렉션 삭제하기
collection.drop()
API 참조
모든 MilvusCollectionHybridSearchRetriever
기능 및 구성에 대한 자세한 설명은 API 참조로 이동하세요.