Simon Willison最近让Claude Code异步跑了一个不算大的实验:装上最新的Datasette alpha、datasette-agent和斯坦福团队的DSPy框架,去审一遍自己写的Datasette Agent系统提示词——那段专门管“只读SQL问答”的核心prompt。

结果这次审计没白跑。执行任务的Fable(Claude Code的一个工作模式)用GPT-4.1 mini和nano做测试,抓到一个很具体的毛病:提示词里的schema列表只给了表名,没给列名;同一段提示词又叮嘱模型“如果已经有信息了就别重复调用describe_table”。两条指令撞在一起,模型在信息不全的情况下被要求少查工具,只能自己猜列名——page_count、o.order_id、first_name,猜错了就报错,报错就重试,陷入一个原本不该存在的循环。

一条省token的指令,怎么把AI逼成了编故事

这个bug有意思的地方不在于它多严重,而在于它太典型。几乎所有text-to-SQL agent的提示词里都会有一句类似“别做多余的工具调用”——这是为了省成本、省延迟,出发点没错。但前提是模型手里的信息必须足够完整。一旦schema信息本身有缺口,这句“节省”指令就变成了一道命令:宁可编,也别再查。

  • 风险.省token指令和信息完整性之间存在系统性张力,稍不注意就会把“别多问”教成“别核实”。
指令冲突:省token如何变成瞎猜列名 schema只给 表名,无列名 提示词要求 别重复查工具 模型瞎猜列名 page_count / order_id 报错→重试循环 本可一次问对

Fable给的修复方向很朴素:要么在schema里补上列名,要么把“别重复查”那句话说得没那么绝对。技术含量不高,但抓得准——这类bug往往不是模型能力问题,是提示词自己写自相矛盾了。

DSPy在这里到底做了什么

DSPy的思路和人工调prompt不是一回事。人工调prompt靠试错和直觉,改一句话跑一遍看效果,全凭经验判断哪里不对。DSPy把prompt当成可优化的参数,先定义一个pipeline和一个metric(这次用的是一套自动生成的“标准答案”数据集),再用优化器在真实的工具调用轨迹里跑,量化出哪条指令在哪种输入下最容易翻车。

这次实验的特别之处,是审计者本身也是个AI agent——Claude Code去自动跑DSPy,评估另一个产品Datasette Agent的提示词。相当于用一个agent的执行能力,去给另一个agent的“说明书”挑错。这不是研究突破,更像是一次成本很低的自动化质检:以前人工反复试错才能摸出来的坑,现在丢给评估流水线跑一轮就能定位。

省流指令和信息完整性之间的张力,是text-to-SQL agent的通病,不是Datasette一家的毛病

这个发现能信到什么程度

得说清楚这次实验的分量。它是Simon Willison个人发起的一次异步任务,单人单次运行,没有同行评审,也没有系统性基准测试。测试模型选的是GPT-4.1 mini和nano——便宜、小、方便跑批量测试,但不是Datasette Agent生产环境里实际会用的更大模型。mini/nano上暴露的“瞎猜列名”问题,换成更强的模型是否依然存在,原文没有验证,只能存疑。

  • 结论.这类问题在小模型上更容易被放大,但指令冲突本身不会因为换大模型而消失,只是出错概率可能降低。

对使用Datasette Agent做数据问答的用户来说,眼下最实际的动作是等:Simon Willison是否会真的把这条建议合并进正式提示词,目前还看不清。对更广泛在做text-to-SQL或数据库问答agent的团队,这个案例更值得直接抄一遍思路——去检查自己的schema描述和“别重复调用工具”类指令是不是也埋着同样的坑,用eval去测,而不是靠感觉判断模型“应该不会瞎编”。