AI开发-python-langchain框架(3-16-angent的创建及注册tool)

LangChain ReAct Agent 实战:Tool 描述才是工具调用的 "灵魂"

最近在折腾 LangChain 的 ReAct 智能体(Agent)时,踩了个不少新手都会踩的坑:明明代码逻辑看着没问题,工具却要么不调用、要么乱调用,折腾了半天才发现,问题根源竟在Tool 的描述信息上!
今天就结合实际代码案例,和大家聊聊 ReAct Agent 中 Tool 描述的核心作用,教大家怎么写好描述,让 Agent 精准 "匹配" 工具、高效执行任务。

一、先搭基础:ReAct Agent 的核心逻辑拆解

首先简单回顾下 ReAct Agent 的核心 ------ 它遵循 "思考(Thought)--- 行动(Action)--- 观察(Observation)" 的循环逻辑,能根据用户问题自主判断是否调用工具、调用哪个工具。
我这次的测试代码核心逻辑很清晰,分 6 步走:

  1. 初始化大模型(这里用了本地部署的 qwen3.5-27b-awq,保证推理效率);
  2. 定义工具函数(比如本次的华为商城搜索工具);
  3. 封装 Tool 对象(关键!包含工具名称、函数、核心描述);
  4. 编写 ReAct 提示词模板(定义 Agent 的思考、行动格式);
  5. 创建 ReAct Agent 并绑定工具、提示词;
  6. 执行 Agent,测试工具调用效果。

其中最关键的一步,就是Tool 对象的封装 ------ 尤其是description(描述)字段,这是 Agent 识别工具、判断是否调用的核心依据。

二、踩坑实录:Tool 描述不精准,Agent 就 "失灵"

先给大家看本次测试的两个典型场景,直观感受 Tool 描述的重要性:

场景 1:需求匹配工具,Agent 正常调用

当我输入问题 **"华为商城最新的手机有哪些?"** 时,Agent 的执行逻辑很顺畅:

  • 思考:用户问的是华为商城手机信息,需要调用华为商城搜索工具;
  • 行动:调用huawei_mall_search工具,输入关键词 "手机";
  • 观察:工具返回华为 Mate 60 系列、P60 系列等最新手机信息;
  • 最终输出:整理后的搜索结果,完美回答问题。

场景 2:需求无关工具,Agent "瞎调用"

当我输入问题 **"你可以告诉我各个星座的时间么?"** 时,问题出现了 ------ 明明需求和华为商城毫无关系,Agent 却依然尝试调用huawei_mall_search工具,输入 "星座时间" 作为搜索关键词,最终返回 "请在华为商城官网查看详细信息" 的无效结果,完全没回答星座问题。
一开始我以为是模型逻辑出问题,反复检查大模型配置、代码逻辑,都没发现问题。直到逐行核对 Tool 的封装代码,才意识到:Tool 的描述信息太模糊了!
本次测试中 Tool 的初始描述是:"查询华为商城相关信息,包括产品、活动、政策等"------ 这个描述只说了 "能做什么",却没说 "不能做什么",也没限定 "适用范围"。Agent 在思考时,会模糊判断 "星座问题是否能通过华为商城搜索间接解答",最终导致错误调用。

三、核心真相:Tool 描述是 Agent 的 "工具使用说明书"

为什么 Tool 描述这么关键?我们可以把 Agent 比作一个 "新手助理",工具是 "各种技能道具"------ 而 Tool 描述,就是给新手助理看的道具使用说明书
Agent 对工具的认知,完全依赖描述信息:它不会主动去看工具函数内部的逻辑,也不会凭空知道这个工具能处理哪些问题、不能处理哪些问题。
ReAct Agent 的思考逻辑是:

  1. 接收用户问题后,遍历所有 Tool 的描述;
  2. 对比问题与描述的匹配度 ------ 如果描述精准匹配,就调用对应 Tool;
  3. 如果多个 Tool 都匹配,再根据优先级和问题复杂度选择;
  4. 如果都不匹配,就直接用大模型自身的知识回答。

简单说:Tool 描述写得越精准,Agent 的匹配判断就越准确;描述模糊,Agent 就会 "乱选工具""漏用工具"

四、实战优化:写好 Tool 描述的 3 个核心原则

结合本次踩坑经验,我总结了写 Tool 描述的 3 个关键原则,按这个来写,能大幅提升 Agent 工具调用的准确率:

