导航栏:首页 / AI教程目录 / AI创客项目开发教程目录 / 第1篇 基础知识篇 / AID101-1-3-03 – 多工具定义实例
本节内容简介
本节将讲解如何在 ESP32-S3-DevKitC-1 开发板上实现多个工具定义和多个工具调用的方法。本节课所使用的这个程序是在上一节演示程序的基础上进行功能扩展。
与上一节ESP32只能控制 LED 开关不同,本节课程的程序新增了对 LED 亮度的控制功能。AI 模型可以根据用户的自然语言指令,智能判断应该调用哪个工具函数:
- 当用户说”打开 LED”时,ESP32 调用
controlLEDOnOFF函数实现LED开关控制 - 当用户说”把 LED 调到亮度最大”时,ESP32调用
controlLEDBrightness函数实现LED亮度控制
本节示例程序
注意
本程序需要配合my_info.h代码使用,否则程序将无法正常编译。
请点击以下链接前往该代码页面,复制下载该代码:
http://ai.taichi-maker.com/index.php/homepage/ai-tutorial-index/ai-maker-project-tutorial-index/my_info_h-code-description/
本节程序在上一节‘AID101-1-3-02 – 单工具定义实例’示例程序的基础上,实现了以下核心进阶:
- 多工具定义:在
tools数组中同时定义了开关控制和亮度调节两个工具 - 多工具调用:
parseToolCallsResponse函数能够根据 AI 返回的函数名,调用不同的处理逻辑 - 参数范围约束:使用
minimum和maximum限制亮度级别在 1-5 之间,确保 AI 生成的参数在合法范围内
理解了这个多工具调用的模式后,就可以进一步扩展:添加更多工具函数(如LED调节颜色、设置LED闪烁模式、读取传感器数据等),构建功能更丰富的 AI 物联网应用。
/*
* ESP32 AI平台调用 Tool Calls 示例 - 增强版
*
* 功能描述:
* 本程序专门为ESP32-S3-DevKitC-1开发板设计,演示如何通过LLM模型的Tool Calls功能
* 控制开发板上内置的WS2812 LED的开关和亮度。程序通过HTTPS协议向AI平台发送带有两个工具定义
* 的请求,AI模型根据用户指令分析出需要调用的工具和参数,ESP32解析响应后执行相应的LED控制操作。
*
* 本程序支持两种类型的指令:
* 1. 打开/关闭LED(如"打开LED"、"关闭LED")
* 2. 调节LED亮度(如"把LED调到亮度最大"、"将LED亮度调到中等")
*
* 作者:Taichi-Maker
* 作者官网:http://ai.taichi-maker.com
* 创建日期:2026年06月25日
* 版本:2.1.2
*
* 硬件要求:
* - ESP32-S3-DevKitC-1开发板(内置一颗WS2812 LED,数据引脚连接到GPIO 48)
*
* 所需软件库:
* - FastLED库(用于控制WS2812 LED)
* - ArduinoJson库(版本7.0.0或更高)--用于处理JSON数据
*
* 配置说明:
* 1. 请先通过Arduino IDE的库管理器安装FastLED和ArduinoJson库。
* 2. 在my_info.h文件中填写您的Wi-Fi名称(ssid)和密码(password)。
* 3. 在my_info.h文件中将ai_api_key替换为您从AI平台获取的有效API密钥(切勿泄露!)。
* 4. 确保开发板已正确连接到电脑,并选择正确的开发板型号与端口。
*
* 使用方法:
* 1. 将本程序上传至ESP32-S3-DevKitC-1开发板。
* 2. 打开串口监视器(波特率设置为115200)。
* 3. 程序会自动连接Wi-Fi并发送用户指令给AI平台。
* 4. AI模型通过Tool Calls功能分析指令并返回控制参数。
* 5. ESP32解析响应并控制LED的开关和亮度。
*
* 注意事项:
* - 本例使用client.setInsecure()跳过了SSL证书验证,仅适用于测试环境;
* 在生产环境中应使用有效证书以确保通信安全。
* - 亮度级别为1-5级,其中1为最暗,5为最亮。
*
* 兼容性说明:
* 本程序专为ESP32-S3-DevKitC-1开发板设计,已在ESP32-S3-DevKitC-1开发板上测试通过。
*
* 许可证:MIT License
*/
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "my_info.h"
// 引入FastLED库
#include <FastLED.h>
// LED配置 - ESP32-S3-DevKitC-1开发板内置WS2812 LED连接到GPIO 48
#define DATA_PIN 48
#define NUM_LEDS 1
// FastLED LED数组
CRGB leds[NUM_LEDS];
/*
* -------------- 带有Tool Calls的JSON请求体(增强版)--------------
*/
const char* ai_payload = R"rawliteral({
"model": "qwen-flash",
"messages": [
{
"role": "system",
"content": "你是一个智能家居助手,可以控制 LED 的开关和亮度。"
},
{
"role": "user",
"content": "把LED调到最大亮度"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "controlLEDOnOFF",
"description": "控制LED的打开或关闭",
"parameters": {
"type": "object",
"properties": {
"action": {
"type": "string",
"description": "LED控制动作",
"enum": ["on", "off"]
}
},
"required": ["action"]
}
}
},
{
"type": "function",
"function": {
"name": "controlLEDBrightness",
"description": "控制LED的亮度级别",
"parameters": {
"type": "object",
"properties": {
"level": {
"type": "integer",
"description": "亮度级别,1-5级,其中1为最暗,5为最亮",
"minimum": 1,
"maximum": 5
}
},
"required": ["level"]
}
}
}
],
"tool_choice": "auto",
"temperature": 0.1
})rawliteral";
// 创建一个安全的Wi-Fi客户端(用于HTTPS连接)
WiFiClientSecure client;
// 创建HTTP客户端对象,用于发送请求
HTTPClient https;
void setup() {
Serial.begin(115200);
delay(1000);
// 初始化FastLED
FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(128);
leds[0] = CRGB::White;
FastLED.show();
Serial.println("FastLED initialized successfully!");
// 开始连接Wi-Fi
Serial.print("Connecting WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
client.setInsecure();
client.setTimeout(15);
Serial.println();
Serial.println("---------- AI Platform Config ----------");
Serial.print("AI Platform API Endpoint: ");
Serial.print(ai_host);
Serial.println(ai_endpoint);
Serial.println();
Serial.print("一切就绪,等待几秒钟,便于您观察板上LED状态.");
delay(5000);
Serial.print("开始调用AI大模型");
callAIPlatform();
}
void loop() {
delay(10);
}
void callAIPlatform() {
Serial.println("\n>>> Calling AI Platform API...");
String auth = "Bearer ";
auth += ai_api_key;
if (https.begin(client, ai_host, ai_port, ai_endpoint)) {
https.setTimeout(20000);
https.setConnectTimeout(10000);
https.addHeader("Content-Type", "application/json");
https.addHeader("Authorization", auth);
int httpCode = https.POST(ai_payload);
if (httpCode > 0) {
Serial.printf("HTTP Response code: %d\n", httpCode);
if (httpCode == HTTP_CODE_OK) {
String resp = https.getString();
Serial.println("----- Response -----");
Serial.println(resp);
Serial.println("----- End -----");
parseToolCallsResponse(resp);
}
} else {
Serial.printf("HTTP error: %s\n", https.errorToString(httpCode).c_str());
}
https.end();
} else {
Serial.println("Unable to connect to server");
}
}
void parseToolCallsResponse(String jsonResponse) {
DynamicJsonDocument doc(4096);
DeserializationError error = deserializeJson(doc, jsonResponse);
if (error) {
Serial.print("JSON解析失败: ");
Serial.println(error.c_str());
return;
}
if (doc.containsKey("choices") && doc["choices"].size() > 0) {
JsonObject choice = doc["choices"][0];
JsonObject message = choice["message"];
if (message.containsKey("tool_calls") && message["tool_calls"].size() > 0) {
JsonObject toolCall = message["tool_calls"][0];
JsonObject function = toolCall["function"];
String functionName = function["name"].as<String>();
Serial.print("检测到工具调用: ");
Serial.println(functionName);
if (functionName == "controlLEDOnOFF") {
String arguments = function["arguments"].as<String>();
DynamicJsonDocument argsDoc(512);
deserializeJson(argsDoc, arguments);
String action = argsDoc["action"].as<String>();
controlLEDOnOFF(action);
} else if (functionName == "controlLEDBrightness") {
String arguments = function["arguments"].as<String>();
DynamicJsonDocument argsDoc(512);
deserializeJson(argsDoc, arguments);
int level = argsDoc["level"].as<int>();
controlLEDBrightness(level);
} else {
Serial.print("未知函数: ");
Serial.println(functionName);
}
}
}
}
/*
* LED控制函数(已改为FastLED实现)
*/
void controlLEDOnOFF(String action) {
Serial.print("控制LED开关: ");
Serial.println(action);
if (action == "on") {
leds[0] = CRGB::White;
FastLED.show();
Serial.println("通过controlLEDOnOFF函数,LED已打开");
} else if (action == "off") {
leds[0] = CRGB::Black;
FastLED.show();
Serial.println("通过controlLEDOnOFF函数,LED已关闭");
} else {
Serial.println("无效的LED控制指令");
}
}
void controlLEDBrightness(int level) {
Serial.print("控制LED亮度: 级别 ");
Serial.println(level);
if (level >= 1 && level <= 5) {
// 映射1-5级到亮度值
uint8_t brightness = map(level, 1, 5, 50, 255);
FastLED.setBrightness(brightness);
leds[0] = CRGB::White;
FastLED.show();
String levelDescription;
switch (level) {
case 1: levelDescription = "最暗"; break;
case 2: levelDescription = "较暗"; break;
case 3: levelDescription = "中等"; break;
case 4: levelDescription = "较亮"; break;
case 5: levelDescription = "最亮"; break;
}
Serial.print("通过controlLEDBrightness函数,LED亮度已设置为");
Serial.print(levelDescription);
} else {
Serial.println("无效的亮度级别,必须在1-5之间");
}
}本程序的新增功能
新增功能1. 新增了可调用的工具
本程序在 tools 数组中定义了两个工具函数。这两个工具并列存在于同一个 tools 数组中,AI 模型会根据用户的自然语言指令,自动判断应该调用哪一个工具。如果用户说的是开关相关指令(如”打开LED”),AI 会选择 controlLEDOnOFF;如果用户说的是亮度相关指令(如”把LED调亮一点”),AI 会选择 controlLEDBrightness。
以下是完整的 tools 数组结构示意:
"tools": [
{
"type": "function",
"function": {
"name": "controlLEDOnOFF",
"description": "控制LED的打开或关闭",
"parameters": {
"type": "object",
"properties": {
"action": {
"type": "string",
"description": "LED控制动作",
"enum": ["on", "off"]
}
},
"required": ["action"]
}
}
},
{
"type": "function",
"function": {
"name": "controlLEDBrightness",
"description": "控制LED的亮度级别",
"parameters": {
"type": "object",
"properties": {
"level": {
"type": "integer",
"description": "亮度级别,1-5级,其中1为最暗,5为最亮",
"minimum": 1,
"maximum": 5
}
},
"required": ["level"]
}
}
}
]可以看到,两个工具对象作为数组元素并列排列。每个工具都包含 type、function(内含 name、description、parameters)等字段。AI 模型通过比较用户指令与每个工具的 description,来决定调用最合适的工具。
工具一:LED 开关控制(controlLEDOnOFF)
{
"type": "function",
"function": {
"name": "controlLEDOnOFF",
"description": "控制LED的打开或关闭",
"parameters": {
"type": "object",
"properties": {
"action": {
"type": "string",
"description": "LED控制动作",
"enum": ["on", "off"]
}
},
"required": ["action"]
}
}
}这个工具与上一节完全相同,用于控制 LED 的开关状态。
工具二:LED 亮度调节(controlLEDBrightness)
{
"type": "function",
"function": {
"name": "controlLEDBrightness",
"description": "控制LED的亮度级别",
"parameters": {
"type": "object",
"properties": {
"level": {
"type": "integer",
"description": "亮度级别,1-5级,其中1为最暗,5为最亮",
"minimum": 1,
"maximum": 5
}
},
"required": ["level"]
}
}
}这是本程序新增的工具函数,用于调节 LED 的亮度级别。下面对这个工具的定义进行逐层解析:
第一层:type 和 function
"type": "function":声明这是一个函数类型的工具,与开关控制工具相同"function":包含该函数的详细定义
第二层:name 和 description
"name": "controlLEDBrightness":函数的唯一标识名。当 AI 决定调节亮度时,会在响应中返回这个名称"description": "控制LED的亮度级别":功能描述,帮助 AI 理解这个工具的用途。当用户说”调亮一点”、”把灯调暗”等指令时,AI 通过这段描述判断应该使用这个工具
第三层:parameters(参数规范)
"type": "object":声明参数整体是一个 JSON 对象"properties":定义参数的具体属性
第四层:level 参数详解
| 字段 | 值 | 作用 |
|---|---|---|
type | "integer" | 限定参数必须是整数类型,AI 不会生成小数或字符串 |
description | "亮度级别,1-5级,其中1为最暗,5为最亮" | 语义描述,帮助 AI 理解参数含义和取值规则 |
minimum | 1 | 最小值约束,AI 生成的数值不会小于 1 |
maximum | 5 | 最大值约束,AI 生成的数值不会大于 5 |
"required": ["level"]:声明level是必填参数,AI 必须在响应中提供这个值
与开关控制工具的对比
| 对比项 | controlLEDOnOFF | controlLEDBrightness |
|---|---|---|
| 功能 | 控制开关 | 控制亮度 |
| 参数名 | action | level |
| 参数类型 | string(字符串) | integer(整数) |
| 约束方式 | enum: ["on", "off"] | minimum: 1, maximum: 5 |
| 适用场景 | “打开LED”、”关闭LED” | “调亮一点”、”调到最亮” |
重点讲解:使用 minimum 和 maximum 约束参数范围
在 controlLEDBrightness 工具的参数定义中,我们使用了两个新的 JSON Schema 关键字:
"level": {
"type": "integer",
"description": "亮度级别,1-5级,其中1为最暗,5为最亮",
"minimum": 1,
"maximum": 5
}这两个关键字的作用
minimum: 1 —— 告诉 AI 模型,level参数的最小值是 1,不能小于 1maximum: 5 —— 告诉 AI 模型,level参数的最大值是 5,不能大于 5
为什么需要这种约束?
在没有 minimum 和 maximum 约束的情况下,如果用户说”把 LED 调到最亮”,AI 模型可能会返回各种不同的值:
- 可能返回
10(假设 10 是最大值) - 可能返回
100(假设百分比制) - 可能返回
255(假设 8 位亮度值)
这些值对于 ESP32 程序来说都是”合法”的整数,但可能超出了硬件实际支持的范围,导致控制失败或产生不可预期的行为。
通过设置 "minimum": 1 和 "maximum": 5,我们明确告诉 AI 模型:
“亮度级别只有 1 到 5 这五个档位,请一定在这个范围内选择。”
这样,无论用户用什么样的自然语言表达亮度需求(”最亮”、”亮一点”、”中等亮度”等),AI 模型都会将其映射到 1-5 之间的整数,确保 ESP32 程序能够正确处理。
实际效果示例
| 用户指令 | AI 推断的 level 值 |
|---|---|
| “把 LED 调到最亮” | 5 |
| “把 LED 调到最暗” | 1 |
| “把 LED 亮度调高一点” | 2(假设当前是1) |
| “把 LED 调到中等亮度” | 3 |
代码解析:关键变化点
1. JSON 请求体的变化(第68-120行)
与上一节相比,最显著的变化是 tools 数组从包含 1 个工具扩展为包含 2 个工具。同时,用户指令也根据演示需求发生了变化。
下面通过两个具体示例,展示 ESP32、AI 平台和硬件之间的完整交互流程。
示例一:用户指令”把LED调到亮度最大”
第一步:ESP32 构造并发送请求
ESP32 将用户指令和工具定义组装成 JSON 请求包,通过 HTTPS POST 发送给 AI 平台:
{
"model": "qwen-flash",
"messages": [
{
"role": "system",
"content": "你是一个智能家居助手,可以控制 LED 的开关和亮度。"
},
{
"role": "user",
"content": "把LED调到亮度最大"
}
],
"tools": [
{ /* controlLEDOnOFF 工具定义 */ },
{ /* controlLEDBrightness 工具定义 */ }
],
"tool_choice": "auto",
"temperature": 0.1
}第二步:AI 平台分析请求
AI 模型收到请求后,执行以下分析:
- 理解用户意图:用户说”把LED调到亮度最大” → 语义解析为”需要调节LED亮度”
- 匹配可用工具:查看
tools列表controlLEDOnOFF的描述是”控制LED的打开或关闭” → 不匹配controlLEDBrightness的描述是”控制LED的亮度级别” → 匹配
- 确定工具选择:选择
controlLEDBrightness工具 - 生成合法参数:根据
"maximum": 5的约束,”亮度最大”对应级别5
第三步:AI 平台返回响应
AI 平台返回包含工具调用指令的 JSON 响应:
{
"choices": [
{
"finish_reason": "tool_calls",
"message": {
"role": "assistant",
"content": "",
"tool_calls": [
{
"function": {
"name": "controlLEDBrightness",
"arguments": "{\"level\": 5}"
}
}
]
}
}
]
}注意:content 为空,说明 AI 没有使用自然语言回复,而是通过 tool_calls 下达结构化指令。
第四步:ESP32 解析响应并执行
ESP32 的 parseToolCallsResponse 函数解析上述响应:
- 检查
finish_reason为"tool_calls"→ 确认是工具调用响应 - 提取
tool_calls[0].function.name→ 得到"controlLEDBrightness" - 提取
tool_calls[0].function.arguments→ 得到{"level": 5} - 解析参数 JSON →
level = 5 - 调用
controlLEDBrightness(5)→ LED 亮度设置为最亮
示例二:用户指令”关闭LED”
第一步:ESP32 构造并发送请求
用户指令部分变为:
{
"model": "qwen-flash",
"messages": [
{
"role": "system",
"content": "你是一个智能家居助手,可以控制 LED 的开关和亮度。"
},
{
"role": "user",
"content": "关闭LED"
}
],
"tools": [
{ /* controlLEDOnOFF 工具定义 */ },
{ /* controlLEDBrightness 工具定义 */ }
],
"tool_choice": "auto",
"temperature": 0.1
}tools 数组内容保持不变(两个工具都包含在内)。
第二步:AI 平台分析请求
- 理解用户意图:用户说”关闭LED” → 语义解析为”需要关闭LED”
- 匹配可用工具:
controlLEDOnOFF的描述是”控制LED的打开或关闭” → 匹配controlLEDBrightness的描述是”控制LED的亮度级别” → 不匹配
- 确定工具选择:选择
controlLEDOnOFF工具 - 生成合法参数:根据
"enum": ["on", "off"],”关闭”对应"off"
第三步:AI 平台返回响应
{
"choices": [
{
"finish_reason": "tool_calls",
"message": {
"role": "assistant",
"content": "",
"tool_calls": [
{
"function": {
"name": "controlLEDOnOFF",
"arguments": "{\"action\": \"off\"}"
}
}
]
}
}
]
}第四步:ESP32 解析响应并执行
- 提取
function.name→"controlLEDOnOFF" - 提取
function.arguments→{"action": "off"} - 解析参数 →
action = "off" - 调用
controlLEDOnOFF("off")→ LED 关闭
两个示例的对比总结
| 步骤 | 亮度调节示例 | 开关控制示例 |
|---|---|---|
| 用户指令 | “把LED调到亮度最大” | “关闭LED” |
| AI 选择的工具 | controlLEDBrightness | controlLEDOnOFF |
| 生成的参数 | {"level": 5} | {"action": "off"} |
| ESP32 调用的函数 | controlLEDBrightness(5) | controlLEDOnOFF("off") |
| 硬件执行结果 | LED 亮度设为最亮 | LED 关闭 |
通过这两个示例可以看出,同一套 tools 定义可以应对不同类型的用户指令。AI 模型会根据指令内容自动选择最合适的工具,而 ESP32 只需要根据返回的函数名和参数执行相应操作即可。
新增功能 2. 解析函数的扩展(第233-242行)
parseToolCallsResponse 函数在原有基础上增加了对 controlLEDBrightness 的处理分支。下面是完整的解析函数中新增部分的代码:
} else if (functionName == "controlLEDBrightness") {
// 解析LED亮度函数参数
String arguments = function["arguments"].as<String>();
// 解析参数JSON
DynamicJsonDocument argsDoc(512);
DeserializationError argsError = deserializeJson(argsDoc, arguments);
if (argsError) {
Serial.print("参数解析失败: ");
Serial.println(argsError.c_str());
return;
}
int level = argsDoc["level"].as<int>();
Serial.print("执行亮度调节: ");
Serial.println(level);
// 调用LED亮度控制函数
controlLEDBrightness(level);
} else {
Serial.print("未知函数: ");
Serial.println(functionName);
}下面对这段新增的亮度控制解析逻辑进行逐行说明:
第一步:判断函数名称
} else if (functionName == "controlLEDBrightness") {当 AI 返回的函数名不是 controlLEDOnOFF 时,程序会继续检查是否为 controlLEDBrightness。如果是,就进入亮度控制的处理分支。
第二步:提取参数字符串
String arguments = function["arguments"].as<String>();从 AI 响应中提取 arguments 字段的值。这是一个 JSON 格式的字符串,例如 {"level": 5}。
第三步:解析参数 JSON
DynamicJsonDocument argsDoc(512);
DeserializationError argsError = deserializeJson(argsDoc, arguments);
if (argsError) {
Serial.print("参数解析失败: ");
Serial.println(argsError.c_str());
return;
}使用 ArduinoJson 库将参数字符串解析为可操作的数据结构。如果解析失败(如 JSON 格式错误),打印错误信息并退出函数。
第四步:提取具体参数值
int level = argsDoc["level"].as<int>();
Serial.print("执行亮度调节: ");
Serial.println(level);从解析后的参数对象中提取 level 字段的整数值,并通过串口打印出来,方便调试观察。
第五步:调用亮度控制函数
controlLEDBrightness(level);将解析得到的亮度级别传递给 controlLEDBrightness 函数,由该函数执行实际的硬件控制操作。
第六步:处理未知函数
} else {
Serial.print("未知函数: ");
Serial.println(functionName);
}如果 AI 返回的函数名既不是 controlLEDOnOFF 也不是 controlLEDBrightness,则打印”未知函数”的提示信息。这是一种防御性编程,确保程序在遇到意外情况时能够给出明确的反馈。
新增功能3. 新增的亮度控制函数(第267-292行)
void controlLEDBrightness(int level) {
Serial.print("控制LED亮度: 级别 ");
Serial.println(level);
if (level >= 1 && level <= 5) {
// 映射1-5级到亮度值
uint8_t brightness = map(level, 1, 5, 50, 255);
FastLED.setBrightness(brightness);
leds[0] = CRGB::White;
FastLED.show();
String levelDescription;
switch (level) {
case 1: levelDescription = "最暗"; break;
case 2: levelDescription = "较暗"; break;
case 3: levelDescription = "中等"; break;
case 4: levelDescription = "较亮"; break;
case 5: levelDescription = "最亮"; break;
}
Serial.print("通过controlLEDBrightness函数,LED亮度已设置为");
Serial.print(levelDescription);
} else {
Serial.println("无效的亮度级别,必须在1-5之间");
}
}这个函数做了以下几件事:
- 参数校验:检查
level是否在 1-5 的合法范围内 - 自动开灯:如果 LED 当前是关闭状态,先自动打开 LED 并设置为白色
- 设置亮度:调用
FastLED.setBrightness(brightness)设置亮度级别 - 友好反馈:通过
switch语句将数字级别转换为用户易懂的描述文字
总结
本节程序在上一节的基础上,实现了以下核心进阶:
- 多工具定义:在
tools数组中同时定义了开关控制和亮度调节两个工具 - 多工具调用:
parseToolCallsResponse函数能够根据 AI 返回的函数名,调用不同的处理逻辑 - 参数范围约束:使用
minimum和maximum限制亮度级别在 1-5 之间,确保 AI 生成的参数在合法范围内
理解了这个多工具调用的模式后,就可以进一步扩展:添加更多工具函数(如调节颜色、设置闪烁模式、读取传感器数据等),构建功能更丰富的 AI 物联网应用。
基础知识篇目录
第〇章 (AID101-1-0) 序言
第一章 (AID101-1-1) 准备工作
第二章 (AID101-1-2) AI大模型API交互基础
- AID101-1-2-01 – 使用ESP32调用AI大模型API的基本操作
- AID101-1-2-02 – System Role详解
- AID101-1-2-03 – User Role 详解
- AID101-1-2-04 – Assistant Role详解
- AID101-1-2-05 -大模型API交互基础知识总结及练习
第三章 (AID101-1-3) AI大模型工具调用(tools call)
- AID101-1-3-01 – AI大模型工具调用(tools call)基础
- AID101-1-3-02 – 单工具定义实例
- AID101-1-3-03 – 多工具定义实例
- AID101-1-3-04 – 后续工具调用(follow-up tools call)实例
- AID101-1-3-05 – 并行多工具调用(parallel tool calls)实例
- AID101-1-3-06 – 应用开发实例: 可用自然语言控制的人工智能LED
附录