Skip to content

在 AI 超级智能体项目中,你是如何实现 RAG 向量存储的?为什么这么实现? ​

  • 标签:后端、编程导航

🏛 业务架构师 ​

我选型与实现的逻辑链是"数据规模 → 运维成本 → 迁移路径"三步:

我的选择:PGVector 起步。理由:

  • 量级匹配:百万级向量、日均万级检索,PGVector + HNSW 索引毫秒级返回,完全够用——很多团队几万条数据就上 Milvus,是为想象中的规模付真实的运维成本;
  • 运维零增量:团队已有 PostgreSQL 体系(备份、监控、权限、DBA 熟悉度全复用)——向量库只是 PG 的一个扩展,而不是一个新组件;
  • 事务与元数据联合查询:向量检索和元数据过滤(权限、分类)在同一个 SQL 里完成——WHERE tenant_id=? AND deleted=false ORDER BY embedding <=> ? LIMIT 5,权限过滤前置到检索,这在多租户场景是刚需,专用向量库做混合过滤反而绕。

规模上来后的演进路径(预先设计好):数据过千万、QPS 上千时评估 Milvus(专用能力:分布式索引、更高吞吐)或云服务——因为走的是 Spring AI 的 VectorStore 抽象,迁移只需换实现类,这是我坚持"接口先行"的回报。

为什么不选 Redis 向量/ES:Redis 向量适合已有 Redis 且规模小的场景(重启丢失策略要评估);ES 向量检索的内存消耗在同等精度下偏高,但已有 ES 团队时它是合理的复用选择。

一句话:向量存储选型不是选最强组件,是选"当前规模下运维成本最低、未来迁移成本也低"的方案——抽象层保迁移自由,规模数据保升级时机。

🏗 系统架构师 ​

我选了 pgvector(PostgreSQL + vector 扩展),决策逻辑按四个维度:

1. 选型对比:

  • pgvector:与业务库同栈,事务/备份/运维全套复用,HNSW 索引支持千万级向量、毫秒检索;中小规模(<1000 万向量)性价比最高;
  • Milvus:专业向量库,亿级分布式检索强,但部署重(etcd+多组件)、运维成本高——超大规模再上;
  • Elasticsearch:向量+dense_vector 与全文混合检索一体,已有 ES 集团的团队顺手;
  • Redis:低延迟小规模,内存成本高;
  • 云托管(Pinecone 等):省事但数据出境与成本问题。

2. 我的实现:Spring AI 的 VectorStore 抽象 + PgVectorStore 自动配置,建表(id、content、metadata JSONB、embedding vector(1024))+ HNSW 索引(cosine 距离);similaritySearch(SearchRequest.query(q).withTopK(5).withSimilarityThreshold(0.7)) 一行检索。metadata 过滤(按来源/标签/时间过滤)+ 向量相似度组合是 pgvector 的独特优势(SQL 生态)。

3. 为什么这么实现:

  • 项目规模(百万级 chunk)单实例 pgvector 足够,多一套 Milvus 是纯运维负债;
  • 数据强一致:文档增删与向量变更在同一事务,杜绝"库里删了向量还在"的一致性问题——分布式向量库做不到;
  • 演进路径清晰:量级上来迁 Milvus,Spring AI 换实现类即可。

架构心法:向量库选型三问——数据量级、是否要混合检索、团队运维能力;规模没到之前,运维简单性 > 参数化性能。

💻 全栈开发专家 ​

我选了 PGVector(PostgreSQL + pgvector 扩展),理由和实现:

为什么是 PGVector:

  1. 运维零新增:项目本来就有 PG,备份、监控、权限、高可用全复用;独立向量库(Milvus)要多养一套分布式系统;
  2. 规模匹配:百万级 chunk 以内,HNSW 索引检索毫秒级,够用;真到上亿再迁 Milvus 不迟;
  3. 向量 + 结构化混合查询:metadata 过滤(按知识库/部门/密级)直接走 SQL,ES/关系库二合一,这是我最看重的点。

实现:

yaml
spring:
  ai:
    vectorstore:
      pgvector:
        index-type: HNSW          # 比 IVFFlat 召回稳定,适合常写入场景
        distance-type: COSINE_DISTANCE
        dimensions: 1024          # 跟 embedding 模型输出对齐
java
// 写:vectorStore.add(documents);  自动向量化入库
// 读:带元数据过滤的相似检索
List<Document> hits = vectorStore.similaritySearch(
    SearchRequest.builder().query(question)
        .topK(5)
        .filterExpression("knowledgeBase == 'product' && level >= 2")
        .build());

踩坑:dimensions 必须和 embedding 模型严格一致(换模型=全量重建向量);HNSW 建索引比 IVFFlat 慢但查询不用预热;生产把 vector 列设为 halfvec(半精度)可以省一半存储、几乎不损召回。