从请求日志重放一次线上调用:在一把 key 上还原提示词、参数与后端
本文演示如何从 LLM API 聚合站的请求日志中,完整还原一次线上调用的提示词、采样参数与实际命中的后端模型,并用同一把 API key 忠实重放请求以复现问题。内容涵盖日志字段解读、参数对齐、后端漂移排查与复现清单,强调可复现性优先于猜测。
为什么需要重放而不是猜
线上出现一次异常输出时,最容易犯的错是凭印象重写一版提示词去试。模型对措辞、系统提示词、temperature、max_tokens 顺序都敏感,重写的请求已经不是你线上跑的那次调用了,结果无论好坏都不说明问题。
聚合站的价值在这里很直接:它记录了每次请求的入参与实际路由到的后端,你可以把一次调用原样搬回来。前提是你会读日志。
日志里通常有哪些字段
一条请求日志一般包含两部分:客户端可见的部分,以及路由层附加的部分。
- 请求标识:请求 ID、时间戳、所属 API key(确认是不是同一把 key 发出的)
- 模型标识:你请求时写的模型名,以及实际路由到的后端
- 消息体:system / user / assistant 各条消息的原文与顺序
- 采样参数:temperature、topp、maxtokens、stop、seed(若支持)等
- 返回:状态码、耗时、token 用量、错误信息(若有)
关键点在于「你请求的模型名」和「实际后端」可能是两个字段。聚合站会把一个模型别名分发到具体后端,所以复现时要把两者都记下来。
第一步:锁定这条日志的身份
先确认三件事再动手:
- 这条请求是用哪把 key 发出的。聚合站支持一把 key 调多个模型,不同 key 可能有不同的可见范围或路由策略,用错 key 重放可能落到别的后端。
- 时间戳是否落在后端配置变更的窗口内。如果异常正好出现在某个时间点附近,先怀疑路由变化再怀疑提示词。
- 请求 ID 是否可检索。有 ID 就能把日志、返回和你本地记录对齐。
第二步:逐字段还原请求体
按日志顺序重建 JSON,不要凭记忆补全:
- 消息数组:system 提示词单独一条,注意前后空白与换行。日志里如果做了截断,需要回到完整记录取原文。
- 参数:把 temperature、topp、maxtokens、stop 等照抄。没有记录的参数不要自己加默认值,保持请求体最小化。
- 工具/函数定义:如果原请求带了 tools,一并还原,否则模型行为可能不同。
一个实用的判断:如果你的重放请求比原请求「更完整」,就已经不是重放了。宁可少写,也不要多写。
第三步:对齐后端
确认日志里的实际后端,然后决定怎么发:
- 如果聚合站允许显式指定后端或使用与当时一致的模型别名,就直接用当时生效的名字发。
- 如果想验证「是不是后端换了导致异常」,可以做两组重放:一组用当前别名(走现在的路由),一组显式指向日志记录的原后端。两组输出的差异就是路由层的贡献。
这一步能区分两类问题:提示词/参数造成的,和后端切换造成的。很多人把后者误判成前者,于是反复改提示词。
第四步:控制复现的变量
重放时尽量只变一个东西:
- 用同一把 key,避免配额或权限差异
- 同一模型别名/后端
- 同一请求体,包括参数顺序(多数实现不敏感,但保持一致没有成本)
- 连续重放多次,观察输出是否稳定。采样参数意味着单次结果不能下结论,看多次的分布。
如果多次重放都稳定复现异常,问题大概率在提示词或参数;如果时有时无,先看采样参数,再看后端是否在多个实例间分流。
第五步:记录复现结论
复现完成后,把结论写回工单或笔记,至少包含:请求 ID、使用的 key(脱敏)、请求模型名、实际后端、完整请求体、重放次数与结果分布。这样下次别人遇到同类现象,不用从零重来。
常见坑
- 只复制了 user 消息,漏掉 system 提示词,导致行为完全不同。
- 日志显示的是截断后的内容,拿去重放等于换了输入。
- 用了另一把 key,落到不同后端,得出「无法复现」的错误结论。
- 把单次输出当作稳定结论,没有考虑采样随机性。
- 忘记记录实际后端,后续排查缺少对照。
小结
重放的核心是把一次调用当作可审计的对象:身份(key + 请求 ID)、输入(消息 + 参数)、路由(实际后端)三样对齐,再控制变量重发。聚合站把这三样都留在日志里,剩下的工作是严谨地照抄,而不是重新创作。