大模型实战:从零实现rag与agent系统

接入与开发

给开发者一份从零搭 RAG+Agent 系统的工程落地清单:目录怎么分、超时并发怎么设、降级与日志怎么记、上线前拿什么评测。

你可能已经跑通了单轮检索问答,也调通了工具调用,但把两者拼成一个能上线的系统时就开始卡:检索结果塞不进上下文、Agent 循环偶尔不收敛、接口一超时就整条链路挂掉、出了问题翻日志也看不出是哪一步慢。这篇不讲协议兼容和框架原理,只给从零搭建时的目录结构、参数清单、降级顺序和评测办法,让你能一步步落地并知道哪一步不适用。

很多人已经跑通过单轮检索问答,也单独调通过工具调用,但把两者拼成一个能上线的系统时就卡住了:检索回来的片段塞不进上下文、Agent 的循环偶尔不收口、接口一超时整条链路就挂、出问题翻日志看不出慢在哪一步。这篇不讲协议兼容和框架原理,只给从零搭建时的目录分层、参数口径、降级顺序和评测办法。

阅读方式建议按顺序走:先定骨架再调参数,然后想清楚坏了先砍哪一步,最后补日志和评测。如果你的场景没有自有资料、或者必须逐条人工复核,下面有些做法并不适用,最后一节会说明边界。

先定骨架:一次请求要经过哪几层

把一次请求拆成入口层、编排层、检索层、模型层、工具层五段,每段只干一件事。这样做的价值不在于架构好看,而是排错时能快速定位是哪一段的锅,替换实现时也不用动其他层。

入口层
做鉴权、限流、请求 id 生成,不碰业务逻辑
编排层
决定这一轮是检索还是调工具,管循环和收口
检索层
输入查询、输出带来源标记的片段
模型层
统一封装调用、重试、模型选择
工具层
外部函数的注册、参数校验与超时
  • 检索和工具做成统一接口:输入是查询或参数,输出是带来源标记的片段,Agent 决定查库还是调函数时走同一套流程
  • 会话状态单独放一层,不要在检索函数里顺手改历史,否则并发时同一会话会互相踩
  • 小团队不必一上来就上向量库集群,先用文件加索引把链路跑通,量上来再换方案,具体选型去 /stacks/vector-dbs 对照
  • 编排层别写死顺序,把「先检索还是先调工具」做成可配置项,方便后续按场景切换
层只负责什么不该做什么
入口层鉴权限流、生成请求 id拼 prompt
编排层循环控制、决定下一步动作直接发 HTTP 请求
检索层召回并打分片段改会话历史
模型层调用与重试判断业务是否成功
工具层参数校验、真实执行替模型写结论

参数怎么定:超时、并发、检索条数

超时分三档:连接超时、单次模型调用超时、整条请求超时。整条请求的超时要明显大于前面各档之和,否则前面的设置形同虚设,整条链路仍然会在中途被掐断。

  1. 先量延迟基线用固定的几组问题跑一遍,记录每段耗时。到 /tools/speed-test 量自己的延迟基线,别拿别人的数字套自己环境。
  2. 再定检索条数检索条数先设小再往上调。召回太多会挤掉对话历史,还拖慢首字时间,收益经常是负的。
  3. 最后定循环上限Agent 循环设步数上限加工具白名单,到点强制收口输出当前结论,不要让它自己判断该不该停。

判断标准很简单:如果加并发之后错误率明显上升而总吞吐没涨,说明瓶颈在上游限速而不是你的编排逻辑,这时候该做的是排队和退避策略,而不是继续加线程。

降级顺序:哪一步坏了先砍哪一步

降级要有固定顺序,推荐先降检索条数,再关掉非必要工具,再换更便宜的模型,最后才是返回兜底话术。一上来就整条失败,用户体验和排错成本都更差。

  • 检索超时不要直接让模型硬答,改成返回检索暂不可用并保留追问入口,能避免编造来源
  • 模型失败要区分可重试和不可重试:网络类可退避重试,参数类重试多次也没用,只会放大限流
  • 多模型路由的降级链只留两级,链太长时单次请求耗时和排错成本都会翻倍
  • 每级降级都要打点,否则你根本不知道线上到底经常降在哪一级

哪些模型能互相顶班,不是看名字像不像,要看能力对照和是否支持同样的输入形态,去 /models 看能力对照再定。另外,降级策略本身也要测:手动把检索层关掉跑一遍,看链路是不是按预期给出可用的兜底回答。

日志和评测:上线后靠什么定位问题

日志不是记全就行,关键是能回答慢在哪、错在哪、答错是检索偏了还是模型偏了。所以字段要围绕这三点设计。

记什么用来回答什么常见漏记点
请求 id把一次请求的所有日志串起来只在入口生成,没往下传
检索命中条数与片段 id检索层是否召回对了只记条数不记 id
工具调用序列Agent 走了哪条路径不记参数和返回值
各段耗时慢在哪一步只有总耗时
最终模型名是不是被降级换过降级换模型后仍记原模型
  1. 攒失败样本把失败样本单独存一份,不要混在通用日志里,攒够一批再回放,比对着线上日志逐条猜快得多。
  2. 固定回归集上线前准备一组固定问题,改检索策略或换模型后重跑,看哪些问题从能答变成答错。
  3. 看引用对不对别只看答得像不像,还要看有没有引用到正确片段,引用错了说明问题出在检索层而不是模型层。

什么情况下这套做法不适用

上面这套偏向有自有资料、要求可控可排查的场景。碰到下面几类情况,需要先调整前提,否则按这套搭出来只会越跑越累。

  • 资料更新极频繁、要求秒级一致的场景,先解决数据同步再谈检索,不然检索层永远在给过期内容做补救
  • 对答案有强合规要求、必须逐条人工复核的场景,Agent 自动收口就不合适,要留人工确认环节
  • 纯闲聊或没有自有资料的场景,检索层是纯负担,直接调模型更省事也更省成本
  • 请求量很小、单次延迟不敏感的内部工具,过度设计降级和日志体系收益有限,可以先简化
下一步把上面的层和参数落成一份自己的清单,然后去站内核对当时的价格与速度数字,再决定用哪个模型和检索方案,避免照搬别人环境里的结论。

常见问题

RAG 和 Agent 一定要一起上吗?先做哪个?

不一定。如果你的问题都是「查资料再回答」,先把检索做稳就够用;只有当需要模型自己决定查几次、要不要换工具时再引入 Agent。建议顺序是先跑通检索链路并用固定问题集验证,再加工具调用和循环控制,否则出问题时你分不清是检索差还是编排乱。

上线后回答变慢,一般先查哪一段?

按耗时占比从大到小排:先看检索层是不是召回条数被调大了,再看模型调用是不是换到了更慢的一档,最后看 Agent 是不是多跑了几轮循环。这三段加起来占了绝大部分延迟,逐段打点记耗时比整体计时有用得多。

检索结果和模型回答对不上,怎么定位?

先把该次请求命中的片段原文和最终回答一起打出来做对照。如果片段里根本没有答案,是检索层的问题;如果片段里有但回答没引用,是拼装或提示词层面的问题。分清楚这两类再改,能省掉大量来回试错。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。