ReAct 与思维链结合:让 AI Agent Harness Engineering 推理能力翻倍的进阶技巧


1. 标题 (Title)

  • ReAct × CoT 进阶指南:让 AI Agent 工程推理力突破天花板的落地方法论
  • 告别“试错式Agent”:拆解 ReAct + 思维链的 Harness Engineering 高阶玩法
  • 从 CoT 到 ReAct 再到 ReCoT:AI 工程推理能力翻倍的完整演进与实战技巧
  • Harness Engineering 实战课:用 ReAct + 结构化思维链构建高可用的 AI 开发助手

2. 引言 (Introduction)

2.1 痛点引入 (Hook)

还在为你的 AI Agent 解决问题时的“断链卡顿”而抓狂吗?
场景一:你用 LangChain 做了一个代码审查 ReAct Agent,它明明拿到了 Git 仓库的结构、发现了函数里有内存泄漏的迹象,却要么直接生成了完全错误的修复方案(根本没去查官方文档的内存管理 API),要么查了十次八次无关的 Stack Overflow 帖子——明明用了 CoT 提示模板,也加了 ReAct 的“观察-思考-行动”循环,为什么工程化问题的解决效率和正确率还是低得可怜?
场景二:你尝试用 AutoGPT Lite 搭建一个基于本地知识库的 AI 运维助手,它执行“排查 Redis 主从延迟 500ms 以上的原因”任务时,要么第一步就去敲 redis-cli PING(完全跳过配置检查、慢查询分析等核心步骤),要么第二步看到 INFO replication 里有 lag=520 就直接重启主从节点——根本没有结构化的推理链路,把 Harness Engineering(工具驾驭工程)做成了“工具滥用工程”!
场景三:你给 AI 大模型(比如 GPT-4o、Claude 3.5 Sonnet)写了一个简单的 ReAct Prompt 解决算法题,比如“设计一个 LRUCache 并测试它的性能瓶颈”,但大模型经常在“观察-行动”环节出bug:比如忘记初始化测试数据量、只生成了空的测试报告、把 Python 的 collections.OrderedDict 和手写双向链表的性能数据混在一起分析——这哪里是“AI 工程师”,分明是“AI 实习生实习生”!

这些问题,你是不是也遇到过?明明把 CoT(思维链)和 ReAct(推理-行动)这两个目前 AI 推理领域最火的技术结合起来了,为什么结果还是差强人意?

2.2 文章内容概述 (What)

别急,这篇文章就是来帮你解决这些问题的!

本文不会停留在“介绍 CoT 是什么、ReAct 是什么、怎么用 LangChain 写一个简单的 ReCoT(ReAct + CoT 缩写,本文后续统一使用该术语)Prompt”这种入门内容上——毕竟网上这类教程已经铺天盖地了。

本文会聚焦于 Harness Engineering 场景下的 ReCoT 进阶技巧,也就是:

  1. 为什么入门的 ReCoT 解决不了工程问题——拆解 CoT、ReAct、入门 ReCoT 的核心缺陷;
  2. 如何构建结构化的 ReCoT 推理链路——从 Harness Engineering 的核心流程(理解→假设→验证→执行→总结)出发,设计一套通用的“结构化思考模板 + 工具调用策略 + 观察解析规则”;
  3. 如何优化 ReCoT 的工具调用效率——减少无关工具调用、避免冗余循环、处理工具调用失败的边界情况;
  4. 如何构建可复用的 ReCoT 组件库——在 LangChain、AutoGPT Lite、MetaGPT 等主流 Agent 框架中,把 ReCoT 的核心能力(结构化思考、工具导航、观察总结)封装成可插拔的组件;
  5. 实战构建高可用的 ReCoT AI 开发助手——从零开始,用 Python + LangChain + 本地知识库 + 代码执行器,搭建一个能“理解需求、写技术方案、查官方文档、写代码、做单元测试、做性能测试、生成测试报告”的全流程 AI 开发助手;
  6. ReCoT 的进阶优化与未来趋势——比如引入多步记忆回溯、自我反思机制、混合思维链(CoT + ToT + CoT)、多 Agent ReCoT 协作等。

2.3 读者收益 (Why)

