解密AI智能体核心:AI Agents From Scratch中的函数调用(Function Calling)实现原理
解密AI智能体核心:AI Agents From Scratch中的函数调用(Function Calling)实现原理
AI智能体(AI Agents)之所以能与现实世界交互,核心在于函数调用(Function Calling) 能力。在开源项目 AI Agents From Scratch 中,函数调用是连接大语言模型(LLM)与外部工具的桥梁,让AI从单纯的文本生成工具升级为具备行动能力的智能体。本文将以项目中的实例为基础,详细解析函数调用的实现原理、核心组件及实际应用。
什么是函数调用?为什么它对AI智能体至关重要?
函数调用是AI智能体根据用户需求,自主选择并执行预设工具函数的过程。它解决了传统LLM的两大局限:无法获取实时数据和无法执行具体操作。在项目的 examples/07_simple-agent/CODE.md 中明确提到:
函数调用是将LLM从文本生成器转变为能使用工具执行操作的智能体的核心功能。
没有函数调用的AI:只能生成基于训练数据的文本,无法获取当前时间、查询天气或调用API。
有函数调用的AI:可以调用工具函数获取实时信息、执行计算、操作文件,甚至控制硬件设备。
函数调用的实现流程:从定义到执行
项目中的 simple-agent.js 展示了函数调用的完整流程,可概括为以下5个步骤:
1. 定义工具函数:用JSON Schema描述能力
函数调用的第一步是定义工具函数。项目中通过 defineChatSessionFunction 方法创建可被LLM识别的函数,包含描述、参数规范和执行逻辑三部分:
const getCurrentTime = defineChatSessionFunction({
description: "获取当前时间", // LLM通过描述判断何时调用
params: { // JSON Schema格式的参数定义
type: "object",
properties: {} // 无参数时为空对象
},
async handler() { // 实际执行逻辑
return new Date().toLocaleTimeString(); // 返回当前时间字符串
}
});
- 描述(description):必须清晰易懂,LLM依赖此判断是否需要调用该函数。
- 参数(params):遵循JSON Schema规范,定义输入参数的类型和约束(如字符串、数字或必填项)。
- 处理器(handler):函数的核心逻辑,可包含API调用、文件操作、计算等功能。
2. 注册函数:让LLM知道可用工具
定义后的函数需注册到会话中,使LLM感知到工具的存在:
const functions = { getCurrentTime }; // 可注册多个函数,如{getCurrentTime, getWeather}
项目中 examples/07_simple-agent/CODE.md 强调:
注册函数后,LLM会根据用户问题和函数描述,自主决定调用哪个工具。
3. 用户提问:触发工具调用需求
当用户提出需要工具支持的问题时(如“现在几点了?”),LLM会分析是否需要调用工具:
const prompt = `What time is it right now?`; // 需要实时时间,需调用getCurrentTime
4. LLM决策与函数执行:AI的“思考”过程
LLM通过以下逻辑决定是否调用函数:
- 分析用户问题,判断是否需要外部信息或操作;
- 匹配可用函数的描述,选择最合适的工具;
- 生成函数调用指令,由框架拦截并执行。
项目中 simple-agent.js 的执行流程如下:
用户提问 → LLM识别需求 → 调用getCurrentTime → 执行handler() → 返回结果给LLM → LLM整理回答
例如,当用户问“现在几点了?”:
- LLM调用
getCurrentTime函数,获取结果(如“1:46:36 PM”); - 再根据系统提示(“转换为24小时制”)处理结果,最终返回“13:46”。
5. 结果处理:从工具输出到自然语言回答
函数执行后,LLM会将工具返回的原始数据(如时间字符串、API响应)转换为自然语言回答,确保用户友好。
函数调用的核心组件:项目源码解析
AI Agents From Scratch将函数调用的核心逻辑封装在多个模块中,关键文件包括:
1. 工具定义工具:defineChatSessionFunction
位于 node-llama-cpp 库中,用于标准化函数定义格式,确保LLM能正确解析函数描述和参数。
2. 智能体基类:tool-calling-agent.js
在 src/agents/tool-calling-agent.js 中定义了工具调用智能体的基础框架:
export class ToolCallingAgent {
constructor(options = {}) {
// 初始化智能体,加载模型和工具
throw new Error('ToolCallingAgent not yet implemented');
}
// 工具调用相关方法
}
尽管该类尚未完全实现,但其结构展示了智能体的核心能力:加载工具、解析用户需求、执行函数调用。
3. 示例代码:simple-agent.js
examples/07_simple-agent/simple-agent.js 是函数调用的最佳实践,完整展示了从模型加载、函数定义到执行调用的全流程。
函数调用的应用场景:让AI智能体“动”起来
函数调用是构建实用AI智能体的基础,项目中列举了多种典型场景:
1. 信息检索:获取实时数据
// 定义天气查询函数
const getWeather = defineChatSessionFunction({
description: "查询城市天气",
params: {
type: "object",
properties: { city: { type: "string" } }
},
handler: async ({ city }) => {
return await fetchWeatherAPI(city); // 调用天气API
}
});
2. 计算与逻辑处理:弥补LLM数学能力不足
// 定义计算器函数
const calculate = defineChatSessionFunction({
description: "执行数学计算",
params: {
type: "object",
properties: { expression: { type: "string" } }
},
handler: async ({ expression }) => {
return eval(expression); // 执行数学表达式(实际应用需注意安全)
}
});
3. 数据库与文件操作:连接外部系统
通过函数调用,AI智能体可查询数据库、读写文件或操作本地资源,实现数据持久化和系统集成。
最佳实践:让函数调用更可靠
根据项目 examples/07_simple-agent/CODE.md 中的建议,优化函数调用需注意:
- 清晰的函数描述:确保LLM能准确理解函数用途,例如用“获取当前时间”而非“时间工具”。
- 严格的参数校验:使用JSON Schema定义参数类型和约束,避免无效输入。
- 错误处理:在handler中捕获异常,返回友好提示(如“获取天气失败,请检查城市名称”)。
- 单一职责原则:一个函数只做一件事,例如区分
getCurrentTime和convertTimezone。
总结:函数调用是AI智能体的“双手”
在 AI Agents From Scratch 项目中,函数调用是连接LLM与现实世界的核心机制。通过 defineChatSessionFunction 定义工具、注册函数、LLM决策执行的流程,AI智能体获得了“行动能力”,从文本生成工具升级为能解决实际问题的助手。
无论是查询天气、执行计算,还是操作文件,函数调用都是实现这些功能的基础。掌握这一机制,你就能构建出更强大、更实用的AI智能体!
要开始实践,可克隆项目仓库:git clone https://gitcode.com/gh_mirrors/ai/ai-agents-from-scratch
查看 examples/07_simple-agent/ 目录,亲手运行和修改函数调用代码。
更多推荐


所有评论(0)