1
0
mirror of https://github.com/hwchase17/langchain.git synced 2025-05-05 15:18:32 +00:00

docs: Fix Qdrant sparse and hybrid vector search ()

- [x] **PR title**


- [x] **PR message**:
- **Description:** Updated the sparse and hybrid vector search due to
changes in the Qdrant API, and cleaned up the notebook
  

- [x] **Add tests and docs**:
    - N/A


- [x] **Lint and test**

Additional guidelines:
- Make sure optional dependencies are imported within a function.
- Please do not add dependencies to pyproject.toml files (even optional
ones) unless they are required for unit tests.
- Most PRs should not touch more than one package.
- Changes should be backwards compatible.
- If you are adding something to community, do not re-import it in
langchain.

If no one reviews your PR within a few days, please @-mention one of
baskaryan, eyurtsev, ccurme, vbarda, hwchase17.

Co-authored-by: Mark Perfect <mark.anthony.perfect1@gmail.com>
This commit is contained in:
Mark Perfect 2025-03-18 22:44:12 -04:00 committed by GitHub
parent f949d9a3d3
commit 38b48d257d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -8,11 +8,9 @@
"source": [
"# Qdrant\n",
"\n",
">[Qdrant](https://qdrant.tech/documentation/) (read: quadrant ) is a vector similarity search engine. It provides a production-ready service with a convenient API to store, search, and manage vectors with additional payload and extended filtering support. It makes it useful for all sorts of neural network or semantic-based matching, faceted search, and other applications.\n",
">[Qdrant](https://qdrant.tech/documentation/) (read: quadrant) is a vector similarity search engine. It provides a production-ready service with a convenient API to store, search, and manage vectors with additional payload and extended filtering support. It makes it useful for all sorts of neural network or semantic-based matching, faceted search, and other applications.\n",
"\n",
"This documentation demonstrates how to use Qdrant with Langchain for dense/sparse and hybrid retrieval.\n",
"\n",
"> This page documents the `QdrantVectorStore` class that supports multiple retrieval modes via Qdrant's new [Query API](https://qdrant.tech/blog/qdrant-1.10.x/). It requires you to run Qdrant v1.10.0 or above.\n",
"This documentation demonstrates how to use Qdrant with LangChain for dense (i.e., embedding-based), sparse (i.e., text search) and hybrid retrieval. The `QdrantVectorStore` class supports multiple retrieval modes via Qdrant's new [Query API](https://qdrant.tech/blog/qdrant-1.10.x/). It requires you to run Qdrant v1.10.0 or above.\n",
"\n",
"\n",
"## Setup\n",
@ -22,7 +20,7 @@
"- Docker deployments\n",
"- Qdrant Cloud\n",
"\n",
"See the [installation instructions](https://qdrant.tech/documentation/install/)."
"Please see the installation instructions [here](https://qdrant.tech/documentation/install/)."
]
},
{
@ -70,11 +68,11 @@
"\n",
"### Local mode\n",
"\n",
"Python client allows you to run the same code in local mode without running the Qdrant server. That's great for testing things out and debugging or storing just a small amount of vectors. The embeddings might be fully kept in memory or persisted on disk.\n",
"The Python client provides the option to run the code in local mode without running the Qdrant server. This is great for testing things out and debugging or storing just a small amount of vectors. The embeddings can be kept fully in-memory or persisted on-disk.\n",
"\n",
"#### In-memory\n",
"\n",
"For some testing scenarios and quick experiments, you may prefer to keep all the data in memory only, so it gets lost when the client is destroyed - usually at the end of your script/notebook.\n",
"For some testing scenarios and quick experiments, you may prefer to keep all the data in-memory only, so it gets removed when the client is destroyed - usually at the end of your script/notebook.\n",
"\n",
"\n",
"import EmbeddingTabs from \"@theme/EmbeddingTabs\";\n",
@ -135,7 +133,7 @@
"source": [
"#### On-disk storage\n",
"\n",
"Local mode, without using the Qdrant server, may also store your vectors on disk so they persist between runs."
"Local mode, without using the Qdrant server, may also store your vectors on-disk so they persist between runs."
]
},
{
@ -173,7 +171,7 @@
"source": [
"### On-premise server deployment\n",
"\n",
"No matter if you choose to launch Qdrant locally with [a Docker container](https://qdrant.tech/documentation/install/), or select a Kubernetes deployment with [the official Helm chart](https://github.com/qdrant/qdrant-helm), the way you're going to connect to such an instance will be identical. You'll need to provide a URL pointing to the service."
"No matter if you choose to launch Qdrant locally with [a Docker container](https://qdrant.tech/documentation/install/) or select a Kubernetes deployment with [the official Helm chart](https://github.com/qdrant/qdrant-helm), the way you're going to connect to such an instance will be identical. You'll need to provide a URL pointing to the service."
]
},
{
@ -280,42 +278,22 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": null,
"id": "7697a362",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['c04134c3-273d-4766-949a-eee46052ad32',\n",
" '9e6ba50c-794f-4b88-94e5-411f15052a02',\n",
" 'd3202666-6f2b-4186-ac43-e35389de8166',\n",
" '50d8d6ee-69bf-4173-a6a2-b254e9928965',\n",
" 'bd2eae02-74b5-43ec-9fcf-09e9d9db6fd3',\n",
" '6dae6b37-826d-4f14-8376-da4603b35de3',\n",
" 'b0964ab5-5a14-47b4-a983-37fa5c5bd154',\n",
" '91ed6c56-fe53-49e2-8199-c3bb3c33c3eb',\n",
" '42a580cb-7469-4324-9927-0febab57ce92',\n",
" 'ff774e5c-f158-4d12-94e2-0a0162b22f27']"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"outputs": [],
"source": [
"from uuid import uuid4\n",
"\n",
"from langchain_core.documents import Document\n",
"\n",
"document_1 = Document(\n",
" page_content=\"I had chocalate chip pancakes and scrambled eggs for breakfast this morning.\",\n",
" page_content=\"I had chocolate chip pancakes and scrambled eggs for breakfast this morning.\",\n",
" metadata={\"source\": \"tweet\"},\n",
")\n",
"\n",
"document_2 = Document(\n",
" page_content=\"The weather forecast for tomorrow is cloudy and overcast, with a high of 62 degrees.\",\n",
" page_content=\"The weather forecast for tomorrow is cloudy and overcast, with a high of 62 degrees Fahrenheit.\",\n",
" metadata={\"source\": \"news\"},\n",
")\n",
"\n",
@ -371,8 +349,16 @@
" document_9,\n",
" document_10,\n",
"]\n",
"uuids = [str(uuid4()) for _ in range(len(documents))]\n",
"\n",
"uuids = [str(uuid4()) for _ in range(len(documents))]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "413c3d9a",
"metadata": {},
"outputs": [],
"source": [
"vector_store.add_documents(documents=documents, ids=uuids)"
]
},
@ -418,11 +404,11 @@
"source": [
"## Query vector store\n",
"\n",
"Once your vector store has been created and the relevant documents have been added you will most likely wish to query it during the running of your chain or agent. \n",
"Once your vector store has been created and the relevant documents have been added, you will most likely wish to query it during the running of your chain or agent. \n",
"\n",
"### Query directly\n",
"\n",
"The simplest scenario for using Qdrant vector store is to perform a similarity search. Under the hood, our query will be encoded into vector embeddings and used to find similar documents in Qdrant collection."
"The simplest scenario for using the Qdrant vector store is to perform a similarity search. Under the hood, our query will be encoded into vector embeddings and used to find similar documents in a Qdrant collection."
]
},
{
@ -459,17 +445,17 @@
"id": "79bcb0ce",
"metadata": {},
"source": [
"`QdrantVectorStore` supports 3 modes for similarity searches. They can be configured using the `retrieval_mode` parameter when setting up the class.\n",
"`QdrantVectorStore` supports 3 modes for similarity searches. They can be configured using the `retrieval_mode` parameter.\n",
"\n",
"- Dense Vector Search(Default)\n",
"- Dense Vector Search (default)\n",
"- Sparse Vector Search\n",
"- Hybrid Search\n",
"\n",
"### Dense Vector Search\n",
"\n",
"To search with only dense vectors,\n",
"Dense vector search involves calculating similarity via vector-based embeddings. To search with only dense vectors:\n",
"\n",
"- The `retrieval_mode` parameter should be set to `RetrievalMode.DENSE`(default).\n",
"- The `retrieval_mode` parameter should be set to `RetrievalMode.DENSE`. This is the default behavior.\n",
"- A [dense embeddings](https://python.langchain.com/docs/integrations/text_embedding/) value should be provided to the `embedding` parameter."
]
},
@ -480,18 +466,31 @@
"metadata": {},
"outputs": [],
"source": [
"from langchain_qdrant import RetrievalMode\n",
"from langchain_qdrant import QdrantVectorStore, RetrievalMode\n",
"from qdrant_client import QdrantClient\n",
"from qdrant_client.http.models import Distance, VectorParams\n",
"\n",
"qdrant = QdrantVectorStore.from_documents(\n",
" docs,\n",
" embedding=embeddings,\n",
" location=\":memory:\",\n",
"# Create a Qdrant client for local storage\n",
"client = QdrantClient(path=\"/tmp/langchain_qdrant\")\n",
"\n",
"# Create a collection with dense vectors\n",
"client.create_collection(\n",
" collection_name=\"my_documents\",\n",
" vectors_config=VectorParams(size=3072, distance=Distance.COSINE),\n",
")\n",
"\n",
"qdrant = QdrantVectorStore(\n",
" client=client,\n",
" collection_name=\"my_documents\",\n",
" embedding=embeddings,\n",
" retrieval_mode=RetrievalMode.DENSE,\n",
")\n",
"\n",
"query = \"What did the president say about Ketanji Brown Jackson\"\n",
"found_docs = qdrant.similarity_search(query)"
"qdrant.add_documents(documents=documents, ids=uuids)\n",
"\n",
"query = \"How much money did the robbers steal?\"\n",
"found_docs = qdrant.similarity_search(query)\n",
"found_docs"
]
},
{
@ -501,10 +500,10 @@
"source": [
"### Sparse Vector Search\n",
"\n",
"To search with only sparse vectors,\n",
"To search with only sparse vectors:\n",
"\n",
"- The `retrieval_mode` parameter should be set to `RetrievalMode.SPARSE`.\n",
"- An implementation of the [`SparseEmbeddings`](https://github.com/langchain-ai/langchain/blob/master/libs/partners/qdrant/langchain_qdrant/sparse_embeddings.py) interface using any sparse embeddings provider has to be provided as value to the `sparse_embedding` parameter.\n",
"- An implementation of the [`SparseEmbeddings`](https://github.com/langchain-ai/langchain/blob/master/libs/partners/qdrant/langchain_qdrant/sparse_embeddings.py) interface using any sparse embeddings provider has to be provided as a value to the `sparse_embedding` parameter.\n",
"\n",
"The `langchain-qdrant` package provides a [FastEmbed](https://github.com/qdrant/fastembed) based implementation out of the box.\n",
"\n",
@ -518,7 +517,7 @@
"metadata": {},
"outputs": [],
"source": [
"%pip install fastembed"
"%pip install -qU fastembed"
]
},
{
@ -528,20 +527,37 @@
"metadata": {},
"outputs": [],
"source": [
"from langchain_qdrant import FastEmbedSparse, RetrievalMode\n",
"from langchain_qdrant import FastEmbedSparse, QdrantVectorStore, RetrievalMode\n",
"from qdrant_client import QdrantClient, models\n",
"from qdrant_client.http.models import Distance, SparseVectorParams, VectorParams\n",
"\n",
"sparse_embeddings = FastEmbedSparse(model_name=\"Qdrant/bm25\")\n",
"\n",
"qdrant = QdrantVectorStore.from_documents(\n",
" docs,\n",
" sparse_embedding=sparse_embeddings,\n",
" location=\":memory:\",\n",
"# Create a Qdrant client for local storage\n",
"client = QdrantClient(path=\"/tmp/langchain_qdrant\")\n",
"\n",
"# Create a collection with sparse vectors\n",
"client.create_collection(\n",
" collection_name=\"my_documents\",\n",
" retrieval_mode=RetrievalMode.SPARSE,\n",
" vectors_config={\"dense\": VectorParams(size=3072, distance=Distance.COSINE)},\n",
" sparse_vectors_config={\n",
" \"sparse\": SparseVectorParams(index=models.SparseIndexParams(on_disk=False))\n",
" },\n",
")\n",
"\n",
"query = \"What did the president say about Ketanji Brown Jackson\"\n",
"found_docs = qdrant.similarity_search(query)"
"qdrant = QdrantVectorStore(\n",
" client=client,\n",
" collection_name=\"my_documents\",\n",
" sparse_embedding=sparse_embeddings,\n",
" retrieval_mode=RetrievalMode.SPARSE,\n",
" sparse_vector_name=\"sparse\",\n",
")\n",
"\n",
"qdrant.add_documents(documents=documents, ids=uuids)\n",
"\n",
"query = \"How much money did the robbers steal?\"\n",
"found_docs = qdrant.similarity_search(query)\n",
"found_docs"
]
},
{
@ -555,9 +571,9 @@
"\n",
"- The `retrieval_mode` parameter should be set to `RetrievalMode.HYBRID`.\n",
"- A [dense embeddings](https://python.langchain.com/docs/integrations/text_embedding/) value should be provided to the `embedding` parameter.\n",
"- An implementation of the [`SparseEmbeddings`](https://github.com/langchain-ai/langchain/blob/master/libs/partners/qdrant/langchain_qdrant/sparse_embeddings.py) interface using any sparse embeddings provider has to be provided as value to the `sparse_embedding` parameter.\n",
"- An implementation of the [`SparseEmbeddings`](https://github.com/langchain-ai/langchain/blob/master/libs/partners/qdrant/langchain_qdrant/sparse_embeddings.py) interface using any sparse embeddings provider has to be provided as a value to the `sparse_embedding` parameter.\n",
"\n",
"Note that if you've added documents with the `HYBRID` mode, you can switch to any retrieval mode when searching. Since both the dense and sparse vectors are available in the collection."
"Note that if you've added documents with the `HYBRID` mode, you can switch to any retrieval mode when searching, since both the dense and sparse vectors are available in the collection."
]
},
{
@ -567,21 +583,39 @@
"metadata": {},
"outputs": [],
"source": [
"from langchain_qdrant import FastEmbedSparse, RetrievalMode\n",
"from langchain_qdrant import FastEmbedSparse, QdrantVectorStore, RetrievalMode\n",
"from qdrant_client import QdrantClient, models\n",
"from qdrant_client.http.models import Distance, SparseVectorParams, VectorParams\n",
"\n",
"sparse_embeddings = FastEmbedSparse(model_name=\"Qdrant/bm25\")\n",
"\n",
"qdrant = QdrantVectorStore.from_documents(\n",
" docs,\n",
" embedding=embeddings,\n",
" sparse_embedding=sparse_embeddings,\n",
" location=\":memory:\",\n",
"# Create a Qdrant client for local storage\n",
"client = QdrantClient(path=\"/tmp/langchain_qdrant\")\n",
"\n",
"# Create a collection with both dense and sparse vectors\n",
"client.create_collection(\n",
" collection_name=\"my_documents\",\n",
" retrieval_mode=RetrievalMode.HYBRID,\n",
" vectors_config={\"dense\": VectorParams(size=3072, distance=Distance.COSINE)},\n",
" sparse_vectors_config={\n",
" \"sparse\": SparseVectorParams(index=models.SparseIndexParams(on_disk=False))\n",
" },\n",
")\n",
"\n",
"query = \"What did the president say about Ketanji Brown Jackson\"\n",
"found_docs = qdrant.similarity_search(query)"
"qdrant = QdrantVectorStore(\n",
" client=client,\n",
" collection_name=\"my_documents\",\n",
" embedding=embeddings,\n",
" sparse_embedding=sparse_embeddings,\n",
" retrieval_mode=RetrievalMode.HYBRID,\n",
" vector_name=\"dense\",\n",
" sparse_vector_name=\"sparse\",\n",
")\n",
"\n",
"qdrant.add_documents(documents=documents, ids=uuids)\n",
"\n",
"query = \"How much money did the robbers steal?\"\n",
"found_docs = qdrant.similarity_search(query)\n",
"found_docs"
]
},
{
@ -728,7 +762,7 @@
"source": [
"## Customizing Qdrant\n",
"\n",
"There are options to use an existing Qdrant collection within your Langchain application. In such cases, you may need to define how to map Qdrant point into the Langchain `Document`.\n",
"There are options to use an existing Qdrant collection within your LangChain application. In such cases, you may need to define how to map Qdrant point into the LangChain `Document`.\n",
"\n",
"### Named vectors\n",
"\n",