读完本文,你将获得:

  1. 一套完整的 Harness Engineering ReCoT 理论体系——不再是零散的 Prompt 技巧,而是从问题定义到落地优化的全链路方法论;
  2. 一套通用的结构化 ReCoT 推理模板库——涵盖代码开发、代码审查、运维排查、技术方案设计、算法题解等多个常见工程场景;
  3. 一套可复用的 ReCoT 组件库——在主流 Agent 框架中开箱即用,节省你 80% 的重复开发时间;
  4. 一个完整的实战项目——高可用的 ReCoT AI 开发助手,你可以直接把它用到自己的工作中;
  5. 对 AI Agent 未来发展的深刻理解——知道 ReCoT 接下来会往哪里走,提前布局自己的技术栈。

3. 准备工作 (Prerequisites)

3.1 技术栈/知识

为了更好地理解和实践本文内容,你需要具备以下技术栈和知识:

  1. 扎实的 Python 编程基础——熟悉 Python 的面向对象编程、装饰器、异步编程(asyncio)、数据结构与算法(至少要懂链表、哈希表、LRUCache 的基本原理);
  2. 对大语言模型(LLM)的基本理解——知道什么是 Prompt、Completion、Token、Temperature、Top-p、Context Window 等核心概念;
  3. 对 CoT(思维链)和 ReAct(推理-行动)的入门了解——至少用过一两次 CoT Prompt 解决问题,看过 ReAct 的原始论文或者入门教程;
  4. 对主流 Agent 框架的基本了解——比如 LangChain(至少用过 LLMChain、SimpleSequentialChain、AgentExecutor 这些基础组件)、AutoGPT Lite 或者 MetaGPT 中的任意一个;
  5. 对 Git、GitHub/GitLab、Docker、Redis 等常见开发/运维工具的基本了解——因为实战项目会用到这些工具;
  6. 对 Harness Engineering(工具驾驭工程)的基本理解——知道 AI Agent 在工程场景中需要“理解工具的功能、知道什么时候用什么工具、怎么正确调用工具、怎么解析工具的返回结果、怎么根据结果调整下一步行动”。

3.2 环境/工具

为了完成本文的实战项目,你需要准备以下环境和工具:

  1. 操作系统:Windows 10/11(WSL2)、macOS(Ventura 及以上)、Linux(Ubuntu 20.04/22.04 及以上)——推荐使用 Linux 或者 macOS,因为代码执行器在 Windows 原生环境中可能会有一些权限问题;
  2. Python 环境:Python 3.10 及以上(建议使用 3.11,性能更好),并安装了 pip、virtualenv 或者 conda 等包管理工具;
  3. 大语言模型 API Key:你可以选择 OpenAI 的 GPT-4o/GPT-4o Mini、Anthropic 的 Claude 3.5 Sonnet/Claude 3 Opus、Google 的 Gemini 1.5 Pro/Gemini 1.5 Flash 中的任意一个——推荐使用 GPT-4o 或者 Claude 3.5 Sonnet,因为它们的工程推理能力和工具驾驭能力目前是最强的;
  4. 本地知识库工具(可选但推荐):比如 LangChain 的 ChromaDB、Qdrant 或者 FAISS——实战项目会用 ChromaDB 搭建一个本地的技术文档知识库;
  5. 代码执行器工具(可选但推荐):比如 LangChain 的 PythonREPLTool、Docker 容器化的代码执行器(比如 E2B)——实战项目会用 Docker 容器化的 E2B 代码执行器,因为它更安全、更隔离;
  6. Git 环境:已安装 Git 并配置了 GitHub/GitLab 的 SSH Key——实战项目会用 Git 克隆模板仓库、管理代码;
  7. 代码编辑器/IDE:推荐使用 VS Code(安装了 Python、LangChain、GitLens 等插件)或者 PyCharm;
  8. 测试工具(可选但推荐):比如 pytest、unittest——实战项目会用 pytest 做单元测试和性能测试。

4. 核心内容:基础理论拆解(为什么入门 ReCoT 不行)

在开始实战之前,我们必须先搞清楚一个问题:为什么我们把 CoT 和 ReAct 简单拼接起来,解决不了复杂的工程问题?

要回答这个问题,我们需要先分别拆解 CoT、ReAct、入门 ReCoT 的核心原理、优点、以及致命缺陷——特别是在 Harness Engineering 场景下的缺陷。

4.1 思维链(Chain of Thought, CoT)基础理论拆解

4.1.1 核心概念

