平台网站建设外包费用,免费网站国内空间,查询企业邮箱,网站设置支付宝在线支付做 Agent 之前#xff0c;彻底搞懂 AI 的 Function Calling / Tools
上篇(链接如上)我们解决了一个问题#xff1a;让 AI 按你说的格式#xff0c;老老实实返回 JSON。
现在这件事你已经会干了#xff1a;
用户说#xff1a;「我想查上海的天气」AI 乖乖返回#xff1a;{…做 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 的基本思路就是你告诉 AI我这里有一堆工具可用天气、股票、日历、航班……用户提问AI 不直接瞎编答案而是说一句「我打算调用 get_weather(city‘上海’)」你的程序根据这句话去真的调用天气 API把真实结果喂回 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 里统一成toolsClaude叫Tool UseGemini文档里叫 Function Calling但参数形式也都是 tools不管叫什么本质是一件事在模型的输出体系里长出了一种新的“说法” 不是对用户说话而是对你的程序说「我要调哪个工具」。从我们在 API 这一侧能观察到的行为可以把 Function Calling 拆成三块工具定义被“塞”进了上下文模型输出里多了一段“调用声明”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: “上海”}。’”然后把这段 JSON 抠出来解析成结构化数据塞进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 这套东西可以浓缩成一句话在输出流里插入了一段“不是对用户说话而是对你的程序说『我要调哪个工具』”的内容。配套的三件事是工具定义注入上下文 你把 API 描述成工具LLM 看见这些“函数签名 注释”。模型输出工具调用声明 它在输出过程中选择“用一段 JSON 特殊标记”来表达「我要调用某个函数」。API 拦截 解析 交给你执行 API 把这段“调用声明”从输出里拎出来变成tool_calls这样的结构化字段你去真的调库 / 调 HTTP。你完全不用关心「底层是怎么训练出来的」只要记住这不是 Prompt 小技巧而是一套产品级别的协议模型确实“长”出了一种新的说话方式向你的代码发起函数调用请求为什么 description 这么关键既然工具定义是用“代码 注释”的形式塞给模型的那很自然description 就是模型看到的“函数注释”写得烂模型就用不好。你可以用一个简单的标准来自查**“如果一个只会看中文代码的实习生拿着这段描述能不能大致用对这个函数”**能那模型大概率也能反之亦然。看两个极端例子。差的写法description: 获取天气好的写法description: 获取指定城市的当前天气信息包括温度和天气状况。当用户询问某地天气、气温、要不要带伞等问题时使用。好的 description 应该说清楚三件事这个函数能干什么在什么场景下应该用它参数怎么填很多人觉得“工具选错了是模型不聪明”实际上相当一部分是工具描述写得像废话模型根本没法正确对齐。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.06functionsfunction_call之后2023.11统一成toolstool_choice有两个关键变化语义上从“函数”升级为“工具”函数只是工具的一种形式以后还可以有别的工具类型代码执行、文件搜索、浏览器等支持一次返回多个调用问「上海和北京哪个更热」时模型可以一次吐出两条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 fromopenai;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: Recordstring, number { 上海: 25, 北京: 18 };returnJSON.stringify({ city, temperature: data[city] ?? 20 });}// 核心循环asyncfunction chat(userMessage: string): Promisestring {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 做了几件刚好对应我们上面那张图的事把业务 API 包装成tools 定义让模型决定什么时候用哪个 tool你这边真正执行getWeather把结果再喂给模型让它生成自然语言回答总结一下核心认知**AI 不会自己调 API它只会“写下一步 token”。**Function Calling / Tools 做的是“给它一种新的说话方式让它能对你的程序说『我要调哪个函数、带什么参数』。”这不是高级 Prompt而是一套标准调用链工具定义注入上下文模型输出“调用声明”API 拦截 解析 执行 喂回结果**description 写得好不好直接决定工具选得准不准。**把模型当成看你代码注释的实习生来写 description会好很多。Function Calling → Tools 是一次很自然的升级从“只能调一个函数”到“一次能规划和触发多个工具”Agent / 工作流的雏形就长在这条循环上这条调用链目前在哪儿简单对一下时间线帮你把心里那条“进化线”画完整时间进化解决的问题早期Prompt 硬凑靠 AI 自觉按格式输出极不稳定2023.06Function Calling模型长出「函数调用」这门“母语”2023.11Tools抽象成通用工具系统支持多函数 / 并行调用在这一篇为止我们解决的是Structured Output我知道要什么字段 → 你帮我按格式说Function Calling / Tools我不知道要调哪个 API → 你帮我决定用哪个工具接下来还有两个更现实的问题想让 AI 操作 Notion / GitHub / 日历 每个产品都要自己造一套 tools 吗有没有可能Notion 官方提供一套标准化的工具接口所有 LLM / Agent 都能直接用A 团队写了一套「Notion Tools」B 团队也要再写一套「Notion Tools」各家 AI 产品都在重复造轮子工具越来越多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书籍书籍和学习文档资料是学习大模型过程中必不可少的我们精选了一系列深入探讨大模型技术的书籍和学习文档它们由领域内的顶尖专家撰写内容全面、深入、详尽为你学习大模型提供坚实的理论基础。书籍含电子版PDF3. 大模型视频教程对于很多自学或者没有基础的同学来说书籍这些纯文字类的学习教材会觉得比较晦涩难以理解因此我们提供了丰富的大模型视频教程以动态、形象的方式展示技术概念帮助你更快、更轻松地掌握核心知识。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%免费】