首页
/ FastGPT 向量数据库集成测试:工厂模式驱动的多库兼容性验证指南

FastGPT 向量数据库集成测试:工厂模式驱动的多库兼容性验证指南

2026-09-09 19:44:11作者:裘旻烁

FastGPT 的核心能力之一是 RAG 检索,而向量数据库(VectorDB)正是承载知识库向量与召回的核心存储层。为了保证在不同向量库(PGVector、Milvus、OceanBase、OpenGauss、SeekDB 等)之上行为一致、稳定可迁移,仓库在 packages/service/test/integrations/vectorDB 目录下维护了一套基于工厂模式的向量库集成测试。本指南将带你理解这套测试的组织方式、环境变量与运行方法,逐条拆解其测试用例的断言意图,并结合源码说明如何低成本地接入一个新的向量库。

为什么需要「真实环境」的向量库集成测试

FastGPT 的向量检索链路涉及多条路径:向量写入、按时间轮询数据、向量召回(embRecall)、全文检索(BM25)以及删除与计数。单测可以用 mock 覆盖控制器的行为,却无法验证:

  • 不同向量库的 insert / delete / embRecall 语义是否一致;
  • Milvus 这类分布式库的 growing segment 写入后索引可见性(存在秒级延迟);
  • BM25 能力门禁在真实 Milvus 元数据下是否能通过;
  • 主键 id 是否随召回结果返回——如 testSuites.ts 注释所强调的,下游反查 indexes.dataId 依赖 id,SDK 只解析 output_fields 指定字段,缺 id 会被吞成空召回。

因此仓库将这类测试独立为 integration 模式,要求连接真实运行的向量库实例,用一套数据、一套用例驱动多个库的测试,保证向量相关操作兼容与稳定。

整体结构:测试数据、测试套件、驱动入口三层分离

README.md 与目录结构可以看到,这套测试被刻意拆成三个角色:

文件 职责
testData.ts 统一测试数据:1536 维 TEST_VECTORS、查询向量、collection id、动态生成的 teamId/datasetId,所有向量库共用
testSuites.ts 工厂函数 createVectorDBTestSuite(vectorCtrl),同一套用例供各驱动复用
*/index.integration.test.ts 各向量库的测试入口,实例化对应控制器并调用工厂,按环境变量决定是否跳过

这种"数据 + 用例 + 入口"三层结构就是工厂模式的落点:新增向量库时,不需要重写任何用例,只需新增一个入口文件并复用 testData.tstestSuites.ts

统一测试数据(testData.ts)

testData.ts 定义了跨库通用的数据基准:

  • VECTOR_DIM = 1536:与主流 Embedding 模型(如 text-embedding-ada-002)输出维度一致的常量;
  • baseVector:通过 ((index % 10) + 1) / 100 生成确定性向量,保证多次运行结果可复现;
  • TEST_VECTORS:3 条向量——基准向量、0.7 倍缩放、0.3 倍缩放,用于制造可区分的相似度梯度;
  • QUERY_VECTOR = baseVector:查询向量即基准向量本身,确保召回必然命中最高相似度项;
  • TEST_COLLECTION_IDS = ['col_1', 'col_2', 'col_3']:三个固定的 collection id;
  • createTestIds():用 Date.now() + 随机后缀生成唯一的 datasetId,避免并行运行时互相污染。

工厂函数(testSuites.ts)

createVectorDBTestSuite(vectorCtrl: VectorControllerType) 接受一个符合统一接口的控制器实例,内部用 describe.sequential 串行注册用例,beforeAll 中先调用 vectorCtrl.init()(初始化表结构与索引),随后依次执行 6 个用例,每个用例结束都会清理本次写入的数据。

环境变量与启动配置

环境变量注入链路

测试环境变量由 test/.env.test.local 提供(该文件不提交到 git)。首次使用时复制模板并填写:

cp test/.env.example test/.env.test.local
# 编辑 test/.env.test.local,填入 PG_URL 等

启动时由 test/setup.ts 调用 test/utils/env.tsloadVectorDBEnv({ envFileNames: ['.env.test.local'] }) 读取并注入 process.env,因此各驱动入口才能直接判断 process.env.PG_URL 等变量是否存在。

支持的变量与对应驱动

变量 说明 适用驱动入口
PG_URL PostgreSQL + pgvector 连接串 pg/PgVectorCtrl
OCEANBASE_URL Oceanbase 连接串 oceanbase/ObVectorCtrl
MILVUS_ADDRESS Milvus 地址 milvus/MilvusCtrl
OPENGAUSS_URL OpenGauss 连接串 opengauss/OpenGaussVectorCtrl
SEEKDB_URL SeekDB 连接串(兼容 MySQL 协议) seekdb/SeekVectorCtrl

