把你的 API 暴露给大模型

LLM 原本什么都做不了

你让它"查北京今天天气",它只能根据训练数据瞎猜。它没有联网、没有 API、没有数据库。

**Function Calling(函数调用,也叫 Tool Use)**解决了这个问题:

你告诉模型"我这里有这些函数可以调",模型根据用户请求决定要不要调、用什么参数调,然后把结果告诉你的程序去真正执行。

注意:模型不真的执行函数,它只输出"应该怎么调"。真正执行的是你的代码。

一个完整的例子

import OpenAI from 'openai'
const client = new OpenAI()

// 1. 定义可用的工具
const tools = [
 {
 type: 'function',
 function: {
 name: 'get_weather',
 description: '查询指定城市的当前天气',
 parameters: {
 type: 'object',
 properties: {
 city: { type: 'string', description: '城市名,如"北京"' },
 },
 required: ['city'],
 },
 },
 },
]

// 2. 真正的工具实现(你的业务代码)
async function getWeather(city) {
 // 假装调了一个天气 API
 return { city, temperature: 22, condition: '晴' }
}

// 3. 发起对话
const messages = [
 { role: 'user', content: '北京今天天气怎样?' },
]

const res = await client.chat.completions.create({
 model: 'gpt-4o-mini',
 messages,
 tools, // 告诉模型有哪些工具
})

const msg = res.choices[0].message
console.log(msg)
// {
// role: 'assistant',
// content: null,
// tool_calls: [
// {
// id: 'call_abc',
// type: 'function',
// function: {
// name: 'get_weather',
// arguments: '{"city":"北京"}',
// },
// },
// ],
// }

看!模型没直接回答,而是告诉你:"我需要调 get_weather('北京')"

完整闭环

// 4. 执行工具
messages.push(msg) // 把模型的 tool_calls 回复加进历史

for (const call of msg.tool_calls) {
 const args = JSON.parse(call.function.arguments)
 const result = await getWeather(args.city)

 messages.push({
 role: 'tool',
 tool_call_id: call.id,
 content: JSON.stringify(result),
 })
}

// 5. 把结果喂回模型,让它组织最终回答
const final = await client.chat.completions.create({
 model: 'gpt-4o-mini',
 messages,
 tools,
})

console.log(final.choices[0].message.content)
// "北京今天晴,22 度,适合出门。"

所以整个流程是个循环:

用户提问


LLM 决策 ──► 不需要工具 ──► 直接回答

 ├──► 需要工具
 │ │
 │ ▼
 │ 执行工具
 │ │
 │ ▼
 │ 结果喂回 LLM ──► 可能还要调下一个工具 ──► 循环

 └─────► 最终回答

多工具 + 并行调用

现代模型(GPT-4o、Claude 3.5+、DeepSeek-V3)支持并行调用多个工具,一次性说"我要查天气、查时间、查日历"。

const tools = [
 { type: 'function', function: { name: 'get_weather', ... } },
 { type: 'function', function: { name: 'get_time', ... } },
 { type: 'function', function: { name: 'search_web', ... } },
]

你的代码要处理 tool_calls 数组(可能不止一个)。

Schema 设计的艺术

工具的 parametersJSON Schema描述,这决定模型能不能正确调用。

// 用 zod + zod-to-json-schema 比手写 JSON Schema 舒服 100 倍
import { z } from 'zod'
import { zodToJsonSchema } from 'zod-to-json-schema'

const sendEmailSchema = z.object({
 to: z.string().email().describe('收件人邮箱'),
 subject: z.string().describe('邮件主题'),
 body: z.string().describe('邮件正文,支持 Markdown'),
 cc: z.array(z.string().email()).optional().describe('抄送列表'),
})

const tool = {
 type: 'function',
 function: {
 name: 'send_email',
 description: '发送一封邮件。只在用户明确要求时使用。',
 parameters: zodToJsonSchema(sendEmailSchema),
 },
}

description 的质量直接决定调用准确率。写清楚什么时候该用、什么时候不该用。

实际场景:前端可以用它做什么

1. 让 AI 操作 UI

const tools = [
 { name: 'set_theme', parameters: { theme: 'dark' | 'light' } },
 { name: 'navigate_to', parameters: { page: string } },
 { name: 'open_modal', parameters: { modal_id: string } },
]
// 用户说"切暗色模式",模型返回 set_theme({ theme: 'dark' }),前端执行

2. 智能搜索/填表

// 用户说"帮我订下周三下午北京飞上海的机票"
// 模型调 search_flights({ from, to, date, time_range })

3. 读写业务数据

const tools = [
 { name: 'create_task', ... },
 { name: 'list_my_tasks', ... },
 { name: 'mark_done', ... },
]
// 用户说"把今天的三件事标记完成",模型连调三次 mark_done

4. 从自然语言生成 SQL/GraphQL 5. 控制 Chrome 扩展、VS Code 插件

安全性(极重要!)

模型会出错、会被 Prompt 注入攻击。永远不要盲目信任 tool_calls

// 灾难
async function execute(call) {
 const args = JSON.parse(call.function.arguments)
 if (call.function.name === 'delete_user') {
 await db.deleteUser(args.userId) //
 }
}

正确做法: -权限校验:每个工具独立权限,按当前用户身份过滤 -危险操作需要用户确认:涉及扣费、删数据、发邮件的,弹窗二次确认 -参数校验:用 zod 严格校验 arguments -工具分级:把工具分成"查询型"(安全)和"执行型"(敏感)

模型的 Function Calling 能力对比

模型能力
GPT-4o事实标准
Claude 3.5/Opus 4推理强,决策精准
DeepSeek-V3性价比高
Gemini 2.0支持
Qwen 2.5+开源里最好
小模型(7B 以下)基本不可用

想做 Function Calling,选模型至关重要。

和 Agent 的关系

Function Calling 是单步的:模型决定调一次工具 → 执行 → 模型看结果 → 回答。

Agent是在 Function Calling 基础上加循环和记忆,让模型能自主完成多步任务("帮我查天气、写邮件、发出去")。下一篇专门讲。

动手作业

给一个 Todo 应用加 AI 接口:

  • 工具 1:add_task({ title, due_date })
  • 工具 2:list_tasks({ filter: 'today'|'week'|'all' })
  • 工具 3:complete_task({ id })

要求:支持自然语言操作,比如"把明天的事推到下周一"(模型要能先 list 再 update)。

参考资料

版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:Function Calling:让 AI 调用你的 API

本文链接:https://www.sshipanoo.com/blog/ai/ai-for-frontend/06-Function-Calling/

本文最后一次更新为 天前,文章中的某些内容可能已过时!