用 AI 写规格、国内大模型做推理:一百块能否搭出生产级 RAG?

天涯轩 · 人人都是产品经理 · 2026-05-30 · 约 4600 字

基本信息

项目内容
作者天涯轩
发布平台人人都是产品经理
发布日期2026-05-30
字数约 4600 字
主题RAG 生产级系统搭建实战

核心观点

  1. 100 元人民币搭出生产级 RAG 平台:Claude Code 生成方案与代码 + 通义千问提供推理与向量,全链路 API 花费约 100 元。包含多格式文档入库、Milvus 混合检索、LangGraph 十节点状态机、评测面板与企业级前端。成本参考意义在于 API 费用透明可预估,但需叠加人力调试与基础设施成本。

  2. 规格驱动 + AI 生成的两段式开发有效:先用 Claude Code 输出约 440 行的实现方案文档(hashed-gliding-metcalfe.md),再按方案逐模块生成 Monorepo 代码。规格驱动使 Monorepo 结构、LangGraph 节点与 API 边界在第一天就清晰,减少”写到哪算哪”的架构漂移。

  3. 真正的敌人是静默失败:14 个 Bug 中最耗时的不是 npm 404 或端口占用,而是检索 0 条、配置被忽略、维度 silently mismatch——它们共同特点是系统不报错。Bug 分布:SDK 参数不兼容 3 个、参数不匹配 3 个、配置/路径问题 3 个、逻辑 Bug 3 个、环境问题 2 个。

  4. Embedding 模型输出维度必须与向量库 Schema 完全一致:通义千问 text-embedding-3-large 实际输出 1024 维,若 Schema 按 OpenAI 默认写成 3072 维,Milvus 可能仍能插入但检索静默返回 0 条——这是全文最隐蔽的故障。变更模型后必须重建集合。

  5. 不同 Embedding 模型的 COSINE 分数分布差异巨大,不能照搬海外模型阈值:通义 v3 直接 search Top5 分数仅 0.26–0.45,若参照 OpenAI 经验设定阈值 0.7 则全部被过滤。正确做法是默认阈值降至 0.2,或由 Rerank + Grade 节点承担质量控制,而非在 retrieve 阶段过早硬过滤。

  6. LangChain 国内 API 接入必须用 configuration.baseURL 而非 baseUrl@langchain/openai 对两种写法处理不一致,baseUrl 会被忽略导致请求打到 api.openai.com,表现为”日志显示成功、检索却无结果”。ChatOpenAI 与 OpenAIEmbeddings 均需使用 configuration: { baseURL: '...' }

  7. 生产 RAG 需要闭环:分类→HyDE→检索→Rerank→压缩→生成→评估→重写:LangGraph 十节点状态机实现查询分类(factual/comparative/general)→ 分解或改写 → HyDE 假设文档 → 混合检索 → Rerank → 压缩 → 生成 → 评估,评估不通过可回退重写形成可调优闭环,而非一次性黑盒。

  8. 故障排查四层策略(可复用):按层自下而上隔离——存储层(Milvus count / PostgreSQL 一致性)→ 向量层(sample vector length / 索引存在性)→ API 层(独立脚测 Base URL / 延迟 / 维度)→ 管道层(retrieve 条数与 score / 阈值与 Rerank)。对比测试用 A/B 两个最小脚本一锤定音。

实操内容保留

环境配置样例

LLM_BASE_URL: https://dashscope.aliyuncs.com/compatible-mode/v1
LLM_MODEL: qwen3.6-plus
EMBEDDING_MODEL: text-embedding-v3(百炼兼容接口)
EMBEDDING_DIMENSION: 1024
DATABASE_URL: PostgreSQL 连接串(Monorepo 根目录.env,非 packages/backend/.env)

LangChain 正确配置 vs 错误配置

