这一节我们重点来聊聊 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来完成函数回调,这中方式便能够很好的达到我们的目的,大家学会了吗。