MultiQueryEmbeddingRetriever

MultiQueryEmbeddingRetriever

임베딩 기반 Retriever로 여러 개의 검색어를 병렬로 사용해 문서를 검색해 주는 컴포넌트예요.

출처: 문서

본문

MultiQueryEmbeddingRetriever는 여러 검색어를 병렬로 검색해서 리트리벌 재현율(recall)을 높여요. 각 검색어는 Text Embedder로 임베딩으로 바뀌고, 임베딩 기반 Retriever가 관련 문서를 가져오죠.

이 컴포넌트는:

  • 스레드 풀(thread pool)로 검색어를 병렬 처리해 성능을 개선해요.
  • 문서 내용을 기준으로 결과의 중복을 자동으로 제거해요.
  • 최종 결과를 관련성 점수순으로 정렬해요.

이 Retriever는 단일 사용자 검색어에서 여러 검색어 변형을 만들어 내는 QueryExpander와 함께 쓸 때 특히 효과적이에요. 이 변형들로 검색하면 원래 검색어 문구와 정확히 맞지 않아도 관련 있는 문서를 찾을 수 있어요.

문서가 사용자 검색어와 다른 단어를 쓰거나, RAG 파이프라인에서 더 다양한 결과를 얻고 싶을 때 MultiQueryEmbeddingRetriever를 쓰세요. 여러 검색어를 돌리는 건 시간이 더 걸리지만 max_workers를 늘려 병렬로 실행하면 빨라져요.

언제 MultiQueryTextRetriever를 쓸까?

정확한 키워드 일치가 필요하고 임베딩을 안 쓰고 싶다면 MultiQueryTextRetriever를 쓰세요. InMemoryBM25Retriever 같은 텍스트 기반 Retriever와 동작하며, 검색어 확장으로 동의어를 만들 수 있을 때 더 좋아요.

추가 Retriever 파라미터 넘기기

retriever_kwargs를 사용해 내부 Retriever에 추가 파라미터를 넘길 수 있어요.

result = multi_query_retriever.run(
    queries=["renewable energy", "sustainable power"],
    retriever_kwargs={"top_k": 5},
)

더 알아보기 (Learn more)

검색 파이프라인을 돌리기 전에 문서를 Document Embedder로 임베딩해서 Document Store에 저장해 두어야 해요.

이 페이지의 예제는 sentence-transformers-haystack 패키지의 Sentence Transformers 임베더를 사용해요. 예제를 실행하려면 설치하세요.

pip install sentence-transformers-haystack
from haystack import Document, Pipeline
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack_integrations.components.embedders.sentence_transformers import (
    SentenceTransformersTextEmbedder,
    SentenceTransformersDocumentEmbedder,
)
from haystack.components.retrievers import (
    InMemoryEmbeddingRetriever,
    MultiQueryEmbeddingRetriever,
)
from haystack.components.query import QueryExpander


documents = [
    Document(
        content="Renewable energy is energy that is collected from renewable resources.",
    ),
    Document(
        content="Solar energy is a type of green energy that is harnessed from the sun.",
    ),
    Document(
        content="Wind energy is another type of green energy that is generated by wind turbines.",
    ),
    Document(
        content="Geothermal energy is heat that comes from the sub-surface of the earth.",
    ),
]

doc_store = InMemoryDocumentStore()
doc_embedder = SentenceTransformersDocumentEmbedder(
    model="sentence-transformers/all-MiniLM-L6-v2",
)
documents_with_embeddings = doc_embedder.run(documents)["documents"]
doc_store.write_documents(documents_with_embeddings)

pipeline = Pipeline()
pipeline.add_component("query_expander", QueryExpander(n_expansions=3))
pipeline.add_component(
    "retriever",
    MultiQueryEmbeddingRetriever(
        retriever=InMemoryEmbeddingRetriever(document_store=doc_store, top_k=2),
        query_embedder=SentenceTransformersTextEmbedder(
            model="sentence-transformers/all-MiniLM-L6-v2",
        ),
    ),
)
pipeline.connect("query_expander.queries", "retriever.queries")

result = pipeline.run({"query_expander": {"query": "sustainable power generation"}})

for doc in result["retriever"]["documents"]:
    print(f"Score: {doc.score:.3f} | {doc.content}")
components:
  query_expander:
    type: haystack.components.query.query_expander.QueryExpander
    init_parameters:
      n_expansions: 3
  retriever:
    type: haystack.components.retrievers.multi_query_embedding_retriever.MultiQueryEmbeddingRetriever
    init_parameters:
      retriever:
        type: haystack.components.retrievers.in_memory.embedding_retriever.InMemoryEmbeddingRetriever
        init_parameters:
          document_store:
            type: haystack.document_stores.in_memory.document_store.InMemoryDocumentStore
            init_parameters: {}
          top_k: 2
      query_embedder:
        type: haystack_integrations.components.embedders.sentence_transformers.sentence_transformers_text_embedder.SentenceTransformersTextEmbedder
        init_parameters:
          model: sentence-transformers/all-MiniLM-L6-v2

connections:
  - sender: query_expander.queries
    receiver: retriever.queries