agent-framework-postgres 0.0.0a1__tar.gz → 1.0.0a260910__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.
- agent_framework_postgres-1.0.0a260910/PKG-INFO +166 -0
- agent_framework_postgres-1.0.0a260910/README.md +140 -0
- agent_framework_postgres-1.0.0a260910/agent_framework_postgres/__init__.py +16 -0
- agent_framework_postgres-1.0.0a260910/agent_framework_postgres/_vector_store.py +943 -0
- agent_framework_postgres-1.0.0a260910/pyproject.toml +60 -0
- agent_framework_postgres-0.0.0a1/PKG-INFO +0 -10
- agent_framework_postgres-0.0.0a1/README.md +0 -1
- agent_framework_postgres-0.0.0a1/agent_framework/postgres/__init__.py +0 -2
- agent_framework_postgres-0.0.0a1/pyproject.toml +0 -26
- {agent_framework_postgres-0.0.0a1 → agent_framework_postgres-1.0.0a260910}/LICENSE +0 -0
- /agent_framework_postgres-0.0.0a1/agent_framework/__init__.py → /agent_framework_postgres-1.0.0a260910/agent_framework_postgres/py.typed +0 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-framework-postgres
|
|
3
|
+
Version: 1.0.0a260910
|
|
4
|
+
Summary: PostgreSQL and pgvector integration for Microsoft Agent Framework.
|
|
5
|
+
Author-email: Microsoft <af-support@microsoft.com>
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: agent-framework-core>=1.18.0,<2
|
|
20
|
+
Requires-Dist: psycopg[binary, pool]>=3.3.5,<4
|
|
21
|
+
Requires-Dist: pgvector>=0.5.0,<0.6
|
|
22
|
+
Project-URL: homepage, https://aka.ms/agent-framework
|
|
23
|
+
Project-URL: issues, https://github.com/microsoft/agent-framework/issues
|
|
24
|
+
Project-URL: source, https://github.com/microsoft/agent-framework/tree/main/python
|
|
25
|
+
|
|
26
|
+
# Agent Framework PostgreSQL / pgvector
|
|
27
|
+
|
|
28
|
+
Store and search vector records in PostgreSQL with this alpha integration for
|
|
29
|
+
[Microsoft Agent Framework](https://learn.microsoft.com/agent-framework/).
|
|
30
|
+
The package uses Psycopg 3 and the official pgvector Python adapter.
|
|
31
|
+
|
|
32
|
+
- **`PostgresCollection`** provides batch upsert, retrieval, deletion, and vector similarity search.
|
|
33
|
+
- **`PostgresStore`** creates collection clients that share a connection pool.
|
|
34
|
+
- **`PostgresSettings`** describes connection settings resolved by Agent Framework.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install agent-framework-postgres --pre
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Requires Python 3.10+, PostgreSQL 13+, and pgvector 0.8.0+.
|
|
43
|
+
Import the connector directly from `agent_framework_postgres`.
|
|
44
|
+
|
|
45
|
+
## Connection setup
|
|
46
|
+
|
|
47
|
+
Have your database administrator install and enable the `vector` extension and
|
|
48
|
+
provide an existing schema. The extension must be visible through the connection's
|
|
49
|
+
`search_path`. The connector never creates schemas, enables extensions, or changes
|
|
50
|
+
server-wide configuration. `ensure_collection_exists()` explicitly creates the
|
|
51
|
+
table and requested indexes; it requires the corresponding permissions and does
|
|
52
|
+
not migrate existing tables.
|
|
53
|
+
|
|
54
|
+
Set `POSTGRES_CONNECTION_STRING` to a PostgreSQL URI or Psycopg conninfo string,
|
|
55
|
+
or pass `connection_string` to either constructor. Both accept a string or AF
|
|
56
|
+
`SecretString`. Settings precedence is **explicit argument > selected `.env`
|
|
57
|
+
file > environment**. Select a file with `env_file_path` and optional
|
|
58
|
+
`env_file_encoding`; missing or empty connection strings are rejected.
|
|
59
|
+
The `schema` argument defaults to `public`.
|
|
60
|
+
|
|
61
|
+
A connector-created pool is closed by `close()` or an async context manager.
|
|
62
|
+
Alternatively, inject an open Psycopg `AsyncConnection` or `AsyncConnectionPool`
|
|
63
|
+
using `client`; it remains caller-owned and bypasses settings loading.
|
|
64
|
+
Injected clients cannot be combined with connection-string or `.env` options.
|
|
65
|
+
Collections created by a store borrow its pool, so keep the store open while
|
|
66
|
+
using them.
|
|
67
|
+
|
|
68
|
+
## Example
|
|
69
|
+
|
|
70
|
+
With `POSTGRES_CONNECTION_STRING` configured, create a typed collection and
|
|
71
|
+
search using precomputed embeddings:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import asyncio
|
|
75
|
+
from dataclasses import dataclass
|
|
76
|
+
from typing import Annotated
|
|
77
|
+
|
|
78
|
+
from agent_framework import Filter, VectorStoreField, vectorstoremodel
|
|
79
|
+
from agent_framework_postgres import PostgresStore
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@vectorstoremodel(collection_name="articles")
|
|
83
|
+
@dataclass
|
|
84
|
+
class Article:
|
|
85
|
+
id: Annotated[str, VectorStoreField("key")]
|
|
86
|
+
text: Annotated[str, VectorStoreField("data")]
|
|
87
|
+
embedding: Annotated[list[float] | None, VectorStoreField("vector", dimensions=3)] = None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
async def main() -> None:
|
|
91
|
+
async with PostgresStore() as store:
|
|
92
|
+
collection = store.get_collection(Article)
|
|
93
|
+
await collection.ensure_collection_exists()
|
|
94
|
+
await collection.upsert(
|
|
95
|
+
[
|
|
96
|
+
Article("1", "PostgreSQL supports vectors", [1, 0, 0]),
|
|
97
|
+
Article("2", "A travel journal", [0, 1, 0]),
|
|
98
|
+
],
|
|
99
|
+
generate_vectors=False,
|
|
100
|
+
)
|
|
101
|
+
results = await collection.search(
|
|
102
|
+
vector=[1, 0, 0],
|
|
103
|
+
filter=Filter("text", "contains_text", "PostgreSQL"),
|
|
104
|
+
score_threshold=0.25,
|
|
105
|
+
top=3,
|
|
106
|
+
)
|
|
107
|
+
async for result in results:
|
|
108
|
+
print(result["record"].text, result["score"])
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
if __name__ == "__main__":
|
|
112
|
+
asyncio.run(main())
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Pass `generate_vectors=False` to preserve supplied embeddings. To generate them
|
|
116
|
+
locally, configure an `embedding_generator`. Retrieval excludes embeddings by
|
|
117
|
+
default; use `include_vectors=True` to return them.
|
|
118
|
+
|
|
119
|
+
## Capabilities and limits
|
|
120
|
+
|
|
121
|
+
The connector supports typed models, string/integer/UUID keys (including generated
|
|
122
|
+
keys), multiple nullable vector columns, storage aliases, and database-side
|
|
123
|
+
filters and paging. Batch writes are transactional; an existing transaction on
|
|
124
|
+
an injected connection remains under the caller's commit control.
|
|
125
|
+
|
|
126
|
+
Vector fields support `float`, `float32`, and `float16` declarations. PostgreSQL
|
|
127
|
+
`vector` storage uses 32-bit floats; `float16` defaults to 16-bit `halfvec`.
|
|
128
|
+
The `postgres.vector_type` provider annotation explicitly selects either storage
|
|
129
|
+
type. Ordinary Python floats and integer-valued elements are accepted and rounded
|
|
130
|
+
to the selected precision; declared `int` and `float64` vector fields are rejected.
|
|
131
|
+
|
|
132
|
+
Storage precision does not determine the model's Python scalar type. The default
|
|
133
|
+
decoder returns ordinary Python floats: use `list[float]` annotations even with
|
|
134
|
+
explicit `float16` or `float32` field metadata. Models annotated with
|
|
135
|
+
`list[numpy.float16]` or `list[numpy.float32]` require a custom `decoder` passed to
|
|
136
|
+
`vectorstoremodel` or `register_vectorstoremodel`. That decoder must reconstruct
|
|
137
|
+
each component with the declared NumPy scalar type and handle omitted vector
|
|
138
|
+
fields when `include_vectors=False`. NumPy is not a connector runtime dependency.
|
|
139
|
+
|
|
140
|
+
Exact search is the default. HNSW and IVFFlat are optional approximate indexes;
|
|
141
|
+
selective filters can reduce their recall. Use
|
|
142
|
+
`operation_options={"exact": True}` when complete recall is required.
|
|
143
|
+
`exact=False` requires an HNSW or IVFFlat field. Result metadata's `approximate`
|
|
144
|
+
flag identifies ANN-permitted query mode, not proof that PostgreSQL used an ANN
|
|
145
|
+
index.
|
|
146
|
+
IVFFlat needs data before index creation: first call
|
|
147
|
+
`ensure_collection_exists(operation_options={"create_indexes": False})`, load
|
|
148
|
+
records, then call `ensure_collection_exists()` again.
|
|
149
|
+
Storage supports up to 16,000 dimensions; ANN indexes support up to 2,000 for
|
|
150
|
+
`vector` and 4,000 for `halfvec`.
|
|
151
|
+
|
|
152
|
+
Scores use the selected metric's units, not probabilities. The default is cosine
|
|
153
|
+
distance, where lower is better and `score_threshold` is a maximum. Cosine
|
|
154
|
+
similarity and dot product use minimum thresholds; negative dot product, L2, and
|
|
155
|
+
L1 distances use maximum thresholds. IVFFlat does not support L1.
|
|
156
|
+
|
|
157
|
+
Keyword/hybrid/full-text search, sparse/binary vectors, nested filter paths,
|
|
158
|
+
schema migration, and server-side embedding generation are not supported.
|
|
159
|
+
|
|
160
|
+
## Documentation
|
|
161
|
+
|
|
162
|
+
- [Microsoft Agent Framework documentation](https://learn.microsoft.com/agent-framework/)
|
|
163
|
+
- [PostgreSQL documentation](https://www.postgresql.org/docs/current/)
|
|
164
|
+
- [pgvector setup, indexes, and distance functions](https://github.com/pgvector/pgvector)
|
|
165
|
+
- [Psycopg connection pools](https://www.psycopg.org/psycopg3/docs/advanced/pool.html)
|
|
166
|
+
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Agent Framework PostgreSQL / pgvector
|
|
2
|
+
|
|
3
|
+
Store and search vector records in PostgreSQL with this alpha integration for
|
|
4
|
+
[Microsoft Agent Framework](https://learn.microsoft.com/agent-framework/).
|
|
5
|
+
The package uses Psycopg 3 and the official pgvector Python adapter.
|
|
6
|
+
|
|
7
|
+
- **`PostgresCollection`** provides batch upsert, retrieval, deletion, and vector similarity search.
|
|
8
|
+
- **`PostgresStore`** creates collection clients that share a connection pool.
|
|
9
|
+
- **`PostgresSettings`** describes connection settings resolved by Agent Framework.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install agent-framework-postgres --pre
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Requires Python 3.10+, PostgreSQL 13+, and pgvector 0.8.0+.
|
|
18
|
+
Import the connector directly from `agent_framework_postgres`.
|
|
19
|
+
|
|
20
|
+
## Connection setup
|
|
21
|
+
|
|
22
|
+
Have your database administrator install and enable the `vector` extension and
|
|
23
|
+
provide an existing schema. The extension must be visible through the connection's
|
|
24
|
+
`search_path`. The connector never creates schemas, enables extensions, or changes
|
|
25
|
+
server-wide configuration. `ensure_collection_exists()` explicitly creates the
|
|
26
|
+
table and requested indexes; it requires the corresponding permissions and does
|
|
27
|
+
not migrate existing tables.
|
|
28
|
+
|
|
29
|
+
Set `POSTGRES_CONNECTION_STRING` to a PostgreSQL URI or Psycopg conninfo string,
|
|
30
|
+
or pass `connection_string` to either constructor. Both accept a string or AF
|
|
31
|
+
`SecretString`. Settings precedence is **explicit argument > selected `.env`
|
|
32
|
+
file > environment**. Select a file with `env_file_path` and optional
|
|
33
|
+
`env_file_encoding`; missing or empty connection strings are rejected.
|
|
34
|
+
The `schema` argument defaults to `public`.
|
|
35
|
+
|
|
36
|
+
A connector-created pool is closed by `close()` or an async context manager.
|
|
37
|
+
Alternatively, inject an open Psycopg `AsyncConnection` or `AsyncConnectionPool`
|
|
38
|
+
using `client`; it remains caller-owned and bypasses settings loading.
|
|
39
|
+
Injected clients cannot be combined with connection-string or `.env` options.
|
|
40
|
+
Collections created by a store borrow its pool, so keep the store open while
|
|
41
|
+
using them.
|
|
42
|
+
|
|
43
|
+
## Example
|
|
44
|
+
|
|
45
|
+
With `POSTGRES_CONNECTION_STRING` configured, create a typed collection and
|
|
46
|
+
search using precomputed embeddings:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import asyncio
|
|
50
|
+
from dataclasses import dataclass
|
|
51
|
+
from typing import Annotated
|
|
52
|
+
|
|
53
|
+
from agent_framework import Filter, VectorStoreField, vectorstoremodel
|
|
54
|
+
from agent_framework_postgres import PostgresStore
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@vectorstoremodel(collection_name="articles")
|
|
58
|
+
@dataclass
|
|
59
|
+
class Article:
|
|
60
|
+
id: Annotated[str, VectorStoreField("key")]
|
|
61
|
+
text: Annotated[str, VectorStoreField("data")]
|
|
62
|
+
embedding: Annotated[list[float] | None, VectorStoreField("vector", dimensions=3)] = None
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
async def main() -> None:
|
|
66
|
+
async with PostgresStore() as store:
|
|
67
|
+
collection = store.get_collection(Article)
|
|
68
|
+
await collection.ensure_collection_exists()
|
|
69
|
+
await collection.upsert(
|
|
70
|
+
[
|
|
71
|
+
Article("1", "PostgreSQL supports vectors", [1, 0, 0]),
|
|
72
|
+
Article("2", "A travel journal", [0, 1, 0]),
|
|
73
|
+
],
|
|
74
|
+
generate_vectors=False,
|
|
75
|
+
)
|
|
76
|
+
results = await collection.search(
|
|
77
|
+
vector=[1, 0, 0],
|
|
78
|
+
filter=Filter("text", "contains_text", "PostgreSQL"),
|
|
79
|
+
score_threshold=0.25,
|
|
80
|
+
top=3,
|
|
81
|
+
)
|
|
82
|
+
async for result in results:
|
|
83
|
+
print(result["record"].text, result["score"])
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if __name__ == "__main__":
|
|
87
|
+
asyncio.run(main())
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Pass `generate_vectors=False` to preserve supplied embeddings. To generate them
|
|
91
|
+
locally, configure an `embedding_generator`. Retrieval excludes embeddings by
|
|
92
|
+
default; use `include_vectors=True` to return them.
|
|
93
|
+
|
|
94
|
+
## Capabilities and limits
|
|
95
|
+
|
|
96
|
+
The connector supports typed models, string/integer/UUID keys (including generated
|
|
97
|
+
keys), multiple nullable vector columns, storage aliases, and database-side
|
|
98
|
+
filters and paging. Batch writes are transactional; an existing transaction on
|
|
99
|
+
an injected connection remains under the caller's commit control.
|
|
100
|
+
|
|
101
|
+
Vector fields support `float`, `float32`, and `float16` declarations. PostgreSQL
|
|
102
|
+
`vector` storage uses 32-bit floats; `float16` defaults to 16-bit `halfvec`.
|
|
103
|
+
The `postgres.vector_type` provider annotation explicitly selects either storage
|
|
104
|
+
type. Ordinary Python floats and integer-valued elements are accepted and rounded
|
|
105
|
+
to the selected precision; declared `int` and `float64` vector fields are rejected.
|
|
106
|
+
|
|
107
|
+
Storage precision does not determine the model's Python scalar type. The default
|
|
108
|
+
decoder returns ordinary Python floats: use `list[float]` annotations even with
|
|
109
|
+
explicit `float16` or `float32` field metadata. Models annotated with
|
|
110
|
+
`list[numpy.float16]` or `list[numpy.float32]` require a custom `decoder` passed to
|
|
111
|
+
`vectorstoremodel` or `register_vectorstoremodel`. That decoder must reconstruct
|
|
112
|
+
each component with the declared NumPy scalar type and handle omitted vector
|
|
113
|
+
fields when `include_vectors=False`. NumPy is not a connector runtime dependency.
|
|
114
|
+
|
|
115
|
+
Exact search is the default. HNSW and IVFFlat are optional approximate indexes;
|
|
116
|
+
selective filters can reduce their recall. Use
|
|
117
|
+
`operation_options={"exact": True}` when complete recall is required.
|
|
118
|
+
`exact=False` requires an HNSW or IVFFlat field. Result metadata's `approximate`
|
|
119
|
+
flag identifies ANN-permitted query mode, not proof that PostgreSQL used an ANN
|
|
120
|
+
index.
|
|
121
|
+
IVFFlat needs data before index creation: first call
|
|
122
|
+
`ensure_collection_exists(operation_options={"create_indexes": False})`, load
|
|
123
|
+
records, then call `ensure_collection_exists()` again.
|
|
124
|
+
Storage supports up to 16,000 dimensions; ANN indexes support up to 2,000 for
|
|
125
|
+
`vector` and 4,000 for `halfvec`.
|
|
126
|
+
|
|
127
|
+
Scores use the selected metric's units, not probabilities. The default is cosine
|
|
128
|
+
distance, where lower is better and `score_threshold` is a maximum. Cosine
|
|
129
|
+
similarity and dot product use minimum thresholds; negative dot product, L2, and
|
|
130
|
+
L1 distances use maximum thresholds. IVFFlat does not support L1.
|
|
131
|
+
|
|
132
|
+
Keyword/hybrid/full-text search, sparse/binary vectors, nested filter paths,
|
|
133
|
+
schema migration, and server-side embedding generation are not supported.
|
|
134
|
+
|
|
135
|
+
## Documentation
|
|
136
|
+
|
|
137
|
+
- [Microsoft Agent Framework documentation](https://learn.microsoft.com/agent-framework/)
|
|
138
|
+
- [PostgreSQL documentation](https://www.postgresql.org/docs/current/)
|
|
139
|
+
- [pgvector setup, indexes, and distance functions](https://github.com/pgvector/pgvector)
|
|
140
|
+
- [Psycopg connection pools](https://www.psycopg.org/psycopg3/docs/advanced/pool.html)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Async PostgreSQL/pgvector vector collections and stores."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import importlib.metadata
|
|
8
|
+
|
|
9
|
+
from ._vector_store import PostgresCollection, PostgresSettings, PostgresStore
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
__version__ = importlib.metadata.version(__name__)
|
|
13
|
+
except importlib.metadata.PackageNotFoundError:
|
|
14
|
+
__version__ = "0.0.0"
|
|
15
|
+
|
|
16
|
+
__all__ = ["PostgresCollection", "PostgresSettings", "PostgresStore", "__version__"]
|