目标:把 RAG 的“检索→融合→重排→生成”标准流程讲清楚,并能跑起来。
🎯 文章目标
- 认识标准流程与关键设计点
- 提供最小可运行示例(Python + Node.js)
- 给出评估维度与常见取舍
📚 背景/前置
- 检索:BM25/向量检索/融合检索
- 融合:RRF/加权融合;重排:交叉编码器/LLM 评分
- 生成:引用与约束输出;支持“无依据拒答”
🔧 核心内容
1) 标准流程
- 切分→嵌入→索引→召回→融合/重排→生成→评估→反馈
- 关键点:切分策略、嵌入模型选择、Top-K、重排器、提示约束
2) Python 最小示例(Chroma + SentenceTransformer)
python
# pip install chromadb sentence-transformers openai
import chromadb
from sentence_transformers import SentenceTransformer
from openai import OpenAI
m = SentenceTransformer('all-MiniLM-L6-v2')
col = chromadb.Client().get_or_create_collection('kb')
col.add(ids=['1','2'], documents=['RAG 包含检索与重写','重排可用交叉编码器提升相关性'])
q = 'RAG 的关键步骤?'
# 向量检索(toy)
ctx = '\n'.join(col.query(query_texts=[q], n_results=2)['documents'][0])
cli = OpenAI()
msg = [
{"role":"system","content":"只基于上下文回答,引用出处,若无依据请说不知道"},
{"role":"user","content":f"上下文:\n{ctx}\n\n问题:{q}"}
]
print(cli.chat.completions.create(model='gpt-4o-mini', messages=msg).choices[0].message.content)
3) Node.js 重排示意(LLM 评分)
javascript
const passages = ['片段A','片段B','片段C']
async function rerank(q, items){
const scored = await Promise.all(items.map(async it => {
const s = await scoreWithLLM(q, it) // 0~1
return { it, s }
}))
return scored.sort((a,b)=>b.s-a.s).map(x=>x.it)
}
4) 评估与观测
- 维度:正确率/引用一致性、Top-K 命中率、延迟与成本
- 方法:离线集 + 在线 A/B;记录失败样本与最慢 5%
📊 对比/取舍(速查)
- 先把召回做稳,再谈生成“写得好”
- 重排提升质量,但增加成本与延迟
- 融合检索对异构语料更稳,但实现更复杂
🧪 踩坑与经验
- 片段切分:过短丢语义,过长拖慢与引噪
- 嵌入版本漂移:更新需回归评测
- 引用不显式:输出不可信,需“引用+拒答规则”
📎 参考与延伸
- RRF/融合检索,交叉编码器与 LLM 重排
- 切分/窗口策略,RAG 评估方法
💭 总结
- 把“检索/融合/重排/生成/评估”串起来,并用观测与闭环持续优化