本地 Ollama 跑通一个问答 Demo 不难,难的是把它做成一个 Agent:模型先决定「要不要查、查什么」,再调工具拿片段,拼回上下文生成答案。这一步之后,超时怎么切、并发怎么排、检索挂了怎么降级、一次请求慢在哪贵在哪,全是工程问题。这篇按接入顺序给一份速查清单,帮你把链路拆开、逐段验证,而不是一锅端调试。
本地 Ollama 跑通一个问答 Demo 不难,难的是把它做成一个 Agent:模型先决定「要不要查、查什么」,再调工具拿片段,拼回上下文生成答案。这一步之后,超时怎么切、并发怎么排、检索挂了怎么降级、一次请求慢在哪贵在哪,全是工程问题。
这篇按接入顺序给一份速查清单,帮你把链路拆开、逐段验证,而不是一锅端调试。如果你还没选好要跑哪个模型,先去站内模型资料库核对各家在本地推理上的适用性,再决定用哪个做决策、哪个做生成。
先把链路拆成两段:检索一段、决策一段
拆开之后,每一段都能单独写测试。检索段可以先喂固定查询看召回是否合理,决策段可以先塞死数据看模型有没有按预期选工具。拼起来出问题时,至少知道是哪一段先不对劲。
| 要拆的部分 | 输入 | 输出 | 失败时的表现 |
|---|---|---|---|
| 检索段 | 查询字符串 | 带来源标识的片段列表 | 召回到不相关内容或空结果 |
| 决策段 | 历史对话 + 工具定义 | 工具调用或直接回答 | 该调不调、反复调同一个工具 |
| 拼接层 | 召回片段 + 原始问题 | 最终提示词 | 片段截断位置不合理、来源丢失 |
把检索包成工具,写清调用契约
工具描述该怎么写才不容易误触发
超时、并发与排队:本地推理的节奏控制
| 超时对象 | 设在哪一层 | 判断标准 | 超时后动作 |
|---|---|---|---|
| 单次模型生成 | 推理调用外层 | 超过你设定的生成预算 | 取消该次调用并按策略降级 |
| 单次检索 | 检索函数外层 | 超过召回预算 | 返回空片段并标记检索超时 |
| 整个 Agent 循环 | 请求入口 | 超过总预算仍无最终答案 | 返回已有片段 + 超时提示 |
| 队列等待 | 入队处 | 等待时间超过阈值 | 直接拒绝并提示稍后重试 |
并发数不要拍脑袋。先固定为 1,压测时逐档加,观察单次生成耗时和失败率的变化。什么时候不适用逐步上调:如果机器已经接近内存上限、或者推理耗时波动明显变大,就说明当前并发已经到顶,再加只会让所有请求都变慢。
降级与日志:让一次慢或一次错都能复盘
排查顺序:先看日志,再切链路
- 打标给每个请求生成唯一标识,贯穿检索、生成、返回三段日志。
- 记录关键字段按清单落日志,尤其是是否触发检索、召回条数、各段耗时、最终状态。
- 采样留存按比例保存原始提示词和召回片段,方便离线复现。
- 定期复盘每周抽一批失败或慢请求,看是检索问题、提示词问题还是模型能力问题。
上线前的小评测:先量基线再调
- 固定问题集要包含边界情况:完全无关的问题、需要多个片段才能回答的问题、检索不到答案的问题;
- 每次改动只动一个变量,然后跑全集对比,别一次改提示词又改分块;
- 评测结果只记两件事:工具触发是否符合预期、答案中的关键说法能否在召回片段里找到出处;
- 延迟基线到站内测速页量,把「模型慢」和「检索慢」分开看。
如果你不知道本地模型在你的机器上大概什么水平,先去站内模型资料库对比不同模型在本地推理上的差异,再到测速页量一遍真实延迟。数字会随机器和模型变化,以当时页面上的为准。
下一步把链路拆开、逐段验证之后,你还需要知道自己这台机器上各模型的实际推理速度,以及站内收录的模型在本地部署上的适用性,去这两个页面核对当时的数字,能少走不少弯路。→常见问题
检索结果明明是对的,模型却答非所问,先查哪儿?
先看工具返回值有没有被完整拼进上下文,再看片段是否被截断或顺序打乱。多数情况不是模型不行,而是召回片段太长被裁掉,或来源标识混进正文干扰理解。用固定问题集复现一次,打印实际送进模型的完整提示词就能定位。
本地跑 Agent,超时该设几秒?
没有通用值,取决于你的机器和模型大小。做法是先量:单次生成跑十次取偏上的耗时,检索跑十次取偏上的耗时,整体超时设为两者之和再留一段余量。具体分档思路可以到 /tools/speed-test 测出你自己的基线再定,别照抄别人的数字。
要不要把每次检索都缓存起来?
高频重复问题值得缓存,但要注意缓存命中和真实检索的延迟差很多,统计时如果不打标,你会低估真实瓶颈。做法是给命中缓存的请求单独打标记,评测和日志里分开展示,避免优化方向跑偏。