llama-index-vector-stores-postgres 0.4.0__tar.gz → 0.4.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: llama-index-vector-stores-postgres
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: llama-index vector_stores postgres integration
5
5
  License: MIT
6
6
  Author: Your Name
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3.10
13
13
  Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Requires-Dist: asyncpg (>=0.29.0,<1.0.0)
16
- Requires-Dist: llama-index-core (>=0.12.0,<0.13.0)
16
+ Requires-Dist: llama-index-core (>=0.12.6,<0.13.0)
17
17
  Requires-Dist: pgvector (>=0.3.6,<1.0.0)
18
18
  Requires-Dist: psycopg2-binary (>=2.9.9,<3.0.0)
19
19
  Requires-Dist: sqlalchemy[asyncio] (>=1.4.49,<2.1)
@@ -4,6 +4,7 @@ from typing import Any, Dict, List, NamedTuple, Optional, Type, Union, TYPE_CHEC
4
4
 
5
5
  import asyncpg # noqa
6
6
  import pgvector # noqa
7
+ from pgvector.sqlalchemy import HALFVEC
7
8
  import psycopg2 # noqa
8
9
  import sqlalchemy
9
10
  import sqlalchemy.ext.asyncio
@@ -46,6 +47,7 @@ def get_data_model(
46
47
  cache_okay: bool,
47
48
  embed_dim: int = 1536,
48
49
  use_jsonb: bool = False,
50
+ use_halfvec: bool = False,
49
51
  ) -> Any:
50
52
  """
51
53
  This part create a dynamic sqlalchemy model with a new table.
@@ -66,6 +68,11 @@ def get_data_model(
66
68
 
67
69
  metadata_dtype = JSONB if use_jsonb else JSON
68
70
 
71
+ if use_halfvec:
72
+ embedding_col = Column(HALFVEC(embed_dim)) # type: ignore
73
+ else:
74
+ embedding_col = Column(Vector(embed_dim)) # type: ignore
75
+
69
76
  if hybrid_search:
70
77
 
71
78
  class HybridAbstractData(base): # type: ignore
@@ -74,7 +81,7 @@ def get_data_model(
74
81
  text = Column(VARCHAR, nullable=False)
75
82
  metadata_ = Column(metadata_dtype)
76
83
  node_id = Column(VARCHAR)
77
- embedding = Column(Vector(embed_dim)) # type: ignore
84
+ embedding = embedding_col
78
85
  text_search_tsv = Column( # type: ignore
79
86
  TSVector(),
80
87
  Computed(
@@ -101,7 +108,7 @@ def get_data_model(
101
108
  text = Column(VARCHAR, nullable=False)
102
109
  metadata_ = Column(metadata_dtype)
103
110
  node_id = Column(VARCHAR)
104
- embedding = Column(Vector(embed_dim)) # type: ignore
111
+ embedding = embedding_col
105
112
 
106
113
  model = type(
107
114
  class_name,
@@ -130,6 +137,8 @@ class PGVectorStore(BasePydanticVectorStore):
130
137
  user="postgres",
131
138
  table_name="paul_graham_essay",
132
139
  embed_dim=1536 # openai embedding dimension
140
+ use_halfvec=True # Enable half precision
141
+
133
142
  )
134
143
  ```
135
144
  """
@@ -153,6 +162,8 @@ class PGVectorStore(BasePydanticVectorStore):
153
162
 
154
163
  hnsw_kwargs: Optional[Dict[str, Any]]
155
164
 
165
+ use_halfvec: bool = False
166
+
156
167
  _base: Any = PrivateAttr()
157
168
  _table_class: Any = PrivateAttr()
158
169
  _engine: Any = PrivateAttr()
@@ -177,6 +188,7 @@ class PGVectorStore(BasePydanticVectorStore):
177
188
  hnsw_kwargs: Optional[Dict[str, Any]] = None,
178
189
  create_engine_kwargs: Optional[Dict[str, Any]] = None,
179
190
  initialization_fail_on_error: bool = False,
191
+ use_halfvec: bool = False,
180
192
  ) -> None:
181
193
  """Constructor.
182
194
 
@@ -196,6 +208,7 @@ class PGVectorStore(BasePydanticVectorStore):
196
208
  contains "hnsw_ef_construction", "hnsw_ef_search", "hnsw_m", and optionally "hnsw_dist_method". Defaults to None,
197
209
  which turns off HNSW search.
198
210
  create_engine_kwargs (Optional[Dict[str, Any]], optional): Engine parameters to pass to create_engine. Defaults to None.
211
+ use_halfvec (bool, optional): If `True`, use half-precision vectors. Defaults to False.
199
212
  """
200
213
  table_name = table_name.lower()
201
214
  schema_name = schema_name.lower()
@@ -223,6 +236,7 @@ class PGVectorStore(BasePydanticVectorStore):
223
236
  hnsw_kwargs=hnsw_kwargs,
224
237
  create_engine_kwargs=create_engine_kwargs or {},
225
238
  initialization_fail_on_error=initialization_fail_on_error,
239
+ use_halfvec=use_halfvec,
226
240
  )
227
241
 
228
242
  # sqlalchemy model
@@ -236,6 +250,7 @@ class PGVectorStore(BasePydanticVectorStore):
236
250
  cache_ok,
237
251
  embed_dim=embed_dim,
238
252
  use_jsonb=use_jsonb,
253
+ use_halfvec=use_halfvec,
239
254
  )
240
255
 
241
256
  async def close(self) -> None:
