Zvec v0.5.0实战:不用部署服务,Python几行代码搞定向量检索+全文搜索
这东西解决什么问题
向量数据库这两年选择太多了。Milvus、Qdrant、Weaviate、Chroma,每个都要单独部署一个服务,配置端口、管理进程,对于很多场景来说太重了。
阿里在今年2月开源了Zvec,定位是"向量数据库里的SQLite"——进程内运行,不需要启动任何服务端,pip install完直接用。6月12日刚发布的v0.5.0加了三个东西:原生全文检索、混合检索、DiskANN磁盘索引。GitHub上目前10500+ Star,这两天一直挂在Trending首页。
我花了一下午把v0.5.0的新功能跑了一遍,下面记录完整过程。
安装
Python 3.10到3.14都支持:
pip install zvec
macOS ARM64、Linux x86_64/ARM64、Windows x86_64都能用。我在M2 Mac上装的,没遇到编译问题,几秒钟就装完了。
Node.js的话用npm:
npm install @zvec/zvec
Go和Rust也有官方SDK,不过这篇用Python演示。
基本用法:创建Collection和向量检索
Zvec的概念和其他向量数据库差不多:Collection对应一个表,里面存Document,每个Document包含标量字段和向量字段。
先来一个最简单的例子:
import zvec
# 定义schema:一个标量字段 + 一个向量字段
schema = zvec.CollectionSchema(
name="articles",
fields=[
zvec.FieldSchema(
name="publish_year",
data_type=zvec.DataType.INT32,
index_param=zvec.InvertIndexParam(enable_range_optimization=True),
),
],
vectors=[
zvec.VectorSchema(
name="embedding",
data_type=zvec.DataType.VECTOR_FP32,
dimension=768,
index_param=zvec.HnswIndexParam(metric_type=zvec.MetricType.COSINE),
),
],
)
# 创建collection,数据存在本地目录
collection = zvec.create_and_open(
path="./articles_data",
schema=schema,
)
注意几个点:
- path是一个本地目录,所有数据和索引都存在这里
- 向量维度要在schema里写死,后面不能改
- 索引类型选了HNSW+Cosine,这是最常用的组合
插入数据:
collection.insert(
zvec.Doc(
id="article_001",
vectors={"embedding": [0.1, 0.2, ...共768个float]},
fields={"publish_year": 2026},
)
)
# 批量插入也是一样,传列表就行
collection.insert([
zvec.Doc(id="article_002", vectors={"embedding": vec2}, fields={"publish_year": 2025}),
zvec.Doc(id="article_003", vectors={"embedding": vec3}, fields={"publish_year": 2026}),
])
插入之后记得调optimize(),这一步会构建向量索引:
collection.optimize()
如果数据量小不调也行,Zvec会用临时索引做检索,但大数据量下性能差距很明显。
查询:
results = collection.query(
queries=zvec.Query(
field_name="embedding",
vector=[0.3, 0.1, ...共768个float],
),
topk=10,
)
for doc in results:
print(f"ID: {doc['id']}, Score: {doc['score']:.4f}")
带过滤条件的查询:
results = collection.query(
queries=zvec.Query(
field_name="embedding",
vector=query_vec,
),
topk=10,
filter="publish_year >= 2025",
)
到这一步,已经是一个能用的向量检索了。整个过程没有启动任何服务、没有配置任何端口。数据就存在本地一个目录里,程序退出数据不丢(WAL保证持久化)。
v0.5.0新功能一:全文检索
这是这次更新我最想试的功能。之前做RAG的时候,向量检索找语义相关的内容,但有时候用户搜一个精确的函数名或者错误码,向量检索就不太灵了。通常的做法是再接一个Elasticsearch做关键词搜索,然后把两路结果合并。
Zvec v0.5.0直接内置了全文检索。在schema里给字符串字段加一个FTS索引就行:
schema = zvec.CollectionSchema(
name="docs",
fields=[
zvec.FieldSchema(
name="content",
data_type=zvec.DataType.STRING,
index_param=zvec.FtsIndexParam(), # 加这行就开启全文检索
),
zvec.FieldSchema(
name="title",
data_type=zvec.DataType.STRING,
),
],
vectors=[
zvec.VectorSchema(
name="embedding",
data_type=zvec.DataType.VECTOR_FP32,
dimension=768,
index_param=zvec.HnswIndexParam(metric_type=zvec.MetricType.COSINE),
),
],
)
collection = zvec.create_and_open(path="./docs_fts", schema=schema)
插入带文本内容的文档:
collection.insert([
zvec.Doc(
id="doc_1",
fields={
"content": "Python的asyncio模块提供了async/await语法来编写并发代码",
"title": "Python异步编程入门",
},
vectors={"embedding": embed("Python的asyncio模块...")},
),
zvec.Doc(
id="doc_2",
fields={
"content": "使用pip install报错ModuleNotFoundError的常见解决方法",
"title": "pip安装问题排查",
},
vectors={"embedding": embed("使用pip install报错...")},
),
])
collection.optimize()
纯关键词搜索:
results = collection.query(
queries=zvec.FtsQuery(
field_name="content",
text="asyncio await",
),
topk=5,
)
搜"ModuleNotFoundError"这种精确错误名也能命中,不用依赖向量语义。
v0.5.0新功能二:混合检索
全文检索单独用意义不大,关键是和向量检索混合起来。Zvec的MultiQuery能在一次调用里同时做向量检索和全文检索,然后自动融合排序:
results = collection.query(
queries=zvec.MultiQuery([
zvec.Query(
field_name="embedding",
vector=query_embedding,
),
zvec.FtsQuery(
field_name="content",
text="asyncio",
),
]),
topk=10,
)
这个比自己手动做两次查询再合并方便太多了。以前用Milvus+ES做类似的事情,光是结果融合和去重就写了好几十行代码。
v0.5.0新功能三:DiskANN索引
第三个新功能是DiskANN索引。HNSW索引全在内存里,100万条768维向量大概要3-4GB内存。DiskANN把索引主体放磁盘,内存占用降到原来的几分之一。
用法就是把索引参数换一下:
vectors=[
zvec.VectorSchema(
name="embedding",
data_type=zvec.DataType.VECTOR_FP32,
dimension=768,
index_param=zvec.DiskAnnIndexParam(metric_type=zvec.MetricType.COSINE),
),
]
代价是查询延迟会高一些。官方benchmark显示,1000万条数据下,DiskANN的延迟大概是HNSW的2-3倍,但内存占用只有十分之一。对于数据量大但查询频率不高的场景(比如离线分析、本地知识库),DiskANN很合适。
实际场景:本地文档RAG
把上面的功能串起来,做一个本地文档问答系统。不需要部署任何外部服务,整个系统就是一个Python脚本:
import zvec
from openai import OpenAI
client = OpenAI() # 用你自己的embedding服务
def get_embedding(text):
resp = client.embeddings.create(
model="text-embedding-3-small",
input=text,
)
return resp.data[0].embedding
# 创建collection
schema = zvec.CollectionSchema(
name="knowledge_base",
fields=[
zvec.FieldSchema(
name="content",
data_type=zvec.DataType.STRING,
index_param=zvec.FtsIndexParam(),
),
zvec.FieldSchema(
name="source",
data_type=zvec.DataType.STRING,
),
],
vectors=[
zvec.VectorSchema(
name="embedding",
data_type=zvec.DataType.VECTOR_FP32,
dimension=1536,
index_param=zvec.HnswIndexParam(metric_type=zvec.MetricType.COSINE),
),
],
)
db = zvec.create_and_open(path="./knowledge_db", schema=schema)
# 导入文档(这里简化,实际项目要做分块)
docs = [
{"id": "1", "content": "Zvec支持Python 3.10到3.14...", "source": "readme.md"},
{"id": "2", "content": "调用optimize()构建索引后检索速度提升10倍...", "source": "guide.md"},
]
for doc in docs:
db.insert(zvec.Doc(
id=doc["id"],
fields={"content": doc["content"], "source": doc["source"]},
vectors={"embedding": get_embedding(doc["content"])},
))
db.optimize()
# 混合检索
def search(question, topk=5):
q_vec = get_embedding(question)
results = db.query(
queries=zvec.MultiQuery([
zvec.Query(field_name="embedding", vector=q_vec),
zvec.FtsQuery(field_name="content", text=question),
]),
topk=topk,
)
return results
整个知识库就是本地一个文件夹。备份就是拷贝目录,迁移也是拷贝目录。这个简单程度是Milvus、Qdrant这些C/S架构的向量数据库做不到的。
踩坑记录
跑的过程中遇到了几个问题,记一下:
1. schema定义后不能改
Collection创建之后,字段名、向量维度、索引类型都不能改。如果要改schema,只能新建Collection重新导入数据。这和SQLite的ALTER TABLE限制类似。
2. 字段名必须完全匹配
插入数据时字段名写错了不会报错,但那个字段的数据会丢失。比如schema里定义的是publish_year,插入时写成publishYear,不会有任何错误提示,但查询时这个字段就是空的。这个行为挺坑的,希望后续版本能加个校验。
3. optimize()的时机
小数据量(几千条以内)不调optimize()也能查,但一旦数据量上万,不调optimize()查询会慢很多。我的建议是批量导入完成后统一调一次,不要每插一条就调。
4. 并发限制
多进程读没问题,但写只能单进程。如果你的应用需要多个worker同时写入,要自己加锁或者用队列。
5. 中文全文检索
FTS默认的分词器对中文的支持还在完善中。我测试时"Python异步编程"能搜到,但"异步"单独搜有时候会漏。如果中文全文检索对你很关键,建议再等等或者自己做分词后存入。
和其他向量数据库的对比
| Zvec | Chroma | Milvus | Qdrant | |
|---|---|---|---|---|
| 架构 | 嵌入式(进程内) | 嵌入式/C-S | 客户端-服务端 | 客户端-服务端 |
| 安装 | pip install | pip install | Docker部署 | Docker部署 |
| 全文检索 | v0.5.0原生支持 | 不支持 | 不支持 | 有payload索引 |
| 混合检索 | 原生MultiQuery | 不支持 | 支持 | 支持 |
| 磁盘索引 | DiskANN | 不支持 | DiskANN | 支持 |
| SDK语言 | Python/Node/Go/Rust | Python/JS | 多语言 | 多语言 |
| 适用场景 | 本地应用、边缘设备、原型 | 原型、小项目 | 生产级大规模 | 生产级中大规模 |
选择建议:如果你的数据量在千万级以下,不想维护额外服务,Zvec够用了。需要分布式、高可用、多节点的场景,还是得上Milvus或Qdrant。
总结
Zvec v0.5.0加了全文检索和混合检索之后,嵌入式向量数据库该有的功能基本齐了。个人项目、本地RAG、边缘部署,pip install完就能跑,不用折腾Docker和服务配置,省心不少。
DiskANN索引让它能处理更大规模的数据而不吃太多内存,不再只能当原型验证的工具了。
代码仓库:https://github.com/alibaba/zvec 文档:https://zvec.org
更多推荐



所有评论(0)