脱敏说明:本文使用
cccc表示 Conda 虚拟环境easy-data-x-ai-test,使用xxxx表示原job_pls项目根目录。项目路径统一写作xxxx/easy-data-x-ai,不记录真实 API Key。
1. 实验目标
本次实验围绕 D3 的 Agentic RAG 流程展开,依次完成:
- 运行不依赖外部服务的离线评测;
- 启动 Docker 中的 SeekDB Server,并建立 D3 产品知识库;
- 对比纯向量检索、混合检索和元数据过滤;
- 测量检索准确率、延迟和上下文成本;
- 使用 OpenAI 兼容的 Ark 接口运行 Agentic RAG;
- 观察工具描述、
top_k和知识库增量更新等生产化问题。
2. 实验环境与模型配置
- 操作系统:Windows PowerShell
- Conda 环境:
cccc - Python:3.11.16
- 项目目录:
xxxx/easy-data-x-ai - 数据库:Docker Compose 启动的 SeekDB Server
- SeekDB 地址:
127.0.0.1:2881 - 演示数据库:
easy_data_x_ai_demo - 知识库集合:
d3_product_kb - 聊天接口:火山引擎 Ark 的 OpenAI 兼容接口
- 聊天模型:
deepseek-v4-flash-ga-260731
D3-2 和 D3-4 已从原来的 SiliconFlow 配置改为读取:
OPENAI_API_KEY=****** OPENAI_BASE_URL=https://ark.cn-beijing.volces.com/api/v3 MODEL_NAME=deepseek-v4-flash-ga-260731API Key 只保存在本地.env中,报告不记录真实值。
需要区分三类模型:
- D3-2、D3-4 的聊天模型由 Ark 提供;
- SeekDB 集合未传入自定义 Embedding,因此使用 pyseekdb 默认的本地
all-MiniLM-L6-v2ONNX 模型; - 完整 RAGAS 模式另有评审模型和标准文本 Embedding 配置,本次没有调用
--mode ragas。
3. D3-5:离线评测
首先运行无需 Docker 和 API Key 的确定性评测:
(cccc)PSxxxx/easy-data-x-ai> python code\D3\d3_5_evaluate.py >>> 已完成 60 条离线评测 >>> Hit@3:1.0 >>> 拒答准确率:1.0评测共包含 60 条案例,其中 50 条需要回答,10 条需要拒答。结果表明,离线工程管线在当前数据集上全部通过了 Top-3 命中和安全拒答检查。
随后运行离线检索三角基准:
(cccc)PSxxxx/easy-data-x-ai> python code\D3\d3_6_benchmark.py--backend offline >>> 已完成 50 条可回答案例的检索三角实验 >>> Hit@1:纯向量 0.72/混合检索 0.88 >>> P95:纯向量 1.9647 ms/混合检索 1.6990 ms离线结果中,混合检索的 Hit@1 比纯向量高 16 个百分点,且本次模拟基准的 P95 延迟更低。这里的延迟只代表本地确定性模拟,不等同于真实数据库性能。
4. SeekDB 启动与 D3-1 建库
4.1 第一次运行的问题
启动容器:
docker compose-f code/docker-compose.yml up-d docker compose-f code/docker-compose.ymlps容器正常显示为Up,端口映射为127.0.0.1:2881->2881/tcp。随后直接运行 D3-1 时出现:
RuntimeError: Embedded 模式依赖 pylibseekdb(当前平台未安装或不支持)原因是 Windows 不具备可用的pylibseekdbEmbedded 后端,而脚本默认先解析为 Embedded 模式。容器已经启动并不代表 Python 客户端会自动切换到 Server 模式。
4.2 设置 Server 模式
$env:SEEKDB_MODE ="server"$env:SEEKDB_HOST ="127.0.0.1"$env:SEEKDB_PORT ="2881"$env:SEEKDB_TENANT ="sys"$env:SEEKDB_DATABASE ="easy_data_x_ai_demo"$env:SEEKDB_USER ="root"$env:SEEKDB_PASSWORD =""$env:SEEKDB_ALLOW_DESTRUCTIVE ="1"再次运行 D3-1 成功:
>>> 集合已就绪:d3_product_kb >>> 已写入或更新 19 个知识片段 release_notes: 5 条 error_codes: 4 条 financial: 3 条 best_practices: 4 条 api_reference: 3 条 >>> d3_1 完成!知识库已就绪D3-1 使用upsert幂等写入文档,因此相同脚本重复运行不会简单地重复增加相同 ID 的记录。
5. D3-3:检索策略对比
运行:
python code\D3\d3_3_compare.py集合中共有 19 条文档,实验包含五种查询场景:错误码、季度数据、版本号、函数名和纯语义性能问题。
结果汇总:
纯向量检索命中率:1/5 增强检索命中率: 3/5典型现象如下:
E-4012查询中,纯向量检索返回相近的E-4013;混合检索使用全文关键词后命中E-4012。OB-4.2.1查询中,纯向量和元数据过滤都成功。DBMS_HYBRID_SEARCH查询中,纯向量返回 FAQ,全文关键词检索命中对应函数说明。- Q3 营收和数据库性能查询的 Top-1 仍未命中脚本设定的目标。
这些❌不是 Python 异常,而是脚本根据 Top-1 文本是否包含目标关键词做出的评测结果。说明检索流程成功,但当前模型、候选数量、分词和 RRF 排序仍会影响最终排名。
6. D3-6:SeekDB 检索基准
运行完整基准:
python code\D3\d3_6_benchmark.py `--backend seekdb `--warmup 5 `--rounds 30 `--top-k 3结果:
>>> 已完成 50 条可回答案例的检索三角实验 >>> Hit@1:纯向量 0.44 / 混合检索 0.74 >>> P95:纯向量 131.6844 ms / 混合检索 140.3247 ms真实 SeekDB 结果显示,混合检索的 Hit@1 比纯向量高 30 个百分点,但 P95 延迟增加约 8.64 ms。混合检索的一次应用请求内部包含全文分支、向量分支和 RRF 融合,因此会以少量延迟换取更好的精确标识符召回。
此前使用默认参数时长时间没有输出,最后出现KeyboardInterrupt。排查发现不是死循环,而是 50 条案例、5 轮预热、30 轮正式采样需要约 3500 次检索,每次都可能触发本地 ONNX Embedding。降低--warmup和--rounds可先进行快速验证。
7. D3-5 retrieval:真实知识库评测
运行:
python code\D3\d3_5_ragas_eval.py--mode retrieval本模式不调用生成模型,只使用真实 SeekDB 检索。当前运行无失败:
[vector] gold_chunk_recall_at_k 0.75 gold_chunk_precision_at_k 0.275 top1_reference_hit 0.3 evidence_coverage_at_k 0.75 all_required_evidence_at_k 0.65 stale_evidence_rate 0.0625 [hybrid] gold_chunk_recall_at_k 0.875 gold_chunk_precision_at_k 0.329167 top1_reference_hit 0.45 evidence_coverage_at_k 0.875 all_required_evidence_at_k 0.85 stale_evidence_rate 0.0875 failures: {'vector': {}, 'hybrid': {}}混合检索提高了召回、精确率、Top-1 命中和证据覆盖率,但旧证据比例从 0.0625 上升到 0.0875,说明混合检索还需要配合版本过滤和时效性策略,不能只看单一指标。
8. D3-2:Agentic RAG
运行:
python code\D3\d3_2_agentic_rag.py切换到 Ark 后,deepseek-v4-flash-ga-260731成功完成工具调用和最终回答:
- OB-4.2.1 兼容性问题成功调用知识库;
- E-4012 错误成功召回连接池耗尽及解决方案;
- 2024 年 Q3 营收成功召回 2.87 亿元等数据;
- 天气问题没有调用知识库,而是按系统提示拒绝回答实时天气。
这证明 D3-2 不要求固定使用 SiliconFlow,关键是聊天模型、Base URL、API Key 和 Tool Use 能力彼此匹配。
9. D3-4:生产化要点
运行:
python code\D3\d3_4_production.py结果:
>>> 已连接知识库:d3_product_kb,共 20 条文档 [模糊描述] ✅ Agent 调用了工具 [清晰描述] ✅ Agent 调用了工具 top_k=1:返回 1 条 top_k=3:返回 3 条 top_k=5:返回 5 条 top_k=8:返回 8 条 增量写入或更新 1 条文档后:20 条 >>> d3_4 完成!三个生产要点演示结束。本实验说明:
- 工具描述越具体,越有利于模型在正确场景调用工具;本次 Ark 模型在模糊和清晰描述下都调用了工具,但查询参数略有差异。
top_k越大,候选上下文越多,但也会增加后续模型输入长度和成本。upsert可以增量加入或更新文档,不需要删除并重建整个知识库。D3-4 写入的OB-4.3.0文档使集合从 19 条变为 20 条;重复运行仍保持 20 条。
10. 问题与解决方法
| 问题 | 原因 | 解决方法 |
|---|---|---|
| D3-1 首次运行提示 Embedded 不可用 | Windows 没有可用的pylibseekdb | 启动 Docker SeekDB,并设置SEEKDB_MODE=server |
| 容器启动后 Python 仍连接 Embedded | 容器状态不会自动修改当前 PowerShell 环境变量 | 手动设置SEEKDB_*后再运行脚本 |
终端出现意外PS语法错误 | 把带 PowerShell 提示符的输出文本再次粘贴进终端 | 只复制命令本身,不要复制(cccc) PS ...>提示符或输出 |
| D3-6 长时间无输出 | 多轮基准反复执行本地 ONNX Embedding,脚本没有逐条进度显示 | 先用--warmup 0 --rounds 1小规模验证,再运行完整基准 |
检索结果出现❌ | Top-1 评测条件未命中,不是程序异常 | 分开判断运行状态和检索质量,分析召回与排序结果 |
| Ark 模型回答时 Windows 编码异常 | GBK 控制台无法输出✅等字符 | 设置$env:PYTHONUTF8 = "1" |
| D3-2 原配置与当前模型不一致 | 脚本原来写死 SiliconFlow 和 DeepSeek-V3 | 改为读取OPENAI_API_KEY、OPENAI_BASE_URL、MODEL_NAME |