// ✅ 正确:configuration.baseURL
new OpenAIEmbeddings({
  model: 'text-embedding-v3',
  apiKey: 'sk-…',
  configuration: { baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1' },
  dimensions: 1024,
});
 
// ❌ 错误:baseUrl 会被忽略,请求打到 api.openai.com,超时或异常
new OpenAIEmbeddings({ baseUrl: 'https://dashscope.aliyuncs.com/…' });

Milvus 集合字段样例

集合名: rag_chunks
主键 id: VarChar
document_id: VarChar(分区键)
dense_vector: FloatVector(dim = 1024,必须与 Embedding 实际输出一致)
sparse_vector: SparseFloatVector(BM25)
metadata: JSON(含 headerPath、section_title 等)

Milvus 索引创建规则

index_type: IVF_FLAT
metric_type: COSINE
params: 必须传对象 { nlist: 1024 }
⚠️ 不能 JSON.stringify 给 extra_params,否则 Go 后端反序列化失败,索引静默未建

LangGraph 十节点查询路由

classify(查询分类)
  → factual / comparative → decompose(子问题分解)→ retrieve
  → general / other → rewrite → 可选 HyDE(生成假设文档)→ retrieve
retrieve 后统一:
  → rerank → compress → generate → evaluate
evaluate 结果:
  → pass / ambiguous → format → END
  → fail 且未超重试次数 → rewrite → 回到检索链路
约束:节点名不得与 RAGState 字段同名(如 grade 节点需改名为 evaluate)

对照自查清单(10 项)

  1. Embedding 维度:向量模型实际输出几维?Milvus Schema dim 必须一致,变更后支持重建集合
  2. API 兼容写法:LangChain 版本下国内 Base URL 怎么传?用 configuration.baseURL,独立脚本验证
  3. 相似度阈值:COSINE 分数在自家语料上的分布区间?可配置阈值,retrieve 勿过早硬过滤
  4. Milvus 索引:索引参数格式是否与 SDK 版本匹配?params 传对象,启动时检查索引是否存在
  5. 环境变量路径:Monorepo 子包从哪里读.env?显式 resolve 根目录路径,变量名与 Zod Schema 一致
  6. 入库幂等:上传一次写几条文档记录?路由创建 documentId,服务层只更新状态不重复 insert
  7. LangGraph 命名:节点名是否与 State 字段冲突?编译期可报错,命名规范 review
  8. 前端样式链:Tailwind 大版本升级插件是否注册?Vite 中 @tailwindcss/vite
  9. 开发代理:multipart 上传走不走 dev proxy?生产直连后端,开发期可用 curl/Postman 绕过
  10. 进程管理:热重载是否残留占用端口?重启前释放 3000 端口,或文档化 kill 命令

关键概念

  • RAG 知识库:检索增强生成,系统核心架构
  • LangGraph:十节点状态机 RAG 管道的编排框架
  • Milvus:稠密+BM25 稀疏混合索引向量数据库
  • 通义千问:对话模型 qwen3.6-plus + 向量模型 text-embedding-3-large
  • Embedding 嵌入:向量维度一致性是生产 RAG 最隐蔽的故障源
  • Claude Code:规格驱动开发中生成方案文档与代码的工具
  • HyDE(Hypothetical Document Embeddings):假设文档嵌入,提升检索召回的技术

不同素材的关联

原文精彩摘录

本次实验的目标因此很明确:不是做一个能跑通的 Demo,而是实测从零完成一套带评测与可观测性的 RAG 平台,究竟消耗多少 Token、会遇到哪些典型故障。开发方式采用「先写规格、再生成代码」:Claude Code 产出施工蓝图 hashed-gliding-metcalfe.md,再据此生成 Monorepo、Docker、前后端与 LangGraph 流水线;模型侧统一走阿里百炼 OpenAI 兼容接口。

若 Schema 按 OpenAI 默认写成 3072 维,而实际 API 返回 1024 维,Milvus 可能仍能插入但检索静默返回 0 条——这是本次实验中最耗时的隐蔽故障之一。

14 个 Bug 里,最耗时的不是 npm 404 或端口占用,而是检索 0 条、配置被忽略、维度 silently mismatch——它们共同特点是系统不报错。生产 RAG 的上限,往往由 Embedding 兼容性、向量库 Schema、阈值与评测闭环决定,而不是 Prompt 写得多漂亮。

不同 Embedding 模型的 COSINE 分数分布差异很大,不能照搬海外模型的阈值;上线前必须用独立脚本测自家模型的分数区间。