Skip to content

Commit 2ff30f9

Browse files
committed
Updated examples to support haystack breaking changes
1 parent df57916 commit 2ff30f9

4 files changed

Lines changed: 73 additions & 68 deletions

File tree

README.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,9 @@
1919

2020
----
2121

22-
**Table of Contents**
22+
# Table of Contents
2323

24-
- [Breaking Changes in Version 2.0.0](#breaking-changes-in-version-200)
2524
- [Overview](#overview)
26-
- [Choosing the Right Document Store](#choosing-the-right-document-store)
2725
- [Installation](#installation)
2826
- [Usage](#usage)
2927
- [Running Couchbase](#running-couchbase)
@@ -32,7 +30,7 @@
3230
- [More Examples](#more-examples)
3331
- [License](#license)
3432

35-
## Breaking Changes in Version 2.0.0
33+
### Breaking Changes in Version 2.0.0
3634

3735
> **Important Note:**
3836
> In version 2.0.0, the following component names have been changed:
@@ -44,7 +42,7 @@
4442
4543
## Overview
4644

47-
An integration of [Couchbase](https://www.couchbase.com) NoSQL database with [Haystack v2.0](https://docs.haystack.deepset.ai/v2.0/docs/intro)
45+
An integration of [Couchbase](https://www.couchbase.com) NoSQL database with [Haystack](https://docs.haystack.deepset.ai/docs/intro)
4846
by [deepset](https://www.deepset.ai). Couchbase supports three types of [vector indexes](https://docs.couchbase.com/server/current/vector-search/vector-search.html) for AI applications, and this library provides document stores for two of them:
4947

5048
### Document Stores
@@ -62,7 +60,7 @@ from couchbase_haystack import CouchbaseSearchDocumentStore, CouchbaseQueryDocum
6260

6361
### Retrievers
6462

65-
In addition to the document stores, the library includes the following [retriever components](https://docs.haystack.deepset.ai/v2.0/docs/retrievers):
63+
In addition to the document stores, the library includes the following [retriever components](https://docs.haystack.deepset.ai/docs/retrievers):
6664

6765
- **`CouchbaseSearchEmbeddingRetriever`** - Works with `CouchbaseSearchDocumentStore` to perform hybrid searches combining vector similarity with full-text and geospatial queries.
6866

@@ -72,7 +70,7 @@ The `couchbase-haystack` library uses the [Couchbase Python SDK](https://docs.co
7270

7371
Both document stores store Documents as JSON documents in Couchbase. Embeddings are stored as part of the document, with indexing and querying managed by different Couchbase services depending on the document store type.
7472

75-
## Choosing the Right Document Store
73+
### Choosing the Right Document Store
7674

7775
Couchbase supports three types of vector indexes. This library currently supports two of them:
7876

@@ -274,7 +272,7 @@ The full list of parameters accepted by `CouchbaseSearchDocumentStore` can be fo
274272

275273
#### Indexing Documents with CouchbaseSearchDocumentStore
276274

277-
With Haystack you can use [DocumentWriter](https://docs.haystack.deepset.ai/v2.0/docs/documentwriter) component to write Documents into a Document Store. In the example below we construct pipeline to write documents to Couchbase using `CouchbaseSearchDocumentStore`:
275+
With Haystack you can use [DocumentWriter](https://docs.haystack.deepset.ai/docs/documentwriter) component to write Documents into a Document Store. In the example below we construct pipeline to write documents to Couchbase using `CouchbaseSearchDocumentStore`:
278276

279277
```python
280278
from haystack import Document
@@ -609,7 +607,7 @@ You can find more examples in the [examples](examples) directory:
609607
#### Search-based (FTS) Examples
610608

611609
- [examples/search/indexing_pipeline.py](examples/search/indexing_pipeline.py) - Indexing documents using `CouchbaseSearchDocumentStore`
612-
- [examples/search/rag_pipeline.py](examples/search/rag_pipeline.py) - RAG pipeline using `CouchbaseSearchEmbeddingRetriever` with [HuggingFaceAPIGenerator](https://docs.haystack.deepset.ai/v2.0/docs/huggingfacetgigenerator)
610+
- [examples/search/rag_pipeline.py](examples/search/rag_pipeline.py) - RAG pipeline using `CouchbaseSearchEmbeddingRetriever` with [HuggingFaceAPIGenerator](https://docs.haystack.deepset.ai/v2.20/docs/huggingfacetgigenerator)
613611

614612
#### GSI-based Examples
615613

examples/gsi/indexing_pipeline.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,16 @@
2020
CouchbaseQueryDocumentStore,
2121
CouchbaseQueryOptions,
2222
QueryVectorSearchType,
23+
CouchbaseClusterOptions,
2324
)
25+
from couchbase.options import KnownConfigProfiles, QueryOptions
2426

2527
logger = logging.getLogger(__name__)
2628

2729

2830
def fetch_archive_from_http(url: str, output_dir: str):
2931
if Path(output_dir).is_dir():
30-
logger.warn(f"'{output_dir}' directory already exists. Skipping data download")
32+
logger.warning(f"'{output_dir}' directory already exists. Skipping data download")
3133
return
3234

3335
with requests.get(url, timeout=10, stream=True) as response:
@@ -50,14 +52,15 @@ def fetch_archive_from_http(url: str, output_dir: str):
5052
# --env COUCHBASE_ADMINISTRATOR_PASSWORD=passw0rd \
5153
# couchbase:enterprise-8.0.0
5254

53-
bucket_name = "haystack_bucket_name"
54-
scope_name = "haystack_scope_name"
55-
collection_name = "haystack_collection_name"
56-
index_name = "haystack_index_name"
55+
bucket_name = os.getenv("BUCKET_NAME")
56+
scope_name = os.getenv("SCOPE_NAME")
57+
collection_name = os.getenv("COLLECTION_NAME")
58+
index_name = os.getenv("INDEX_NAME")
5759

5860
document_store = CouchbaseQueryDocumentStore(
5961
cluster_connection_string=Secret.from_env_var("CONNECTION_STRING"),
60-
authenticator=CouchbasePasswordAuthenticator(username=Secret.from_token("username"), password=Secret.from_token("password")),
62+
authenticator=CouchbasePasswordAuthenticator(username=Secret.from_env_var("USER_NAME"), password=Secret.from_env_var("PASSWORD")),
63+
cluster_options=CouchbaseClusterOptions(profile=KnownConfigProfiles.WanDevelopment),
6164
bucket=bucket_name,
6265
scope=scope_name,
6366
collection=collection_name,
@@ -73,7 +76,7 @@ def fetch_archive_from_http(url: str, output_dir: str):
7376
p = Pipeline()
7477
p.add_component("text_file_converter", TextFileToDocument())
7578
p.add_component("cleaner", DocumentCleaner())
76-
p.add_component("splitter", DocumentSplitter(split_by="sentence", split_length=250, split_overlap=30))
79+
p.add_component("splitter", DocumentSplitter(split_by="word", split_length=250, split_overlap=30))
7780
p.add_component("embedder", SentenceTransformersDocumentEmbedder(model="sentence-transformers/all-MiniLM-L6-v2"))
7881
p.add_component("writer", DocumentWriter(document_store=document_store))
7982

@@ -86,6 +89,8 @@ def fetch_archive_from_http(url: str, output_dir: str):
8689
file_paths = [docs_dir / Path(name) for name in os.listdir(docs_dir)]
8790
result = p.run({"text_file_converter": {"sources": file_paths}})
8891

92+
logger.info(f"Data written to Couchbase: {result}")
93+
8994
# Assuming you have a Docker container running, navigate to <http://localhost:8091>
9095
# to open the Couchbase Web Console and explore your data.
9196

@@ -94,8 +99,9 @@ def fetch_archive_from_http(url: str, output_dir: str):
9499
# this is a current limitation of the couchbase gsi vector index
95100
cfg = {
96101
"dimension": 384,
97-
"train_list": 500,
98102
"description": "IVF,PQ32x8",
99103
"similarity": "L2",
100104
}
101-
document_store.scope.query(f"Create Index {index_name} ON {collection_name} (embedding vector) USING GSI WITH {json.dumps(cfg)}")
105+
document_store.scope.query(f"Create Index {index_name} ON {collection_name} (embedding vector) USING GSI WITH {json.dumps(cfg)}", QueryOptions(timeout=timedelta(seconds=300))).execute()
106+
107+
logger.info(f"Index created: {index_name}")

examples/gsi/rag_pipeline.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1-
from couchbase.options import KnownConfigProfiles
1+
import os
22
from haystack import GeneratedAnswer, Pipeline
33
from haystack.components.builders.answer_builder import AnswerBuilder
4-
from haystack.components.builders.prompt_builder import PromptBuilder
4+
from haystack.components.builders.chat_prompt_builder import ChatPromptBuilder
5+
from haystack.dataclasses import ChatMessage
56
from haystack.components.embedders import SentenceTransformersTextEmbedder
6-
from haystack.components.generators import HuggingFaceAPIGenerator
7+
from haystack.components.generators.chat import HuggingFaceAPIChatGenerator
8+
from haystack.utils.hf import HFGenerationAPIType
79
from haystack.utils import Secret
8-
910
from couchbase_haystack import (
1011
CouchbaseClusterOptions,
1112
CouchbasePasswordAuthenticator,
1213
CouchbaseQueryDocumentStore,
1314
CouchbaseQueryEmbeddingRetriever,
1415
QueryVectorSearchType,
1516
)
17+
from couchbase.options import KnownConfigProfiles
1618

1719
# Load HF Token from environment variables.
1820
HF_TOKEN = Secret.from_env_var("HF_API_TOKEN")
@@ -26,51 +28,49 @@
2628
# couchbase:enterprise-8.0.0
2729

2830
document_store = CouchbaseQueryDocumentStore(
29-
cluster_connection_string=Secret.from_token("localhost"),
30-
authenticator=CouchbasePasswordAuthenticator(username=Secret.from_token("username"), password=Secret.from_token("password")),
31+
cluster_connection_string=Secret.from_env_var("CONNECTION_STRING"),
32+
authenticator=CouchbasePasswordAuthenticator(username=Secret.from_env_var("USER_NAME"), password=Secret.from_env_var("PASSWORD")),
3133
cluster_options=CouchbaseClusterOptions(
3234
profile=KnownConfigProfiles.WanDevelopment,
3335
),
34-
bucket="haystack_bucket_name",
35-
scope="haystack_scope_name",
36-
collection="haystack_collection_name",
36+
bucket=os.getenv("BUCKET_NAME"),
37+
scope=os.getenv("SCOPE_NAME"),
38+
collection=os.getenv("COLLECTION_NAME"),
3739
search_type=QueryVectorSearchType.ANN,
3840
similarity="L2",
3941
nprobes=10,
4042
)
4143

42-
# Build a RAG pipeline with a Retriever to get relevant documents to the query and a HuggingFaceTGIGenerator
44+
# Build a RAG pipeline with a Retriever to get relevant documents to the query and a HuggingFaceAPIChatGenerator
4345
# interacting with LLMs using a custom prompt.
44-
prompt_template = """
45-
Given these documents, answer the question.\nDocuments:
46+
prompt_messages = [
47+
ChatMessage.from_system("You are a helpful assistant that answers questions based on the provided documents."),
48+
ChatMessage.from_user("""Given these documents, answer the question.
49+
Documents:
4650
{% for doc in documents %}
4751
{{ doc.content }}
4852
{% endfor %}
4953
50-
\nQuestion: {{question}}
51-
\nAnswer:
52-
"""
54+
Question: {{question}}
55+
Answer:""")
56+
]
5357
rag_pipeline = Pipeline()
5458
rag_pipeline.add_component(
5559
"query_embedder",
5660
SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2", progress_bar=False),
5761
)
5862
rag_pipeline.add_component("retriever", CouchbaseQueryEmbeddingRetriever(document_store=document_store))
59-
rag_pipeline.add_component("prompt_builder", PromptBuilder(template=prompt_template))
60-
rag_pipeline.add_component(
61-
"llm",
62-
HuggingFaceAPIGenerator(
63-
api_type="serverless_inference_api",
64-
api_params={"model": "mistralai/Mistral-7B-v0.1"},
65-
),
66-
)
63+
rag_pipeline.add_component("prompt_builder", ChatPromptBuilder(template=prompt_messages, required_variables=["question"]))
64+
rag_pipeline.add_component("llm", HuggingFaceAPIChatGenerator(
65+
api_type=HFGenerationAPIType.SERVERLESS_INFERENCE_API,
66+
api_params={"model": "mistralai/Mistral-7B-Instruct-v0.2"},
67+
))
6768
rag_pipeline.add_component("answer_builder", AnswerBuilder())
6869

6970
rag_pipeline.connect("query_embedder", "retriever.query_embedding")
70-
rag_pipeline.connect("retriever.documents", "prompt_builder.documents")
71-
rag_pipeline.connect("prompt_builder.prompt", "llm.prompt")
71+
rag_pipeline.connect("retriever", "prompt_builder.documents")
72+
rag_pipeline.connect("prompt_builder", "llm")
7273
rag_pipeline.connect("llm.replies", "answer_builder.replies")
73-
rag_pipeline.connect("llm.meta", "answer_builder.meta")
7474
rag_pipeline.connect("retriever", "answer_builder.documents")
7575

7676
# Ask a question on the data you just added.

examples/search/rag_pipeline.py

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import os
12
from haystack import GeneratedAnswer, Pipeline
23
from haystack.components.builders.answer_builder import AnswerBuilder
3-
from haystack.components.builders.prompt_builder import PromptBuilder
4+
from haystack.components.builders.chat_prompt_builder import ChatPromptBuilder
5+
from haystack.dataclasses import ChatMessage
46
from haystack.components.embedders import SentenceTransformersTextEmbedder
5-
from haystack.components.generators import HuggingFaceAPIGenerator
7+
from haystack.components.generators.chat import HuggingFaceAPIChatGenerator
8+
from haystack.utils.hf import HFGenerationAPIType
69
from haystack.utils import Secret
710

811
from couchbase_haystack import CouchbasePasswordAuthenticator, CouchbaseSearchDocumentStore, CouchbaseSearchEmbeddingRetriever
@@ -19,46 +22,44 @@
1922
# couchbase:enterprise-7.6.2
2023

2124
document_store = CouchbaseSearchDocumentStore(
22-
cluster_connection_string=Secret.from_token("localhost"),
23-
authenticator=CouchbasePasswordAuthenticator(username=Secret.from_token("username"), password=Secret.from_token("password")),
24-
bucket="haystack_bucket_name",
25-
scope="haystack_scope_name",
26-
collection="haystack_collection_name",
27-
vector_search_index="vector_search_index",
25+
cluster_connection_string=Secret.from_env_var("CONNECTION_STRING"),
26+
authenticator=CouchbasePasswordAuthenticator(username=Secret.from_env_var("USER_NAME"), password=Secret.from_env_var("PASSWORD")),
27+
bucket=os.getenv("BUCKET_NAME"),
28+
scope=os.getenv("SCOPE_NAME"),
29+
collection=os.getenv("COLLECTION_NAME"),
30+
vector_search_index="vector_search",
2831
)
2932

3033
# Build a RAG pipeline with a Retriever to get relevant documents to the query and a HuggingFaceTGIGenerator
3134
# interacting with LLMs using a custom prompt.
32-
prompt_template = """
33-
Given these documents, answer the question.\nDocuments:
35+
prompt_messages = [
36+
ChatMessage.from_system("You are a helpful assistant that answers questions based on the provided documents."),
37+
ChatMessage.from_user("""Given these documents, answer the question.
38+
Documents:
3439
{% for doc in documents %}
3540
{{ doc.content }}
3641
{% endfor %}
3742
38-
\nQuestion: {{question}}
39-
\nAnswer:
40-
"""
43+
Question: {{question}}
44+
Answer:""")
45+
]
4146
rag_pipeline = Pipeline()
4247
rag_pipeline.add_component(
4348
"query_embedder",
4449
SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2", progress_bar=False),
4550
)
4651
rag_pipeline.add_component("retriever", CouchbaseSearchEmbeddingRetriever(document_store=document_store))
47-
rag_pipeline.add_component("prompt_builder", PromptBuilder(template=prompt_template))
48-
rag_pipeline.add_component(
49-
"llm",
50-
HuggingFaceAPIGenerator(
51-
api_type="serverless_inference_api",
52-
api_params={"model": "mistralai/Mistral-7B-v0.1"},
53-
),
54-
)
52+
rag_pipeline.add_component("prompt_builder", ChatPromptBuilder(template=prompt_messages, required_variables=["question"]))
53+
rag_pipeline.add_component("llm", HuggingFaceAPIChatGenerator(
54+
api_type=HFGenerationAPIType.SERVERLESS_INFERENCE_API,
55+
api_params={"model": "mistralai/Mistral-7B-Instruct-v0.2"},
56+
))
5557
rag_pipeline.add_component("answer_builder", AnswerBuilder())
5658

5759
rag_pipeline.connect("query_embedder", "retriever.query_embedding")
58-
rag_pipeline.connect("retriever.documents", "prompt_builder.documents")
59-
rag_pipeline.connect("prompt_builder.prompt", "llm.prompt")
60+
rag_pipeline.connect("retriever", "prompt_builder.documents")
61+
rag_pipeline.connect("prompt_builder", "llm")
6062
rag_pipeline.connect("llm.replies", "answer_builder.replies")
61-
rag_pipeline.connect("llm.meta", "answer_builder.meta")
6263
rag_pipeline.connect("retriever", "answer_builder.documents")
6364

6465
# Ask a question on the data you just added.

0 commit comments

Comments
 (0)