浙江省网站建设_网站建设公司_代码压缩_seo优化
2025/12/26 19:14:30 网站建设 项目流程

做 Agent 之前,彻底搞懂 AI 的 Function Calling / Tools

上篇(链接如上)我们解决了一个问题:让 AI 按你说的格式,老老实实返回 JSON。

现在这件事你已经会干了:

  • 用户说:「我想查上海的天气」
  • AI 乖乖返回:{ "city": "上海" }
  • 你的代码拿着这个 JSON 去调天气 API,一切顺滑

这种玩法在预先设计好的流程里特别好用:

  • 问题是固定的,比如「查天气」「查快递」「查库存」
  • 你知道自己要什么字段(城市、运单号、SKU…)
  • 也知道下一步要调哪个 API

本质上,这是在用 Structured Output 做「表单填空」:

我先设计好一张表,让 AI 帮我把表填满,然后我拿着这张表去调接口。

只要流程是「可穷举、可编排」的,这一套就非常好用。

问题来了:真正的聊天场景,根本不是这么玩的。

你把大模型接进自己应用里,用户不会配合你走流程,它会这样问:

  • 「上海天气怎么样?」—— 你心里想:应该调天气 API
  • 下一句直接换:「特斯拉股价多少?」—— 应该调股票 API
  • 再下一句:「明天有什么会议?」—— 应该查日历
  • 再下一句:「北京到上海机票多少钱?」—— 又是航班 API

每一句话都可能是一个完全不同的任务。

这时候 Structured Output 突然就不够用了:

  • 你没法提前知道用户下一句要问什么
  • 也就没法提前设计「返回什么样的 JSON」
  • 更没法写死:某个 JSON 一定对应某个 API

结果就是:第一句还能按套路提取字段,第二句开始整个链条直接断掉。

Structured Output 只解决了一个问题:「当我知道要什么字段时,AI 能不能按格式给我?」

它完全解决不了另一个更关键的问题:「当我不知道用户到底想干什么时,该调哪个 API?」

那有没有可能,让 AI 自己做这件事——用户说一句话,它自己判断:「这次该用天气 API」「这次该用股票 API」?

有的,这就是这一篇要讲的东西:

Function Calling / Tool Calling:让 AI 自己选工具,你只负责帮它把活干了。

AI 能“说”,但不能“做”

先搞清楚一个本质问题:LLM 到底能干什么?

答案很残酷:它只能生成 token(文字)

  • 它没法自己发 HTTP 请求
  • 没法自己读写数据库
  • 没法自己调用任何外部 API
  • 甚至连“真的执行一行代码”都不行

你可以把它当成一个超能版输入法 / 文案机: 你给一段话,它接着往下写。写得再聪明,本质都是在「预测下一个 token」。

但它可以干的一件事,是「看懂意图 + 拿主意」:

  • 看懂用户是在问天气,还是问股价,还是问会议
  • 决定「下一步该干什么」

所以 Tool Calling / Function Calling 的基本思路就是:

  1. 你告诉 AI:我这里有一堆工具可用(天气、股票、日历、航班……)

  2. 用户提问

  3. AI 不直接瞎编答案,而是说一句:

    「我打算调用 get_weather(city=‘上海’)」

  4. 你的程序根据这句话,去真的调用天气 API

  5. 把真实结果喂回 AI,让它用自然语言把结果解释给用户听

一句话总结:

AI 负责“决定调用谁”,程序负责“真的去干活”。

早期方案是靠 Prompt 硬凑

在 Function Calling 这种「原生能力」出现之前,大家都是硬玩 Prompt。

套路大概是这样:

System: 当用户问天气时,请输出以下格式:[FUNCTION_CALL]name: get_weatherargs: {"city": "xxx"}[/FUNCTION_CALL]User: 上海今天天气怎么样?

然后你的程序拿到这段字符串,用正则把:

[FUNCTION_CALL]...[/FUNCTION_CALL]

中间那一坨抠出来,当成一次函数调用描述。

问题和上一篇讲的“让 AI 输出 JSON”是一模一样的:

  • 它可能在标签外面加一堆废话
  • 标签写错、少个中括号
  • args里的 JSON 不合法
  • 参数名拼错、类型不对……

