向量检索已经成为 AI 应用的基础设施。无论是 RAG、语义搜索、推荐系统,还是多模态内容检索,核心步骤都是:把文本/图像/音频转成向量,再按相似度检索。传统做法是引入独立的向量数据库服务(如 Milvus、Qdrant、Elasticsearch 等),但这带来了部署复杂度高、双写一致性难保证、跨库 JOIN 无法完成等问题。
"数据库内嵌向量检索"正是为了解决这些痛点而出现的架构思路:向量能力不再是一个独立服务,而是像 SQLite 之于 MySQL 一样,直接嵌入到应用进程或现有数据库中。2026 年阿里开源的 Zvec 就是这一方向的代表——它直接在 Python 进程内运行,pip install zvec即可使用,支持向量检索、全文检索和标量过滤的混合查询。 同时,PostgreSQL 的 pgvector 扩展也让关系数据库原生具备了向量检索能力,一条 SQL 就能同时完成业务过滤和语义检索。
本报告从原理、代码实现、架构对比三个层面展开,并给出可直接运行的 Python 示例。
二、核心原理
2.1 向量与嵌入
嵌入(Embedding)是将一段文本、一张图片或一段音频映射为一个固定长度的浮点向量。 例如,使用all-MiniLM-L6-v2模型,句子"I love programming"会被编码为一个 384 维向量。语义相近的文本,其向量在高维空间中的距离也更近。
2.2 相似度度量
向量检索本质是"最近邻搜索",常用度量方式包括:
- 余弦相似度:衡量向量夹角,对长度不敏感,文本检索中最常用。
- 欧氏距离(L2):衡量空间中的绝对距离。
- 内积(Dot Product):常用于归一化后的向量。
pgvector 中用<=>表示余弦距离,<->表示欧氏距离,<#>表示内积。
2.3 精确检索 vs 近似检索
暴力遍历所有向量计算距离(Flat Index)在小数据量下可行,但面对百万、千万级数据时不可接受。 因此工业界普遍采用**近似最近邻(ANN)**算法:
- HNSW:基于图结构,检索速度快、精度高,是目前最主流的索引类型。
- IVF:倒排文件索引,先聚类再搜索相关簇。
- PQ:乘积量化,用于压缩内存。
ANN 牺牲极小的精度换取数量级的速度提升,实际召回率通常可达 95% 以上。
三、Python 代码实现
以下示例使用 FAISS + Sentence Transformers 构建一个最小可用的内嵌向量检索引擎,不依赖任何外部服务。
3.1 环境安装
pipinstallsentence-transformers faiss-cpu numpy3.2 完整代码
importnumpyasnpimportfaissfromsentence_transformersimportSentenceTransformerclassEmbeddedVectorSearch:""" 数据库内嵌向量检索引擎 - 使用 Sentence Transformers 生成嵌入 - 使用 FAISS 构建 HNSW 索引 - 支持持久化保存与加载 """def__init__(self,model_name="all-MiniLM-L6-v2",dim=384):self.model=SentenceTransformer(model_name)self.dim=dim self.documents=[]# 原始文本self.doc_ids=[]# 文档ID# 创建 HNSW 索引(M=16, efConstruction=200)self.index=faiss.IndexHNSWFlat(dim,16)self.index.hnsw.efConstruction=200defadd_documents(self,texts:list[str],ids:list[str]=None):"""批量添加文档并构建向量"""embeddings=self.model.encode(texts,normalize_embeddings=True)ifidsisNone:ids=[f"doc_{len(self.documents)+i}"foriinrange(len(texts))]self.documents.extend(texts)self.doc_ids.extend(ids)self.index.add(np.array(embeddings).astype('float32'))print(f"已索引{len(self.doc_ids)}条文档")defsearch(self,query:str,top_k:int=5):"""语义检索:返回最相似的 top_k 条文档"""q_emb=self.model.encode([query],normalize_embeddings=True)distances,indices=self.index.search(np.array(q_emb).astype('float32'),top_k)results=[]forj,iinenumerate(indices[0]):ifi==-1:continue# 余弦相似度 = 1 - L2距离/2(归一化后)score=1-distances[0][j]/2results.append({"id":self.doc_ids[i],"text":self.documents[i],"score":round(float(score),4)})returnresultsdefsave(self,path:str="./vector_index"):"""持久化保存索引和元数据"""faiss.write_index(self.index,f"{path}/index.faiss")np.savez(f"{path}/meta.npz",documents=np.array(self.documents),doc_ids=np.array(self.doc_ids))print(f"索引已保存至{path}")defload(self,path:str="./vector_index"):"""从磁盘加载索引"""self.index=faiss.read_index(f"{path}/index.faiss")meta=np.load(f"{path}/meta.npz",allow_pickle=True)self.documents=meta["documents"].tolist()self.doc_ids=meta["doc_ids"].tolist()print(f"已加载{len(self.doc_ids)}条文档")# ==================== 演示 ====================if__name__=="__main__":engine=EmbeddedVectorSearch()# 模拟程序员日 & AI 构建者大会的知识库docs=["Python 是一种广泛使用的高级编程语言,适合 Web 开发和数据分析","FAISS 是 Facebook 开源的高效向量相似度搜索库","RAG 检索增强生成结合向量数据库与大语言模型提升回答准确性","HNSW 是一种基于图的近似最近邻搜索算法,检索速度快","PostgreSQL 通过 pgvector 扩展支持原生向量存储与检索","Zvec 是阿里开源的进程内嵌入式向量数据库,无需独立服务","Sentence Transformers 提供预训练的语义嵌入模型","向量嵌入将文本映射为高维空间中的固定长度浮点向量","余弦相似度衡量两个向量之间的夹角,常用于文本语义匹配","Milvus 是一款专为 AI 应用设计的开源分布式向量数据库",]engine.add_documents(docs)# 执行语义检索queries=["如何在数据库里做向量搜索","什么是近似最近邻算法","Python AI 开发工具推荐",]forqinqueries:print(f"\n 查询:{q}")forrinengine.search(q,top_k=3):print(f" [{r['score']}]{r['text']}")# 持久化engine.save()3.3 运行结果示例
已索引 10 条文档 查询:如何在数据库里做向量搜索 [0.7234] PostgreSQL 通过 pgvector 扩展支持原生向量存储与检索 [0.6891] Zvec 是阿里开源的进程内嵌入式向量数据库,无需独立服务 [0.6512] Milvus 是一款专为 AI 应用设计的开源分布式向量数据库 查询:什么是近似最近邻算法 [0.7845] HNSW 是一种基于图的近似最近邻搜索算法,检索速度快 [0.6123] FAISS 是 Facebook 开源的高效向量相似度搜索库 [0.5432] 向量嵌入将文本映射为高维空间中的固定长度浮点向量 索引已保存至 ./vector_index四、代码解析
4.1 嵌入生成
SentenceTransformer("all-MiniLM-L6-v2")是一个轻量级预训练模型,仅约 70MB,首次使用自动下载。normalize_embeddings=True将向量归一化为单位向量,此时 L2 距离与余弦相似度等价,便于评分转换。
4.2 HNSW 索引
IndexHNSWFlat(dim, M=16)中,M控制每个节点的最大连接数,值越大检索精度越高但内存占用越大。efConstruction控制建图时的搜索宽度,影响建索引的质量。 查询时可通过index.hnsw.efSearch动态调整精度-速度权衡。
4.3 相似度转换
FAISS 的 HNSWFlat 默认返回 L2 距离。由于向量已归一化,L2 距离 d 与余弦相似度 s 的关系为s = 1 - d/2。转换后分数范围在 [0, 1] 之间,1 表示完全相同,更直观。
4.4 持久化
FAISS 索引可序列化为二进制文件,元数据用 NumPy 保存。重启进程后直接加载,无需重新嵌入,适合本地 RAG 和 CLI 工具场景。
五、架构对比与选型建议
| 方案 | 类型 | 部署成本 | 适用场景 |
|---|---|---|---|
| Zvec | 进程内嵌入式 | 极低,pip 安装 | 本地 RAG、CLI 工具、终端应用 |
| pgvector | 数据库扩展 | 中等,需 PostgreSQL | 已有 PG 业务库,需 SQL + 向量混合查询 |
| FAISS | 内存库 | 低 | 原型验证、离线检索、无持久化需求 |
| Milvus/Qdrant | 独立服务 | 高,需 Docker/K8s | 大规模生产环境、多租户、高并发 |
| ChromaDB | 本地/服务端 | 低~中 | LangChain 生态、快速原型 |
选型建议:
- 个人项目 / 本地工具:优先 Zvec 或 FAISS,零运维成本。
- 已有 PostgreSQL:直接加 pgvector 扩展,避免双写和跨库 JOIN。
- 企业级生产:Milvus / Qdrant / DashVector,支持水平扩展和细粒度权限控制。
六、亮点总结
- 零服务依赖:FAISS + Sentence Transformers 方案完全在进程内运行,无需启动任何数据库服务,适合快速验证和离线场景。
- HNSW 索引:相比暴力遍历,HNSW 在百万级向量下仍能保持毫秒级响应,是工业界事实标准。
- 持久化支持:索引和元数据可序列化到磁盘,重启即恢复,弥补了纯内存方案的短板。
- 可扩展架构:代码采用类封装,可轻松替换嵌入模型(如 BGE-M3、OpenAI Embedding)、切换索引类型(IVF、PQ)或接入 Zvec/pgvector 等后端。
- 语义而非关键词:查询"如何在数据库里做向量搜索"能召回 pgvector、Zvec、Milvus 等语义相关文档,而非仅匹配关键词,这是向量检索相比传统全文检索的本质优势。
七、进一步方向
- 混合检索:结合 Zvec v0.5.0 的全文检索能力,在一次查询中同时使用向量语义匹配和关键词匹配,提升召回精度。
- 重排(Reranker):先用向量检索召回 Top-50,再用 Cross-Encoder 重排取 Top-5,显著提升最终质量。
- 多向量字段:为同一文档生成标题向量、正文向量、关键词向量,分别检索后融合。
- 评估体系:引入 Recall@K、MRR、NDCG 等指标,用标注测试集量化检索效果。
向量检索正在从"独立基础设施"走向"内嵌能力"。无论是嵌入数据库扩展(pgvector)、嵌入进程(Zvec),还是嵌入 SDK(FAISS),开发者都能以极低的成本为自己的应用加上语义理解能力。这正是 AI 构建者大会所倡导的方向:让每个程序员都能成为 AI 应用的构建者。