目录
3.1.1 CoT框架:分步推理
1. CoT的工作原理
2. Python实现示例
3.1.2 ToT框架:多路径探索式推理
1. 技术概述与定义
2. 基本工作原理
3. 技术实现细节
4. 实现案例
3.1.3 ReAct框架:将Reasoning+Acting结合
1. 核心组件
2. 工作流程
3. Python实现案例
《AI Agent智能体开发实践》(邓立国,邓淇文)【摘要 书评 试读】- 京东图书
《AI Agent智能体开发实践》1~6章试读_《ai agent 智能体开发实践》在线阅读-CSDN博客
智能体的规划与推理能力是其实现复杂任务的核心,其中Chain-of-Thought(CoT,思维链)、Tree-of-Thought(ToT,思维树)和ReAct框架是三种关键技术。本节详细解析这三种关键技术。
3.1.1 CoT框架:分步推理
CoT是一种让大型语言模型展示其推理过程的技术,通过引导模型逐步展示解决问题的中间推理步骤,而不是直接给出最终答案。
1. CoT的工作原理
1)基本机制
(1)模型接收包含问题的提示(prompt)。
(2)不是直接回答,而是首先生成一系列中间推理步骤。
(3)基于这些中间步骤得出最终答案。
2)与传统提示的区别
(1)传统提示:问题→直接答案。
(2)CoT提示:问题→推理步骤1→推理步骤2→……→最终答案。
2. Python实现示例
【示例3.1】使用DeepSeek API实现CoT。
import requests import os from dotenv import load_dotenv # 可选,用于加载环境变量 # 1. 加载API密钥(避免硬编码,更安全) load_dotenv() # 加载.env文件中的环境变量 API_KEY = ("DEEPSEEK_API_KEY") # 从.env文件读取API_KEY API_URL = "https://api.deepseek.com/v1/chat/completions" # DeepSeek Chat API端点(需确认最新地址) # 2. 定义CoT Prompt模板(以数学计算为例) def build_cot_prompt(question): cot_template = """ 你需要解决以下问题,并严格按照要求分步推理: 问题:{question} 要求: 1. 先明确问题中的已知信息和需要求的结果; 2. 每一步推理都必须说明“为什么这么做”(如“第一步:计算总消耗,因为需要先知道用掉多少”); 3. 不允许跳步,即使是简单计算也需说明理由; 4. 推理结束后,用“【最终答案】”开头总结结果。 【推理过程】 """ return cot_template.format(question=question) # 传入具体问题,生成完整Prompt # 3. 调用DeepSeek API,获取CoT推理结果 def call_deepseek_cot(question): # 构建请求体(遵循DeepSeek API格式,参考官方文档) prompt = build_cot_prompt(question) payload = { "model": "deepseek-chat", # 模型名称(如deepseek-chat、deepseek-coder,需确认可用模型) "messages": [{"role": "user", "content": prompt}], # 用户消息(CoT Prompt) "temperature": 0.2, # 温度:越低推理越稳定(CoT需低温度,避免逻辑混乱) "max_tokens": 1000 # 最大输出长度:确保能容纳完整推理过程 } # 发送HTTP请求 headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } response = requests.post(API_URL, json=payload, headers=headers) response.raise_for_status() # 捕获HTTP错误(如API密钥无效、额度不足) # 解析模型输出 cot_result = response.json()["choices"][0]["message"]["content"] return cot_result # 4. 示例:运行CoT推理(解决数学问题) if __name__ == "__main__": # 待解决的复杂问题 user_question = "一个长方形操场,长是宽的2倍,周长是180米,求操场的面积是多少平方米?" # 调用API获取推理结果 cot_output = call_deepseek_cot(user_question) # 打印结果(含推理过程和最终答案) print("DeepSeek CoT推理结果:") print("="*50) print(cot_output)运行代码,输出如下:
DeepSeek CoT推理结果: ================================================== 【推理过程】 第一步:明确已知信息和需要求的结果。 已知信息:操场是一个长方形,长是宽的2倍,周长是180米。 需要求的结果:操场的面积(单位:平方米)。 第二步:设未知数表示宽。 因为长是宽的2倍,所以设宽为 \( w \) 米,那么长就是 \( 2w \) 米。这样设未知数可以方便地表示长和宽的关系。 第三步:根据周长公式列出方程。 长方形的周长公式是 \( 2 \times (长 + 宽) \),因为周长是长和宽之和的两倍。已知周长是180米,所以: \[ 2 \times (2w + w) = 180 \] 这里将长 \( 2w \) 和宽 \( w \) 代入公式。 第四步:简化方程并求解宽 \( w \)。 先计算括号内的和:\( 2w + w = 3w \)。 所以方程变为: \[ 2 \times 3w = 180 \] 即: \[ 6w = 180 \] 然后两边同时除以6,解出 \( w \): \[ w = 180 \div 6 = 30 \] 因此宽是30米。 第五步:求长。 因为长是宽的2倍,所以长 \( l = 2w = 2 \times 30 = 60 \) 米。 这里直接利用已知关系计算。 第六步:计算面积。 长方形的面积公式是 \( 长 \times 宽 \),所以: \[ 面积 = 60 \times 30 = 1800 \] 这里将求出的长和宽相乘得到面积。 【最终答案】操场的面积是1800平方米。CoT技术显著提升了大型语言模型解决复杂问题的能力,通过展示推理过程增强了模型的可解释性,是当前AI解释性和可靠性研究的重要方向之一。
3.1.2 ToT框架:多路径探索式推理
ToT是一种利用大型语言模型解决问题的先进框架,由普林斯顿大学和谷歌DeepMind联合提出。该技术通过分解问题、生成思维步骤、评估状态并运用搜索算法探索解决方案,模仿人类决策过程,具有通用性和模块化特点。
1. 技术概述与定义
ToT框架将语言模型的推理过程建模为对树状结构的搜索,通过逐步将问题拆解为更易处理的子问题,每一步都探索并缓存可行的解题路径,从而提高语言模型解决问题的能力。它推广了流行的“链式思维(Chain of Thought,CoT)”方法,通过允许模型探索作为解决问题中间步骤的连贯文本单元("思想"),使模型能够考虑多种不同的推理路径并自我评估选择。
2. 基本工作原理
1)ToT框架的核心在于将问题的解决过程视为一棵思维树,其中:
(1)每个节点代表一个思维步骤(即中间推理过程)。
(2)边代表从一个状态到另一个状态的转变。
(3)通过生成和评估这些步骤,与搜索算法相结合,实现系统性探索。
2)该框架包含4个关键组成部分:
(1)思维分解:将问题分解为多个中间推理步骤。
(2)思维生成器:生成可能的下一步思维(即树的分支)。
(3)状态评估器:评估当前思维状态的质量和前景。
(4)搜索算法:系统性地探索思维树(如BFS、DFS等)。
3. 技术实现细节
1)问题分解与初始节点生成
(1)将复杂问题分解为多个子问题或步骤,形成树状结构的根节点(初始状态)。
(2)通过模型的生成能力产生多个可能的初步思路,作为树的初始分支。
2)搜索策略选择
(1)广度优先搜索(BFS):并行扩展所有可能路径,避免局部最优,但计算成本高。
(2)深度优先搜索(DFS):深入单一路径直至得出结论,适合资源有限的场景。
(3)也可采用蒙特卡洛树搜索等更复杂的算法。
3)节点评估与路径选择
(1)自我评估:模型直接判断当前路径的合理性(如概率输出)。
(2)外部验证:通过规则、工具调用或人工反馈进行验证。
(3)动态剪枝淘汰低概率或无效路径,减少计算开销。
4)回溯与全局优化
(1)当路径陷入死胡同时返回父节点并尝试其他分支。
(2)对模糊节点引入蒙特卡洛采样,多次评估以量化不确定性。
4. 实现案例
【示例3.2】ToT数学问题求解:找出所有三个连续正整数,其和为36。
ToT解决过程:
初始思维:设第一个数为x,则三个数为x、x+1、x+2。
分支1:建立方程x+(x+1)+(x+2)=36→3x+3=36。
分支2:考虑平均数36/3=12,所以三个数为11、12、13。
评估:两种方法都得到x=11,验证正确性。
class TreeOfThought: def __init__(self): self.solutions = [] def generate_thoughts(self, current_state): """生成可能的思考路径""" # 在这个问题中,我们只有一种数学方法,所以返回单一思考 return ["algebraic_approach"] def evaluate_states(self, states): """评估思考状态""" # 在这个简单问题中,所有状态都同样好 return [1 for _ in states] def solve_problem(self): """使用ToT框架解决问题""" initial_thoughts = self.generate_thoughts(None) scores = self.evaluate_states(initial_thoughts) # 选择最佳思考路径(这里只有一条) best_thought = initial_thoughts[scores.index(max(scores))] if best_thought == "algebraic_approach": # 代数方法解决 # 设三个连续整数为n, n+1, n+2 # 和为: n + (n+1) + (n+2) = 3n + 3 = 36 # => 3n = 33 => n = 11 n = (36 - 3) // 3 if n > 0 and (n + (n+1) + (n+2)) == 36: self.solutions.append((n, n+1, n+2)) return self.solutions def alternative_brute_force_approach(self): """另一种暴力搜索方法,展示ToT的多路径探索""" solutions = [] # 遍历可能的连续整数序列 for x in range(1, 36): y = x + 1 z = x + 2 if x + y + z == 36: solutions.append((x, y, z)) break # 因为是连续正整数,只有一个解 return solutions # 使用ToT解决问题 if __name__ == "__main__": print("使用Tree-of-Thought方法解决问题:") tot = TreeOfThought() solutions = tot.solve_problem() if solutions: print(f"找到的解: {solutions[0]}") print(f"验证: {solutions[0][0]} + {solutions[0][1]} + {solutions[0][2]} = {sum(solutions[0])}") else: print("没有找到解") print("\n替代方法验证:") alt_solutions = tot.alternative_brute_force_approach() if alt_solutions: print(f"暴力搜索找到的解: {alt_solutions[0]}") else: print("暴力搜索没有找到解")代码解释:
(1)TreeOfThought类:实现了基本的ToT框架。
- generate_thoughts():生成可能的解决路径(这里只有代数方法)。
- evaluate_states():评估各思考路径的质量。
- solve_problem():执行最佳思考路径来解决问题。
(2)代数方法:
- 设三个连续整数为n,n+1,n+2。
- 建立方程:3n+3=36。
- 解得n=11。
- 验证解(11,12,13)确实满足和为36。
(3)替代方法:
- 实现暴力搜索来验证结果。
- 展示ToT可以包含多种解决路径。
运行代码,输出如下:
使用Tree-of-Thought方法解决问题: 找到的解: (11, 12, 13) 验证: 11 + 12 + 13 = 36 替代方法验证: 暴力搜索找到的解: (11, 12, 13)ToT框架已在GitHub上开源,主要资源包括:
- 官方实现:https://github.com/princeton-nlp/tree-of-thought-llm。
- 非官方实现:https://github.com/kyegomez/tree-of-thoughts。
3.1.3 ReAct框架:将Reasoning+Acting结合
ReAct框架是一种结合“推理(Reasoning)”和“行动(Acting)”的AI智能体开发框架,旨在通过动态的思考与执行循环解决复杂任务。其核心运作机制可以概括为“思考(Thought)→行动(Action)→观察(Observation)”的迭代循环。
- 思考:模型基于当前任务目标和已有的观察信息进行逻辑推理和规划,分析问题并决定下一步需要执行的动作。
- 行动:根据“思考”阶段制定的计划,模型生成并执行具体的行动指令,如调用外部API、查询数据库等。
- 观察:模型接收并处理“行动”执行后从外部环境获得的反馈信息,这些观察结果将作为下一轮“思考”的输入。
1. 核心组件
(1)推理引擎:负责分析问题和生成行动计划。
(2)行动执行器:负责执行具体动作。
(3)记忆模块:存储历史交互和知识。
(4)环境接口:与外部环境交互的接口。
2. 工作流程
(1)接收输入/观察环境状态。
(2)推理生成可能的行动方案。
(3)选择最优行动并执行。
(4)观察行动结果并更新状态。
(5)重复(2)~(4)步直到问题解决。
3. Python实现案例
【示例3.3】ReAct智能体实现(react_framework.py)。
import json from typing import List, Dict, Any, Optional, Callable class Tool: """表示一个可被智能体调用的工具""" def __init__(self, name: str, description: str, func: Callable): self.name = name self.description = description self.func = func def run(self, parameters: Dict) -> Any: return self.func(**parameters) class ReActAgent: """实现Reasoning+Acting循环的智能体""" def __init__(self, tools: List[Tool], llm_model: Callable): self.tools = {tool.name: tool for tool in tools} self.llm_model = llm_model self.max_iterations = 10 def _parse_llm_response(self, response: str) -> Dict: """解析大语言模型的输出,提取思考和行动""" try: # 简单解析,实际应用中可能需要更复杂的解析逻辑 if "Thought:" in response and "Action:" in response: thought = response.split("Thought:")[1].split("Action:")[0].strip() action_part = response.split("Action:")[1].strip() if "Action Input:" in action_part: action_name = action_part.split("Action Input:")[0].strip() action_input_str = action_part.split("Action Input:")[1].strip() try: # 尝试解析为JSON action_input = json.loads(action_input_str) except json.JSONDecodeError: # 如果不是有效的JSON,作为字符串处理 action_input = {"input": action_input_str} return { "thought": thought, "action": { "name": action_name, "parameters": action_input } } except Exception as e: print(f"解析LLM响应时出错: {e}") # 默认回退 return { "thought": "无法解析行动,直接回答", "action": None, "answer": response } def run(self, query: str) -> str: """运行ReAct循环处理用户查询""" history = [] history.append(f"用户查询: {query}") for i in range(self.max_iterations): # 构建提示 prompt = "\n".join(history) + "\n思考:" # 获取LLM响应 llm_response = self.llm_model(prompt) # 解析响应 parsed = self._parse_llm_response(llm_response) # 记录思考 history.append(f"思考: {parsed['thought']}") # 处理行动 if parsed.get("action"): action = parsed["action"] tool_name = action["name"] parameters = action["parameters"] # 记录行动 history.append(f"行动: {tool_name}, 参数: {json.dumps(parameters)}") # 执行工具 if tool_name in self.tools: try: result = self.tools[tool_name].run(parameters) history.append(f"行动结果: {result}") except Exception as e: history.append(f"行动执行错误: {str(e)}") result = None else: history.append(f"错误: 未知工具 '{tool_name}'") result = None else: # 如果没有行动,直接返回答案 return parsed.get("answer", "无法生成答案") return "达到最大迭代次数,未找到确定答案" # 示例工具实现 def get_weather(city: str) -> str: """获取指定城市的天气信息""" # 实际应用中这里会调用天气API weather_data = { "北京": "晴朗,25°C", "上海": "多云,28°C", "广州": "小雨,27°C" } return weather_data.get(city, "未知天气") def search_wikipedia(query: str) -> str: """在维基百科上搜索信息""" # 实际应用中这里会调用维基百科API # 简化示例,返回一些模拟数据 if "Python" in query: return "Python是一种广泛使用的高级编程语言,由Guido van Rossum于1989年圣诞节期间创建。" elif "人工智能" in query: return "人工智能是指计算机系统能够执行通常需要人类智能才能完成的任务的能力,如视觉感知、语音识别等。" return f"关于'{query}'的信息未找到" # 示例使用 if __name__ == "__main__": # 定义工具 tools = [ Tool("get_weather", "获取指定城市的当前天气", get_weather), Tool("search_wikipedia", "在维基百科上搜索信息", search_wikipedia) ] # 模拟LLM模型 def mock_llm_model(prompt: str) -> str: """模拟大语言模型的输出""" if "天气" in prompt: return """思考: 用户想了解北京的天气,我可以使用get_weather工具获取信息 行动: get_weather Action Input: {"city": "北京"}""" elif "Python" in prompt or "人工智能" in prompt: return """思考: 用户的问题需要百科知识,我可以使用search_wikipedia工具查找信息 行动: search_wikipedia Action Input: {"query": "Python"}""" return "直接回答: 我不知道这个问题的答案" # 创建智能体 agent = ReActAgent(tools, mock_llm_model) # 测试运行 weather_query = "北京现在的天气如何?" print(f"查询: {weather_query}") print(f"回答: {agent.run(weather_query)}") python_query = "Python是什么时候创建的?" print(f"\n查询: {python_query}") print(f"回答: {agent.run(python_query)}")运行代码,输出如下:
查询: 北京现在的天气如何? 回答: 思考: 用户想了解北京的天气,我可以使用get_weather工具获取信息 行动: get_weather Action Input: {"city": "北京"} 查询: Python是什么时候创建的? 回答: 思考: 用户的问题需要百科知识,我可以使用search_wikipedia工具查找信息 行动: search_wikipedia Action Input: {"query": "Python"}ReAct框架通过将推理与行动相结合,为AI智能体开发提供了强大的范式。其关键优势在于:
在实际应用中,可以根据具体需求调整推理和行动的平衡,并不断优化工具集和提示工程,以获得最佳性能。