RAG 系统踩过的坑,都是钱买的
做 RAG 系统别一上来就搞框架
# RAG 系统踩过的坑,都是钱买的
先说个数据:我们团队做 RAG 系统前后花了将近三个月,烧了大概六万块云资源费,最后上线的版本跟第一个 MVP 几乎一模一样。听起来很蠢对吧?但这里面每一个坑都挺有代表性的,写出来让大家避一避。
坑一:先搞向量数据库,再想数据怎么切
我们第一个版本的错误流程是:先选了 Pinecone 做向量数据库,选了 BGE-large 做 embedding 模型,然后才开始整理数据。
结果发现:我们的文档格式很乱——PDF 扫描件、Word 文档、HTML 页面、Excel 表格混在一起。直接丢进 embedding 模型里,切出来的 chunk 质量差到离谱。有的 chunk 只有半句话,有的 chunk 包含了整个页面的元数据(页眉页脚导航栏),检索出来全是噪声。
**正确的做法**:先花两周时间整理数据源。搞清楚你的文档长什么样、什么格式、大概多少量级。格式清洗比选 embedding 模型重要十倍。
我们后来重做的时候,先做了一个数据管道:PDF 用 OCR 转文本,Word 直接解析,HTML 抽正文,Excel 转 markdown 表格。花了一周时间,但后续的检索质量提升了至少一个量级。
坑二:Chunk 大小不是越大越好
这是一个普遍的误区。很多人觉得 chunk 越大上下文越完整,检索效果越好。实际上不是。
我们的测试数据:
原因很简单:chunk 太大之后,检索出来的内容里面混入了大量无关信息,LLM 处理的时候注意力被分散,反而影响回答质量。而且 chunk 越大,embedding 的语义集中度越低。
**结论**:对于中文内容,chunk_size 在 300-500 字符区间效果最好。而且要用重叠(overlap)来保证语义连续性,我们用的是 50-100 字符的重叠。
坑三:不要只用向量检索
纯向量检索有个致命缺陷:它只能找到"语义相似"的内容,找不到"精确匹配"的内容。
举个例子:用户问"合同编号 HT-2025-0892 的签署方是谁",向量检索大概率会给你一堆关于合同签署的通用内容,而不是这个具体编号的信息。
我们后来加了 Hybrid Search——向量检索 + BM25 关键词检索——然后把两个结果用 Reciprocal Rank Fusion 合并。准确率从 71% 提升到了 84%。
代码上不算复杂:
from sentence_transformers import SentenceTransformer
from elasticsearch import Elasticsearch
model = SentenceTransformer('BAAI/bge-large-zh')
es = Elasticsearch(['http://localhost:9200'])
def hybrid_search(query: str, top_k: int = 10):
# 向量检索
query_embedding = model.encode(query).tolist()
vector_results = es.search(
index='docs',
body={
'size': top_k,
'query': {
'script_score': {
'query': {'match_all': {}},
'script': {
'source': 'cosineSimilarity(params.q, \'embedding\') + 1.0',
'params': {'q': query_embedding}
}
}
}
}
)
# BM25 检索
keyword_results = es.search(
index='docs',
body={
'size': top_k,
'query': {
'multi_match': {
'query': query,
'fields': ['title', 'content'],
'type': 'best_fields'
}
}
}
)
# RRF 合并
return rrf_rank(vector_results, keyword_results, top_k)
坑四:评估比实现重要
这是我最后悔没有早点做的事。我们前两个月一直在"调模型""调参数""换数据库",但从来没有系统性地评估过效果。
直到有一天产品负责人问"我们这系统到底准不准",我们愣是答不上来。
后来我们做了一套评估体系:
2. 每条问题人工标注"期望答案"
3. 用 Retriever F1、Answer Relevancy、Context Precision 三个指标量化评估
做完评估之后发现:我们换了三个 embedding 模型,效果差异不超过 3%;但 chunk 策略的调整带来了 15% 的提升。
**教训**:先建评估体系,再优化。没有评估的优化就是拍脑袋。
坑五:忘记处理"我不知道"的情况
最后一个坑,但可能是最致命的。我们最初版本的 RAG 系统有一个问题:当检索结果不相关时,它还是会硬着头皮回答,而且看起来"很有自信"。
用户问"我们的差旅报销标准是什么",检索结果里根本没有这个内容,但模型会基于一些无关的文档片段编一个答案出来,还带着一股"我确定是这样"的语气。
这个在 AI 安全里叫"幻觉",但在业务场景里叫"事故"。
解决方案是用一个"置信度阈值"——当检索到的 chunk 和问题的语义相似度低于某个阈值时,直接返回"抱歉,我暂时没有找到相关信息",而不是硬答。
我们在生产环境设的阈值是 cosine_similarity > 0.72,低于这个值的查询走 fallback 流程,转人工或者提示用户换一种问法。这个设置让误答率从 18% 降到了 3%。
一句话总结
RAG 系统的核心不是选哪个模型、用哪个向量数据库,而是**数据质量**和**评估体系**。先把这两件事做好,其他的都是锦上添花。