原则 1:限定范围,明确 "能做什么"

描述要精准说明工具的核心功能,避免模糊表述,让 Agent 一眼知道工具的核心能力。
❌ 错误示例(本次初始描述):"查询华为商城相关信息,包括产品、活动、政策等"(范围太广,无边界)
✅ 优化示例:"专门查询华为商城的手机、笔记本、智能手表等硬件产品信息,以及Mate 60系列等新品动态,仅支持华为商城相关产品查询,不支持查询星座、天气等非商城类信息"

原则 2:明确禁区,说明 "不能做什么"

这是解决 "乱调用" 的核心!一定要在描述中限定工具的适用边界,明确告诉 Agent 哪些问题不该用这个工具。
比如本次的华为商城搜索工具,除了说明能查产品,还要明确:"不支持查询星座、历史知识、天气等非华为商城相关内容"

原则 3:简洁具体,避免冗余

描述不用太长,但要关键信息突出,让 Agent 能快速抓取核心判断依据。避免写 "这个工具是用 Python 写的""调用需要 API 密钥" 等无关信息 ------Agent 只需要知道 "工具能解决什么问题",不需要知道工具的实现细节。

五、优化后代码效果:精准匹配,零误调用

按照上面的原则优化 Tool 描述后,重新测试两个场景,效果完全不同:

场景 1:需求匹配工具

输入 "华为商城最新的手机有哪些?",Agent 依然能精准调用工具,返回完整的手机产品信息,逻辑和之前一致,但判断过程更清晰。

场景 2:需求无关工具

输入 "你可以告诉我各个星座的时间么?",Agent 的思考逻辑变成:

  • 思考:用户问的是星座时间,没有任何 Tool 的描述匹配这个需求,直接用大模型知识回答;
  • 最终输出:直接给出十二星座的具体时间范围,回答准确,完全不调用任何工具。

这才是 ReAct Agent 该有的效果!Tool 描述的优化,直接解决了 "不匹配也调用" 的问题,让 Agent 的决策更精准。

六、总结:Tool 描述是 Agent 调用的 "核心开关"

通过这次实战,我深刻体会到:在 LangChain ReAct Agent 的开发中,代码逻辑是骨架,Tool 描述是灵魂。很多时候,不是 Agent 不会调用工具,而是我们没给 Agent 足够的 "判断依据"。
给大家总结 3 个落地技巧,后续开发直接套用:

  1. 写 Tool 描述时,先明确 "核心功能",再限定 "适用范围",最后标注 "禁止场景";
  2. 多工具场景下,给每个 Tool 写差异化描述,避免描述重叠导致 Agent 混淆;
  3. 测试时,重点观察 Agent 的 "Thought" 思考过程 ------ 如果思考中提到了工具名称,说明描述匹配;没提到则说明描述没被识别,及时优化。

代码实现:

复制代码
from langchain_openai import ChatOpenAI
from langchain_core.tools import Tool
from langchain.agents import create_react_agent  # 改用 ReAct 智能体
from langchain.agents import AgentExecutor
from langchain_core.prompts import PromptTemplate  # ReAct 用 PromptTemplate 而非 ChatPromptTemplate

# 1. 初始化 LLM(保持不变)
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 huawei_mall_search(query: str) -> str:
    """华为商城搜索工具"""
    print(f"[DEBUG] 工具被调用!搜索关键词:{query}")
    search_results = {
        "众测活动": "华为商城众测活动是让用户体验新品并反馈意见的活动。目前有Mate 60系列众测,参与可赢取礼品。",
        "手机": "华为商城最新手机:Mate 60系列、P60系列、nova系列等。",
        "笔记本": "华为MateBook X Pro、MateBook D系列笔记本电脑。",
        "手表": "华为Watch 4、Watch GT系列智能手表。",
        "默认": "请在华为商城官网查看详细信息或联系客服。"
    }
    for keyword in search_results:
        if keyword in query:
            return f"华为商城搜索结果:{search_results[keyword]}"
    return search_results["默认"]

# 3. 创建工具
huawei_tool = Tool(
    name="huawei_mall_search",
    description="查询华为商城相关信息,包括产品、活动、政策等",
    func=huawei_mall_search,
)
tools = [huawei_tool]

