pgvector-haystack 3.3.1__tar.gz → 3.4.1__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-3.3.1 → pgvector_haystack-3.4.1}/CHANGELOG.md +18 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/PKG-INFO +2 -8
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/README.md +1 -7
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/pyproject.toml +34 -35
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/src/haystack_integrations/components/retrievers/pgvector/embedding_retriever.py +2 -2
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/src/haystack_integrations/components/retrievers/pgvector/keyword_retriever.py +2 -2
- pgvector_haystack-3.4.1/src/haystack_integrations/components/retrievers/py.typed +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/src/haystack_integrations/document_stores/pgvector/converters.py +3 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/src/haystack_integrations/document_stores/pgvector/document_store.py +171 -87
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/src/haystack_integrations/document_stores/pgvector/filters.py +3 -3
- pgvector_haystack-3.4.1/src/haystack_integrations/document_stores/py.typed +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/tests/test_document_store_async.py +31 -12
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/tests/test_retrieval.py +0 -1
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/tests/test_retrieval_async.py +0 -1
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/.gitignore +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/LICENSE.txt +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/examples/embedding_retrieval.py +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/examples/hybrid_retrieval.py +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/pydoc/config.yml +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/src/haystack_integrations/components/retrievers/pgvector/__init__.py +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/src/haystack_integrations/document_stores/pgvector/__init__.py +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/tests/__init__.py +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/tests/conftest.py +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/tests/test_converters.py +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/tests/test_document_store.py +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/tests/test_filters.py +0 -0
- {pgvector_haystack-3.3.1 → pgvector_haystack-3.4.1}/tests/test_retrievers.py +0 -0
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [integrations/pgvector-v3.4.0] - 2025-06-10
|
|
4
|
+
|
|
5
|
+
### 🐛 Bug Fixes
|
|
6
|
+
|
|
7
|
+
- Fix pgvector types + add py.typed (#1914)
|
|
8
|
+
|
|
9
|
+
### 🧹 Chores
|
|
10
|
+
|
|
11
|
+
- Align core-integrations Hatch scripts (#1898)
|
|
12
|
+
- Update md files for new hatch scripts (#1911)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## [integrations/pgvector-v3.3.1] - 2025-05-28
|
|
16
|
+
|
|
17
|
+
### 🌀 Miscellaneous
|
|
18
|
+
|
|
19
|
+
- Add pins for Pgvector (#1849)
|
|
20
|
+
|
|
3
21
|
## [integrations/pgvector-v3.3.0] - 2025-05-06
|
|
4
22
|
|
|
5
23
|
### 🚀 Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pgvector-haystack
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.1
|
|
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
|
|
@@ -54,13 +54,7 @@ docker run -d -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgr
|
|
|
54
54
|
then run the tests:
|
|
55
55
|
|
|
56
56
|
```console
|
|
57
|
-
hatch run test
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
To run the coverage report:
|
|
61
|
-
|
|
62
|
-
```console
|
|
63
|
-
hatch run cov
|
|
57
|
+
hatch run test:all
|
|
64
58
|
```
|
|
65
59
|
|
|
66
60
|
## License
|
|
@@ -28,13 +28,7 @@ docker run -d -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgr
|
|
|
28
28
|
then run the tests:
|
|
29
29
|
|
|
30
30
|
```console
|
|
31
|
-
hatch run test
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
To run the coverage report:
|
|
35
|
-
|
|
36
|
-
```console
|
|
37
|
-
hatch run cov
|
|
31
|
+
hatch run test:all
|
|
38
32
|
```
|
|
39
33
|
|
|
40
34
|
## License
|
|
@@ -43,32 +43,43 @@ git_describe_command = 'git describe --tags --match="integrations/pgvector-v[0-9
|
|
|
43
43
|
|
|
44
44
|
[tool.hatch.envs.default]
|
|
45
45
|
installer = "uv"
|
|
46
|
-
dependencies = [
|
|
47
|
-
|
|
48
|
-
"pytest",
|
|
49
|
-
"pytest-rerunfailures",
|
|
50
|
-
"ipython",
|
|
51
|
-
"haystack-pydoc-tools",
|
|
52
|
-
"pytest-asyncio",
|
|
53
|
-
]
|
|
46
|
+
dependencies = ["haystack-pydoc-tools", "ruff"]
|
|
47
|
+
|
|
54
48
|
[tool.hatch.envs.default.scripts]
|
|
55
|
-
test = "pytest {args:tests}"
|
|
56
|
-
test-cov = "coverage run -m pytest {args:tests}"
|
|
57
|
-
test-cov-retry = "test-cov --reruns 3 --reruns-delay 30 -x"
|
|
58
|
-
cov-report = ["- coverage combine", "coverage report"]
|
|
59
|
-
cov = ["test-cov", "cov-report"]
|
|
60
|
-
cov-retry = ["test-cov-retry", "cov-report"]
|
|
61
49
|
docs = ["pydoc-markdown pydoc/config.yml"]
|
|
50
|
+
fmt = "ruff check --fix {args} && ruff format {args}"
|
|
51
|
+
fmt-check = "ruff check {args} && ruff format --check {args}"
|
|
62
52
|
|
|
63
|
-
[tool.hatch.envs.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
53
|
+
[tool.hatch.envs.test]
|
|
54
|
+
dependencies = [
|
|
55
|
+
"pytest",
|
|
56
|
+
"pytest-asyncio",
|
|
57
|
+
"pytest-cov",
|
|
58
|
+
"pytest-rerunfailures",
|
|
59
|
+
"mypy",
|
|
60
|
+
"pip"
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[tool.hatch.envs.test.scripts]
|
|
64
|
+
unit = 'pytest -m "not integration" {args:tests}'
|
|
65
|
+
integration = 'pytest -m "integration" {args:tests}'
|
|
66
|
+
all = 'pytest {args:tests}'
|
|
67
|
+
cov-retry = 'all --cov=haystack_integrations --reruns 3 --reruns-delay 30 -x'
|
|
68
|
+
|
|
69
|
+
types = "mypy -p haystack_integrations.document_stores.pgvector -p haystack_integrations.components.retrievers.pgvector {args}"
|
|
70
|
+
|
|
71
|
+
[tool.mypy]
|
|
72
|
+
install_types = true
|
|
73
|
+
non_interactive = true
|
|
74
|
+
check_untyped_defs = true
|
|
75
|
+
disallow_incomplete_defs = true
|
|
76
|
+
|
|
77
|
+
[[tool.mypy.overrides]]
|
|
78
|
+
module = [
|
|
79
|
+
# pgvector-python does not provide types https://github.com/pgvector/pgvector-python/issues/57#issuecomment-1968064333
|
|
80
|
+
"pgvector.*",
|
|
81
|
+
]
|
|
82
|
+
ignore_missing_imports = true
|
|
72
83
|
|
|
73
84
|
[tool.black]
|
|
74
85
|
target-version = ["py38"]
|
|
@@ -157,15 +168,3 @@ exclude_lines = ["no cov", "if __name__ == .__main__.:", "if TYPE_CHECKING:"]
|
|
|
157
168
|
|
|
158
169
|
[tool.pytest.ini_options]
|
|
159
170
|
markers = ["integration: integration tests"]
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
[[tool.mypy.overrides]]
|
|
163
|
-
module = [
|
|
164
|
-
"haystack.*",
|
|
165
|
-
"haystack_integrations.*",
|
|
166
|
-
"numpy.*",
|
|
167
|
-
"pgvector.*",
|
|
168
|
-
"psycopg.*",
|
|
169
|
-
"pytest.*",
|
|
170
|
-
]
|
|
171
|
-
ignore_missing_imports = true
|
|
@@ -140,7 +140,7 @@ class PgvectorEmbeddingRetriever:
|
|
|
140
140
|
filters: Optional[Dict[str, Any]] = None,
|
|
141
141
|
top_k: Optional[int] = None,
|
|
142
142
|
vector_function: Optional[Literal["cosine_similarity", "inner_product", "l2_distance"]] = None,
|
|
143
|
-
):
|
|
143
|
+
) -> Dict[str, List[Document]]:
|
|
144
144
|
"""
|
|
145
145
|
Retrieve documents from the `PgvectorDocumentStore`, based on their embeddings.
|
|
146
146
|
|
|
@@ -173,7 +173,7 @@ class PgvectorEmbeddingRetriever:
|
|
|
173
173
|
filters: Optional[Dict[str, Any]] = None,
|
|
174
174
|
top_k: Optional[int] = None,
|
|
175
175
|
vector_function: Optional[Literal["cosine_similarity", "inner_product", "l2_distance"]] = None,
|
|
176
|
-
):
|
|
176
|
+
) -> Dict[str, List[Document]]:
|
|
177
177
|
"""
|
|
178
178
|
Asynchronously retrieve documents from the `PgvectorDocumentStore`, based on their embeddings.
|
|
179
179
|
|
|
@@ -113,7 +113,7 @@ class PgvectorKeywordRetriever:
|
|
|
113
113
|
query: str,
|
|
114
114
|
filters: Optional[Dict[str, Any]] = None,
|
|
115
115
|
top_k: Optional[int] = None,
|
|
116
|
-
):
|
|
116
|
+
) -> Dict[str, List[Document]]:
|
|
117
117
|
"""
|
|
118
118
|
Retrieve documents from the `PgvectorDocumentStore`, based on keywords.
|
|
119
119
|
|
|
@@ -143,7 +143,7 @@ class PgvectorKeywordRetriever:
|
|
|
143
143
|
query: str,
|
|
144
144
|
filters: Optional[Dict[str, Any]] = None,
|
|
145
145
|
top_k: Optional[int] = None,
|
|
146
|
-
):
|
|
146
|
+
) -> Dict[str, List[Document]]:
|
|
147
147
|
"""
|
|
148
148
|
Asynchronously retrieve documents from the `PgvectorDocumentStore`, based on keywords.
|
|
149
149
|
|
|
File without changes
|
|
@@ -57,6 +57,9 @@ def _from_pg_to_haystack_documents(documents: List[Dict[str, Any]]) -> List[Docu
|
|
|
57
57
|
haystack_dict["embedding"] = document["embedding"].tolist()
|
|
58
58
|
else: # halfvec
|
|
59
59
|
haystack_dict["embedding"] = document["embedding"].to_list()
|
|
60
|
+
# Document.from_dict expects the meta field to be a a dict or not be present (not None)
|
|
61
|
+
if "meta" in haystack_dict and haystack_dict["meta"] is None:
|
|
62
|
+
haystack_dict.pop("meta")
|
|
60
63
|
|
|
61
64
|
haystack_document = Document.from_dict(haystack_dict)
|
|
62
65
|
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
# SPDX-FileCopyrightText: 2023-present deepset GmbH <info@deepset.ai>
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
from typing import Any, Dict, List, Literal, Optional
|
|
4
|
+
from typing import Any, Dict, List, Literal, Optional, Tuple, Union, overload
|
|
5
5
|
|
|
6
6
|
from haystack import default_from_dict, default_to_dict, logging
|
|
7
7
|
from haystack.dataclasses.document import Document
|
|
8
8
|
from haystack.document_stores.errors import DocumentStoreError, DuplicateDocumentError
|
|
9
9
|
from haystack.document_stores.types import DuplicatePolicy
|
|
10
10
|
from haystack.utils.auth import Secret, deserialize_secrets_inplace
|
|
11
|
-
from psycopg import AsyncConnection, Connection, Error, IntegrityError
|
|
12
|
-
from psycopg.
|
|
13
|
-
from psycopg.
|
|
14
|
-
from psycopg.
|
|
15
|
-
from psycopg.rows import dict_row
|
|
16
|
-
from psycopg.sql import SQL, Identifier
|
|
11
|
+
from psycopg import AsyncConnection, Connection, Cursor, Error, IntegrityError
|
|
12
|
+
from psycopg.cursor_async import AsyncCursor
|
|
13
|
+
from psycopg.rows import DictRow, dict_row
|
|
14
|
+
from psycopg.sql import SQL, Composed, Identifier
|
|
17
15
|
from psycopg.sql import Literal as SQLLiteral
|
|
18
16
|
|
|
19
17
|
from pgvector.psycopg import register_vector, register_vector_async
|
|
@@ -174,12 +172,12 @@ class PgvectorDocumentStore:
|
|
|
174
172
|
self.keyword_index_name = keyword_index_name
|
|
175
173
|
self.language = language
|
|
176
174
|
|
|
177
|
-
self._connection = None
|
|
178
|
-
self._async_connection = None
|
|
179
|
-
self._cursor = None
|
|
180
|
-
self._async_cursor = None
|
|
181
|
-
self._dict_cursor = None
|
|
182
|
-
self._async_dict_cursor = None
|
|
175
|
+
self._connection: Optional[Connection] = None
|
|
176
|
+
self._async_connection: Optional[AsyncConnection] = None
|
|
177
|
+
self._cursor: Optional[Cursor] = None
|
|
178
|
+
self._async_cursor: Optional[AsyncCursor] = None
|
|
179
|
+
self._dict_cursor: Optional[Cursor[DictRow]] = None
|
|
180
|
+
self._async_dict_cursor: Optional[AsyncCursor[DictRow]] = None
|
|
183
181
|
self._table_initialized = False
|
|
184
182
|
|
|
185
183
|
def to_dict(self) -> Dict[str, Any]:
|
|
@@ -247,20 +245,33 @@ class PgvectorDocumentStore:
|
|
|
247
245
|
return False
|
|
248
246
|
return True
|
|
249
247
|
|
|
248
|
+
@overload
|
|
250
249
|
def _execute_sql(
|
|
251
|
-
self, sql_query:
|
|
252
|
-
):
|
|
250
|
+
self, cursor: Cursor, sql_query: Composed, params: Optional[tuple] = None, error_msg: str = ""
|
|
251
|
+
) -> Cursor: ...
|
|
252
|
+
|
|
253
|
+
@overload
|
|
254
|
+
def _execute_sql(
|
|
255
|
+
self, cursor: Cursor[DictRow], sql_query: Composed, params: Optional[tuple] = None, error_msg: str = ""
|
|
256
|
+
) -> Cursor[DictRow]: ...
|
|
257
|
+
|
|
258
|
+
def _execute_sql(
|
|
259
|
+
self,
|
|
260
|
+
cursor: Union[Cursor, Cursor[DictRow]],
|
|
261
|
+
sql_query: Composed,
|
|
262
|
+
params: Optional[tuple] = None,
|
|
263
|
+
error_msg: str = "",
|
|
264
|
+
) -> Union[Cursor, Cursor[DictRow]]:
|
|
253
265
|
"""
|
|
254
266
|
Internal method to execute SQL statements and handle exceptions.
|
|
255
267
|
|
|
256
268
|
:param sql_query: The SQL query to execute.
|
|
257
269
|
:param params: The parameters to pass to the SQL query.
|
|
258
270
|
:param error_msg: The error message to use if an exception is raised.
|
|
259
|
-
:param cursor: The cursor to use to execute the SQL query.
|
|
271
|
+
:param cursor: The cursor to use to execute the SQL query.
|
|
260
272
|
"""
|
|
261
273
|
|
|
262
274
|
params = params or ()
|
|
263
|
-
cursor = cursor or self._cursor
|
|
264
275
|
|
|
265
276
|
if cursor is None or self._connection is None:
|
|
266
277
|
message = (
|
|
@@ -269,7 +280,7 @@ class PgvectorDocumentStore:
|
|
|
269
280
|
)
|
|
270
281
|
raise ValueError(message)
|
|
271
282
|
|
|
272
|
-
sql_query_str = sql_query.as_string(cursor)
|
|
283
|
+
sql_query_str = sql_query.as_string(cursor)
|
|
273
284
|
logger.debug("SQL query: {query}\nParameters: {parameters}", query=sql_query_str, parameters=params)
|
|
274
285
|
|
|
275
286
|
try:
|
|
@@ -283,24 +294,33 @@ class PgvectorDocumentStore:
|
|
|
283
294
|
|
|
284
295
|
return result
|
|
285
296
|
|
|
297
|
+
@overload
|
|
298
|
+
async def _execute_sql_async(
|
|
299
|
+
self, cursor: AsyncCursor, sql_query: Composed, params: Optional[tuple] = None, error_msg: str = ""
|
|
300
|
+
) -> AsyncCursor: ...
|
|
301
|
+
|
|
302
|
+
@overload
|
|
303
|
+
async def _execute_sql_async(
|
|
304
|
+
self, cursor: AsyncCursor[DictRow], sql_query: Composed, params: Optional[tuple] = None, error_msg: str = ""
|
|
305
|
+
) -> AsyncCursor[DictRow]: ...
|
|
306
|
+
|
|
286
307
|
async def _execute_sql_async(
|
|
287
308
|
self,
|
|
288
|
-
|
|
309
|
+
cursor: Union[AsyncCursor, AsyncCursor[DictRow]],
|
|
310
|
+
sql_query: Composed,
|
|
289
311
|
params: Optional[tuple] = None,
|
|
290
312
|
error_msg: str = "",
|
|
291
|
-
|
|
292
|
-
):
|
|
313
|
+
) -> Union[AsyncCursor, AsyncCursor[DictRow]]:
|
|
293
314
|
"""
|
|
294
315
|
Internal method to asynchronously execute SQL statements and handle exceptions.
|
|
295
316
|
|
|
296
317
|
:param sql_query: The SQL query to execute.
|
|
297
318
|
:param params: The parameters to pass to the SQL query.
|
|
298
319
|
:param error_msg: The error message to use if an exception is raised.
|
|
299
|
-
:param cursor: The cursor to use to execute the SQL query.
|
|
320
|
+
:param cursor: The cursor to use to execute the SQL query.
|
|
300
321
|
"""
|
|
301
322
|
|
|
302
323
|
params = params or ()
|
|
303
|
-
cursor = cursor or self._async_cursor
|
|
304
324
|
|
|
305
325
|
if cursor is None or self._async_connection is None:
|
|
306
326
|
message = (
|
|
@@ -309,7 +329,7 @@ class PgvectorDocumentStore:
|
|
|
309
329
|
)
|
|
310
330
|
raise ValueError(message)
|
|
311
331
|
|
|
312
|
-
sql_query_str = sql_query.as_string(cursor)
|
|
332
|
+
sql_query_str = sql_query.as_string(cursor)
|
|
313
333
|
logger.debug("SQL query: {query}\nParameters: {parameters}", query=sql_query_str, parameters=params)
|
|
314
334
|
|
|
315
335
|
try:
|
|
@@ -425,23 +445,33 @@ class PgvectorDocumentStore:
|
|
|
425
445
|
self._build_table_creation_queries()
|
|
426
446
|
)
|
|
427
447
|
|
|
448
|
+
assert self._cursor is not None
|
|
449
|
+
|
|
428
450
|
table_exists = bool(
|
|
429
451
|
self._execute_sql(
|
|
430
|
-
|
|
452
|
+
cursor=self._cursor,
|
|
453
|
+
sql_query=sql_table_exists,
|
|
454
|
+
params=(self.schema_name, self.table_name),
|
|
455
|
+
error_msg="Could not check if table exists",
|
|
431
456
|
).fetchone()
|
|
432
457
|
)
|
|
433
458
|
if not table_exists:
|
|
434
|
-
self._execute_sql(sql_create_table, error_msg="Could not create table")
|
|
459
|
+
self._execute_sql(cursor=self._cursor, sql_query=sql_create_table, error_msg="Could not create table")
|
|
435
460
|
|
|
436
461
|
index_exists = bool(
|
|
437
462
|
self._execute_sql(
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
463
|
+
cursor=self._cursor,
|
|
464
|
+
sql_query=sql_keyword_index_exists,
|
|
465
|
+
params=(self.schema_name, self.table_name, self.keyword_index_name),
|
|
466
|
+
error_msg="Could not check if keyword index exists",
|
|
441
467
|
).fetchone()
|
|
442
468
|
)
|
|
443
469
|
if not index_exists:
|
|
444
|
-
self._execute_sql(
|
|
470
|
+
self._execute_sql(
|
|
471
|
+
cursor=self._cursor,
|
|
472
|
+
sql_query=sql_create_keyword_index,
|
|
473
|
+
error_msg="Could not create keyword index on table",
|
|
474
|
+
)
|
|
445
475
|
|
|
446
476
|
if self.search_strategy == "hnsw":
|
|
447
477
|
self._handle_hnsw()
|
|
@@ -459,31 +489,39 @@ class PgvectorDocumentStore:
|
|
|
459
489
|
self._build_table_creation_queries()
|
|
460
490
|
)
|
|
461
491
|
|
|
492
|
+
assert self._async_cursor is not None
|
|
493
|
+
|
|
462
494
|
table_exists = bool(
|
|
463
495
|
await (
|
|
464
496
|
await self._execute_sql_async(
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
497
|
+
cursor=self._async_cursor,
|
|
498
|
+
sql_query=sql_table_exists,
|
|
499
|
+
params=(self.schema_name, self.table_name),
|
|
500
|
+
error_msg="Could not check if table exists",
|
|
469
501
|
)
|
|
470
502
|
).fetchone()
|
|
471
503
|
)
|
|
472
504
|
if not table_exists:
|
|
473
|
-
await self._execute_sql_async(
|
|
505
|
+
await self._execute_sql_async(
|
|
506
|
+
cursor=self._async_cursor, sql_query=sql_create_table, error_msg="Could not create table"
|
|
507
|
+
)
|
|
474
508
|
|
|
475
509
|
index_exists = bool(
|
|
476
510
|
await (
|
|
477
511
|
await self._execute_sql_async(
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
512
|
+
cursor=self._async_cursor,
|
|
513
|
+
sql_query=sql_keyword_index_exists,
|
|
514
|
+
params=(self.schema_name, self.table_name, self.keyword_index_name),
|
|
515
|
+
error_msg="Could not check if keyword index exists",
|
|
482
516
|
)
|
|
483
517
|
).fetchone()
|
|
484
518
|
)
|
|
485
519
|
if not index_exists:
|
|
486
|
-
await self._execute_sql_async(
|
|
520
|
+
await self._execute_sql_async(
|
|
521
|
+
cursor=self._async_cursor,
|
|
522
|
+
sql_query=sql_create_keyword_index,
|
|
523
|
+
error_msg="Could not create keyword index on table",
|
|
524
|
+
)
|
|
487
525
|
|
|
488
526
|
if self.search_strategy == "hnsw":
|
|
489
527
|
await self._handle_hnsw_async()
|
|
@@ -501,8 +539,11 @@ class PgvectorDocumentStore:
|
|
|
501
539
|
table_name=Identifier(self.table_name),
|
|
502
540
|
)
|
|
503
541
|
|
|
542
|
+
assert self._cursor is not None
|
|
543
|
+
|
|
504
544
|
self._execute_sql(
|
|
505
|
-
|
|
545
|
+
cursor=self._cursor,
|
|
546
|
+
sql_query=delete_sql,
|
|
506
547
|
error_msg=f"Could not delete table {self.schema_name}.{self.table_name} in PgvectorDocumentStore",
|
|
507
548
|
)
|
|
508
549
|
|
|
@@ -515,8 +556,11 @@ class PgvectorDocumentStore:
|
|
|
515
556
|
table_name=Identifier(self.table_name),
|
|
516
557
|
)
|
|
517
558
|
|
|
559
|
+
assert self._async_cursor is not None
|
|
560
|
+
|
|
518
561
|
await self._execute_sql_async(
|
|
519
|
-
|
|
562
|
+
cursor=self._async_cursor,
|
|
563
|
+
sql_query=delete_sql,
|
|
520
564
|
error_msg=f"Could not delete table {self.schema_name}.{self.table_name} in PgvectorDocumentStore",
|
|
521
565
|
)
|
|
522
566
|
|
|
@@ -578,14 +622,19 @@ class PgvectorDocumentStore:
|
|
|
578
622
|
self._build_hnsw_queries()
|
|
579
623
|
)
|
|
580
624
|
|
|
625
|
+
assert self._cursor is not None
|
|
626
|
+
|
|
581
627
|
if self.hnsw_ef_search:
|
|
582
|
-
self._execute_sql(
|
|
628
|
+
self._execute_sql(
|
|
629
|
+
cursor=self._cursor, sql_query=sql_set_hnsw_ef_search, error_msg="Could not set hnsw.ef_search"
|
|
630
|
+
)
|
|
583
631
|
|
|
584
632
|
index_exists = bool(
|
|
585
633
|
self._execute_sql(
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
634
|
+
cursor=self._cursor,
|
|
635
|
+
sql_query=sql_hnsw_index_exists,
|
|
636
|
+
params=(self.schema_name, self.table_name, self.hnsw_index_name),
|
|
637
|
+
error_msg="Could not check if HNSW index exists",
|
|
589
638
|
).fetchone()
|
|
590
639
|
)
|
|
591
640
|
|
|
@@ -597,9 +646,9 @@ class PgvectorDocumentStore:
|
|
|
597
646
|
)
|
|
598
647
|
return
|
|
599
648
|
|
|
600
|
-
self._execute_sql(sql_drop_hnsw_index, error_msg="Could not drop HNSW index")
|
|
649
|
+
self._execute_sql(cursor=self._cursor, sql_query=sql_drop_hnsw_index, error_msg="Could not drop HNSW index")
|
|
601
650
|
|
|
602
|
-
self._execute_sql(sql_create_hnsw_index, error_msg="Could not create HNSW index")
|
|
651
|
+
self._execute_sql(cursor=self._cursor, sql_query=sql_create_hnsw_index, error_msg="Could not create HNSW index")
|
|
603
652
|
|
|
604
653
|
async def _handle_hnsw_async(self):
|
|
605
654
|
"""
|
|
@@ -610,16 +659,20 @@ class PgvectorDocumentStore:
|
|
|
610
659
|
self._build_hnsw_queries()
|
|
611
660
|
)
|
|
612
661
|
|
|
662
|
+
assert self._async_cursor is not None
|
|
663
|
+
|
|
613
664
|
if self.hnsw_ef_search:
|
|
614
|
-
await self._execute_sql_async(
|
|
665
|
+
await self._execute_sql_async(
|
|
666
|
+
cursor=self._async_cursor, sql_query=sql_set_hnsw_ef_search, error_msg="Could not set hnsw.ef_search"
|
|
667
|
+
)
|
|
615
668
|
|
|
616
669
|
index_exists = bool(
|
|
617
670
|
await (
|
|
618
671
|
await self._execute_sql_async(
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
672
|
+
cursor=self._async_cursor,
|
|
673
|
+
sql_query=sql_hnsw_index_exists,
|
|
674
|
+
params=(self.schema_name, self.table_name, self.hnsw_index_name),
|
|
675
|
+
error_msg="Could not check if HNSW index exists",
|
|
623
676
|
)
|
|
624
677
|
).fetchone()
|
|
625
678
|
)
|
|
@@ -632,9 +685,13 @@ class PgvectorDocumentStore:
|
|
|
632
685
|
)
|
|
633
686
|
return
|
|
634
687
|
|
|
635
|
-
await self._execute_sql_async(
|
|
688
|
+
await self._execute_sql_async(
|
|
689
|
+
cursor=self._async_cursor, sql_query=sql_drop_hnsw_index, error_msg="Could not drop HNSW index"
|
|
690
|
+
)
|
|
636
691
|
|
|
637
|
-
await self._execute_sql_async(
|
|
692
|
+
await self._execute_sql_async(
|
|
693
|
+
cursor=self._async_cursor, sql_query=sql_create_hnsw_index, error_msg="Could not create HNSW index"
|
|
694
|
+
)
|
|
638
695
|
|
|
639
696
|
def count_documents(self) -> int:
|
|
640
697
|
"""
|
|
@@ -648,10 +705,13 @@ class PgvectorDocumentStore:
|
|
|
648
705
|
)
|
|
649
706
|
|
|
650
707
|
self._ensure_db_setup()
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
708
|
+
assert self._cursor is not None
|
|
709
|
+
result = self._execute_sql(
|
|
710
|
+
cursor=self._cursor, sql_query=sql_count, error_msg="Could not count documents in PgvectorDocumentStore"
|
|
711
|
+
).fetchone()
|
|
712
|
+
if result is not None:
|
|
713
|
+
return result[0]
|
|
714
|
+
return 0
|
|
655
715
|
|
|
656
716
|
async def count_documents_async(self) -> int:
|
|
657
717
|
"""
|
|
@@ -665,12 +725,18 @@ class PgvectorDocumentStore:
|
|
|
665
725
|
)
|
|
666
726
|
|
|
667
727
|
await self._ensure_db_setup_async()
|
|
668
|
-
|
|
728
|
+
assert self._async_cursor is not None
|
|
669
729
|
result = await (
|
|
670
|
-
await self._execute_sql_async(
|
|
730
|
+
await self._execute_sql_async(
|
|
731
|
+
cursor=self._async_cursor,
|
|
732
|
+
sql_query=sql_count,
|
|
733
|
+
error_msg="Could not count documents in PgvectorDocumentStore",
|
|
734
|
+
)
|
|
671
735
|
).fetchone()
|
|
672
736
|
|
|
673
|
-
|
|
737
|
+
if result is not None:
|
|
738
|
+
return result[0]
|
|
739
|
+
return 0
|
|
674
740
|
|
|
675
741
|
def filter_documents(self, filters: Optional[Dict[str, Any]] = None) -> List[Document]:
|
|
676
742
|
"""
|
|
@@ -696,11 +762,13 @@ class PgvectorDocumentStore:
|
|
|
696
762
|
sql_filter += sql_where_clause
|
|
697
763
|
|
|
698
764
|
self._ensure_db_setup()
|
|
765
|
+
assert self._dict_cursor is not None
|
|
766
|
+
|
|
699
767
|
result = self._execute_sql(
|
|
700
|
-
sql_filter,
|
|
701
|
-
params,
|
|
702
|
-
error_msg="Could not filter documents from PgvectorDocumentStore.",
|
|
703
768
|
cursor=self._dict_cursor,
|
|
769
|
+
sql_query=sql_filter,
|
|
770
|
+
params=params,
|
|
771
|
+
error_msg="Could not filter documents from PgvectorDocumentStore.",
|
|
704
772
|
)
|
|
705
773
|
|
|
706
774
|
records = result.fetchall()
|
|
@@ -732,18 +800,20 @@ class PgvectorDocumentStore:
|
|
|
732
800
|
sql_filter += sql_where_clause
|
|
733
801
|
|
|
734
802
|
await self._ensure_db_setup_async()
|
|
803
|
+
assert self._async_dict_cursor is not None
|
|
804
|
+
|
|
735
805
|
result = await self._execute_sql_async(
|
|
736
|
-
sql_filter,
|
|
737
|
-
params,
|
|
738
|
-
error_msg="Could not filter documents from PgvectorDocumentStore.",
|
|
739
806
|
cursor=self._async_dict_cursor,
|
|
807
|
+
sql_query=sql_filter,
|
|
808
|
+
params=params,
|
|
809
|
+
error_msg="Could not filter documents from PgvectorDocumentStore.",
|
|
740
810
|
)
|
|
741
811
|
|
|
742
812
|
records = await result.fetchall()
|
|
743
813
|
docs = _from_pg_to_haystack_documents(records)
|
|
744
814
|
return docs
|
|
745
815
|
|
|
746
|
-
def _build_insert_statement(self, policy: DuplicatePolicy):
|
|
816
|
+
def _build_insert_statement(self, policy: DuplicatePolicy) -> Composed:
|
|
747
817
|
"""
|
|
748
818
|
Builds the SQL insert statement to write documents.
|
|
749
819
|
"""
|
|
@@ -885,7 +955,10 @@ class PgvectorDocumentStore:
|
|
|
885
955
|
)
|
|
886
956
|
|
|
887
957
|
self._ensure_db_setup()
|
|
888
|
-
self.
|
|
958
|
+
assert self._cursor is not None
|
|
959
|
+
self._execute_sql(
|
|
960
|
+
cursor=self._cursor, sql_query=delete_sql, error_msg="Could not delete documents from PgvectorDocumentStore"
|
|
961
|
+
)
|
|
889
962
|
|
|
890
963
|
async def delete_documents_async(self, document_ids: List[str]) -> None:
|
|
891
964
|
"""
|
|
@@ -905,9 +978,16 @@ class PgvectorDocumentStore:
|
|
|
905
978
|
)
|
|
906
979
|
|
|
907
980
|
await self._ensure_db_setup_async()
|
|
908
|
-
|
|
981
|
+
assert self._async_cursor is not None
|
|
982
|
+
await self._execute_sql_async(
|
|
983
|
+
cursor=self._async_cursor,
|
|
984
|
+
sql_query=delete_sql,
|
|
985
|
+
error_msg="Could not delete documents from PgvectorDocumentStore",
|
|
986
|
+
)
|
|
909
987
|
|
|
910
|
-
def _build_keyword_retrieval_query(
|
|
988
|
+
def _build_keyword_retrieval_query(
|
|
989
|
+
self, query: str, top_k: int, filters: Optional[Dict[str, Any]] = None
|
|
990
|
+
) -> Tuple[Composed, tuple]:
|
|
911
991
|
"""
|
|
912
992
|
Builds the SQL query and the where parameters for keyword retrieval.
|
|
913
993
|
"""
|
|
@@ -919,7 +999,7 @@ class PgvectorDocumentStore:
|
|
|
919
999
|
)
|
|
920
1000
|
|
|
921
1001
|
where_params = ()
|
|
922
|
-
sql_where_clause = SQL("")
|
|
1002
|
+
sql_where_clause: Union[Composed, SQL] = SQL("")
|
|
923
1003
|
if filters:
|
|
924
1004
|
sql_where_clause, where_params = _convert_filters_to_where_clause_and_params(
|
|
925
1005
|
filters=filters, operator="AND"
|
|
@@ -954,11 +1034,12 @@ class PgvectorDocumentStore:
|
|
|
954
1034
|
sql_query, where_params = self._build_keyword_retrieval_query(query=query, top_k=top_k, filters=filters)
|
|
955
1035
|
|
|
956
1036
|
self._ensure_db_setup()
|
|
1037
|
+
assert self._dict_cursor is not None
|
|
957
1038
|
result = self._execute_sql(
|
|
958
|
-
sql_query,
|
|
959
|
-
(query, *where_params),
|
|
960
|
-
error_msg="Could not retrieve documents from PgvectorDocumentStore.",
|
|
961
1039
|
cursor=self._dict_cursor,
|
|
1040
|
+
sql_query=sql_query,
|
|
1041
|
+
params=(query, *where_params),
|
|
1042
|
+
error_msg="Could not retrieve documents from PgvectorDocumentStore.",
|
|
962
1043
|
)
|
|
963
1044
|
|
|
964
1045
|
records = result.fetchall()
|
|
@@ -982,11 +1063,12 @@ class PgvectorDocumentStore:
|
|
|
982
1063
|
sql_query, where_params = self._build_keyword_retrieval_query(query=query, top_k=top_k, filters=filters)
|
|
983
1064
|
|
|
984
1065
|
await self._ensure_db_setup_async()
|
|
1066
|
+
assert self._async_dict_cursor is not None
|
|
985
1067
|
result = await self._execute_sql_async(
|
|
986
|
-
sql_query,
|
|
987
|
-
(query, *where_params),
|
|
988
|
-
error_msg="Could not retrieve documents from PgvectorDocumentStore.",
|
|
989
1068
|
cursor=self._async_dict_cursor,
|
|
1069
|
+
sql_query=sql_query,
|
|
1070
|
+
params=(query, *where_params),
|
|
1071
|
+
error_msg="Could not retrieve documents from PgvectorDocumentStore.",
|
|
990
1072
|
)
|
|
991
1073
|
|
|
992
1074
|
records = await result.fetchall()
|
|
@@ -999,7 +1081,7 @@ class PgvectorDocumentStore:
|
|
|
999
1081
|
vector_function: Optional[Literal["cosine_similarity", "inner_product", "l2_distance"]],
|
|
1000
1082
|
top_k: int,
|
|
1001
1083
|
filters: Optional[Dict[str, Any]] = None,
|
|
1002
|
-
):
|
|
1084
|
+
) -> Tuple[Composed, tuple]:
|
|
1003
1085
|
"""
|
|
1004
1086
|
Performs checks and builds the SQL query and the where parameters for embedding retrieval.
|
|
1005
1087
|
"""
|
|
@@ -1038,7 +1120,7 @@ class PgvectorDocumentStore:
|
|
|
1038
1120
|
score=SQL(score_definition),
|
|
1039
1121
|
)
|
|
1040
1122
|
|
|
1041
|
-
sql_where_clause = SQL("")
|
|
1123
|
+
sql_where_clause: Union[Composed, SQL] = SQL("")
|
|
1042
1124
|
params = ()
|
|
1043
1125
|
if filters:
|
|
1044
1126
|
sql_where_clause, params = _convert_filters_to_where_clause_and_params(filters)
|
|
@@ -1078,11 +1160,12 @@ class PgvectorDocumentStore:
|
|
|
1078
1160
|
query_embedding=query_embedding, vector_function=vector_function, top_k=top_k, filters=filters
|
|
1079
1161
|
)
|
|
1080
1162
|
self._ensure_db_setup()
|
|
1163
|
+
assert self._dict_cursor is not None
|
|
1081
1164
|
result = self._execute_sql(
|
|
1082
|
-
sql_query,
|
|
1083
|
-
params,
|
|
1084
|
-
error_msg="Could not retrieve documents from PgvectorDocumentStore.",
|
|
1085
1165
|
cursor=self._dict_cursor,
|
|
1166
|
+
sql_query=sql_query,
|
|
1167
|
+
params=params,
|
|
1168
|
+
error_msg="Could not retrieve documents from PgvectorDocumentStore.",
|
|
1086
1169
|
)
|
|
1087
1170
|
|
|
1088
1171
|
records = result.fetchall()
|
|
@@ -1107,11 +1190,12 @@ class PgvectorDocumentStore:
|
|
|
1107
1190
|
)
|
|
1108
1191
|
|
|
1109
1192
|
await self._ensure_db_setup_async()
|
|
1193
|
+
assert self._async_dict_cursor is not None
|
|
1110
1194
|
result = await self._execute_sql_async(
|
|
1111
|
-
sql_query,
|
|
1112
|
-
params,
|
|
1113
|
-
error_msg="Could not retrieve documents from PgvectorDocumentStore.",
|
|
1114
1195
|
cursor=self._async_dict_cursor,
|
|
1196
|
+
sql_query=sql_query,
|
|
1197
|
+
params=params,
|
|
1198
|
+
error_msg="Could not retrieve documents from PgvectorDocumentStore.",
|
|
1115
1199
|
)
|
|
1116
1200
|
|
|
1117
1201
|
records = await result.fetchall()
|
|
@@ -6,7 +6,7 @@ from itertools import chain
|
|
|
6
6
|
from typing import Any, Dict, List, Literal, Optional, Tuple
|
|
7
7
|
|
|
8
8
|
from haystack.errors import FilterError
|
|
9
|
-
from psycopg.sql import SQL
|
|
9
|
+
from psycopg.sql import SQL, Composed
|
|
10
10
|
from psycopg.types.json import Jsonb
|
|
11
11
|
|
|
12
12
|
# we need this mapping to cast meta values to the correct type,
|
|
@@ -21,7 +21,7 @@ PYTHON_TYPES_TO_PG_TYPES = {
|
|
|
21
21
|
NO_VALUE = "no_value"
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def _validate_filters(filters: Optional[Dict[str, Any]] = None):
|
|
24
|
+
def _validate_filters(filters: Optional[Dict[str, Any]] = None) -> None:
|
|
25
25
|
"""
|
|
26
26
|
Validates the filters provided.
|
|
27
27
|
"""
|
|
@@ -36,7 +36,7 @@ def _validate_filters(filters: Optional[Dict[str, Any]] = None):
|
|
|
36
36
|
|
|
37
37
|
def _convert_filters_to_where_clause_and_params(
|
|
38
38
|
filters: Dict[str, Any], operator: Literal["WHERE", "AND"] = "WHERE"
|
|
39
|
-
) -> Tuple[
|
|
39
|
+
) -> Tuple[Composed, Tuple]:
|
|
40
40
|
"""
|
|
41
41
|
Convert Haystack filters to a WHERE clause and a tuple of params to query PostgreSQL.
|
|
42
42
|
"""
|
|
File without changes
|
|
@@ -10,6 +10,7 @@ from haystack.dataclasses.document import ByteStream, Document
|
|
|
10
10
|
from haystack.document_stores.errors import DuplicateDocumentError
|
|
11
11
|
from haystack.document_stores.types import DuplicatePolicy
|
|
12
12
|
from haystack.utils import Secret
|
|
13
|
+
from psycopg.sql import SQL
|
|
13
14
|
|
|
14
15
|
from haystack_integrations.document_stores.pgvector import PgvectorDocumentStore
|
|
15
16
|
|
|
@@ -97,16 +98,18 @@ class TestDocumentStoreAsync:
|
|
|
97
98
|
@pytest.mark.integration
|
|
98
99
|
@pytest.mark.asyncio
|
|
99
100
|
async def test_hnsw_index_recreation():
|
|
100
|
-
async def get_index_oid(document_store, schema_name, index_name):
|
|
101
|
-
sql_get_index_oid = """
|
|
101
|
+
async def get_index_oid(cursor, document_store, schema_name, index_name):
|
|
102
|
+
sql_get_index_oid = SQL("""
|
|
102
103
|
SELECT c.oid
|
|
103
104
|
FROM pg_class c
|
|
104
105
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
105
106
|
WHERE c.relkind = 'i'
|
|
106
107
|
AND n.nspname = %s
|
|
107
108
|
AND c.relname = %s;
|
|
108
|
-
"""
|
|
109
|
-
result = await document_store._execute_sql_async(
|
|
109
|
+
""")
|
|
110
|
+
result = await document_store._execute_sql_async(
|
|
111
|
+
cursor=cursor, sql_query=sql_get_index_oid, params=(schema_name, index_name)
|
|
112
|
+
)
|
|
110
113
|
return (await result.fetchone())[0]
|
|
111
114
|
|
|
112
115
|
# create a new schema
|
|
@@ -127,14 +130,18 @@ async def test_hnsw_index_recreation():
|
|
|
127
130
|
|
|
128
131
|
# get the hnsw index oid
|
|
129
132
|
hnws_index_name = "haystack_hnsw_index"
|
|
130
|
-
first_oid = await get_index_oid(
|
|
133
|
+
first_oid = await get_index_oid(
|
|
134
|
+
cursor=ds1._async_cursor, document_store=ds1, schema_name=ds1.schema_name, index_name=hnws_index_name
|
|
135
|
+
)
|
|
131
136
|
|
|
132
137
|
# create second document store with recreation enabled
|
|
133
138
|
ds2 = PgvectorDocumentStore(**params, hnsw_recreate_index_if_exists=True)
|
|
134
139
|
await ds2._ensure_db_setup_async()
|
|
135
140
|
|
|
136
141
|
# get the index oid
|
|
137
|
-
second_oid = await get_index_oid(
|
|
142
|
+
second_oid = await get_index_oid(
|
|
143
|
+
cursor=ds2._async_cursor, document_store=ds2, schema_name=ds2.schema_name, index_name=hnws_index_name
|
|
144
|
+
)
|
|
138
145
|
|
|
139
146
|
# verify that oids differ
|
|
140
147
|
assert second_oid != first_oid, "Index was not recreated (OID remained the same)"
|
|
@@ -147,16 +154,18 @@ async def test_hnsw_index_recreation():
|
|
|
147
154
|
@pytest.mark.integration
|
|
148
155
|
@pytest.mark.asyncio
|
|
149
156
|
async def test_create_table_if_not_exists():
|
|
150
|
-
async def get_table_oid(document_store, schema_name, table_name):
|
|
151
|
-
sql_get_table_oid = """
|
|
157
|
+
async def get_table_oid(cursor, document_store, schema_name, table_name):
|
|
158
|
+
sql_get_table_oid = SQL("""
|
|
152
159
|
SELECT c.oid
|
|
153
160
|
FROM pg_class c
|
|
154
161
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
155
162
|
WHERE c.relkind = 'r'
|
|
156
163
|
AND n.nspname = %s
|
|
157
164
|
AND c.relname = %s;
|
|
158
|
-
"""
|
|
159
|
-
result = await document_store._execute_sql_async(
|
|
165
|
+
""")
|
|
166
|
+
result = await document_store._execute_sql_async(
|
|
167
|
+
cursor=cursor, sql_query=sql_get_table_oid, params=(schema_name, table_name)
|
|
168
|
+
)
|
|
160
169
|
return (await result.fetchone())[0]
|
|
161
170
|
|
|
162
171
|
connection_string = "postgresql://postgres:postgres@localhost:5432/postgres"
|
|
@@ -176,11 +185,21 @@ async def test_create_table_if_not_exists():
|
|
|
176
185
|
await document_store._ensure_db_setup_async()
|
|
177
186
|
await document_store._initialize_table_async()
|
|
178
187
|
|
|
179
|
-
first_table_oid = await get_table_oid(
|
|
188
|
+
first_table_oid = await get_table_oid(
|
|
189
|
+
cursor=document_store._async_cursor,
|
|
190
|
+
document_store=document_store,
|
|
191
|
+
schema_name=schema_name,
|
|
192
|
+
table_name=table_name,
|
|
193
|
+
)
|
|
180
194
|
assert first_table_oid is not None, "Table was not created"
|
|
181
195
|
|
|
182
196
|
await document_store._initialize_table_async()
|
|
183
|
-
second_table_oid = await get_table_oid(
|
|
197
|
+
second_table_oid = await get_table_oid(
|
|
198
|
+
cursor=document_store._async_cursor,
|
|
199
|
+
document_store=document_store,
|
|
200
|
+
schema_name=schema_name,
|
|
201
|
+
table_name=table_name,
|
|
202
|
+
)
|
|
184
203
|
|
|
185
204
|
assert first_table_oid == second_table_oid, "Table was recreated"
|
|
186
205
|
|
|
@@ -13,7 +13,6 @@ from haystack_integrations.document_stores.pgvector import PgvectorDocumentStore
|
|
|
13
13
|
|
|
14
14
|
@pytest.mark.integration
|
|
15
15
|
class TestEmbeddingRetrieval:
|
|
16
|
-
|
|
17
16
|
@pytest.mark.parametrize("document_store", ["document_store", "document_store_w_hnsw_index"], indirect=True)
|
|
18
17
|
def test_embedding_retrieval_cosine_similarity(self, document_store: PgvectorDocumentStore):
|
|
19
18
|
query_embedding = [0.1] * 768
|
|
@@ -14,7 +14,6 @@ from haystack_integrations.document_stores.pgvector import PgvectorDocumentStore
|
|
|
14
14
|
@pytest.mark.integration
|
|
15
15
|
@pytest.mark.asyncio
|
|
16
16
|
class TestEmbeddingRetrievalAsync:
|
|
17
|
-
|
|
18
17
|
@pytest.mark.parametrize("document_store", ["document_store", "document_store_w_hnsw_index"], indirect=True)
|
|
19
18
|
async def test_embedding_retrieval_cosine_similarity_async(self, document_store: PgvectorDocumentStore):
|
|
20
19
|
query_embedding = [0.1] * 768
|
|
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
|