大语言模型(LLM)确实能处理不少问题,但有两个硬伤没法绕开:一是训练完后知识就“冻结”了,跟不上最新的变化;二是它碰不到外部的数据,没法实时查询或修改。那怎么办?函数调用(也叫“工具使用”)就是来填这两个坑的。它让模型能调用外部的API或函数,相当于给它配了“外设”。
具体怎么玩呢?比如你问模型“北京的天气怎么样”,同时给它一个get_weather函数,这个函数接受一个位置参数,返回天气信息。模型不会自己去调天气API——它没这个权限——而是输出一个结构化的数据,告诉你:“嘿,你应该调用get_weather,参数是‘北京’。”然后你拿着这个信息,自己去调天气服务,拿到温度、云量、风况之类的数据,再塞回给模型。模型就能顺理成章地回答:“北京现在18度,多云,空气质量良好。”

函数调用的应用场景
这个能力到底能干什么?简单列几个方向:
- 跟外部API集成。比如调气象API查天气,用地图API把地址转成经纬度,或者通过货币兑换API做汇率换算。
- 构建高级聊天机器人。不只是闲聊,还能回答产品问题、查公司财务数据,甚至做一个能随时更新信息的助手。
- 结构化数据提取。从杂乱的日志里抽取出实体,或者从用户输入中精准捞出一个或多个参数——包括处理列表和嵌套结构。
- 控制函数调用行为。比如管理并行调用、设定模型在什么情况下才能调哪些函数。
- 用自然语言查数据库。直接把“这个月销售额是多少”转成SQL查询,扔给BigQuery。
- 多模态函数调用。图片、视频、音频、PDF——这些东西也能触发函数调用。
函数调用工作原理
你可能会好奇,这个机制到底怎么运作的?核心是你在给模型的提示里,加了一份“函数声明”——用结构化的数据描述好每个函数的名称、作用、参数类型和说明。模型拿到这些声明后,会结合用户的提问,自己判断哪个函数能用、该怎么用。然后它返回一个符合OpenAPI规范的对象,告诉你调用哪个函数、参数是什么。你照着这个结果去调真正的API,拿到数据后再喂回给模型,整个流程就跑通了。
创建函数调用应用的过程
如果要自己动手做一个能跟模型交互、并用上函数调用的程序,步骤大致如下:
- 选好模型,搭好环境。
- 定义一组可用的函数,用函数声明描述清楚。
- 把用户的提问和这些函数声明一起丢给模型。
- 根据模型输出的结构化数据,真正去调函数或API。
- 把函数返回的结果再送回给模型。
这个应用可以是文本聊天机器人、语音客服、自动化工作流——没有限制。
函数声明
为了让大多数模型都能理解,函数声明一般按OpenAPI架构来设计。实现的时候,先创建一个tools对象,里面放一个或多个函数声明。一个完整的函数声明包含这些字段:
name:函数的唯一标识符,就是个字符串。description:详细说明这个函数能干什么、怎么用。parameters:定义输入数据,是个对象。里面又分:type:参数的数据类型,比如string、integer、boolean。description:说明参数的用途和格式。type:整体数据类型,通常是object。properties:列出每个参数,每个参数都有自己的类型和描述。required:一个数组,列出哪些参数是必须的。
函数声明最佳实践
name:起名要清晰,别用空格、句点或短划线,用下划线或驼峰命名法更好。description:写得详细、具体,必要时可以给示例。别整些模糊的描述。properties > type:尽量用强类型,能减少模型幻觉。比如参数值来自固定选项就用enum,别在描述里罗列;如果一定是整数,就用integer。properties > description:给具体示例和限制条件。
支持函数调用的模型
好消息是,现在不少模型都原生支持函数调用,比如OpenAI GPT、Anthropic Claude、Amazon SageMaker、Google Gemini、GLM4、Hammer、Qwen等。你可以基于这些平台写对应的程序来实现。
通用提示词
既然很多模型都支持原生函数调用,为什么还要讲提示词?原因很现实:第一,你用的模型可能不支持;第二,每个平台的函数调用格式和API不通用,换个平台就得重写,很麻烦。下面这个例子,就是用提示词来实现通用的函数调用,配合Python代码格式化。
respones_shema = {
"title": "Function Call",
"type": "object",
"properties": {
"functionCall": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the function to call."
},
"args": {
"description": "Arguments for the function, can be any valid JSON object.",
"oneOf": [
{"type": "null"},
{"type": "boolean"},
{"type": "integer"},
{"type": "number"},
{"type": "string"},
{"type": "array"},
{"type": "object"}
]
}
},
"required": ["name", "args"],
"additionalProperties": false
}
},
"required": ["functionCall"],
"additionalProperties": false
}
system_prompts = f"""
You ha ve access to the following tools:
{json.dumps(tools)}
You can select one of the above tools or
just response user's content and respond
with only a JSON object matching the following schema:
{json.dumps(response_schema)}
"""
具体的LLM API调用,大家可以根据不同平台自行实现。关键在于,这个方案让函数调用不再依赖某个特定平台的格式,而是在提示层就约定好了规则。
