diff --git a/llama-index-integrations/vector_stores/llama-index-vector-stores-qdrant/llama_index/vector_stores/qdrant/base.py b/llama-index-integrations/vector_stores/llama-index-vector-stores-qdrant/llama_index/vector_stores/qdrant/base.py index c69ce034e3c68af8de3a5e210f282bc2429fe3bf..151de9d4e18aa71f35f7e9649f0b4ef803e54f39 100644 --- a/llama-index-integrations/vector_stores/llama-index-vector-stores-qdrant/llama_index/vector_stores/qdrant/base.py +++ b/llama-index-integrations/vector_stores/llama-index-vector-stores-qdrant/llama_index/vector_stores/qdrant/base.py @@ -29,6 +29,7 @@ from llama_index.vector_stores.qdrant.utils import ( SparseEncoderCallable, default_sparse_encoder, relative_score_fusion, + fastembed_sparse_encoder, ) from qdrant_client.http import models as rest from qdrant_client.http.exceptions import UnexpectedResponse @@ -49,6 +50,10 @@ import_err_msg = ( "`qdrant-client` package not found, please run `pip install qdrant-client`" ) +DENSE_VECTOR_NAME = "text-dense" +SPARSE_VECTOR_NAME_OLD = "text-sparse" +SPARSE_VECTOR_NAME = "text-sparse-new" + class QdrantVectorStore(BasePydanticVectorStore): """ @@ -163,11 +168,12 @@ class QdrantVectorStore(BasePydanticVectorStore): # setup hybrid search if enabled if enable_hybrid: - self._sparse_doc_fn = sparse_doc_fn or default_sparse_encoder( - "naver/efficient-splade-VI-BT-large-doc" + self._sparse_doc_fn = sparse_doc_fn or self.get_default_sparse_doc_encoder( + collection_name ) - self._sparse_query_fn = sparse_query_fn or default_sparse_encoder( - "naver/efficient-splade-VI-BT-large-query" + self._sparse_query_fn = ( + sparse_query_fn + or self.get_default_sparse_query_encoder(collection_name) ) self._hybrid_fusion_fn = hybrid_fusion_fn or cast( HybridFusionCallable, relative_score_fusion @@ -228,17 +234,18 @@ class QdrantVectorStore(BasePydanticVectorStore): ): vectors.append( { - "text-sparse": rest.SparseVector( + # Dynamically switch between the old and new sparse vector name + self.sparse_vector_name: rest.SparseVector( indices=sparse_indices[i], values=sparse_vectors[i], ), - "text-dense": node.get_embedding(), + DENSE_VECTOR_NAME: node.get_embedding(), } ) else: vectors.append( { - "text-dense": node.get_embedding(), + DENSE_VECTOR_NAME: node.get_embedding(), } ) else: @@ -375,13 +382,14 @@ class QdrantVectorStore(BasePydanticVectorStore): self._client.create_collection( collection_name=collection_name, vectors_config={ - "text-dense": rest.VectorParams( + DENSE_VECTOR_NAME: rest.VectorParams( size=vector_size, distance=rest.Distance.COSINE, ) }, + # Newly created collection will have the new sparse vector name sparse_vectors_config={ - "text-sparse": rest.SparseVectorParams( + SPARSE_VECTOR_NAME: rest.SparseVectorParams( index=rest.SparseIndexParams() ) }, @@ -413,13 +421,13 @@ class QdrantVectorStore(BasePydanticVectorStore): await self._aclient.create_collection( collection_name=collection_name, vectors_config={ - "text-dense": rest.VectorParams( + DENSE_VECTOR_NAME: rest.VectorParams( size=vector_size, distance=rest.Distance.COSINE, ) }, sparse_vectors_config={ - "text-sparse": rest.SparseVectorParams( + SPARSE_VECTOR_NAME: rest.SparseVectorParams( index=rest.SparseIndexParams() ) }, @@ -497,7 +505,7 @@ class QdrantVectorStore(BasePydanticVectorStore): requests=[ rest.SearchRequest( vector=rest.NamedVector( - name="text-dense", + name=DENSE_VECTOR_NAME, vector=query_embedding, ), limit=query.similarity_top_k, @@ -506,7 +514,8 @@ class QdrantVectorStore(BasePydanticVectorStore): ), rest.SearchRequest( vector=rest.NamedSparseVector( - name="text-sparse", + # Dynamically switch between the old and new sparse vector name + name=self.sparse_vector_name, vector=rest.SparseVector( indices=sparse_indices[0], values=sparse_embedding[0], @@ -548,7 +557,8 @@ class QdrantVectorStore(BasePydanticVectorStore): requests=[ rest.SearchRequest( vector=rest.NamedSparseVector( - name="text-sparse", + # Dynamically switch between the old and new sparse vector name + name=self.sparse_vector_name, vector=rest.SparseVector( indices=sparse_indices[0], values=sparse_embedding[0], @@ -569,7 +579,7 @@ class QdrantVectorStore(BasePydanticVectorStore): requests=[ rest.SearchRequest( vector=rest.NamedVector( - name="text-dense", + name=DENSE_VECTOR_NAME, vector=query_embedding, ), limit=query.similarity_top_k, @@ -629,7 +639,7 @@ class QdrantVectorStore(BasePydanticVectorStore): requests=[ rest.SearchRequest( vector=rest.NamedVector( - name="text-dense", + name=DENSE_VECTOR_NAME, vector=query_embedding, ), limit=query.similarity_top_k, @@ -638,7 +648,8 @@ class QdrantVectorStore(BasePydanticVectorStore): ), rest.SearchRequest( vector=rest.NamedSparseVector( - name="text-sparse", + # Dynamically switch between the old and new sparse vector name + name=self.sparse_vector_name, vector=rest.SparseVector( indices=sparse_indices[0], values=sparse_embedding[0], @@ -679,7 +690,8 @@ class QdrantVectorStore(BasePydanticVectorStore): requests=[ rest.SearchRequest( vector=rest.NamedSparseVector( - name="text-sparse", + # Dynamically switch between the old and new sparse vector name + name=self.sparse_vector_name, vector=rest.SparseVector( indices=sparse_indices[0], values=sparse_embedding[0], @@ -699,7 +711,7 @@ class QdrantVectorStore(BasePydanticVectorStore): requests=[ rest.SearchRequest( vector=rest.NamedVector( - name="text-dense", + name=DENSE_VECTOR_NAME, vector=query_embedding, ), limit=query.similarity_top_k, @@ -857,3 +869,34 @@ class QdrantVectorStore(BasePydanticVectorStore): ) return Filter(must=must_conditions) + + def use_old_sparse_encoder(self, collection_name: str) -> bool: + return ( + self._collection_exists(collection_name) + and SPARSE_VECTOR_NAME_OLD + in self.client.get_collection(collection_name).config.params.vectors + ) + + @property + def sparse_vector_name(self) -> str: + return ( + SPARSE_VECTOR_NAME_OLD + if self.use_old_sparse_encoder(self.collection_name) + else SPARSE_VECTOR_NAME + ) + + def get_default_sparse_doc_encoder( + self, collection_name: str + ) -> SparseEncoderCallable: + if self.use_old_sparse_encoder(collection_name): + return default_sparse_encoder("naver/efficient-splade-VI-BT-large-doc") + + return fastembed_sparse_encoder(model_name="prithvida/Splade_PP_en_v1") + + def get_default_sparse_query_encoder( + self, collection_name: str + ) -> SparseEncoderCallable: + if self.use_old_sparse_encoder(collection_name): + return default_sparse_encoder("naver/efficient-splade-VI-BT-large-query") + + return fastembed_sparse_encoder(model_name="prithvida/Splade_PP_en_v1") diff --git a/llama-index-integrations/vector_stores/llama-index-vector-stores-qdrant/pyproject.toml b/llama-index-integrations/vector_stores/llama-index-vector-stores-qdrant/pyproject.toml index 08d37b7ad52d842409626f28023a88537d95554d..1a0f0c9b4cab49cc02f87d65c8ee00847225c661 100644 --- a/llama-index-integrations/vector_stores/llama-index-vector-stores-qdrant/pyproject.toml +++ b/llama-index-integrations/vector_stores/llama-index-vector-stores-qdrant/pyproject.toml @@ -27,7 +27,7 @@ exclude = ["**/BUILD"] license = "MIT" name = "llama-index-vector-stores-qdrant" readme = "README.md" -version = "0.1.6" +version = "0.2.0" [tool.poetry.dependencies] python = ">=3.9,<3.13"