当长对话导致上下文漂移和隐藏错误
I’m happy to translate the article for you, but I need the full text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source line, formatting, and any code blocks exactly as you specify.
为什么长线程看起来一致却暗中漂移
我在与模型一起进行一次重构时,保持同一个聊天窗口打开了一周。起初,模型的建议符合我的风格:小函数、描述性的命名、单元测试草案。到了周中,它开始推荐我从未使用过的模式。并不是明显错误——只是微妙地不同。模型仍然用相同的语气回复,但它的注意力已经迁移到线程中更近的示例上。最近的 token 占主导。最初引导提示的思维状态逐渐变薄。
这种漂移并不是剧烈的切换,而是缓慢的潜移。比如我会询问数据库迁移,得到的答案却假设使用了不同的 ORM。我接受了代码的形态,随后才意识到某个调用签名根本不存在。到那时,已经有好几处本地更改依赖于错误的假设。
小的隐藏假设会变成 bug
一个具体例子:我让模型帮助把一组 SQL 更新转换为批量事务。在一段很长的对话中,它开始假设自动提交(autocommit)已关闭。它生成的代码在一个分支里省略了显式的 commit。由于开发环境的数据库驱动行为与生产环境不同,本地测试通过了。这个不匹配导致了生产环境的静默失败。我没有询问提交语义,因为我以为模型记得我们之前关于数据库的说明。结果它并没有可靠地记住。
另一次,它建议了一个与旧版库匹配的配置标志名称。重构时把这些建议链式写进了迁移脚本。脚本在预发布环境运行时,写入了错误的 S3 前缀。每个错误单独看都很合理,合在一起却导致了面向用户的宕机。
工具调用失败,模型填补空白
我们将模型连接到工具:代码检查器、测试运行器、包管理器、小型 shell。这增加了失败的可能性。我曾看到编排器返回了一个测试摘要的部分 JSON,模型却继续运行,好像缺失的字段仍然存在。输出看起来很连贯。它还因为工具输出格式错误而忽略了一个失败的作业。在日志中唯一的线索是一条不一致的校验和以及随后一次撤销预期行为的更改。
这让我学会把工具输出视为不可信的输入。我们现在记录原始工具响应,而不仅仅是模型的摘要。当响应被截断或缺少必需字段时,我们会中止并将原始负载呈现给人工。然后可以让模型使用完整数据重新处理。这会强制硬性停止,而不是让模型在看不见的假设下继续。
我设置的实用防护措施
我添加了三条小规则,这些规则比任何提示微调都更能减少这些潜在错误。
-
拆分研究和代码线程。
我把深入探索移到一个单独的工作区,这样编码线程保持简短且指令明确。对于探索,我们使用专注的研究流程,将引用和原始输出放在同一个地方;当我需要核实来源时,我会把这项工作推到研究会话,而不是实时重构会话,并使用共享工作区进行比较。 -
每隔几轮重置或快照上下文。
如果一个线程的编辑次数超过半打,我们会对当前状态进行快照,然后启动一个全新的提示,明确列出假设。 -
对模型输出执行模式检查。
若模型声称某个函数签名或依赖名称, 小型验证器会在应用更改前将其与仓库进行比对。快速失败,记录所有内容。
这些并不光鲜亮丽,但能阻止一连串的小错误。
何时记录、何时重置以及何时要求提供证据
日志记录比巧妙的提示更重要。我保留一份纯文本时间线,记录模型建议、工具输出和人工批准。该时间线使得重建生产事故并查看假设首次出现的地方变得容易。当在预演环境中出现异常时,我会重放导致变更的精确模型输入。可复现性是发现漂移的方式。
重置上下文的成本远低于调试级联。如果会话中混杂了不同的风格或多个研究分支,启动一个新聊天,重新陈述约束,并仅粘贴已验证的代码片段。当模型引用版本、测试或变更日志时,要求提供来源,并在可能的情况下强制使用工具获取权威文件。我们为此类取源使用单独的渠道,以免主线程累积噪音。我仍然信任模型进行草稿,但不再信任它记住每个隐藏的假设。