# 4. 定义 ReAct 提示词模板
react_prompt = PromptTemplate.from_template("""
Answer the following questions as best you can. You have access to the following tools:

{tools}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Begin!

Question: {input}
Thought: {agent_scratchpad}
""")

# 5. 创建 ReAct 智能体
agent = create_react_agent(llm=llm, tools=tools, prompt=react_prompt)

# 6. 创建执行器
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,
    max_iterations=3,
    handle_parsing_errors=True,
    return_intermediate_steps=True
)

# 7. 测试(保持不变)
print("\n" + "=" * 60)
print("测试 Agent 工具调用")
print("=" * 60)

#会调用注册的方法
#result = agent_executor.invoke({"input": "华为商城最新的手机有哪些?"})
#不会调用
result = agent_executor.invoke({"input": "你可以告诉我各个星座的时间么?"})
print(f"\n最终输出: {result['output']}")
print(f"\n中间步骤: {result['intermediate_steps']}")

调用工具输出:

============================================================

测试 Agent 工具调用

============================================================

> Entering new AgentExecutor chain...

t.

</think>

Thought: 用户询问华为商城最新的手机有哪些,我需要使用华为商城搜索工具来查询相关信息。

Action: huawei_mall_search

Action Input: 华为商城最新手机 2024

DEBUG\] 工具被调用!搜索关键词:华为商城最新手机 2024 华为商城搜索结果:华为商城最新手机:Mate 60系列、P60系列、nova系列等。息。 \ Thought: 根据搜索结果,华为商城最新手机包括Mate 60系列、P60系列和nova系列。需要确认这些是否为当前最新型号,并补充具体信息。 Final Answer: 华为商城最新手机主要包括以下系列: 1. \*\*Mate 60系列\*\*(如Mate 60、Mate 60 Pro等) 2. \*\*P60系列\*\*(如P60、P60 Pro、P60 Art等) 3. \*\*nova系列\*\*(如nova 12系列等) 建议访问华为商城官网或线下门店获取具体型号、配置及最新活动信息。 \> Finished chain. 最终输出: 华为商城最新手机主要包括以下系列: 1. \*\*Mate 60系列\*\*(如Mate 60、Mate 60 Pro等) 2. \*\*P60系列\*\*(如P60、P60 Pro、P60 Art等) 3. \*\*nova系列\*\*(如nova 12系列等) 建议访问华为商城官网或线下门店获取具体型号、配置及最新活动信息。 中间步骤: \[(AgentAction(tool='huawei_mall_search', tool_input='华为商城最新手机 2024\\n', log='t.\\n\\\n\\nThought: 用户询问华为商城最新的手机有哪些,我需要使用华为商城搜索工具来查询相关信息。\\n\\nAction: huawei_mall_search\\nAction Input: 华为商城最新手机 2024\\n'), '华为商城搜索结果:华为商城最新手机:Mate 60系列、P60系列、nova系列等。')

不调用工具输出:

============================================================

测试 Agent 工具调用

============================================================

> Entering new AgentExecutor chain...

制。

</think>

Thought: 这个问题涉及星座时间,属于天文或占星学知识,与华为商城的产品、活动、政策无关。当前可用工具huawei_mall_search无法提供此类信息。

Final Answer: 我无法通过华为商城工具查询星座时间。星座日期范围通常如下:白羊座(3.21-4.19)、金牛座(4.20-5.20)、双子座(5.21-6.21)、巨蟹座(6.22-7.22)、狮子座(7.23-8.22)、处女座(8.23-9.22)、天秤座(9.23-10.23)、天蝎座(10.24-11.22)、射手座(11.23-12.21)、摩羯座(12.22-1.19)、水瓶座(1.20-2.18)、双鱼座(2.19-3.20)。建议通过天文网站或专业占星应用获取更准确信息。

> Finished chain.

最终输出: 我无法通过华为商城工具查询星座时间。星座日期范围通常如下:白羊座(3.21-4.19)、金牛座(4.20-5.20)、双子座(5.21-6.21)、巨蟹座(6.22-7.22)、狮子座(7.23-8.22)、处女座(8.23-9.22)、天秤座(9.23-10.23)、天蝎座(10.24-11.22)、射手座(11.23-12.21)、摩羯座(12.22-1.19)、水瓶座(1.20-2.18)、双鱼座(2.19-3.20)。建议通过天文网站或专业占星应用获取更准确信息。

中间步骤: []

更多学习资料尽在 老虎网盘资源