为什么你用AI编程总拿不到想要的结果?北航研究揭秘:50%问题来自CoT和你自己
现在几乎所有主流的代码生成工具都在用CoT。但问题来了:这些"思考步骤"真的可靠吗?来自北京航空航天大学的研究者们发现,虽然CoT提升了性能,但关于这些中间推理步骤的质量,学术界竟然没有系统性的研究!为此他们分析了1,023个AI生成的代码案例,结果发现竟然有76.4%的"思考链"(Chain of Thought,简称CoT)存在质量问题!这意味着我们一直以为很靠谱的CoT推理过程,可能大部分时候都不太靠谱。
严谨的CoT质量大解剖
研究者们设计了一套相当硬核的评估方法。他们同时使用了三个顶级推理模型:
- Gemini-2.0-Flash-Thinking
- DeepSeek-R1
- OpenAI的o1
让每个模型都在CoderEval和SWE-bench这两个知名代码生成基准上进行测试,总共产生了1,023个CoT-代码对。他们招募了四位有十年以上开发经验的专家,用一种叫"开放式卡片分类法"的方法来分析问题。
简单说,就是把每个失败的代码案例当作一张"卡片",专家们先独立分析每张卡片的问题根源,然后通过讨论达成一致的分类标准,最终Cohen's Kappa一致性达到了82%。这个数字意味着专家们的判断高度一致,基本消除了主观偏差。
研究最终建立了一个完整的CoT质量影响因素分类框架:
从这个分类图可以看出,影响CoT质量的因素被分为外部因素和内部因素两大类。外部因素主要包括实现细节不明确和缺少上下文信息;内部因素则包括误解显式需求、不理解隐含需求和错误规划。
外部因素:需求描述的致命缺陷
分析结果显示,53.6%的CoT质量问题来自外部因素,主要是两大类:上下文信息缺失和实现细节不清楚。让我用具体例子来说明这些问题有多要命。
最糟糕的是缺少关键上下文:
- 任务要求:"返回C优化模块,如果不可用则返回False"
- 问题分析:这个示例的指令看起来很明确,但问题是:哪个C优化模块?AI的思考过程只能写成module_name = 'c_optimizations_module_name'这样的占位符,因为prompt根本没说要检查什么模块。结果就是生成了看起来合理但完全无法运行的代码。研究者们发现,在外部因素中,55.6%是因为这种关键信息缺失,44.4%是因为功能细节描述不够精确。
实现细节模糊的典型案例:
- 任务要求:"移除字符串末尾的路径分隔符"
- 问题分析:看起来很简单对吧?但仔细想想,如果字符串是"/home/user//"(末尾有两个斜杠),AI应该怎么处理?是只移除最后一个斜杠变成"/home/user/",还是移除所有连续的斜杠变成"/home/user"?AI的思考过程显示它选择了用rstrip(os.sep)移除所有连续分隔符,但测试用例期待的却是只移除一个。这种模糊的描述让AI只能猜,而且往往猜错。
内部因素:AI理解能力的真实边界
内部因素占了40.1%。这些问题完全来自AI自身的理解缺陷,即使给它完美的需求描述,它还是会搞错。以下是三种典型的内部因素问题。
误解显式需求的经典案例:
- 任务要求:"将路径片段转换为glob模式,但保持现有模式不变"
- AI的逻辑:检查路径中是否包含通配符(*、?、[),如果有就保持不变,没有就添加"/**"
- 问题分析:听起来很合理,但有个致命问题:测试样本中有个路径"pp:root/somedir"不包含通配符,按AI的逻辑会被转换为"pp:root/somedir/**",但需求明确说这应该保持不变,因为它本身就是一个"现有模式"。AI完全理解错了什么叫"现有模式",仅仅根据有没有通配符来判断。
不理解隐含需求的要命疏漏:
- 任务场景:写配置文件函数,需求明确说"创建所需的包含目录"
- AI的6个步骤:检查文件是否存在→判断是否覆盖→打开文件→写入内容→关闭文件→设置权限
- 致命遗漏:这个问题更严重,占了内部因素的59.7%。AI的思考步骤完全忽略了"创建目录"这一点!看似很完整,但就是没有"创建目录"这一步,结果当然是在目录不存在时直接崩溃。更糟糕的是,AI也没考虑异常处理,比如文件存在时应该抛出FileExistsError而不是默默返回。
错误规划的混乱逻辑:
- 任务要求:"为删除操作添加成功消息混入类"(Django任务)
- 规划冲突:AI制定了一个看似详细的5步计划,但仔细分析发现步骤2和步骤3之间有严重冲突:先说要在admin的delete_selected中集成混入类,然后又说要在通用视图的BaseDeleteView中使用同一个混入类
- 逻辑问题:更离谱的是,既然在BaseDeleteView中已经集成了混入类,为什么还要在继承它的DeleteView中重复应用?这种冗余和不一致的规划显示AI在处理复杂任务时的逻辑混乱。研究发现,35.8%的内部问题源于这种对明确需求的误解,4.5%来自错误的步骤规划。
最意外的发现:CoT和代码的复杂关系
这里有个特别有趣的发现,研究者们发现,即使CoT是正确的,仍然有18.5%的代码会出错,反过来,即使CoT是错误的,居然还有3.1%的代码是正确的。这说明AI并不严格按照自己的"思考步骤"来生成代码,它们之间的关系比我们想象的要复杂得多。换句话说,AI可能一边说着"我要这样做",一边却在做着完全不同的事情。
上图显示了在不同数据集上CoT质量问题的具体分布情况。在CoderEval数据集中,外部因素是主要问题,而在SWE-bench-NF数据集中,内外部因素的分布更加均衡。
研究还提供了详细的统计数据:
从这个表格可以看出,虽然DeepSeek-R1在代码通过率上表现最好,但即使是最好的模型,仍然有大量的CoT存在质量问题。
进一步的分析显示,不同模型在各种错误因素上表现出不同的特点:
这个详细的分布表显示,缺少依赖信息是所有模型的共同弱点,而在边界条件处理方面,Gemini-2.0相对更优秀一些。
多智能体检测:让AI互相"挑刺"
面对这些问题,研究者们尝试了一种多智能体辩论(MAD)的检测方法。简单说就是让三个AI分别扮演质疑者、辩护者和仲裁者的角色,通过辩论来找出CoT中的问题。结果显示,这种方法在检测错误CoT方面显著优于单一模型,召回率能达到43.9%。不过代价也很明显:计算成本大幅增加,在实际应用中需要权衡性能和成本。当然,对于关键业务场景,这种额外的检测成本可能是值得的。
自我修复:详细反馈是关键
在修复方面,研究者们测试了三种不同粒度的反馈:简单反馈、错误类型反馈和详细错误反馈。结果很明确:反馈越详细,修复效果越好。Gemini-2.0在详细错误反馈下能达到7.4%的pass@1,虽然绝对数字不高,但相比简单反馈已经有了显著提升。这给我们一个重要启示:如果您想让AI修复代码问题,别只是说"有问题",要具体说明"哪里有什么问题"。
给AI产品开发工程师的实战建议
这项研究对喜欢用AI编程的朋友有很大帮助,像GitHub Copilot、Cursor这样的工具,都在大量使用CoT技术来提升代码生成质量。但现在我们知道,这些"思考过程"的可靠性还有很大提升空间,对于模型的内部因素,我们无法控制,但外部因素我们仍然能做一些工作,比如第一,在设计prompt时要特别注意上下文的完整性,把隐含的需求尽量显式化。第二,别盲目信任AI的推理过程,即使看起来很有道理。您需要建立"双重验证"机制:既要检查代码的功能正确性,也要审核推理步骤的逻辑性。第三,考虑在关键场景下使用多模型验证,虽然成本高一些,但能显著提升可靠性。感兴趣您可以看下《14种主流Prompt技术,顶级团队2000次实验,只有这几种真能打》这里面有实验各模型在软件工程上最佳和最差的Prompt Engine统计
写在最后:理性看待AI能力
这项研究给我们上了重要一课:AI的能力确实在快速提升,但我们对AI能力边界的理解还远远不够。76.4%的CoT质量问题听起来很吓人,但换个角度想,这也说明AI在23.6%的情况下还是能产生高质量推理的,这已经相当不错了。关键是我们要有正确的期待,既不要过分依赖,也不要因为发现问题就完全否定。
文章来自于“AI修猫Prompt”,作者“AI修猫Prompt”。
全部评论
留言在赶来的路上...
发表评论