From e002c855bd7e7d3dff2c0d858114acce9450887f Mon Sep 17 00:00:00 2001 From: Anush Date: Fri, 14 Jun 2024 08:31:32 +0530 Subject: [PATCH] qdrant[patch]: Use collection_exists API instead of exceptions (#22764) ## Description Currently, the Qdrant integration relies on exceptions raised by [`get_collection` ](https://qdrant.tech/documentation/concepts/collections/#collection-info) to check if a collection exists. Using [`collection_exists`](https://qdrant.tech/documentation/concepts/collections/#check-collection-existence) is recommended to avoid missing any unhandled exceptions. This PR addresses this. ## Testing All integration and unit tests pass. No user-facing changes. --- .../qdrant/langchain_qdrant/vectorstores.py | 35 ++++++++++--------- libs/partners/qdrant/poetry.lock | 15 ++++---- libs/partners/qdrant/pyproject.toml | 2 +- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/libs/partners/qdrant/langchain_qdrant/vectorstores.py b/libs/partners/qdrant/langchain_qdrant/vectorstores.py index c7e14a0696..ee332c2cfe 100644 --- a/libs/partners/qdrant/langchain_qdrant/vectorstores.py +++ b/libs/partners/qdrant/langchain_qdrant/vectorstores.py @@ -23,14 +23,12 @@ from typing import ( ) import numpy as np -from grpc import RpcError # type: ignore from langchain_core.documents import Document from langchain_core.embeddings import Embeddings from langchain_core.runnables.config import run_in_executor from langchain_core.vectorstores import VectorStore from qdrant_client import AsyncQdrantClient, QdrantClient from qdrant_client.http import models -from qdrant_client.http.exceptions import UnexpectedResponse from qdrant_client.local.async_qdrant_local import AsyncQdrantLocal from langchain_qdrant._utils import maximal_marginal_relevance @@ -1636,14 +1634,16 @@ class Qdrant(VectorStore): path=path, **kwargs, ) - try: - # Skip any validation in case of forced collection recreate. - if force_recreate: - raise ValueError + collection_exists = client.collection_exists(collection_name) + + if collection_exists and force_recreate: + client.delete_collection(collection_name) + collection_exists = False + if collection_exists: # Get the vector configuration of the existing collection and vector, if it # was specified. If the old configuration does not match the current one, - # an exception is being thrown. + # an exception is raised. collection_info = client.get_collection(collection_name=collection_name) current_vector_config = collection_info.config.params.vectors if isinstance(current_vector_config, dict) and vector_name is not None: @@ -1700,7 +1700,7 @@ class Qdrant(VectorStore): f"If you want to recreate the collection, set `force_recreate` " f"parameter to `True`." ) - except (UnexpectedResponse, RpcError, ValueError): + else: vectors_config = models.VectorParams( size=vector_size, distance=models.Distance[distance_func], @@ -1714,8 +1714,6 @@ class Qdrant(VectorStore): vector_name: vectors_config, } - if client.collection_exists(collection_name): - client.delete_collection(collection_name) client.create_collection( collection_name=collection_name, vectors_config=vectors_config, @@ -1795,14 +1793,17 @@ class Qdrant(VectorStore): path=path, **kwargs, ) - try: - # Skip any validation in case of forced collection recreate. - if force_recreate: - raise ValueError + collection_exists = client.collection_exists(collection_name) + + if collection_exists and force_recreate: + client.delete_collection(collection_name) + collection_exists = False + + if collection_exists: # Get the vector configuration of the existing collection and vector, if it # was specified. If the old configuration does not match the current one, - # an exception is being thrown. + # an exception is raised. collection_info = client.get_collection(collection_name=collection_name) current_vector_config = collection_info.config.params.vectors if isinstance(current_vector_config, dict) and vector_name is not None: @@ -1861,7 +1862,7 @@ class Qdrant(VectorStore): f"recreate the collection, set `force_recreate` parameter to " f"`True`." ) - except (UnexpectedResponse, RpcError, ValueError): + else: vectors_config = models.VectorParams( size=vector_size, distance=models.Distance[distance_func], @@ -1875,7 +1876,7 @@ class Qdrant(VectorStore): vector_name: vectors_config, } - client.recreate_collection( + client.create_collection( collection_name=collection_name, vectors_config=vectors_config, shard_number=shard_number, diff --git a/libs/partners/qdrant/poetry.lock b/libs/partners/qdrant/poetry.lock index b47c7a77f6..d856d2518d 100644 --- a/libs/partners/qdrant/poetry.lock +++ b/libs/partners/qdrant/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "annotated-types" @@ -463,7 +463,7 @@ files = [ [[package]] name = "langchain-core" -version = "0.2.0rc1" +version = "0.2.5" description = "Building applications with LLMs through composability" optional = false python-versions = ">=3.8.1,<4.0" @@ -472,28 +472,25 @@ develop = true [package.dependencies] jsonpatch = "^1.33" -langsmith = "^0.1.0" +langsmith = "^0.1.75" packaging = "^23.2" pydantic = ">=1,<3" PyYAML = ">=5.3" tenacity = "^8.1.0" -[package.extras] -extended-testing = ["jinja2 (>=3,<4)"] - [package.source] type = "directory" url = "../../core" [[package]] name = "langsmith" -version = "0.1.58" +version = "0.1.76" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langsmith-0.1.58-py3-none-any.whl", hash = "sha256:1148cc836ec99d1b2f37cd2fa3014fcac213bb6bad798a2b21bb9111c18c9768"}, - {file = "langsmith-0.1.58.tar.gz", hash = "sha256:a5060933c1fb3006b498ec849677993329d7e6138bdc2ec044068ab806e09c39"}, + {file = "langsmith-0.1.76-py3-none-any.whl", hash = "sha256:4b8cb14f2233d9673ce9e6e3d545359946d9690a2c1457ab01e7459ec97b964e"}, + {file = "langsmith-0.1.76.tar.gz", hash = "sha256:5829f997495c0f9a39f91fe0a57e0cb702e8642e6948945f5bb9f46337db7732"}, ] [package.dependencies] diff --git a/libs/partners/qdrant/pyproject.toml b/libs/partners/qdrant/pyproject.toml index 0871b867ee..59e897988f 100644 --- a/libs/partners/qdrant/pyproject.toml +++ b/libs/partners/qdrant/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langchain-qdrant" -version = "0.1.0" +version = "0.1.1" description = "An integration package connecting Qdrant and LangChain" authors = [] readme = "README.md"