当长聊天偏离时:上下文窗口与 AI 辅助编码中的隐藏错误

发布: (2025年12月26日 GMT+8 17:40)
7 分钟阅读
原文: Dev.to

Source: Dev.to

请提供您希望翻译的正文内容,我将按照要求保留原始链接、格式和代码块,仅翻译文本部分。

上下文窗口并不稳定

我一直把模型当作一个有状态的工程师,记得我在启动时设定的每一个约束。这是个错误。在长达 10 小时的调试对话中,模型逐渐放弃了最初的约束:项目要求使用 Python 3.8 并且是同步代码,但在大约十几轮对话后,它开始返回异步原生的代码片段以及仅在更高版本中有效的类型特性。该行为并非随机。注意力倾向于最近的 token。早期的约束仍然存在于上下文中,但相较于最新的澄清、代码示例和错误信息,它们的信号强度变得很低。

实际上,这导致我合并了一个建议的修复,其中引入了 await,而我们的调用点根本没有使用异步。测试在 CI 中失败。很容易把责任归咎于模型,但真正的问题在于我的工作流程:我让一个冗长的对话不断累积细节,却没有重新强调那些对正确性至关重要的硬性约束。

Small drift cascades into big bugs

一个 Pull Request 最初只包含几项无害的改动。模型先建议使用更短的 SQL 查询,然后是一个模式微调,接着是将字段重命名以匹配查询。每个建议单独看都很合理。我接受了其中的三项。结果在生产环境中全部崩溃——因为有客户依赖于稳定的列名,而新查询的排序语义不同。这样一连串微小的编辑形成了一条脆弱的假设链。

漂移之所以微妙,是因为它常常保持局部一致性。模型会围绕当前上下文进行重写。如果单元测试覆盖了新的局部逻辑,它们仍然会通过。集成测试和下游使用者会在后期才发现真正的破坏。就我而言,一个夜间任务在一周内悄悄产生了错误的聚合数据,直到有人注意到才被发现。

隐含假设潜藏于行间

大多数失败模式都源于模型悄悄使用的隐式默认值。时区、SQL 方言、分页行为以及 API 版本控制不断让我们出错。例如,模型生成了一个没有 ORDER BY 的 SQL LIMIT,而我们副本集群返回的行是非确定性的。看起来像是聚合代码的逻辑错误,但根本原因是模型默认了一个显而易见的 ORDER BY,却没有写出来。

工具集成会让情况更糟。一次工具调用失败返回部分或空数据,模型会用看似合理的内容填补空白,而这些内容随后会变成代码。我见过查询输出因超时被截断,随后模型凭空捏造一个模式继续执行。从外部看这像是幻觉,实际上是工具响应缺少防护措施导致的。

实际捕捉漂移的方法:日志、快照和检查

在经历了足够多的静默失败后,我开始把每一次模型的输出都视为可审计的。我会对提示和响应进行快照,并附加一个简短的上下文哈希。我记录影响建议的最近几条系统和用户消息。这样我就能回答:哪些 token 最近出现并可能影响输出?当某个建议导致测试失败时,我会重新播放准确的提示,以确认漂移。

我还要求在人工审查之前进行机器检查。生成的 JSON 或基于模式的输出会使用严格的解析器进行验证。生成的 SQL 在只读沙箱中执行。如果模型调用外部工具,我会在接受下游更改之前断言响应的形状和非空负载。为了更广泛的验证,我将实验保存在共享的聊天工作区,以便比较不同模型和会话的答案;当需要专注的来源链时,我会将笔记推送到研究流程中,使用专门的来源工具进行交叉核对。

防止意外的运营护栏

具体措施比模糊规则更有效。我开始在逻辑边界处重置对话,而不是仅在我想的时候。对于单个功能,我保留一个简洁的提示,列出不可协商的约束,并在每次交互的顶部加入它。我对模型输出强制使用模式验证器,并在生成的补丁更改公共标识符时快速失败。这帮助我们避免了两次意外的 API 合同更改。

我们还为涉及迁移或下游合同的更改添加了一个低成本的人在环节的门槛。没有模型建议会被合并,直到 CI 运行一套针对性的集成检查。我使用共享环境比较不同的完成结果,因为分歧提供的信息比单一答案更有价值。当工具调用表现不稳定时,我记录失败并将模型输出视为不可信,直到工具错误得到解决。

Back to Blog

相关文章

阅读更多 »