企业级RAG落地的五层思考
企业级RAG落地的五层思考
在之前的RAG文章中,我分享了从零搭建RAG系统的过程。那时候更多是"能跑起来"的兴奋。但经过几个月的实践、踩坑、以及在实习中接触到的企业场景后,我开始思考一个更本质的问题:RAG要怎么在企业里真正落地?
不是demo级的"问个问题返回答案",而是能稳定服务、能量化评估、能在出问题时优雅降级的完整系统。
这篇文章整理了我目前的思考框架,分为五个层次。不一定适用所有场景,但至少是我反复思考和实践后的总结。
第一层:顶层设计 — 场景定义
很多RAG项目失败不是因为技术不行,而是一开始就没想清楚场景。在写第一行代码之前,需要回答三个问题:
用户是谁?
内部员工和外部客户对系统的要求完全不同。内部员工可能容忍一定的幻觉率,因为他们有领域知识可以判断;外部客户则零容忍 — 一个错误答案可能就是一次客诉。这决定了你的整个质量标准。
数据是什么样的?
这个问题比想象中复杂得多。你的数据是结构化的表格、半结构化的文档、还是扫描件的OCR结果?数据清洗的难度直接决定了RAG的天花板 — 我在自己的项目中就深有体会,博客内容的Markdown解析和Rust文档的HTML处理是完全不同的挑战。
时效性要求?
知识库需要实时更新还是每天批量同步?这影响了整个数据管线的架构设计。实时场景需要增量索引,离线场景可以用批处理。
第二层:核心链路 — 数据与架构
场景想清楚之后,就是搭建核心的RAG管线。我把它分为三个子层:
数据层:清洗SOP + 语义切片 + 元数据标注
"垃圾进,垃圾出"在RAG领域格外残酷。数据清洗不是一次性工作,而是需要一套标准化的SOP:
- 清洗规则:去噪(页眉页脚、水印文字)、格式统一(Markdown标准化)、编码修复
- 语义切片:不是简单的按字数切,而是按语义边界切分。我在shinBlog的RAG服务中用的是LangChain的RecursiveCharacterTextSplitter,但在实际企业场景中,可能需要针对文档类型定制切分策略
- 元数据标注:切片不能丢失上下文。每个chunk需要附带来源、标题、章节、日期等元信息,这些在检索和引用溯源时至关重要
检索层:混合检索 → 重排序 → Top K
纯向量检索有明显局限 — 精确匹配查询(如产品编号、错误代码)表现很差。成熟的方案是混合检索:
- Vector + BM25:语义相似度和关键词匹配互补
- Rerank:用交叉编码器对初步检索结果进行重排序,大幅提升相关性
- Top K控制:不是越多越好。通常Top 3-5是最佳平衡点 — 太多会引入噪音,太少可能遗漏关键信息
我在Kokoron的记忆系统中也应用了类似思路 — ChromaDB做向量检索,配合importance评分做重排。
生成层:System Prompt约束 + 引用溯源
检索只是手段,生成才是目的。这一层要解决两个关键问题:
- System Prompt约束:通过精心设计的提示词,限制模型只基于检索到的文档回答,降低幻觉。这不是万能的,但能显著减少"模型自由发挥"的情况
- 引用溯源(Citation):每个回答都应该标注来源。这不仅提升可信度,也方便用户验证信息。在企业场景中,引用溯源几乎是必须的
第三层:质量防线 — 评测闭环
光搭建管线还不够,没有评测就不知道系统到底好不好、有没有退化。
离线评测
- Golden Dataset:人工标注的标准问答对集合,作为基准
- Recall@K:检索到的前K个文档中包含正确答案的比例 — 衡量检索质量
- Faithfulness:生成的答案是否忠实于检索到的文档,而非模型"编造" — 衡量生成质量
这些指标构成了版本迭代的基线。每次修改检索策略或更换模型,都必须跑一遍评测。
在线监控
上线之后,离线指标不再够用。需要关注:
- 点踩率:用户主动标记"不好"的比例
- 引用点击率:用户是否真的会去看引用来源 — 高点击率意味着用户在验证而非盲信
- 空答率:系统回答"我不知道"的比例 — 太高说明知识库覆盖不足,太低说明可能在勉强回答
第四层:稳定性保障 — 性能优化
企业场景不是demo,需要面对真实的并发和成本压力。
语义缓存(Semantic Cache)
如果1000个用户问的是同一类问题,为什么要调用1000次LLM?
语义缓存的核心思想是:对语义相似的查询返回缓存结果。和传统缓存不同,这里的"相同"是向量空间中的相似度。效果可以非常惊人 — QPS可以提升10倍,LLM调用成本下降90%。
实现时需要注意:
- 缓存失效策略(知识库更新后需要清理相关缓存)
- 相似度阈值(太低会返回不相关答案,太高等于没缓存)
- 个性化场景慎用(不同用户的上下文可能导致同一问题需要不同答案)
异步流式(Streaming)
首字延迟是用户体验的关键指标。没有人愿意对着空白页面等5秒。
SSE(Server-Sent Events)是目前最主流的方案。在我的shinBlog RAG服务中,就是用FastAPI + SSE实现的流式返回。企业级场景可能需要更复杂的分段渲染:先返回检索到的引用来源,再逐步生成回答。
目标是首字延迟控制在200ms以内。
第五层:兜底策略 — 安全网
最后一层往往是最被忽视的,但也是最关键的 — 当系统不确定或出问题时,如何优雅处理?
拒答机制
当检索结果的相似度低于某个阈值(比如0.6),直接拒答而不是勉强编造。说"我不知道"永远比说错话好。
在Koclaw的记忆系统中,我对importance < 2的记忆设置了不自动注入的规则,背后逻辑是类似的 — 低质量信息不如不提供。
规则干预
某些高敏感查询不应该走LLM:
- 包含个人隐私信息的查询
- 涉及法律、医疗等专业领域的问题
- 包含特定敏感关键词的查询
这些场景应该直接走规则引擎或转人工处理。
降级策略
当向量数据库故障时,系统不应该直接挂掉,而是降级到BM25纯关键词检索保底。虽然质量会下降,但至少能保持基本可用。
类似地,当LLM服务不可用时,可以返回检索到的原文片段作为临时方案。
个人感想
搭建RAG看起来简单 — 切片、嵌入、检索、生成,四步完事。但真正要在生产环境中可靠运行,需要考虑的东西远远超出这四步。
从自己的shinBlog RAG助手,到为Koclaw设计的记忆检索系统,再到实习中接触的企业RAG需求,每一次实践都让我更深刻地理解:技术方案只占30%,剩下的70%是工程化、可观测性和对边界情况的处理。
这五层框架不是终点,而是思考的起点。如果你也在做RAG相关的工作,希望这些思考对你有所帮助。
有问题或想讨论的话,欢迎通过 GitHub 联系我。