让 AI 不再只会聊天!Function Calling 让大模型真正“动起来”!🔥

123 阅读6分钟

这一节我们重点来聊聊 Function Calling(函数调用),它在 LLM(大语言模型)应用中至关重要,首先就是让 LLM 具备心动能力,传统的大模型只能生成文本,但无法直接执行操作。

Function Calling的优势

Function Calling 让 LLM 不只是聊天助手,而是一个可执行任务的智能体。比如:

💡 示例(无 Function Calling): 用户:“北京的天气怎么样?” LLM:“请访问 weather.com 查询。” ❌ 这并不智能!

💡 示例(有 Function Calling): 用户:“北京的天气怎么样?” LLM(调用 get_weather())→ “北京的天气是晴天 🌞。” ✅ 大模型自己调用 API 获取信息!

这样子是不是就非常智能了。第二点就是提高 LLM 准确性,大模型并不总是可靠,它会“幻觉”出错误答案,比如:生成错误的天气数据,胡编乱造编程代码,给出错误的数学计算结果,而Function Calling 让模型直接调用正确的 API,避免它自己猜测错误信息。

💡 示例:计算货币兑换 ❌ 直接让 LLM 计算:

用户:“100 美元换多少人民币?”  
LLM:“大约 650 元。”(错误,实际汇率变动)  

✅ 使用 Function Calling:

LLM(调用 `get_exchange_rate("USD", "CNY")`)
→ “根据实时汇率,100 美元 = 720 元。”(准确)  

第三点就是让LLM具备工具的使用能力:LLM 不是全能的,但可以学会使用工具!Function Calling 让大模型像“开发者”一样调用工具,比如:获取实时数据(天气、股票、新闻,操作数据库(查询用户信息、更新订单,执行代码(运行 Python 代码、Shell 命令)等等。

💡 示例:使用 Python 计算 ❌ 让 LLM 直接回答数学问题(可能错误) ✅ 让 LLM 通过 Function Calling 执行 Python 代码:

def calculate(expression):
    return eval(expression)

LLM(调用 `calculate("2+2*2")`)
→ “结果是 6。”

第四点允许LLM处理复杂任务,Function Calling 让 LLM 具备多步骤思维,能执行需要外部工具的复杂任务,比如:旅行计划(调用天气、航班、酒店 API),电商助手(查询商品、对比价格、下单),AI 代理(调用多个 API 解决复杂问题)

💡 示例:计划旅游 用户:“下周去上海旅行,帮我查天气并推荐酒店。” LLM:

调用 get_weather("上海") 查天气
调用 search_hotels("上海") 查酒店
结合结果,给出推荐

第五点让 LLM 与企业系统集成,就是和我们传统的数据库集成,function Calling 可以让 LLM 连接到企业内部系统,比如:CRM(查询客户信息),ERP(管理库存、物流),机器人(控制智能家居、自动化设备)

💡 示例:查询客户订单 用户:“查一下订单 12345 的状态。” LLM(调用 get_order_status(12345))→ “订单已发货,预计明天到达。” ✅

第六点让 LLM 变得个更智能(多工具 AI 代理)。结合 Function Calling,LLM 可以像人一样决定何时调用哪个工具,甚至自动组合多个 API 解决问题!

💡 示例:智能 AI 助手 ✅ 用户:“帮我查明天纽约的天气,并把结果发给我邮箱。” LLM: 调用 get_weather("纽约") 查天气 调用 send_email("user@example.com", "纽约天气", "明天天气晴") 发送邮件 反馈结果:“天气已发送到您的邮箱。” ✅

如果我们希望 LLM 能够像一个智能体,而不仅仅是聊天机器人,那么 Function Calling 是 必不可少的!下面我们就围绕 Function Calling 来介绍它主流使用的几种方式。

OpenAI 原生 Function Calling

直接使用 OpenAI 的 function_call 功能,让大模型自主决定是否调用函数。LangChain 对 OpenAI 的 function_call 进行了封装,我们可以用 openai.ChatOpenAI 搭配 OpenAIFunctionsAgent 来实现函数调用。

from langchain.chat_models import ChatOpenAI
from langchain.schema import SystemMessage, HumanMessage
from langchain.tools import Tool
from langchain.agents import initialize_agent, AgentType

# 定义一个函数
def get_weather(location: str) -> str:
    return f"{location} 的天气是晴天 🌞"

# 用 LangChain 的 Tool 包装函数
weather_tool = Tool(
    name="get_weather",
    func=get_weather,
    description="获取指定位置的天气信息"
)

# 初始化 ChatOpenAI 并启用 function calling
llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)

# 初始化 agent,使用 OpenAIFunctionsAgent
agent = initialize_agent(
    tools=[weather_tool],
    llm=llm,
    agent=AgentType.OPENAI_FUNCTIONS,
    verbose=True
)

# 运行 agent
agent.run("北京的天气怎么样?")

这种方式让大模型自主决定何时调用 get_weather,在多轮对话时,LangChain 会记住工具的使用情况,AgentType.OPENAI_FUNCTIONS 让 LangChain 自动解析 OpenAI function call 返回的 JSON。

自定义函数调用(工具调用)

如果我们想要手动管理函数调用,而不是完全交给 OpenAI API。如我们可以自己定义 function_call 逻辑。

import openai

def get_weather(location: str) -> str:
    return f"{location} 的天气是晴天 🌞"

functions = [
    {
        "name": "get_weather",
        "description": "获取天气信息",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {"type": "string", "description": "城市名称"}
            },
            "required": ["location"]
        }
    }
]

