weaviate-haystack 7.8.0__tar.gz → 7.9.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 (31) hide show
  1. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/CHANGELOG.md +55 -14
  2. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/PKG-INFO +2 -2
  3. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/docker-compose.yml +14 -2
  4. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/pyproject.toml +1 -1
  5. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/src/haystack_integrations/document_stores/weaviate/document_store.py +49 -4
  6. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/test_document_store.py +86 -3
  7. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/.gitignore +0 -0
  8. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/LICENSE.txt +0 -0
  9. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/README.md +0 -0
  10. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/pydoc/config_docusaurus.yml +0 -0
  11. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/src/haystack_integrations/components/retrievers/py.typed +0 -0
  12. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/src/haystack_integrations/components/retrievers/weaviate/__init__.py +0 -0
  13. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/src/haystack_integrations/components/retrievers/weaviate/bm25_retriever.py +0 -0
  14. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/src/haystack_integrations/components/retrievers/weaviate/embedding_retriever.py +0 -0
  15. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/src/haystack_integrations/components/retrievers/weaviate/hybrid_retriever.py +0 -0
  16. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/src/haystack_integrations/document_stores/py.typed +0 -0
  17. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/src/haystack_integrations/document_stores/weaviate/__init__.py +0 -0
  18. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/src/haystack_integrations/document_stores/weaviate/_filters.py +0 -0
  19. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/src/haystack_integrations/document_stores/weaviate/auth.py +0 -0
  20. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/__init__.py +0 -0
  21. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/conftest.py +0 -0
  22. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/test_auth.py +0 -0
  23. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/test_bm25_retriever.py +0 -0
  24. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/test_bm25_retriever_async.py +0 -0
  25. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/test_document_store_async.py +0 -0
  26. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/test_embedding_retriever.py +0 -0
  27. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/test_embedding_retriever_async.py +0 -0
  28. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/test_files/robot1.jpg +0 -0
  29. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/test_filters.py +0 -0
  30. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/test_hybrid_retriever.py +0 -0
  31. {weaviate_haystack-7.8.0 → weaviate_haystack-7.9.0}/tests/test_hybrid_retriever_async.py +0 -0
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [integrations/weaviate-v7.8.0] - 2026-09-01
4
+
5
+ ### 🐛 Bug Fixes
6
+
7
+ - `Weaviate` match `search_term` against metadata field value, not content + default size value set to 10 (#3643)
8
+ - Fix new issues raised by ruff 0.16.0 (#3670)
9
+ - `WeaviateDocumentStore` get_metadata_field_unique_values setting list of values to return to `Any` (#3708)
10
+ - Weaviate adding optional parameter `filters` to `get_metadata_field_unique_values()` (#3741)
11
+ - Standardize license files (#3771)
12
+
13
+ ### 🧪 Testing
14
+
15
+ - `WeaviateDocumentStore` removing duplicated tests already covered by haystack Mixin tests (#3787)
16
+
17
+
3
18
  ## [integrations/weaviate-v7.7.0] - 2026-07-22
4
19
 
5
20
  ### 🚜 Refactor
@@ -207,21 +222,20 @@
207
222
 
208
223
  ### 🧹 Chores
209
224
 
210
- - Weaviate - remove legacy filter support (#1070)
211
225
  - Update changelog after removing legacy filters (#1083)
212
226
  - Update ruff linting scripts and settings (#1105)
213
227
 
228
+ ## [integrations/weaviate-v3.0.0] - 2024-09-12
214
229
 
215
- ## [integrations/weaviate-v2.2.1] - 2024-09-07
230
+ ### 🧹 Chores
216
231
 
217
- ### 🚀 Features
232
+ - Weaviate - remove legacy filter support (#1070)
218
233
 
219
- - Add filter_policy to weaviate integration (#824)
234
+
235
+ ## [integrations/weaviate-v2.2.1] - 2024-09-07
220
236
 
221
237
  ### 🐛 Bug Fixes
222
238
 
223
- - Weaviate filter error (#811)
224
- - Fix connection to Weaviate Cloud Service (#624)
225
239
  - Pin weaviate-client (#1046)
226
240
  - Weaviate - fix connection issues with some WCS URLs (#1058)
227
241
 
@@ -229,9 +243,27 @@
229
243
 
230
244
  - Do not retry tests in `hatch run test` command (#954)
231
245
 
232
- ### ⚙️ CI
246
+ ### 🌀 Miscellaneous
233
247
 
234
- - Retry tests to reduce flakyness (#836)
248
+ - Chore: weaviate - ruff update, don't ruff tests (#986)
249
+
250
+ ## [integrations/weaviate-v2.2.0] - 2024-08-02
251
+
252
+ ### 🌀 Miscellaneous
253
+
254
+ - Fix: Weaviate: Use collections.list_all instead of collections._get_all (#921)
255
+
256
+ ## [integrations/weaviate-v2.1.3] - 2024-07-17
257
+
258
+ ### 🌀 Miscellaneous
259
+
260
+ - Fix: `weaviate` - Fallback to default filter policy when deserializing retrievers without the init parameter (#903)
261
+
262
+ ## [integrations/weaviate-v2.1.2] - 2024-07-15
263
+
264
+ ### 🚀 Features
265
+
266
+ - Add filter_policy to weaviate integration (#824)
235
267
 
236
268
  ### 🧹 Chores
237
269
 
@@ -239,15 +271,24 @@
239
271
 
240
272
  ### 🌀 Miscellaneous
241
273
 
274
+ - Chore: Minor retriever pydoc fix (#884)
275
+
276
+ ## [integrations/weaviate-v2.1.1] - 2024-06-25
277
+
278
+ ### 🐛 Bug Fixes
279
+
280
+ - Weaviate filter error (#811)
281
+ - Fix connection to Weaviate Cloud Service (#624)
282
+
283
+ ### ⚙️ CI
284
+
285
+ - Retry tests to reduce flakyness (#836)
286
+
287
+ ### 🌀 Miscellaneous
288
+
242
289
  - Handle connection to WCS and add tests
243
290
  - Revert "Handle connection to WCS and add tests"
244
-
245
- This reverts commit f48802b2ce612896fd06a13cf33dffd9f77a8859.
246
291
  - Ci: install `pytest-rerunfailures` where needed; add retry config to `test-cov` script (#845)
247
- - Chore: Minor retriever pydoc fix (#884)
248
- - Fix: `weaviate` - Fallback to default filter policy when deserializing retrievers without the init parameter (#903)
249
- - Fix: Weaviate: Use collections.list_all instead of collections._get_all (#921)
250
- - Chore: weaviate - ruff update, don't ruff tests (#986)
251
292
 
252
293
  ## [integrations/weaviate-v2.1.0] - 2024-06-10
253
294
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: weaviate-haystack
3
- Version: 7.8.0
3
+ Version: 7.9.0
4
4
  Summary: An integration of Weaviate vector database 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/weaviate/README.md
@@ -21,7 +21,7 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
21
21
  Requires-Python: >=3.10
22
22
  Requires-Dist: haystack-ai>=2.28.0
23
23
  Requires-Dist: python-dateutil>=2.7.0
24
- Requires-Dist: weaviate-client>=4.20
24
+ Requires-Dist: weaviate-client>=4.23.0
25
25
  Description-Content-Type: text/markdown
26
26
 
27
27
  # weaviate-haystack
@@ -7,7 +7,7 @@ services:
7
7
  - '8080'
8
8
  - --scheme
9
9
  - http
10
- image: semitechnologies/weaviate:1.36.2
10
+ image: cr.weaviate.io/semitechnologies/weaviate:1.39.4
11
11
  ports:
12
12
  - 8080:8080
13
13
  - 50051:50051
@@ -18,4 +18,16 @@ services:
18
18
  PERSISTENCE_DATA_PATH: '/var/lib/weaviate'
19
19
  DEFAULT_VECTORIZER_MODULE: 'none'
20
20
  ENABLE_MODULES: ''
21
- CLUSTER_HOSTNAME: 'node1'
21
+ CLUSTER_HOSTNAME: 'node1'
22
+ healthcheck:
23
+ test:
24
+ - CMD
25
+ - busybox
26
+ - wget
27
+ - -q
28
+ - -O
29
+ - '-'
30
+ - http://127.0.0.1:8080/v1/.well-known/ready
31
+ interval: 5s
32
+ timeout: 3s
33
+ retries: 20
@@ -25,7 +25,7 @@ classifiers = [
25
25
  ]
26
26
  dependencies = [
27
27
  "haystack-ai>=2.28.0",
28
- "weaviate-client>=4.20",
28
+ "weaviate-client>=4.23.0",
29
29
  "python-dateutil>=2.7.0",
30
30
  ]
31
31
 
@@ -4,6 +4,7 @@
4
4
 
5
5
  import base64
6
6
  import datetime
7
+ import importlib.metadata
7
8
  import json
8
9
  from contextlib import suppress
9
10
  from dataclasses import asdict
@@ -38,6 +39,27 @@ from .auth import AuthCredentials
38
39
 
39
40
  logger = logging.getLogger(__name__)
40
41
 
42
+ # Weaviate tracks which framework integrations talk to it through this header, so that adoption of
43
+ # weaviate-haystack shows up in Weaviate's own telemetry. See https://github.com/weaviate/weaviate/pull/10535.
44
+ _INTEGRATION_HEADER = "X-Weaviate-Client-Integration"
45
+ _INTEGRATION_NAME = "haystack-python"
46
+ _PACKAGE_NAME = "weaviate-haystack"
47
+
48
+
49
+ def _integration_header_value() -> str:
50
+ """
51
+ Builds the value of the Weaviate client integration header.
52
+
53
+ :returns:
54
+ A `<name>/<version>` string. The version falls back to `unknown` when the package metadata is
55
+ unavailable, for example when running from a source checkout that was never installed.
56
+ """
57
+ try:
58
+ version = importlib.metadata.version(_PACKAGE_NAME)
59
+ except importlib.metadata.PackageNotFoundError:
60
+ version = "unknown"
61
+ return f"{_INTEGRATION_NAME}/{version}"
62
+
41
63
 
42
64
  # This is the default collection properties for Weaviate.
43
65
  # It's a list of properties that will be created on the collection.
@@ -144,6 +166,9 @@ class WeaviateDocumentStore:
144
166
  ```
145
167
  {"X-OpenAI-Api-Key": "<THE-KEY>"}, {"X-HuggingFace-Api-Key": "<THE-KEY>"}
146
168
  ```
169
+ Every connection also carries `X-Weaviate-Client-Integration: haystack-python/<version>`, which
170
+ identifies this integration in Weaviate's telemetry. Supplying that header here, in any casing,
171
+ overrides it.
147
172
  :param embedded_options:
148
173
  If set, create an embedded Weaviate cluster inside the client. For a full list of options see
149
174
  `weaviate.embedded.EmbeddedOptions`.
@@ -183,6 +208,26 @@ class WeaviateDocumentStore:
183
208
  "properties", DOCUMENT_COLLECTION_PROPERTIES
184
209
  )
185
210
 
211
+ def _connection_headers(self) -> dict[str, Any]:
212
+ """
213
+ Builds the headers passed to the Weaviate client.
214
+
215
+ Merges the integration identification header into the user supplied `additional_headers`. A user
216
+ supplied value for the same header wins, so the header can be overridden or suppressed. The merged
217
+ headers are deliberately not stored on the instance: `to_dict()` must keep serializing only the
218
+ headers the user actually passed, so that a serialized pipeline does not bake in the version of
219
+ `weaviate-haystack` that happened to write it.
220
+
221
+ :returns:
222
+ The headers to pass to the Weaviate client.
223
+ """
224
+ headers: dict[str, Any] = dict(self._additional_headers) if self._additional_headers else {}
225
+ # The comparison is case insensitive because gRPC metadata keys are case sensitive: a user supplied
226
+ # "x-weaviate-client-integration" would otherwise end up alongside our own spelling of the header.
227
+ if not any(key.lower() == _INTEGRATION_HEADER.lower() for key in headers):
228
+ headers[_INTEGRATION_HEADER] = _integration_header_value()
229
+ return headers
230
+
186
231
  @property
187
232
  def client(self) -> weaviate.WeaviateClient:
188
233
  """Return the synchronous Weaviate client, creating and connecting it if necessary."""
@@ -199,7 +244,7 @@ class WeaviateDocumentStore:
199
244
  self._client = weaviate.connect_to_weaviate_cloud(
200
245
  self._url,
201
246
  auth_credentials=self._auth_client_secret.resolve_value(),
202
- headers=self._additional_headers,
247
+ headers=self._connection_headers(),
203
248
  additional_config=self._additional_config,
204
249
  )
205
250
  else:
@@ -216,7 +261,7 @@ class WeaviateDocumentStore:
216
261
  ),
217
262
  auth_client_secret=self._auth_client_secret.resolve_value() if self._auth_client_secret else None,
218
263
  additional_config=self._additional_config,
219
- additional_headers=self._additional_headers,
264
+ additional_headers=self._connection_headers(),
220
265
  embedded_options=self._embedded_options,
221
266
  skip_init_checks=False,
222
267
  )
@@ -244,7 +289,7 @@ class WeaviateDocumentStore:
244
289
  self._async_client = weaviate.use_async_with_weaviate_cloud(
245
290
  self._url,
246
291
  auth_credentials=self._auth_client_secret.resolve_value(),
247
- headers=self._additional_headers,
292
+ headers=self._connection_headers(),
248
293
  additional_config=self._additional_config,
249
294
  )
250
295
  else:
@@ -261,7 +306,7 @@ class WeaviateDocumentStore:
261
306
  ),
262
307
  auth_client_secret=self._auth_client_secret.resolve_value() if self._auth_client_secret else None,
263
308
  additional_config=self._additional_config,
264
- additional_headers=self._additional_headers,
309
+ additional_headers=self._connection_headers(),
265
310
  embedded_options=self._embedded_options,
266
311
  skip_init_checks=False,
267
312
  )
@@ -3,6 +3,7 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
5
  import base64
6
+ import importlib.metadata
6
7
  import logging
7
8
  import os
8
9
  from collections.abc import Generator
@@ -43,6 +44,7 @@ from haystack_integrations.document_stores.weaviate.auth import AuthApiKey
43
44
  from haystack_integrations.document_stores.weaviate.document_store import (
44
45
  DOCUMENT_COLLECTION_PROPERTIES,
45
46
  WeaviateDocumentStore,
47
+ _integration_header_value,
46
48
  )
47
49
 
48
50
 
@@ -81,7 +83,10 @@ def test_client_connects_to_weaviate_cloud(mock_connect, monkeypatch):
81
83
 
82
84
  mock_connect.assert_called_once()
83
85
  _args, kwargs = mock_connect.call_args
84
- assert kwargs["headers"] == {"X-HuggingFace-Api-Key": "k"}
86
+ assert kwargs["headers"] == {
87
+ "X-HuggingFace-Api-Key": "k",
88
+ "X-Weaviate-Client-Integration": _integration_header_value(),
89
+ }
85
90
 
86
91
 
87
92
  @pytest.mark.asyncio
@@ -100,9 +105,84 @@ async def test_async_client_connects_to_weaviate_cloud(mock_connect, monkeypatch
100
105
  mock_client.collections.exists = exists
101
106
  mock_connect.return_value = mock_client
102
107
 
103
- ds = WeaviateDocumentStore(url="rAnD0m.something.weaviate.cloud", auth_client_secret=AuthApiKey())
108
+ ds = WeaviateDocumentStore(
109
+ url="rAnD0m.something.weaviate.cloud",
110
+ auth_client_secret=AuthApiKey(),
111
+ additional_headers={"X-HuggingFace-Api-Key": "k"},
112
+ )
104
113
  assert await ds.async_client is mock_client
114
+
105
115
  mock_connect.assert_called_once()
116
+ _args, kwargs = mock_connect.call_args
117
+ assert kwargs["headers"] == {
118
+ "X-HuggingFace-Api-Key": "k",
119
+ "X-Weaviate-Client-Integration": _integration_header_value(),
120
+ }
121
+
122
+
123
+ @patch("haystack_integrations.document_stores.weaviate.document_store.weaviate.WeaviateClient")
124
+ def test_client_sends_integration_header(mock_weaviate_client_class):
125
+ mock_client = MagicMock()
126
+ mock_client.collections.exists.return_value = True
127
+ mock_weaviate_client_class.return_value = mock_client
128
+
129
+ ds = WeaviateDocumentStore(url="http://localhost:8080")
130
+ ds.client # noqa: B018
131
+
132
+ headers = mock_weaviate_client_class.call_args.kwargs["additional_headers"]
133
+ assert headers["X-Weaviate-Client-Integration"].startswith("haystack-python/")
134
+
135
+
136
+ @pytest.mark.asyncio
137
+ @patch("haystack_integrations.document_stores.weaviate.document_store.weaviate.WeaviateAsyncClient")
138
+ async def test_async_client_sends_integration_header(mock_weaviate_async_client_class):
139
+ mock_client = MagicMock()
140
+
141
+ async def connect() -> None:
142
+ return None
143
+
144
+ async def exists(_name: str) -> bool:
145
+ return True
146
+
147
+ mock_client.connect = connect
148
+ mock_client.collections.exists = exists
149
+ mock_weaviate_async_client_class.return_value = mock_client
150
+
151
+ ds = WeaviateDocumentStore(url="http://localhost:8080")
152
+ await ds.async_client
153
+
154
+ headers = mock_weaviate_async_client_class.call_args.kwargs["additional_headers"]
155
+ assert headers["X-Weaviate-Client-Integration"].startswith("haystack-python/")
156
+
157
+
158
+ @pytest.mark.parametrize("header_name", ["X-Weaviate-Client-Integration", "x-weaviate-client-integration"])
159
+ @patch("haystack_integrations.document_stores.weaviate.document_store.weaviate.WeaviateClient")
160
+ def test_user_supplied_integration_header_wins(mock_weaviate_client_class, header_name):
161
+ mock_client = MagicMock()
162
+ mock_client.collections.exists.return_value = True
163
+ mock_weaviate_client_class.return_value = mock_client
164
+
165
+ ds = WeaviateDocumentStore(url="http://localhost:8080", additional_headers={header_name: "custom/1.0"})
166
+ ds.client # noqa: B018
167
+
168
+ headers = mock_weaviate_client_class.call_args.kwargs["additional_headers"]
169
+ assert headers == {header_name: "custom/1.0"}
170
+
171
+
172
+ def test_integration_header_value_falls_back_to_unknown_version(monkeypatch):
173
+ def raise_package_not_found(_package_name: str) -> str:
174
+ raise importlib.metadata.PackageNotFoundError
175
+
176
+ monkeypatch.setattr(importlib.metadata, "version", raise_package_not_found)
177
+
178
+ assert _integration_header_value() == "haystack-python/unknown"
179
+
180
+
181
+ def test_integration_header_is_not_serialized():
182
+ assert WeaviateDocumentStore().to_dict()["init_parameters"]["additional_headers"] is None
183
+
184
+ ds = WeaviateDocumentStore(additional_headers={"X-HuggingFace-Api-Key": "k"})
185
+ assert ds.to_dict()["init_parameters"]["additional_headers"] == {"X-HuggingFace-Api-Key": "k"}
106
186
 
107
187
 
108
188
  def test_to_data_object_with_sparse_embedding_logs_warning(caplog):
@@ -325,7 +405,10 @@ class TestWeaviateDocumentStore(
325
405
  mock_weaviate_client_class.assert_called_once_with(
326
406
  auth_client_secret=AuthApiKey().resolve_value(),
327
407
  connection_params=None,
328
- additional_headers={"X-HuggingFace-Api-Key": "MY_HUGGINGFACE_KEY"},
408
+ additional_headers={
409
+ "X-HuggingFace-Api-Key": "MY_HUGGINGFACE_KEY",
410
+ "X-Weaviate-Client-Integration": _integration_header_value(),
411
+ },
329
412
  embedded_options=EmbeddedOptions(
330
413
  persistence_data_path=DEFAULT_PERSISTENCE_DATA_PATH,
331
414
  binary_path=DEFAULT_BINARY_PATH,