Skip to content

如何在 LangChain 中实现函数调用 Function Calling? ​

  • 标签:LangChain、Function Calling

🏛 业务架构师 ​

在 LangChain 里实现 Function Calling,流程四步(0.2/0.3 版现代写法):

1. 定义工具:

python
from langchain_core.tools import tool

@tool
def query_inventory(sku: str) -> str:
    """查询指定 SKU 的库存数量。sku 为商品编码,如 'A1024'。"""
    return inventory_service.get(sku)

2. 绑定到模型:model_with_tools = llm.bind_tools([query_inventory])——工具的 Schema 自动随请求传给模型(底层就是厂商的 Function Calling API)。

3. 调用与执行:模型返回 AIMessage,检查 tool_calls 字段——有调用意图就执行:

python
for tc in ai_msg.tool_calls:
    result = query_inventory.invoke(tc["args"])
    messages.append(ToolMessage(content=result, tool_call_id=tc["id"]))

把结果以 ToolMessage 回填,再调模型生成最终回答。

4. 循环(Agent 化):把"调用→执行→回填→再调用"放进循环直到模型不再发起工具调用——手写循环用 create_react_agent 或 LangGraph 的 ToolNode 更省事。

生产化要点(业务视角):docstring 是给模型看的说明书,直接决定选对率;工具执行前做参数校验与鉴权;返回结果限幅(大结果截断防撑爆上下文);全链路记日志(哪个用户、调了什么工具、什么参数)——审计与排障都靠它。工具多时(>10 个)考虑分组路由,工具越多误选率越高。

🏗 系统架构师 ​

LangChain 实现 Function Calling 我给现代姿势(1.x,LCEL + create_agent / bind_tools):

基础绑定:

python
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool

@tool
def get_weather(city: str) -> str:
    """查询指定城市的实时天气。"""
    return f"{city}: 晴, 22℃"

llm = ChatOpenAI(model="gpt-4o")
llm_with_tools = llm.bind_tools([get_weather])   # 工具定义注入

决策与执行循环:

python
response = llm_with_tools.invoke("北京今天热吗?")
if response.tool_calls:                          # 模型产生调用意图
    for tc in response.tool_calls:
        result = get_weather.invoke(tc["args"])  # 应用侧执行
    # 结果以 ToolMessage 回填,再调模型出最终答案

Agent 全托管:

python
from langchain.agents import create_agent
agent = create_agent(llm, tools=[get_weather])
agent.invoke({"messages": [("user", "北京适合跑步吗?")]})

架构师视角的要点:

  • 模型只产意图、框架执行:tool_calls 是结构化输出(名称+参数),执行由你的代码完成——安全边界(校验、权限、审计)加在这层,LangChain 的 before_model/after_model 钩子或 LangGraph 的 ToolNode 可插拔治理;
  • 描述质量 = 准确率:docstring 就是给模型的 API 文档;
  • 结构化输出配合:工具参数本身走 Schema 校验,失败信息结构化回喂让模型自救;
  • 生产推荐 LangGraph 的 agent 预制件(create_react_agent):循环、消息状态、持久化开箱即用,比手写 while 循环可控。

💻 全栈开发专家 ​

LangChain 实现 Function Calling 的标准链路(新版 API):

python
from langchain_core.tools import tool

@tool
def query_weather(city: str, date: str) -> str:
    """查询指定城市日期的天气。city:城市名; date:yyyy-MM-dd"""
    return weather_api.get(city, date)

@tool
def create_order(sku: str, count: int) -> str:
    """为当前用户下单。sku:商品编码; count:数量"""
    return order_service.create(sku, count)

llm_with_tools = llm.bind_tools([query_weather, create_order])

# Agent 循环(或直接用 create_tool_calling_agent)
msgs = [HumanMessage("北京明天适合跑步吗?顺便帮我买瓶水,SKU=B100")]
ai_msg = llm_with_tools.invoke(msgs)
msgs.append(ai_msg)

for tool_call in ai_msg.tool_calls:          # 模型可能一次调多个
    result = {"query_weather": query_weather,
              "create_order": create_order}[tool_call["name"]].invoke(tool_call["args"])
    msgs.append(ToolMessage(content=str(result),
                            tool_call_id=tool_call["id"]))  # id 必须对应
final = llm_with_tools.invoke(msgs)           # 基于结果生成回答

关键工程点:

  1. ToolMessage 的 tool_call_id 必须回填模型给的 id,错一个模型直接报错;
  2. 工具执行要 try/except——错误信息转成文本回喂(模型能重试或解释),别让异常炸掉循环;
  3. 并行调用:模型单轮可能返回多个 tool_calls,逐个执行(或并行)后统一回填;
  4. 写操作(create_order)生产上要加:参数校验、幂等键、确认门;
  5. 简单场景用上面的手动循环就够,需要多轮自主决策再上 create_tool_calling_agent/LangGraph。