一、先搞懂:ZeroShot_ReAct 到底是什么?
首先要明确两个核心概念的结合------ZeroShot(零样本)与ReAct(推理+行动),二者结合才构成了这个Agent的强大能力:
1. ReAct:让AI像人一样"思考+行动"
ReAct是一种大模型推理框架,核心逻辑源于人类解决问题的习惯:先思考(Thought),再行动(Action),根据行动结果(Observation)再调整思考,循环往复直到得出答案。这种框架打破了"大模型只做文本生成"的局限,让AI具备了"主动调用外部工具"的能力,而不是单纯依赖自身知识库回答问题。
比如面对"现在几点了"这个问题,AI不会凭空猜测,而是会思考"我需要获取当前时间,这需要调用专门的工具",然后执行调用操作,拿到结果后再整理成最终答案------这就是ReAct的核心价值:让推理与行动协同,解决大模型"不会实时交互、不会计算"的痛点。
2. ZeroShot:无需训练,即插即用
ZeroShot(零样本)则解决了"使用门槛"的问题。传统Agent可能需要提前准备大量训练样本,告诉AI"什么场景用什么工具",而ZeroShot_ReAct Agent完全不需要------它仅通过工具的描述信息,就能自主判断"当前问题是否需要调用工具、调用哪个工具、如何传递参数"。
简单来说,你只需要告诉Agent"有一个工具能获取当前时间,无需参数",它就能在遇到"查询时间"的问题时,自动调用这个工具;遇到"数学计算"的问题时,自动匹配计算工具------这就是它最便捷的地方:无需训练,配置好工具和提示词,就能直接使用。
ZeroShot_ReAct 核心优势总结
-
零样本适配:无需训练样本,仅通过工具描述即可实现工具调用决策,降低开发成本;
-
推理透明:全程遵循"思考-行动-观察"的流程,可清晰追溯AI的决策逻辑,便于调试;
-
灵活扩展:新增工具时,只需添加工具描述和实现逻辑,无需修改Agent核心代码;
-
兼容性强:可适配各类兼容OpenAI API的大模型,无论是在线模型还是本地部署的模型(如Qwen、DeepSeek等)都能无缝对接。
二、实战拆解:ZeroShot_ReAct Agent 实现步骤
结合本次实战案例,我们搭建的Agent能实现两个核心功能:获取当前系统时间、执行数学表达式计算。整个实现过程分为4个核心步骤,逻辑清晰,可直接复用思路扩展更多工具。
步骤1:配置大模型(LLM)------ Agent的"大脑"
大模型是ZeroShot_ReAct Agent的核心,负责"思考决策":判断是否需要调用工具、调用哪个工具、如何处理工具返回结果。本次实战选用了本地部署的Qwen3.5模型,通过兼容OpenAI API的方式接入LangChain。
核心配置思路:只需指定模型的API密钥、部署地址、模型名称,以及温度(temperature)和最大令牌数(max_tokens)------温度越低,AI的决策越稳定,避免随机猜测;最大令牌数则限制单次输出的长度,防止冗余。
这里的关键的是:只要模型兼容OpenAI API,无论你用的是在线模型(如GPT、DeepSeek)还是本地部署的模型(如Ollama部署的Qwen、Llama),都能直接替换使用,无需修改后续核心逻辑。
步骤2:定义工具------ Agent的"手脚"
工具是Agent与外部交互的载体,也是ZeroShot_ReAct实现"行动"的核心。每个工具都需要明确三个关键信息:工具名称、工具功能(函数实现)、工具描述------这三个信息,尤其是工具描述,直接决定了AI能否正确判断何时调用该工具。
本次实战定义了两个工具,思路可直接复用:
-
时间工具:负责获取当前系统时间,无需输入参数,工具描述需明确"无需参数",避免AI传递多余信息;
-
计算工具:负责执行数学表达式计算,支持加减乘除和括号,工具描述需明确支持的表达式类型,让AI知道该工具能解决什么问题、需要传递什么格式的输入。
这里有一个细节:工具的描述必须简洁、准确,避免模糊表述。因为ZeroShot_ReAct Agent正是通过解析工具描述,来判断"当前问题是否需要调用该工具"------描述越清晰,AI的决策越准确,减少调用错误。同时,工具的函数实现需考虑安全性,比如计算工具需限制可执行的函数,避免恶意代码注入。
步骤3:自定义ReAct提示模板------ Agent的"行为准则"
提示模板(Prompt)是ZeroShot_ReAct Agent的"规则手册",核心作用是告诉AI"如何思考、如何输出、如何调用工具"。因为大模型本身并不知道"ReAct流程",也不知道"如何规范调用工具",需要通过提示模板来约束其行为。
本次实战的提示模板,重点做了两个核心约束(也是ZeroShot_ReAct能正常工作的关键):
-
格式约束:明确规定"需要调用工具"和"无需调用工具"的输出格式,比如调用工具时必须按照"思考-行动-输入"的三行格式输出,不能添加任何多余文字,确保Agent能正确解析AI的输出;
-
工具约束:明确告知AI可用的工具名称和工具功能,并且强调"工具名称必须完全匹配,区分大小写",避免AI因名称错误导致调用失败。
此外,提示模板中还预留了"历史执行记录"的位置,用于存储AI的思考、行动和观察记录,让AI能根据上一步的结果调整下一步的决策------这正是ReAct框架"循环推理"的核心实现。
步骤4:创建Agent和执行器------ 让Agent"动起来"
有了"大脑"(大模型)、"手脚"(工具)和"行为准则"(提示模板),就可以将三者组装成完整的ZeroShot_ReAct Agent,再通过执行器(AgentExecutor)来运行任务。
核心思路:使用LangChain提供的create_react_agent方法,将大模型、工具、提示模板整合,生成Agent;再通过AgentExecutor来控制Agent的执行流程,比如设置最大迭代次数(防止死循环)、开启详细日志(便于调试)、自动处理解析错误(提升稳定性)。
执行器的作用相当于"管家",负责调度Agent的思考和行动,确保整个流程有序进行:接收用户问题 → Agent思考决策 → 调用工具(如有) → 处理工具返回结果 → 输出最终答案。
三、关键细节与避坑指南
在搭建ZeroShot_ReAct Agent的过程中,有几个细节直接影响Agent的稳定性和准确性,新手很容易踩坑,这里重点提醒:
-
工具描述要精准:避免模糊表述,比如"计算工具"不能只写"能计算",要明确支持的运算类型、输入格式,否则AI可能无法判断何时调用;
-
格式约束要严格:AI的输出格式必须和提示模板中规定的一致,否则执行器无法解析,会导致调用失败------这也是为什么提示模板中要强调"不要添加任何额外文字";
-
大模型选择要适配:建议选择推理能力较强的模型,比如Qwen3.5、DeepSeek等,避免因模型推理能力不足,导致无法正确判断是否需要调用工具;
-
安全性要考虑:如果工具涉及外部调用或代码执行(如计算工具),需做好安全防护,比如限制可执行的函数、过滤危险输入,避免恶意攻击。
四、总结与扩展方向
本次实战搭建的ZeroShot_ReAct Agent,虽然功能简单,但已经覆盖了核心实现逻辑------它的本质就是"通过提示模板约束大模型,让大模型根据工具描述,自主完成'思考-行动-观察'的循环,实现零样本工具调用"。
对比传统的工具调用方式,ZeroShot_ReAct的优势在于"灵活、低成本":无需训练样本,新增工具时只需添加工具描述和实现逻辑,就能快速适配新的需求;而ReAct框架则让AI的决策过程更加透明,便于调试和优化,这也是其在企业智能决策、自动化流程等场景中广泛应用的原因之一。
后续扩展方向也很明确:
-
扩展工具:新增天气查询、知识库检索、文件读取等工具,实现更复杂的任务;
-
优化提示模板:调整思考逻辑的描述,提升AI的决策准确性;
-
对接更多模型:尝试接入不同的大模型,对比其在ZeroShot_ReAct场景下的表现;
-
增加记忆功能:结合LangChain的记忆组件,让Agent能记住历史对话,实现多轮交互下的工具调用。
ZeroShot_ReAct Agent是LangChain Agent体系中最基础也最实用的方案,掌握它的实现思路,能为后续搭建更复杂的智能Agent(如多Agent协同、带记忆的Agent)打下坚实基础。
如果觉得本文对你有帮助,欢迎点赞、收藏,后续会持续分享LangChain实战技巧,一起玩转大模型应用开发~
代码实现:
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | import os from dotenv ``import load_dotenv from langchain.agents ``import AgentExecutor, create_react_agent from langchain_core.tools ``import Tool from langchain_openai ``import ChatOpenAI from langchain_core.prompts ``import PromptTemplate ``# ← 用于自定义 prompt # 加载环境变量 load_dotenv() # ======================== # 1. 配置 LLM(Ollama 兼容 OpenAI API) # ======================== DEEPSEEK_API_KEY ``= "123" # 替换为实际的 API Key llm ``= ChatOpenAI( ``api_key``=``DEEPSEEK_API_KEY, ``base_url``=``"http://192.168.0.100:8085/v1"``, ``model``=``"qwen3.5-27b-awq"``, ``temperature``=``0.3``, ``max_tokens``=``1024``, ) # ======================== # 2. 定义工具 # ======================== def get_current_time(``*``args, ``*``*``kwargs): ``from datetime ``import datetime ``current_time ``= datetime.now().strftime(``"%Y年%m月%d日 %H:%M:%S"``) ``return f``"当前时间:{current_time}" def calculate_math_expression(expression: ``str``): ``try``: ``# 构建安全的白名单内置函数 ``safe_funcs ``= {} ``for func_name ``in (``"abs"``, ``"round"``, ``"min"``, ``"max"``, ``"pow"``): ``if hasattr``(__builtins__, func_name): ``safe_funcs[func_name] ``= getattr``(__builtins__, func_name) ``# 执行安全计算 ``result ``= eval``(expression, {``"__builtins__"``: {}}, safe_funcs) ``return f``"数学表达式计算结果:{expression} = {result}" ``except Exception as e: ``return f``"计算失败,错误信息:{str(e)}" tools ``= [ ``Tool( ``name``=``"GetCurrentTime"``, ``func``=``get_current_time, ``description``=``"获取当前系统时间,无需任何输入参数" ``), ``Tool( ``name``=``"CalculateMathExpression"``, ``func``=``calculate_math_expression, ``description``=``"计算一个数学表达式,例如 '100 * (25 + 15) / 4 - 80',仅支持 + - * / 和括号" ``) ] # ======================== # 3. 自定义 ReAct 提示模板(中文 + 严格格式约束) # ======================== react_prompt_template ``= """你是一个智能助手,必须严格遵守以下交互协议: ## 规则 1. 如果需要使用工具,请**严格按照以下三行格式输出**,不要添加任何额外文字、标点、说明或自然语言: Thought: 我需要使用工具来解决问题。 Action: 工具名称 Action Input: 工具输入内容 2. 如果不需要工具,直接输出: Thought: 我可以直接回答。 Final Answer: 你的最终答案 ## 可用工具 {tools} ## 合法工具名称(必须完全匹配,区分大小写): {tool_names} ## 用户问题 {input} ## 历史执行记录(如有) {agent_scratchpad} """ # 创建 PromptTemplate,确保包含所有必要变量 prompt ``= PromptTemplate( ``input_variables``=``[``"tools"``, ``"tool_names"``, ``"input"``, ``"agent_scratchpad"``], ``template``=``react_prompt_template ) # ======================== # 4. 创建 Agent 和执行器 # ======================== agent ``= create_react_agent( ``llm``=``llm, ``tools``=``tools, ``prompt``=``prompt ) agent_executor ``= AgentExecutor( ``agent``=``agent, ``tools``=``tools, ``verbose``=``True``, ``handle_parsing_errors``=``True``, ``# 自动处理解析错误并重试 ``max_iterations``=``5``, ``# 防止死循环 ) # ======================== # 5. 执行任务 # ======================== if __name__ ``=``= "__main__"``: ``print``(``"===== 任务1:获取当前时间 ====="``) ``agent_executor.invoke({``"input"``: ``"请告诉我现在的时间是多少?"``}) ``print``(``"\n" + "=" * 50 + "\n"``) ``print``(``"===== 任务2:数学计算 ====="``) ``agent_executor.invoke({``"input"``: ``"请帮我计算 100 * (25 + 15) / 4 - 80 的结果是多少?"``}) |
结果输出:
===== 任务1:获取当前时间 =====
> Entering new AgentExecutor chain...
写。
</think>
Thought: 我需要使用工具来解决问题。
Action: GetCurrentTime
Action Input:当前时间:2026年04月07日 16:49:28案。
</think>
Thought: 我可以直接回答。
Final Answer: 当前时间是2026年04月07日 16:49:28。
> Finished chain.
==================================================
===== 任务2:数学计算 =====
> Entering new AgentExecutor chain...
0'
</think>
Thought: 我需要使用工具来解决问题。
Action: CalculateMathExpression
Action Input: 100 * (25 + 15) / 4 - 80数学表达式计算结果:100 * (25 + 15) / 4 - 80 = 920.0题。
</think>