思维链(CoT) 是 Google Research 在 2022 年发表的论文《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》中提出的一种 Prompt 技术。

它的核心思想很简单:在给大语言模型(LLM)提问时,不要只给输入和输出,还要给几个“中间推理步骤”的示例——也就是“思维链示例”(Few-Shot CoT),或者直接在 Prompt 里加上一句“请一步步思考”(Zero-Shot CoT)。

这样做的目的是引导 LLM 像人类一样,通过“分解问题→逐步推理→得出结论”的方式来解决复杂的逻辑、数学、编程问题,而不是直接“猜答案”。

4.1.2 问题背景

在 CoT 出现之前,LLM 在解决“多步推理问题”(比如小学数学应用题、复杂的逻辑推理题、算法题)时的表现非常差——哪怕是 GPT-3(175B 参数)这样的大模型,在 GSM8K(小学数学应用题数据集)上的准确率也只有不到 20%。

为什么会这样?因为当时的主流 Prompt 技术是“输入-输出”式的(也就是 Direct Prompting):LLM 拿到问题后,直接生成答案,中间没有任何思考过程——就像一个小学生,拿到数学题后直接写答案,根本不打草稿,结果自然可想而知。

4.1.3 核心原理(为什么 CoT 有用?)

CoT 为什么能大幅提升 LLM 的多步推理能力?Google Research 的论文里给出了三个主要原因:

  1. 分解复杂问题:CoT 引导 LLM 把一个复杂的问题分解成多个简单的子问题,每个子问题的解决难度都大大降低;
  2. 激活 LLM 的“推理神经”:LLM 的参数里其实已经存储了大量的“推理知识”(比如数学公式、逻辑规则、编程语法),但 Direct Prompting 无法激活这些知识——CoT 通过“中间推理步骤”的示例,给 LLM 一个“信号”:“哦,原来我需要先调用这些推理知识,再一步步得出结论”;
  3. 修正推理错误:在 Few-Shot CoT 中,LLM 可以学习到“正确的推理路径”——哪怕它在某一步推理中犯了错误,也可以通过模仿示例中的步骤来修正(虽然 Zero-Shot CoT 做不到这一点,但它至少能让 LLM 开始思考)。

不过,后来的研究(比如 OpenAI 的《GPT-4 Technical Report》、Meta 的《Scaling Laws for Neural Language Models》补充研究)发现,CoT 有用还有一个更重要的原因:大语言模型的“涌现能力”(Emergent Abilities)——只有当 LLM 的参数规模达到一定程度(比如 100B 以上),CoT 才能发挥作用;参数规模越小,CoT 的效果越差,甚至可能起反作用。

4.1.4 概念结构与核心要素组成

CoT 的概念结构非常简单,它主要由三个核心要素组成:

  1. 任务说明(Task Instruction):告诉 LLM 它需要做什么——比如“请解决以下小学数学应用题”;
  2. 思维链示例(Few-Shot Examples, 可选但推荐):给 LLM 几个“输入→中间推理步骤→输出”的完整示例——示例的质量和数量直接决定了 CoT 的效果;
  3. 目标问题(Target Question):给 LLM 需要解决的实际问题;
  4. 思维链触发词(Trigger Word, 可选但 Zero-Shot CoT 必须):比如“请一步步思考”、“Let’s think step by step”、“首先,我们需要…”——触发词可以引导 LLM 自动生成中间推理步骤。

我们可以用一个简单的 Mermaid ER 实体关系图来表示 CoT 的核心要素之间的关系:

包含/指导

应用于

可能包含

Zero-Shot CoT 必须包含

TASK_INSTRUCTION

string

content

任务说明内容

FEW_SHOT_EXAMPLE

string

input

示例输入

string

reasoning_steps

示例中间推理步骤

string

output

示例输出

TARGET_QUESTION

string

content

目标问题内容

TRIGGER_WORD

string

content

触发词内容

boolean

is_zero_shot

是否用于 Zero-Shot CoT

4.1.5 问题解决:CoT 的应用场景

CoT 主要适用于以下几类“多步推理问题”:

  1. 数学问题:比如小学数学应用题(GSM8K)、高中数学题(MATH)、大学数学题(AMC);
  2. 逻辑推理问题:比如三段论推理、常识推理(CommonsenseQA)、策略游戏推理(比如 Chess、Go 的简单局面);
  3. 代码理解与生成问题:比如代码补全、代码解释、简单算法题的代码生成;
  4. 自然语言理解问题:比如文本摘要的逻辑梳理、问答系统的多跳推理(Multi-Hop QA)。

