Tool 是 LangChain Agent 调用外部世界的方式。Function Calling 是 LLM 调 Tool 的底层协议。
Tool = 让 LLM 能够执行外部动作的函数封装。
1 2 3 4 5 6
| 传统 LLM: 输入 → LLM → 输出文本
带 Tool 的 LLM: 输入 → LLM → [需要执行 search] → search() → 结果 → LLM → 最终回答 ↑ 工具调用 ↑ 工具返回
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from langchain_core.tools import tool
@tool def search_wiki(query: str) -> str: """在维基百科搜索相关词条""" return f"关于'{query}'的搜索结果..."
@tool def calculate(expression: str) -> float: """执行数学计算""" return eval(expression)
tools = [search_wiki, calculate]
|
1 2 3 4 5 6 7 8
| from langchain_core.tools import StructuredTool
search_tool = StructuredTool.from_function( name="search_wiki", description="在维基百科搜索相关词条", func=lambda query: wikipedia.search(query), return_direct=False )
|
1 2 3 4 5 6 7 8 9 10
| from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage
llm = ChatOpenAI(model="gpt-4o")
llm_with_tools = llm.bind_tools(tools)
llm_with_tools = llm.with_configurable_tools(tools=[search_wiki, calculate])
|
调用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| response = llm_with_tools.invoke("查一下水的沸点是多少")
print(response)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from langchain_core.messages import HumanMessage, AIMessage, ToolMessage
messages = [HumanMessage(content="水的沸点是多少")]
ai_response = llm_with_tools.invoke(messages) messages.append(ai_response)
tool_result = search_wiki.invoke(ai_response.tool_calls[0].args) messages.append(ToolMessage(content=tool_result, tool_call_id=ai_response.tool_calls[0].id))
final_response = llm.invoke(messages) print(final_response.content)
|
create_react_agent(自动完成上述循环)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from langchain_openai import ChatOpenAI from langchain_core.tools import tool from langchain.agents import create_react_agent
llm = ChatOpenAI(model="gpt-4o") agent = create_react_agent(llm, tools)
result = agent.invoke({"input": "水的沸点是多少摄氏度?加上273.15转成开尔文"})
print(result["output"])
|
输入设计原则
| 原则 | 说明 |
|---|
| 名字清晰 | search_wiki 比 search 更明确 |
| 描述详细 | 描述会发给 LLM,帮助它判断何时调用 |
| 类型严格 | 用 Pydantic 或类型注解限定输入 |
| 单一职责 | 一个 Tool 做一件事 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @tool def search_flights( origin: str, destination: str, date: str, max_price: float | None = None ) -> str: """搜索航班信息
Args: origin: 出发地机场代码(如 PEK, SHA) destination: 目的地机场代码 date: 出发日期,格式 YYYY-MM-DD max_price: 最高票价(可选) """ ...
|
输出设计原则
| 原则 | 说明 |
|---|
| 返回字符串 | Tool 的返回必须是字符串 |
| 信息完整 | 包含 LLM 回答所需的所有信息 |
| 结构化 | 尽量返回 JSON 或格式化文本 |
多个独立 Tool 可以并行执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @tool def get_weather(city: str) -> str: """获取城市天气""" ...
@tool def get_news(topic: str) -> str: """获取新闻""" ...
llm_with_tools = llm.bind_tools([get_weather, get_news]) response = llm_with_tools.invoke("北京今天天气和最新科技新闻")
|
Agent 类型选择
| Agent | 特点 | 适用场景 |
|---|
create_react_agent | ReAct(推理+行动交替) | 通用场景,最常用 |
create_conversational_agent | 对话式,有记忆 | 聊天机器人 |
create_openai_functions_agent | OpenAI Function Calling | 需要精确工具选择 |
create_self_ask_agent | Self-Ask with Search | 需要搜索验证的场景 |
MCP + LangChain(扩展)
MCP(Model Context Protocol)是新标准,让 Tool 调用更统一:
1 2 3 4 5 6 7 8 9
| from langchain_mcp_adapters import MCPClient
client = MCPClient.from_config_file("servers_config.json")
tools = client.get_tools() agent = create_react_agent(llm, tools)
|
详见 11-新兴协议/MCP协议