关键行为:未设置对应环境变量时,该驱动的集成测试会整体跳过,不会报错。 这一语义由入口文件中的 describe.skipIf(!isEnabled) 实现,例如 pg/index.integration.test.ts

const isEnabled = Boolean(process.env.PG_URL);

describe.skipIf(!isEnabled)('PG Vector Integration', () => {
  const vectorCtrl = new PgVectorCtrl();
  createVectorDBTestSuite(vectorCtrl);
});

运行方式

在项目根目录执行(pnpm workspace 环境):

# 仅运行 workspace 默认测试(不包含 integration)
pnpm test

# 运行 service 的 integration 测试(含 vectorDB 集成测试)
FASTGPT_TEST_MODE=integration pnpm test

FASTGPT_TEST_MODE=integration 是进入集成模式的开关。未设置时集成测试不会被执行;设置后,凡是配好了对应连接串的向量库都会跑同一套 createVectorDBTestSuite

六条核心用例逐条拆解

统一用例定义在 testSuites.ts,以下按执行顺序说明其验证目标:

1. insert and count:写入与计数

并行向 3 个 collection 各写入 1 条向量,然后分别断言:

  • getVectorCount({ teamId, datasetId }) 返回 3(等于 TEST_VECTORS.length);
  • getVectorCount({ teamId, datasetId, collectionId: TEST_COLLECTION_IDS[0] }) 返回 1,验证按 collection 粒度的过滤计数。

写入后固定等待 500ms,为部分向量库的索引异步可见性留出时间。

2. embRecall returns results:基础向量召回

QUERY_VECTOR 发起召回(limit: 3),断言:

  • 结果非空;
  • 每条结果的 collectionId 都落在 TEST_COLLECTION_IDS 内;
  • 每条结果都带 id 且属于本次插入的 id——这是整条链路的关键契约,见前文"主键必返"注释。

3. embRecall respects forbidCollectionIdList:排除指定集合

召回时传入 forbidCollectionIdList: [TEST_COLLECTION_IDS[0]],断言返回结果中不包含被排除的 collection。这是知识库检索中"跳过某目录/集合"能力的基础。

4. embRecall respects filterCollectionIdList:限定指定集合

与上一条相对,传入 filterCollectionIdList: [TEST_COLLECTION_IDS[1]],断言所有结果都来自该 collection,验证白名单过滤语义。

5. getVectorDataByTime returns data:按时间窗轮询

new Date(0) 为起点、Date.now() + 600_000 为终点查询时间窗内的向量数据,过滤出本次 team/dataset 的记录,断言其 id 集合包含本次插入的全部 id。这条用例验证的是增量同步类任务(如定时构建索引、统计回收)依赖的时间窗查询接口。

6. delete by idList removes vectors:按 id 删除

先插入 3 条,再按 idList 删除前 2 条,随后断言 getVectorCount 变为 1,验证精确删除的幂等性与计数一致性。

每个用例结束后统一调用 cleanupTestVectors,按 teamId + datasetIds 整库清理,避免测试数据残留影响后续运行。

控制器统一接口:工厂模式的契约基础

所有向量库控制器都实现同一个接口 VectorControllerType,定义于 packages/service/common/vectorDB/type.ts#L87-L117

export interface VectorControllerType {
  init(): Promise<void>;                     // 建表、建索引等初始化
  insert(props): Promise<InsertVectorResponseType>;
  delete(props): Promise<void>;              // 支持按 datasetIds 或 idList 删除
  embRecall(props): Promise<EmbeddingRecallResponseType>;
  getVectorDataByTime(start, end): Promise<GetVectorDataByTimeResponseType>;
  getVectorCount(props): Promise<number>;
}

六个方法正好对应六条核心用例,这正是"一套用例驱动多个库"能够成立的前提——各库入口只需 new 对应的控制器实现(如 PgVectorCtrlMilvusCtrlObVectorCtrl({ type: 'oceanbase' })OpenGaussVectorCtrlSeekVectorCtrl({ type: 'seekdb' })),传入工厂即可获得全部用例。

值得注意的是各入口都先执行 vi.unmock('@fastgpt/service/common/vectorDB/xxx')vi.unmock('@fastgpt/service/common/vectorDB/constants'),确保集成测试中使用真实控制器实现而非仓库默认的 mock。

