qdrant-haystack 9.5.0__tar.gz → 10.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/CHANGELOG.md +23 -0
  2. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/PKG-INFO +3 -4
  3. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/pyproject.toml +3 -9
  4. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/src/haystack_integrations/components/retrievers/qdrant/retriever.py +56 -56
  5. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/src/haystack_integrations/document_stores/qdrant/converters.py +1 -2
  6. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/src/haystack_integrations/document_stores/qdrant/document_store.py +465 -66
  7. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/src/haystack_integrations/document_stores/qdrant/filters.py +11 -10
  8. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/tests/test_document_store.py +143 -2
  9. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/tests/test_document_store_async.py +155 -2
  10. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/.gitignore +0 -0
  11. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/LICENSE.txt +0 -0
  12. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/README.md +0 -0
  13. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/examples/embedding_retrieval.py +0 -0
  14. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/pydoc/config_docusaurus.yml +0 -0
  15. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/src/haystack_integrations/components/retrievers/py.typed +0 -0
  16. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/src/haystack_integrations/components/retrievers/qdrant/__init__.py +0 -0
  17. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/src/haystack_integrations/document_stores/py.typed +0 -0
  18. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/src/haystack_integrations/document_stores/qdrant/__init__.py +0 -0
  19. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/src/haystack_integrations/document_stores/qdrant/migrate_to_sparse.py +0 -0
  20. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/tests/__init__.py +0 -0
  21. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/tests/conftest.py +0 -0
  22. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/tests/test_converters.py +0 -0
  23. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/tests/test_dict_converters.py +0 -0
  24. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/tests/test_embedding_retriever.py +0 -0
  25. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/tests/test_filters.py +0 -0
  26. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/tests/test_hybrid_retriever.py +0 -0
  27. {qdrant_haystack-9.5.0 → qdrant_haystack-10.1.0}/tests/test_sparse_embedding_retriever.py +0 -0
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## [unreleased]
4
+
5
+ ### 🧹 Chores
6
+
7
+ - Make fmt command more forgiving (#2671)
8
+ - [**breaking**] Qdrant - drop Python 3.9 and use X|Y typing (#2726)
9
+
10
+
11
+ ## [integrations/qdrant-v9.5.0] - 2026-01-07
12
+
13
+ ### 🚀 Features
14
+
15
+ - Adding `delete_by_filter()` and `update_by_filter()` to `QdrantDocumentStore` (#2650)
16
+
17
+ ### 🐛 Bug Fixes
18
+
19
+ - Fix types for qdrant-client 1.16.1 (#2561)
20
+
21
+ ### 🧹 Chores
22
+
23
+ - Remove Readme API CI workflow and configs (#2573)
24
+
25
+
3
26
  ## [integrations/qdrant-v9.4.0] - 2025-11-18
4
27
 
5
28
  ### 🧹 Chores
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qdrant-haystack
3
- Version: 9.5.0
3
+ Version: 10.1.0
4
4
  Summary: An integration of Qdrant ANN vector database backend with Haystack
5
5
  Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations
6
6
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/qdrant/README.md
@@ -11,15 +11,14 @@ License-File: LICENSE.txt
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: License :: OSI Approved :: Apache Software License
13
13
  Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3.9
15
14
  Classifier: Programming Language :: Python :: 3.10
16
15
  Classifier: Programming Language :: Python :: 3.11
17
16
  Classifier: Programming Language :: Python :: 3.12
18
17
  Classifier: Programming Language :: Python :: 3.13
19
18
  Classifier: Programming Language :: Python :: Implementation :: CPython
20
19
  Classifier: Programming Language :: Python :: Implementation :: PyPy
21
- Requires-Python: >=3.9
22
- Requires-Dist: haystack-ai>=2.11.0
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: haystack-ai>=2.22.0
23
22
  Requires-Dist: qdrant-client>=1.12.0
24
23
  Description-Content-Type: text/markdown
25
24
 
@@ -7,7 +7,7 @@ name = "qdrant-haystack"
7
7
  dynamic = ["version"]
8
8
  description = 'An integration of Qdrant ANN vector database backend with Haystack'
9
9
  readme = "README.md"
10
- requires-python = ">=3.9"
10
+ requires-python = ">=3.10"
11
11
  license = "Apache-2.0"
12
12
  keywords = []
13
13
  authors = [
@@ -18,7 +18,6 @@ classifiers = [
18
18
  "License :: OSI Approved :: Apache Software License",
19
19
  "Development Status :: 4 - Beta",
20
20
  "Programming Language :: Python",
21
- "Programming Language :: Python :: 3.9",
22
21
  "Programming Language :: Python :: 3.10",
23
22
  "Programming Language :: Python :: 3.11",
24
23
  "Programming Language :: Python :: 3.12",
@@ -26,7 +25,7 @@ classifiers = [
26
25
  "Programming Language :: Python :: Implementation :: CPython",
27
26
  "Programming Language :: Python :: Implementation :: PyPy",
28
27
  ]
29
- dependencies = ["haystack-ai>=2.11.0", "qdrant-client>=1.12.0"]
28
+ dependencies = ["haystack-ai>=2.22.0", "qdrant-client>=1.12.0"]
30
29
 
31
30
  [project.urls]
32
31
  Source = "https://github.com/deepset-ai/haystack-core-integrations"
@@ -50,7 +49,7 @@ dependencies = ["haystack-pydoc-tools", "ruff"]
50
49
 
51
50
  [tool.hatch.envs.default.scripts]
52
51
  docs = ["pydoc-markdown pydoc/config_docusaurus.yml"]
53
- fmt = "ruff check --fix {args} && ruff format {args}"
52
+ fmt = "ruff check --fix {args}; ruff format {args}"
54
53
  fmt-check = "ruff check {args} && ruff format --check {args}"
55
54
 
56
55
  [tool.hatch.envs.test]
@@ -80,7 +79,6 @@ disallow_incomplete_defs = true
80
79
 
81
80
 
82
81
  [tool.ruff]
83
- target-version = "py39"
84
82
  line-length = 120
85
83
 
86
84
  [tool.ruff.lint]
@@ -132,10 +130,6 @@ ignore = [
132
130
  # Ignore assertions
133
131
  "S101",
134
132
  ]
135
- unfixable = [
136
- # Don't touch unused imports
137
- "F401",
138
- ]
139
133
 
140
134
  [tool.ruff.lint.flake8-tidy-imports]
141
135
  ban-relative-imports = "parents"
@@ -1,4 +1,4 @@
1
- from typing import Any, Optional, Union
1
+ from typing import Any
2
2
 
3
3
  from haystack import Document, component, default_from_dict, default_to_dict
4
4
  from haystack.dataclasses.sparse_embedding import SparseEmbedding
@@ -43,14 +43,14 @@ class QdrantEmbeddingRetriever:
43
43
  def __init__(
44
44
  self,
45
45
  document_store: QdrantDocumentStore,
46
- filters: Optional[Union[dict[str, Any], models.Filter]] = None,
46
+ filters: dict[str, Any] | models.Filter | None = None,
47
47
  top_k: int = 10,
48
48
  scale_score: bool = False,
49
49
  return_embedding: bool = False,
50
- filter_policy: Union[str, FilterPolicy] = FilterPolicy.REPLACE,
51
- score_threshold: Optional[float] = None,
52
- group_by: Optional[str] = None,
53
- group_size: Optional[int] = None,
50
+ filter_policy: str | FilterPolicy = FilterPolicy.REPLACE,
51
+ score_threshold: float | None = None,
52
+ group_by: str | None = None,
53
+ group_size: int | None = None,
54
54
  ) -> None:
55
55
  """
56
56
  Create a QdrantEmbeddingRetriever component.
@@ -134,13 +134,13 @@ class QdrantEmbeddingRetriever:
134
134
  def run(
135
135
  self,
136
136
  query_embedding: list[float],
137
- filters: Optional[Union[dict[str, Any], models.Filter]] = None,
138
- top_k: Optional[int] = None,
139
- scale_score: Optional[bool] = None,
140
- return_embedding: Optional[bool] = None,
141
- score_threshold: Optional[float] = None,
142
- group_by: Optional[str] = None,
143
- group_size: Optional[int] = None,
137
+ filters: dict[str, Any] | models.Filter | None = None,
138
+ top_k: int | None = None,
139
+ scale_score: bool | None = None,
140
+ return_embedding: bool | None = None,
141
+ score_threshold: float | None = None,
142
+ group_by: str | None = None,
143
+ group_size: int | None = None,
144
144
  ) -> dict[str, list[Document]]:
145
145
  """
146
146
  Run the Embedding Retriever on the given input data.
@@ -189,13 +189,13 @@ class QdrantEmbeddingRetriever:
189
189
  async def run_async(
190
190
  self,
191
191
  query_embedding: list[float],
192
- filters: Optional[Union[dict[str, Any], models.Filter]] = None,
193
- top_k: Optional[int] = None,
194
- scale_score: Optional[bool] = None,
195
- return_embedding: Optional[bool] = None,
196
- score_threshold: Optional[float] = None,
197
- group_by: Optional[str] = None,
198
- group_size: Optional[int] = None,
192
+ filters: dict[str, Any] | models.Filter | None = None,
193
+ top_k: int | None = None,
194
+ scale_score: bool | None = None,
195
+ return_embedding: bool | None = None,
196
+ score_threshold: float | None = None,
197
+ group_by: str | None = None,
198
+ group_size: int | None = None,
199
199
  ) -> dict[str, list[Document]]:
200
200
  """
201
201
  Asynchronously run the Embedding Retriever on the given input data.
@@ -271,14 +271,14 @@ class QdrantSparseEmbeddingRetriever:
271
271
  def __init__(
272
272
  self,
273
273
  document_store: QdrantDocumentStore,
274
- filters: Optional[Union[dict[str, Any], models.Filter]] = None,
274
+ filters: dict[str, Any] | models.Filter | None = None,
275
275
  top_k: int = 10,
276
276
  scale_score: bool = False,
277
277
  return_embedding: bool = False,
278
- filter_policy: Union[str, FilterPolicy] = FilterPolicy.REPLACE,
279
- score_threshold: Optional[float] = None,
280
- group_by: Optional[str] = None,
281
- group_size: Optional[int] = None,
278
+ filter_policy: str | FilterPolicy = FilterPolicy.REPLACE,
279
+ score_threshold: float | None = None,
280
+ group_by: str | None = None,
281
+ group_size: int | None = None,
282
282
  ) -> None:
283
283
  """
284
284
  Create a QdrantSparseEmbeddingRetriever component.
@@ -362,13 +362,13 @@ class QdrantSparseEmbeddingRetriever:
362
362
  def run(
363
363
  self,
364
364
  query_sparse_embedding: SparseEmbedding,
365
- filters: Optional[Union[dict[str, Any], models.Filter]] = None,
366
- top_k: Optional[int] = None,
367
- scale_score: Optional[bool] = None,
368
- return_embedding: Optional[bool] = None,
369
- score_threshold: Optional[float] = None,
370
- group_by: Optional[str] = None,
371
- group_size: Optional[int] = None,
365
+ filters: dict[str, Any] | models.Filter | None = None,
366
+ top_k: int | None = None,
367
+ scale_score: bool | None = None,
368
+ return_embedding: bool | None = None,
369
+ score_threshold: float | None = None,
370
+ group_by: str | None = None,
371
+ group_size: int | None = None,
372
372
  ) -> dict[str, list[Document]]:
373
373
  """
374
374
  Run the Sparse Embedding Retriever on the given input data.
@@ -422,13 +422,13 @@ class QdrantSparseEmbeddingRetriever:
422
422
  async def run_async(
423
423
  self,
424
424
  query_sparse_embedding: SparseEmbedding,
425
- filters: Optional[Union[dict[str, Any], models.Filter]] = None,
426
- top_k: Optional[int] = None,
427
- scale_score: Optional[bool] = None,
428
- return_embedding: Optional[bool] = None,
429
- score_threshold: Optional[float] = None,
430
- group_by: Optional[str] = None,
431
- group_size: Optional[int] = None,
425
+ filters: dict[str, Any] | models.Filter | None = None,
426
+ top_k: int | None = None,
427
+ scale_score: bool | None = None,
428
+ return_embedding: bool | None = None,
429
+ score_threshold: float | None = None,
430
+ group_by: str | None = None,
431
+ group_size: int | None = None,
432
432
  ) -> dict[str, list[Document]]:
433
433
  """
434
434
  Asynchronously run the Sparse Embedding Retriever on the given input data.
@@ -515,13 +515,13 @@ class QdrantHybridRetriever:
515
515
  def __init__(
516
516
  self,
517
517
  document_store: QdrantDocumentStore,
518
- filters: Optional[Union[dict[str, Any], models.Filter]] = None,
518
+ filters: dict[str, Any] | models.Filter | None = None,
519
519
  top_k: int = 10,
520
520
  return_embedding: bool = False,
521
- filter_policy: Union[str, FilterPolicy] = FilterPolicy.REPLACE,
522
- score_threshold: Optional[float] = None,
523
- group_by: Optional[str] = None,
524
- group_size: Optional[int] = None,
521
+ filter_policy: str | FilterPolicy = FilterPolicy.REPLACE,
522
+ score_threshold: float | None = None,
523
+ group_by: str | None = None,
524
+ group_size: int | None = None,
525
525
  ) -> None:
526
526
  """
527
527
  Create a QdrantHybridRetriever component.
@@ -600,12 +600,12 @@ class QdrantHybridRetriever:
600
600
  self,
601
601
  query_embedding: list[float],
602
602
  query_sparse_embedding: SparseEmbedding,
603
- filters: Optional[Union[dict[str, Any], models.Filter]] = None,
604
- top_k: Optional[int] = None,
605
- return_embedding: Optional[bool] = None,
606
- score_threshold: Optional[float] = None,
607
- group_by: Optional[str] = None,
608
- group_size: Optional[int] = None,
603
+ filters: dict[str, Any] | models.Filter | None = None,
604
+ top_k: int | None = None,
605
+ return_embedding: bool | None = None,
606
+ score_threshold: float | None = None,
607
+ group_by: str | None = None,
608
+ group_size: int | None = None,
609
609
  ) -> dict[str, list[Document]]:
610
610
  """
611
611
  Run the Sparse Embedding Retriever on the given input data.
@@ -660,12 +660,12 @@ class QdrantHybridRetriever:
660
660
  self,
661
661
  query_embedding: list[float],
662
662
  query_sparse_embedding: SparseEmbedding,
663
- filters: Optional[Union[dict[str, Any], models.Filter]] = None,
664
- top_k: Optional[int] = None,
665
- return_embedding: Optional[bool] = None,
666
- score_threshold: Optional[float] = None,
667
- group_by: Optional[str] = None,
668
- group_size: Optional[int] = None,
663
+ filters: dict[str, Any] | models.Filter | None = None,
664
+ top_k: int | None = None,
665
+ return_embedding: bool | None = None,
666
+ score_threshold: float | None = None,
667
+ group_by: str | None = None,
668
+ group_size: int | None = None,
669
669
  ) -> dict[str, list[Document]]:
670
670
  """
671
671
  Asynchronously run the Sparse Embedding Retriever on the given input data.
@@ -1,5 +1,4 @@
1
1
  import uuid
2
- from typing import Union
3
2
 
4
3
  from haystack import logging
5
4
  from haystack.dataclasses import Document
@@ -58,7 +57,7 @@ def convert_id(_id: str) -> str:
58
57
  return uuid.uuid5(UUID_NAMESPACE, _id).hex
59
58
 
60
59
 
61
- QdrantPoint = Union[rest.ScoredPoint, rest.Record]
60
+ QdrantPoint = rest.ScoredPoint | rest.Record
62
61
 
63
62
 
64
63
  def convert_qdrant_point_to_haystack_document(point: QdrantPoint, use_sparse_embeddings: bool) -> Document: