qdrant-haystack 6.0.0__py3-none-any.whl → 10.2.0__py3-none-any.whl

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.
@@ -1,198 +1,116 @@
1
+ from collections.abc import Callable
1
2
  from datetime import datetime
2
- from typing import List, Optional, Union
3
+ from typing import Any
3
4
 
4
5
  from haystack.utils.filters import COMPARISON_OPERATORS, LOGICAL_OPERATORS, FilterError
5
6
  from qdrant_client.http import models
6
7
 
7
- COMPARISON_OPERATORS = COMPARISON_OPERATORS.keys()
8
- LOGICAL_OPERATORS = LOGICAL_OPERATORS.keys()
9
-
10
8
 
11
9
  def convert_filters_to_qdrant(
12
- filter_term: Optional[Union[List[dict], dict, models.Filter]] = None, is_parent_call: bool = True
13
- ) -> Optional[Union[models.Filter, List[models.Filter], List[models.Condition]]]:
10
+ filter_term: list[dict[str, Any]] | dict[str, Any] | models.Filter | None = None,
11
+ ) -> models.Filter | None:
14
12
  """Converts Haystack filters to the format used by Qdrant.
15
13
 
16
14
  :param filter_term: the haystack filter to be converted to qdrant.
17
- :param is_parent_call: indicates if this is the top-level call to the function. If True, the function returns
18
- a single models.Filter object; if False, it may return a list of filters or conditions for further processing.
19
-
20
- :returns: a single Qdrant Filter in the parent call or a list of such Filters in recursive calls.
21
-
22
- :raises FilterError: If the invalid filter criteria is provided or if an unknown operator is encountered.
23
-
15
+ :returns: a single Qdrant Filter or None.
16
+ :raises FilterError: If invalid filter criteria is provided.
24
17
  """
25
-
26
18
  if isinstance(filter_term, models.Filter):
27
19
  return filter_term
28
20
  if not filter_term:
29
21
  return None
30
22
 
31
- must_clauses: List[models.Filter] = []
32
- should_clauses: List[models.Filter] = []
33
- must_not_clauses: List[models.Filter] = []
34
- # Indicates if there are multiple same LOGICAL OPERATORS on each level
35
- # and prevents them from being combined
36
- same_operator_flag = False
37
- conditions, qdrant_filter, current_level_operators = (
38
- [],
39
- [],
40
- [],
41
- )
42
-
43
23
  if isinstance(filter_term, dict):
44
24
  filter_term = [filter_term]
45
25
 
46
- # ======== IDENTIFY FILTER ITEMS ON EACH LEVEL ========
26
+ conditions = _process_filter_items(filter_term)
27
+
28
+ return _build_final_filter(conditions)
47
29
 
48
- for item in filter_term:
49
- operator = item.get("operator")
50
30
 
51
- # Check for repeated similar operators on each level
52
- same_operator_flag = operator in current_level_operators and operator in LOGICAL_OPERATORS
53
- if not same_operator_flag:
54
- current_level_operators.append(operator)
31
+ def _process_filter_items(filter_items: list[dict[str, Any]]) -> list[models.Condition]:
32
+ """Process a list of filter items and return all conditions."""
33
+ all_conditions: list[models.Condition] = []
55
34
 
35
+ for item in filter_items:
36
+ operator = item.get("operator")
56
37
  if operator is None:
57
38
  msg = "Operator not found in filters"
58
39
  raise FilterError(msg)
59
40
 
60
- if operator in LOGICAL_OPERATORS and "conditions" not in item:
61
- msg = f"'conditions' not found for '{operator}'"
41
+ if operator in LOGICAL_OPERATORS:
42
+ condition = _process_logical_operator(item)
43
+ if condition:
44
+ all_conditions.append(condition)
45
+ elif operator in COMPARISON_OPERATORS:
46
+ condition = _process_comparison_operator(item)
47
+ if condition:
48
+ all_conditions.append(condition)
49
+ else:
50
+ msg = f"Unknown operator {operator} used in filters"
62
51
  raise FilterError(msg)
63
52
 
64
- if operator in LOGICAL_OPERATORS:
65
- # Recursively process nested conditions
66
- current_filter = convert_filters_to_qdrant(item.get("conditions", []), is_parent_call=False) or []
67
-
68
- # When same_operator_flag is set to True,
69
- # ensure each clause is appended as an independent list to avoid merging distinct clauses.
70
- if operator == "AND":
71
- must_clauses = [must_clauses, current_filter] if same_operator_flag else must_clauses + current_filter
72
- elif operator == "OR":
73
- should_clauses = (
74
- [should_clauses, current_filter] if same_operator_flag else should_clauses + current_filter
75
- )
76
- elif operator == "NOT":
77
- must_not_clauses = (
78
- [must_not_clauses, current_filter] if same_operator_flag else must_not_clauses + current_filter
79
- )
53
+ return all_conditions
80
54
 
81
- elif operator in COMPARISON_OPERATORS:
82
- field = item.get("field")
83
- value = item.get("value")
84
- if field is None or value is None:
85
- msg = f"'field' or 'value' not found for '{operator}'"
86
- raise FilterError(msg)
87
55
 
88
- parsed_conditions = _parse_comparison_operation(comparison_operation=operator, key=field, value=value)
56
+ def _process_logical_operator(item: dict[str, Any]) -> models.Condition | None:
57
+ """Process a logical operator (AND, OR, NOT) and return the corresponding condition."""
58
+ operator = item["operator"]
59
+ conditions = item.get("conditions")
89
60
 
90
- # check if the parsed_conditions are models.Filter or models.Condition
91
- for condition in parsed_conditions:
92
- if isinstance(condition, models.Filter):
93
- qdrant_filter.append(condition)
94
- else:
95
- conditions.append(condition)
61
+ if not conditions:
62
+ msg = f"'conditions' not found for '{operator}'"
63
+ raise FilterError(msg)
96
64
 
97
- else:
98
- msg = f"Unknown operator {operator} used in filters"
99
- raise FilterError(msg)
65
+ # Recursively process nested conditions
66
+ nested_conditions = _process_filter_items(conditions)
100
67
 
101
- # ======== PROCESS FILTER ITEMS ON EACH LEVEL ========
102
-
103
- # If same logical operators have separate clauses, create separate filters
104
- if same_operator_flag:
105
- qdrant_filter = build_filters_for_repeated_operators(
106
- must_clauses, should_clauses, must_not_clauses, qdrant_filter
107
- )
108
-
109
- # else append a single Filter for existing clauses
110
- elif must_clauses or should_clauses or must_not_clauses:
111
- qdrant_filter.append(
112
- models.Filter(
113
- must=must_clauses or None,
114
- should=should_clauses or None,
115
- must_not=must_not_clauses or None,
116
- )
117
- )
118
-
119
- # In case of parent call, a single Filter is returned
120
- if is_parent_call:
121
- # If qdrant_filter has just a single Filter in parent call,
122
- # then it might be returned instead.
123
- if len(qdrant_filter) == 1 and isinstance(qdrant_filter[0], models.Filter):
124
- return qdrant_filter[0]
125
- else:
126
- must_clauses.extend(conditions)
127
- return models.Filter(
128
- must=must_clauses or None,
129
- should=should_clauses or None,
130
- must_not=must_not_clauses or None,
131
- )
68
+ if not nested_conditions:
69
+ return None
132
70
 
133
- # Store conditions of each level in output of the loop
134
- elif conditions:
135
- qdrant_filter.extend(conditions)
71
+ # Build the appropriate filter based on operator
72
+ if operator == "AND":
73
+ return models.Filter(must=nested_conditions)
74
+ elif operator == "OR":
75
+ return models.Filter(should=nested_conditions)
76
+ elif operator == "NOT":
77
+ return models.Filter(must_not=nested_conditions)
136
78
 
137
- return qdrant_filter
79
+ return None
138
80
 
139
81
 
140
- def build_filters_for_repeated_operators(
141
- must_clauses,
142
- should_clauses,
143
- must_not_clauses,
144
- qdrant_filter,
145
- ) -> List[models.Filter]:
146
- """
147
- Flattens the nested lists of clauses by creating separate Filters for each clause of a logical operator.
82
+ def _process_comparison_operator(item: dict[str, Any]) -> models.Condition | None:
83
+ """Process a comparison operator and return the corresponding condition."""
84
+ operator = item["operator"]
85
+ field = item.get("field")
86
+ value = item.get("value")
148
87
 
149
- :param must_clauses: a nested list of must clauses or an empty list.
150
- :param should_clauses: a nested list of should clauses or an empty list.
151
- :param must_not_clauses: a nested list of must_not clauses or an empty list.
152
- :param qdrant_filter: a list where the generated Filter objects will be appended.
153
- This list will be modified in-place.
88
+ if field is None or value is None:
89
+ msg = f"'field' or 'value' not found for '{operator}'"
90
+ raise FilterError(msg)
154
91
 
92
+ return _build_comparison_condition(operator, field, value)
155
93
 
156
- :returns: the modified `qdrant_filter` list with appended generated Filter objects.
157
- """
158
94
 
159
- if any(isinstance(i, list) for i in must_clauses):
160
- for i in must_clauses:
161
- qdrant_filter.append(
162
- models.Filter(
163
- must=i or None,
164
- should=should_clauses or None,
165
- must_not=must_not_clauses or None,
166
- )
167
- )
168
- if any(isinstance(i, list) for i in should_clauses):
169
- for i in should_clauses:
170
- qdrant_filter.append(
171
- models.Filter(
172
- must=must_clauses or None,
173
- should=i or None,
174
- must_not=must_not_clauses or None,
175
- )
176
- )
177
- if any(isinstance(i, list) for i in must_not_clauses):
178
- for i in must_clauses:
179
- qdrant_filter.append(
180
- models.Filter(
181
- must=must_clauses or None,
182
- should=should_clauses or None,
183
- must_not=i or None,
184
- )
185
- )
95
+ def _build_final_filter(conditions: list[models.Condition]) -> models.Filter | None:
96
+ """Build the final filter from a list of conditions."""
97
+ if not conditions:
98
+ return None
186
99
 
187
- return qdrant_filter
100
+ if len(conditions) == 1:
101
+ # If single condition and it's already a Filter, return it
102
+ if isinstance(conditions[0], models.Filter):
103
+ return conditions[0]
104
+ # Otherwise wrap it in a Filter
105
+ return models.Filter(must=[conditions[0]])
188
106
 
107
+ # Multiple conditions - combine with AND logic
108
+ return models.Filter(must=conditions)
189
109
 
190
- def _parse_comparison_operation(
191
- comparison_operation: str, key: str, value: Union[dict, List, str, float]
192
- ) -> List[models.Condition]:
193
- conditions: List[models.Condition] = []
194
110
 
195
- condition_builder_mapping = {
111
+ def _build_comparison_condition(operator: str, key: str, value: Any) -> models.Condition:
112
+ """Build a comparison condition based on operator, key, and value."""
113
+ condition_builders: dict[str, Callable[[str, Any], models.Condition]] = {
196
114
  "==": _build_eq_condition,
197
115
  "in": _build_in_condition,
198
116
  "!=": _build_ne_condition,
@@ -203,15 +121,12 @@ def _parse_comparison_operation(
203
121
  "<=": _build_lte_condition,
204
122
  }
205
123
 
206
- condition_builder = condition_builder_mapping.get(comparison_operation)
207
-
208
- if condition_builder is None:
209
- msg = f"Unknown operator {comparison_operation} used in filters"
210
- raise ValueError(msg)
211
-
212
- conditions.append(condition_builder(key, value))
124
+ builder = condition_builders.get(operator)
125
+ if builder is None:
126
+ msg = f"Unknown operator {operator} used in filters"
127
+ raise FilterError(msg)
213
128
 
214
- return conditions
129
+ return builder(key, value)
215
130
 
216
131
 
217
132
  def _build_eq_condition(key: str, value: models.ValueVariants) -> models.Condition:
@@ -220,7 +135,7 @@ def _build_eq_condition(key: str, value: models.ValueVariants) -> models.Conditi
220
135
  return models.FieldCondition(key=key, match=models.MatchValue(value=value))
221
136
 
222
137
 
223
- def _build_in_condition(key: str, value: List[models.ValueVariants]) -> models.Condition:
138
+ def _build_in_condition(key: str, value: list[models.ValueVariants]) -> models.Condition:
224
139
  if not isinstance(value, list):
225
140
  msg = f"Value {value} is not a list"
226
141
  raise FilterError(msg)
@@ -248,7 +163,7 @@ def _build_ne_condition(key: str, value: models.ValueVariants) -> models.Conditi
248
163
  )
249
164
 
250
165
 
251
- def _build_nin_condition(key: str, value: List[models.ValueVariants]) -> models.Condition:
166
+ def _build_nin_condition(key: str, value: list[models.ValueVariants]) -> models.Condition:
252
167
  if not isinstance(value, list):
253
168
  msg = f"Value {value} is not a list"
254
169
  raise FilterError(msg)
@@ -264,9 +179,10 @@ def _build_nin_condition(key: str, value: List[models.ValueVariants]) -> models.
264
179
  )
265
180
 
266
181
 
267
- def _build_lt_condition(key: str, value: Union[str, float, int]) -> models.Condition:
182
+ def _build_lt_condition(key: str, value: str | float | int) -> models.Condition:
268
183
  if isinstance(value, str) and is_datetime_string(value):
269
- return models.FieldCondition(key=key, range=models.DatetimeRange(lt=value))
184
+ dt_value = datetime.fromisoformat(value)
185
+ return models.FieldCondition(key=key, range=models.DatetimeRange(lt=dt_value))
270
186
 
271
187
  if isinstance(value, (int, float)):
272
188
  return models.FieldCondition(key=key, range=models.Range(lt=value))
@@ -275,9 +191,10 @@ def _build_lt_condition(key: str, value: Union[str, float, int]) -> models.Condi
275
191
  raise FilterError(msg)
276
192
 
277
193
 
278
- def _build_lte_condition(key: str, value: Union[str, float, int]) -> models.Condition:
194
+ def _build_lte_condition(key: str, value: str | float | int) -> models.Condition:
279
195
  if isinstance(value, str) and is_datetime_string(value):
280
- return models.FieldCondition(key=key, range=models.DatetimeRange(lte=value))
196
+ dt_value = datetime.fromisoformat(value)
197
+ return models.FieldCondition(key=key, range=models.DatetimeRange(lte=dt_value))
281
198
 
282
199
  if isinstance(value, (int, float)):
283
200
  return models.FieldCondition(key=key, range=models.Range(lte=value))
@@ -286,9 +203,10 @@ def _build_lte_condition(key: str, value: Union[str, float, int]) -> models.Cond
286
203
  raise FilterError(msg)
287
204
 
288
205
 
289
- def _build_gt_condition(key: str, value: Union[str, float, int]) -> models.Condition:
206
+ def _build_gt_condition(key: str, value: str | float | int) -> models.Condition:
290
207
  if isinstance(value, str) and is_datetime_string(value):
291
- return models.FieldCondition(key=key, range=models.DatetimeRange(gt=value))
208
+ dt_value = datetime.fromisoformat(value)
209
+ return models.FieldCondition(key=key, range=models.DatetimeRange(gt=dt_value))
292
210
 
293
211
  if isinstance(value, (int, float)):
294
212
  return models.FieldCondition(key=key, range=models.Range(gt=value))
@@ -297,9 +215,10 @@ def _build_gt_condition(key: str, value: Union[str, float, int]) -> models.Condi
297
215
  raise FilterError(msg)
298
216
 
299
217
 
300
- def _build_gte_condition(key: str, value: Union[str, float, int]) -> models.Condition:
218
+ def _build_gte_condition(key: str, value: str | float | int) -> models.Condition:
301
219
  if isinstance(value, str) and is_datetime_string(value):
