跳转到内容

RAG 知识库集成(架构与权衡)

RAG 知识助理 tutorial 给了完整 代码;本页讲架构权衡 — 把”能跑”做到”生产质量”的 6 个关键决策。

决策 1:Embedding model

ModelDim$ / 1M token适合
OpenAI text-embedding-3-small1536$0.02通用 / 中英混合(默认推荐)
OpenAI text-embedding-3-large3072$0.13高精度 / 复杂语义
Anthropic Voyage AI1024$0.05长文档优秀
Cohere multilingual1024$0.10多语言场景
BGE-large(开源 / 本地)1024$0隐私 / 离线 / 自托管

关键权衡

  • 切换 model 必须双写并行 30 天 → 灰度迁移 → 删旧 — 不能直接切(向量空间不兼容)
  • 1536 dim PG 索引(ivfflat)建索引时间 ~10 min / 1M chunks;3072 dim 约 30 min

决策 2:切块策略

策略块大小重叠适合
固定字符切(朴素)500 字符100 字符实现简单;适合 MVP
句子边界切3-5 句1 句中等;段落语义保留
Section / Heading 切按 H2/H3 边界结构化文档(Markdown / docx)
Semantic chunking嵌套 LLM 判定边界高质量;成本高

生产推荐:Heading 切 + 强 metadata(source / page / heading_path)

function chunkByHeadings(markdown: string): { text: string; metadata: any }[] {
const sections = markdown.split(/\n(?=#{1,3} )/);
return sections.flatMap((section) => {
const headingMatch = section.match(/^(#{1,3}) (.+)$/m);
const heading = headingMatch?.[2];
const body = section.replace(/^#{1,3} .+\n/, "").trim();
if (body.length < 100) return [{ text: section, metadata: { heading } }];
// 长 section 再按段落切
return body.split(/\n\n+/).map((para) => ({
text: `## ${heading}\n\n${para}`,
metadata: { heading },
}));
});
}

决策 3:Hybrid Search(vector + BM25)

纯向量检索对专有名词 / 缩写 / 错别字 容易漏。叠加 BM25 全文搜回率显著高。

SELECT id, text,
(embedding <=> $1) AS vector_distance,
ts_rank(to_tsvector('simple', text), plainto_tsquery('simple', $2)) AS bm25_score
FROM doc_chunks
WHERE user_id = $3
ORDER BY (embedding <=> $1) + (1.0 - ts_rank(...)) ASC
LIMIT 20;

或者用 Reciprocal Rank Fusion (RRF):vector 和 BM25 分别取 top 50,按 1/rank 加权融合。

决策 4:Re-ranking

top-k 检索后用 cross-encoder 二次精排,提升准确率 10-20%。

import { CohereClient } from "cohere-ai";
const cohere = new CohereClient({ token: process.env.COHERE_API_KEY });
const reranked = await cohere.rerank({
model: "rerank-multilingual-v3.0",
query: question,
documents: topK.map((d) => d.text),
topN: 5,
});
const finalContext = reranked.results.map((r) => topK[r.index].text);

成本:~$2 / 1000 query。值不值看准确率提升。

决策 5:引用透明

LLM 回复后明确标 [1] [2] 标号,artifact 卡列源:

const c = await openai.chat.completions.create({
messages: [
{ role: "system", content: `回答末尾用 [1] [2] 标注引用源。如果不足 → 直说"信息不足"。
来源:
[1] ${chunks[0].source} ${chunks[0].text.slice(0, 100)}...
[2] ${chunks[1].source} ${chunks[1].text.slice(0, 100)}...` },
{ role: "user", content: question },
],
});
await agent.send(convId, { type: "text", text: c.choices[0]?.message?.content });
await agent.sendArtifact(convId, {
artifact: {
subtype: "info", title: "参考来源",
payload: { body: chunks.map((c, i) => `**[${i+1}]** ${c.source}`).join("\n") },
},
});

为什么这是必须的:用户对”AI 幻觉”敏感;明确引用提升信任感 + 让用户能验证。

决策 6:数据主权边界

Hashee 平台:永远看不到文档内容(盲管道)。 你的 Agent 后端:保存文档明文 + embedding(业务需要)。 用户撤销:触发 relation.revoked → 必须立即 DELETE FROM doc_chunks WHERE user_id = ?

明文存哪:

位置隐私实用
Agent 后端 PG高(用户授权后访问)
用户自己设备(V2 路线)极高低(agent 离线时不可达)
第三方向量 DB(Pinecone / Weaviate)中(看 vendor TOS)

V1 推荐:Agent 自己后端 PG + pgvector

性能基准

操作P50P95
Embedding(OpenAI small)80 ms200 ms
pgvector top-5 检索 (100k chunks)30 ms80 ms
LLM 总结(gpt-4o-mini)800 ms2 s
端到端 RAG 回答1-2 s3 s

监控

指标报警
Embedding 调用 / day异常飙升 → 看是否被滥用
检索 vector_distance p50> 0.5 → 知识库覆盖差
LLM “信息不足” 回复率> 30% → 库需扩充
用户点 thumbs down 比例> 10% → 检查 prompt / 切块策略

相关页面