pgvector-haystack 3.1.0__tar.gz → 3.2.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 (25) hide show
  1. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/CHANGELOG.md +11 -1
  2. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/PKG-INFO +1 -1
  3. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/src/haystack_integrations/document_stores/pgvector/converters.py +5 -1
  4. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/src/haystack_integrations/document_stores/pgvector/document_store.py +29 -2
  5. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/tests/conftest.py +24 -0
  6. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/tests/test_document_store.py +22 -0
  7. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/tests/test_retrievers.py +2 -0
  8. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/.gitignore +0 -0
  9. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/LICENSE.txt +0 -0
  10. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/README.md +0 -0
  11. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/examples/embedding_retrieval.py +0 -0
  12. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/examples/hybrid_retrieval.py +0 -0
  13. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/pydoc/config.yml +0 -0
  14. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/pyproject.toml +0 -0
  15. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/src/haystack_integrations/components/retrievers/pgvector/__init__.py +0 -0
  16. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/src/haystack_integrations/components/retrievers/pgvector/embedding_retriever.py +0 -0
  17. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/src/haystack_integrations/components/retrievers/pgvector/keyword_retriever.py +0 -0
  18. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/src/haystack_integrations/document_stores/pgvector/__init__.py +0 -0
  19. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/src/haystack_integrations/document_stores/pgvector/filters.py +0 -0
  20. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/tests/__init__.py +0 -0
  21. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/tests/test_converters.py +0 -0
  22. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/tests/test_document_store_async.py +0 -0
  23. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/tests/test_filters.py +0 -0
  24. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/tests/test_retrieval.py +0 -0
  25. {pgvector_haystack-3.1.0 → pgvector_haystack-3.2.0}/tests/test_retrieval_async.py +0 -0
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [integrations/pgvector-v3.1.0] - 2025-03-20
4
+
5
+ ### 🚀 Features
6
+
7
+ - Pgvector - async support (+ refactoring) (#1547)
8
+
9
+ ### ⚙️ CI
10
+
11
+ - Review testing workflows (#1541)
12
+
3
13
  ## [integrations/pgvector-v3.0.1] - 2025-03-12
4
14
 
5
15
  ### 🌀 Miscellaneous
@@ -8,6 +18,7 @@
8
18
 
9
19
  ## [integrations/pgvector-v3.0.0] - 2025-03-11
10
20
 
21
+
11
22
  ### 🧹 Chores
12
23
 
13
24
  - Remove Python 3.8 support (#1421)
@@ -20,7 +31,6 @@
20
31
 
21
32
  - Pgvector - remove support for dataframe (#1370)
22
33
 
23
- ### 🌀 Miscellaneous
24
34
 
25
35
  ## [integrations/pgvector-v1.3.0] - 2025-02-03
26
36
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pgvector-haystack
3
- Version: 3.1.0
3
+ Version: 3.2.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
@@ -51,8 +51,12 @@ def _from_pg_to_haystack_documents(documents: List[Dict[str, Any]]) -> List[Docu
51
51
  blob_mime_type = haystack_dict.pop("blob_mime_type")
52
52
 
53
53
  # convert the embedding to a list of floats
54
+ # for strange reasons, halfvec and vector have different methods to convert the embedding to a list
54
55
  if document.get("embedding") is not None:
55
- haystack_dict["embedding"] = document["embedding"].tolist()
56
+ if hasattr(document["embedding"], "tolist"): # vector
57
+ haystack_dict["embedding"] = document["embedding"].tolist()
58
+ else: # halfvec
59
+ haystack_dict["embedding"] = document["embedding"].to_list()
56
60
 
57
61
  haystack_document = Document.from_dict(haystack_dict)
58
62
 
@@ -26,7 +26,7 @@ logger = logging.getLogger(__name__)
26
26
  CREATE_TABLE_STATEMENT = """
27
27
  CREATE TABLE {schema_name}.{table_name} (
28
28
  id VARCHAR(128) PRIMARY KEY,
29
- embedding VECTOR({embedding_dimension}),
29
+ embedding {embedding_col_type}({embedding_dimension}),
30
30
  content TEXT,
31
31
  blob_data BYTEA,
32
32
  blob_meta JSONB,
@@ -64,6 +64,12 @@ VECTOR_FUNCTION_TO_POSTGRESQL_OPS = {
64
64
  "l2_distance": "vector_l2_ops",
65
65
  }
66
66
 
67
+ HALF_VECTOR_FUNCTION_TO_POSTGRESQL_OPS = {
68
+ "cosine_similarity": "halfvec_cosine_ops",
69
+ "inner_product": "halfvec_ip_ops",
70
+ "l2_distance": "halfvec_l2_ops",
71
+ }
72
+
67
73
  HNSW_INDEX_CREATION_VALID_KWARGS = ["m", "ef_construction"]
68
74
 
69
75
 
@@ -81,6 +87,7 @@ class PgvectorDocumentStore:
81
87
  table_name: str = "haystack_documents",
82
88
  language: str = "english",
83
89
  embedding_dimension: int = 768,
90
+ vector_type: Literal["vector", "halfvec"] = "vector",
84
91
  vector_function: Literal["cosine_similarity", "inner_product", "l2_distance"] = "cosine_similarity",
85
92
  recreate_table: bool = False,
86
93
  search_strategy: Literal["exact_nearest_neighbor", "hnsw"] = "exact_nearest_neighbor",
@@ -112,6 +119,11 @@ class PgvectorDocumentStore:
112
119
  `SELECT cfgname FROM pg_ts_config;`.
113
120
  More information can be found in this [StackOverflow answer](https://stackoverflow.com/a/39752553).
114
121
  :param embedding_dimension: The dimension of the embedding.
122
+ :param vector_type: The type of vector used for embedding storage.
123
+ "vector" is the default.
124
+ "halfvec" stores embeddings in half-precision, which is particularly useful for high-dimensional embeddings
125
+ (dimension greater than 2,000 and up to 4,000). Requires pgvector versions 0.7.0 or later. For more
126
+ information, see the [pgvector documentation](https://github.com/pgvector/pgvector?tab=readme-ov-file).
115
127
  :param vector_function: The similarity function to use when searching for similar embeddings.
116
128
  `"cosine_similarity"` and `"inner_product"` are similarity functions and
117
129
  higher scores indicate greater similarity between the documents.
@@ -145,6 +157,10 @@ class PgvectorDocumentStore:
145
157
  self.table_name = table_name
146
158
  self.schema_name = schema_name
147
159
  self.embedding_dimension = embedding_dimension
160
+ if vector_type not in ["vector", "halfvec"]:
161
+ msg = "vector_type must be one of ['vector', 'halfvec']"
162
+ raise ValueError(msg)
163
+ self.vector_type = vector_type
148
164
  if vector_function not in VALID_VECTOR_FUNCTIONS:
149
165
  msg = f"vector_function must be one of {VALID_VECTOR_FUNCTIONS}, but got {vector_function}"
150
166
  raise ValueError(msg)
@@ -180,6 +196,7 @@ class PgvectorDocumentStore:
180
196
  schema_name=self.schema_name,
181
197
  table_name=self.table_name,
182
198
  embedding_dimension=self.embedding_dimension,
199
+ vector_type=self.vector_type,
183
200
  vector_function=self.vector_function,
184
201
  recreate_table=self.recreate_table,
185
202
  search_strategy=self.search_strategy,
@@ -376,6 +393,7 @@ class PgvectorDocumentStore:
376
393
  schema_name=Identifier(self.schema_name),
377
394
  table_name=Identifier(self.table_name),
378
395
  embedding_dimension=SQLLiteral(self.embedding_dimension),
396
+ embedding_col_type=SQL(self.vector_type),
379
397
  )
380
398
 
381
399
  sql_keyword_index_exists = SQL(
@@ -516,7 +534,16 @@ class PgvectorDocumentStore:
516
534
  index_name=Identifier(self.hnsw_index_name),
517
535
  )
518
536
 
519
- pg_ops = VECTOR_FUNCTION_TO_POSTGRESQL_OPS[self.vector_function]
537
+ if self.vector_type == "halfvec":
538
+ if self.vector_function not in HALF_VECTOR_FUNCTION_TO_POSTGRESQL_OPS:
539
+ msg = f"Unsupported vector_function '{self.vector_function}' for halfvec type."
540
+ raise ValueError(msg)
541
+ pg_ops = HALF_VECTOR_FUNCTION_TO_POSTGRESQL_OPS[self.vector_function]
542
+ else:
543
+ if self.vector_function not in VECTOR_FUNCTION_TO_POSTGRESQL_OPS:
544
+ msg = f"Unsupported vector_function '{self.vector_function}' for vector type."
545
+ raise ValueError(msg)
546
+ pg_ops = VECTOR_FUNCTION_TO_POSTGRESQL_OPS[self.vector_function]
520
547
 
521
548
  sql_create_hnsw_index = SQL(
522
549
  "CREATE INDEX {index_name} ON {schema_name}.{table_name} USING hnsw (embedding {ops})"
@@ -54,6 +54,30 @@ def document_store_w_hnsw_index(request, monkeypatch):
54
54
  store.delete_table()
55
55
 
56
56
 
57
+ @pytest.fixture
58
+ def document_store_w_halfvec_hnsw_index(request, monkeypatch):
59
+ monkeypatch.setenv("PG_CONN_STR", "postgresql://postgres:postgres@localhost:5432/postgres")
60
+ table_name = f"haystack_halfvec_hnsw_{request.node.name}"
61
+ embedding_dimension = 2500
62
+ vector_function = "cosine_similarity"
63
+ recreate_table = True
64
+
65
+ store = PgvectorDocumentStore(
66
+ table_name=table_name,
67
+ embedding_dimension=embedding_dimension,
68
+ vector_function=vector_function,
69
+ recreate_table=recreate_table,
70
+ search_strategy="hnsw",
71
+ vector_type="halfvec",
72
+ )
73
+ yield store
74
+
75
+ # Ensure connection just for table deletion.
76
+ # During test execution, the tested methods are expected to call _ensure_db_setup() themselves.
77
+ store._ensure_db_setup()
78
+ store.delete_table()
79
+
80
+
57
81
  @pytest.fixture
58
82
  def patches_for_unit_tests():
59
83
  with patch("haystack_integrations.document_stores.pgvector.document_store.register_vector") as mock_register, patch(
@@ -95,6 +95,7 @@ def test_to_dict(monkeypatch):
95
95
  create_extension=False,
96
96
  table_name="my_table",
97
97
  embedding_dimension=512,
98
+ vector_type="halfvec",
98
99
  vector_function="l2_distance",
99
100
  recreate_table=True,
100
101
  search_strategy="hnsw",
@@ -113,6 +114,7 @@ def test_to_dict(monkeypatch):
113
114
  "table_name": "my_table",
114
115
  "schema_name": "public",
115
116
  "embedding_dimension": 512,
117
+ "vector_type": "halfvec",
116
118
  "vector_function": "l2_distance",
117
119
  "recreate_table": True,
118
120
  "search_strategy": "hnsw",
@@ -126,6 +128,26 @@ def test_to_dict(monkeypatch):
126
128
  }
127
129
 
128
130
 
131
+ @pytest.mark.integration
132
+ def test_halfvec_hnsw_write_documents(document_store_w_halfvec_hnsw_index: PgvectorDocumentStore):
133
+ documents = [
134
+ Document(id="1", content="Hello, world!", embedding=[0.1] * 2500),
135
+ Document(id="2", content="Hello, mum!", embedding=[0.3] * 2500),
136
+ Document(id="3", content="Hello, dad!", embedding=[0.2] * 2500),
137
+ ]
138
+ document_store_w_halfvec_hnsw_index.write_documents(documents)
139
+
140
+ retrieved_docs = document_store_w_halfvec_hnsw_index.filter_documents()
141
+ retrieved_docs.sort(key=lambda x: x.id)
142
+
143
+ for original_doc, retrieved_doc in zip(documents, retrieved_docs):
144
+ assert original_doc.id == retrieved_doc.id
145
+ assert original_doc.content == retrieved_doc.content
146
+ assert len(original_doc.embedding) == len(retrieved_doc.embedding)
147
+ # these embeddings are in half precision, so we increase the tolerance
148
+ assert original_doc.embedding == pytest.approx(retrieved_doc.embedding, abs=5e-5)
149
+
150
+
129
151
  @pytest.mark.integration
130
152
  def test_hnsw_index_recreation():
131
153
  def get_index_oid(document_store, schema_name, index_name):
@@ -54,6 +54,7 @@ class TestEmbeddingRetriever:
54
54
  "schema_name": "public",
55
55
  "table_name": "haystack",
56
56
  "embedding_dimension": 768,
57
+ "vector_type": "vector",
57
58
  "vector_function": "cosine_similarity",
58
59
  "recreate_table": True,
59
60
  "search_strategy": "exact_nearest_neighbor",
@@ -198,6 +199,7 @@ class TestKeywordRetriever:
198
199
  "schema_name": "public",
199
200
  "table_name": "haystack",
200
201
  "embedding_dimension": 768,
202
+ "vector_type": "vector",
201
203
  "vector_function": "cosine_similarity",
202
204
  "recreate_table": True,
203
205
  "search_strategy": "exact_nearest_neighbor",