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