pgvector 0.3.6__tar.gz → 0.4.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 (65) hide show
  1. {pgvector-0.3.6 → pgvector-0.4.0}/LICENSE.txt +1 -1
  2. {pgvector-0.3.6 → pgvector-0.4.0}/PKG-INFO +256 -7
  3. {pgvector-0.3.6 → pgvector-0.4.0}/README.md +253 -4
  4. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/asyncpg/__init__.py +3 -1
  5. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/asyncpg/register.py +1 -1
  6. pgvector-0.4.0/pgvector/bit.py +75 -0
  7. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/django/__init__.py +3 -1
  8. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/django/functions.py +5 -1
  9. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/django/halfvec.py +1 -1
  10. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/django/sparsevec.py +1 -1
  11. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/django/vector.py +1 -1
  12. {pgvector-0.3.6/pgvector/utils → pgvector-0.4.0/pgvector}/halfvec.py +5 -0
  13. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/peewee/__init__.py +3 -1
  14. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/peewee/halfvec.py +1 -1
  15. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/peewee/sparsevec.py +1 -1
  16. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/peewee/vector.py +1 -1
  17. pgvector-0.4.0/pgvector/pg8000/__init__.py +5 -0
  18. pgvector-0.4.0/pgvector/pg8000/register.py +23 -0
  19. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/psycopg/__init__.py +3 -1
  20. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/psycopg/bit.py +1 -1
  21. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/psycopg/halfvec.py +1 -1
  22. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/psycopg/sparsevec.py +1 -1
  23. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/psycopg/vector.py +1 -1
  24. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/psycopg2/__init__.py +3 -1
  25. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/psycopg2/halfvec.py +1 -1
  26. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/psycopg2/register.py +1 -3
  27. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/psycopg2/sparsevec.py +1 -1
  28. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/psycopg2/vector.py +2 -1
  29. {pgvector-0.3.6/pgvector/utils → pgvector-0.4.0/pgvector}/sparsevec.py +6 -1
  30. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/sqlalchemy/__init__.py +3 -1
  31. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/sqlalchemy/halfvec.py +1 -1
  32. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/sqlalchemy/sparsevec.py +1 -1
  33. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/sqlalchemy/vector.py +1 -1
  34. pgvector-0.4.0/pgvector/utils/__init__.py +9 -0
  35. {pgvector-0.3.6/pgvector/utils → pgvector-0.4.0/pgvector}/vector.py +5 -0
  36. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector.egg-info/PKG-INFO +256 -7
  37. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector.egg-info/SOURCES.txt +8 -4
  38. {pgvector-0.3.6 → pgvector-0.4.0}/pyproject.toml +2 -2
  39. {pgvector-0.3.6 → pgvector-0.4.0}/tests/test_asyncpg.py +32 -19
  40. pgvector-0.4.0/tests/test_bit.py +63 -0
  41. {pgvector-0.3.6 → pgvector-0.4.0}/tests/test_django.py +40 -19
  42. {pgvector-0.3.6 → pgvector-0.4.0}/tests/test_half_vector.py +18 -1
  43. {pgvector-0.3.6 → pgvector-0.4.0}/tests/test_peewee.py +12 -11
  44. pgvector-0.4.0/tests/test_pg8000.py +60 -0
  45. {pgvector-0.3.6 → pgvector-0.4.0}/tests/test_psycopg.py +45 -19
  46. {pgvector-0.3.6 → pgvector-0.4.0}/tests/test_psycopg2.py +51 -11
  47. {pgvector-0.3.6 → pgvector-0.4.0}/tests/test_sparse_vector.py +28 -3
  48. pgvector-0.4.0/tests/test_sqlalchemy.py +649 -0
  49. {pgvector-0.3.6 → pgvector-0.4.0}/tests/test_sqlmodel.py +44 -44
  50. {pgvector-0.3.6 → pgvector-0.4.0}/tests/test_vector.py +18 -1
  51. pgvector-0.3.6/pgvector/utils/bit.py +0 -61
  52. pgvector-0.3.6/tests/test_bit.py +0 -39
  53. pgvector-0.3.6/tests/test_sqlalchemy.py +0 -454
  54. {pgvector-0.3.6/pgvector/utils → pgvector-0.4.0/pgvector}/__init__.py +0 -0
  55. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/django/bit.py +0 -0
  56. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/django/extensions.py +0 -0
  57. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/django/indexes.py +0 -0
  58. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/peewee/bit.py +0 -0
  59. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/psycopg/register.py +0 -0
  60. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/sqlalchemy/bit.py +0 -0
  61. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector/sqlalchemy/functions.py +0 -0
  62. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector.egg-info/dependency_links.txt +0 -0
  63. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector.egg-info/requires.txt +0 -0
  64. {pgvector-0.3.6 → pgvector-0.4.0}/pgvector.egg-info/top_level.txt +0 -0
  65. {pgvector-0.3.6 → pgvector-0.4.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2021-2024 Andrew Kane
3
+ Copyright (c) 2021-2025 Andrew Kane
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,11 +1,11 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: pgvector
3
- Version: 0.3.6
3
+ Version: 0.4.0
4
4
  Summary: pgvector support for Python
5
5
  Author-email: Andrew Kane <andrew@ankane.org>
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/pgvector/pgvector-python
8
- Requires-Python: >=3.8
8
+ Requires-Python: >=3.9
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE.txt
11
11
  Requires-Dist: numpy
@@ -14,7 +14,7 @@ Requires-Dist: numpy
14
14
 
15
15
  [pgvector](https://github.com/pgvector/pgvector) support for Python
16
16
 
17
- Supports [Django](https://github.com/django/django), [SQLAlchemy](https://github.com/sqlalchemy/sqlalchemy), [SQLModel](https://github.com/tiangolo/sqlmodel), [Psycopg 3](https://github.com/psycopg/psycopg), [Psycopg 2](https://github.com/psycopg/psycopg2), [asyncpg](https://github.com/MagicStack/asyncpg), and [Peewee](https://github.com/coleifer/peewee)
17
+ Supports [Django](https://github.com/django/django), [SQLAlchemy](https://github.com/sqlalchemy/sqlalchemy), [SQLModel](https://github.com/tiangolo/sqlmodel), [Psycopg 3](https://github.com/psycopg/psycopg), [Psycopg 2](https://github.com/psycopg/psycopg2), [asyncpg](https://github.com/MagicStack/asyncpg), [pg8000](https://github.com/tlocke/pg8000), and [Peewee](https://github.com/coleifer/peewee)
18
18
 
19
19
  [![Build Status](https://github.com/pgvector/pgvector-python/actions/workflows/build.yml/badge.svg)](https://github.com/pgvector/pgvector-python/actions)
20
20
 
@@ -34,6 +34,7 @@ And follow the instructions for your database library:
34
34
  - [Psycopg 3](#psycopg-3)
35
35
  - [Psycopg 2](#psycopg-2)
36
36
  - [asyncpg](#asyncpg)
37
+ - [pg8000](#pg8000)
37
38
  - [Peewee](#peewee)
38
39
 
39
40
  Or check out some examples:
@@ -45,6 +46,7 @@ Or check out some examples:
45
46
  - [Hybrid search](https://github.com/pgvector/pgvector-python/blob/master/examples/hybrid_search/cross_encoder.py) with SentenceTransformers (cross-encoder)
46
47
  - [Sparse search](https://github.com/pgvector/pgvector-python/blob/master/examples/sparse_search/example.py) with Transformers
47
48
  - [Late interaction search](https://github.com/pgvector/pgvector-python/blob/master/examples/colbert/exact.py) with ColBERT
49
+ - [Visual document retrieval](https://github.com/pgvector/pgvector-python/blob/master/examples/colpali/exact.py) with ColPali
48
50
  - [Image search](https://github.com/pgvector/pgvector-python/blob/master/examples/image_search/example.py) with PyTorch
49
51
  - [Image search](https://github.com/pgvector/pgvector-python/blob/master/examples/imagehash/example.py) with perceptual hashing
50
52
  - [Morgan fingerprints](https://github.com/pgvector/pgvector-python/blob/master/examples/rdkit/example.py) with RDKit
@@ -145,6 +147,36 @@ class Item(models.Model):
145
147
 
146
148
  Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
147
149
 
150
+ #### Half-Precision Indexing
151
+
152
+ Index vectors at half-precision
153
+
154
+ ```python
155
+ from django.contrib.postgres.indexes import OpClass
156
+ from django.db.models.functions import Cast
157
+ from pgvector.django import HnswIndex, HalfVectorField
158
+
159
+ class Item(models.Model):
160
+ class Meta:
161
+ indexes = [
162
+ HnswIndex(
163
+ OpClass(Cast('embedding', HalfVectorField(dimensions=3)), name='halfvec_l2_ops'),
164
+ name='my_index',
165
+ m=16,
166
+ ef_construction=64
167
+ )
168
+ ]
169
+ ```
170
+
171
+ Note: Add `'django.contrib.postgres'` to `INSTALLED_APPS` to use `OpClass`
172
+
173
+ Get the nearest neighbors
174
+
175
+ ```python
176
+ distance = L2Distance(Cast('embedding', HalfVectorField(dimensions=3)), [3, 1, 2])
177
+ Item.objects.order_by(distance)[:5]
178
+ ```
179
+
148
180
  ## SQLAlchemy
149
181
 
150
182
  Enable the extension
@@ -226,6 +258,77 @@ index.create(engine)
226
258
 
227
259
  Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
228
260
 
261
+ #### Half-Precision Indexing
262
+
263
+ Index vectors at half-precision
264
+
265
+ ```python
266
+ from pgvector.sqlalchemy import HALFVEC
267
+ from sqlalchemy.sql import func
268
+
269
+ index = Index(
270
+ 'my_index',
271
+ func.cast(Item.embedding, HALFVEC(3)).label('embedding'),
272
+ postgresql_using='hnsw',
273
+ postgresql_with={'m': 16, 'ef_construction': 64},
274
+ postgresql_ops={'embedding': 'halfvec_l2_ops'}
275
+ )
276
+ ```
277
+
278
+ Get the nearest neighbors
279
+
280
+ ```python
281
+ order = func.cast(Item.embedding, HALFVEC(3)).l2_distance([3, 1, 2])
282
+ session.scalars(select(Item).order_by(order).limit(5))
283
+ ```
284
+
285
+ #### Arrays
286
+
287
+ Add an array column
288
+
289
+ ```python
290
+ from pgvector.sqlalchemy import Vector
291
+ from sqlalchemy import ARRAY
292
+
293
+ class Item(Base):
294
+ embeddings = mapped_column(ARRAY(Vector(3)))
295
+ ```
296
+
297
+ And register the types with the underlying driver
298
+
299
+ For Psycopg 3, use
300
+
301
+ ```python
302
+ from pgvector.psycopg import register_vector
303
+ from sqlalchemy import event
304
+
305
+ @event.listens_for(engine, "connect")
306
+ def connect(dbapi_connection, connection_record):
307
+ register_vector(dbapi_connection)
308
+ ```
309
+
310
+ For [async connections](https://docs.sqlalchemy.org/en/20/orm/extensions/asyncio.html) with Psycopg 3, use
311
+
312
+ ```python
313
+ from pgvector.psycopg import register_vector_async
314
+ from sqlalchemy import event
315
+
316
+ @event.listens_for(engine.sync_engine, "connect")
317
+ def connect(dbapi_connection, connection_record):
318
+ dbapi_connection.run_async(register_vector_async)
319
+ ```
320
+
321
+ For Psycopg 2, use
322
+
323
+ ```python
324
+ from pgvector.psycopg2 import register_vector
325
+ from sqlalchemy import event
326
+
327
+ @event.listens_for(engine, "connect")
328
+ def connect(dbapi_connection, connection_record):
329
+ register_vector(dbapi_connection, arrays=True)
330
+ ```
331
+
229
332
  ## SQLModel
230
333
 
231
334
  Enable the extension
@@ -238,10 +341,9 @@ Add a vector column
238
341
 
239
342
  ```python
240
343
  from pgvector.sqlalchemy import Vector
241
- from sqlalchemy import Column
242
344
 
243
345
  class Item(SQLModel, table=True):
244
- embedding: Any = Field(sa_column=Column(Vector(3)))
346
+ embedding: Any = Field(sa_type=Vector(3))
245
347
  ```
246
348
 
247
349
  Also supports `HALFVEC`, `BIT`, and `SPARSEVEC`
@@ -287,7 +389,7 @@ Also supports `sum`
287
389
  Add an approximate index
288
390
 
289
391
  ```python
290
- from sqlalchemy import Index
392
+ from sqlmodel import Index
291
393
 
292
394
  index = Index(
293
395
  'my_index',
@@ -326,6 +428,15 @@ from pgvector.psycopg import register_vector
326
428
  register_vector(conn)
327
429
  ```
328
430
 
431
+ For [connection pools](https://www.psycopg.org/psycopg3/docs/advanced/pool.html), use
432
+
433
+ ```python
434
+ def configure(conn):
435
+ register_vector(conn)
436
+
437
+ pool = ConnectionPool(..., configure=configure)
438
+ ```
439
+
329
440
  For [async connections](https://www.psycopg.org/psycopg3/docs/advanced/async.html), use
330
441
 
331
442
  ```python
@@ -464,6 +575,51 @@ await conn.execute('CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops
464
575
 
465
576
  Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
466
577
 
578
+ ## pg8000
579
+
580
+ Enable the extension
581
+
582
+ ```python
583
+ conn.run('CREATE EXTENSION IF NOT EXISTS vector')
584
+ ```
585
+
586
+ Register the vector type with your connection
587
+
588
+ ```python
589
+ from pgvector.pg8000 import register_vector
590
+
591
+ register_vector(conn)
592
+ ```
593
+
594
+ Create a table
595
+
596
+ ```python
597
+ conn.run('CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3))')
598
+ ```
599
+
600
+ Insert a vector
601
+
602
+ ```python
603
+ embedding = np.array([1, 2, 3])
604
+ conn.run('INSERT INTO items (embedding) VALUES (:embedding)', embedding=embedding)
605
+ ```
606
+
607
+ Get the nearest neighbors to a vector
608
+
609
+ ```python
610
+ conn.run('SELECT * FROM items ORDER BY embedding <-> :embedding LIMIT 5', embedding=embedding)
611
+ ```
612
+
613
+ Add an approximate index
614
+
615
+ ```python
616
+ conn.run('CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)')
617
+ # or
618
+ conn.run('CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)')
619
+ ```
620
+
621
+ Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
622
+
467
623
  ## Peewee
468
624
 
469
625
  Add a vector column
@@ -521,6 +677,99 @@ Item.add_index('embedding vector_l2_ops', using='hnsw')
521
677
 
522
678
  Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
523
679
 
680
+ ## Reference
681
+
682
+ ### Half Vectors
683
+
684
+ Create a half vector from a list
685
+
686
+ ```python
687
+ vec = HalfVector([1, 2, 3])
688
+ ```
689
+
690
+ Or a NumPy array
691
+
692
+ ```python
693
+ vec = HalfVector(np.array([1, 2, 3]))
694
+ ```
695
+
696
+ Get a list
697
+
698
+ ```python
699
+ lst = vec.to_list()
700
+ ```
701
+
702
+ Get a NumPy array
703
+
704
+ ```python
705
+ arr = vec.to_numpy()
706
+ ```
707
+
708
+ ### Sparse Vectors
709
+
710
+ Create a sparse vector from a list
711
+
712
+ ```python
713
+ vec = SparseVector([1, 0, 2, 0, 3, 0])
714
+ ```
715
+
716
+ Or a NumPy array
717
+
718
+ ```python
719
+ vec = SparseVector(np.array([1, 0, 2, 0, 3, 0]))
720
+ ```
721
+
722
+ Or a SciPy sparse array
723
+
724
+ ```python
725
+ arr = coo_array(([1, 2, 3], ([0, 2, 4],)), shape=(6,))
726
+ vec = SparseVector(arr)
727
+ ```
728
+
729
+ Or a dictionary of non-zero elements
730
+
731
+ ```python
732
+ vec = SparseVector({0: 1, 2: 2, 4: 3}, 6)
733
+ ```
734
+
735
+ Note: Indices start at 0
736
+
737
+ Get the number of dimensions
738
+
739
+ ```python
740
+ dim = vec.dimensions()
741
+ ```
742
+
743
+ Get the indices of non-zero elements
744
+
745
+ ```python
746
+ indices = vec.indices()
747
+ ```
748
+
749
+ Get the values of non-zero elements
750
+
751
+ ```python
752
+ values = vec.values()
753
+ ```
754
+
755
+ Get a list
756
+
757
+ ```python
758
+ lst = vec.to_list()
759
+ ```
760
+
761
+ Get a NumPy array
762
+
763
+ ```python
764
+ arr = vec.to_numpy()
765
+ ```
766
+
767
+ Get a SciPy sparse array
768
+
769
+ ```python
770
+ arr = vec.to_coo()
771
+ ```
772
+
524
773
  ## History
525
774
 
526
775
  View the [changelog](https://github.com/pgvector/pgvector-python/blob/master/CHANGELOG.md)
@@ -2,7 +2,7 @@
2
2
 
3
3
  [pgvector](https://github.com/pgvector/pgvector) support for Python
4
4
 
5
- Supports [Django](https://github.com/django/django), [SQLAlchemy](https://github.com/sqlalchemy/sqlalchemy), [SQLModel](https://github.com/tiangolo/sqlmodel), [Psycopg 3](https://github.com/psycopg/psycopg), [Psycopg 2](https://github.com/psycopg/psycopg2), [asyncpg](https://github.com/MagicStack/asyncpg), and [Peewee](https://github.com/coleifer/peewee)
5
+ Supports [Django](https://github.com/django/django), [SQLAlchemy](https://github.com/sqlalchemy/sqlalchemy), [SQLModel](https://github.com/tiangolo/sqlmodel), [Psycopg 3](https://github.com/psycopg/psycopg), [Psycopg 2](https://github.com/psycopg/psycopg2), [asyncpg](https://github.com/MagicStack/asyncpg), [pg8000](https://github.com/tlocke/pg8000), and [Peewee](https://github.com/coleifer/peewee)
6
6
 
7
7
  [![Build Status](https://github.com/pgvector/pgvector-python/actions/workflows/build.yml/badge.svg)](https://github.com/pgvector/pgvector-python/actions)
8
8
 
@@ -22,6 +22,7 @@ And follow the instructions for your database library:
22
22
  - [Psycopg 3](#psycopg-3)
23
23
  - [Psycopg 2](#psycopg-2)
24
24
  - [asyncpg](#asyncpg)
25
+ - [pg8000](#pg8000)
25
26
  - [Peewee](#peewee)
26
27
 
27
28
  Or check out some examples:
@@ -33,6 +34,7 @@ Or check out some examples:
33
34
  - [Hybrid search](https://github.com/pgvector/pgvector-python/blob/master/examples/hybrid_search/cross_encoder.py) with SentenceTransformers (cross-encoder)
34
35
  - [Sparse search](https://github.com/pgvector/pgvector-python/blob/master/examples/sparse_search/example.py) with Transformers
35
36
  - [Late interaction search](https://github.com/pgvector/pgvector-python/blob/master/examples/colbert/exact.py) with ColBERT
37
+ - [Visual document retrieval](https://github.com/pgvector/pgvector-python/blob/master/examples/colpali/exact.py) with ColPali
36
38
  - [Image search](https://github.com/pgvector/pgvector-python/blob/master/examples/image_search/example.py) with PyTorch
37
39
  - [Image search](https://github.com/pgvector/pgvector-python/blob/master/examples/imagehash/example.py) with perceptual hashing
38
40
  - [Morgan fingerprints](https://github.com/pgvector/pgvector-python/blob/master/examples/rdkit/example.py) with RDKit
@@ -133,6 +135,36 @@ class Item(models.Model):
133
135
 
134
136
  Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
135
137
 
138
+ #### Half-Precision Indexing
139
+
140
+ Index vectors at half-precision
141
+
142
+ ```python
143
+ from django.contrib.postgres.indexes import OpClass
144
+ from django.db.models.functions import Cast
145
+ from pgvector.django import HnswIndex, HalfVectorField
146
+
147
+ class Item(models.Model):
148
+ class Meta:
149
+ indexes = [
150
+ HnswIndex(
151
+ OpClass(Cast('embedding', HalfVectorField(dimensions=3)), name='halfvec_l2_ops'),
152
+ name='my_index',
153
+ m=16,
154
+ ef_construction=64
155
+ )
156
+ ]
157
+ ```
158
+
159
+ Note: Add `'django.contrib.postgres'` to `INSTALLED_APPS` to use `OpClass`
160
+
161
+ Get the nearest neighbors
162
+
163
+ ```python
164
+ distance = L2Distance(Cast('embedding', HalfVectorField(dimensions=3)), [3, 1, 2])
165
+ Item.objects.order_by(distance)[:5]
166
+ ```
167
+
136
168
  ## SQLAlchemy
137
169
 
138
170
  Enable the extension
@@ -214,6 +246,77 @@ index.create(engine)
214
246
 
215
247
  Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
216
248
 
249
+ #### Half-Precision Indexing
250
+
251
+ Index vectors at half-precision
252
+
253
+ ```python
254
+ from pgvector.sqlalchemy import HALFVEC
255
+ from sqlalchemy.sql import func
256
+
257
+ index = Index(
258
+ 'my_index',
259
+ func.cast(Item.embedding, HALFVEC(3)).label('embedding'),
260
+ postgresql_using='hnsw',
261
+ postgresql_with={'m': 16, 'ef_construction': 64},
262
+ postgresql_ops={'embedding': 'halfvec_l2_ops'}
263
+ )
264
+ ```
265
+
266
+ Get the nearest neighbors
267
+
268
+ ```python
269
+ order = func.cast(Item.embedding, HALFVEC(3)).l2_distance([3, 1, 2])
270
+ session.scalars(select(Item).order_by(order).limit(5))
271
+ ```
272
+
273
+ #### Arrays
274
+
275
+ Add an array column
276
+
277
+ ```python
278
+ from pgvector.sqlalchemy import Vector
279
+ from sqlalchemy import ARRAY
280
+
281
+ class Item(Base):
282
+ embeddings = mapped_column(ARRAY(Vector(3)))
283
+ ```
284
+
285
+ And register the types with the underlying driver
286
+
287
+ For Psycopg 3, use
288
+
289
+ ```python
290
+ from pgvector.psycopg import register_vector
291
+ from sqlalchemy import event
292
+
293
+ @event.listens_for(engine, "connect")
294
+ def connect(dbapi_connection, connection_record):
295
+ register_vector(dbapi_connection)
296
+ ```
297
+
298
+ For [async connections](https://docs.sqlalchemy.org/en/20/orm/extensions/asyncio.html) with Psycopg 3, use
299
+
300
+ ```python
301
+ from pgvector.psycopg import register_vector_async
302
+ from sqlalchemy import event
303
+
304
+ @event.listens_for(engine.sync_engine, "connect")
305
+ def connect(dbapi_connection, connection_record):
306
+ dbapi_connection.run_async(register_vector_async)
307
+ ```
308
+
309
+ For Psycopg 2, use
310
+
311
+ ```python
312
+ from pgvector.psycopg2 import register_vector
313
+ from sqlalchemy import event
314
+
315
+ @event.listens_for(engine, "connect")
316
+ def connect(dbapi_connection, connection_record):
317
+ register_vector(dbapi_connection, arrays=True)
318
+ ```
319
+
217
320
  ## SQLModel
218
321
 
219
322
  Enable the extension
@@ -226,10 +329,9 @@ Add a vector column
226
329
 
227
330
  ```python
228
331
  from pgvector.sqlalchemy import Vector
229
- from sqlalchemy import Column
230
332
 
231
333
  class Item(SQLModel, table=True):
232
- embedding: Any = Field(sa_column=Column(Vector(3)))
334
+ embedding: Any = Field(sa_type=Vector(3))
233
335
  ```
234
336
 
235
337
  Also supports `HALFVEC`, `BIT`, and `SPARSEVEC`
@@ -275,7 +377,7 @@ Also supports `sum`
275
377
  Add an approximate index
276
378
 
277
379
  ```python
278
- from sqlalchemy import Index
380
+ from sqlmodel import Index
279
381
 
280
382
  index = Index(
281
383
  'my_index',
@@ -314,6 +416,15 @@ from pgvector.psycopg import register_vector
314
416
  register_vector(conn)
315
417
  ```
316
418
 
419
+ For [connection pools](https://www.psycopg.org/psycopg3/docs/advanced/pool.html), use
420
+
421
+ ```python
422
+ def configure(conn):
423
+ register_vector(conn)
424
+
425
+ pool = ConnectionPool(..., configure=configure)
426
+ ```
427
+
317
428
  For [async connections](https://www.psycopg.org/psycopg3/docs/advanced/async.html), use
318
429
 
319
430
  ```python
@@ -452,6 +563,51 @@ await conn.execute('CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops
452
563
 
453
564
  Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
454
565
 
566
+ ## pg8000
567
+
568
+ Enable the extension
569
+
570
+ ```python
571
+ conn.run('CREATE EXTENSION IF NOT EXISTS vector')
572
+ ```
573
+
574
+ Register the vector type with your connection
575
+
576
+ ```python
577
+ from pgvector.pg8000 import register_vector
578
+
579
+ register_vector(conn)
580
+ ```
581
+
582
+ Create a table
583
+
584
+ ```python
585
+ conn.run('CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3))')
586
+ ```
587
+
588
+ Insert a vector
589
+
590
+ ```python
591
+ embedding = np.array([1, 2, 3])
592
+ conn.run('INSERT INTO items (embedding) VALUES (:embedding)', embedding=embedding)
593
+ ```
594
+
595
+ Get the nearest neighbors to a vector
596
+
597
+ ```python
598
+ conn.run('SELECT * FROM items ORDER BY embedding <-> :embedding LIMIT 5', embedding=embedding)
599
+ ```
600
+
601
+ Add an approximate index
602
+
603
+ ```python
604
+ conn.run('CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)')
605
+ # or
606
+ conn.run('CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)')
607
+ ```
608
+
609
+ Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
610
+
455
611
  ## Peewee
456
612
 
457
613
  Add a vector column
@@ -509,6 +665,99 @@ Item.add_index('embedding vector_l2_ops', using='hnsw')
509
665
 
510
666
  Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
511
667
 
668
+ ## Reference
669
+
670
+ ### Half Vectors
671
+
672
+ Create a half vector from a list
673
+
674
+ ```python
675
+ vec = HalfVector([1, 2, 3])
676
+ ```
677
+
678
+ Or a NumPy array
679
+
680
+ ```python
681
+ vec = HalfVector(np.array([1, 2, 3]))
682
+ ```
683
+
684
+ Get a list
685
+
686
+ ```python
687
+ lst = vec.to_list()
688
+ ```
689
+
690
+ Get a NumPy array
691
+
692
+ ```python
693
+ arr = vec.to_numpy()
694
+ ```
695
+
696
+ ### Sparse Vectors
697
+
698
+ Create a sparse vector from a list
699
+
700
+ ```python
701
+ vec = SparseVector([1, 0, 2, 0, 3, 0])
702
+ ```
703
+
704
+ Or a NumPy array
705
+
706
+ ```python
707
+ vec = SparseVector(np.array([1, 0, 2, 0, 3, 0]))
708
+ ```
709
+
710
+ Or a SciPy sparse array
711
+
712
+ ```python
713
+ arr = coo_array(([1, 2, 3], ([0, 2, 4],)), shape=(6,))
714
+ vec = SparseVector(arr)
715
+ ```
716
+
717
+ Or a dictionary of non-zero elements
718
+
719
+ ```python
720
+ vec = SparseVector({0: 1, 2: 2, 4: 3}, 6)
721
+ ```
722
+
723
+ Note: Indices start at 0
724
+
725
+ Get the number of dimensions
726
+
727
+ ```python
728
+ dim = vec.dimensions()
729
+ ```
730
+
731
+ Get the indices of non-zero elements
732
+
733
+ ```python
734
+ indices = vec.indices()
735
+ ```
736
+
737
+ Get the values of non-zero elements
738
+
739
+ ```python
740
+ values = vec.values()
741
+ ```
742
+
743
+ Get a list
744
+
745
+ ```python
746
+ lst = vec.to_list()
747
+ ```
748
+
749
+ Get a NumPy array
750
+
751
+ ```python
752
+ arr = vec.to_numpy()
753
+ ```
754
+
755
+ Get a SciPy sparse array
756
+
757
+ ```python
758
+ arr = vec.to_coo()
759
+ ```
760
+
512
761
  ## History
513
762
 
514
763
  View the [changelog](https://github.com/pgvector/pgvector-python/blob/master/CHANGELOG.md)
@@ -1,5 +1,7 @@
1
1
  from .register import register_vector
2
- from ..utils import Vector, HalfVector, SparseVector
2
+
3
+ # TODO remove
4
+ from .. import Vector, HalfVector, SparseVector
3
5
 
4
6
  __all__ = [
5
7
  'register_vector',
@@ -1,4 +1,4 @@
1
- from ..utils import Vector, HalfVector, SparseVector
1
+ from .. import Vector, HalfVector, SparseVector
2
2
 
3
3
 
4
4
  async def register_vector(conn, schema='public'):