我们可以用一个简单的 Few-Shot CoT 示例来演示它的应用——比如解决一道 GSM8K 小学数学应用题:

### 任务说明
请解决以下小学数学应用题,并给出完整的中间推理步骤。

### 思维链示例 1
**输入**:小明有 15 个苹果,他给了小红 3 个,又给了小刚 5 个,请问小明还剩几个苹果?
**中间推理步骤**:
1.  首先,我们需要计算小明一共给出去了多少个苹果:小红的 3 个 + 小刚的 5 个 = 8 个;
2.  然后,我们用小明原来有的苹果数减去给出去的苹果数,就能得到剩下的苹果数:15 个 - 8 个 = 7 个;
**输出**:小明还剩 7 个苹果。

### 思维链示例 2
**输入**:一个长方形的长是 12 厘米,宽是 8 厘米,请问这个长方形的周长是多少厘米?
**中间推理步骤**:
1.  首先,我们需要回忆一下长方形的周长公式:周长 = 2 × (长 + 宽);
2.  然后,我们把长和宽代入公式:长 + 宽 = 12 厘米 + 8 厘米 = 20 厘米;
3.  最后,我们计算周长:2 × 20 厘米 = 40 厘米;
**输出**:这个长方形的周长是 40 厘米。

### 目标问题
**输入**:小李有 20 支铅笔,他用了 4 支,又买了 7 支,请问小李现在有几支铅笔?
**中间推理步骤**:

当我们把这个 Prompt 输入给 GPT-4o Mini 时,它会自动生成完整的中间推理步骤和正确的输出:

**中间推理步骤**:
1.  首先,我们需要计算小李用了 4 支铅笔后还剩多少支:原来的 20 支 - 用掉的 4 支 = 16 支;
2.  然后,我们用剩下的铅笔数加上又买的铅笔数,就能得到现在的铅笔数:16 支 + 7 支 = 23 支;
**输出**:小李现在有 23 支铅笔。
4.1.6 边界与外延
4.1.6.1 CoT 的边界(什么时候 CoT 没用?)

CoT 虽然强大,但它也有自己的边界——在以下几种情况下,CoT 的效果会非常差,甚至可能起反作用:

  1. 单步推理问题:比如“1+1等于几”、“中国的首都是哪里”——这类问题不需要分解,直接“猜答案”的效率和正确率更高,CoT 反而会增加 LLM 的推理时间,甚至可能引入不必要的错误;
  2. 参数规模较小的 LLM:比如 GPT-2(1.5B 参数)、Llama 2 7B——这类 LLM 没有“涌现能力”,CoT 不仅不能提升它们的推理能力,反而会让它们生成混乱的中间推理步骤;
  3. 需要外部知识的问题:比如“2024年巴黎奥运会的金牌榜第一名是哪个国家”、“最新版 Python 的 asyncio.run() 函数有什么新特性”——这类问题的答案不在 LLM 的训练数据里(或者训练数据已经过时),CoT 再怎么推理也得不出正确的答案;
  4. 需要实时交互的问题:比如“现在的天气怎么样”、“帮我查一下这个 GitHub 仓库的最新提交记录”——这类问题需要 LLM 调用外部工具(比如天气 API、GitHub API),但 CoT 本身不具备“工具调用”的能力;
  5. 需要多轮迭代优化的问题:比如“设计一个高并发的电商订单系统”、“写一个能通过所有测试用例的 LRUCache 代码”——这类问题需要 LLM 不断地“提出方案→验证方案→修正方案→再验证方案”,但 CoT 本身是“一次性”的,无法进行多轮迭代优化。
4.1.6.2 CoT 的外延(CoT 的变种技术)