@@ -272,6 +287,7 @@ class PGVectorStore(BasePydanticVectorStore):
272
287
  use_jsonb: bool = False,
273
288
  hnsw_kwargs: Optional[Dict[str, Any]] = None,
274
289
  create_engine_kwargs: Optional[Dict[str, Any]] = None,
290
+ use_halfvec: bool = False,
275
291
  ) -> "PGVectorStore":
276
292
  """Construct from params.
277
293
 
@@ -296,6 +312,7 @@ class PGVectorStore(BasePydanticVectorStore):
296
312
  contains "hnsw_ef_construction", "hnsw_ef_search", "hnsw_m", and optionally "hnsw_dist_method". Defaults to None,
297
313
  which turns off HNSW search.
298
314
  create_engine_kwargs (Optional[Dict[str, Any]], optional): Engine parameters to pass to create_engine. Defaults to None.
315
+ use_halfvec (bool, optional): If `True`, use half-precision vectors. Defaults to False.
299
316
 
300
317
  Returns:
301
318
  PGVectorStore: Instance of PGVectorStore constructed from params.
@@ -321,6 +338,7 @@ class PGVectorStore(BasePydanticVectorStore):
321
338
  use_jsonb=use_jsonb,
322
339
  hnsw_kwargs=hnsw_kwargs,
323
340
  create_engine_kwargs=create_engine_kwargs,
341
+ use_halfvec=use_halfvec,
324
342
  )
325
343
 
326
344
  @property
@@ -396,13 +414,25 @@ class PGVectorStore(BasePydanticVectorStore):
396
414
 
397
415
  hnsw_ef_construction = self.hnsw_kwargs.pop("hnsw_ef_construction")
398
416
  hnsw_m = self.hnsw_kwargs.pop("hnsw_m")
399
- hnsw_dist_method = self.hnsw_kwargs.pop("hnsw_dist_method", "vector_cosine_ops")
417
+
418
+ # If user didn’t specify an operator, pick a default based on whether halfvec is used
419
+ if "hnsw_dist_method" in self.hnsw_kwargs:
420
+ hnsw_dist_method = self.hnsw_kwargs.pop("hnsw_dist_method")
421
+ else:
422
+ if self.use_halfvec:
423
+ hnsw_dist_method = "halfvec_l2_ops"
424
+ else:
425
+ # Default to vector_cosine_ops
426
+ hnsw_dist_method = "vector_cosine_ops"
400
427
 
401
428
  index_name = f"{self._table_class.__tablename__}_embedding_idx"
402
429
 
403
430
  with self._session() as session, session.begin():
404
431
  statement = sqlalchemy.text(
405
- f"CREATE INDEX IF NOT EXISTS {index_name} ON {self.schema_name}.{self._table_class.__tablename__} USING hnsw (embedding {hnsw_dist_method}) WITH (m = {hnsw_m}, ef_construction = {hnsw_ef_construction})"
432
+ f"CREATE INDEX IF NOT EXISTS {index_name} "
433
+ f"ON {self.schema_name}.{self._table_class.__tablename__} "
434
+ f"USING hnsw (embedding {hnsw_dist_method}) "
435
+ f"WITH (m = {hnsw_m}, ef_construction = {hnsw_ef_construction})"
406
436
  )
407
437
  session.execute(statement)
408
438
  session.commit()
@@ -494,6 +524,8 @@ class PGVectorStore(BasePydanticVectorStore):
494
524
  return "@>"
495
525
  elif operator == FilterOperator.TEXT_MATCH:
496
526
  return "LIKE"
527
+ elif operator == FilterOperator.TEXT_MATCH_INSENSITIVE:
528
+ return "ILIKE"
497
529
  else:
498
530
  _logger.warning(f"Unknown operator: {operator}, fallback to '='")
499
531
  return "="
@@ -520,8 +552,11 @@ class PGVectorStore(BasePydanticVectorStore):
520
552
  f"{self._to_postgres_operator(filter_.operator)} "
521
553
  f"'[\"{filter_.value}\"]'"
522
554
  )
523
- elif filter_.operator == FilterOperator.TEXT_MATCH:
524
- # Where the operator is text_match, we need to wrap the filter in '%' characters
555
+ elif (
556
+ filter_.operator == FilterOperator.TEXT_MATCH
557
+ or filter_.operator == FilterOperator.TEXT_MATCH_INSENSITIVE
558
+ ):
559
+ # Where the operator is text_match or ilike, we need to wrap the filter in '%' characters
525
560
  return text(
526
561
  f"metadata_->>'{filter_.key}' "
527
562
  f"{self._to_postgres_operator(filter_.operator)} "
@@ -27,14 +27,14 @@ exclude = ["**/BUILD"]
27
27
  license = "MIT"
28
28
  name = "llama-index-vector-stores-postgres"
29
29
  readme = "README.md"
30
- version = "0.4.0"
30
+ version = "0.4.2"
31
31
 
32
32
  [tool.poetry.dependencies]
33
33
  python = ">=3.9,<4.0"
34
34
  pgvector = ">=0.3.6,<1.0.0"
35
35
  psycopg2-binary = ">=2.9.9,<3.0.0"
36
36
  asyncpg = ">=0.29.0,<1.0.0"
37
- llama-index-core = "^0.12.0"
37
+ llama-index-core = "^0.12.6"
38
38
 
39
39
  [tool.poetry.dependencies.sqlalchemy]
40
40
  extras = ["asyncio"]