ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

大模型应用从Demo到上线:RAG、记忆、API、MCP与鉴权审计全链路实战

大模型应用从Demo到上线:RAG、记忆、API、MCP与鉴权审计全链路实战 1. 从能跑通到敢上线这套应用到底在解决什么问题大模型应用最尴尬的阶段不是跑不通而是能演示但不敢上线。你在本地用几十行代码接上模型问答流畅、效果惊艳可一旦要交给真实用户使用问题就全冒出来了用户问了三轮之后模型忘了前面说过什么知识库里的文档更新了但回答还是老一套接口裸奔没有任何身份校验谁调用了什么、花了多少 token、返回了什么内容一概查不到。这套大模型上下文与工具链搭建要解决的正是从 demo 到可用系统之间那段最脏最累的工程活。我把它拆成四块核心能力来理解RAG负责让模型知道外部知识记忆负责让模型记住对话历史API负责把能力暴露成可调用的服务MCP负责让模型能动手操作工具。而鉴权审计是贯穿这四块的一条安全底线——没有它前面四块做得再漂亮也只是个玩具。这四块加一条底线构成了一个能真正交付给团队内部或客户使用的大模型应用骨架。这篇文章适合谁看如果你已经会用 LangChain 或类似框架跑通一个最简单的 RAG 问答但不知道下一步该怎么把它做成一个有身份、有记忆、有工具、有日志的完整系统那这篇就是写给你的。我会按实际搭建顺序把每一块的选型理由、关键参数、踩过的坑都摊开讲。需要说明的是文中涉及的具体参数和步骤一部分来自我自己的实践一部分是基于常见工程实践做的合理补全你落地时按自己的环境调整即可。先给一个整体架构的直觉用户请求进来先过鉴权层你是谁、有没有权限再进上下文编排层RAG 检索 记忆召回拼成最终 prompt然后交给模型模型如果需要调工具就走MCP通道最后所有环节的关键动作写入审计日志。这个链路听起来简单但每一环都有它自己的坑下面逐个拆。2. RAG 不是接个向量库就完事检索质量才是命门2.1 为什么很多人搭的 RAG 效果很差我见过太多人搭 RAG 的流程是这样的把文档切块、丢进向量库、用户提问时检索 top-k、拼进 prompt。跑起来确实能答但稍微问得刁钻一点就开始胡说。问题几乎从来不在模型而在检索环节。检索没把对的片段捞出来模型再强也只能基于错误上下文编答案。RAG 的本质是先找对资料再让模型读资料答题。找资料这一步做不好后面全白搭。所以搭建 RAG 时我建议你把 70% 的精力花在检索质量上而不是纠结用哪个模型。检索质量取决于三件事切块策略、向量模型选择、召回后的重排。2.2 切块策略固定长度是最省事也最容易翻车的做法固定长度切块比如每 500 字一刀最大的问题是会把一个完整的语义单元拦腰截断。比如一份产品说明里退款政策分三段固定切块可能把第二段切到下一个 chunk 里检索时只捞到第一段模型就答不全。我的做法是按结构切块 适度重叠。如果文档有明确的标题层级Markdown、HTML就按标题切如果是纯文本就按段落切段落太长再按句子边界切。每个 chunk 之间保留 10% 到 15% 的重叠防止边界信息丢失。chunk 大小我一般控制在 300 到 800 字之间——太短语义不完整太长检索精度下降且浪费 token。提示chunk 大小没有万能值它和你的文档类型强相关。技术文档可以小一点300-500 字叙述性内容可以大一点600-800 字。上线前一定要用真实问题测一遍召回率。2.3 向量模型与重排两段式召回比单段靠谱得多向量模型的选择上中文场景我一般优先考虑在中文语料上表现好的模型而不是盲目追大参数。向量模型不是越大越好它和你的语料领域匹配才是关键。如果你的知识库是垂直领域比如医疗、法律通用向量模型往往力不从心这时候要么换领域模型要么加一层关键词召回做混合检索。这里我要重点讲重排Rerank。很多人的 RAG 只做了一次向量召回就完事这是效果差的主因之一。正确做法是两段式第一段用向量检索快速召回 top-20 到 top-50 的候选第二段用重排模型对这几十个候选精排取 top-3 到 top-5 喂给大模型。重排模型比向量模型慢但只处理几十条成本可控而精度提升非常明显。环节常用方案作用我的建议粗召回向量检索从海量 chunk 中快速筛出候选top-20 到 top-50宁多勿少精排重排模型对候选按相关性重新排序必做取 top-3 到 top-5兜底关键词检索补充向量检索漏掉的字面匹配垂直领域强烈建议加2.4 一个容易被忽略的坑知识库更新与失效RAG 上线后最常被投诉的问题是我明明更新了文档它还在按旧的答。这是因为向量库里的旧 chunk 没被删掉。所以你的 RAG 必须有一套文档版本管理机制文档更新时先按文档 ID 删除旧的所有 chunk再重新切块入库。千万别只做追加否则新旧内容会同时被检索到模型直接精神分裂。另外检索时最好带上时间衰减的考量。如果同一个问题有新旧两个版本的答案优先返回新的。这个可以在重排阶段加一个时间权重或者干脆在元数据里标记版本检索时过滤掉过期版本。3. 记忆系统让模型记住我们聊过什么3.1 短期记忆和长期记忆别混为一谈大模型的记忆这个词被用得很乱。我把它分成两类短期记忆是当前这轮对话的上下文长期记忆是跨会话、跨时间沉淀下来的信息。这两者的实现方式完全不同混在一起做必然出问题。短期记忆就是对话历史。最朴素的做法是把所有历史消息都塞进 prompt但很快你就会撞上上下文长度上限——热词里那个maximum context length is 1048576 tokens的报错就是上下文塞爆的典型症状。所以短期记忆必须做窗口管理只保留最近 N 轮对话或者当 token 超过阈值时把更早的对话做摘要压缩。长期记忆则是另一回事。它要解决的是用户上周说过他偏好简洁回答这周再来时模型还记得。长期记忆通常需要落库存储按用户 ID 或会话 ID 索引每次新会话开始时召回相关记忆注入 prompt。3.2 记忆的打分 时间半衰期思路热词里有个说法我觉得很到位记忆 score 时间半衰期。意思是每条记忆都有一个重要性分数同时随着时间推移它的权重会衰减。这样设计的好处是重要的记忆比如用户的核心偏好能长期保留而琐碎的临时信息比如帮我查下天气会自然淡出。具体实现上每条记忆存一个importance分数和一个last_access_time。召回时计算一个综合分final_score importance * decay_factor decay_factor 0.5 ** (elapsed_days / half_life_days)half_life_days就是半衰期比如设成 7 天意味着 7 天后这条记忆的权重减半。这个公式简单但有效比单纯按时间排序或者按重要性排序都更符合直觉。3.3 记忆写入的时机不是每句话都值得记新手常犯的错是把用户说的每句话都存成记忆结果记忆库迅速膨胀召回时全是噪音。我的经验是只记三类信息用户的稳定偏好我喜欢用表格、重要事实我的项目用的是 Python、明确的指令以后回答别超过三句话。判断标准是这条信息在下次对话时还有用吗如果答案是否定的就别存。写入时机上我一般不在对话过程中实时写而是在一轮对话结束后用一个轻量的模型调用做一次记忆抽取把值得记的内容结构化后入库。这样既避免了频繁写库也保证了记忆的质量。3.4 跨设备记忆同步的现实难题热词里有人问一台电脑上的记忆配置怎么用到另一台电脑上这其实点出了记忆系统的一个工程现实记忆必须存在服务端而不是本地。如果你的记忆存在本地文件里换台机器就丢了。正确做法是记忆统一存数据库哪怕是 SQLite 也行客户端只负责发送用户标识服务端按标识召回。这样无论用户从哪台设备来记忆都是一致的。4. API 层把能力封装成别人敢调的服务4.1 为什么不能直接把模型调用暴露出去很多人图省事前端直接调模型 API。这在内部玩玩可以一旦要给多人用就是灾难API Key 暴露在前端等于公开任何人都能盗用你的额度没有限流一个人写个循环就能把你的账单打爆没有日志出了问题根本不知道是谁在什么时候调了什么。所以 API 层的第一职责是隔离前端只跟你的后端说话后端拿着真正的模型 Key 去调模型。这样 Key 永远不出服务端同时你获得了限流、鉴权、日志的全部控制权。4.2 接口设计把 RAG、记忆、工具统一成一个入口我建议对外只暴露一个对话接口把 RAG 检索、记忆召回、工具调用这些复杂逻辑全部藏在后端。前端只需要传user_id、session_id、message三个核心字段后端返回模型回复。这样做的好处是前端极简而且以后你换向量库、换模型、加工具前端完全不用改。接口内部的处理顺序我一般是这样的校验user_id和 token确认身份和权限按session_id召回短期记忆对话历史按user_id召回长期记忆用message做 RAG 检索拿到相关文档片段把记忆 检索结果 当前问题拼成 prompt调用模型如果模型要求调工具则走 MCP把本轮对话写入短期记忆抽取长期记忆记录审计日志这个顺序不是随便定的。记忆召回必须在 RAG 之前因为记忆可能影响检索策略审计日志必须最后写因为它要记录完整的处理结果。4.3 错误处理401 和 400 背后藏着什么热词里高频出现的两个报错很值得说。401 unauthorized: incorrect api key基本就是 Key 配错了或者过期了排查时先确认环境变量有没有正确加载再确认 Key 有没有多余空格。400 maximum context length则是上下文超限说明你的记忆窗口或者 RAG 召回量太大需要做截断或摘要。我的经验是API 层一定要做统一的错误封装。不要把模型返回的原始错误直接透给前端而是转成你自己的错误码和友好提示。同时把原始错误写进审计日志方便排查。这样用户看到的是服务暂时繁忙而你看到的是完整的堆栈。注意模型 API 的 Key 一定要放在服务端环境变量里绝对不要硬编码进代码更不要提交到代码仓库。这是最基础也最容易被忽视的安全红线。5. MCP让模型从会说变成会做5.1 MCP 到底解决什么问题MCPModel Context Protocol本质上是一套标准化的工具调用协议。在它出现之前每接一个工具比如查数据库、调浏览器、读文件你都要为这个工具写一套专门的适配代码工具一多就乱成一锅粥。MCP 的价值在于把模型怎么调用工具这件事标准化了工具方按 MCP 协议暴露自己的能力模型方按 MCP 协议去发现和调用双方解耦。打个比方MCP 就像 USB 接口。以前每个设备都有自己的接口现在统一成 USB插上就能用。模型不需要知道工具内部怎么实现只需要知道这个工具叫什么、需要什么参数、返回什么。5.2 MCP 和普通 API 的区别在哪很多人会问MCP 和普通 API 有啥区别不都是调用吗区别在于发现机制和上下文注入。普通 API 你得提前知道接口地址和参数格式写死在代码里。MCP 是动态的模型可以在运行时查询现在有哪些工具可用每个工具会自带描述和参数 schema模型据此决定调不调、怎么调。这让模型具备了自主选择工具的能力而不是被动执行预设流程。热词里提到的 Playwright MCP、浏览器操作类 MCP就是典型的例子模型可以自主决定我需要打开一个网页看看然后调用浏览器工具拿到结果后继续推理。这种能力在自动化测试、信息采集等场景里非常实用。5.3 接入 MCP 的实操要点接入 MCP 时我踩过的坑主要有这几个。第一是工具描述要写清楚模型是靠描述来决定用不用这个工具的描述含糊模型就不会调或者乱调。第二是参数校验要做在服务端不能信任模型传来的参数该校验类型校验类型该限制范围限制范围。第三是工具调用要有超时和熔断某个工具挂了不能把整个对话卡死。还有一个容易被忽略的点工具调用的结果也要进审计日志。模型调了什么工具、传了什么参数、拿到什么结果这些都必须记录。一方面是为了排查问题另一方面是安全审计的需要——万一模型被诱导调用了不该调的工具日志就是证据。6. 鉴权与审计那条不能省的安全底线6.1 鉴权先回答你是谁鉴权解决的是身份问题。最基础的是 API Key 或 Token 机制每个用户或每个应用分配一个凭证请求时带上服务端校验。再往上可以做基于角色的权限控制RBAC比如普通用户只能问答管理员才能管理知识库。我建议至少做到用户级隔离每个用户只能访问自己的会话和记忆不能串。这个在数据库层面就要设计好所有查询都带上user_id过滤条件。别小看这一点很多事故就是因为查询忘了加用户过滤导致 A 用户看到了 B 用户的数据。6.2 审计再回答你干了什么审计解决的是追溯问题。一个完整的审计日志应该记录谁user_id、什么时候timestamp、从哪来IP 或来源标识、做了什么调用了哪个接口、触发了哪些工具、结果如何成功/失败、返回摘要、消耗多少token 数、耗时。审计日志的写入要和主流程解耦。我的做法是主流程把日志事件丢进一个队列由独立的消费者异步写库。这样即使日志系统出问题也不会拖慢主流程。但要注意关键的安全事件比如鉴权失败、权限越界必须同步记录不能异步否则可能丢。6.3 审计日志的存储与查询审计日志量会很大别用主业务库存。我一般单独用一个库或者一张表按时间分区。查询时按user_id和时间范围过滤。如果日志量特别大可以考虑冷热分离最近 7 天的热数据放快速存储更早的归档。提示审计日志本身也是敏感数据里面可能包含用户对话内容。存储时要考虑加密访问时要严格控制权限。别为了审计反而制造了新的泄露点。7. 把四块拼起来一次完整请求的生命周期前面把 RAG、记忆、API、MCP、鉴权审计分开讲了现在把它们串起来看一次完整请求是怎么走的这样你能更清楚各模块的边界。用户在前端输入一个问题前端带上 token 和 session_id 发给后端。后端第一件事是鉴权校验 token 有效性解析出 user_id。鉴权失败直接返回 401同时记一条审计日志。鉴权通过后后端并行做两件事召回该 session 的短期记忆最近几轮对话召回该 user 的长期记忆按打分和时间半衰期排序取 top-N。接着用用户问题做 RAG 检索粗召回一批候选重排后取 top 几条。然后把长期记忆、短期记忆、检索结果、当前问题按模板拼成最终 prompt。这里要注意 token 预算给记忆和检索结果分配的总 token 不能超过模型上下文的一定比例我一般留 50% 给模型输出和系统提示超了就截断或摘要。拼好 prompt 后调用模型。如果模型返回的是工具调用请求就走 MCP 通道执行工具把结果回填给模型继续推理直到模型给出最终回答。最后把本轮问答写入短期记忆异步抽取长期记忆写审计日志返回结果给前端。这个链路里任何一环失败都要有降级方案。RAG 检索失败就退化成纯模型回答记忆召回失败就当没有记忆工具调用失败就告诉模型工具不可用。系统不能因为一个非核心环节挂了就整个不可用。8. 上线前我必做的几项检查搭完这套系统别急着上线。我每次上线前都会过一遍这几项检查能挡掉大部分事故。第一压测上下文边界。故意构造一个超长对话看系统是优雅截断还是直接报 400。第二测鉴权绕过。用无效 token、过期 token、别人的 token 分别请求确认都被正确拒绝。第三测工具调用的异常路径。把某个工具故意关掉看模型是否能优雅处理工具不可用。第四检查审计日志完整性。随便走几个流程看日志里是不是每个关键动作都有记录有没有漏。还有一个我特别想强调的给模型输出加一层内容过滤。模型可能会输出不该输出的内容尤其是当 RAG 检索到的文档里包含敏感信息时。上线前一定要在输出环节加一道过滤把明显不合适的回答拦下来。这道过滤宁可误杀不可放过。最后分享一个我自己的体会这套系统里最难的从来不是某个单点技术而是各模块之间的边界和降级。RAG、记忆、MCP 单独拿出来都不算特别难难的是它们同时工作时谁先谁后、谁失败了怎么办、token 预算怎么分。我建议你在设计阶段就把这些边界画清楚别等到线上出问题再补那时候改起来成本高得多。
返回列表