302
- return models.FieldCondition(key=key, range=models.DatetimeRange(gte=value))
220
+ dt_value = datetime.fromisoformat(value)
221
+ return models.FieldCondition(key=key, range=models.DatetimeRange(gte=dt_value))
303
222
 
304
223
  if isinstance(value, (int, float)):
305
224
  return models.FieldCondition(key=key, range=models.Range(gte=value))
@@ -1,3 +1,5 @@
1
+ # mypy: disable-error-code="assignment, arg-type"
2
+
1
3
  import logging
2
4
  import time
3
5
 
@@ -5,12 +7,13 @@ from qdrant_client.http import models
5
7
 
6
8
  from haystack_integrations.document_stores.qdrant import QdrantDocumentStore
7
9
 
10
+ # using Haystack logging is problematic here
8
11
  logger = logging.getLogger(__name__)
9
12
  logger.addHandler(logging.StreamHandler())
10
13
  logger.setLevel(logging.INFO)
11
14
 
12
15
 
13
- def migrate_to_sparse_embeddings_support(old_document_store: QdrantDocumentStore, new_index: str):
16
+ def migrate_to_sparse_embeddings_support(old_document_store: QdrantDocumentStore, new_index: str) -> None: # type: ignore
14
17
  """
15
18
  Utility function to migrate an existing `QdrantDocumentStore` to a new one with support for sparse embeddings.
16
19
 
@@ -60,8 +63,10 @@ def migrate_to_sparse_embeddings_support(old_document_store: QdrantDocumentStore
60
63
  init_parameters["recreate_index"] = True
61
64
 
62
65
  new_document_store = QdrantDocumentStore(**init_parameters)
66
+ new_document_store._initialize_client()
67
+ assert new_document_store._client is not None
63
68
 
64
- client = new_document_store.client
69
+ client = new_document_store._client
65
70
 
66
71
  original_indexing_threshold = client.get_collection(
67
72
  collection_name=new_index
@@ -114,7 +119,7 @@ def migrate_to_sparse_embeddings_support(old_document_store: QdrantDocumentStore
114
119
 
115
120
  message = (
116
121
  f"Points transmitted: {points_transmitted}/{total_points}\n"
117
- f"Percent done {points_transmitted/total_points*100:.2f}%\n"
122
+ f"Percent done {points_transmitted / total_points * 100:.2f}%\n"
118
123
  f"Time elapsed: {time.time() - start:.2f} seconds\n"
119
124
  f"Time remaining: {(((time.time() - start) / points_transmitted) * points_remaining) / 60:.2f} minutes\n"
120
125
  f"Current offset: {next_page_offset}\n"
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: qdrant-haystack
3
- Version: 6.0.0
3
+ Version: 10.2.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,15 @@ 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.8
15
- Classifier: Programming Language :: Python :: 3.9
16
14
  Classifier: Programming Language :: Python :: 3.10
17
15
  Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
18
  Classifier: Programming Language :: Python :: Implementation :: CPython
19
19
  Classifier: Programming Language :: Python :: Implementation :: PyPy
20
- Requires-Python: >=3.8
21
- Requires-Dist: haystack-ai
22
- Requires-Dist: qdrant-client>=1.10.0
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: haystack-ai>=2.22.0
22
+ Requires-Dist: qdrant-client>=1.12.0
23
23
  Description-Content-Type: text/markdown
24
24
 
25
25
  # qdrant-haystack
@@ -27,26 +27,11 @@ Description-Content-Type: text/markdown
27
27
  [![PyPI - Version](https://img.shields.io/pypi/v/qdrant-haystack.svg)](https://pypi.org/project/qdrant-haystack)
28
28
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/qdrant-haystack.svg)](https://pypi.org/project/qdrant-haystack)
29
29
 
30
- -----
30
+ - [Integration page](https://haystack.deepset.ai/integrations/qdrant-document-store)
31
+ - [Changelog](https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/qdrant/CHANGELOG.md)
31
32
 
32
- **Table of Contents**
33
+ ---
33
34
 
34
- - [Installation](#installation)
35
- - [License](#license)
35
+ ## Contributing
36
36
 
37
- ## Installation
38
-
39
- ```console
40
- pip install qdrant-haystack
41
- ```
42
-
43
- ## Testing
44
- The test suites use Qdrant's in-memory instance. No additional steps required.
45
-
46
- ```console
47
- hatch run test
48
- ```
49
-
50
- ## License
51
-
52
- `qdrant-haystack` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
37
+ Refer to the general [Contribution Guidelines](https://github.com/deepset-ai/haystack-core-integrations/blob/main/CONTRIBUTING.md).
@@ -0,0 +1,13 @@
1
+ haystack_integrations/components/retrievers/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ haystack_integrations/components/retrievers/qdrant/__init__.py,sha256=AE1hdw4sqb0rTSqfAxKCRUOZVE8gbHdQ1wDccdN86hc,313
3
+ haystack_integrations/components/retrievers/qdrant/retriever.py,sha256=UFloH86KQGuLPu3dAVf7bS6EgTVX0FzjdxEqaSMvu4k,32593
4
+ haystack_integrations/document_stores/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ haystack_integrations/document_stores/qdrant/__init__.py,sha256=kUGc5uewqArhmVR-JqB_NmJ4kNkTIQIvYDNSoO2ELn0,302
6
+ haystack_integrations/document_stores/qdrant/converters.py,sha256=Rm5LI3Aw5gBuXwpZzvaECvpLhgSEI3zp9Va97-SfipU,2605
7
+ haystack_integrations/document_stores/qdrant/document_store.py,sha256=XYKLXzhHdnzK6q4LFbAAxF3IBPVXnjkTMaIdC1hl9Iw,103894
8
+ haystack_integrations/document_stores/qdrant/filters.py,sha256=uiac8igBikWb6hWpiS6SaE9N1GX52II2tOEGLC4izb0,8319
9
+ haystack_integrations/document_stores/qdrant/migrate_to_sparse.py,sha256=DcQ9_Ilx1fgXOzjsUDpuaM9TKh2utmVm2hYFn-V2CkQ,5129
10
+ qdrant_haystack-10.2.0.dist-info/METADATA,sha256=YfmwvqF3VOLrFWDS2znUhVUFnLmRBO59TPtra_M2XZs,1829
11
+ qdrant_haystack-10.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
12
+ qdrant_haystack-10.2.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
13
+ qdrant_haystack-10.2.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.25.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,11 +0,0 @@
1
- haystack_integrations/components/retrievers/qdrant/__init__.py,sha256=IRjcM4f8b5eKFEMn8tn6h6RrfslEGP3WafU7mrzNzQM,313
2
- haystack_integrations/components/retrievers/qdrant/retriever.py,sha256=VsQVsvf79imTCdWUKikUxpjczl5oxOV64a91aGXZwpE,21997
3
- haystack_integrations/document_stores/qdrant/__init__.py,sha256=kUGc5uewqArhmVR-JqB_NmJ4kNkTIQIvYDNSoO2ELn0,302
4
- haystack_integrations/document_stores/qdrant/converters.py,sha256=2hcuI3kty1dVHzX1WGXxEtlrnZ9E8TAG56XATCFa6Pw,2491
5
- haystack_integrations/document_stores/qdrant/document_store.py,sha256=lljz3ksd6naKM9bsFaaaKLC1W6ZkyCCLFVR44WaQ1oA,42552
6
- haystack_integrations/document_stores/qdrant/filters.py,sha256=Nv_eKIYKwUWvldJfa0omfFQ0kgqi6L3DUFeMuIWziOY,11751
7
- haystack_integrations/document_stores/qdrant/migrate_to_sparse.py,sha256=yhZr4GB6N1S-Ikzl52hpuZt2aHNIb4leqFDhVMU3Uho,4910
8
- qdrant_haystack-6.0.0.dist-info/METADATA,sha256=2EO3rBoGCI7Umy8XPhXj9eE8bSbYLDXUErdtA9yqmtQ,1863
9
- qdrant_haystack-6.0.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
10
- qdrant_haystack-6.0.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
11
- qdrant_haystack-6.0.0.dist-info/RECORD,,