为了突破 CoT 的边界,研究者们提出了很多 CoT 的变种技术,比如:

  1. Zero-Shot CoT:不需要 Few-Shot 示例,只需要在 Prompt 里加上一句“请一步步思考”(或者“Let’s think step by step”)——适合没有合适 Few-Shot 示例的场景;
  2. Self-Consistency CoT(自我一致性思维链):让 LLM 生成多个不同的思维链推理路径,然后用“投票”的方式选择出现次数最多的答案——适合解决有歧义的问题,能大幅提升 CoT 的准确率;
  3. Tree of Thought(ToT,思维树):把 CoT 的“线性推理”变成“树状推理”——LLM 可以在每个推理步骤生成多个可能的子步骤,然后用“剪枝”的方式保留最有可能的子步骤,最后选择最优的推理路径——适合解决非常复杂的、需要探索多个可能性的问题(比如策略游戏推理、数学证明);
  4. Graph of Thought(GoT,思维图):把 ToT 的“树状推理”变成“图状推理”——LLM 可以在不同的推理步骤之间建立“连接”(比如共享某个子问题的解决方案)——适合解决有多个依赖关系的复杂问题;
  5. Chain of Verification(CoVe,验证链):让 LLM 先生成一个初步的答案,然后生成一个“验证问题列表”,再逐一回答这些验证问题,最后根据验证结果修正初步的答案——适合解决容易出现“幻觉”(Hallucination)的问题,能大幅提升 LLM 输出的可信度。

我们可以用一个简单的 Markdown 表格来对比 CoT 及其主要变种技术的核心属性:

技术名称 核心推理结构 是否需要 Few-Shot 示例 是否需要外部工具 是否支持多轮迭代优化 是否支持剪枝/投票 适用场景 准确率(GSM8K 数据集,GPT-4) 推理时间(相对值)
Direct Prompting 无(直接输出) 可选 单步推理问题 ~60% 1x
Zero-Shot CoT 线性 多步推理问题(无示例) ~75% 2x
Few-Shot CoT 线性 多步推理问题(有示例) ~90% 2.5x
Self-Consistency CoT 多条线性 是(投票) 有歧义的多步推理问题 ~95% 8x-10x
Tree of Thought (ToT) 树状 是(局部迭代) 是(剪枝) 非常复杂的探索性多步推理问题 ~97% 20x-50x
Graph of Thought (GoT) 图状 是(全局迭代) 是(剪枝+投票) 有多个依赖关系的复杂问题 ~98% 50x-100x
Chain of Verification (CoVe) 线性+验证链 是(验证后修正) 容易出现幻觉的问题 ~92%(针对幻觉问题的准确率提升 30%-50%) 4x-6x

4.1.7 致命缺陷(特别是在 Harness Engineering 场景下)

虽然 CoT 及其变种技术能大幅提升 LLM 的多步推理能力,但它们都有一个致命缺陷——这个缺陷在 Harness Engineering 场景下尤为明显,甚至可以说是“致命的”:

CoT 及其变种技术都不具备“工具调用”和“实时环境交互”的能力,也无法处理“推理结果与现实环境不符”的情况。

什么意思?我们用一个简单的 Harness Engineering 场景来演示——比如“帮我写一个 Python 函数,计算两个数的最大公约数(GCD),并测试它是否能通过所有常见的测试用例”。

如果我们只用 Few-Shot CoT 来解决这个问题,Prompt 可能长这样:

### 任务说明
请帮我写一个 Python 函数,计算两个正整数的最大公约数(GCD),并给出完整的中间推理步骤、函数代码、以及常见测试用例的测试结果。

### 思维链示例
**输入**:请帮我写一个 Python 函数,计算两个正整数的最小公倍数(LCM),并给出完整的中间推理步骤、函数代码、以及常见测试用例的测试结果。
**中间推理步骤**:
1.  首先,我需要回忆一下最小公倍数的定义:两个正整数的最小公倍数是能被这两个数同时整除的最小正整数;
2.  然后,我需要回忆一下最小公倍数的计算公式:LCM(a, b) = (a × b) / GCD(a, b)——所以我需要先实现一个计算最大公约数的函数;
3.  接下来,我需要回忆一下计算最大公约数的常用算法:欧几里得算法(辗转相除法)——它的原理是 GCD(a, b) = GCD(b, a mod b),直到 b 等于 0,此时 a 就是最大公约数;
4.  然后,我需要用 Python 代码实现欧几里得算法;
5.  接下来,我需要用 Python 代码实现最小公倍数的函数;
6.  然后,我需要设计几个常见的测试用例:
    a.  测试用例 1:LCM(4, 6) = 12;
    b.  测试用例 2:LCM(5, 7) = 35(两个质数);
    c.  测试用例 3:LCM(12, 18) = 36;
    d.  测试用例 4:LCM(1, 100) = 100;
    e.  测试用例 5:LCM(0, 5)——需要处理边界情况(输入为 0);
7.  最后,我需要模拟这些测试用例的执行过程,给出测试结果;
**函数代码**:
```python
def gcd(a: int, b: int) -> int:
    \"\"\"计算两个正整数的最大公约数(欧几里得算法)\"\"\"
    while b != 0:
        a, b = b, a % b
    return a

def lcm(a: int, b: int) -> int:
    \"\"\"计算两个正整数的最小公倍数\"\"\"
    if a == 0 or b == 0:
        raise ValueError("输入的两个数必须都是正整数")
    return (a * b) // gcd(a, b)

测试用例与测试结果

  1. 测试用例 1:LCM(4, 6) = (4×6)/GCD(4,6) = 24/2 = 12 ✅;
  2. 测试用例 2:LCM(5, 7) = (5×7)/GCD(5,7) = 35/1 = 35 ✅;
  3. 测试用例 3:LCM(12, 18) = (12×18)/GCD(12,18) = 216/6 = 36 ✅;
  4. 测试用例 4:LCM(1, 100) = (1×100)/GCD(1,100) = 100/1 = 100 ✅;
  5. 测试用例 5:LCM(0, 5) → 抛出 ValueError ✅;

目标问题

输入:请帮我写一个 Python 函数,计算两个正整数的最大公约数(GCD),并给出完整的中间推理步骤、函数代码、以及常见测试用例的测试结果。
中间推理步骤


当我们把这个 Prompt 输入给 GPT-4o 时,它会生成看起来非常完美的中间推理步骤、函数代码和测试结果——比如:

```markdown
**中间推理步骤**:
1.  首先,我需要回忆一下最大公约数的定义:两个正整数的最大公约数是能被这两个数同时整除的最大正整数;
2.  然后,我需要回忆一下计算最大公约数的常用算法:欧几里得算法(辗转相除法)——它的原理是 GCD(a, b) = GCD(b, a mod b),直到 b 等于 0,此时 a 就是最大公约数;
3.  接下来,我需要考虑边界情况:
    a.  如果输入的两个数中有一个是 0,需要抛出错误;
    b.  如果输入的两个数中有一个是负数,需要先取绝对值(不过任务说明里说输入是正整数,所以这一步可以省略,但为了函数的鲁棒性,最好还是加上);
4.  然后,我需要用 Python 代码实现欧几里得算法;
5.  接下来,我需要设计几个常见的测试用例:
    a.  测试用例 1:GCD(4, 6) = 2;
    b.  测试用例 2:GCD(5, 7) = 1(两个质数);
    c.  测试用例 3:GCD(12, 18) = 6;
    d.  测试用例 4:GCD(1, 100) = 1;
    e.  测试用例 5:GCD(0, 5) → 抛出 ValueError;
    f.  测试用例 6:GCD(-4, 6) → 先取绝对值,再计算,结果为 2;
