vecspan 0.1.0__py3-none-any.whl
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.
- vecspan/__init__.py +50 -0
- vecspan/backends/__init__.py +6 -0
- vecspan/backends/base.py +107 -0
- vecspan/backends/memory.py +289 -0
- vecspan/backends/milvus.py +696 -0
- vecspan/backends/qdrant.py +532 -0
- vecspan/capabilities.py +16 -0
- vecspan/client.py +205 -0
- vecspan/errors.py +27 -0
- vecspan/filters.py +258 -0
- vecspan/naming.py +35 -0
- vecspan/py.typed +0 -0
- vecspan/registry.py +67 -0
- vecspan/types.py +282 -0
- vecspan/validate.py +348 -0
- vecspan-0.1.0.dist-info/METADATA +137 -0
- vecspan-0.1.0.dist-info/RECORD +19 -0
- vecspan-0.1.0.dist-info/WHEEL +5 -0
- vecspan-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vecspan
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: One Python API for Milvus, Qdrant, and other vector databases.
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Provides-Extra: milvus
|
|
8
|
+
Requires-Dist: pymilvus>=2.5.0; extra == "milvus"
|
|
9
|
+
Provides-Extra: qdrant
|
|
10
|
+
Requires-Dist: qdrant-client>=1.12.0; extra == "qdrant"
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
13
|
+
|
|
14
|
+
# vecspan
|
|
15
|
+
|
|
16
|
+
vecspan 是一个同步 Python 客户端。业务代码只依赖一套集合、写入、过滤和检索接口,Milvus 和 Qdrant 放在适配器后面。向量由调用方传入,这个库不负责生成 embedding。
|
|
17
|
+
|
|
18
|
+
## 安装
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install vecspan
|
|
22
|
+
pip install "vecspan[milvus]"
|
|
23
|
+
pip install "vecspan[qdrant]"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
只装其中一个可选依赖时,另一个后端不会被导入。
|
|
27
|
+
|
|
28
|
+
## 连接
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from vecspan import VectorClient
|
|
32
|
+
|
|
33
|
+
client = VectorClient.connect("memory://")
|
|
34
|
+
client = VectorClient.connect("milvus://localhost:19530")
|
|
35
|
+
client = VectorClient.connect("milvus://user:password@localhost:19530/default")
|
|
36
|
+
client = VectorClient.connect("qdrant://localhost:6333", api_key="...")
|
|
37
|
+
client = VectorClient.connect("qdrant+https://example.com", api_key="...")
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`memory://` 把数据放在当前进程里,用来做单测和本地开发。第三方后端可以用 `register_backend(scheme)` 注册,工厂签名是 `factory(parsed_url, **kwargs)`。
|
|
41
|
+
|
|
42
|
+
## 集合和写入
|
|
43
|
+
|
|
44
|
+
主键在创建时选定,之后不再改变。`int` 的可移植范围是 `0 .. 2^63-1`。`uuid` 只接受 UUID,因为 Qdrant 的 point id 不能是任意字符串。
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from vecspan import (
|
|
48
|
+
CollectionSpec,
|
|
49
|
+
Distance,
|
|
50
|
+
Filter,
|
|
51
|
+
PayloadField,
|
|
52
|
+
PayloadType,
|
|
53
|
+
Point,
|
|
54
|
+
VectorField,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
client.create_collection(CollectionSpec(
|
|
58
|
+
name="docs",
|
|
59
|
+
id_type="uuid",
|
|
60
|
+
vectors=[VectorField("embedding", size=768, distance=Distance.COSINE)],
|
|
61
|
+
payload_fields=[
|
|
62
|
+
PayloadField("source", PayloadType.KEYWORD, indexed=True),
|
|
63
|
+
PayloadField("year", PayloadType.INT, indexed=True),
|
|
64
|
+
],
|
|
65
|
+
))
|
|
66
|
+
|
|
67
|
+
client.upsert("docs", [Point(
|
|
68
|
+
id="550e8400-e29b-41d4-a716-446655440000",
|
|
69
|
+
vectors={"embedding": [0.1] * 768},
|
|
70
|
+
payload={"source": "wiki", "year": 2020},
|
|
71
|
+
)])
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
一个 point 可以带多个命名向量。写入分成四个语义:
|
|
75
|
+
|
|
76
|
+
| 方法 | 语义 |
|
|
77
|
+
| --- | --- |
|
|
78
|
+
| `upsert(name, points)` | 按 id 新增,或整条替换向量和 payload |
|
|
79
|
+
| `update_payload(name, ids, payload)` | 合并 payload,未提到的字段保留 |
|
|
80
|
+
| `update_vectors(name, ids, vectors)` | 只替换给出的向量字段 |
|
|
81
|
+
| `delete(name, ids=...)` 或 `delete(name, filter=...)` | 按 id 或按过滤条件删除 |
|
|
82
|
+
|
|
83
|
+
`update_payload` 在 Qdrant 上是合并写。Milvus 在客户端支持 `partial_update` 时走局部更新,否则先读出整行再写回。后一种做法在读和写之间有并发窗口。
|
|
84
|
+
|
|
85
|
+
未在 `payload_fields` 里声明的字段仍然可以写入。声明过的字段会按类型检查;标了 `indexed=True` 的字段会建标量索引。
|
|
86
|
+
|
|
87
|
+
## 读取
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
client.get("docs", [point_id])
|
|
91
|
+
client.count("docs", filter=Filter.eq("source", "wiki"))
|
|
92
|
+
page = client.scroll("docs", limit=100)
|
|
93
|
+
page = client.scroll("docs", limit=100, offset=page.next_offset)
|
|
94
|
+
|
|
95
|
+
query = (Filter.eq("source", "wiki") & Filter.gte("year", 2020)) | Filter.is_null("lang")
|
|
96
|
+
hits = client.search("docs", vector=query_vector, filter=query, limit=10)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`scroll` 的 `offset` 只对同一次连接里的同一个集合有意义。过滤条件支持 `eq`、`gt` / `gte` / `lt` / `lte`、`in_`、`is_null`,以及 `&`、`|`、`~`。
|
|
100
|
+
|
|
101
|
+
集合有多个向量字段时,`search` 必须传 `vector_name`。只有一个向量字段时可以省略。
|
|
102
|
+
|
|
103
|
+
`SearchHit.score` 是后端自己的分数,不会在库之间换算。Cosine 和 Dot 越大越近,L2 越小越近。memory 和 Qdrant 的 L2 是欧氏距离,Milvus 的 L2 是平方欧氏距离,数值不要跨库比较。
|
|
104
|
+
|
|
105
|
+
HNSW 参数 `m` 和 `ef_construct` 写在 `VectorField` 上,默认 `16` 和 `200`。检索时可以用 `backend_options` 覆盖搜索宽度:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
client.search("docs", vector=query_vector, backend_options={"ef": 128})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`hnsw_ef` 和 `ef` 是同一个参数。Milvus 另外接受 `nprobe`。
|
|
112
|
+
|
|
113
|
+
## 范围
|
|
114
|
+
|
|
115
|
+
v1 包含:
|
|
116
|
+
|
|
117
|
+
- 集合的创建、删除、是否存在、描述、列表
|
|
118
|
+
- `upsert`、`update_payload`、`update_vectors`、`delete`
|
|
119
|
+
- `get`、`count`、`scroll`、`search`
|
|
120
|
+
- 过滤表达式,以及默认的 HNSW 索引
|
|
121
|
+
- `MemoryBackend`,以及同一套契约测试
|
|
122
|
+
|
|
123
|
+
v1 不包含稀疏向量、混合检索、分区、别名、多副本和权限。客户端是同步的。
|
|
124
|
+
|
|
125
|
+
## 测试
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
pip install pytest
|
|
129
|
+
pytest
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
连上真实数据库时再跑集成测试:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
VECSPAN_MILVUS_URL=milvus://localhost:19530 pytest -m integration
|
|
136
|
+
VECSPAN_QDRANT_URL=qdrant://localhost:6333 pytest -m integration
|
|
137
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
vecspan/__init__.py,sha256=5h-LJ2bf0bOtIjBaNSnJL2ykbPa9croaEvKPFz-gXK0,1031
|
|
2
|
+
vecspan/capabilities.py,sha256=SNQXhd8UswzhsPnpIwyBj-AjlpZ5fMox2d05gEc4GbU,374
|
|
3
|
+
vecspan/client.py,sha256=M7DeU1HJ5CrKI67U24cHbAXw-bes657t07nYDMaP5DM,7768
|
|
4
|
+
vecspan/errors.py,sha256=qMlSQ_GdGT6byusHUovYYLenF6ecntatGBp7rtpd0ng,695
|
|
5
|
+
vecspan/filters.py,sha256=nSx4UrMFUfVL_wh_Ss_TCQcTotIDIfShL9joZVTLKFA,8028
|
|
6
|
+
vecspan/naming.py,sha256=0_GOLMzKhpBR8es4aj9pOWlSixW85mMmi3Z5c2oIIuM,1205
|
|
7
|
+
vecspan/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
vecspan/registry.py,sha256=Jk0HioPPAWVqmsX3flrTEq0lOR7BOrEcykMbcG40_Kw,2540
|
|
9
|
+
vecspan/types.py,sha256=dVdPzfu33hQYKrZDjKscYx5fvluyffFoFjm_5jBn_aQ,9348
|
|
10
|
+
vecspan/validate.py,sha256=WlnJVbXXnToMk0EN6_n6Xm0gM-_CXTXj7uoRGtw533Q,13583
|
|
11
|
+
vecspan/backends/__init__.py,sha256=y1m6JCRo7EfDdg7riUSgjMhrBZV8pq5_uneQugASJMo,229
|
|
12
|
+
vecspan/backends/base.py,sha256=Sy3IOTK7JDw-LOKSUT9AUPOP68tDcSGR8nKBbHXUXnA,3421
|
|
13
|
+
vecspan/backends/memory.py,sha256=QDBtFBK-ndNIAR9uQYtMTMMJgLxMJKuEiIWIwkgacvQ,10624
|
|
14
|
+
vecspan/backends/milvus.py,sha256=xi4vE2DKJd3RF-iwIxSc-m5Q16h4vuqVB8WNDo0zbus,25649
|
|
15
|
+
vecspan/backends/qdrant.py,sha256=_5Wu4ddcY_E3QamsxyDCMXXCsX4kKr9jl9y6zX2Eqzg,19286
|
|
16
|
+
vecspan-0.1.0.dist-info/METADATA,sha256=HFKd-UeXyjipMzDY6F1KvO7Bk19LKsCafajJ-CYUSYM,4837
|
|
17
|
+
vecspan-0.1.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
18
|
+
vecspan-0.1.0.dist-info/top_level.txt,sha256=iK5rabENhuN5lBsVb6Rrnby9ckMqrI0PKtGwq9-590A,8
|
|
19
|
+
vecspan-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
vecspan
|