pgvector-haystack 7.0.0__tar.gz → 8.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.
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/CHANGELOG.md +19 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/PKG-INFO +3 -3
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/pyproject.toml +2 -2
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/document_stores/pgvector/document_store.py +44 -22
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/tests/test_document_store.py +21 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/tests/test_document_store_async.py +27 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/.gitignore +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/LICENSE.txt +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/README.md +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/examples/embedding_retrieval.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/examples/hybrid_retrieval.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/pydoc/config_docusaurus.yml +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/components/retrievers/pgvector/__init__.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/components/retrievers/pgvector/embedding_retriever.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/components/retrievers/pgvector/keyword_retriever.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/components/retrievers/py.typed +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/document_stores/pgvector/__init__.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/document_stores/pgvector/converters.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/document_stores/pgvector/filters.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/document_stores/py.typed +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/tests/__init__.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/tests/conftest.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/tests/test_converters.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/tests/test_filters.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/tests/test_retrieval.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/tests/test_retrieval_async.py +0 -0
- {pgvector_haystack-7.0.0 → pgvector_haystack-8.1.0}/tests/test_retrievers.py +0 -0
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [integrations/pgvector-v8.0.0] - 2026-10-16
|
|
4
|
+
|
|
5
|
+
### 🧪 Testing
|
|
6
|
+
|
|
7
|
+
- Test compatible integrations with Python 3.15; update pyproject (#4104)
|
|
8
|
+
|
|
9
|
+
### 🧹 Chores
|
|
10
|
+
|
|
11
|
+
- Drop redundant deserialize_secrets_inplace calls in integrations requiring haystack-ai>=2.23 (#4058)
|
|
12
|
+
- [**breaking**] Drop Python 3.10 support (#4105)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## [integrations/pgvector-v7.0.0] - 2026-09-29
|
|
16
|
+
|
|
17
|
+
### 🐛 Bug Fixes
|
|
18
|
+
|
|
19
|
+
- [**breaking**] Pgvector - an empty filter must not delete every document (#4006)
|
|
20
|
+
|
|
21
|
+
|
|
3
22
|
## [integrations/pgvector-v6.6.1] - 2026-09-25
|
|
4
23
|
|
|
5
24
|
### 🐛 Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pgvector-haystack
|
|
3
|
-
Version:
|
|
3
|
+
Version: 8.1.0
|
|
4
4
|
Summary: An integration of pgvector (vector search extension for Postgres) 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/pgvector/README.md
|
|
@@ -11,14 +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.10
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
19
19
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
20
20
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
21
|
-
Requires-Python: >=3.
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
22
|
Requires-Dist: haystack-ai>=2.28.0
|
|
23
23
|
Requires-Dist: pgvector>=0.3.0
|
|
24
24
|
Requires-Dist: psycopg[binary]
|
|
@@ -7,7 +7,7 @@ name = "pgvector-haystack"
|
|
|
7
7
|
dynamic = ["version"]
|
|
8
8
|
description = "An integration of pgvector (vector search extension for Postgres) with Haystack"
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
11
|
license = "Apache-2.0"
|
|
12
12
|
keywords = []
|
|
13
13
|
authors = [{ name = "deepset GmbH", email = "info@deepset.ai" }]
|
|
@@ -15,11 +15,11 @@ classifiers = [
|
|
|
15
15
|
"License :: OSI Approved :: Apache Software License",
|
|
16
16
|
"Development Status :: 4 - Beta",
|
|
17
17
|
"Programming Language :: Python",
|
|
18
|
-
"Programming Language :: Python :: 3.10",
|
|
19
18
|
"Programming Language :: Python :: 3.11",
|
|
20
19
|
"Programming Language :: Python :: 3.12",
|
|
21
20
|
"Programming Language :: Python :: 3.13",
|
|
22
21
|
"Programming Language :: Python :: 3.14",
|
|
22
|
+
"Programming Language :: Python :: 3.15",
|
|
23
23
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
24
24
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
25
25
|
]
|
|
@@ -10,7 +10,7 @@ from haystack.dataclasses.document import Document
|
|
|
10
10
|
from haystack.document_stores.errors import DocumentStoreError, DuplicateDocumentError
|
|
11
11
|
from haystack.document_stores.types import DuplicatePolicy
|
|
12
12
|
from haystack.errors import FilterError
|
|
13
|
-
from haystack.utils.auth import Secret
|
|
13
|
+
from haystack.utils.auth import Secret
|
|
14
14
|
from psycopg import AsyncConnection, Connection, Cursor, Error, IntegrityError
|
|
15
15
|
from psycopg.cursor_async import AsyncCursor
|
|
16
16
|
from psycopg.rows import DictRow, dict_row
|
|
@@ -222,7 +222,6 @@ class PgvectorDocumentStore:
|
|
|
222
222
|
:returns:
|
|
223
223
|
Deserialized component.
|
|
224
224
|
"""
|
|
225
|
-
deserialize_secrets_inplace(data["init_parameters"], ["connection_string"])
|
|
226
225
|
return default_from_dict(cls, data)
|
|
227
226
|
|
|
228
227
|
def close(self) -> None:
|
|
@@ -371,6 +370,47 @@ class PgvectorDocumentStore:
|
|
|
371
370
|
|
|
372
371
|
return result
|
|
373
372
|
|
|
373
|
+
def _create_connection(self) -> Connection:
|
|
374
|
+
"""
|
|
375
|
+
Opens a new connection to the PostgreSQL database.
|
|
376
|
+
|
|
377
|
+
Subclasses can override this method to connect differently (e.g. through a cloud provider's connector).
|
|
378
|
+
It must only open and return the connection: autocommit, the pgvector extension, vector type
|
|
379
|
+
registration, cursors, and table initialization are handled by `_ensure_db_setup`.
|
|
380
|
+
|
|
381
|
+
:raises DocumentStoreError: If the connection cannot be opened.
|
|
382
|
+
"""
|
|
383
|
+
conn_str = self.connection_string.resolve_value() or ""
|
|
384
|
+
try:
|
|
385
|
+
return Connection.connect(conn_str)
|
|
386
|
+
except Error as e:
|
|
387
|
+
msg = (
|
|
388
|
+
"Failed to connect to PostgreSQL database. Ensure the connection string follows the "
|
|
389
|
+
"PostgreSQL connection specification: "
|
|
390
|
+
"https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING."
|
|
391
|
+
)
|
|
392
|
+
raise DocumentStoreError(msg) from e
|
|
393
|
+
|
|
394
|
+
async def _create_connection_async(self) -> AsyncConnection:
|
|
395
|
+
"""
|
|
396
|
+
Opens a new async connection to the PostgreSQL database.
|
|
397
|
+
|
|
398
|
+
Async counterpart of `_create_connection`, overridable in the same way. Everything else is handled by
|
|
399
|
+
`_ensure_db_setup_async`.
|
|
400
|
+
|
|
401
|
+
:raises DocumentStoreError: If the connection cannot be opened.
|
|
402
|
+
"""
|
|
403
|
+
conn_str = self.connection_string.resolve_value() or ""
|
|
404
|
+
try:
|
|
405
|
+
return await AsyncConnection.connect(conn_str)
|
|
406
|
+
except Error as e:
|
|
407
|
+
msg = (
|
|
408
|
+
"Failed to connect to PostgreSQL database. Ensure the connection string follows the "
|
|
409
|
+
"PostgreSQL connection specification: "
|
|
410
|
+
"https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING."
|
|
411
|
+
)
|
|
412
|
+
raise DocumentStoreError(msg) from e
|
|
413
|
+
|
|
374
414
|
def _ensure_db_setup(self) -> None:
|
|
375
415
|
"""
|
|
376
416
|
Ensures that the connection to the PostgreSQL database exists and is valid.
|
|
@@ -388,16 +428,7 @@ class PgvectorDocumentStore:
|
|
|
388
428
|
except Error as e:
|
|
389
429
|
logger.debug("Failed to close connection: {e}", e=str(e))
|
|
390
430
|
|
|
391
|
-
|
|
392
|
-
try:
|
|
393
|
-
connection = Connection.connect(conn_str)
|
|
394
|
-
except Error as e:
|
|
395
|
-
msg = (
|
|
396
|
-
"Failed to connect to PostgreSQL database. Ensure the connection string follows the "
|
|
397
|
-
"PostgreSQL connection specification: "
|
|
398
|
-
"https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING."
|
|
399
|
-
)
|
|
400
|
-
raise DocumentStoreError(msg) from e
|
|
431
|
+
connection = self._create_connection()
|
|
401
432
|
connection.autocommit = True
|
|
402
433
|
if self.create_extension:
|
|
403
434
|
connection.execute("CREATE EXTENSION IF NOT EXISTS vector")
|
|
@@ -431,16 +462,7 @@ class PgvectorDocumentStore:
|
|
|
431
462
|
if self._async_connection:
|
|
432
463
|
await self._async_connection.close()
|
|
433
464
|
|
|
434
|
-
|
|
435
|
-
try:
|
|
436
|
-
async_connection = await AsyncConnection.connect(conn_str)
|
|
437
|
-
except Error as e:
|
|
438
|
-
msg = (
|
|
439
|
-
"Failed to connect to PostgreSQL database. Ensure the connection string follows the "
|
|
440
|
-
"PostgreSQL connection specification: "
|
|
441
|
-
"https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING."
|
|
442
|
-
)
|
|
443
|
-
raise DocumentStoreError(msg) from e
|
|
465
|
+
async_connection = await self._create_connection_async()
|
|
444
466
|
await async_connection.set_autocommit(True)
|
|
445
467
|
if self.create_extension:
|
|
446
468
|
await async_connection.execute("CREATE EXTENSION IF NOT EXISTS vector")
|
|
@@ -448,6 +448,27 @@ def test_close_is_exception_safe(mock_store):
|
|
|
448
448
|
assert mock_store._connection is None
|
|
449
449
|
|
|
450
450
|
|
|
451
|
+
@pytest.mark.usefixtures("patches_for_unit_tests")
|
|
452
|
+
def test_ensure_db_setup_uses_overridden_create_connection(monkeypatch):
|
|
453
|
+
monkeypatch.setenv("PG_CONN_STR", "some-connection-string")
|
|
454
|
+
mock_connection = Mock(spec=Connection)
|
|
455
|
+
|
|
456
|
+
class CustomConnectionDocumentStore(PgvectorDocumentStore):
|
|
457
|
+
def _create_connection(self) -> Connection:
|
|
458
|
+
return mock_connection
|
|
459
|
+
|
|
460
|
+
store = CustomConnectionDocumentStore()
|
|
461
|
+
with patch.object(CustomConnectionDocumentStore, "_initialize_table") as mock_initialize_table:
|
|
462
|
+
store._ensure_db_setup()
|
|
463
|
+
|
|
464
|
+
assert store._connection is mock_connection
|
|
465
|
+
assert mock_connection.autocommit is True
|
|
466
|
+
mock_connection.execute.assert_called_once_with("CREATE EXTENSION IF NOT EXISTS vector")
|
|
467
|
+
assert store._cursor is not None
|
|
468
|
+
assert store._dict_cursor is not None
|
|
469
|
+
mock_initialize_table.assert_called_once()
|
|
470
|
+
|
|
471
|
+
|
|
451
472
|
@pytest.mark.integration
|
|
452
473
|
def test_halfvec_hnsw_write_documents(document_store_w_halfvec_hnsw_index: PgvectorDocumentStore):
|
|
453
474
|
documents = [
|
|
@@ -409,3 +409,30 @@ async def test_close_async_is_exception_safe(mock_store):
|
|
|
409
409
|
await mock_store.close_async()
|
|
410
410
|
|
|
411
411
|
assert mock_store._async_connection is None
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
@pytest.mark.asyncio
|
|
415
|
+
async def test_ensure_db_setup_async_uses_overridden_create_connection_async(monkeypatch):
|
|
416
|
+
monkeypatch.setenv("PG_CONN_STR", "some-connection-string")
|
|
417
|
+
mock_connection = Mock(spec=AsyncConnection)
|
|
418
|
+
mock_connection.set_autocommit = AsyncMock()
|
|
419
|
+
mock_connection.execute = AsyncMock()
|
|
420
|
+
|
|
421
|
+
class CustomConnectionDocumentStore(PgvectorDocumentStore):
|
|
422
|
+
async def _create_connection_async(self) -> AsyncConnection:
|
|
423
|
+
return mock_connection
|
|
424
|
+
|
|
425
|
+
store = CustomConnectionDocumentStore()
|
|
426
|
+
with (
|
|
427
|
+
patch("haystack_integrations.document_stores.pgvector.document_store.register_vector_async") as mock_register,
|
|
428
|
+
patch.object(CustomConnectionDocumentStore, "_initialize_table_async") as mock_initialize_table,
|
|
429
|
+
):
|
|
430
|
+
await store._ensure_db_setup_async()
|
|
431
|
+
|
|
432
|
+
assert store._async_connection is mock_connection
|
|
433
|
+
mock_connection.set_autocommit.assert_awaited_once_with(True)
|
|
434
|
+
mock_connection.execute.assert_awaited_once_with("CREATE EXTENSION IF NOT EXISTS vector")
|
|
435
|
+
mock_register.assert_awaited_once_with(mock_connection)
|
|
436
|
+
assert store._async_cursor is not None
|
|
437
|
+
assert store._async_dict_cursor is not None
|
|
438
|
+
mock_initialize_table.assert_awaited_once()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|