# AI 终于能"干活"了——Function Calling 完全指南

0 阅读5分钟

写给想让 AI 真正帮你做事的开发者,不讲废话,直接上干货


先说一个让人抓狂的场景

你有没有遇到过这种情况:

问 AI:“帮我查一下北京今天的天气。”

AI 一本正经地回答你:“北京今天天气晴,气温大约在 15-22 度之间……”

然后你一看,完全是编的。因为它根本没有联网,它只是在用训练数据里的"印象"给你瞎猜。

或者你问它:“帮我查一下我们数据库里,上个月销售额最高的产品是哪个?”

它说:“我没有访问您数据库的权限,无法回答这个问题。”

这就是大模型的另一个"硬伤":它只会说话,不会干活。

Function Calling 就是给大模型装上了"手"。


Function Calling 到底是什么?

你告诉 AI 有哪些工具可以用,AI 自己决定什么时候用哪个工具,然后告诉你怎么调用,你去执行,把结果再喂给 AI,AI 给你最终答案。

用一个比喻:

想象你有一个超级聪明的老板(AI),但他不会用电脑。你是他的助理(你的代码)。

老板说:“去查一下今天北京的天气。”

你去查了,把结果告诉他:“北京今天晴,22 度。”

老板说:“好,那告诉客户,今天适合户外活动。”

整个过程:老板负责思考和决策,你负责执行具体操作。


工作流程

① 定义函数(工具)
        ↓
② 用户提问 + 函数定义 → 发给 AI
        ↓
③ AI 判断:要不要调用函数?调用哪个?传什么参数?
        ↓
④ AI 返回:getWeather({"city": "北京"})
        ↓
⑤ 代码执行 getWeather("北京")
        ↓
⑥ 结果返回给 AI
        ↓
⑦ AI 生成最终回答

完整代码示例(JavaScript)

第一步:定义你的函数

// 这是你真正要执行的函数
function getWeather(city) {
  // 实际项目里这里调用真实天气 API
  const weatherData = {
    '北京': { temperature: 22, condition: '晴', humidity: 40 },
    '上海': { temperature: 25, condition: '多云', humidity: 65 },
    '广州': { temperature: 30, condition: '阵雨', humidity: 80 },
  };
  return weatherData[city] || { error: '城市不存在' };
}

function getStockPrice(symbol) {
  const prices = {
    'AAPL': { price: 175.5, change: '+1.2%' },
    'TSLA': { price: 245.0, change: '-0.8%' },
  };
  return prices[symbol] || { error: '股票代码不存在' };
}

第二步:告诉 AI 有哪些工具可以用

const tools = [
  {
    type: 'function',
    function: {
      name: 'getWeather',
      description: '获取指定城市的实时天气信息',
      parameters: {
        type: 'object',
        properties: {
          city: {
            type: 'string',
            description: '城市名称,例如:北京、上海、广州',
          },
        },
        required: ['city'],
      },
    },
  },
  {
    type: 'function',
    function: {
      name: 'getStockPrice',
      description: '获取指定股票的实时价格',
      parameters: {
        type: 'object',
        properties: {
          symbol: {
            type: 'string',
            description: '股票代码,例如:AAPL、TSLA',
          },
        },
        required: ['symbol'],
      },
    },
  },
];

第三步:处理 AI 的决策

import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

