LangChain 函数调用(Function Calling)学习总结

5 阅读3分钟

LangChain 函数调用(Function Calling)学习总结

一、这是什么?(概念解释)

函数调用(Function Calling) 是一种让大语言模型(LLM)能够与外部工具交互的能力。

简单来说:

  • 普通的 LLM 只能"说"(输出文字)
  • 有了函数调用,LLM 可以"做"(调用外部 API、查询数据库、执行工具等)

在 LangChain 中,通过 bind_tools() 方法将自定义工具绑定到 ChatModel 上,让模型可以根据用户问题自动选择合适的工具来执行。


二、有什么用?(应用场景)

场景说明
实时信息查询查询天气、股票、新闻等实时数据
网络搜索调用 Google 搜索获取最新资讯
数据库操作查询/更新数据库中的数据
复杂计算调用计算器、数学库进行精确计算
系统操作读取文件、发送邮件、控制 IoT 设备
多步骤任务组合多个工具完成复杂任务

三、完整示例代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import os
from typing import Type, Any
import requests
from langchain_core.messages import ToolMessage
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.tools import BaseTool
from langchain_openai import ChatOpenAI
from pydantic import Field, BaseModel
import dotenv

dotenv.load_dotenv()

# ============ 第一步:定义工具 ============

# 1. 定义工具的参数 Schema(用 Pydantic 描述)
class WeatherArgsSchema(BaseModel):
    city: str = Field(description="需要查询天气的目标城市,例如:北京")

# 2. 创建自定义工具类(继承 BaseTool)
class WeatherTool(BaseTool):
    """查询指定城市的天气预报"""
    name: str = "weather_query"
    description: str = "当你需要查询天气信息时使用此工具"
    args_schema: Type[BaseModel] = WeatherArgsSchema

    def _run(self, city: str) -> str:
        # 这里调用实际的天气 API
        return f"{city}今天晴天,温度 25°C"

# ============ 第二步:创建模型并绑定工具 ============

# 初始化工具
weather_tool = WeatherTool()
tools = [weather_tool]

# 创建 ChatModel
llm = ChatOpenAI(model="gpt-4o-mini")

# 将工具绑定到模型上(关键步骤!)
llm_with_tools = llm.bind_tools(tools=tools)

# ============ 第三步:创建执行链 ============

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个智能助手,可以调用工具帮助用户"),
    ("human", "{query}")
])

chain = {"query": RunnablePassthrough()} | prompt | llm_with_tools

# ============ 第四步:调用并处理工具结果 ============

query = "北京今天天气怎么样?"
response = chain.invoke(query)

# 检查模型是否想要调用工具
if response.tool_calls:
    # 模型决定调用工具
    print(f"模型想调用工具: {response.tool_calls}")

    # 手动执行工具
    for tool_call in response.tool_calls:
        tool_result = weather_tool.invoke(tool_call['args'])
        print(f"工具返回: {tool_result}")

    # 将工具结果反馈给模型,生成最终回答
    final_response = llm.invoke([
        *prompt.invoke(query).to_messages(),
        response,
        ToolMessage(content=tool_result, tool_call_id=tool_call['id'])
    ])
    print(f"最终回答: {final_response.content}")
else:
    # 模型直接回答
    print(f"直接回答: {response.content}")

四、函数调用流程图

┌─────────────────────────────────────────────────────────────────────────┐
│                        函数调用完整流程                                   │
└─────────────────────────────────────────────────────────────────────────┘

  用户提问                         LLM 处理                    工具执行
     │                              │                           │
     ▼                              │                           │
  "北京天气怎么样?" ────────────────▶│ 分析问题                     │
     │                              │                           │
     │                              │ 需要天气信息 ─────────────▶│
     │                              │                           │
     │                              │ 返回 tool_calls:          │
     │                              │ [{name: "weather_query",  │
     │                              │   args: {city: "北京"}}]  │
     │                              │◀──────────────────────────│
     │                              │                           │
     │                              │ 解析 tool_calls            │
     │                              │                           │
     │                              │ 调用工具 ──────────────────▶│
     │                              │                           │ 执行天气API
     │                              │◀──────────────────────────│
     │                              │                           │
     │                              │ 获取工具结果               │
     │                              │ "北京:晴天,25°C"          │
     │                              │                           │
     │                              │ 再次调用 LLM               │
     │                              │ (上下文 + 工具结果)         │
     │                              │                           │
     │◀─────────────────────────────│ 生成最终回答               │
     │                              │                           │
  "根据查询结果,          │                           │
   北京今天是晴天,        │                           │
   温度25度。"             │                           │
     │                              │                           │


  ┌─────────────────────────────────────────────────────────────────────────┐
  │                         核心要点                                         │
  └─────────────────────────────────────────────────────────────────────────┘

  1. bind_tools() - 让 LLM 知道有哪些工具可用
  2. tool_calls   - LLM 返回的工具调用指令
  3. 工具执行     - 手动执行工具获取实际结果
  4. 结果反馈     - 将工具结果返回给 LLM 生成最终回答