只要是「靠说服 AI 按格式输出」,就会出现同一种问题:

你把格式写得再清楚,模型也有概率「不听话」。

Function Calling:把“调函数”变成模型的母语

OpenAI 在 2023 年中正式放出 Function Calling 能力。其他厂商也陆续跟上,只是名字不同:

  • OpenAI:一开始叫 Function Calling,后来 API 里统一成tools
  • Claude:叫Tool Use
  • Gemini:文档里叫 Function Calling,但参数形式也都是 tools

不管叫什么,本质是一件事:

在模型的输出体系里,长出了一种新的“说法”: 不是对用户说话,而是对你的程序说「我要调哪个工具」。

从我们在 API 这一侧能观察到的行为,可以把 Function Calling 拆成三块:

  1. 工具定义被“塞”进了上下文
  2. 模型输出里多了一段“调用声明”
  3. API 在流里把这段“调用声明”拎出来,变成结构化字段

下面按调用链的视角拆开说。

1)告诉模型你有哪些“积木”:工具定义

你先得把手上的 API 都描述成一块块「可以调用的工具」,传给 LLM。

以 OpenAI 为例,工具定义长这样(简化版):

const tools = [{type: "function",function: { name: "get_weather", description: "获取指定城市的当前天气信息。当用户询问天气、气温时使用。", parameters: { type: "object", properties: { city: { type: "string", description: "城市名称,如上海" } }, required: ["city"] } }}];

对你来说,这就是一个 JS 对象。 对模型来说,这最终会被转换成一段更“像代码”的文本注入到上下文里,比如:

// 下面这些是你可以调用的工具:namespace functions { // 获取指定城市的当前天气信息。当用户询问天气、气温时使用。 type get_weather = (_: { // 城市名称,如上海 city: string, }) => any;}

你可以把它理解为:我们在模型脑子里声明了一堆「函数签名 + 注释」。

至于底层到底是怎么塞进去的、用的是不是 TypeScript 这套样式,不重要。重要的是:

  • 它能看见有哪些函数
  • 每个函数的名字、参数、注释都在
  • 形式接近代码,而代码是它最熟悉的语料之一

2)模型不是直接“干活”,而是输出一段“调用声明”

用户问一句:

「上海今天天气怎么样?」

和普通对话的差别在于:这次模型不会直接跟用户聊天,而是给你一段“调用计划”。

你在 API 侧拿到的大致是这种结构(不同厂商字段不一样,意思是一样的):

{ "role": "assistant", "tool_calls": [ { "id": "call_abc123", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\": \"上海\"}" } } ]}

从模型内部视角,你可以把它脑补成类似这样的输出流:

<|tool_call|>{"name": "get_weather", "arguments": {"city": "上海"}}<|end_tool_call|>

这里的<|tool_call|>/<|end_tool_call|>不是给人看的文字,而是特殊标记 token。 API 在流里一看到这些标记,就知道:

“哦,模型现在不是在跟用户说话,而是在跟我说: ——‘我要调用 get_weather,参数是 {city: “上海”}。’”

然后:

  1. 把这段 JSON 抠出来
  2. 解析成结构化数据
  3. 塞进tool_calls字段里返回给你

这一步,你可以完全当成「模型在发起一次 RPC 调用请求,只不过用的是自然语言世界里的 token」。

3)真正调用 API 的,是你这边的代码

拿到了tool_calls,接下来就是纯工程问题了:

  • 你写的get_weather函数里面发 HTTP
  • 跟真正的天气服务打交道
  • 把返回值格式化成字符串 / JSON,准备喂回模型

伪代码大概是这样:

for (const toolCall of choice.message.tool_calls ?? []) { const args = JSON.parse(toolCall.function.arguments); const result = await getWeather(args.city); // 真正的 API 调用 messages.push({ role: "tool", tool_call_id: toolCall.id, content: result });}

然后再把messages丢回 API,再来一轮模型输出。

这时模型看到的上下文里,多了一条“工具的执行结果”,大概长这样:

工具 get_weather 的返回值是:{"city": "上海", "temperature": 25, "weather": "多云"}

于是它就会继续生成一条真正写给用户的回答

「上海今天多云,气温 25 度,出门记得带件外套。」

至此,一次完整的 Tool Calling 就结束了。

本质是三层配合,但你只需要关心调用链

从调用链的视角看,Function Calling / Tools 这套东西可以浓缩成一句话:

在输出流里插入了一段“不是对用户说话,而是对你的程序说『我要调哪个工具』”的内容。

配套的三件事是:

  1. 工具定义注入上下文: 你把 API 描述成工具,LLM 看见这些“函数签名 + 注释”。
  2. 模型输出工具调用声明: 它在输出过程中,选择“用一段 JSON + 特殊标记”来表达「我要调用某个函数」。
  3. API 拦截 + 解析 + 交给你执行: API 把这段“调用声明”从输出里拎出来,变成tool_calls这样的结构化字段,你去真的调库 / 调 HTTP。

你完全不用关心「底层是怎么训练出来的」,只要记住:

  • 这不是 Prompt 小技巧,而是一套产品级别的协议
  • 模型确实“长”出了一种新的说话方式:向你的代码发起函数调用请求

为什么 description 这么关键?

既然工具定义是用“代码 + 注释”的形式塞给模型的,那很自然:

description 就是模型看到的“函数注释”,写得烂,模型就用不好。

你可以用一个简单的标准来自查:

**“如果一个只会看中文+代码的实习生,拿着这段描述,能不能大致用对这个函数?”**能,那模型大概率也能;反之亦然。

看两个极端例子。

差的写法:

description: "获取天气"

好的写法:

description: "获取指定城市的当前天气信息,包括温度和天气状况。当用户询问某地天气、气温、要不要带伞等问题时使用。"

好的 description 应该说清楚三件事:

  1. 这个函数能干什么
  2. 在什么场景下应该用它
  3. 参数怎么填

很多人觉得“工具选错了是模型不聪明”,实际上相当一部分是工具描述写得像废话,模型根本没法正确对齐。

Function Calling → Tools:从“调一个”到“调一堆”

Function Calling 解决了“能不能调函数”的问题,很快就遇到下一个:

“函数不止一个怎么办?”

典型场景:

  • 天气:get_weather
  • 股价:get_stock_price
  • 日历:list_events
  • 发邮件:send_email
  • ……

你希望的是:

  • 用户问天气 → 它挑get_weather
  • 问股价 → 挑get_stock_price
  • 问会议 → 挑list_events
  • 必要的时候还能一次挑多个

OpenAI 在 2023 年 11 月把这一层抽象成了Tools

  • 之前(2023.06):functions+function_call
  • 之后(2023.11):统一成tools+tool_choice

有两个关键变化:

  1. 语义上从“函数”升级为“工具”
  • 函数只是工具的一种形式
  • 以后还可以有别的工具类型(代码执行、文件搜索、浏览器等)
  1. 支持一次返回多个调用
  • 问「上海和北京哪个更热」时,模型可以一次吐出两条tool_call
  • 你的程序可以并行执行两个 HTTP 调用,效率直接翻倍

这个并行本质上很简单:

  • 模型负责列出「要调用哪些工具 + 参数」
  • 是否并行执行,是你程序的决策
  • LLM 不关心网络、IO,它只关心“调用计划”

一图看懂:完整的 Tools 调用循环

用过 Tools 的同学,对下面这张“循环图”应该都不陌生:

┌─────────────────────────────────────────────────────────────┐│ 你的程序 ││ ││ 1. 调用 LLM API:用户问题 + 工具定义 ││ ↓ ││ ┌─────────────────────────────────────────────────────┐ ││ │ LLM / Tools │ ││ │ 模型思考:需要调用 get_weather │ ││ │ 输出:tool_calls(函数名 + 参数) │ ││ └─────────────────────────────────────────────────────┘ ││ ↓ ││ 2. 检测到 tool_calls,执行真实函数 ││ result = get_weather("上海") // 真正发 HTTP ││ ↓ ││ 3. 把 result 作为 tool 结果喂回 LLM ││ ↓ ││ ┌─────────────────────────────────────────────────────┐ ││ │ LLM / Tools │ ││ │ 模型看到结果,生成自然语言回答 │ ││ └─────────────────────────────────────────────────────┘ ││ ↓ ││ 4. 返回最终答案给用户 ││ │└─────────────────────────────────────────────────────────────┘

关键点:至少两次 API 调用

  • 第一次:用户问题 + 工具定义 → 模型返回tool_calls
  • 第二次:tool_calls的执行结果 → 模型返回最终回答

如果任务更复杂(比如还要发邮件、写日报),这个循环可能会跑三次、四次甚至更多。这就是最原始的Agent 循环雏形

模型负责决定“下一步干什么”,程序负责真的去干,然后再把结果喂回去。

放一个完整的 TypeScript 示例

下面这个例子,你几乎可以直接 copy 改改就用。

import OpenAI from"openai";const openai = new OpenAI();// 工具定义(会被转成“代码 + 注释”的形式注入模型上下文)const tools: OpenAI.ChatCompletionTool[] = [ { type: "function", function: { name: "get_weather", description: "获取指定城市的当前天气信息。当用户询问天气、气温时使用。", parameters: { type: "object", properties: { city: { type: "string", description: "城市名称,如:上海、北京" } }, required: ["city"] } } }];// 模拟天气 API(实际项目中这里是真实的 HTTP 请求)function getWeather(city: string): string {const data: Record<string, number> = { 上海: 25, 北京: 18 };returnJSON.stringify({ city, temperature: data[city] ?? 20 });}// 核心循环asyncfunction chat(userMessage: string): Promise<string> {const messages: OpenAI.ChatCompletionMessageParam[] = [ { role: "user", content: userMessage } ];while (true) { const response = await openai.chat.completions.create({ model: "gpt-4o", messages, tools, }); const choice = response.choices[0]; // 1)模型觉得可以直接回答了 if (choice.finish_reason === "stop") { return choice.message.content || ""; } // 2)模型说:“我要调工具” if (choice.finish_reason === "tool_calls") { // 把这条“调用声明”也记进对话里 messages.push(choice.message); for (const toolCall of choice.message.tool_calls ?? []) { const args = JSON.parse(toolCall.function.arguments); const result = getWeather(args.city); // 真正执行函数 // 把工具的执行结果喂回模型 messages.push({ role: "tool", tool_call_id: toolCall.id, content: result }); } // 然后继续 while 循环,再调一次 API,让模型基于工具结果给最终答案 } }}// democonst answer = await chat("上海天气怎么样?");console.log(answer); // 例如:"上海今天气温 25 度,天气良好,适合出门。"

这个 demo 做了几件刚好对应我们上面那张图的事:

  1. 把业务 API 包装成tools 定义
  2. 让模型决定什么时候用哪个 tool
  3. 你这边真正执行getWeather
  4. 把结果再喂给模型,让它生成自然语言回答

总结一下

核心认知:

  1. **AI 不会自己调 API,它只会“写下一步 token”。**Function Calling / Tools 做的是:

    “给它一种新的说话方式,让它能对你的程序说『我要调哪个函数、带什么参数』。”

  2. 这不是高级 Prompt,而是一套标准调用链:

  • 工具定义注入上下文
  • 模型输出“调用声明”
  • API 拦截 + 解析 + 执行 + 喂回结果
  1. **description 写得好不好,直接决定工具选得准不准。**把模型当成看你代码注释的实习生来写 description,会好很多。
  2. Function Calling → Tools 是一次很自然的升级:
  • 从“只能调一个函数”到“一次能规划和触发多个工具”
  • Agent / 工作流的雏形就长在这条循环上

这条调用链目前在哪儿?

简单对一下时间线,帮你把心里那条“进化线”画完整:

时间进化解决的问题
早期Prompt 硬凑靠 AI 自觉按格式输出,极不稳定
2023.06Function Calling模型长出「函数调用」这门“母语”
2023.11Tools抽象成通用工具系统,支持多函数 / 并行调用

在这一篇为止,我们解决的是:

  • Structured Output:我知道要什么字段 → 你帮我按格式说
  • Function Calling / Tools:我不知道要调哪个 API → 你帮我决定用哪个工具

接下来还有两个更现实的问题:

  1. 想让 AI 操作 Notion / GitHub / 日历, 每个产品都要自己造一套 tools 吗?

    有没有可能:Notion 官方提供一套标准化的工具接口,所有 LLM / Agent 都能直接用?

  • A 团队写了一套「Notion Tools」
  • B 团队也要再写一套「Notion Tools」
  • 各家 AI 产品都在重复造轮子
  1. 工具越来越多,token 和上下文怎么办?

    现在只有get_weather一个工具还好说, 如果你这边有 50 个、100 个工具,全都变成“代码 + 注释”塞进上下文:

  • 上下文本身就要吃掉几十万 token
  • 模型选错工具的风险上升
  • 成本和复杂度一起炸掉

这两个问题,就是下一篇要聊的主角:

MCP:工具的“USB 接口”标准,解决跨产品复用;

Advanced Tool Use:工具太多时,怎么做搜索、裁剪和程序化调用。

AI时代,未来的就业机会在哪里?

答案就藏在大模型的浪潮里。从ChatGPT、DeepSeek等日常工具,到自然语言处理、计算机视觉、多模态等核心领域,技术普惠化、应用垂直化与生态开源化正催生Prompt工程师、自然语言处理、计算机视觉工程师、大模型算法工程师、AI应用产品经理等AI岗位。

掌握大模型技能,就是把握高薪未来。

那么,普通人如何抓住大模型风口?

AI技术的普及对个人能力提出了新的要求,在AI时代,持续学习和适应新技术变得尤为重要。无论是企业还是个人,都需要不断更新知识体系,提升与AI协作的能力,以适应不断变化的工作环境。

因此,这里给大家整理了一份《2025最新大模型全套学习资源》,包括2025最新大模型学习路线、大模型书籍、视频教程、项目实战、最新行业报告、面试题等,带你从零基础入门到精通,快速掌握大模型技术!

由于篇幅有限,有需要的小伙伴可以扫码获取!

1. 成长路线图&学习规划

要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。这里,我们为新手和想要进一步提升的专业人士准备了一份详细的学习成长路线图和规划。

2. 大模型经典PDF书籍

书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础(书籍含电子版PDF)

3. 大模型视频教程

对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识

4. 大模型项目实战

学以致用,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。

5. 大模型行业报告

行业分析主要包括对不同行业的现状、趋势、问题、机会等进行系统地调研和评估,以了解哪些行业更适合引入大模型的技术和应用,以及在哪些方面可以发挥大模型的优势。

6. 大模型面试题

面试不仅是技术的较量,更需要充分的准备。

在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。

为什么大家都在学AI大模型?

随着AI技术的发展,企业对人才的需求从“单一技术”转向 “AI+行业”双背景。企业对人才的需求从“单一技术”转向 “AI+行业”双背景。金融+AI、制造+AI、医疗+AI等跨界岗位薪资涨幅达30%-50%。

同时很多人面临优化裁员,近期科技巨头英特尔裁员2万人,传统岗位不断缩减,因此转行AI势在必行!

这些资料有用吗?

这份资料由我们和鲁为民博士(北京清华大学学士和美国加州理工学院博士)共同整理,现任上海殷泊信息科技CEO,其创立的MoPaaS云平台获Forrester全球’强劲表现者’认证,服务航天科工、国家电网等1000+企业,以第一作者在IEEE Transactions发表论文50+篇,获NASA JPL火星探测系统强化学习专利等35项中美专利。本套AI大模型课程由清华大学-加州理工双料博士、吴文俊人工智能奖得主鲁为民教授领衔研发。

资料内容涵盖了从入门到进阶的各类视频教程和实战项目,无论你是小白还是有些技术基础的技术人员,这份资料都绝对能帮助你提升薪资待遇,转行大模型岗位。


大模型全套学习资料已整理打包,有需要的小伙伴可以微信扫描下方CSDN官方认证二维码,免费领取【保证100%免费】

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询