Milvus 专属:BM25 全文检索集成测试

除通用用例外,Milvus 还配有独立的全文检索测试 milvus/fullText.integration.test.ts,覆盖 4 个场景:

用例 验证内容
TC-FT-0 从真实 collection 元数据探测 BM25 能力(describeCollectionFunctionType 在不同 SDK/服务端组合下可能返回数字 1 或字符串 BM25,该用例确保能力门禁不误报)
TC-FT-1 BM25 全文检索命中后,通过 indexes.dataId 反查 dataset_data 返回正确记录(results[0].dataId === String(doc._id)
TC-FT-2 filterCollectionIdList 把全文结果收窄到指定 collection
TC-FT-3 不存在的词返回空结果

该测试体现了两个重要的实现事实:

  1. Milvus 单表方案要求每条向量在 insert 时携带 BM25 文本texts 字段),其他 provider 会忽略该字段——这正是 testSuites.tstexts: ['integration-test-${index}'] 注释所说明的;
  2. 全文后端跟随实际向量库:provider 为 milvus 时恒为 BM25(modeldata_v2 单表),无独立引擎开关;且 Milvus 最低版本要求 2.5(推荐 2.5.16+),由应用启动版本门禁保证。

测试写入后调用 waitVisible()(默认 800ms)等待 Milvus 对刚写入的 growing segment 建立 sparse 索引并可见——这是分布式向量库测试中典型的时序处理。

本地环境搭建:docker-compose 一键起库

仓库提供了完整的测试依赖编排文件 packages/service/test/integrations/vectorDB/yml/docker-compose.yml,包含:

  • pgTestfastgpt/pgvector:0.8.0-pg15(PostgreSQL 15 + pgvector 0.8.0),映射宿主机 6001:5432,带 pg_isready 健康检查;
  • milvus-testmilvusdb/milvus:v2.5.16 standalone 模式,映射 6002:19530,配套 etcd(v3.5.5)与 MinIO(2023-03-20 版本)两个依赖服务,security_opt: seccomp:unconfined,带 /healthz 健康检查;
  • ob-testoceanbase/oceanbase-ce:4.3.5-lts,映射 6005:2881MODE=MINI 节省资源,并通过 config 注入初始化 SQL ALTER SYSTEM SET ob_vector_memory_limit_percentage = 30; 调整向量内存上限;
  • seekdb-testoceanbase/seekdb:1.0.1.0-100000392025122619,映射 6003:28816004:2886,兼容 MySQL 协议,用 mysqladmin ping 做健康检查。

启动后按上文映射关系填写 test/.env.test.local 即可,例如:

PG_URL=postgresql://username:password@127.0.0.1:6001/postgres
MILVUS_ADDRESS=127.0.0.1:6002
OCEANBASE_URL=...
OPENGAUSS_URL=...
SEEKDB_URL=...

注意 docker-compose 中的账号密码等配置只有首次运行生效,修改后需删除持久化数据目录再重启。

新增一个向量库的接入步骤

结合 README 与源码实现,接入新向量库只需四步:

  1. packages/service/common/vectorDB 下实现符合 VectorControllerType 接口的控制器(若为 MySQL 协议兼容库可参考 seekdb 入口的 new SeekVectorCtrl({ type: 'xxx' }) 写法);
  2. 新建 packages/service/test/integrations/vectorDB/<name>/index.integration.test.ts,模式为:vi.unmock 真实控制器 → 依据环境变量构造 isEnableddescribe.skipIf(!isEnabled) → 实例化控制器 → createVectorDBTestSuite(vectorCtrl)
  3. test/.env.test.local 中补充对应连接串变量;
  4. 可选:若需要 docker 环境,在 yml/docker-compose.yml 中追加对应服务。

完成后执行 FASTGPT_TEST_MODE=integration pnpm test,新库即可与 PG、Milvus 等库共享同一套 6 条核心用例,无需编写任何重复断言。

小结

这套集成测试的价值在于:把"向量库可插拔"从架构承诺变成了可执行验证。通过统一测试数据、统一用例工厂、按环境变量启停的驱动入口,FastGPT 得以在多向量库之间保持稳定的插入、召回、过滤、删除与计数语义;Milvus BM25 专项用例又针对分布式库的索引可见性与反查链路做了真实环境校准。无论你是要新增一种向量库支持,还是排查某个库的召回异常,都可以从这组集成测试入手:先看 testData.ts 理解数据基准,再看 testSuites.ts 对照接口契约,最后用 docker-compose 拉起目标库复现问题。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395