6.  最后,我需要模拟这些测试用例的执行过程,给出测试结果;
**函数代码**:
```python
def gcd(a: int, b: int) -> int:
    \"\"\"计算两个整数的最大公约数(欧几里得算法)\"\"\"
    # 处理边界情况:输入为 0
    if a == 0 or b == 0:
        raise ValueError("输入的两个数不能为 0")
    # 处理负数情况:先取绝对值
    a = abs(a)
    b = abs(b)
    # 欧几里得算法
    while b != 0:
        a, b = b, a % b
    return a

测试用例与测试结果

  1. 测试用例 1:GCD(4, 6) → 取绝对值后为 4 和 6 → 欧几里得算法:GCD(4,6)=GCD(6,4)=GCD(4,2)=GCD(2,0)=2 ✅;
  2. 测试用例 2:GCD(5, 7) → 取绝对值后为 5 和 7 → GCD(5,7)=GCD(7,5)=GCD(5,2)=GCD(2,1)=GCD(1,0)=1 ✅;
  3. 测试用例 3:GCD(12, 18) → 取绝对值后为 12 和 18 → GCD(12,18)=GCD(18,12)=GCD(12,6)=GCD(6,0)=6 ✅;
  4. 测试用例 4:GCD(1, 100) → 取绝对值后为 1 和 100 → GCD(1,100)=GCD(100,1)=GCD(1,0)=1 ✅;
  5. 测试用例 5:GCD(0, 5) → 抛出 ValueError ✅;
  6. 测试用例 6:GCD(-4, 6) → 取绝对值后为 4 和 6 → 结果为 2 ✅;

看起来非常完美,对吧?但是——**如果我们把这个函数代码复制到 Python 环境中运行测试用例 6,会发生什么?**

测试用例 6 是 `GCD(-4, 6)`——我们来手动执行一下函数代码:
1.  首先,检查输入是否为 0:-4 和 6 都不是 0,跳过;
2.  然后,取绝对值:a = abs(-4) = 4,b = abs(6) = 6;
3.  接下来,执行欧几里得算法:
    a.  第一次循环:b != 0 → a, b = b, a % b → a = 6, b = 4 % 6 = 4;
    b.  第二次循环:b != 0 → a, b = b, a % b → a = 4, b = 6 % 4 = 2;
    c.  第三次循环:b != 0 → a, b = b, a % b → a = 2, b = 4 % 2 = 0;
    d.  循环结束,返回 a = 2;
4.  看起来测试用例 6 是通过的,对吧?

那我们再换一个测试用例——比如 `GCD(6, -4)`——执行结果也是 2,没问题。

那我们再换一个更复杂的测试用例——比如 `GCD(123456789, 987654321)`——GPT-4o 模拟的测试结果是 9,对吧?

那我们把这个函数代码复制到 Python 环境中运行一下——结果真的是 9,没问题。

那……CoT 的致命缺陷在哪里?

别急,我们再换一个 Harness Engineering 场景——比如“帮我写一个 Python 函数,读取当前目录下的 `requirements.txt` 文件,统计里面有多少个依赖包,并测试它是否能通过所有常见的测试用例”。

如果我们只用 Few-Shot CoT 来解决这个问题,GPT-4o 可能会生成这样的函数代码:

```python
def count_requirements() -> int:
    \"\"\"读取当前目录下的 requirements.txt 文件,统计依赖包的数量\"\"\"
    with open("requirements.txt", "r", encoding="utf-8") as f:
        lines = f.readlines()
    # 过滤掉空行和注释行(以 # 开头的行)
    count = 0
    for line in lines:
        line = line.strip()
        if line and not line.startswith("#"):
            count += 1
    return count

然后模拟的测试用例与测试结果可能长这样:

  1. 测试用例 1:当前目录下有一个 requirements.txt 文件,内容为:
    # 这是一个注释
    langchain==0.2.10
    openai==1.35.10
    
    python-dotenv==1.0.1
    
    → 统计结果为 3 ✅;
  2. 测试用例 2:当前目录下没有 requirements.txt 文件 → 抛出 FileNotFoundError ✅;

看起来非常完美,对吧?但是——如果当前目录下真的没有 requirements.txt 文件,GPT-4o 能知道吗?

答案是:不能!

因为 CoT 及其变种技术都不具备“实时环境交互”的能力——GPT-4o 只能“模拟”测试用例的执行过程,它根本不知道当前目录下有没有 requirements.txt 文件,也不知道当前目录下的 requirements.txt 文件的真实内容是什么。

那如果我们让 GPT-4o 写这个函数,然后我们自己去运行测试用例——如果测试用例失败了,比如统计结果不对,或者文件编码不对,我们再把错误信息反馈给 GPT-4o,让它修正函数代码——这算不算“多轮迭代优化”?

算——但这是人类驱动的多轮迭代优化,不是AI 自主驱动的多轮迭代优化

在 Harness Engineering 场景下,我们需要的是AI 自主驱动的多轮迭代优化——也就是:

  1. AI 理解需求;
  2. AI 提出初步的解决方案;
  3. AI 自主调用外部工具(比如代码执行器、文件系统工具、API 工具)来验证解决方案;
  4. AI 自主解析工具的返回结果
  5. 如果验证失败,AI 自主修正解决方案
  6. 重复步骤 3-5,直到验证通过;
  7. AI 输出最终的解决方案。

而 CoT 及其变种技术,根本做不到这一点——这就是它们的致命缺陷


(本章剩余内容将继续拆解 ReAct 的基础理论、致命缺陷,以及入门 ReCoT 的致命缺陷,预计本章总字数将超过 15000 字)

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