ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

RAG、记忆、API与MCP:带鉴权审计的大模型应用落地实战

RAG、记忆、API与MCP:带鉴权审计的大模型应用落地实战 1. 从能跑通到敢上线这套应用到底在解决什么问题大模型应用最尴尬的阶段不是Demo跑不起来而是Demo跑起来之后没人敢用。我见过太多团队花两周搭出一个能对话、能查知识库的原型演示时效果惊艳一旦要接入真实业务问题全冒出来了模型记不住上一轮说过什么工具调用没有权限边界谁在什么时候调了什么接口完全没记录出了事连回溯都做不到。这套基于RAG、记忆、API和MCP构建的带鉴权审计应用要解决的就是从能跑通到敢上线之间那段最难走的路。先把四个核心件的关系理清楚。RAG负责让模型知道——把外部知识库的内容检索出来塞进上下文解决模型知识陈旧和幻觉问题。记忆负责让模型记得——跨轮次、跨会话保留关键信息解决对话断裂和个性化缺失。API负责让模型能做——通过函数调用去操作外部系统比如查订单、发邮件、写数据库。MCP负责让模型接得上——用一套标准化协议把上面这些能力统一暴露给模型避免每接一个工具就写一套胶水代码。但光有这四个还不够。真正让应用能上生产的是鉴权和审计这两层。鉴权决定谁能让模型做什么审计决定模型到底做了什么、能不能查。很多教程讲到RAG和工具调用就停了鉴权审计一笔带过结果就是应用永远停在内部试用阶段。这篇内容我会把这两层当成一等公民来讲因为它们才是决定应用能不能交付的关键。适合谁看如果你已经用LangChain、LlamaIndex或者类似框架搭过RAG原型能调通大模型API但对怎么加权限怎么记录工具调用MCP到底怎么落地还比较模糊那这篇就是写给你的。如果你是完全零基础建议先把RAG的基本检索流程跑通再回来因为这里会涉及不少工程细节。提示本文所有方案都基于常见工程实践推导具体参数和选型需要根据你的业务规模、合规要求和现有技术栈调整不要照搬。2. RAG不是塞进去就行检索质量决定应用下限2.1 为什么你的RAG总是答非所问RAG的原理听起来简单用户提问去知识库检索相关片段拼进提示词让模型基于片段回答。但实际做下来十有八九会遇到检索出来的东西跟问题不相关或者相关的内容没被检索到。这不是模型的问题是检索环节的问题。最常见的坑是切分粒度。很多人把文档按固定字数切比如每500字一块。结果一个完整的操作步骤被切成两半检索到上半段却丢了关键的下半段。我的经验是切分要跟着文档的语义结构走Markdown按标题层级切代码按函数切FAQ按问答对切。如果文档结构混乱那就用递归切分先按段落段落太长再按句子尽量保证每块内容是语义完整的。第二个坑是只用向量检索。向量检索擅长语义相似但对精确匹配很弱。用户问错误码401怎么解决向量检索可能返回一堆讲权限问题的段落但真正包含401这个精确字符串的段落反而排在后面。解决办法是混合检索向量检索加关键词检索BM25两路结果用倒数排名融合RRF合并。实测下来混合检索的命中率比纯向量检索能高出20到30个百分点。2.2 检索参数怎么调才不玄学检索有几个关键参数调不好就是玄学。我列一下我的常用起点和调整逻辑参数常用起点调整逻辑召回数量 top_k10-20太小漏召回太大引入噪声先大后精排相似度阈值0.3-0.5低于阈值的结果宁可不给避免误导模型重排数量3-5精排后只保留最相关的几块进上下文上下文窗口占用不超过50%给对话历史和工具结果留空间这里有个容易被忽略的点重排Rerank。向量检索是粗筛重排模型是精排。粗筛召回20条用重排模型比如bge-reranker这类对每条打分取前3到5条。重排模型比向量模型慢但只对少量候选打分总体开销可控效果提升明显。我试过在同一个知识库上加不加重排答案准确率能差15%以上。还有一个实战技巧给检索结果加上来源标注。每块内容带上文档名、章节、更新时间。这样模型回答时能引用来源审计时也能追溯这个答案是从哪来的。这在需要合规的场景里几乎是必须的。2.3 知识库更新与失效处理知识库不是建好就完事。业务文档会更新旧内容会失效。如果知识库不更新模型就会拿着过时的信息一本正经地胡说。我的做法是给每块内容打上版本和时间戳检索时优先返回新版本。同时维护一个失效标记旧版本不删除但标记为失效检索时过滤掉。这样既保留了历史可追溯又不会让旧内容污染答案。更新策略上小规模知识库可以全量重建索引大规模的要走增量更新。增量更新的关键是内容指纹对每块内容算一个哈希内容没变就跳过变了才重新向量化。这样能把更新成本降下来。我见过一个团队每次更新都全量重跑几万条文档要跑几个小时改成增量后几分钟搞定。3. 记忆系统让模型记住该记的忘掉该忘的3.1 短期记忆和长期记忆要分开设计记忆这块最大的误区是把所有历史对话都塞进上下文。这么做有两个问题一是上下文很快被撑爆二是无关信息会干扰模型判断。正确的做法是短期记忆和长期记忆分开。短期记忆是当前会话的上下文保留最近几轮对话。但不是原样保留而是要做摘要压缩。比如每5轮对话做一次摘要把摘要加最近2轮原文一起放进上下文。这样既保留了连贯性又控制了长度。我常用的策略是最近3轮保留原文更早的用摘要替代。长期记忆是跨会话的需要持久化存储。这里的关键是记什么。不是所有信息都值得记。我的筛选标准是用户明确表达的偏好我喜欢简洁的回答、重要的实体信息我的项目叫XX、未完成的任务下次继续讨论XX。这些信息抽取出来后存进向量库或结构化存储下次会话开始时检索相关记忆注入上下文。3.2 记忆的评分与衰减机制长期记忆如果只增不减很快就会变成垃圾场。我参考了一套记忆评分加时间衰减的机制效果不错。每段记忆有一个分数初始分基于重要性用户明确说的偏好分数高随口一提的分数低。每次被检索命中并实际使用分数加一点。同时分数随时间衰减衰减公式类似半衰期模型score score * 0.5^(days / half_life)。半衰期设成7到30天看业务场景。这样久未使用的记忆会自然沉底常用的记忆会浮上来。检索时按分数排序只取前几条。这样既控制了注入上下文的信息量又保证了最相关的记忆优先。实测下来这套机制比全部保留或只保留最近都要好尤其在长期使用的场景里。3.3 记忆与RAG的边界在哪很多人会混淆记忆和RAG。简单说RAG是公共知识记忆是个人上下文。RAG查的是所有人都能访问的知识库记忆存的是这个用户自己的历史。两者检索路径可以复用但存储要分开权限也要分开——A用户的记忆绝不能被B用户检索到。在实现上记忆检索和RAG检索可以走同一套向量检索流程但记忆的命名空间要按用户ID隔离。查询时带上用户ID过滤确保只检索到自己的记忆。这一点在鉴权章节还会展开因为它是权限边界的一部分。4. 工具调用与MCP把能力标准化地接进来4.1 从函数调用到MCP的演进逻辑早期让模型调用工具是直接在提示词里描述函数签名模型输出JSON代码解析后执行。这种方式能用但每接一个新工具就要改提示词、改解析逻辑工具一多就乱。后来有了函数调用Function Calling模型原生支持输出结构化的调用请求省去了提示词工程但工具的定义和注册还是各框架各搞一套。**MCPModel Context Protocol**要解决的就是这个标准化问题。它定义了一套协议工具、资源、提示词都按统一格式暴露模型侧按统一格式调用。好处是工具提供方和模型使用方解耦工具写一次任何支持MCP的客户端都能用。你可以把它理解成AI工具界的USB接口——以前每个设备一个专用接口现在统一成USB-C。MCP的核心概念有三个Tools可调用的函数、Resources可读取的数据、Prompts预定义的提示模板。实际落地时Tools用得最多Resources次之Prompts看场景。4.2 一个MCP Server的落地要点写一个MCP Server核心是把你的能力包装成标准接口。以查询订单为例你需要定义工具名、描述、参数schema然后实现执行逻辑。描述很重要模型靠描述判断什么时候调用这个工具。描述要写清楚这个工具做什么什么情况下用参数是什么意思。几个实战要点参数校验要在服务端做。不要信任模型传来的参数类型、范围、必填项都要校验。模型偶尔会传错类型或者漏参数。超时要设。工具执行可能卡住必须设超时超时后返回明确的错误信息让模型知道。错误要结构化返回。不要直接抛异常返回{success: false, error: 订单不存在}这样的结构模型能理解并据此回复用户。幂等性要考虑。如果工具是写操作比如下单要防止模型重复调用导致重复下单。可以用请求ID做幂等。MCP Server可以本地跑stdio传输也可以远程跑HTTP/SSE传输。本地适合个人工具远程适合团队共享。远程的话鉴权就特别重要不能让任何人都能调你的工具。4.3 工具编排多个工具怎么协同单个工具好办难的是多个工具协同。比如用户问帮我查一下上个月的订单如果有未发货的帮我催一下这需要先查订单再筛选未发货再调催单工具。模型能不能自己编排好取决于工具描述是否清晰、上下文是否给足。我的经验是把复杂流程封装成高层工具。与其让模型自己串联三个底层工具不如提供一个查询并催单的高层工具内部逻辑自己实现。这样模型只需要调一次成功率和稳定性都高。底层工具留给需要灵活组合的场景。另外工具返回结果要控制长度。有的工具返回一大坨JSON直接塞进上下文会挤爆窗口。做法是在工具层做裁剪只返回模型需要的关键字段或者返回摘要加一个引用ID模型需要详情时再查。5. 鉴权谁能让模型做什么5.1 鉴权要覆盖的三个层面鉴权不是加个API Key就完事。在这类应用里鉴权要覆盖三个层面第一层是用户鉴权谁在跟这个应用对话。这决定了这个用户能访问哪些知识库、哪些记忆、哪些工具。用户A不能查用户B的订单这是最基本的隔离。第二层是工具鉴权这个用户有没有权限调用某个工具。比如普通用户能查订单但只有管理员能调退款工具。工具鉴权要在MCP Server侧做不能只靠前端隐藏按钮。第三层是数据鉴权工具执行时能访问哪些数据。比如查订单工具只能查当前用户的订单不能查别人的。这层要在数据访问层做过滤通常是在查询里强制加上用户ID条件。三层缺一不可。我见过只做了第一层、工具层裸奔的应用结果用户通过构造提示词让模型调用了管理员工具直接越权。5.2 权限模型怎么设计权限模型不用一上来就搞RBAC那么复杂。小规模应用一个简单的权限表就够用户ID到工具列表的映射加上数据范围。比如用户角色可调用工具数据范围普通用户查订单、查物流仅自己的数据客服查订单、查物流、改地址所服务客户的数据管理员全部工具全部数据工具调用前先查这张表没权限直接拒绝返回明确的错误。拒绝信息不要泄露太多细节比如不要说你没有退款权限而是说该操作不可用避免信息泄露。权限判断要在服务端做而且要在工具执行前做。不要等工具执行到一半才发现没权限那样可能已经产生了副作用。5.3 密钥与凭证的管理应用要调大模型API、要连数据库、要调外部服务这些都需要凭证。凭证管理最容易出的问题是硬编码——直接写在代码里提交到仓库泄露风险极高。正确做法是用环境变量或密钥管理服务。本地开发用.env文件记得加进.gitignore生产环境用专门的密钥管理。凭证要定期轮换尤其是怀疑泄露时立即轮换。还有一个细节日志里不能打印凭证。我见过日志把完整的API Key打出来日志一泄露全完了。打印时要做脱敏只显示前几位和后几位中间用星号代替。注意调用外部API时如果遇到401错误先检查凭证是否正确、是否过期、是否有空格或换行混入。这类问题排查起来很费时间但原因往往很简单。6. 审计模型做了什么必须查得到6.1 审计日志要记什么审计的核心是可追溯。出了问题能查到谁在什么时候让模型做了什么模型调了哪些工具返回了什么。所以审计日志至少要记请求信息用户ID、会话ID、时间戳、原始输入检索信息检索了哪些知识库、命中了哪些片段、相似度分数模型信息用的哪个模型、输入token数、输出token数、耗时工具调用调了哪个工具、参数是什么、返回什么、成功还是失败最终输出模型给用户的回复这些信息串起来就是一次完整的调用链路。出问题时按会话ID或用户ID一查全流程清清楚楚。日志的存储要考虑量和成本。全量存原始输入输出量会很大。我的做法是结构化字段全存原始文本按需存比如只存摘要或者存一段时间后归档。敏感信息要脱敏后再存。6.2 审计与鉴权的联动审计不只是事后查还能实时风控。比如某个用户在短时间内大量调用敏感工具或者频繁触发权限拒绝这可能是异常行为可以实时告警甚至临时封禁。实现上审计日志写入后可以接一个规则引擎匹配到异常模式就触发动作。规则不用太复杂几条就够单位时间调用次数超阈值、敏感工具调用、连续权限拒绝。这些规则能挡住大部分明显的滥用。审计日志本身也要保护。不能让普通用户看到别人的审计日志也不能让用户删改自己的日志。日志写入应该是只追加的不允许修改和删除。这在合规场景里是硬要求。6.3 排查问题的完整链路线上出问题时排查链路是这样的用户反馈回答不对先拿会话ID查审计日志看这次请求检索了什么、模型看到了什么、调了什么工具。常见的问题定位现象可能原因排查方向答非所问检索没命中看检索片段和相似度信息过时知识库未更新看命中片段的版本时间工具没调描述不清或权限不足看工具描述和权限判断日志调用失败参数错误或超时看工具入参和错误返回越权访问鉴权缺失看权限判断是否执行有了完整审计这些问题都能快速定位。没有审计就只能靠猜效率差十倍不止。7. 把这些拼起来一个可运行的架构骨架7.1 请求的完整流转把前面几块拼起来一次用户请求的流转是这样的用户发消息带上身份凭证鉴权层验证身份确定用户权限记忆层检索该用户的相关长期记忆RAG层检索知识库重排后取top片段组装上下文系统提示 记忆 检索结果 最近对话调用大模型模型可能返回工具调用请求工具调用前做鉴权通过后执行MCP工具工具结果回填上下文再次调用模型生成最终回复全程写审计日志更新短期记忆必要时抽取长期记忆这个流程里鉴权和审计是横切的贯穿每一步。任何一步都要能回答谁在做、有没有权限、做了什么。7.2 技术选型的取舍选型上没有银弹看你的团队和场景。几个常见组合轻量起步LangChain/LlamaIndex 向量库如Chroma 自建MCP Server。上手快适合验证。中等规模LangGraph做编排 专业向量库如Milvus/Qdrant 独立MCP服务。可控性和扩展性更好。大规模自研编排层 分布式向量库 服务化MCP 独立鉴权审计服务。灵活但成本高。我的建议是从轻量起步但把鉴权和审计的接口预留好。这两块后期补的代价很大一开始就设计好边界后面替换实现就行。7.3 上线前必须过的检查项上线前对照这份清单过一遍能避开大部分坑检索命中率是否达标用真实问题测别只用构造的问题记忆是否会串用户多用户并发测试工具鉴权是否在服务端强制执行尝试绕过前端直接调审计日志是否完整随机抽几次调用看能否还原全流程凭证是否脱敏检查日志和错误信息超时和降级是否处理模拟工具超时、模型超时上下文超长是否处理构造超长输入看是否优雅降级这份清单里的每一项我都见过因为没做而翻车的案例。尤其是工具鉴权和审计出问题就是安全事故。8. 几个我踩过的坑和对应的解法8.1 上下文窗口被撑爆的连锁反应有一次线上突然大量报错提示上下文超长。排查发现是某个工具返回了超大JSON加上检索片段和记忆直接把窗口撑爆。模型调用失败用户看到的是莫名其妙的错误。解法是在每一层都做长度控制工具返回裁剪到关键字段检索片段限制总长度记忆只取top几条。同时加一个总长度检查组装完上下文后算一下token数超了就按优先级裁剪先裁记忆再裁检索最后裁历史。这样即使某层失控也不会直接崩。8.2 记忆串用户的惊魂一刻测试环境一切正常上线后有个用户反馈看到了别人的信息。查下来是记忆检索时忘了加用户ID过滤向量检索把别人的记忆也召回了。幸好发现得早没有造成大范围影响。这个坑的教训是凡是涉及用户数据的检索必须强制加用户ID过滤而且要在数据访问层做不能靠调用方记得传。我后来的做法是把用户ID作为检索函数的必填参数不传直接报错从接口层面杜绝遗漏。8.3 工具重复调用的幂等处理模型有时候会重复调用同一个工具。比如查订单模型可能连续调两次。查询类工具无所谓但写操作就麻烦了。有次测试退款工具模型重复调用导致重复退款虽然测试环境金额小但暴露了问题。解法是给写操作加幂等键。每次工具调用生成一个唯一ID服务端记录已处理的ID重复的ID直接返回上次结果不重复执行。幂等键可以由会话ID加工具名加参数哈希生成保证同一请求重复调用只执行一次。8.4 审计日志写入失败的降级审计日志很重要但如果日志服务挂了不能因此让整个应用不可用。我的做法是审计写入异步化加本地缓冲日志先写本地队列后台异步刷到存储。存储挂了就暂存本地恢复后补写。这样审计不阻塞主流程同时尽量保证不丢日志。但要注意鉴权不能降级。鉴权失败必须拒绝请求不能因为鉴权服务挂了就放行。这是安全底线宁可不可用也不能不安全。9. 后续可以继续深化的方向这套骨架跑通之后还有不少可以深化的地方。GraphRAG可以处理需要多跳推理的问题把知识图谱和向量检索结合适合关系复杂的知识库。Agentic RAG让模型自己决定检索策略什么时候检索、检索几轮、要不要换查询词适合问题类型多变的场景。多模态把图片、表格也纳入检索适合文档类型丰富的知识库。但我的建议是不要一上来就追新。把基础的RAG、记忆、鉴权、审计做扎实比堆一堆花哨功能更有价值。我见过太多应用功能列表很长但基础体验一塌糊涂用户用两次就跑了。先把核心链路做稳再考虑锦上添花。最后分享一个我自己的体会这类应用的质量八成取决于工程细节两成取决于模型能力。模型再强检索不准、记忆串号、权限裸奔应用就是不可用。反过来模型一般但工程扎实应用反而稳定可靠。所以别把精力全花在换模型上多花点时间打磨检索、记忆、鉴权、审计这些不性感但决定成败的环节。
返回列表