llm = openai.ChatCompletion.create(
    model="gpt-4-turbo",
    messages=[{"role": "user", "content": "北京的天气怎么样?"}],
    functions=functions
)

# 解析函数调用
if "function_call" in llm["choices"][0]["message"]:
    function_name = llm["choices"][0]["message"]["function_call"]["name"]
    arguments = llm["choices"][0]["message"]["function_call"]["arguments"]
    
    if function_name == "get_weather":
        result = get_weather(eval(arguments)["location"])
        print("调用 get_weather:", result)

使用这种方式我们可以完全控制函数调用,不依赖 LangChain 的 AgentType.OPENAI_FUNCTIONS,这就很灵活,我们可以不使用 LangChain Tool 。

Multi-Function Calling(多个函数调用)

假如我们要让大模型同时调用多个函数(例如天气 + 汇率转换)该怎么办呢。

from langchain.tools import Tool

def get_weather(location: str) -> str:
    return f"{location} 的天气是晴天 🌞"

def convert_currency(amount: float, from_currency: str, to_currency: str) -> str:
    return f"{amount} {from_currency} = {amount * 7.2} {to_currency}"

# 定义多个工具
weather_tool = Tool(name="get_weather", func=get_weather, description="获取天气信息")
currency_tool = Tool(name="convert_currency", func=convert_currency, description="货币转换")

# 初始化 Agent
agent = initialize_agent(
    tools=[weather_tool, currency_tool],
    llm=ChatOpenAI(model="gpt-4-turbo"),
    agent=AgentType.OPENAI_FUNCTIONS,
    verbose=True
)

# 运行多个函数调用
agent.run("北京的天气如何?顺便帮我把 100 美元换算成人民币")

当我们需要构建多功能 AI 助手的时候就非常有用了,模型可以同时调用 get_weather 和 convert_currency。

自定义 Tool + Prompt Engineering

如果我们是自己定义 prompt,而不是完全依赖 function calling。可以这样做:

from langchain.prompts import ChatPromptTemplate
from langchain.schema import AIMessage, HumanMessage

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个智能助手,你可以调用以下函数:\n1. 获取天气\n2. 货币转换"),
    ("human", "{input}")
])

messages = prompt.format_messages(input="帮我查一下上海的天气")

llm = ChatOpenAI(model="gpt-4-turbo")
response = llm(messages)

print(response.content)

我们能手动手动控制大模型的回答方式,用 prompt 来引导模型。

LangGraph(高级 Function Calling)

最后一种方式,也是我们主要推荐的方式,使用LangGraph构建的工作流来完成函数回调。

from langchain_experimental.graphs import StateGraph
from langchain.tools import Tool

# 定义函数
def get_weather(location: str):
    return f"{location} 的天气是晴天 🌞"

weather_tool = Tool(name="get_weather", func=get_weather, description="获取天气信息")

# 构建 LangGraph
graph = StateGraph()
graph.add_node("weather", weather_tool)
graph.set_entry_point("weather")

# 运行
result = graph.invoke("北京")
print(result)

我们以后再构造 AI 代理、自动化任务还有各种复杂多步交互的时候,肯定是需要LangGragh来完成函数回调,这中方式便能够很好的达到我们的目的,大家学会了吗。