async function chatWithTools(userMessage) {
  const messages = [{ role: 'user', content: userMessage }];

  // 第一次请求:让 AI 决定要不要调用函数
  const response = await client.chat.completions.create({
    model: 'gpt-4o',
    messages: messages,
    tools: tools,
    tool_choice: 'auto',
  });

  const message = response.choices[0].message;

  // 如果 AI 决定要调用函数
  if (message.tool_calls) {
    console.log(`AI 决定调用函数:${message.tool_calls[0].function.name}`);

    messages.push(message);

    // 执行 AI 要求的函数
    for (const toolCall of message.tool_calls) {
      const funcName = toolCall.function.name;
      const funcArgs = JSON.parse(toolCall.function.arguments);

      let result;
      if (funcName === 'getWeather') {
        result = getWeather(funcArgs.city);
      } else if (funcName === 'getStockPrice') {
        result = getStockPrice(funcArgs.symbol);
      }

      console.log(`函数执行结果:${JSON.stringify(result)}`);

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

    // 第二次请求:让 AI 基于函数结果生成最终回答
    const finalResponse = await client.chat.completions.create({
      model: 'gpt-4o',
      messages: messages,
    });

    return finalResponse.choices[0].message.content;
  }

  return message.content;
}

// 测试
async function main() {
  console.log(await chatWithTools('北京今天天气怎么样?'));
  console.log(await chatWithTools('苹果公司股票现在多少钱?'));
  console.log(await chatWithTools('你好,今天几号?'));
}

main();

运行结果:

AI 决定调用函数:getWeather
函数执行结果:{"temperature":22,"condition":"晴","humidity":40}
北京今天天气晴,气温 22 度,湿度 40%,是个不错的好天气!

AI 决定调用函数:getStockPrice
函数执行结果:{"price":175.5,"change":"+1.2%"}
苹果公司(AAPL)股票目前报价 175.5 美元,今日上涨 1.2%。

今天是 2025 年 X 月 X 日。(直接回答,不调用函数)

多函数并行调用

AI 可以同时决定调用多个函数,并行执行,效率翻倍。

// 并行执行所有函数调用
const results = await Promise.all(
  message.tool_calls.map(async (toolCall) => {
    const funcName = toolCall.function.name;
    const funcArgs = JSON.parse(toolCall.function.arguments);

    if (funcName === 'getWeather') return getWeather(funcArgs.city);
    if (funcName === 'getStockPrice') return getStockPrice(funcArgs.symbol);
  })
);

能做什么?

🔍 数据查询类

  • 查数据库(订单、库存、销售数据)
  • 查实时信息(天气、股价、汇率)
  • 搜索内部知识库

🛠️ 操作执行类

  • 发送邮件、短信
  • 创建日历事件
  • 操作文件
  • 调用第三方 API

🤖 Agent 自动化类

  • 自动化工作流
  • 代码执行
  • 浏览器操作

四个容易踩的坑

坑 1:函数描述写得太烂

❌ 烂描述:

{ "name": "query", "description": "查询数据" }

✅ 好描述:

{
  "name": "queryOrderStatus",
  "description": "根据订单号查询订单状态,包括支付、发货、物流等。当用户询问订单进度时使用。",
  "parameters": {
    "properties": {
      "order_id": {
        "type": "string",
        "description": "订单号,例如:ORD202501010001"
      }
    },
    "required": ["order_id"]
  }
}

原则:函数描述是给 AI 看的说明书,越详细越好。

坑 2:没处理 AI 不调用函数的情况

代码要同时处理两种情况:tool_calls 存在 和 不存在。

坑 3:函数执行出错没处理

try {
  return getWeather(city);
} catch (error) {
  return { error: error.message, message: '获取天气失败,请稍后重试' };
}

坑 4:tool_choice 设置不当

  • "auto" — AI 自己决定(推荐
  • "required" — 强制调用(别乱用)
  • 强制指定某个函数 — 按需使用

Function Calling vs RAG

对比项Function CallingRAG
解决的问题执行操作、获取实时数据基于知识库回答问题
数据来源实时调用外部系统预先建好的向量库
适合场景查天气、操作数据库、发邮件文档问答、企业知识库
实时性强,每次最新弱,需定期更新

两者经常结合使用:

  • RAG → 回答产品知识问题
  • Function Calling → 查询订单、处理退款

进阶:构建 Agent

Function Calling 的终极形态——自主完成复杂任务的 Agent

你说:“帮我分析上个月销售数据,找出最佳产品,然后给销售团队发邮件。”

Agent 会这样工作:

1. querySalesData(month="2025-02") → 获取数据
2. analyzeData(data) → 分析最佳产品
3. getTeamEmails(team="sales") → 获取邮箱
4. sendEmail(to, subject, body) → 发送邮件
5. 返回完成结果

整个过程 AI 自主决策,你只需定义好工具。


主流框架

  • LangChain.js — @tool 装饰器
  • LlamaIndex — 专注数据操作
  • AutoGen — 微软出品,多 Agent 协作
  • CrewAI — 角色扮演式多 Agent
  • OpenAI Assistants API — 官方封装

总结

AI 负责思考和决策,代码负责执行和操作,两者分工合作,AI 才能真正"干活"。

Function Calling 是构建实用 AI 应用的必备技能

推荐学习路径:

  1. 用 OpenAI API 跑通天气查询示例
  2. 把项目里的接口包装成 Function
  3. 让 AI 自主完成多步操作任务

点个赞 👍 收藏一下,后续写 Agent 构建实战、多工具协作等!