chore: import upstream snapshot with attribution
CodeQL / Analyze (python) (push) Has been cancelled
Update Platform Components Table / update (push) Has been cancelled
Docker image release / Build base image (push) Has been cancelled
Sync docs with Docusaurus / sync (push) Has been cancelled
Tests / Check if changed (push) Has been cancelled
Tests / format (push) Has been cancelled
Tests / check-imports (push) Has been cancelled
Tests / Unit / macos-latest (push) Has been cancelled
Tests / Unit / ubuntu-latest (push) Has been cancelled
Tests / Unit / windows-latest (push) Has been cancelled
Tests / mypy (push) Has been cancelled
Tests / Integration / ubuntu-latest (push) Has been cancelled
Tests / Integration / macos-latest (push) Has been cancelled
Tests / Integration / windows-latest (push) Has been cancelled
Tests / notify-slack-on-failure (push) Has been cancelled
Tests / Mark tests as completed (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Update Platform Components Table / update (push) Has been cancelled
Docker image release / Build base image (push) Has been cancelled
Sync docs with Docusaurus / sync (push) Has been cancelled
Tests / Check if changed (push) Has been cancelled
Tests / format (push) Has been cancelled
Tests / check-imports (push) Has been cancelled
Tests / Unit / macos-latest (push) Has been cancelled
Tests / Unit / ubuntu-latest (push) Has been cancelled
Tests / Unit / windows-latest (push) Has been cancelled
Tests / mypy (push) Has been cancelled
Tests / Integration / ubuntu-latest (push) Has been cancelled
Tests / Integration / macos-latest (push) Has been cancelled
Tests / Integration / windows-latest (push) Has been cancelled
Tests / notify-slack-on-failure (push) Has been cancelled
Tests / Mark tests as completed (push) Has been cancelled
This commit is contained in:
+100
@@ -0,0 +1,100 @@
|
||||
---
|
||||
title: "ArcadeDBEmbeddingRetriever"
|
||||
id: arcadedbembeddingretriever
|
||||
slug: "/arcadedbembeddingretriever"
|
||||
description: "An embedding-based Retriever compatible with the ArcadeDB Document Store."
|
||||
---
|
||||
|
||||
# ArcadeDBEmbeddingRetriever
|
||||
|
||||
An embedding-based Retriever compatible with the ArcadeDB Document Store. It uses ArcadeDB's LSM_VECTOR (HNSW) index for vector similarity search.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [ChatPromptBuilder](../builders/chatpromptbuilder.mdx) in a RAG pipeline 2. The last component in a semantic search pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of [ArcadeDBDocumentStore](../../document-stores/arcadedbdocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A vector representing the query (a list of floats) |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [ArcadeDB](/reference/integrations-arcadedb) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/arcadedb |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `ArcadeDBEmbeddingRetriever` retrieves documents from `ArcadeDBDocumentStore` by comparing the query embedding with document embeddings using the store's HNSW index. It accepts optional `filters` for metadata filtering and `top_k` to limit the number of results. Use a Document Embedder in your indexing pipeline and a Text Embedder in your query pipeline so embeddings are available.
|
||||
|
||||
## Installation
|
||||
|
||||
```shell
|
||||
pip install arcadedb-haystack
|
||||
```
|
||||
|
||||
Ensure ArcadeDB is running, for example via Docker, and credentials are set (`ARCADEDB_USERNAME`, `ARCADEDB_PASSWORD`).
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.arcadedb import ArcadeDBDocumentStore
|
||||
from haystack_integrations.components.retrievers.arcadedb import ArcadeDBEmbeddingRetriever
|
||||
|
||||
document_store = ArcadeDBDocumentStore(
|
||||
url="http://localhost:2480",
|
||||
database="haystack",
|
||||
embedding_dimension=768,
|
||||
)
|
||||
retriever = ArcadeDBEmbeddingRetriever(document_store=document_store, top_k=5)
|
||||
|
||||
# Example: run with a query embedding (e.g. from an embedder)
|
||||
result = retriever.run(query_embedding=[0.1] * 768)
|
||||
for doc in result["documents"]:
|
||||
print(doc.content)
|
||||
```
|
||||
|
||||
### In a pipeline
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersTextEmbedder,
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
)
|
||||
from haystack_integrations.document_stores.arcadedb import ArcadeDBDocumentStore
|
||||
from haystack_integrations.components.retrievers.arcadedb import ArcadeDBEmbeddingRetriever
|
||||
|
||||
document_store = ArcadeDBDocumentStore(
|
||||
url="http://localhost:2480",
|
||||
database="haystack",
|
||||
embedding_dimension=768,
|
||||
recreate_type=True,
|
||||
)
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(content="Elephants have been observed to recognize themselves in mirrors."),
|
||||
Document(content="Bioluminescent waves can be seen in the Maldives and Puerto Rico."),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder()
|
||||
documents_with_embeddings = document_embedder.run(documents)
|
||||
document_store.write_documents(
|
||||
documents_with_embeddings["documents"],
|
||||
policy=DuplicatePolicy.OVERWRITE,
|
||||
)
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder())
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
ArcadeDBEmbeddingRetriever(document_store=document_store, top_k=3),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
result = query_pipeline.run({"text_embedder": {"text": "How many languages are there?"}})
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
---
|
||||
title: "AstraEmbeddingRetriever"
|
||||
id: astraretriever
|
||||
slug: "/astraretriever"
|
||||
description: "This is an embedding-based Retriever compatible with the Astra Document Store."
|
||||
---
|
||||
|
||||
# AstraEmbeddingRetriever
|
||||
|
||||
This is an embedding-based Retriever compatible with the Astra Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline <br /> 2. The last component in the semantic search pipeline <br /> 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of [AstraDocumentStore](../../document-stores/astradocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A list of floats |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [Astra](/reference/integrations-astra) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/astra |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
`AstraEmbeddingRetriever` compares the query and document embeddings and fetches the documents most relevant to the query from the [`AstraDocumentStore`](../../document-stores/astradocumentstore.mdx) based on the outcome.
|
||||
|
||||
When using the `AstraEmbeddingRetriever` in your NLP system, make sure it has the query and document embeddings available. You can do so by adding a Document Embedder to your indexing pipeline and a Text Embedder to your query pipeline.
|
||||
|
||||
In addition to the `query_embedding`, the `AstraEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
### Setup and installation
|
||||
|
||||
Once you have an AstraDB account and have created a database, install the `astra-haystack` integration:
|
||||
|
||||
```shell
|
||||
pip install astra-haystack
|
||||
```
|
||||
|
||||
From the configuration in AstraDB’s web UI, you need the database ID and a generated token.
|
||||
|
||||
You will additionally need a collection name and a namespace. When you create the collection name, you also need to set the embedding dimensions and the similarity metric. The namespace organizes data in a database and is called a keyspace in Apache Cassandra.
|
||||
|
||||
Then, optionally, install sentence-transformers as well to run the example below:
|
||||
|
||||
```shell
|
||||
pip install sentence-transformers
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
We strongly encourage passing authentication data through environment variables: make sure to populate the environment variables `ASTRA_DB_API_ENDPOINT` and `ASTRA_DB_APPLICATION_TOKEN` before running the following example.
|
||||
|
||||
### In a pipeline
|
||||
|
||||
Use this Retriever in a query pipeline like this:
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersTextEmbedder,
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
)
|
||||
from haystack_integrations.components.retrievers.astra import AstraEmbeddingRetriever
|
||||
from haystack_integrations.document_stores.astra import AstraDocumentStore
|
||||
|
||||
document_store = AstraDocumentStore()
|
||||
|
||||
model = "sentence-transformers/all-mpnet-base-v2"
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder(model=model)
|
||||
documents_with_embeddings = document_embedder.run(documents)
|
||||
|
||||
document_store.write_documents(
|
||||
documents_with_embeddings.get("documents"),
|
||||
policy=DuplicatePolicy.SKIP,
|
||||
)
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component(
|
||||
"text_embedder",
|
||||
SentenceTransformersTextEmbedder(model=model),
|
||||
)
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
AstraEmbeddingRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
|
||||
result = query_pipeline.run({"text_embedder": {"text": query}})
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
|
||||
The example output would be:
|
||||
|
||||
```python
|
||||
Document(id=cfe93bc1c274908801e6670440bf2bbba54fad792770d57421f85ffa2a4fcc94, content: 'There are over 7,000 languages spoken around the world today.', score: 0.8929937, embedding: vector of size 768)
|
||||
```
|
||||
|
||||
## Additional References
|
||||
|
||||
🧑🍳 Cookbook: [Using AstraDB as a data store in your Haystack pipelines](https://haystack.deepset.ai/cookbook/astradb_haystack_integration)
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
---
|
||||
title: "AutoMergingRetriever"
|
||||
id: automergingretriever
|
||||
slug: "/automergingretriever"
|
||||
description: "Use AutoMergingRetriever to improve search results by returning complete parent documents instead of fragmented chunks when multiple related pieces match a query."
|
||||
---
|
||||
|
||||
# AutoMergingRetriever
|
||||
|
||||
Use AutoMergingRetriever to improve search results by returning complete parent documents instead of fragmented chunks when multiple related pieces match a query.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | Used after the main Retriever component that returns hierarchical documents. |
|
||||
| **Mandatory init variables** | `document_store`: Document Store from which to retrieve the parent documents |
|
||||
| **Mandatory run variables** | `documents`: A list of leaf documents that were matched by a Retriever |
|
||||
| **Output variables** | `documents`: A list resulting documents |
|
||||
| **API reference** | [Retrievers](/reference/retrievers-api) |
|
||||
| **GitHub link** | [https://github.com/deepset-ai/haystack/blob/dae8c7babaf28d2ffab4f2a8dedecd63e2394fb4/haystack/components/retrievers/auto_merging_retriever.py](https://github.com/deepset-ai/haystack/blob/dae8c7babaf28d2ffab4f2a8dedecd63e2394fb4/haystack/components/retrievers/auto_merging_retriever.py#L116) |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `AutoMergingRetriever` is a component that works with a hierarchical document structure. It returns the parent documents instead of individual leaf documents when a certain threshold is met.
|
||||
|
||||
This can be particularly useful when working with paragraphs split into multiple chunks. When several chunks from the same paragraph match your query, the complete paragraph often provides more context and value than the individual pieces alone.
|
||||
|
||||
Here is how this Retriever works:
|
||||
|
||||
1. It requires documents to be organized in a tree structure, with leaf nodes stored in a document index - see [`HierarchicalDocumentSplitter`](../preprocessors/hierarchicaldocumentsplitter.mdx) documentation.
|
||||
2. When searching, it counts how many leaf documents under the same parent match your query.
|
||||
3. If this count exceeds your defined threshold, it returns the parent document instead of the individual leaves.
|
||||
|
||||
The `AutoMergingRetriever` can currently be used by the following Document Stores:
|
||||
|
||||
- [AstraDocumentStore](../../document-stores/astradocumentstore.mdx)
|
||||
- [ElasticsearchDocumentStore](../../document-stores/elasticsearch-document-store.mdx)
|
||||
- [OpenSearchDocumentStore](../../document-stores/opensearch-document-store.mdx)
|
||||
- [PgvectorDocumentStore](../../document-stores/pgvectordocumentstore.mdx)
|
||||
- [QdrantDocumentStore](../../document-stores/qdrant-document-store.mdx)
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
```python
|
||||
from haystack import Document
|
||||
from haystack.components.preprocessors import HierarchicalDocumentSplitter
|
||||
from haystack.components.retrievers.auto_merging_retriever import AutoMergingRetriever
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
|
||||
## create a hierarchical document structure with 3 levels, where the parent document has 3 children
|
||||
text = "The sun rose early in the morning. It cast a warm glow over the trees. Birds began to sing."
|
||||
original_document = Document(content=text)
|
||||
builder = HierarchicalDocumentSplitter(block_sizes=[10, 3], split_overlap=0, split_by="word")
|
||||
docs = builder.run([original_document])["documents"]
|
||||
|
||||
## store level-1 parent documents and initialize the retriever
|
||||
doc_store_parents = InMemoryDocumentStore()
|
||||
for doc in docs["documents"]:
|
||||
if doc.meta["children_ids"] and doc.meta["level"] == 1:
|
||||
doc_store_parents.write_documents([doc])
|
||||
retriever = AutoMergingRetriever(doc_store_parents, threshold=0.5)
|
||||
|
||||
## assume we retrieved 2 leaf docs from the same parent, the parent document should be returned,
|
||||
## since it has 3 children and the threshold=0.5, and we retrieved 2 children (2/3 > 0.66(6))
|
||||
leaf_docs = [doc for doc in docs["documents"] if not doc.meta["children_ids"]]
|
||||
docs = retriever.run(leaf_docs[4:6])
|
||||
>> {'documents': [Document(id=538..),
|
||||
>> content: 'warm glow over the trees. Birds began to sing.',
|
||||
>> meta: {'block_size': 10, 'parent_id': '835..', 'children_ids': ['c17...', '3ff...', '352...'], 'level': 1, 'source_id': '835...',
|
||||
>> 'page_number': 1, 'split_id': 1, 'split_idx_start': 45})]}
|
||||
```
|
||||
|
||||
### In a pipeline
|
||||
|
||||
This is an example of a RAG Haystack pipeline. It first retrieves leaf-level document chunks using BM25, merges them into higher-level parent documents with `AutoMergingRetriever`, constructs a prompt, and generates an answer using OpenAI's chat model.
|
||||
|
||||
```python
|
||||
from typing import List, Tuple
|
||||
from haystack import Document, Pipeline
|
||||
from haystack_experimental.components.splitters import HierarchicalDocumentSplitter
|
||||
from haystack.components.builders.answer_builder import AnswerBuilder
|
||||
from haystack.components.builders.chat_prompt_builder import ChatPromptBuilder
|
||||
from haystack.components.generators.chat import OpenAIChatGenerator
|
||||
from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
|
||||
from haystack.components.retrievers import AutoMergingRetriever
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack.dataclasses import ChatMessage
|
||||
|
||||
|
||||
def indexing(
|
||||
documents: List[Document],
|
||||
) -> Tuple[InMemoryDocumentStore, InMemoryDocumentStore]:
|
||||
splitter = HierarchicalDocumentSplitter(
|
||||
block_sizes={10, 3},
|
||||
split_overlap=0,
|
||||
split_by="word",
|
||||
)
|
||||
docs = splitter.run(documents)
|
||||
|
||||
leaf_documents = [doc for doc in docs["documents"] if doc.meta["__level"] == 1]
|
||||
leaf_doc_store = InMemoryDocumentStore()
|
||||
leaf_doc_store.write_documents(leaf_documents, policy=DuplicatePolicy.OVERWRITE)
|
||||
|
||||
parent_documents = [doc for doc in docs["documents"] if doc.meta["__level"] == 0]
|
||||
parent_doc_store = InMemoryDocumentStore()
|
||||
parent_doc_store.write_documents(parent_documents, policy=DuplicatePolicy.OVERWRITE)
|
||||
|
||||
return leaf_doc_store, parent_doc_store
|
||||
|
||||
|
||||
## Add documents
|
||||
docs = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
leaf_docs, parent_docs = indexing(docs)
|
||||
|
||||
prompt_template = [
|
||||
ChatMessage.from_system("You are a helpful assistant."),
|
||||
ChatMessage.from_user(
|
||||
"Given these documents, answer the question.\nDocuments:\n"
|
||||
"{% for doc in documents %}{{ doc.content }}{% endfor %}\n"
|
||||
"Question: {{question}}\nAnswer:",
|
||||
),
|
||||
]
|
||||
|
||||
rag_pipeline = Pipeline()
|
||||
rag_pipeline.add_component(
|
||||
instance=InMemoryBM25Retriever(document_store=leaf_docs),
|
||||
name="bm25_retriever",
|
||||
)
|
||||
rag_pipeline.add_component(
|
||||
instance=AutoMergingRetriever(parent_docs, threshold=0.6),
|
||||
name="retriever",
|
||||
)
|
||||
rag_pipeline.add_component(
|
||||
instance=ChatPromptBuilder(
|
||||
template=prompt_template,
|
||||
required_variables={"question", "documents"},
|
||||
),
|
||||
name="prompt_builder",
|
||||
)
|
||||
rag_pipeline.add_component(instance=OpenAIChatGenerator(), name="llm")
|
||||
rag_pipeline.add_component(instance=AnswerBuilder(), name="answer_builder")
|
||||
|
||||
rag_pipeline.connect("bm25_retriever.documents", "retriever.documents")
|
||||
rag_pipeline.connect("retriever", "prompt_builder.documents")
|
||||
rag_pipeline.connect("prompt_builder.messages", "llm.messages")
|
||||
rag_pipeline.connect("llm.replies", "answer_builder.replies")
|
||||
rag_pipeline.connect("retriever", "answer_builder.documents")
|
||||
|
||||
question = "How many languages are there?"
|
||||
result = rag_pipeline.run(
|
||||
{
|
||||
"bm25_retriever": {"query": question},
|
||||
"prompt_builder": {"question": question},
|
||||
"answer_builder": {"query": question},
|
||||
},
|
||||
)
|
||||
```
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
---
|
||||
title: "AzureAISearchBM25Retriever"
|
||||
id: azureaisearchbm25retriever
|
||||
slug: "/azureaisearchbm25retriever"
|
||||
description: "A keyword-based Retriever that fetches Documents matching a query from the Azure AI Search Document Store."
|
||||
---
|
||||
|
||||
# AzureAISearchBM25Retriever
|
||||
|
||||
A keyword-based Retriever that fetches Documents matching a query from the Azure AI Search Document Store.
|
||||
|
||||
A keyword-based Retriever that fetches documents matching a query from the Azure AI Search Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. Before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. Before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of [`AzureAISearchDocumentStore`](../../document-stores/azureaisearchdocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query`: A string |
|
||||
| **Output variables** | `documents`: A list of documents (matching the query) |
|
||||
| **API reference** | [Azure AI Search](/reference/integrations-azure_ai_search) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/azure_ai_search |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `AzureAISearchBM25Retriever` is a keyword-based Retriever designed to fetch documents that match a query from an `AzureAISearchDocumentStore`. It uses the BM25 algorithm which calculates a weighted word overlap between the query and the documents to determine their similarity. The Retriever accepts textual query but you can also provide a combination of terms with boolean operators. Some examples of valid queries could be `"pool"`, `"pool spa"`, and `"pool spa +airport"`.
|
||||
|
||||
In addition to the `query`, the `AzureAISearchBM25Retriever` accepts other optional parameters, including `top_k` (the maximum number of documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
If your search index includes a [semantic configuration](https://learn.microsoft.com/en-us/azure/search/semantic-how-to-query-request), you can enable semantic ranking to apply it to the Retriever's results. For more details, refer to the [Azure AI documentation](https://learn.microsoft.com/en-us/azure/search/hybrid-search-how-to-query#semantic-hybrid-search).
|
||||
|
||||
If you want a combination of BM25 and vector retrieval, use the `AzureAISearchHybridRetriever`, which uses both vector search and BM25 search to match documents and query.
|
||||
|
||||
## Usage
|
||||
|
||||
### Installation
|
||||
|
||||
This integration requires you to have an active Azure subscription with a deployed [Azure AI Search](https://azure.microsoft.com/en-us/products/ai-services/ai-search) service.
|
||||
|
||||
To start using Azure AI search with Haystack, install the package with:
|
||||
|
||||
```shell
|
||||
pip install azure-ai-search-haystack
|
||||
```
|
||||
|
||||
### On its own
|
||||
|
||||
This Retriever needs `AzureAISearchDocumentStore` and indexed documents to run.
|
||||
|
||||
```python
|
||||
from haystack import Document
|
||||
from haystack_integrations.components.retrievers.azure_ai_search import (
|
||||
AzureAISearchBM25Retriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.azure_ai_search import (
|
||||
AzureAISearchDocumentStore,
|
||||
)
|
||||
|
||||
document_store = AzureAISearchDocumentStore(index_name="haystack_docs")
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
document_store.write_documents(documents=documents)
|
||||
|
||||
retriever = AzureAISearchBM25Retriever(document_store=document_store)
|
||||
retriever.run(query="How many languages are spoken around the world today?")
|
||||
```
|
||||
|
||||
### In a RAG pipeline
|
||||
|
||||
The below example shows how to use the `AzureAISearchBM25Retriever` in a RAG pipeline. Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
|
||||
|
||||
```python
|
||||
|
||||
from haystack_integrations.components.retrievers.azure_ai_search import (
|
||||
AzureAISearchBM25Retriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.azure_ai_search import (
|
||||
AzureAISearchDocumentStore,
|
||||
)
|
||||
|
||||
from haystack import Document
|
||||
from haystack import Pipeline
|
||||
from haystack.components.builders.answer_builder import AnswerBuilder
|
||||
from haystack.components.builders.prompt_builder import PromptBuilder
|
||||
from haystack.components.generators import OpenAIGenerator
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
|
||||
import os
|
||||
|
||||
api_key = os.environ["OPENAI_API_KEY"]
|
||||
|
||||
## Create a RAG query pipeline
|
||||
prompt_template = """
|
||||
Given these documents, answer the question.\nDocuments:
|
||||
{% for doc in documents %}
|
||||
{{ doc.content }}
|
||||
{% endfor %}
|
||||
|
||||
\nQuestion: {{question}}
|
||||
\nAnswer:
|
||||
"""
|
||||
|
||||
document_store = AzureAISearchDocumentStore(index_name="haystack-docs")
|
||||
|
||||
## Add Documents
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
## policy param is optional, as AzureAISearchDocumentStore has a default policy of DuplicatePolicy.OVERWRITE
|
||||
document_store.write_documents(documents=documents, policy=DuplicatePolicy.OVERWRITE)
|
||||
|
||||
retriever = AzureAISearchBM25Retriever(document_store=document_store)
|
||||
rag_pipeline = Pipeline()
|
||||
rag_pipeline.add_component(name="retriever", instance=retriever)
|
||||
rag_pipeline.add_component(
|
||||
instance=PromptBuilder(template=prompt_template),
|
||||
name="prompt_builder",
|
||||
)
|
||||
rag_pipeline.add_component(instance=OpenAIGenerator(), name="llm")
|
||||
rag_pipeline.add_component(instance=AnswerBuilder(), name="answer_builder")
|
||||
rag_pipeline.connect("retriever", "prompt_builder.documents")
|
||||
rag_pipeline.connect("prompt_builder", "llm")
|
||||
rag_pipeline.connect("llm.replies", "answer_builder.replies")
|
||||
rag_pipeline.connect("llm.meta", "answer_builder.meta")
|
||||
rag_pipeline.connect("retriever", "answer_builder.documents")
|
||||
|
||||
question = "Tell me something about languages?"
|
||||
result = rag_pipeline.run(
|
||||
{
|
||||
"retriever": {"query": question},
|
||||
"prompt_builder": {"question": question},
|
||||
"answer_builder": {"query": question},
|
||||
},
|
||||
)
|
||||
print(result["answer_builder"]["answers"][0])
|
||||
```
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
---
|
||||
title: "AzureAISearchEmbeddingRetriever"
|
||||
id: azureaisearchembeddingretriever
|
||||
slug: "/azureaisearchembeddingretriever"
|
||||
description: "An embedding Retriever compatible with the Azure AI Search Document Store."
|
||||
---
|
||||
|
||||
# AzureAISearchEmbeddingRetriever
|
||||
|
||||
An embedding Retriever compatible with the Azure AI Search Document Store.
|
||||
|
||||
This Retriever accepts the embeddings of a single query as input and returns a list of matching documents.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the embedding retrieval pipeline 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of [`AzureAISearchDocumentStore`](../../document-stores/azureaisearchdocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A list of floats |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [Azure AI Search](/reference/integrations-azure_ai_search) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/azure_ai_search |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `AzureAISearchEmbeddingRetriever` is an embedding-based Retriever compatible with the `AzureAISearchDocumentStore`. It compares the query and document embeddings and fetches the most relevant documents from the `AzureAISearchDocumentStore` based on the outcome.
|
||||
|
||||
The query needs to be embedded before being passed to this component. For example, you could use a Text [Embedder](../embedders.mdx) component.
|
||||
|
||||
By default, the `AzureAISearchDocumentStore` uses the [HNSW algorithm](https://learn.microsoft.com/en-us/azure/search/vector-search-overview#nearest-neighbors-search) with cosine similarity to handle vector searches. The vector configuration is set during the initialization of the document store and can be customized by providing the `vector_search_configuration` parameter.
|
||||
|
||||
In addition to the `query_embedding`, the `AzureAISearchEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
:::info[Semantic Ranking]
|
||||
|
||||
The semantic ranking capability of Azure AI Search is not available for vector retrieval. To include semantic ranking in your retrieval process, use the [`AzureAISearchBM25Retriever`](azureaisearchbm25retriever.mdx) or [`AzureAISearchHybridRetriever`](azureaisearchhybridretriever.mdx). For more details, see [Azure AI documentation](https://learn.microsoft.com/en-us/azure/search/semantic-how-to-query-request?tabs=portal-query#set-up-the-query).
|
||||
:::
|
||||
|
||||
## Usage
|
||||
|
||||
### Installation
|
||||
|
||||
This integration requires you to have an active Azure subscription with a deployed [Azure AI Search](https://azure.microsoft.com/en-us/products/ai-services/ai-search) service.
|
||||
|
||||
To start using Azure AI search with Haystack, install the package with:
|
||||
|
||||
```shell
|
||||
pip install azure-ai-search-haystack
|
||||
```
|
||||
|
||||
### On its own
|
||||
|
||||
This Retriever needs `AzureAISearchDocumentStore` and indexed documents to run.
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.azure_ai_search import (
|
||||
AzureAISearchDocumentStore,
|
||||
)
|
||||
from haystack_integrations.components.retrievers.azure_ai_search import (
|
||||
AzureAISearchEmbeddingRetriever,
|
||||
)
|
||||
|
||||
document_store = AzureAISearchDocumentStore()
|
||||
|
||||
retriever = AzureAISearchEmbeddingRetriever(document_store=document_store)
|
||||
|
||||
## example run query
|
||||
retriever.run(query_embedding=[0.1] * 384)
|
||||
```
|
||||
|
||||
### In a pipeline
|
||||
|
||||
Here is how you could use the `AzureAISearchEmbeddingRetriever` in a pipeline. In this example, you would create two pipelines: an indexing one and a querying one.
|
||||
|
||||
In the indexing pipeline, the documents are passed to the Document Embedder and then written into the Document Store.
|
||||
|
||||
Then, in the querying pipeline, we use a Text Embedder to get the vector representation of the input query that will be then passed to the `AzureAISearchEmbeddingRetriever` to get the results.
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
SentenceTransformersTextEmbedder,
|
||||
)
|
||||
from haystack.components.writers import DocumentWriter
|
||||
|
||||
from haystack_integrations.components.retrievers.azure_ai_search import (
|
||||
AzureAISearchEmbeddingRetriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.azure_ai_search import (
|
||||
AzureAISearchDocumentStore,
|
||||
)
|
||||
|
||||
document_store = AzureAISearchDocumentStore(index_name="retrieval-example")
|
||||
|
||||
model = "sentence-transformers/all-mpnet-base-v2"
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="""Elephants have been observed to behave in a way that indicates a
|
||||
high level of self-awareness, such as recognizing themselves in mirrors.""",
|
||||
),
|
||||
Document(
|
||||
content="""In certain parts of the world, like the Maldives, Puerto Rico, and
|
||||
San Diego, you can witness the phenomenon of bioluminescent waves.""",
|
||||
),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder(model=model)
|
||||
|
||||
## Indexing Pipeline
|
||||
indexing_pipeline = Pipeline()
|
||||
indexing_pipeline.add_component(instance=document_embedder, name="doc_embedder")
|
||||
indexing_pipeline.add_component(
|
||||
instance=DocumentWriter(document_store=document_store),
|
||||
name="doc_writer",
|
||||
)
|
||||
indexing_pipeline.connect("doc_embedder", "doc_writer")
|
||||
|
||||
indexing_pipeline.run({"doc_embedder": {"documents": documents}})
|
||||
|
||||
## Query Pipeline
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component(
|
||||
"text_embedder",
|
||||
SentenceTransformersTextEmbedder(model=model),
|
||||
)
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
AzureAISearchEmbeddingRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
|
||||
result = query_pipeline.run({"text_embedder": {"text": query}})
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
---
|
||||
title: "AzureAISearchHybridRetriever"
|
||||
id: azureaisearchhybridretriever
|
||||
slug: "/azureaisearchhybridretriever"
|
||||
description: "A Retriever based both on dense and sparse embeddings, compatible with the Azure AI Search Document Store."
|
||||
---
|
||||
|
||||
# AzureAISearchHybridRetriever
|
||||
|
||||
A Retriever based both on dense and sparse embeddings, compatible with the Azure AI Search Document Store.
|
||||
|
||||
This Retriever combines embedding-based retrieval and BM25 text search search to find matching documents in the search index to get more relevant results.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a TextEmbedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in a hybrid search pipeline 3. After a TextEmbedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of [`AzureAISearchDocumentStore`](../../document-stores/azureaisearchdocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query`: A string <br /> <br />`query_embedding`: A list of floats |
|
||||
| **Output variables** | `documents`: A list of documents (matching the query) |
|
||||
| **API reference** | [Azure AI Search](/reference/integrations-azure_ai_search) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/azure_ai_search |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `AzureAISearchHybridRetriever` combines vector retrieval and BM25 text search to fetch relevant documents from the `AzureAISearchDocumentStore`. It processes both textual (keyword) queries and query embeddings in a single request, executing all subqueries in parallel. The results are merged and reordered using [Reciprocal Rank Fusion (RRF)](https://learn.microsoft.com/en-us/azure/search/hybrid-search-ranking) to create a unified result set.
|
||||
|
||||
Besides the `query` and `query_embedding`, the `AzureAISearchHybridRetriever` accepts optional parameters such as `top_k` (the maximum number of documents to retrieve) and `filters` to refine the search. Additional keyword arguments can also be passed during initialization for further customization.
|
||||
|
||||
If your search index includes a [semantic configuration](https://learn.microsoft.com/en-us/azure/search/semantic-how-to-query-request), you can enable semantic ranking to apply it to the Retriever's results. For more details, refer to the [Azure AI documentation](https://learn.microsoft.com/en-us/azure/search/hybrid-search-how-to-query#semantic-hybrid-search).
|
||||
|
||||
For purely keyword-based retrieval, you can use `AzureAISearchBM25Retriever`, and for embedding-based retrieval, `AzureAISearchEmbeddingRetriever` is available.
|
||||
|
||||
## Usage
|
||||
|
||||
### Installation
|
||||
|
||||
This integration requires you to have an active Azure subscription with a deployed [Azure AI Search](https://azure.microsoft.com/en-us/products/ai-services/ai-search) service.
|
||||
|
||||
To start using Azure AI search with Haystack, install the package with:
|
||||
|
||||
```shell
|
||||
pip install azure-ai-search-haystack
|
||||
```
|
||||
|
||||
### On its own
|
||||
|
||||
This Retriever needs `AzureAISearchDocumentStore` and indexed documents to run.
|
||||
|
||||
```python
|
||||
from haystack import Document
|
||||
from haystack_integrations.components.retrievers.azure_ai_search import (
|
||||
AzureAISearchHybridRetriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.azure_ai_search import (
|
||||
AzureAISearchDocumentStore,
|
||||
)
|
||||
|
||||
document_store = AzureAISearchDocumentStore(index_name="haystack_docs")
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
document_store.write_documents(documents=documents)
|
||||
|
||||
retriever = AzureAISearchHybridRetriever(document_store=document_store)
|
||||
## fake embeddings to keep the example simple
|
||||
retriever.run(
|
||||
query="How many languages are spoken around the world today?",
|
||||
query_embedding=[0.1] * 384,
|
||||
)
|
||||
```
|
||||
|
||||
### In a RAG pipeline
|
||||
|
||||
The following example demonstrates using the `AzureAISearchHybridRetriever` in a pipeline. An indexing pipeline is responsible for indexing and storing documents with embeddings in the `AzureAISearchDocumentStore`, while the query pipeline uses hybrid retrieval to fetch relevant documents based on a given query.
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
SentenceTransformersTextEmbedder,
|
||||
)
|
||||
from haystack.components.writers import DocumentWriter
|
||||
|
||||
from haystack_integrations.components.retrievers.azure_ai_search import (
|
||||
AzureAISearchHybridRetriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.azure_ai_search import (
|
||||
AzureAISearchDocumentStore,
|
||||
)
|
||||
|
||||
document_store = AzureAISearchDocumentStore(index_name="hybrid-retrieval-example")
|
||||
|
||||
model = "sentence-transformers/all-mpnet-base-v2"
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="""Elephants have been observed to behave in a way that indicates a
|
||||
high level of self-awareness, such as recognizing themselves in mirrors.""",
|
||||
),
|
||||
Document(
|
||||
content="""In certain parts of the world, like the Maldives, Puerto Rico, and
|
||||
San Diego, you can witness the phenomenon of bioluminescent waves.""",
|
||||
),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder(model=model)
|
||||
|
||||
## Indexing Pipeline
|
||||
indexing_pipeline = Pipeline()
|
||||
indexing_pipeline.add_component(instance=document_embedder, name="doc_embedder")
|
||||
indexing_pipeline.add_component(
|
||||
instance=DocumentWriter(document_store=document_store),
|
||||
name="doc_writer",
|
||||
)
|
||||
indexing_pipeline.connect("doc_embedder", "doc_writer")
|
||||
|
||||
indexing_pipeline.run({"doc_embedder": {"documents": documents}})
|
||||
|
||||
## Query Pipeline
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component(
|
||||
"text_embedder",
|
||||
SentenceTransformersTextEmbedder(model=model),
|
||||
)
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
AzureAISearchHybridRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
|
||||
result = query_pipeline.run(
|
||||
{"text_embedder": {"text": query}, "retriever": {"query": query}},
|
||||
)
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: "ChromaEmbeddingRetriever"
|
||||
id: chromaembeddingretriever
|
||||
slug: "/chromaembeddingretriever"
|
||||
description: "This is an embedding Retriever compatible with the Chroma Document Store."
|
||||
---
|
||||
|
||||
# ChromaEmbeddingRetriever
|
||||
|
||||
This is an embedding Retriever compatible with the Chroma Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [ChromaDocumentStore](../../document-stores/chromadocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A list of floats |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [Chroma](/reference/integrations-chroma) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/chroma |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `ChromaEmbeddingRetriever` is an embedding-based Retriever compatible with the `ChromaDocumentStore`. It compares the query and document embeddings and fetches the documents most relevant to the query from the `ChromaDocumentStore` based on the outcome.
|
||||
|
||||
The query needs to be embedded before being passed to this component. For example, you could use a text [embedder](../embedders.mdx) component.
|
||||
|
||||
In addition to the `query_embedding`, the `ChromaEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
### Usage
|
||||
|
||||
#### On its own
|
||||
|
||||
This Retriever needs the `ChromaDocumentStore` and indexed documents to run.
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.chroma import ChromaDocumentStore
|
||||
from haystack_integrations.components.retrievers.chroma import ChromaEmbeddingRetriever
|
||||
|
||||
document_store = ChromaDocumentStore()
|
||||
|
||||
retriever = ChromaEmbeddingRetriever(document_store=document_store)
|
||||
|
||||
## example run query
|
||||
retriever.run(query_embedding=[0.1] * 384)
|
||||
```
|
||||
|
||||
#### In a pipeline
|
||||
|
||||
Here is how you could use the `ChromaEmbeddingRetriever` in a pipeline. In this example, you would create two pipelines: an indexing one and a querying one.
|
||||
|
||||
In the indexing pipeline, the documents are passed to the Document Embedder and then written into the document Store.
|
||||
|
||||
Then, in the querying pipeline, we use a text embedder to get the vector representation of the input query that will be then passed to the `ChromaEmbeddingRetriever` to get the results.
|
||||
|
||||
```python
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from haystack import Pipeline
|
||||
from haystack.dataclasses import Document
|
||||
from haystack.components.writers import DocumentWriter
|
||||
|
||||
## Note: the following requires a "pip install sentence-transformers"
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
SentenceTransformersTextEmbedder,
|
||||
)
|
||||
|
||||
from haystack_integrations.document_stores.chroma import ChromaDocumentStore
|
||||
from haystack_integrations.components.retrievers.chroma import ChromaEmbeddingRetriever
|
||||
from sentence_transformers import SentenceTransformer
|
||||
|
||||
## Chroma is used in-memory so we use the same instances in the two pipelines below
|
||||
document_store = ChromaDocumentStore()
|
||||
|
||||
documents = [
|
||||
Document(content="This contains variable declarations", meta={"title": "one"}),
|
||||
Document(
|
||||
content="This contains another sort of variable declarations",
|
||||
meta={"title": "two"},
|
||||
),
|
||||
Document(
|
||||
content="This has nothing to do with variable declarations",
|
||||
meta={"title": "three"},
|
||||
),
|
||||
Document(content="A random doc", meta={"title": "four"}),
|
||||
]
|
||||
|
||||
indexing = Pipeline()
|
||||
indexing.add_component("embedder", SentenceTransformersDocumentEmbedder())
|
||||
indexing.add_component("writer", DocumentWriter(document_store))
|
||||
indexing.connect("embedder.documents", "writer.documents")
|
||||
indexing.run({"embedder": {"documents": documents}})
|
||||
|
||||
querying = Pipeline()
|
||||
querying.add_component("query_embedder", SentenceTransformersTextEmbedder())
|
||||
querying.add_component("retriever", ChromaEmbeddingRetriever(document_store))
|
||||
querying.connect("query_embedder.embedding", "retriever.query_embedding")
|
||||
results = querying.run({"query_embedder": {"text": "Variable declarations"}})
|
||||
|
||||
for d in results["retriever"]["documents"]:
|
||||
print(d.meta, d.score)
|
||||
```
|
||||
|
||||
## Additional References
|
||||
|
||||
🧑🍳 Cookbook: [Use Chroma for RAG and Indexing](https://haystack.deepset.ai/cookbook/chroma-indexing-and-rag-examples)
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: "ChromaQueryTextRetriever"
|
||||
id: chromaqueryretriever
|
||||
slug: "/chromaqueryretriever"
|
||||
description: "This is a a Retriever compatible with the Chroma Document Store."
|
||||
---
|
||||
|
||||
# ChromaQueryTextRetriever
|
||||
|
||||
This is a a Retriever compatible with the Chroma Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [ChromaDocumentStore](../../document-stores/chromadocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query`: A single query in plain-text format to be processed by the [Retriever](../retrievers.mdx) |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [Chroma](/reference/integrations-chroma) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/chroma |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `ChromaQueryTextRetriever` is an embedding-based Retriever compatible with the `ChromaDocumentStore` that uses the Chroma [query API](https://docs.trychroma.com/reference/Collection#query).
|
||||
This component takes a plain-text query string in input and returns the matching documents.
|
||||
Chroma will create the embedding for the query using its [embedding function](https://docs.trychroma.com/embeddings#default-all-minilm-l6-v2); in case you do not want to use the default embedding function, this must be specified at `ChromaDocumentStore` initialization.
|
||||
|
||||
### Usage
|
||||
|
||||
#### On its own
|
||||
|
||||
This Retriever needs the `ChromaDocumentStore` and indexed documents to run.
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.chroma import ChromaDocumentStore
|
||||
from haystack_integrations.components.retrievers.chroma import ChromaQueryTextRetriever
|
||||
|
||||
document_store = ChromaDocumentStore()
|
||||
|
||||
retriever = ChromaQueryTextRetriever(document_store=document_store)
|
||||
|
||||
## example run query
|
||||
retriever.run(query="How does Chroma Retriever work?")
|
||||
```
|
||||
|
||||
#### In a pipeline
|
||||
|
||||
Here is how you could use the `ChromaQueryTextRetriever` in a Pipeline. In this example, you would create two pipelines: an indexing one and a querying one.
|
||||
|
||||
In the indexing pipeline, the documents are written in the Document Store.
|
||||
|
||||
Then, in the querying pipeline, `ChromaQueryTextRetriever` gets the answer from the Document Store based on the provided query.
|
||||
|
||||
```python
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from haystack import Pipeline
|
||||
from haystack.dataclasses import Document
|
||||
from haystack.components.writers import DocumentWriter
|
||||
|
||||
from haystack_integrations.document_stores.chroma import ChromaDocumentStore
|
||||
from haystack_integrations.components.retrievers.chroma import ChromaQueryTextRetriever
|
||||
|
||||
## Chroma is used in-memory so we use the same instances in the two pipelines below
|
||||
document_store = ChromaDocumentStore()
|
||||
|
||||
documents = [
|
||||
Document(content="This contains variable declarations", meta={"title": "one"}),
|
||||
Document(
|
||||
content="This contains another sort of variable declarations",
|
||||
meta={"title": "two"},
|
||||
),
|
||||
Document(
|
||||
content="This has nothing to do with variable declarations",
|
||||
meta={"title": "three"},
|
||||
),
|
||||
Document(content="A random doc", meta={"title": "four"}),
|
||||
]
|
||||
|
||||
indexing = Pipeline()
|
||||
indexing.add_component("writer", DocumentWriter(document_store))
|
||||
indexing.run({"writer": {"documents": documents}})
|
||||
|
||||
querying = Pipeline()
|
||||
querying.add_component("retriever", ChromaQueryTextRetriever(document_store))
|
||||
results = querying.run({"retriever": {"query": "Variable declarations", "top_k": 3}})
|
||||
|
||||
for d in results["retriever"]["documents"]:
|
||||
print(d.meta, d.score)
|
||||
```
|
||||
|
||||
## Additional References
|
||||
|
||||
🧑🍳 Cookbook: [Use Chroma for RAG and Indexing](https://haystack.deepset.ai/cookbook/chroma-indexing-and-rag-examples)
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
---
|
||||
title: "ElasticsearchBM25Retriever"
|
||||
id: elasticsearchbm25retriever
|
||||
slug: "/elasticsearchbm25retriever"
|
||||
description: "A keyword-based Retriever that fetches Documents matching a query from the Elasticsearch Document Store."
|
||||
---
|
||||
|
||||
# ElasticsearchBM25Retriever
|
||||
|
||||
A keyword-based Retriever that fetches Documents matching a query from the Elasticsearch Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. Before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. Before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of [ElasticsearchDocumentStore](../../document-stores/elasticsearch-document-store.mdx) |
|
||||
| **Mandatory run variables** | `query`: A string |
|
||||
| **Output variables** | `documents`: A list of documents (matching the query) |
|
||||
| **API reference** | [Elasticsearch](/reference/integrations-elasticsearch) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/elasticsearch |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
`ElasticsearchBM25Retriever` is a keyword-based Retriever that fetches Documents matching a query from an `ElasticsearchDocumentStore`. It determines the similarity between Documents and the query based on the BM25 algorithm, which computes a weighted word overlap between the two strings.
|
||||
|
||||
Since the `ElasticsearchBM25Retriever` matches strings based on word overlap, it’s often used to find exact matches to names of persons or products, IDs, or well-defined error messages. The BM25 algorithm is very lightweight and simple. Nevertheless, it can be hard to beat with more complex embedding-based approaches on out-of-domain data.
|
||||
|
||||
In addition to the `query`, the `ElasticsearchBM25Retriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
When initializing Retriever, you can also adjust how [inexact fuzzy matching](https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#fuzziness) is performed, using the `fuzziness` parameter.
|
||||
|
||||
If you want a semantic match between a query and documents, you can use `ElasticsearchEmbeddingRetriever`, which uses vectors created by embedding models to retrieve relevant information.
|
||||
|
||||
## Installation
|
||||
|
||||
[Install](https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html) Elasticsearch and then [start](https://www.elastic.co/guide/en/elasticsearch/reference/current/starting-elasticsearch.html) an instance. Haystack supports Elasticsearch 8.
|
||||
|
||||
If you have Docker set up, we recommend pulling the Docker image and running it.
|
||||
|
||||
```shell
|
||||
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.11.1
|
||||
docker run -p 9200:9200 -e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms1024m -Xmx1024m" -e "xpack.security.enabled=false" elasticsearch:8.11.1
|
||||
```
|
||||
|
||||
As an alternative, you can go to [Elasticsearch integration GitHub](https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/elasticsearch) and start a Docker container running Elasticsearch using the provided `docker-compose.yml`:
|
||||
|
||||
```shell
|
||||
docker compose up
|
||||
```
|
||||
|
||||
Once you have a running Elasticsearch instance, install the `elasticsearch-haystack` integration:
|
||||
|
||||
```shell
|
||||
pip install elasticsearch-haystack
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
```python
|
||||
from haystack import Document
|
||||
from haystack_integrations.components.retrievers.elasticsearch import (
|
||||
ElasticsearchBM25Retriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.elasticsearch import (
|
||||
ElasticsearchDocumentStore,
|
||||
)
|
||||
from elasticsearch import Elasticsearch
|
||||
|
||||
document_store = ElasticsearchDocumentStore(hosts="http://localhost:9200/")
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
document_store.write_documents(documents=documents)
|
||||
|
||||
retriever = ElasticsearchBM25Retriever(document_store=document_store)
|
||||
retriever.run(query="How many languages are spoken around the world today?")
|
||||
```
|
||||
|
||||
### In a RAG pipeline
|
||||
|
||||
Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
|
||||
|
||||
```python
|
||||
|
||||
from haystack_integrations.components.retrievers.elasticsearch import (
|
||||
ElasticsearchBM25Retriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.elasticsearch import (
|
||||
ElasticsearchDocumentStore,
|
||||
)
|
||||
|
||||
from elasticsearch import Elasticsearch
|
||||
|
||||
from haystack import Document
|
||||
from haystack import Pipeline
|
||||
from haystack.components.builders.answer_builder import AnswerBuilder
|
||||
from haystack.components.builders.prompt_builder import PromptBuilder
|
||||
from haystack.components.generators import OpenAIGenerator
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
|
||||
import os
|
||||
|
||||
api_key = os.environ["OPENAI_API_KEY"]
|
||||
|
||||
## Create a RAG query pipeline
|
||||
prompt_template = """
|
||||
Given these documents, answer the question.\nDocuments:
|
||||
{% for doc in documents %}
|
||||
{{ doc.content }}
|
||||
{% endfor %}
|
||||
|
||||
\nQuestion: {{question}}
|
||||
\nAnswer:
|
||||
"""
|
||||
|
||||
document_store = ElasticsearchDocumentStore(hosts="http://localhost:9200/")
|
||||
|
||||
## Add Documents
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
## DuplicatePolicy.SKIP param is optional, but useful to run the script multiple times without throwing errors
|
||||
document_store.write_documents(documents=documents, policy=DuplicatePolicy.SKIP)
|
||||
|
||||
retriever = ElasticsearchBM25Retriever(document_store=document_store)
|
||||
rag_pipeline = Pipeline()
|
||||
rag_pipeline.add_component(name="retriever", instance=retriever)
|
||||
rag_pipeline.add_component(
|
||||
instance=PromptBuilder(template=prompt_template),
|
||||
name="prompt_builder",
|
||||
)
|
||||
rag_pipeline.add_component(instance=OpenAIGenerator(api_key=api_key), name="llm")
|
||||
rag_pipeline.add_component(instance=AnswerBuilder(), name="answer_builder")
|
||||
rag_pipeline.connect("retriever", "prompt_builder.documents")
|
||||
rag_pipeline.connect("prompt_builder", "llm")
|
||||
rag_pipeline.connect("llm.replies", "answer_builder.replies")
|
||||
rag_pipeline.connect("llm.meta", "answer_builder.meta")
|
||||
rag_pipeline.connect("retriever", "answer_builder.documents")
|
||||
|
||||
question = "How many languages are spoken around the world today?"
|
||||
result = rag_pipeline.run(
|
||||
{
|
||||
"retriever": {"query": question},
|
||||
"prompt_builder": {"question": question},
|
||||
"answer_builder": {"query": question},
|
||||
},
|
||||
)
|
||||
print(result["answer_builder"]["answers"][0].data)
|
||||
```
|
||||
|
||||
Here’s an example output you might get:
|
||||
|
||||
```python
|
||||
"Over 7,000 languages are spoken around the world today"
|
||||
```
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
---
|
||||
title: "ElasticsearchEmbeddingRetriever"
|
||||
id: elasticsearchembeddingretriever
|
||||
slug: "/elasticsearchembeddingretriever"
|
||||
description: "An embedding-based Retriever compatible with the Elasticsearch Document Store."
|
||||
---
|
||||
|
||||
# ElasticsearchEmbeddingRetriever
|
||||
|
||||
An embedding-based Retriever compatible with the Elasticsearch Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of [ElasticsearchDocumentStore](../../document-stores/elasticsearch-document-store.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A list of floats |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [Elasticsearch](/reference/integrations-elasticsearch) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/elasticsearch |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `ElasticsearchEmbeddingRetriever` is an embedding-based Retriever compatible with the `ElasticsearchDocumentStore`. It compares the query and Document embeddings and fetches the Documents most relevant to the query from the `ElasticsearchDocumentStore` based on the outcome.
|
||||
|
||||
When using the `ElasticsearchEmbeddingRetriever` in your NLP system, ensure it has the query and Document embeddings available. You can do so by adding a Document Embedder to your indexing pipeline and a Text Embedder to your query pipeline.
|
||||
|
||||
In addition to the `query_embedding`, the `ElasticsearchEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
When initializing Retriever, you can also set `num_candidates`: the number of approximate nearest neighbor candidates on each shard. It's an advanced setting you can read more about in the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search.html#tune-approximate-knn-for-speed-accuracy).
|
||||
|
||||
The `embedding_similarity_function` to use for embedding retrieval must be defined when the corresponding `ElasticsearchDocumentStore` is initialized.
|
||||
|
||||
## Installation
|
||||
|
||||
[Install](https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html) Elasticsearch and then [start](https://www.elastic.co/guide/en/elasticsearch/reference/current/starting-elasticsearch.html) an instance. Haystack supports Elasticsearch 8.
|
||||
|
||||
If you have Docker set up, we recommend pulling the Docker image and running it.
|
||||
|
||||
```shell
|
||||
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.11.1
|
||||
docker run -p 9200:9200 -e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms1024m -Xmx1024m" -e "xpack.security.enabled=false" elasticsearch:8.11.1
|
||||
```
|
||||
|
||||
As an alternative, you can go to [Elasticsearch integration GitHub](https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/elasticsearch) and start a Docker container running Elasticsearch using the provided `docker-compose.yml`:
|
||||
|
||||
```shell
|
||||
docker compose up
|
||||
```
|
||||
|
||||
Once you have a running Elasticsearch instance, install the `elasticsearch-haystack` integration:
|
||||
|
||||
```shell
|
||||
pip install elasticsearch-haystack
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### In a pipeline
|
||||
|
||||
Use this Retriever in a query Pipeline like this:
|
||||
|
||||
```python
|
||||
from haystack_integrations.components.retrievers.elasticsearch import (
|
||||
ElasticsearchEmbeddingRetriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.elasticsearch import (
|
||||
ElasticsearchDocumentStore,
|
||||
)
|
||||
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersTextEmbedder,
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
)
|
||||
|
||||
document_store = ElasticsearchDocumentStore(hosts="http://localhost:9200/")
|
||||
|
||||
model = "BAAI/bge-large-en-v1.5"
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder(model=model)
|
||||
documents_with_embeddings = document_embedder.run(documents)
|
||||
|
||||
document_store.write_documents(
|
||||
documents_with_embeddings.get("documents"),
|
||||
policy=DuplicatePolicy.SKIP,
|
||||
)
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component(
|
||||
"text_embedder",
|
||||
SentenceTransformersTextEmbedder(model=model),
|
||||
)
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
ElasticsearchEmbeddingRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
|
||||
result = query_pipeline.run({"text_embedder": {"text": query}})
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
|
||||
The example output would be:
|
||||
|
||||
```python
|
||||
Document(id=cfe93bc1c274908801e6670440bf2bbba54fad792770d57421f85ffa2a4fcc94, content: 'There are over 7,000 languages spoken around the world today.', score: 0.87717235, embedding: vector of size 1024)
|
||||
```
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: "FAISSEmbeddingRetriever"
|
||||
id: faissembeddingretriever
|
||||
slug: "/faissembeddingretriever"
|
||||
description: "An embedding-based Retriever compatible with the FAISSDocumentStore."
|
||||
---
|
||||
|
||||
# FAISSEmbeddingRetriever
|
||||
|
||||
An embedding-based Retriever compatible with the FAISSDocumentStore.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in a semantic search pipeline 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [`FAISSDocumentStore`](../../document-stores/faissdocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A vector representing the query (a list of floats) |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [FAISS](/reference/integrations-faiss) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/faiss |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `FAISSEmbeddingRetriever` is an embedding-based Retriever that queries a `FAISSDocumentStore`. It compares the query embedding to document embeddings stored in FAISS and returns the most similar documents.
|
||||
|
||||
This Retriever expects precomputed embeddings in the Document Store and a query embedding at runtime. You can generate them with a Document Embedder in your indexing pipeline and a Text Embedder in your query pipeline.
|
||||
|
||||
In addition to `query_embedding`, you can pass:
|
||||
|
||||
- `top_k`: The maximum number of documents to return.
|
||||
- `filters`: Metadata filters to restrict retrieved documents.
|
||||
|
||||
You can also configure default filters and `filter_policy` at initialization.
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.faiss import FAISSDocumentStore
|
||||
from haystack_integrations.components.retrievers.faiss import FAISSEmbeddingRetriever
|
||||
|
||||
document_store = FAISSDocumentStore(embedding_dim=768)
|
||||
retriever = FAISSEmbeddingRetriever(document_store=document_store, top_k=5)
|
||||
|
||||
# Example query embedding
|
||||
result = retriever.run(query_embedding=[0.1] * 768)
|
||||
print(result["documents"])
|
||||
```
|
||||
|
||||
### In a pipeline
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
SentenceTransformersTextEmbedder,
|
||||
)
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack_integrations.document_stores.faiss import FAISSDocumentStore
|
||||
from haystack_integrations.components.retrievers.faiss import FAISSEmbeddingRetriever
|
||||
|
||||
document_store = FAISSDocumentStore(embedding_dim=768)
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of intelligence.",
|
||||
),
|
||||
Document(
|
||||
content="In certain places, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder()
|
||||
document_embedder.warm_up()
|
||||
documents_with_embeddings = document_embedder.run(documents)["documents"]
|
||||
document_store.write_documents(
|
||||
documents_with_embeddings,
|
||||
policy=DuplicatePolicy.OVERWRITE,
|
||||
)
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder())
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
FAISSEmbeddingRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
result = query_pipeline.run({"text_embedder": {"text": query}})
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
---
|
||||
title: "FilterRetriever"
|
||||
id: filterretriever
|
||||
slug: "/filterretriever"
|
||||
description: "Use this Retriever with any Document Store to get the Documents that match specific filters."
|
||||
---
|
||||
|
||||
# FilterRetriever
|
||||
|
||||
Use this Retriever with any Document Store to get the Documents that match specific filters.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | At the beginning of a Pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a Document Store |
|
||||
| **Mandatory run variables** | `filters`: A dictionary of filters in the same syntax supported by the Document Stores |
|
||||
| **Output variables** | `documents`: All the documents that match these filters |
|
||||
| **API reference** | [Retrievers](/reference/retrievers-api) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack/blob/main/haystack/components/retrievers/filter_retriever.py |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
`FilterRetriever` retrieves Documents that match the provided filters.
|
||||
|
||||
It’s a special kind of Retriever – it can work with all Document Stores instead of being specialized to work with only one.
|
||||
|
||||
However, as every other Retriever, it needs some Document Store at initialization time, and it will perform filtering on the content of that instance only.
|
||||
|
||||
Therefore, it can be used as any other Retriever in a Pipeline.
|
||||
|
||||
Pay attention when using `FilterRetriever` on a Document Store that contains many Documents, as `FilterRetriever` will return all documents that match the filters. The `run` command with no filters can easily overwhelm other components in the Pipeline (for example, Generators):
|
||||
|
||||
```python
|
||||
filter_retriever.run({})
|
||||
```
|
||||
|
||||
Another thing to note is that `FilterRetriever` does not score your Documents or rank them in any way. If you need to rank the Documents by similarity to a query, consider using Ranker components.
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
```python
|
||||
from haystack import Document
|
||||
from haystack.components.retrievers import FilterRetriever
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
|
||||
docs = [
|
||||
Document(content="Python is a popular programming language", meta={"lang": "en"}),
|
||||
Document(
|
||||
content="python ist eine beliebte Programmiersprache",
|
||||
meta={"lang": "de"},
|
||||
),
|
||||
]
|
||||
|
||||
doc_store = InMemoryDocumentStore()
|
||||
doc_store.write_documents(docs)
|
||||
retriever = FilterRetriever(doc_store)
|
||||
result = retriever.run(filters={"field": "lang", "operator": "==", "value": "en"})
|
||||
|
||||
assert "documents" in result
|
||||
assert len(result["documents"]) == 1
|
||||
assert result["documents"][0].content == "Python is a popular programming language"
|
||||
```
|
||||
|
||||
### In a RAG pipeline
|
||||
|
||||
Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
|
||||
|
||||
```python
|
||||
from haystack.components.retrievers.filter_retriever import FilterRetriever
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.components.builders.answer_builder import AnswerBuilder
|
||||
from haystack.components.builders.prompt_builder import PromptBuilder
|
||||
from haystack.components.generators import OpenAIGenerator
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
|
||||
import os
|
||||
api_key = os.environ['OPENAI_API_KEY']
|
||||
|
||||
document_store = InMemoryDocumentStore()
|
||||
documents = [
|
||||
Document(content="Mark lives in Berlin.", meta={"year": 2018}),
|
||||
Document(content="Mark lives in Paris.", meta={"year": 2021}),
|
||||
Document(content="Mark is Danish.", meta={"year": 2021}),
|
||||
Document(content="Mark lives in New York.", meta={"year": 2023}),
|
||||
]
|
||||
document_store.write_documents(documents=documents)
|
||||
|
||||
## Create a RAG query pipeline
|
||||
prompt_template = """
|
||||
Given these documents, answer the question.\nDocuments:
|
||||
{% for doc in documents %}
|
||||
{{ doc.content }}
|
||||
{% endfor %}
|
||||
|
||||
\nQuestion: {{question}}
|
||||
\nAnswer:
|
||||
"""
|
||||
|
||||
rag_pipeline = Pipeline()
|
||||
rag_pipeline.add_component(name="retriever", instance=FilterRetriever(document_store=document_store))
|
||||
rag_pipeline.add_component(instance=PromptBuilder(template=prompt_template), name="prompt_builder")
|
||||
rag_pipeline.add_component(instance=OpenAIGenerator(api_key=api_key), name="llm")
|
||||
rag_pipeline.connect("retriever", "prompt_builder.documents")
|
||||
rag_pipeline.connect("prompt_builder", "llm")
|
||||
|
||||
result = rag_pipeline.run(
|
||||
{
|
||||
"retriever": {"filters": {"field": "year", "operator": "==", "value": 2021}},
|
||||
"prompt_builder": {"question": "Where does Mark live?"},
|
||||
}
|
||||
)
|
||||
print(result['answer_builder']['answers'][0])`
|
||||
```
|
||||
|
||||
Here’s an example output you might get:
|
||||
|
||||
```
|
||||
According to the provided documents, Mark lives in Paris.
|
||||
```
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
---
|
||||
title: "InMemoryBM25Retriever"
|
||||
id: inmemorybm25retriever
|
||||
slug: "/inmemorybm25retriever"
|
||||
description: "A keyword-based Retriever compatible with InMemoryDocumentStore."
|
||||
---
|
||||
|
||||
# InMemoryBM25Retriever
|
||||
|
||||
A keyword-based Retriever compatible with InMemoryDocumentStore.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | In query pipelines: <br />In a RAG pipeline, before a [`PromptBuilder`](../builders/promptbuilder.mdx) <br />In a semantic search pipeline, as the last component <br />In an extractive QA pipeline, before an [`ExtractiveReader`](../readers/extractivereader.mdx) |
|
||||
| **Mandatory init variables** | `document_store`: An instance of [InMemoryDocumentStore](../../document-stores/inmemorydocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query`: A query string |
|
||||
| **Output variables** | `documents`: A list of documents (matching the query) |
|
||||
| **API reference** | [Retrievers](/reference/retrievers-api) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack/blob/main/haystack/components/retrievers/in_memory/bm25_retriever.py |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
`InMemoryBM25Retriever` is a keyword-based Retriever that fetches Documents matching a query from a temporary in-memory database. It determines the similarity between Documents and the query based on the BM25 algorithm, which computes a weighted word overlap between the two strings.
|
||||
|
||||
Since the `InMemoryBM25Retriever` matches strings based on word overlap, it’s often used to find exact matches to names of persons or products, IDs, or well-defined error messages. The BM25 algorithm is very lightweight and simple. Nevertheless, it can be hard to beat with more complex embedding-based approaches on out-of-domain data.
|
||||
|
||||
In addition to the `query`, the `InMemoryBM25Retriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
Some relevant parameters that impact the BM25 retrieval must be defined when the corresponding `InMemoryDocumentStore` is initialized: these include the specific BM25 algorithm and its parameters.
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
```python
|
||||
from haystack import Document
|
||||
from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
|
||||
document_store = InMemoryDocumentStore()
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
document_store.write_documents(documents=documents)
|
||||
|
||||
retriever = InMemoryBM25Retriever(document_store=document_store)
|
||||
retriever.run(query="How many languages are spoken around the world today?")
|
||||
```
|
||||
|
||||
### In a Pipeline
|
||||
|
||||
#### In a RAG Pipeline
|
||||
|
||||
Here's an example of the Retriever in a retrieval-augmented generation pipeline:
|
||||
|
||||
```python
|
||||
import os
|
||||
from haystack import Document
|
||||
from haystack import Pipeline
|
||||
from haystack.components.builders.answer_builder import AnswerBuilder
|
||||
from haystack.components.builders.prompt_builder import PromptBuilder
|
||||
from haystack.components.generators import OpenAIGenerator
|
||||
from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
|
||||
## Create a RAG query pipeline
|
||||
prompt_template = """
|
||||
Given these documents, answer the question.\nDocuments:
|
||||
{% for doc in documents %}
|
||||
{{ doc.content }}
|
||||
{% endfor %}
|
||||
|
||||
\nQuestion: {{question}}
|
||||
\nAnswer:
|
||||
"""
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "sk-XXXXXX"
|
||||
|
||||
rag_pipeline = Pipeline()
|
||||
rag_pipeline.add_component(
|
||||
instance=InMemoryBM25Retriever(document_store=InMemoryDocumentStore()),
|
||||
name="retriever",
|
||||
)
|
||||
rag_pipeline.add_component(
|
||||
instance=PromptBuilder(template=prompt_template),
|
||||
name="prompt_builder",
|
||||
)
|
||||
rag_pipeline.add_component(instance=OpenAIGenerator(), name="llm")
|
||||
rag_pipeline.add_component(instance=AnswerBuilder(), name="answer_builder")
|
||||
rag_pipeline.connect("retriever", "prompt_builder.documents")
|
||||
rag_pipeline.connect("prompt_builder", "llm")
|
||||
rag_pipeline.connect("llm.replies", "answer_builder.replies")
|
||||
rag_pipeline.connect("llm.metadata", "answer_builder.metadata")
|
||||
rag_pipeline.connect("retriever", "answer_builder.documents")
|
||||
|
||||
## Draw the pipeline
|
||||
rag_pipeline.draw("./rag_pipeline.png")
|
||||
|
||||
## Add Documents
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
rag_pipeline.get_component("retriever").document_store.write_documents(documents)
|
||||
|
||||
## Run the pipeline
|
||||
question = "How many languages are there?"
|
||||
result = rag_pipeline.run(
|
||||
{
|
||||
"retriever": {"query": question},
|
||||
"prompt_builder": {"question": question},
|
||||
"answer_builder": {"query": question},
|
||||
},
|
||||
)
|
||||
print(result["answer_builder"]["answers"][0])
|
||||
```
|
||||
|
||||
#### In a Document Search Pipeline
|
||||
|
||||
Here's how you can use this Retriever in a document search pipeline:
|
||||
|
||||
```python
|
||||
from haystack import Document
|
||||
from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
from haystack.pipeline import Pipeline
|
||||
|
||||
## Create components and a query pipeline
|
||||
document_store = InMemoryDocumentStore()
|
||||
retriever = InMemoryBM25Retriever(document_store=document_store)
|
||||
|
||||
pipeline = Pipeline()
|
||||
pipeline.add_component(instance=retriever, name="retriever")
|
||||
|
||||
## Add Documents
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
document_store.write_documents(documents)
|
||||
|
||||
## Run the pipeline
|
||||
result = pipeline.run(data={"retriever": {"query": "How many languages are there?"}})
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
---
|
||||
title: "InMemoryEmbeddingRetriever"
|
||||
id: inmemoryembeddingretriever
|
||||
slug: "/inmemoryembeddingretriever"
|
||||
description: "Use this Retriever with the InMemoryDocumentStore if you're looking for embedding-based retrieval."
|
||||
---
|
||||
|
||||
# InMemoryEmbeddingRetriever
|
||||
|
||||
Use this Retriever with the InMemoryDocumentStore if you're looking for embedding-based retrieval.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | In query pipelines: <br />In a RAG pipeline, before a [`PromptBuilder`](../builders/promptbuilder.mdx) <br />In a semantic search pipeline, as the last component <br />In an extractive QA pipeline, after a Tex tEmbedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) |
|
||||
| **Mandatory init variables** | `document_store`: An instance of [InMemoryDocumentStore](../../document-stores/inmemorydocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A list of floating point numbers |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [Retrievers](/reference/retrievers-api) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack/blob/main/haystack/components/retrievers/in_memory/embedding_retriever.py |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `InMemoryEmbeddingRetriever` is an embedding-based Retriever compatible with the `InMemoryDocumentStore`. It compares the query and Document embeddings and fetches the Documents most relevant to the query from the `InMemoryDocumentStore` based on the outcome.
|
||||
|
||||
When using the `InMemoryEmbeddingRetriever` in your NLP system, make sure it has the query and Document embeddings available. You can do so by adding a DocumentEmbedder to your indexing pipeline and a Text Embedder to your query pipeline. For details, see [Embedders](../embedders.mdx).
|
||||
|
||||
In addition to the `query_embedding`, the `InMemoryEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
The `embedding_similarity_function` to use for embedding retrieval must be defined when the corresponding`InMemoryDocumentStore` is initialized.
|
||||
|
||||
## Usage
|
||||
|
||||
### In a pipeline
|
||||
|
||||
Use this Retriever in a query pipeline like this:
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersTextEmbedder,
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
)
|
||||
from haystack.components.retrievers import InMemoryEmbeddingRetriever
|
||||
|
||||
document_store = InMemoryDocumentStore(embedding_similarity_function="cosine")
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder()
|
||||
|
||||
documents_with_embeddings = document_embedder.run(documents)["documents"]
|
||||
document_store.write_documents(documents_with_embeddings)
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder())
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
InMemoryEmbeddingRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
|
||||
result = query_pipeline.run({"text_embedder": {"text": query}})
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
---
|
||||
title: "MongoDBAtlasEmbeddingRetriever"
|
||||
id: mongodbatlasembeddingretriever
|
||||
slug: "/mongodbatlasembeddingretriever"
|
||||
description: "This is an embedding Retriever compatible with the MongoDB Atlas Document Store."
|
||||
---
|
||||
|
||||
# MongoDBAtlasEmbeddingRetriever
|
||||
|
||||
This is an embedding Retriever compatible with the MongoDB Atlas Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [MongoDBAtlasDocumentStore](../../document-stores/mongodbatlasdocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A list of floats |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [MongoDB Atlas](/reference/integrations-mongodb-atlas) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/mongodb_atlas |
|
||||
|
||||
</div>
|
||||
|
||||
The `MongoDBAtlasEmbeddingRetriever` is an embedding-based Retriever compatible with the [`MongoDBAtlasDocumentStore`](../../document-stores/mongodbatlasdocumentstore.mdx). It compares the query and Document embeddings and fetches the Documents most relevant to the query from the Document Store based on the outcome.
|
||||
|
||||
### Parameters
|
||||
|
||||
When using the `MongoDBAtlasEmbeddingRetriever` in your NLP system, ensure the query and Document [embeddings](../embedders.mdx) are available. You can do so by adding a Document Embedder to your indexing Pipeline and a Text Embedder to your query Pipeline.
|
||||
|
||||
In addition to the `query_embedding`, the `MongoDBAtlasEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
## Usage
|
||||
|
||||
### Installation
|
||||
|
||||
To start using MongoDB Atlas with Haystack, install the package with:
|
||||
|
||||
```shell
|
||||
pip install mongodb-atlas-haystack
|
||||
```
|
||||
|
||||
### On its own
|
||||
|
||||
The Retriever needs an instance of `MongoDBAtlasDocumentStore` and indexed Documents to run.
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.mongodb_atlas import (
|
||||
MongoDBAtlasDocumentStore,
|
||||
)
|
||||
from haystack_integrations.components.retrievers.mongodb_atlas import (
|
||||
MongoDBAtlasEmbeddingRetriever,
|
||||
)
|
||||
|
||||
document_store = MongoDBAtlasDocumentStore()
|
||||
|
||||
retriever = MongoDBAtlasEmbeddingRetriever(document_store=document_store)
|
||||
|
||||
## example run query
|
||||
retriever.run(query_embedding=[0.1] * 384)
|
||||
```
|
||||
|
||||
### In a Pipeline
|
||||
|
||||
```python
|
||||
from haystack import Pipeline, Document
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack.components.writers import DocumentWriter
|
||||
from haystack.components.generators import OpenAIGenerator
|
||||
from haystack.components.builders.prompt_builder import PromptBuilder
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
SentenceTransformersTextEmbedder,
|
||||
)
|
||||
from haystack_integrations.document_stores.mongodb_atlas import (
|
||||
MongoDBAtlasDocumentStore,
|
||||
)
|
||||
from haystack_integrations.components.embedders.mongodb_atlas import (
|
||||
MongoDBAtlasEmbeddingRetriever,
|
||||
)
|
||||
|
||||
## Create some example documents
|
||||
documents = [
|
||||
Document(content="My name is Jean and I live in Paris."),
|
||||
Document(content="My name is Mark and I live in Berlin."),
|
||||
Document(content="My name is Giorgio and I live in Rome."),
|
||||
]
|
||||
|
||||
## We support many different databases. Here we load a simple and lightweight in-memory document store.
|
||||
document_store = MongoDBAtlasDocumentStore()
|
||||
|
||||
## Define some more components
|
||||
doc_writer = DocumentWriter(document_store=document_store, policy=DuplicatePolicy.SKIP)
|
||||
doc_embedder = SentenceTransformersDocumentEmbedder(model="intfloat/e5-base-v2")
|
||||
query_embedder = SentenceTransformersTextEmbedder(model="intfloat/e5-base-v2")
|
||||
|
||||
## Pipeline that ingests document for retrieval
|
||||
ingestion_pipe = Pipeline()
|
||||
ingestion_pipe.add_component(instance=doc_embedder, name="doc_embedder")
|
||||
ingestion_pipe.add_component(instance=doc_writer, name="doc_writer")
|
||||
|
||||
ingestion_pipe.connect("doc_embedder.documents", "doc_writer.documents")
|
||||
ingestion_pipe.run({"doc_embedder": {"documents": documents}})
|
||||
|
||||
## Build a RAG pipeline with a Retriever to get relevant documents to
|
||||
## the query and a OpenAIGenerator interacting with LLMs using a custom prompt.
|
||||
prompt_template = """
|
||||
Given these documents, answer the question.\nDocuments:
|
||||
{% for doc in documents %}
|
||||
{{ doc.content }}
|
||||
{% endfor %}
|
||||
|
||||
\nQuestion: {{question}}
|
||||
\nAnswer:
|
||||
"""
|
||||
rag_pipeline = Pipeline()
|
||||
rag_pipeline.add_component(instance=query_embedder, name="query_embedder")
|
||||
rag_pipeline.add_component(
|
||||
instance=MongoDBAtlasEmbeddingRetriever(document_store=document_store),
|
||||
name="retriever",
|
||||
)
|
||||
rag_pipeline.add_component(
|
||||
instance=PromptBuilder(template=prompt_template),
|
||||
name="prompt_builder",
|
||||
)
|
||||
rag_pipeline.add_component(instance=OpenAIGenerator(), name="llm")
|
||||
rag_pipeline.connect("query_embedder", "retriever.query_embedding")
|
||||
rag_pipeline.connect("embedding_retriever", "prompt_builder.documents")
|
||||
rag_pipeline.connect("prompt_builder", "llm")
|
||||
|
||||
## Ask a question on the data you just added.
|
||||
question = "Where does Mark live?"
|
||||
result = rag_pipeline.run(
|
||||
{
|
||||
"query_embedder": {"text": question},
|
||||
"prompt_builder": {"question": question},
|
||||
},
|
||||
)
|
||||
|
||||
## For details, like which documents were used to generate the answer, look into the GeneratedAnswer object
|
||||
print(result["answer_builder"]["answers"])
|
||||
```
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
---
|
||||
title: "MongoDBAtlasFullTextRetriever"
|
||||
id: mongodbatlasfulltextretriever
|
||||
slug: "/mongodbatlasfulltextretriever"
|
||||
description: "This is a full-text search Retriever compatible with the MongoDB Atlas Document Store."
|
||||
---
|
||||
|
||||
# MongoDBAtlasFullTextRetriever
|
||||
|
||||
This is a full-text search Retriever compatible with the MongoDB Atlas Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. Before a [ChatPromptBuilder](../builders/chatpromptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. Before an [ExtractiveReader](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [MongoDBAtlasDocumentStore](../../document-stores/mongodbatlasdocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query`: A query string to search for. If the query contains multiple terms, Atlas Search evaluates each term separately for matches. |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [MongoDB Atlas](/reference/integrations-mongodb-atlas) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/mongodb_atlas |
|
||||
|
||||
</div>
|
||||
|
||||
The `MongoDBAtlasFullTextRetriever` is a full-text search Retriever compatible with the [`MongoDBAtlasDocumentStore`](../../document-stores/mongodbatlasdocumentstore.mdx). The full-text search is dependent on the `full_text_search_index` used in the [`MongoDBAtlasDocumentStore`](../../document-stores/mongodbatlasdocumentstore.mdx).
|
||||
|
||||
### Parameters
|
||||
|
||||
In addition to the `query`, the `MongoDBAtlasFullTextRetriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
When running the component, you can specify more optional parameters such as `fuzzy` or `synonyms`, `match_criteria`, `score`. Check out our [MongoDB Atlas](/reference/integrations-mongodb-atlas) API Reference for more details on all parameters.
|
||||
|
||||
## Usage
|
||||
|
||||
### Installation
|
||||
|
||||
To start using MongoDB Atlas with Haystack, install the package with:
|
||||
|
||||
```shell
|
||||
pip install mongodb-atlas-haystack
|
||||
```
|
||||
|
||||
### On its own
|
||||
|
||||
The Retriever needs an instance of `MongoDBAtlasDocumentStore` and indexed documents to run.
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.mongodb_atlas import (
|
||||
MongoDBAtlasDocumentStore,
|
||||
)
|
||||
from haystack_integrations.components.retrievers.mongodb_atlas import (
|
||||
MongoDBAtlasFullTextRetriever,
|
||||
)
|
||||
|
||||
store = MongoDBAtlasDocumentStore(
|
||||
database_name="your_existing_db",
|
||||
collection_name="your_existing_collection",
|
||||
vector_search_index="your_existing_index",
|
||||
full_text_search_index="your_existing_index",
|
||||
)
|
||||
retriever = MongoDBAtlasFullTextRetriever(document_store=store)
|
||||
|
||||
results = retriever.run(query="Your search query")
|
||||
print(results["documents"])
|
||||
```
|
||||
|
||||
### In a Pipeline
|
||||
|
||||
Here's a Hybrid Retrieval pipeline example that makes use of both available MongoDB Atlas Retrievers:
|
||||
|
||||
```python
|
||||
from haystack import Pipeline, Document
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack.components.writers import DocumentWriter
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
SentenceTransformersTextEmbedder,
|
||||
)
|
||||
from haystack.components.joiners import DocumentJoiner
|
||||
|
||||
from haystack_integrations.document_stores.mongodb_atlas import (
|
||||
MongoDBAtlasDocumentStore,
|
||||
)
|
||||
from haystack_integrations.components.retrievers.mongodb_atlas import (
|
||||
MongoDBAtlasEmbeddingRetriever,
|
||||
MongoDBAtlasFullTextRetriever,
|
||||
)
|
||||
|
||||
documents = [
|
||||
Document(content="My name is Jean and I live in Paris."),
|
||||
Document(content="My name is Mark and I live in Berlin."),
|
||||
Document(content="My name is Giorgio and I live in Rome."),
|
||||
Document(content="Python is a programming language popular for data science."),
|
||||
Document(
|
||||
content="MongoDB Atlas offers full-text search and vector search capabilities.",
|
||||
),
|
||||
]
|
||||
|
||||
document_store = MongoDBAtlasDocumentStore(
|
||||
database_name="haystack_test",
|
||||
collection_name="test_collection",
|
||||
vector_search_index="test_vector_search_index",
|
||||
full_text_search_index="test_full_text_search_index",
|
||||
)
|
||||
|
||||
## Clean out any old data so this example is repeatable
|
||||
print(f"Clearing collection {document_store.collection_name} …")
|
||||
document_store.collection.delete_many({})
|
||||
|
||||
ingest_pipe = Pipeline()
|
||||
|
||||
doc_embedder = SentenceTransformersDocumentEmbedder(model="intfloat/e5-base-v2")
|
||||
ingest_pipe.add_component(instance=doc_embedder, name="doc_embedder")
|
||||
|
||||
doc_writer = DocumentWriter(document_store=document_store, policy=DuplicatePolicy.SKIP)
|
||||
ingest_pipe.add_component(instance=doc_writer, name="doc_writer")
|
||||
ingest_pipe.connect("doc_embedder.documents", "doc_writer.documents")
|
||||
|
||||
print(f"Running ingestion on {len(documents)} in-memory docs …")
|
||||
ingest_pipe.run({"doc_embedder": {"documents": documents}})
|
||||
|
||||
query_pipe = Pipeline()
|
||||
|
||||
text_embedder = SentenceTransformersTextEmbedder(model="intfloat/e5-base-v2")
|
||||
query_pipe.add_component(instance=text_embedder, name="text_embedder")
|
||||
|
||||
embed_retriever = MongoDBAtlasEmbeddingRetriever(document_store=document_store, top_k=3)
|
||||
query_pipe.add_component(instance=embed_retriever, name="embedding_retriever")
|
||||
query_pipe.connect("text_embedder", "embedding_retriever")
|
||||
|
||||
## (c) full-text retriever
|
||||
ft_retriever = MongoDBAtlasFullTextRetriever(document_store=document_store, top_k=3)
|
||||
query_pipe.add_component(instance=ft_retriever, name="full_text_retriever")
|
||||
|
||||
joiner = DocumentJoiner(join_mode="reciprocal_rank_fusion", top_k=3)
|
||||
query_pipe.add_component(instance=joiner, name="joiner")
|
||||
|
||||
query_pipe.connect("embedding_retriever", "joiner")
|
||||
query_pipe.connect("full_text_retriever", "joiner")
|
||||
|
||||
question = "Where does Mark live?"
|
||||
print(f"Running hybrid retrieval for query: '{question}'")
|
||||
output = query_pipe.run(
|
||||
{
|
||||
"text_embedder": {"text": question},
|
||||
"full_text_retriever": {"query": question},
|
||||
},
|
||||
)
|
||||
|
||||
print("\nFinal fused documents:")
|
||||
for doc in output["joiner"]["documents"]:
|
||||
print(f"- {doc.content}")
|
||||
```
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
---
|
||||
title: "MultiQueryEmbeddingRetriever"
|
||||
id: multiqueryembeddingretriever
|
||||
slug: "/multiqueryembeddingretriever"
|
||||
description: "Retrieves documents using multiple queries in parallel with an embedding-based Retriever."
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# MultiQueryEmbeddingRetriever
|
||||
|
||||
Retrieves documents using multiple queries in parallel with an embedding-based Retriever.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | After a [`QueryExpander`](../query/queryexpander.mdx) component, before a [`ChatPromptBuilder`](../builders/chatpromptbuilder.mdx) in RAG pipelines |
|
||||
| **Mandatory init variables** | `retriever`: An embedding-based Retriever (such as `InMemoryEmbeddingRetriever`)<br />`query_embedder`: A Text Embedder component |
|
||||
| **Mandatory run variables** | `queries`: A list of query strings |
|
||||
| **Output variables** | `documents`: A list of retrieved documents sorted by relevance score |
|
||||
| **API reference** | [Retrievers](/reference/retrievers-api) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack/blob/main/haystack/components/retrievers/multi_query_embedding_retriever.py |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
`MultiQueryEmbeddingRetriever` improves retrieval recall by searching for documents using multiple queries in parallel. Each query is converted to an embedding using a Text Embedder, and an embedding-based Retriever fetches relevant documents.
|
||||
|
||||
The component:
|
||||
- Processes queries in parallel using a thread pool for better performance
|
||||
- Automatically deduplicates results based on document content
|
||||
- Sorts the final results by relevance score
|
||||
|
||||
This Retriever is particularly effective when combined with [`QueryExpander`](../query/queryexpander.mdx), which generates multiple query variations from a single user query. By searching with these variations, you can find documents that might not match the original query phrasing but are still relevant.
|
||||
|
||||
Use `MultiQueryEmbeddingRetriever` when your documents use different words than your users' queries, or when you want to find more diverse results in RAG pipelines. Running multiple queries takes more time, but you can speed it up by increasing `max_workers` to run queries in parallel.
|
||||
|
||||
:::tip[When to use a `MultiQueryTextRetriever` instead]
|
||||
|
||||
If you need exact keyword matching and don't want to use embeddings, use [`MultiQueryTextRetriever`](multiquerytextretriever.mdx) instead. It works with text-based Retrievers like `InMemoryBM25Retriever` and is better when synonyms can be generated through query expansion.
|
||||
:::
|
||||
|
||||
### Passing Additional Retriever Parameters
|
||||
|
||||
You can pass additional parameters to the underlying Retriever using `retriever_kwargs`:
|
||||
|
||||
```python
|
||||
result = multi_query_retriever.run(
|
||||
queries=["renewable energy", "sustainable power"],
|
||||
retriever_kwargs={"top_k": 5},
|
||||
)
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
This pipeline takes a single query "sustainable power generation" and expands it into multiple variations using an LLM (for example: "renewable energy sources", "green electricity", "clean power"). The Retriever then converts each variation to an embedding and searches for similar documents. This way, documents about "solar energy" or "wind energy" can be found even though they don't contain the words "sustainable power generation".
|
||||
|
||||
Before running the pipeline, documents must be embedded using a Document Embedder and stored in the Document Store.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python" default>
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
from haystack.components.embedders 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}")
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="yaml" label="YAML">
|
||||
|
||||
```yaml
|
||||
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.components.embedders.sentence_transformers_text_embedder.SentenceTransformersTextEmbedder
|
||||
init_parameters:
|
||||
model: sentence-transformers/all-MiniLM-L6-v2
|
||||
|
||||
connections:
|
||||
- sender: query_expander.queries
|
||||
receiver: retriever.queries
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
+307
@@ -0,0 +1,307 @@
|
||||
---
|
||||
title: "MultiQueryTextRetriever"
|
||||
id: multiquerytextretriever
|
||||
slug: "/multiquerytextretriever"
|
||||
description: "Retrieves documents using multiple queries in parallel with a text-based Retriever."
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# MultiQueryTextRetriever
|
||||
|
||||
Retrieves documents using multiple queries in parallel with a text-based Retriever.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | After a [`QueryExpander`](../query/queryexpander.mdx) component, before a [`ChatPromptBuilder`](../builders/chatpromptbuilder.mdx) in RAG pipelines |
|
||||
| **Mandatory init variables** | `retriever`: A text-based Retriever (such as `InMemoryBM25Retriever`) |
|
||||
| **Mandatory run variables** | `queries`: A list of query strings |
|
||||
| **Output variables** | `documents`: A list of retrieved documents sorted by relevance score |
|
||||
| **API reference** | [Retrievers](/reference/retrievers-api) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack/blob/main/haystack/components/retrievers/multi_query_text_retriever.py |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
`MultiQueryTextRetriever` improves retrieval recall by searching for documents using multiple queries in parallel. It wraps a text-based Retriever (such as `InMemoryBM25Retriever`) and processes multiple query strings simultaneously using a thread pool.
|
||||
|
||||
The component:
|
||||
- Processes queries in parallel for better performance
|
||||
- Automatically deduplicates results based on document content
|
||||
- Sorts the final results by relevance score
|
||||
|
||||
This Retriever is particularly effective when combined with [`QueryExpander`](../query/queryexpander.mdx), which generates multiple query variations from a single user query. By searching with these variations, you can find documents that use different keywords than the original query.
|
||||
|
||||
Use `MultiQueryTextRetriever` when your documents use different words than your users' queries, or when you want to use query expansion with keyword-based search (BM25). Running multiple queries takes more time, but you can speed it up by increasing `max_workers` to run queries in parallel.
|
||||
|
||||
:::tip[When to use `MultiQueryEmbeddingRetriever` instead]
|
||||
|
||||
If you need semantic search where meaning matters more than exact keyword matches, use [`MultiQueryEmbeddingRetriever`](multiqueryembeddingretriever.mdx) instead. It works with embedding-based Retrievers and requires a Text Embedder.
|
||||
:::
|
||||
|
||||
### Passing Additional Retriever Parameters
|
||||
|
||||
You can pass additional parameters to the underlying Retriever using `retriever_kwargs`:
|
||||
|
||||
```python
|
||||
result = multiquery_retriever.run(
|
||||
queries=["renewable energy", "sustainable power"],
|
||||
retriever_kwargs={"top_k": 5},
|
||||
)
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
In this example, we pass three queries manually to the Retriever: "renewable energy", "geothermal", and "hydropower". The Retriever runs a BM25 search for each query (retrieving up to 2 documents per query), then combines all results, removes duplicates, and sorts them by score.
|
||||
|
||||
```python
|
||||
from haystack import Document
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
from haystack.components.retrievers import (
|
||||
InMemoryBM25Retriever,
|
||||
MultiQueryTextRetriever,
|
||||
)
|
||||
|
||||
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="Hydropower is a form of renewable energy using the flow of water to generate electricity.",
|
||||
),
|
||||
Document(
|
||||
content="Geothermal energy is heat that comes from the sub-surface of the earth.",
|
||||
),
|
||||
]
|
||||
|
||||
document_store = InMemoryDocumentStore()
|
||||
document_store.write_documents(documents)
|
||||
|
||||
retriever = MultiQueryTextRetriever(
|
||||
retriever=InMemoryBM25Retriever(document_store=document_store, top_k=2),
|
||||
)
|
||||
|
||||
results = retriever.run(queries=["renewable energy", "geothermal", "hydropower"])
|
||||
|
||||
for doc in results["documents"]:
|
||||
print(f"Content: {doc.content}, Score: {doc.score:.4f}")
|
||||
```
|
||||
|
||||
### In a pipeline with QueryExpander
|
||||
|
||||
This pipeline takes a single query "sustainable power" and expands it into multiple variations using an LLM (for example: "renewable energy sources", "green electricity", "clean power"). The Retriever then searches for each variation and combines the results. This way, documents about "solar energy" or "hydropower" can be found even though they don't contain the words "sustainable power".
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python" default>
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
from haystack.components.query import QueryExpander
|
||||
from haystack.components.retrievers import (
|
||||
InMemoryBM25Retriever,
|
||||
MultiQueryTextRetriever,
|
||||
)
|
||||
|
||||
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="Hydropower is a form of renewable energy using the flow of water to generate electricity.",
|
||||
),
|
||||
Document(
|
||||
content="Geothermal energy is heat that comes from the sub-surface of the earth.",
|
||||
),
|
||||
]
|
||||
|
||||
document_store = InMemoryDocumentStore()
|
||||
document_store.write_documents(documents)
|
||||
|
||||
pipeline = Pipeline()
|
||||
pipeline.add_component("query_expander", QueryExpander(n_expansions=3))
|
||||
pipeline.add_component(
|
||||
"retriever",
|
||||
MultiQueryTextRetriever(
|
||||
retriever=InMemoryBM25Retriever(document_store=document_store, top_k=2),
|
||||
),
|
||||
)
|
||||
pipeline.connect("query_expander.queries", "retriever.queries")
|
||||
|
||||
result = pipeline.run({"query_expander": {"query": "sustainable power"}})
|
||||
|
||||
for doc in result["retriever"]["documents"]:
|
||||
print(f"Score: {doc.score:.3f} | {doc.content}")
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="yaml" label="YAML">
|
||||
|
||||
```yaml
|
||||
components:
|
||||
query_expander:
|
||||
type: haystack.components.query.query_expander.QueryExpander
|
||||
init_parameters:
|
||||
n_expansions: 3
|
||||
retriever:
|
||||
type: haystack.components.retrievers.multi_query_text_retriever.MultiQueryTextRetriever
|
||||
init_parameters:
|
||||
retriever:
|
||||
type: haystack.components.retrievers.in_memory.bm25_retriever.InMemoryBM25Retriever
|
||||
init_parameters:
|
||||
document_store:
|
||||
type: haystack.document_stores.in_memory.document_store.InMemoryDocumentStore
|
||||
init_parameters: {}
|
||||
top_k: 2
|
||||
|
||||
connections:
|
||||
- sender: query_expander.queries
|
||||
receiver: retriever.queries
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### In a RAG pipeline
|
||||
|
||||
This RAG pipeline answers questions using query expansion. When a user asks "What types of energy come from natural sources?", the pipeline:
|
||||
|
||||
1. Expands the question into multiple search queries using an LLM
|
||||
2. Retrieves relevant documents for each query variation
|
||||
3. Builds a prompt containing the retrieved documents and the original question
|
||||
4. Sends the prompt to an LLM to generate an answer
|
||||
|
||||
The question is sent to both the `query_expander` (for generating search queries) and the `prompt_builder` (for the final prompt to the LLM).
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python" default>
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
from haystack.components.builders import ChatPromptBuilder
|
||||
from haystack.components.generators.chat import OpenAIChatGenerator
|
||||
from haystack.components.query import QueryExpander
|
||||
from haystack.components.retrievers import (
|
||||
InMemoryBM25Retriever,
|
||||
MultiQueryTextRetriever,
|
||||
)
|
||||
from haystack.dataclasses import ChatMessage
|
||||
|
||||
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_store = InMemoryDocumentStore()
|
||||
document_store.write_documents(documents)
|
||||
|
||||
prompt_template = [
|
||||
ChatMessage.from_system(
|
||||
"You are a helpful assistant that answers questions based on the provided documents.",
|
||||
),
|
||||
ChatMessage.from_user(
|
||||
"Given these documents, answer the question.\n"
|
||||
"Documents:\n"
|
||||
"{% for doc in documents %}"
|
||||
"{{ doc.content }}\n"
|
||||
"{% endfor %}\n"
|
||||
"Question: {{ question }}",
|
||||
),
|
||||
]
|
||||
|
||||
# Note: This assumes OPENAI_API_KEY environment variable is set
|
||||
rag_pipeline = Pipeline()
|
||||
rag_pipeline.add_component("query_expander", QueryExpander(n_expansions=2))
|
||||
rag_pipeline.add_component(
|
||||
"retriever",
|
||||
MultiQueryTextRetriever(
|
||||
retriever=InMemoryBM25Retriever(document_store=document_store, top_k=2),
|
||||
),
|
||||
)
|
||||
rag_pipeline.add_component(
|
||||
"prompt_builder",
|
||||
ChatPromptBuilder(
|
||||
template=prompt_template,
|
||||
required_variables=["documents", "question"],
|
||||
),
|
||||
)
|
||||
rag_pipeline.add_component("llm", OpenAIChatGenerator())
|
||||
|
||||
rag_pipeline.connect("query_expander.queries", "retriever.queries")
|
||||
rag_pipeline.connect("retriever.documents", "prompt_builder.documents")
|
||||
rag_pipeline.connect("prompt_builder.prompt", "llm.messages")
|
||||
|
||||
question = "What types of energy come from natural sources?"
|
||||
result = rag_pipeline.run(
|
||||
{"query_expander": {"query": question}, "prompt_builder": {"question": question}},
|
||||
)
|
||||
|
||||
print(result["llm"]["replies"][0].text)
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="yaml" label="YAML">
|
||||
|
||||
```yaml
|
||||
components:
|
||||
query_expander:
|
||||
type: haystack.components.query.query_expander.QueryExpander
|
||||
init_parameters:
|
||||
n_expansions: 2
|
||||
retriever:
|
||||
type: haystack.components.retrievers.multi_query_text_retriever.MultiQueryTextRetriever
|
||||
init_parameters:
|
||||
retriever:
|
||||
type: haystack.components.retrievers.in_memory.bm25_retriever.InMemoryBM25Retriever
|
||||
init_parameters:
|
||||
document_store:
|
||||
type: haystack.document_stores.in_memory.document_store.InMemoryDocumentStore
|
||||
init_parameters: {}
|
||||
top_k: 2
|
||||
prompt_builder:
|
||||
type: haystack.components.builders.chat_prompt_builder.ChatPromptBuilder
|
||||
init_parameters:
|
||||
required_variables:
|
||||
- documents
|
||||
- question
|
||||
llm:
|
||||
type: haystack.components.generators.chat.openai.OpenAIChatGenerator
|
||||
init_parameters: {}
|
||||
|
||||
connections:
|
||||
- sender: query_expander.queries
|
||||
receiver: retriever.queries
|
||||
- sender: retriever.documents
|
||||
receiver: prompt_builder.documents
|
||||
- sender: prompt_builder.prompt
|
||||
receiver: llm.messages
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
---
|
||||
title: "OpenSearchBM25Retriever"
|
||||
id: opensearchbm25retriever
|
||||
slug: "/opensearchbm25retriever"
|
||||
description: "This is a keyword-based Retriever that fetches Documents matching a query from an OpenSearch Document Store."
|
||||
---
|
||||
|
||||
# OpenSearchBM25Retriever
|
||||
|
||||
This is a keyword-based Retriever that fetches Documents matching a query from an OpenSearch Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. Before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. Before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of an [OpenSearchDocumentStore](../../document-stores/opensearch-document-store.mdx) |
|
||||
| **Mandatory run variables** | `query`: A query string |
|
||||
| **Output variables** | `documents`: A list of documents matching the query |
|
||||
| **API reference** | [OpenSearch](/reference/integrations-opensearch) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/opensearch |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
`OpenSearchBM25Retriever` is a keyword-based Retriever that fetches Documents matching a query from an `OpenSearchDocumentStore`. It determines the similarity between Documents and the query based on the BM25 algorithm, which computes a weighted word overlap between the two strings.
|
||||
|
||||
Since the `OpenSearchBM25Retriever` matches strings based on word overlap, it’s often used to find exact matches to names of persons or products, IDs, or well-defined error messages. The BM25 algorithm is very lightweight and simple. Nevertheless, it can be hard to beat with more complex embedding-based approaches on out-of-domain data.
|
||||
|
||||
In addition to the `query`, the `OpenSearchBM25Retriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
You can adjust how [inexact fuzzy matching](https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#fuzziness) is performed, using the `fuzziness` parameter.
|
||||
It is also possible to specify if all terms in the query must match using the `all_terms_must_match` parameter, which defaults to `False`.
|
||||
|
||||
If you want more flexible matching of a query to Documents, you can use the `OpenSearchEmbeddingRetriever`, which uses vectors created by LLMs to retrieve relevant information.
|
||||
|
||||
### Setup and installation
|
||||
|
||||
[Install](https://opensearch.org/docs/latest/install-and-configure/install-opensearch/index/) and run an OpenSearch instance.
|
||||
|
||||
If you have Docker set up, we recommend pulling the Docker image and running it.
|
||||
|
||||
```shell
|
||||
docker pull opensearchproject/opensearch:2.11.0
|
||||
docker run -p 9200:9200 -p 9600:9600 -e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms1024m -Xmx1024m" opensearchproject/opensearch:2.11.0
|
||||
```
|
||||
|
||||
As an alternative, you can go to [OpenSearch integration GitHub](https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/opensearch) and start a Docker container running OpenSearch using the provided `docker-compose.yml`:
|
||||
|
||||
```shell
|
||||
docker compose up
|
||||
```
|
||||
|
||||
Once you have a running OpenSearch instance, install the `opensearch-haystack` integration:
|
||||
|
||||
```shell
|
||||
pip install opensearch-haystack
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
This Retriever needs the `OpensearchDocumentStore` and indexed Documents to run. You can’t use it on its own.
|
||||
|
||||
### In a RAG pipeline
|
||||
|
||||
Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
|
||||
|
||||
```python
|
||||
from haystack_integrations.components.retrievers.opensearch import (
|
||||
OpenSearchBM25Retriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.opensearch import OpenSearchDocumentStore
|
||||
|
||||
from haystack import Document
|
||||
from haystack import Pipeline
|
||||
from haystack.components.builders.answer_builder import AnswerBuilder
|
||||
from haystack.components.builders.prompt_builder import PromptBuilder
|
||||
from haystack.components.generators import OpenAIGenerator
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
|
||||
import os
|
||||
|
||||
api_key = os.environ["OPENAI_API_KEY"]
|
||||
|
||||
## Create a RAG query pipeline
|
||||
prompt_template = """
|
||||
Given these documents, answer the question.\nDocuments:
|
||||
{% for doc in documents %}
|
||||
{{ doc.content }}
|
||||
{% endfor %}
|
||||
|
||||
\nQuestion: {{question}}
|
||||
\nAnswer:
|
||||
"""
|
||||
|
||||
document_store = OpenSearchDocumentStore(
|
||||
hosts="http://localhost:9200",
|
||||
use_ssl=True,
|
||||
verify_certs=False,
|
||||
http_auth=("admin", "admin"),
|
||||
)
|
||||
|
||||
## Add Documents
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
## DuplicatePolicy.SKIP param is optional, but useful to run the script multiple times without throwing errors
|
||||
document_store.write_documents(documents=documents, policy=DuplicatePolicy.SKIP)
|
||||
|
||||
retriever = OpenSearchBM25Retriever(document_store=document_store)
|
||||
rag_pipeline = Pipeline()
|
||||
rag_pipeline.add_component(name="retriever", instance=retriever)
|
||||
rag_pipeline.add_component(
|
||||
instance=PromptBuilder(template=prompt_template),
|
||||
name="prompt_builder",
|
||||
)
|
||||
rag_pipeline.add_component(instance=OpenAIGenerator(api_key=api_key), name="llm")
|
||||
rag_pipeline.add_component(instance=AnswerBuilder(), name="answer_builder")
|
||||
rag_pipeline.connect("retriever", "prompt_builder.documents")
|
||||
rag_pipeline.connect("prompt_builder", "llm")
|
||||
rag_pipeline.connect("llm.replies", "answer_builder.replies")
|
||||
rag_pipeline.connect("llm.metadata", "answer_builder.metadata")
|
||||
rag_pipeline.connect("retriever", "answer_builder.documents")
|
||||
|
||||
question = "How many languages are spoken around the world today?"
|
||||
result = rag_pipeline.run(
|
||||
{
|
||||
"retriever": {"query": question},
|
||||
"prompt_builder": {"question": question},
|
||||
"answer_builder": {"query": question},
|
||||
},
|
||||
)
|
||||
print(result["answer_builder"]["answers"][0])
|
||||
```
|
||||
|
||||
Here’s an example output:
|
||||
|
||||
```python
|
||||
GeneratedAnswer(
|
||||
data='Over 7,000 languages are spoken around the world today.',
|
||||
query='How many languages are spoken around the world today?',
|
||||
documents=[
|
||||
Document(id=cfe93bc1c274908801e6670440bf2bbba54fad792770d57421f85ffa2a4fcc94, content: 'There are over 7,000 languages spoken around the world today.', score: 7.179112),
|
||||
Document(id=7f225626ad1019b273326fbaf11308edfca6d663308a4a3533ec7787367d59a2, content: 'In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the ph...', score: 1.1426818)],
|
||||
meta={'model': 'gpt-3.5-turbo-0613', 'index': 0, 'finish_reason': 'stop', 'usage': {'prompt_tokens': 86, 'completion_tokens': 13, 'total_tokens': 99}})
|
||||
```
|
||||
|
||||
## Additional References
|
||||
|
||||
🧑🍳 Cookbook: [PDF-Based Question Answering with Amazon Bedrock and Haystack](https://haystack.deepset.ai/cookbook/amazon_bedrock_for_documentation_qa)
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
---
|
||||
title: "OpenSearchEmbeddingRetriever"
|
||||
id: opensearchembeddingretriever
|
||||
slug: "/opensearchembeddingretriever"
|
||||
description: "An embedding-based Retriever compatible with the OpenSearch Document Store."
|
||||
---
|
||||
|
||||
# OpenSearchEmbeddingRetriever
|
||||
|
||||
An embedding-based Retriever compatible with the OpenSearch Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of an [OpenSearchDocumentStore](../../document-stores/opensearch-document-store.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A list of floats |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [OpenSearch](/reference/integrations-opensearch) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/opensearch |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `OpenSearchEmbeddingRetriever` is an embedding-based Retriever compatible with the `OpenSearchDocumentStore`. It compares the query and Document embeddings and fetches the Documents most relevant to the query from the `OpenSearchDocumentStore` based on the outcome.
|
||||
|
||||
When using the `OpenSearchEmbeddingRetriever` in your NLP system, make sure it has the query and Document embeddings available. You can do so by adding a Document Embedder to your indexing pipeline and a Text Embedder to your query pipeline.
|
||||
|
||||
In addition to the `query_embedding`, the `OpenSearchEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
The `embedding_dim` for storing and retrieving embeddings must be defined when the corresponding `OpenSearchDocumentStore` is initialized.
|
||||
|
||||
### Setup and installation
|
||||
|
||||
[Install](https://opensearch.org/docs/latest/install-and-configure/install-opensearch/index/) and run an OpenSearch instance.
|
||||
|
||||
If you have Docker set up, we recommend pulling the Docker image and running it.
|
||||
|
||||
```shell
|
||||
docker pull opensearchproject/opensearch:2.11.0
|
||||
docker run -p 9200:9200 -p 9600:9600 -e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms1024m -Xmx1024m" opensearchproject/opensearch:2.11.0
|
||||
```
|
||||
|
||||
As an alternative, you can go to [OpenSearch integration GitHub](https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/opensearch) and start a Docker container running OpenSearch using the provided `docker-compose.yml`:
|
||||
|
||||
```shell
|
||||
docker compose up
|
||||
```
|
||||
|
||||
Once you have a running OpenSearch instance, install the `opensearch-haystack` integration:
|
||||
|
||||
```shell
|
||||
pip install opensearch-haystack
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### In a pipeline
|
||||
|
||||
Use this Retriever in a query Pipeline like this:
|
||||
|
||||
```python
|
||||
from haystack_integrations.components.retrievers.opensearch import (
|
||||
OpenSearchEmbeddingRetriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.opensearch import OpenSearchDocumentStore
|
||||
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack import Document
|
||||
from haystack import Pipeline
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersTextEmbedder,
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
)
|
||||
|
||||
document_store = OpenSearchDocumentStore(
|
||||
hosts="http://localhost:9200",
|
||||
use_ssl=True,
|
||||
verify_certs=False,
|
||||
http_auth=("admin", "admin"),
|
||||
)
|
||||
|
||||
model = "sentence-transformers/all-mpnet-base-v2"
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder(model=model)
|
||||
documents_with_embeddings = document_embedder.run(documents)
|
||||
|
||||
document_store.write_documents(
|
||||
documents_with_embeddings.get("documents"),
|
||||
policy=DuplicatePolicy.SKIP,
|
||||
)
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component(
|
||||
"text_embedder",
|
||||
SentenceTransformersTextEmbedder(model=model),
|
||||
)
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
OpenSearchEmbeddingRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
|
||||
result = query_pipeline.run({"text_embedder": {"text": query}})
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
|
||||
The example output would be:
|
||||
|
||||
```python
|
||||
Document(id=cfe93bc1c274908801e6670440bf2bbba54fad792770d57421f85ffa2a4fcc94, content: 'There are over 7,000 languages spoken around the world today.', score: 0.70026743, embedding: vector of size 768)
|
||||
```
|
||||
|
||||
## Additional References
|
||||
|
||||
🧑🍳 Cookbook: [PDF-Based Question Answering with Amazon Bedrock and Haystack](https://haystack.deepset.ai/cookbook/amazon_bedrock_for_documentation_qa)
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
---
|
||||
title: "OpenSearchHybridRetriever"
|
||||
id: opensearchhybridretriever
|
||||
slug: "/opensearchhybridretriever"
|
||||
description: "This is a [SuperComponent](../../concepts/components/supercomponents.mdx) that implements a Hybrid Retriever in a single component, relying on OpenSearch as the backend Document Store."
|
||||
---
|
||||
|
||||
# OpenSearchHybridRetriever
|
||||
|
||||
This is a [SuperComponent](../../concepts/components/supercomponents.mdx) that implements a Hybrid Retriever in a single component, relying on OpenSearch as the backend Document Store.
|
||||
|
||||
A Hybrid Retriever uses both traditional keyword-based search (such as BM25) and embedding-based search to retrieve documents, combining the strengths of both approaches. The Retriever then merges and re-ranks the results from both methods.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| Most common position in a pipeline | After an [OpenSearchDocumentStore](../../document-stores/opensearch-document-store.mdx) |
|
||||
| Mandatory init variables | `document_store`: An instance of `OpenSearchDocumentStore` to use for retrieval <br /> <br />`embedder`: Any [Embedder](../embedders.mdx) implementing the `TextEmbedder` protocol |
|
||||
| Mandatory run variables | `query`: A query string |
|
||||
| Output variables | `documents`: A list of documents matching the query |
|
||||
| API reference | [OpenSearch](/reference/integrations-opensearch) |
|
||||
| GitHub | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/opensearch |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `OpenSearchHybridRetriever` combines two retrieval methods:
|
||||
|
||||
1. **BM25 Retrieval**: A keyword-based search that uses the BM25 algorithm to find documents based on term frequency and inverse document frequency. It's based on the [`OpenSearchBM25Retriever`](opensearchbm25retriever.mdx) component and is suitable for traditional keyword-based search.
|
||||
2. **Embedding-based Retrieval**: A semantic search that uses vector similarity to find documents that are semantically similar to the query. It's based on the [`OpenSearchEmbeddingRetriever`](opensearchembeddingretriever.mdx) component and is suitable for semantic search.
|
||||
|
||||
The component automatically handles:
|
||||
|
||||
- Converting the query into an embedding using the provided embedded,
|
||||
- Running both retrieval methods in parallel,
|
||||
- Merging and re-ranking the results using the specified join mode.
|
||||
|
||||
### Setup and Installation
|
||||
|
||||
```shell
|
||||
pip install opensearch-haystack
|
||||
```
|
||||
|
||||
### Optional Parameters
|
||||
|
||||
This Retriever accepts various optional parameters. You can verify the most up-to-date list of parameters in our [API Reference](/reference/integrations-opensearch#opensearchhybridretriever).
|
||||
|
||||
You can pass additional parameters to the underlying components using the `bm25_retriever` and `embedding_retriever` dictionaries.
|
||||
The `DocumentJoiner` parameters are all exposed on the `OpenSearchHybridRetriever` class, so you can set them directly.
|
||||
|
||||
Here's an example:
|
||||
|
||||
```python
|
||||
retriever = OpenSearchHybridRetriever(
|
||||
document_store=document_store,
|
||||
embedder=embedder,
|
||||
bm25_retriever={"raise_on_failure": True},
|
||||
embedding_retriever={"raise_on_failure": False},
|
||||
)
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
This Retriever needs the `OpensearchDocumentStore` populated with documents to run. You can’t use it on its own.
|
||||
|
||||
### In a pipeline
|
||||
|
||||
Here's a basic example of how to use the `OpenSearchHybridRetriever`:
|
||||
|
||||
You can use the following command to run OpenSearch locally using Docker. Make sure you have Docker installed and running on your machine. Note that this example disables the security plugin for simplicity. In a production environment, you should enable security features.
|
||||
|
||||
```dockerfile
|
||||
docker run -d \\
|
||||
--name opensearch-nosec \\
|
||||
-p 9200:9200 \\
|
||||
-p 9600:9600 \\
|
||||
-e "discovery.type=single-node" \\
|
||||
-e "DISABLE_SECURITY_PLUGIN=true" \\
|
||||
opensearchproject/opensearch:2.12.0
|
||||
```
|
||||
|
||||
```python
|
||||
from haystack import Document
|
||||
from haystack.components.embedders import SentenceTransformersTextEmbedder, SentenceTransformersDocumentEmbedder
|
||||
from haystack_integrations.components.retrievers.opensearch import OpenSearchHybridRetriever
|
||||
from haystack_integrations.document_stores.opensearch import OpenSearchDocumentStore
|
||||
|
||||
## Initialize the document store
|
||||
doc_store = OpenSearchDocumentStore(
|
||||
hosts=["http://localhost:9200"],
|
||||
index="document_store",
|
||||
embedding_dim=384,
|
||||
)
|
||||
|
||||
## Create some sample documents
|
||||
docs = [
|
||||
Document(content="Machine learning is a subset of artificial intelligence."),
|
||||
Document(content="Deep learning is a subset of machine learning."),
|
||||
Document(content="Natural language processing is a field of AI."),
|
||||
Document(content="Reinforcement learning is a type of machine learning."),
|
||||
Document(content="Supervised learning is a type of machine learning."),
|
||||
]
|
||||
|
||||
## Embed the documents and add them to the document store
|
||||
doc_embedder = SentenceTransformersDocumentEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
|
||||
docs = doc_embedder.run(docs)
|
||||
doc_store.write_documents(docs['documents'])
|
||||
|
||||
## Initialize some haystack text embedder, in this case the SentenceTransformersTextEmbedder
|
||||
embedder = SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
|
||||
|
||||
## Initialize the hybrid retriever
|
||||
retriever = OpenSearchHybridRetriever(
|
||||
document_store=doc_store,
|
||||
embedder=embedder,
|
||||
top_k_bm25=3,
|
||||
top_k_embedding=3,
|
||||
join_mode="reciprocal_rank_fusion"
|
||||
)
|
||||
|
||||
## Run the retriever
|
||||
results = retriever.run(query="What is reinforcement learning?", filters_bm25=None, filters_embedding=None)
|
||||
|
||||
>> results['documents']
|
||||
{'documents': [Document(id=..., content: 'Reinforcement learning is a type of machine learning.', score: 1.0),
|
||||
Document(id=..., content: 'Supervised learning is a type of machine learning.', score: 0.9760624679979518),
|
||||
Document(id=..., content: 'Deep learning is a subset of machine learning.', score: 0.4919354838709677),
|
||||
Document(id=..., content: 'Machine learning is a subset of artificial intelligence.', score: 0.4841269841269841)]}
|
||||
```
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
---
|
||||
title: "PgvectorEmbeddingRetriever"
|
||||
id: pgvectorembeddingretriever
|
||||
slug: "/pgvectorembeddingretriever"
|
||||
description: "An embedding-based Retriever compatible with the Pgvector Document Store."
|
||||
---
|
||||
|
||||
# PgvectorEmbeddingRetriever
|
||||
|
||||
An embedding-based Retriever compatible with the Pgvector Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [PgvectorDocumentStore](../../document-stores/pgvectordocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A vector representing the query (a list of floats) |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [Pgvector](/reference/integrations-pgvector) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/pgvector |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `PgvectorEmbeddingRetriever` is an embedding-based Retriever compatible with the `PgvectorDocumentStore`. It compares the query and Document embeddings and fetches the Documents most relevant to the query from the `PgvectorDocumentStore` based on the outcome.
|
||||
|
||||
When using the `PgvectorEmbeddingRetriever` in your Pipeline, make sure it has the query and Document embeddings available. You can do so by adding a Document Embedder to your indexing Pipeline and a Text Embedder to your query Pipeline.
|
||||
|
||||
In addition to the `query_embedding`, the `PgvectorEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
Some relevant parameters that impact the embedding retrieval must be defined when the corresponding `PgvectorDocumentStore` is initialized: these include embedding dimension, vector function, and some others related to the search strategy (exact nearest neighbor or HNSW).
|
||||
|
||||
## Installation
|
||||
|
||||
To quickly set up a PostgreSQL database with pgvector, you can use Docker:
|
||||
|
||||
```shell
|
||||
docker run -d -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=postgres ankane/pgvector
|
||||
```
|
||||
|
||||
For more information on installing pgvector, visit the [pgvector GitHub repository](https://github.com/pgvector/pgvector).
|
||||
|
||||
To use pgvector with Haystack, install the `pgvector-haystack` integration:
|
||||
|
||||
```shell
|
||||
pip install pgvector-haystack
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
This Retriever needs the `PgvectorDocumentStore` and indexed Documents to run.
|
||||
|
||||
```python
|
||||
import os
|
||||
from haystack_integrations.document_stores.pgvector import PgvectorDocumentStore
|
||||
from haystack_integrations.components.retrievers.pgvector import (
|
||||
PgvectorEmbeddingRetriever,
|
||||
)
|
||||
|
||||
os.environ["PG_CONN_STR"] = "postgresql://postgres:postgres@localhost:5432/postgres"
|
||||
|
||||
document_store = PgvectorDocumentStore()
|
||||
retriever = PgvectorEmbeddingRetriever(document_store=document_store)
|
||||
|
||||
## using a fake vector to keep the example simple
|
||||
retriever.run(query_embedding=[0.1] * 768)
|
||||
```
|
||||
|
||||
### In a Pipeline
|
||||
|
||||
```python
|
||||
import os
|
||||
from haystack.document_stores import DuplicatePolicy
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersTextEmbedder,
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
)
|
||||
|
||||
from haystack_integrations.document_stores.pgvector import PgvectorDocumentStore
|
||||
from haystack_integrations.components.retrievers.pgvector import (
|
||||
PgvectorEmbeddingRetriever,
|
||||
)
|
||||
|
||||
os.environ["PG_CONN_STR"] = "postgresql://postgres:postgres@localhost:5432/postgres"
|
||||
|
||||
document_store = PgvectorDocumentStore(
|
||||
embedding_dimension=768,
|
||||
vector_function="cosine_similarity",
|
||||
recreate_table=True,
|
||||
)
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder()
|
||||
documents_with_embeddings = document_embedder.run(documents)
|
||||
|
||||
document_store.write_documents(
|
||||
documents_with_embeddings.get("documents"),
|
||||
policy=DuplicatePolicy.OVERWRITE,
|
||||
)
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder())
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
PgvectorEmbeddingRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
|
||||
result = query_pipeline.run({"text_embedder": {"text": query}})
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
---
|
||||
title: "PgvectorKeywordRetriever"
|
||||
id: pgvectorkeywordretriever
|
||||
slug: "/pgvectorkeywordretriever"
|
||||
description: "This is a keyword-based Retriever that fetches documents matching a query from the Pgvector Document Store."
|
||||
---
|
||||
|
||||
# PgvectorKeywordRetriever
|
||||
|
||||
This is a keyword-based Retriever that fetches documents matching a query from the Pgvector Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. Before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. Before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [PgvectorDocumentStore](../../document-stores/pgvectordocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query`: A string |
|
||||
| **Output variables** | `document`: A list of documents (matching the query) |
|
||||
| **API reference** | [Pgvector](/reference/integrations-pgvector) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/pgvector |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `PgvectorKeywordRetriever` is a keyword-based Retriever compatible with the `PgvectorDocumentStore`.
|
||||
|
||||
The component uses the `ts_rank_cd` function of PostgreSQL to rank the documents.
|
||||
It considers how often the query terms appear in the document, how close together the terms are in the document, and how important is the part of the document where they occur.
|
||||
For more details, see [Postgres documentation](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-RANKING).
|
||||
|
||||
Keep in mind that, unlike similar components such as `ElasticsearchBM25Retriever`, this Retriever does not apply fuzzy search out of the box, so it’s necessary to carefully formulate the query in order to avoid getting zero results.
|
||||
|
||||
In addition to the `query`, the `PgvectorKeywordRetriever` accepts other optional parameters, including `top_k` (the maximum number of documents to retrieve) and `filters` to narrow the search space.
|
||||
|
||||
### Installation
|
||||
|
||||
To quickly set up a PostgreSQL database with pgvector, you can use Docker:
|
||||
|
||||
```shell
|
||||
docker run -d -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=postgres ankane/pgvector
|
||||
```
|
||||
|
||||
For more information on how to install pgvector, visit the [pgvector GitHub repository](https://github.com/pgvector/pgvector).
|
||||
|
||||
Install the `pgvector-haystack` integration:
|
||||
|
||||
```shell
|
||||
pip install pgvector-haystack
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
This Retriever needs the `PgvectorDocumentStore` and indexed documents to run.
|
||||
|
||||
Set an environment variable `PG_CONN_STR` with the connection string to your PostgreSQL database.
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.pgvector import PgvectorDocumentStore
|
||||
from haystack_integrations.components.retrievers.pgvector import (
|
||||
PgvectorKeywordRetriever,
|
||||
)
|
||||
|
||||
document_store = PgvectorDocumentStore()
|
||||
retriever = PgvectorKeywordRetriever(document_store=document_store)
|
||||
|
||||
retriever.run(query="my nice query")
|
||||
```
|
||||
|
||||
### In a RAG pipeline
|
||||
|
||||
The prerequisites necessary for running this code are:
|
||||
|
||||
- Set an environment variable `OPENAI_API_KEY` with your OpenAI API key.
|
||||
- Set an environment variable `PG_CONN_STR` with the connection string to your PostgreSQL database.
|
||||
|
||||
```python
|
||||
from haystack import Document
|
||||
from haystack import Pipeline
|
||||
from haystack.components.builders.answer_builder import AnswerBuilder
|
||||
from haystack.components.builders.prompt_builder import PromptBuilder
|
||||
from haystack.components.generators import OpenAIGenerator
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
|
||||
from haystack_integrations.document_stores.pgvector import PgvectorDocumentStore
|
||||
from haystack_integrations.components.retrievers.pgvector import (
|
||||
PgvectorKeywordRetriever,
|
||||
)
|
||||
|
||||
## Create a RAG query pipeline
|
||||
prompt_template = """
|
||||
Given these documents, answer the question.\nDocuments:
|
||||
{% for doc in documents %}
|
||||
{{ doc.content }}
|
||||
{% endfor %}
|
||||
|
||||
\nQuestion: {{question}}
|
||||
\nAnswer:
|
||||
"""
|
||||
|
||||
document_store = PgvectorDocumentStore(
|
||||
language="english", # this parameter influences text parsing for keyword retrieval
|
||||
recreate_table=True,
|
||||
)
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
## DuplicatePolicy.SKIP param is optional, but useful to run the script multiple times without throwing errors
|
||||
document_store.write_documents(documents=documents, policy=DuplicatePolicy.SKIP)
|
||||
|
||||
retriever = PgvectorKeywordRetriever(document_store=document_store)
|
||||
rag_pipeline = Pipeline()
|
||||
rag_pipeline.add_component(name="retriever", instance=retriever)
|
||||
rag_pipeline.add_component(
|
||||
instance=PromptBuilder(template=prompt_template),
|
||||
name="prompt_builder",
|
||||
)
|
||||
rag_pipeline.add_component(instance=OpenAIGenerator(), name="llm")
|
||||
rag_pipeline.add_component(instance=AnswerBuilder(), name="answer_builder")
|
||||
rag_pipeline.connect("retriever", "prompt_builder.documents")
|
||||
rag_pipeline.connect("prompt_builder", "llm")
|
||||
rag_pipeline.connect("llm.replies", "answer_builder.replies")
|
||||
rag_pipeline.connect("llm.meta", "answer_builder.meta")
|
||||
rag_pipeline.connect("retriever", "answer_builder.documents")
|
||||
|
||||
question = "languages spoken around the world today"
|
||||
result = rag_pipeline.run(
|
||||
{
|
||||
"retriever": {"query": question},
|
||||
"prompt_builder": {"question": question},
|
||||
"answer_builder": {"query": question},
|
||||
},
|
||||
)
|
||||
print(result["answer_builder"])
|
||||
```
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
---
|
||||
title: "PineconeEmbeddingRetriever"
|
||||
id: pineconedenseretriever
|
||||
slug: "/pineconedenseretriever"
|
||||
description: "An embedding-based Retriever compatible with the Pinecone Document Store."
|
||||
---
|
||||
|
||||
# PineconeEmbeddingRetriever
|
||||
|
||||
An embedding-based Retriever compatible with the Pinecone Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [PineconeDocumentStore](../../document-stores/pinecone-document-store.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A vector representing the query (a list of floats) |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [Pinecone](/reference/integrations-pinecone) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/pinecone |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `PineconeEmbeddingRetriever` is an embedding-based Retriever compatible with the `PineconeDocumentStore`. It compares the query and Document embeddings and fetches the Documents most relevant to the query from the `PineconeDocumentStore` based on the outcome.
|
||||
|
||||
When using the `PineconeEmbeddingRetriever` in your NLP system, make sure it has the query and Document embeddings available. You can do so by adding a Document Embedder to your indexing Pipeline and a Text Embedder to your query Pipeline.
|
||||
|
||||
In addition to the `query_embedding`, the `PineconeEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
Some relevant parameters that impact the embedding retrieval must be defined when the corresponding `PineconeDocumentStore` is initialized: these include the `dimension` of the embeddings and the distance `metric` to use.
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
This Retriever needs the `PineconeDocumentStore` and indexed Documents to run.
|
||||
|
||||
```python
|
||||
from haystack_integrations.components.retrievers.pinecone import (
|
||||
PineconeEmbeddingRetriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.pinecone import PineconeDocumentStore
|
||||
|
||||
## Make sure you have the PINECONE_API_KEY environment variable set
|
||||
document_store = PineconeDocumentStore(
|
||||
index="my_index_with_documents",
|
||||
namespace="my_namespace",
|
||||
dimension=768,
|
||||
)
|
||||
|
||||
retriever = PineconeEmbeddingRetriever(document_store=document_store)
|
||||
|
||||
## using an imaginary vector to keep the example simple, example run query:
|
||||
retriever.run(query_embedding=[0.1] * 768)
|
||||
```
|
||||
|
||||
### In a pipeline
|
||||
|
||||
Install the dependencies you’ll need:
|
||||
|
||||
```shell
|
||||
pip install pinecone-haystack
|
||||
pip install sentence-transformers
|
||||
```
|
||||
|
||||
Use this Retriever in a query Pipeline like this:
|
||||
|
||||
```python
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack import Document
|
||||
from haystack import Pipeline
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersTextEmbedder,
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
)
|
||||
from haystack_integrations.components.retrievers.pinecone import (
|
||||
PineconeEmbeddingRetriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.pinecone import PineconeDocumentStore
|
||||
|
||||
## Make sure you have the PINECONE_API_KEY environment variable set
|
||||
document_store = PineconeDocumentStore(
|
||||
index="my_index",
|
||||
namespace="my_namespace",
|
||||
dimension=768,
|
||||
)
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder()
|
||||
documents_with_embeddings = document_embedder.run(documents)
|
||||
|
||||
document_store.write_documents(
|
||||
documents_with_embeddings.get("documents"),
|
||||
policy=DuplicatePolicy.OVERWRITE,
|
||||
)
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder())
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
PineconeEmbeddingRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
|
||||
result = query_pipeline.run({"text_embedder": {"text": query}})
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
|
||||
The example output would be:
|
||||
|
||||
```python
|
||||
Document(id=cfe93bc1c274908801e6670440bf2bbba54fad792770d57421f85ffa2a4fcc94, content: 'There are over 7,000 languages spoken around the world today.', score: 0.87717235, embedding: vector of size 768)
|
||||
```
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
---
|
||||
title: "QdrantEmbeddingRetriever"
|
||||
id: qdrantembeddingretriever
|
||||
slug: "/qdrantembeddingretriever"
|
||||
description: "An embedding-based Retriever compatible with the Qdrant Document Store."
|
||||
---
|
||||
|
||||
# QdrantEmbeddingRetriever
|
||||
|
||||
An embedding-based Retriever compatible with the Qdrant Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1\. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG Pipeline <br /> <br />2. The last component in the semantic search pipeline <br />3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [QdrantDocumentStore](../../document-stores/qdrant-document-store.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A vector representing the query (a list of floats) |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [Qdrant](/reference/integrations-qdrant) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/qdrant |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `QdrantEmbeddingRetriever` is an embedding-based Retriever compatible with the `QdrantDocumentStore`. It compares the query and Document embeddings and fetches the Documents most relevant to the query from the `QdrantDocumentStore` based on the outcome.
|
||||
|
||||
When using the `QdrantEmbeddingRetriever` in your NLP system, make sure it has the query and Document embeddings available. You can add a Document Embedder to your indexing Pipeline and a Text Embedder to your query Pipeline.
|
||||
|
||||
In addition to the `query_embedding`, the `QdrantEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
Some relevant parameters that impact the embedding retrieval must be defined when the corresponding `QdrantDocumentStore` is initialized: these include the embedding dimension (`embedding_dim`), the `similarity` function to use when comparing embeddings and the HNWS configuration (`hnsw_config`).
|
||||
|
||||
### Installation
|
||||
|
||||
To start using Qdrant with Haystack, first install the package with:
|
||||
|
||||
```shell
|
||||
pip install qdrant-haystack
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
#### On its own
|
||||
|
||||
This Retriever needs the `QdrantDocumentStore` and indexed Documents to run.
|
||||
|
||||
```python
|
||||
from haystack_integrations.components.retrievers.qdrant import QdrantEmbeddingRetriever
|
||||
from haystack_integrations.document_stores.qdrant import QdrantDocumentStore
|
||||
|
||||
document_store = QdrantDocumentStore(
|
||||
":memory:",
|
||||
recreate_index=True,
|
||||
return_embedding=True,
|
||||
wait_result_from_api=True,
|
||||
)
|
||||
retriever = QdrantEmbeddingRetriever(document_store=document_store)
|
||||
|
||||
## using a fake vector to keep the example simple
|
||||
retriever.run(query_embedding=[0.1] * 768)
|
||||
```
|
||||
|
||||
#### In a Pipeline
|
||||
|
||||
```python
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack import Document
|
||||
from haystack import Pipeline
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersTextEmbedder,
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
)
|
||||
|
||||
from haystack_integrations.components.retrievers.qdrant import QdrantEmbeddingRetriever
|
||||
from haystack_integrations.document_stores.qdrant import QdrantDocumentStore
|
||||
|
||||
document_store = QdrantDocumentStore(
|
||||
":memory:",
|
||||
recreate_index=True,
|
||||
return_embedding=True,
|
||||
wait_result_from_api=True,
|
||||
)
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder()
|
||||
documents_with_embeddings = document_embedder.run(documents)
|
||||
|
||||
document_store.write_documents(
|
||||
documents_with_embeddings.get("documents"),
|
||||
policy=DuplicatePolicy.OVERWRITE,
|
||||
)
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder())
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
QdrantEmbeddingRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
|
||||
result = query_pipeline.run({"text_embedder": {"text": query}})
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
---
|
||||
title: "QdrantHybridRetriever"
|
||||
id: qdranthybridretriever
|
||||
slug: "/qdranthybridretriever"
|
||||
description: "A Retriever based both on dense and sparse embeddings, compatible with the Qdrant Document Store."
|
||||
---
|
||||
|
||||
# QdrantHybridRetriever
|
||||
|
||||
A Retriever based both on dense and sparse embeddings, compatible with the Qdrant Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1\. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline <br /> <br />2. The last component in a hybrid search pipeline <br /> 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [QdrantDocumentStore](../../document-stores/qdrant-document-store.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A dense vector representing the query (a list of floats) <br /> <br />`query_sparse_embedding`: A [`SparseEmbedding`](../../concepts/data-classes.mdx#sparseembedding) object containing a vectorial representation of the query |
|
||||
| **Output variables** | `document`: A list of documents |
|
||||
| **API reference** | [Qdrant](/reference/integrations-qdrant) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/qdrant |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `QdrantHybridRetriever` is a Retriever based both on dense and sparse embeddings, compatible with the [`QdrantDocumentStore`](../../document-stores/qdrant-document-store.mdx).
|
||||
|
||||
It compares the query and document’s dense and sparse embeddings and fetches the documents most relevant to the query from the `QdrantDocumentStore`, fusing the scores with Reciprocal Rank Fusion.
|
||||
|
||||
:::tip[Hybrid Retrieval Pipeline]
|
||||
|
||||
If you want additional customization for merging or fusing results, consider creating a hybrid retrieval pipeline with [`DocumentJoiner`](../joiners/documentjoiner.mdx).
|
||||
|
||||
You can check out our hybrid retrieval pipeline [tutorial](https://haystack.deepset.ai/tutorials/33_hybrid_retrieval) for detailed steps.
|
||||
:::
|
||||
|
||||
When using the `QdrantHybridRetriever`, make sure it has the query and document with dense and sparse embeddings available. You can do so by:
|
||||
|
||||
- Adding a (dense) document Embedder and a sparse document Embedder to your indexing pipeline,
|
||||
- Adding a (dense) text Embedder and a sparse text Embedder to your query pipeline.
|
||||
|
||||
In addition to `query_embedding` and `query_sparse_embedding`, the `QdrantHybridRetriever` accepts other optional parameters, including `top_k` (the maximum number of documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
:::note[Sparse Embedding Support]
|
||||
|
||||
To use Sparse Embedding support, you need to initialize the `QdrantDocumentStore` with `use_sparse_embeddings=True`, which is `False` by default.
|
||||
|
||||
If you want to use Document Store or collection previously created with this feature disabled, you must migrate the existing data. You can do this by taking advantage of the `migrate_to_sparse_embeddings_support` utility function.
|
||||
:::
|
||||
|
||||
### Installation
|
||||
|
||||
To start using Qdrant with Haystack, first install the package with:
|
||||
|
||||
```shell
|
||||
pip install qdrant-haystack
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
```python
|
||||
from haystack_integrations.components.retrievers.qdrant import QdrantHybridRetriever
|
||||
from haystack_integrations.document_stores.qdrant import QdrantDocumentStore
|
||||
from haystack.dataclasses import Document, SparseEmbedding
|
||||
|
||||
document_store = QdrantDocumentStore(
|
||||
":memory:",
|
||||
use_sparse_embeddings=True,
|
||||
recreate_index=True,
|
||||
return_embedding=True,
|
||||
wait_result_from_api=True,
|
||||
)
|
||||
|
||||
doc = Document(
|
||||
content="test",
|
||||
embedding=[0.5] * 768,
|
||||
sparse_embedding=SparseEmbedding(indices=[0, 3, 5], values=[0.1, 0.5, 0.12]),
|
||||
)
|
||||
|
||||
document_store.write_documents([doc])
|
||||
|
||||
retriever = QdrantHybridRetriever(document_store=document_store)
|
||||
embedding = [0.1] * 768
|
||||
sparse_embedding = SparseEmbedding(indices=[0, 1, 2, 3], values=[0.1, 0.8, 0.05, 0.33])
|
||||
retriever.run(query_embedding=embedding, query_sparse_embedding=sparse_embedding)
|
||||
```
|
||||
|
||||
### In a pipeline
|
||||
|
||||
Currently, you can compute sparse embeddings using Fastembed Sparse Embedders.
|
||||
First, install the package with:
|
||||
|
||||
```shell
|
||||
pip install fastembed-haystack
|
||||
```
|
||||
|
||||
In the example below, we are using Fastembed Embedders to compute dense embeddings as well.
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.components.writers import DocumentWriter
|
||||
from haystack_integrations.components.retrievers.qdrant import QdrantHybridRetriever
|
||||
from haystack_integrations.document_stores.qdrant import QdrantDocumentStore
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack_integrations.components.embedders.fastembed import (
|
||||
FastembedTextEmbedder,
|
||||
FastembedDocumentEmbedder,
|
||||
FastembedSparseTextEmbedder,
|
||||
FastembedSparseDocumentEmbedder,
|
||||
)
|
||||
|
||||
document_store = QdrantDocumentStore(
|
||||
":memory:",
|
||||
recreate_index=True,
|
||||
use_sparse_embeddings=True,
|
||||
embedding_dim=384,
|
||||
)
|
||||
|
||||
documents = [
|
||||
Document(content="My name is Wolfgang and I live in Berlin"),
|
||||
Document(content="I saw a black horse running"),
|
||||
Document(content="Germany has many big cities"),
|
||||
Document(content="fastembed is supported by and maintained by Qdrant."),
|
||||
]
|
||||
|
||||
indexing = Pipeline()
|
||||
indexing.add_component(
|
||||
"sparse_doc_embedder",
|
||||
FastembedSparseDocumentEmbedder(model="prithvida/Splade_PP_en_v1"),
|
||||
)
|
||||
indexing.add_component(
|
||||
"dense_doc_embedder",
|
||||
FastembedDocumentEmbedder(model="BAAI/bge-small-en-v1.5"),
|
||||
)
|
||||
indexing.add_component(
|
||||
"writer",
|
||||
DocumentWriter(document_store=document_store, policy=DuplicatePolicy.OVERWRITE),
|
||||
)
|
||||
indexing.connect("sparse_doc_embedder", "dense_doc_embedder")
|
||||
indexing.connect("dense_doc_embedder", "writer")
|
||||
|
||||
indexing.run({"sparse_doc_embedder": {"documents": documents}})
|
||||
|
||||
querying = Pipeline()
|
||||
querying.add_component(
|
||||
"sparse_text_embedder",
|
||||
FastembedSparseTextEmbedder(model="prithvida/Splade_PP_en_v1"),
|
||||
)
|
||||
querying.add_component(
|
||||
"dense_text_embedder",
|
||||
FastembedTextEmbedder(
|
||||
model="BAAI/bge-small-en-v1.5",
|
||||
prefix="Represent this sentence for searching relevant passages: ",
|
||||
),
|
||||
)
|
||||
querying.add_component(
|
||||
"retriever",
|
||||
QdrantHybridRetriever(document_store=document_store),
|
||||
)
|
||||
|
||||
querying.connect(
|
||||
"sparse_text_embedder.sparse_embedding",
|
||||
"retriever.query_sparse_embedding",
|
||||
)
|
||||
querying.connect("dense_text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
question = "Who supports fastembed?"
|
||||
|
||||
results = query_mix.run(
|
||||
{
|
||||
"dense_text_embedder": {"text": question},
|
||||
"sparse_text_embedder": {"text": question},
|
||||
},
|
||||
)
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
|
||||
## Document(id=...,
|
||||
## content: 'fastembed is supported by and maintained by Qdrant.',
|
||||
## score: 1.0)
|
||||
```
|
||||
|
||||
## Additional References
|
||||
|
||||
:notebook: Tutorial: [Creating a Hybrid Retrieval Pipeline](https://haystack.deepset.ai/tutorials/33_hybrid_retrieval)
|
||||
|
||||
🧑🍳 Cookbook: [Sparse Embedding Retrieval with Qdrant and FastEmbed](https://haystack.deepset.ai/cookbook/sparse_embedding_retrieval)
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
---
|
||||
title: "QdrantSparseEmbeddingRetriever"
|
||||
id: qdrantsparseembeddingretriever
|
||||
slug: "/qdrantsparseembeddingretriever"
|
||||
description: "A Retriever based on sparse embeddings, compatible with the Qdrant Document Store."
|
||||
---
|
||||
|
||||
# QdrantSparseEmbeddingRetriever
|
||||
|
||||
A Retriever based on sparse embeddings, compatible with the Qdrant Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1\. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline <br /> <br />2. The last component in the semantic search pipeline <br /> 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [QdrantDocumentStore](../../document-stores/qdrant-document-store.mdx) |
|
||||
| **Mandatory run variables** | `query_sparse_embedding`: A [`SparseEmbedding`](../../concepts/data-classes.mdx#sparseembedding) object containing a vectorial representation of the query |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [Qdrant](/reference/integrations-qdrant) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/qdrant |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `QdrantSparseEmbeddingRetriever` is a Retriever based on sparse embeddings, compatible with the [`QdrantDocumentStore`](../../document-stores/qdrant-document-store.mdx).
|
||||
|
||||
It compares the query and document sparse embeddings and, based on the outcome, fetches the documents most relevant to the query from the `QdrantDocumentStore`.
|
||||
|
||||
When using the `QdrantSparseEmbeddingRetriever`, make sure it has the query and document sparse embeddings available. You can do so by adding a sparse document Embedder to your indexing pipeline and a sparse text Embedder to your query pipeline.
|
||||
|
||||
In addition to the `query_sparse_embedding`, the `QdrantSparseEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
:::note[Sparse Embedding Support]
|
||||
|
||||
To use Sparse Embedding support, you need to initialize the `QdrantDocumentStore` with `use_sparse_embeddings=True`, which is `False` by default.
|
||||
|
||||
If you want to use Document Store or collection previously created with this feature disabled, you must migrate the existing data. You can do this by taking advantage of the `migrate_to_sparse_embeddings_support` utility function.
|
||||
:::
|
||||
|
||||
### Installation
|
||||
|
||||
To start using Qdrant with Haystack, first install the package with:
|
||||
|
||||
```shell
|
||||
pip install qdrant-haystack
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
This Retriever needs the `QdrantDocumentStore` and indexed documents to run.
|
||||
|
||||
```python
|
||||
from haystack_integrations.components.retrievers.qdrant import (
|
||||
QdrantSparseEmbeddingRetriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.qdrant import QdrantDocumentStore
|
||||
from haystack.dataclasses import Document, SparseEmbedding
|
||||
|
||||
document_store = QdrantDocumentStore(
|
||||
":memory:",
|
||||
use_sparse_embeddings=True,
|
||||
recreate_index=True,
|
||||
return_embedding=True,
|
||||
)
|
||||
|
||||
doc = Document(
|
||||
content="test",
|
||||
sparse_embedding=SparseEmbedding(indices=[0, 3, 5], values=[0.1, 0.5, 0.12]),
|
||||
)
|
||||
document_store.write_documents([doc])
|
||||
|
||||
retriever = QdrantSparseEmbeddingRetriever(document_store=document_store)
|
||||
sparse_embedding = SparseEmbedding(indices=[0, 1, 2, 3], values=[0.1, 0.8, 0.05, 0.33])
|
||||
retriever.run(query_sparse_embedding=sparse_embedding)
|
||||
```
|
||||
|
||||
### In a pipeline
|
||||
|
||||
In Haystack, you can compute sparse embeddings using Fastembed Embedders.
|
||||
|
||||
First, install the package with:
|
||||
|
||||
```shell
|
||||
pip install fastembed-haystack
|
||||
```
|
||||
|
||||
Then, try out this pipeline:
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.components.writers import DocumentWriter
|
||||
from haystack_integrations.components.retrievers.qdrant import (
|
||||
QdrantSparseEmbeddingRetriever,
|
||||
)
|
||||
from haystack_integrations.document_stores.qdrant import QdrantDocumentStore
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack_integrations.components.embedders.fastembed import (
|
||||
FastembedDocumentEmbedder,
|
||||
FastembedTextEmbedder,
|
||||
)
|
||||
|
||||
document_store = QdrantDocumentStore(
|
||||
":memory:",
|
||||
recreate_index=True,
|
||||
use_sparse_embeddings=True,
|
||||
)
|
||||
|
||||
documents = [
|
||||
Document(content="My name is Wolfgang and I live in Berlin"),
|
||||
Document(content="I saw a black horse running"),
|
||||
Document(content="Germany has many big cities"),
|
||||
Document(content="fastembed is supported by and maintained by Qdrant."),
|
||||
]
|
||||
|
||||
sparse_document_embedder = FastembedSparseDocumentEmbedder()
|
||||
writer = DocumentWriter(document_store=document_store, policy=DuplicatePolicy.OVERWRITE)
|
||||
|
||||
indexing_pipeline = Pipeline()
|
||||
indexing_pipeline.add_component("sparse_document_embedder", sparse_document_embedder)
|
||||
indexing_pipeline.add_component("writer", writer)
|
||||
indexing_pipeline.connect("sparse_document_embedder", "writer")
|
||||
|
||||
indexing_pipeline.run({"sparse_document_embedder": {"documents": documents}})
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component("sparse_text_embedder", FastembedSparseTextEmbedder())
|
||||
query_pipeline.add_component(
|
||||
"sparse_retriever",
|
||||
QdrantSparseEmbeddingRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect(
|
||||
"sparse_text_embedder.sparse_embedding",
|
||||
"sparse_retriever.query_sparse_embedding",
|
||||
)
|
||||
|
||||
query = "Who supports fastembed?"
|
||||
|
||||
result = query_pipeline.run({"sparse_text_embedder": {"text": query}})
|
||||
|
||||
print(result["sparse_retriever"]["documents"][0]) # noqa: T201
|
||||
|
||||
## Document(id=...,
|
||||
## content: 'fastembed is supported by and maintained by Qdrant.',
|
||||
## score: 0.758..)
|
||||
```
|
||||
|
||||
## Additional References
|
||||
|
||||
🧑🍳 Cookbook: [Sparse Embedding Retrieval with Qdrant and FastEmbed](https://haystack.deepset.ai/cookbook/sparse_embedding_retrieval)
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
---
|
||||
title: "SentenceWindowRetriever"
|
||||
id: sentencewindowretrieval
|
||||
slug: "/sentencewindowretrieval"
|
||||
description: "Use this component to retrieve neighboring sentences around relevant sentences to get the full context."
|
||||
---
|
||||
|
||||
# SentenceWindowRetriever
|
||||
|
||||
Use this component to retrieve neighboring sentences around relevant sentences to get the full context.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | Used after the main Retriever component, like the `InMemoryEmbeddingRetriever` or any other Retriever. |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a Document Store |
|
||||
| **Mandatory run variables** | `retrieved_documents`: A list of already retrieved documents for which you want to get a context window |
|
||||
| **Output variables** | `context_windows`: A list of strings <br /> <br />`context_documents`: A list of documents ordered by `split_idx_start` |
|
||||
| **API reference** | [Retrievers](/reference/retrievers-api) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack/blob/main/haystack/components/retrievers/sentence_window_retriever.py |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The "sentence window" is a retrieval technique that allows for the retrieval of the context around relevant sentences.
|
||||
|
||||
During indexing, documents are broken into smaller chunks or sentences and indexed. During retrieval, the sentences most relevant to a given query, based on a certain similarity metric, are retrieved.
|
||||
|
||||
Once we have the relevant sentences, we can retrieve neighboring sentences to provide full context. The number of neighboring sentences to retrieve is defined by a fixed number of sentences before and after the relevant sentence.
|
||||
|
||||
This component is meant to be used with other Retrievers, such as the `InMemoryEmbeddingRetriever`. These Retrievers find relevant sentences by comparing a query against indexed sentences using a similarity metric. Then, the `SentenceWindowRetriever` component retrieves neighboring sentences around the relevant ones by leveraging metadata stored in the `Document` object.
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
```python
|
||||
splitter = DocumentSplitter(split_length=10, split_overlap=5, split_by="word")
|
||||
text = (
|
||||
"This is a text with some words. There is a second sentence. And there is also a third sentence. "
|
||||
"It also contains a fourth sentence. And a fifth sentence. And a sixth sentence. And a seventh sentence"
|
||||
)
|
||||
doc = Document(content=text)
|
||||
|
||||
docs = splitter.run([doc])
|
||||
doc_store = InMemoryDocumentStore()
|
||||
doc_store.write_documents(docs["documents"])
|
||||
|
||||
retriever = SentenceWindowRetriever(document_store=doc_store, window_size=3)
|
||||
```
|
||||
|
||||
### In a Pipeline
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
|
||||
from haystack.components.retrievers import SentenceWindowRetriever
|
||||
from haystack.components.preprocessors import DocumentSplitter
|
||||
from haystack.document_stores.in_memory import InMemoryDocumentStore
|
||||
|
||||
splitter = DocumentSplitter(split_length=10, split_overlap=5, split_by="word")
|
||||
text = (
|
||||
"This is a text with some words. There is a second sentence. And there is also a third sentence. "
|
||||
"It also contains a fourth sentence. And a fifth sentence. And a sixth sentence. And a seventh sentence"
|
||||
)
|
||||
doc = Document(content=text)
|
||||
docs = splitter.run([doc])
|
||||
doc_store = InMemoryDocumentStore()
|
||||
doc_store.write_documents(docs["documents"])
|
||||
|
||||
rag = Pipeline()
|
||||
rag.add_component("bm25_retriever", InMemoryBM25Retriever(doc_store, top_k=1))
|
||||
rag.add_component(
|
||||
"sentence_window_retriever",
|
||||
SentenceWindowRetriever(document_store=doc_store, window_size=3),
|
||||
)
|
||||
rag.connect("bm25_retriever", "sentence_window_retriever")
|
||||
|
||||
rag.run({"bm25_retriever": {"query": "third"}})
|
||||
```
|
||||
|
||||
## Additional References
|
||||
|
||||
:notebook: Tutorial: [Retrieving a Context Window Around a Sentence](https://haystack.deepset.ai/tutorials/42_sentence_window_retriever)
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
---
|
||||
title: "SnowflakeTableRetriever"
|
||||
id: snowflaketableretriever
|
||||
slug: "/snowflaketableretriever"
|
||||
description: "Connects to a Snowflake database to execute an SQL query."
|
||||
---
|
||||
|
||||
# SnowflakeTableRetriever
|
||||
|
||||
Connects to a Snowflake database to execute an SQL query.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | Before a [`PromptBuilder`](../builders/promptbuilder.mdx) |
|
||||
| **Mandatory init variables** | `user`: User's login <br /> <br />`account`: Snowflake account identifier <br /> <br />`api_key`: Snowflake account password. Can be set with `SNOWFLAKE_API_KEY` env var |
|
||||
| **Mandatory run variables** | `query`: An SQL query to execute |
|
||||
| **Output variables** | `dataframe`: The resulting Pandas dataframe version of the table |
|
||||
| **API reference** | [Snowflake](/reference/integrations-snowflake) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/snowflake |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `SnowflakeTableRetriever` connects to a Snowflake database and retrieves data using an SQL query. It then returns a Pandas dataframe and a Markdown version of the table:
|
||||
|
||||
To start using the integration, install it with:
|
||||
|
||||
```bash
|
||||
pip install snowflake-haystack
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### On its own
|
||||
|
||||
```python
|
||||
from haystack_integrations.components.retrievers.snowflake import SnowflakeTableRetriever
|
||||
|
||||
snowflake = SnowflakeRetriever(
|
||||
user="<ACCOUNT-USER>",
|
||||
account="<ACCOUNT-IDENTIFIER>",
|
||||
api_key=Secret.from_env_var("SNOWFLAKE_API_KEY"),
|
||||
warehouse="<WAREHOUSE-NAME>",
|
||||
)
|
||||
|
||||
snowflake.run(query="""select * from table limit 10;"""")
|
||||
```
|
||||
|
||||
### In a pipeline
|
||||
|
||||
In the following pipeline example, the `PromptBuilder` is using the table received from the `SnowflakeTableRetriever` to create a prompt template and pass it on to an LLM:
|
||||
|
||||
```python
|
||||
from haystack import Pipeline
|
||||
from haystack.utils import Secret
|
||||
from haystack.components.builders import PromptBuilder
|
||||
from haystack.components.generators import OpenAIGenerator
|
||||
from haystack_integrations.components.retrievers.snowflake import (
|
||||
SnowflakeTableRetriever,
|
||||
)
|
||||
|
||||
executor = SnowflakeTableRetriever(
|
||||
user="<ACCOUNT-USER>",
|
||||
account="<ACCOUNT-IDENTIFIER>",
|
||||
api_key=Secret.from_env_var("SNOWFLAKE_API_KEY"),
|
||||
warehouse="<WAREHOUSE-NAME>",
|
||||
)
|
||||
|
||||
pipeline = Pipeline()
|
||||
pipeline.add_component(
|
||||
"builder",
|
||||
PromptBuilder(template="Describe this table: {{ table }}"),
|
||||
)
|
||||
pipeline.add_component("snowflake", executor)
|
||||
pipeline.add_component("llm", OpenAIGenerator(model="gpt-4o"))
|
||||
|
||||
pipeline.connect("snowflake.table", "builder.table")
|
||||
pipeline.connect("builder", "llm")
|
||||
|
||||
pipeline.run(data={"query": "select employee, salary from table limit 10;"})
|
||||
```
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
---
|
||||
title: "ValkeyEmbeddingRetriever"
|
||||
id: valkeyembeddingretriever
|
||||
slug: "/valkeyembeddingretriever"
|
||||
description: "This is an embedding Retriever compatible with the Valkey Document Store."
|
||||
---
|
||||
|
||||
# ValkeyEmbeddingRetriever
|
||||
|
||||
This is an embedding Retriever compatible with the Valkey Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`ChatPromptBuilder`](../builders/chatpromptbuilder.mdx) or [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in a semantic search pipeline 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [ValkeyDocumentStore](../../document-stores/valkeydocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A list of floats |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [Valkey](/reference/integrations-valkey) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/valkey |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `ValkeyEmbeddingRetriever` is an embedding-based Retriever compatible with the [`ValkeyDocumentStore`](../../document-stores/valkeydocumentstore.mdx). It compares the query and Document embeddings and fetches the Documents most relevant to the query from the `ValkeyDocumentStore` based on vector similarity.
|
||||
|
||||
### Parameters
|
||||
|
||||
When using the `ValkeyEmbeddingRetriever` in your system, ensure the query and Document [embeddings](../embedders.mdx) are available. You can do so by adding a Document embedder to your indexing pipeline and a text embedder to your query pipeline.
|
||||
|
||||
In addition to the `query_embedding`, the `ValkeyEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
## Usage
|
||||
|
||||
### Installation
|
||||
|
||||
To start using Valkey with Haystack, install the package with:
|
||||
|
||||
```shell
|
||||
pip install valkey-haystack
|
||||
```
|
||||
|
||||
### On its own
|
||||
|
||||
This Retriever needs an instance of `ValkeyDocumentStore` and indexed Documents to run.
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.valkey import ValkeyDocumentStore
|
||||
from haystack_integrations.components.retrievers.valkey import ValkeyEmbeddingRetriever
|
||||
|
||||
document_store = ValkeyDocumentStore(
|
||||
nodes_list=[("localhost", 6379)],
|
||||
index_name="my_documents",
|
||||
embedding_dim=768,
|
||||
distance_metric="cosine",
|
||||
)
|
||||
|
||||
retriever = ValkeyEmbeddingRetriever(document_store=document_store)
|
||||
|
||||
# Using a fake vector to keep the example simple
|
||||
retriever.run(query_embedding=[0.1] * 768)
|
||||
```
|
||||
|
||||
### In a Pipeline
|
||||
|
||||
```python
|
||||
from haystack import Document, Pipeline
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
SentenceTransformersTextEmbedder,
|
||||
)
|
||||
from haystack.components.writers import DocumentWriter
|
||||
from haystack_integrations.document_stores.valkey import ValkeyDocumentStore
|
||||
from haystack_integrations.components.retrievers.valkey import ValkeyEmbeddingRetriever
|
||||
|
||||
document_store = ValkeyDocumentStore(
|
||||
nodes_list=[("localhost", 6379)],
|
||||
index_name="my_documents",
|
||||
embedding_dim=768,
|
||||
distance_metric="cosine",
|
||||
)
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
indexing = Pipeline()
|
||||
indexing.add_component("embedder", SentenceTransformersDocumentEmbedder())
|
||||
indexing.add_component("writer", DocumentWriter(document_store))
|
||||
indexing.connect("embedder.documents", "writer.documents")
|
||||
indexing.run({"embedder": {"documents": documents}})
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder())
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
ValkeyEmbeddingRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
result = query_pipeline.run({"text_embedder": {"text": query}})
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
|
||||
For a full RAG example with `ValkeyEmbeddingRetriever`, see the [ValkeyDocumentStore](../../document-stores/valkeydocumentstore.mdx#using-valkey-in-a-rag-pipeline) documentation.
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
---
|
||||
title: "WeaviateBM25Retriever"
|
||||
id: weaviatebm25retriever
|
||||
slug: "/weaviatebm25retriever"
|
||||
description: "This is a keyword-based Retriever that fetches Documents matching a query from the Weaviate Document Store."
|
||||
---
|
||||
|
||||
# WeaviateBM25Retriever
|
||||
|
||||
This is a keyword-based Retriever that fetches Documents matching a query from the Weaviate Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. Before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. Before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [WeaviateDocumentStore](../../document-stores/weaviatedocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query`: A string |
|
||||
| **Output variables** | `documents`: A list of documents (matching the query) |
|
||||
| **API reference** | [Weaviate](/reference/integrations-weaviate) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/weaviate |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
`WeaviateBM25Retriever` is a keyword-based Retriever that fetches Documents matching a query from [`WeaviateDocumentStore`](../../document-stores/weaviatedocumentstore.mdx). It determines the similarity between Documents and the query based on the BM25 algorithm, which computes a weighted word overlap between the
|
||||
two strings.
|
||||
|
||||
Since the `WeaviateBM25Retriever` matches strings based on word overlap, it’s often used to find exact matches to names of persons or products, IDs, or well-defined error messages. The BM25 algorithm is very lightweight and simple. Beating it with more complex embedding-based approaches on out-of-domain data can be hard.
|
||||
|
||||
If you want a semantic match between a query and documents, use the [`WeaviateEmbeddingRetriever`](weaviateembeddingretriever.mdx), which uses vectors created by embedding models to retrieve relevant information.
|
||||
|
||||
### Parameters
|
||||
|
||||
In addition to the `query`, the `WeaviateBM25Retriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
### Usage
|
||||
|
||||
### Installation
|
||||
|
||||
To start using Weaviate with Haystack, install the package with:
|
||||
|
||||
```shell
|
||||
pip install weaviate-haystack
|
||||
```
|
||||
|
||||
#### On its own
|
||||
|
||||
This Retriever needs an instance of `WeaviateDocumentStore` and indexed Documents to run.
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.weaviate.document_store import (
|
||||
WeaviateDocumentStore,
|
||||
)
|
||||
from haystack_integrations.components.retrievers.weaviate import WeaviateBM25Retriever
|
||||
|
||||
document_store = WeaviateDocumentStore(url="http://localhost:8080")
|
||||
|
||||
retriever = WeaviateBM25Retriever(document_store=document_store)
|
||||
|
||||
retriever.run(query="How to make a pizza", top_k=3)
|
||||
```
|
||||
|
||||
#### In a Pipeline
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.weaviate.document_store import (
|
||||
WeaviateDocumentStore,
|
||||
)
|
||||
from haystack_integrations.components.retrievers.weaviate import (
|
||||
WeaviateBM25Retriever,
|
||||
)
|
||||
|
||||
from haystack import Document
|
||||
from haystack import Pipeline
|
||||
from haystack.components.builders.answer_builder import AnswerBuilder
|
||||
from haystack.components.builders.prompt_builder import PromptBuilder
|
||||
from haystack.components.generators import OpenAIGenerator
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
|
||||
## Create a RAG query pipeline
|
||||
prompt_template = """
|
||||
Given these documents, answer the question.\nDocuments:
|
||||
{% for doc in documents %}
|
||||
{{ doc.content }}
|
||||
{% endfor %}
|
||||
|
||||
\nQuestion: {{question}}
|
||||
\nAnswer:
|
||||
"""
|
||||
|
||||
document_store = WeaviateDocumentStore(url="http://localhost:8080")
|
||||
|
||||
## Add Documents
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
## DuplicatePolicy.SKIP param is optional, but useful to run the script multiple times without throwing errors
|
||||
document_store.write_documents(documents=documents, policy=DuplicatePolicy.SKIP)
|
||||
|
||||
rag_pipeline = Pipeline()
|
||||
rag_pipeline.add_component(
|
||||
name="retriever",
|
||||
instance=WeaviateBM25Retriever(document_store=document_store),
|
||||
)
|
||||
rag_pipeline.add_component(
|
||||
instance=PromptBuilder(template=prompt_template),
|
||||
name="prompt_builder",
|
||||
)
|
||||
rag_pipeline.add_component(instance=OpenAIGenerator(), name="llm")
|
||||
rag_pipeline.add_component(instance=AnswerBuilder(), name="answer_builder")
|
||||
rag_pipeline.connect("retriever", "prompt_builder.documents")
|
||||
rag_pipeline.connect("prompt_builder", "llm")
|
||||
rag_pipeline.connect("llm.replies", "answer_builder.replies")
|
||||
rag_pipeline.connect("llm.metadata", "answer_builder.metadata")
|
||||
rag_pipeline.connect("retriever", "answer_builder.documents")
|
||||
|
||||
question = "How many languages are spoken around the world today?"
|
||||
result = rag_pipeline.run(
|
||||
{
|
||||
"retriever": {"query": question},
|
||||
"prompt_builder": {"question": question},
|
||||
"answer_builder": {"query": question},
|
||||
},
|
||||
)
|
||||
print(result["answer_builder"]["answers"][0])
|
||||
```
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
---
|
||||
title: "WeaviateEmbeddingRetriever"
|
||||
id: weaviateembeddingretriever
|
||||
slug: "/weaviateembeddingretriever"
|
||||
description: "This is an embedding Retriever compatible with the Weaviate Document Store."
|
||||
---
|
||||
|
||||
# WeaviateEmbeddingRetriever
|
||||
|
||||
This is an embedding Retriever compatible with the Weaviate Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in the semantic search pipeline 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [WeaviateDocumentStore](../../document-stores/weaviatedocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query_embedding`: A list of floats |
|
||||
| **Output variables** | `documents`: A list of documents |
|
||||
| **API reference** | [Weaviate](/reference/integrations-weaviate) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/weaviate |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `WeaviateEmbeddingRetriever` is an embedding-based Retriever compatible with the [`WeaviateDocumentStore`](../../document-stores/weaviatedocumentstore.mdx). It compares the query and Document embeddings and fetches the Documents most relevant to the query from the `WeaviateDocumentStore` based on the outcome.
|
||||
|
||||
### Parameters
|
||||
|
||||
When using the `WeaviateEmbeddingRetriever` in your NLP system, ensure the query and Document [embeddings](../embedders.mdx) are available. You can do so by adding a Document Embedder to your indexing Pipeline and a Text Embedder to your query Pipeline.
|
||||
|
||||
In addition to the `query_embedding`, the `WeaviateEmbeddingRetriever` accepts other optional parameters, including `top_k` (the maximum number of Documents to retrieve) and `filters` to narrow down the search space.
|
||||
|
||||
You can also specify `distance`, the maximum allowed distance between embeddings, and `certainty`, the normalized distance between the result items and the search embedding. The behavior of `distance` depends on the Collection’s distance metric used. See the [official Weaviate documentation](https://weaviate.io/developers/weaviate/api/graphql/search-operators#variables) for more information.
|
||||
|
||||
The embedding similarity function depends on the vectorizer used in the `WeaviateDocumentStore` collection. Check out the [official Weaviate documentation](https://weaviate.io/developers/weaviate/modules/retriever-vectorizer-modules) to see all the supported vectorizers.
|
||||
|
||||
## Usage
|
||||
|
||||
### Installation
|
||||
|
||||
To start using Weaviate with Haystack, install the package with:
|
||||
|
||||
```shell
|
||||
pip install weaviate-haystack
|
||||
```
|
||||
|
||||
### On its own
|
||||
|
||||
This Retriever needs an instance of `WeaviateDocumentStore` and indexed Documents to run.
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.weaviate.document_store import (
|
||||
WeaviateDocumentStore,
|
||||
)
|
||||
from haystack_integrations.components.retrievers.weaviate import (
|
||||
WeaviateEmbeddingRetriever,
|
||||
)
|
||||
|
||||
document_store = WeaviateDocumentStore(url="http://localhost:8080")
|
||||
|
||||
retriever = WeaviateEmbeddingRetriever(document_store=document_store)
|
||||
|
||||
## using a fake vector to keep the example simple
|
||||
retriever.run(query_embedding=[0.1] * 768)
|
||||
```
|
||||
|
||||
### In a Pipeline
|
||||
|
||||
```python
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack import Document
|
||||
from haystack import Pipeline
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersTextEmbedder,
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
)
|
||||
|
||||
from haystack_integrations.document_stores.weaviate.document_store import (
|
||||
WeaviateDocumentStore,
|
||||
)
|
||||
from haystack_integrations.components.retrievers.weaviate import (
|
||||
WeaviateEmbeddingRetriever,
|
||||
)
|
||||
|
||||
document_store = WeaviateDocumentStore(url="http://localhost:8080")
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder()
|
||||
documents_with_embeddings = document_embedder.run(documents)
|
||||
|
||||
document_store.write_documents(
|
||||
documents_with_embeddings.get("documents"),
|
||||
policy=DuplicatePolicy.OVERWRITE,
|
||||
)
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder())
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
WeaviateEmbeddingRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
|
||||
result = query_pipeline.run({"text_embedder": {"text": query}})
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
---
|
||||
title: "WeaviateHybridRetriever"
|
||||
id: weaviatehybridretriever
|
||||
slug: "/weaviatehybridretriever"
|
||||
description: "A Retriever that combines BM25 keyword search and vector similarity to fetch documents from the Weaviate Document Store."
|
||||
---
|
||||
|
||||
# WeaviateHybridRetriever
|
||||
|
||||
A Retriever that combines BM25 keyword search and vector similarity to fetch documents from the Weaviate Document Store.
|
||||
|
||||
<div className="key-value-table">
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Most common position in a pipeline** | 1. After a Text Embedder and before a [`PromptBuilder`](../builders/promptbuilder.mdx) in a RAG pipeline 2. The last component in a hybrid search pipeline 3. After a Text Embedder and before an [`ExtractiveReader`](../readers/extractivereader.mdx) in an extractive QA pipeline |
|
||||
| **Mandatory init variables** | `document_store`: An instance of a [WeaviateDocumentStore](../../document-stores/weaviatedocumentstore.mdx) |
|
||||
| **Mandatory run variables** | `query`: A string <br /> <br />`query_embedding`: A list of floats |
|
||||
| **Output variables** | `documents`: A list of documents (matching the query) |
|
||||
| **API reference** | [Weaviate](/reference/integrations-weaviate) |
|
||||
| **GitHub link** | https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/weaviate |
|
||||
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
The `WeaviateHybridRetriever` combines keyword-based (BM25) and vector similarity search to fetch documents from the [`WeaviateDocumentStore`](../../document-stores/weaviatedocumentstore.mdx). Weaviate executes both searches in parallel and fuses the results into a single ranked list. The Retriever requires both a text query and its corresponding embedding.
|
||||
|
||||
The `alpha` parameter controls how much each search method contributes to the final results:
|
||||
|
||||
- `alpha = 0.0`: only keyword (BM25) scoring is used,
|
||||
- `alpha = 1.0`: only vector similarity scoring is used,
|
||||
- Values in between blend the two; higher values favor the vector score, lower values favor BM25.
|
||||
|
||||
If you don't specify `alpha`, the Weaviate server default is used.
|
||||
|
||||
You can also use the `max_vector_distance` parameter to set a threshold for the vector component. Candidates with a distance larger than this threshold are excluded from the vector portion before blending.
|
||||
|
||||
See the [official Weaviate documentation](https://weaviate.io/developers/weaviate/search/hybrid#parameters) for more details on hybrid search parameters.
|
||||
|
||||
### Parameters
|
||||
|
||||
When using the `WeaviateHybridRetriever`, you need to provide both the query text and its embedding. You can do this by adding a Text Embedder to your query pipeline.
|
||||
|
||||
In addition to `query` and `query_embedding`, the retriever accepts optional parameters including `top_k` (the maximum number of documents to return), `filters` to narrow down the search space, and `filter_policy` to determine how filters are applied.
|
||||
|
||||
## Usage
|
||||
|
||||
### Installation
|
||||
|
||||
To start using Weaviate with Haystack, install the package with:
|
||||
|
||||
```shell
|
||||
pip install weaviate-haystack
|
||||
```
|
||||
|
||||
### On its own
|
||||
|
||||
This Retriever needs an instance of `WeaviateDocumentStore` and indexed documents to run.
|
||||
|
||||
```python
|
||||
from haystack_integrations.document_stores.weaviate.document_store import (
|
||||
WeaviateDocumentStore,
|
||||
)
|
||||
from haystack_integrations.components.retrievers.weaviate import WeaviateHybridRetriever
|
||||
|
||||
document_store = WeaviateDocumentStore(url="http://localhost:8080")
|
||||
|
||||
retriever = WeaviateHybridRetriever(document_store=document_store)
|
||||
|
||||
## using a fake vector to keep the example simple
|
||||
retriever.run(query="How many languages are there?", query_embedding=[0.1] * 768)
|
||||
```
|
||||
|
||||
### In a pipeline
|
||||
|
||||
```python
|
||||
from haystack.document_stores.types import DuplicatePolicy
|
||||
from haystack import Document
|
||||
from haystack import Pipeline
|
||||
from haystack.components.embedders import (
|
||||
SentenceTransformersTextEmbedder,
|
||||
SentenceTransformersDocumentEmbedder,
|
||||
)
|
||||
|
||||
from haystack_integrations.document_stores.weaviate.document_store import (
|
||||
WeaviateDocumentStore,
|
||||
)
|
||||
from haystack_integrations.components.retrievers.weaviate import (
|
||||
WeaviateHybridRetriever,
|
||||
)
|
||||
|
||||
document_store = WeaviateDocumentStore(url="http://localhost:8080")
|
||||
|
||||
documents = [
|
||||
Document(content="There are over 7,000 languages spoken around the world today."),
|
||||
Document(
|
||||
content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.",
|
||||
),
|
||||
Document(
|
||||
content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.",
|
||||
),
|
||||
]
|
||||
|
||||
document_embedder = SentenceTransformersDocumentEmbedder()
|
||||
documents_with_embeddings = document_embedder.run(documents)
|
||||
|
||||
document_store.write_documents(
|
||||
documents_with_embeddings.get("documents"),
|
||||
policy=DuplicatePolicy.OVERWRITE,
|
||||
)
|
||||
|
||||
query_pipeline = Pipeline()
|
||||
query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder())
|
||||
query_pipeline.add_component(
|
||||
"retriever",
|
||||
WeaviateHybridRetriever(document_store=document_store),
|
||||
)
|
||||
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
|
||||
|
||||
query = "How many languages are there?"
|
||||
|
||||
result = query_pipeline.run(
|
||||
{"text_embedder": {"text": query}, "retriever": {"query": query}},
|
||||
)
|
||||
|
||||
print(result["retriever"]["documents"][0])
|
||||
```
|
||||
|
||||
### Adjusting the Alpha Parameter
|
||||
|
||||
You can set the `alpha` parameter at initialization or override it at query time:
|
||||
|
||||
```python
|
||||
from haystack_integrations.components.retrievers.weaviate import WeaviateHybridRetriever
|
||||
|
||||
## Favor keyword search (good for exact matches)
|
||||
retriever_keyword_heavy = WeaviateHybridRetriever(
|
||||
document_store=document_store,
|
||||
alpha=0.25,
|
||||
)
|
||||
|
||||
## Balanced hybrid search
|
||||
retriever_balanced = WeaviateHybridRetriever(document_store=document_store, alpha=0.5)
|
||||
|
||||
## Favor vector search (good for semantic similarity)
|
||||
retriever_vector_heavy = WeaviateHybridRetriever(
|
||||
document_store=document_store,
|
||||
alpha=0.75,
|
||||
)
|
||||
|
||||
## Override alpha at query time
|
||||
result = retriever_balanced.run(
|
||||
query="artificial intelligence",
|
||||
query_embedding=embedding,
|
||||
alpha=0.8,
|
||||
)
|
||||
```
|
||||
Reference in New Issue
Block a user