RAG 检索增强生成实战笔记
最近搭了一个基于内部文档的问答系统,走了一遍完整的 RAG(Retrieval-Augmented Generation)流程,记录关键环节和踩过的坑。
一、RAG 解决什么问题
大模型有两个天然短板:知识截止于训练时间、对企业私有数据一无所知,还容易幻觉。RAG 的思路是先检索、再生成——提问时先从知识库查出相关文档片段,塞进提示词里让模型基于这些材料回答。
二、完整流程
- 文档加载与清洗:解析 PDF/Word/Markdown,去掉页眉页脚等噪声。
- 切分(Chunking):把长文档切成小块。实践下来 300~500 字、块间重叠 50 字左右效果不错;按语义边界切优于按固定长度硬切。
- 向量化(Embedding):用嵌入模型把每个块转成向量。
- 入库:存入向量数据库(FAISS / Milvus / Chroma 等)。
- 检索:用户提问同样向量化,做近似最近邻搜索取 Top-K。
- 生成:把检索结果拼进 Prompt,交给 LLM 生成最终答案。
三、最小代码骨架
# 伪代码示意
query_vec = embed(user_question)
docs = vector_db.search(query_vec, top_k=5)
prompt = f"""请仅根据以下资料回答问题,资料中没有就说不知道。
资料:
{chr(10).join(docs)}
问题:{user_question}"""
answer = llm.chat(prompt)
四、踩坑记录
- 切分太碎导致上下文丢失,回答片面;切太大则噪声多、挤占上下文窗口。需要针对文档类型调参。
- 纯向量检索会漏关键词:比如专有名词、编号。混合检索(向量 + BM25)明显更稳。
- 加一层 Rerank(如 bge-reranker)对召回结果重排,精度提升明显,值得这点延迟开销。
- 提示词里一定要强调"不知道就说不知道",否则模型会用自身知识硬答,失去 RAG 的意义。
小结
RAG 的门槛在"跑通",天花板在"检索质量"。文档处理、切分策略、混合检索、重排,每一环都值得打磨。