导航栏:首页 / AI教程目录 / AI创客项目开发教程目录 / 第1篇 基础知识篇 / AID101-1-2-04–Assistant Role详解
本节内容简介
本节将详细讲解 Assistant Role(助手角色)在 ESP32 开发板上调用 AI 平台 API 实现多轮对话的工作原理。通过本节课程,您将理解 Assistant Role 如何在对话中存储 AI 的回答,如何通过携带对话历史实现上下文感知的连续对话,以及如何在实际应用中动态管理多轮对话。
Assistant Role(助手角色)详解
什么是 Assistant Role?
Assistant Role(助手角色)是 AI 大语言模型 API 调用中用于存储 AI 回答的角色。在多轮对话中,每一轮 AI 的回答都会被记录为 Assistant Role,并携带在下一轮请求的 messages 数组中,从而使 AI 能够理解对话的上下文,实现连贯的交互体验。
核心作用:
- 💬 回答存储:记录 AI 在每一轮对话中的回答内容
- 🔄 上下文传递:将历史对话信息传递给 AI,使其理解对话脉络
- 🧠 连续对话:支持多轮问答,让对话更加自然连贯
- 📝 对话管理:帮助程序跟踪和管理对话历史
为什么需要 Assistant Role?
与人类对话一样,与 AI 的连续对话也需要”记忆”。当用户与AI交流时,如果没有上下文,AI 无法理解用户在之前的对话中的交流内容,通过 Assistant Role,我们将 AI 每一轮的回答都记录下来,并在下一轮请求时一同发送,这样 AI 就能理解完整的对话上下文。
Assistant Role 与 System Role、User Role 的关系
三种角色的协作分工
| 角色 | 作用 | 内容来源 | 变化频率 |
|---|---|---|---|
| System Role | 设定 AI 的行为规则和身份 | 开发者预设 | 通常固定 |
| User Role | 用户的提问和指令 | 用户输入 | 每次对话都可能变化 |
| Assistant Role | AI 的回答记录 | AI 自动生成 | 每轮对话都会新增 |
messages 数组中三种消息的顺序
messages 数组中的消息顺序非常重要,AI 模型按照消息出现的顺序来理解对话上下文。因此,必须严格按照时间顺序排列消息:
正确顺序:
1. system (最先)
2. user (第一轮用户问题)
3. assistant (第一轮AI回答)
4. user (第二轮用户问题)
5. assistant (第二轮AI回答)
6. user (第三轮用户问题)
...以此类推
示例程序一:带有上下文的单轮对话
注意
本程序需要配合my_info.h代码使用,否则程序将无法正常编译。
请点击以下链接前往该代码页面,复制下载该代码:
http://ai.taichi-maker.com/index.php/homepage/ai-tutorial-index/ai-maker-project-tutorial-index/my_info_h-code-description/
/*
* ESP32 AI平台调用 Assistant角色示例
*
* 功能描述:
* 本程序演示如何在 ESP32(特别是 ESP32-S3)开发板上,通过 HTTPS 协议向 AI 平台
* 发送带有上下文的对话请求,展示如何使用 assistant role 实现多轮对话功能。
*
* 本程序仅执行一次对话请求,但这次请求中包含了完整的对话历史,
* 模拟了多轮对话中的"第二轮"场景,演示 assistant role 如何传递上下文。
*
* 对话场景:
* - User(第一轮): 帮我计算2的2次方
* - AI(第一轮回答): 2的2次方等于4。计算方法是:2 × 2 = 4。
* - User(第二轮/本程序请求点): 那3呢
*
* 通过本程序,初学者可以清晰理解:当 AI 需要理解上下文时,
* 需要在请求中携带之前的对话历史(通过 assistant role)。
*
* 作者:Taichi-Maker
* 作者官网:http://ai.taichi-maker.com
* 创建日期:2026年03月27日
* 版本:1.0.1
*
* 硬件要求:
* - 支持 Wi-Fi 的 ESP32 开发板(推荐使用 ESP32-S3-DevKitC-1,因其性能更好、内存更大)
*
* 所需软件库:
* - ArduinoJson 库(版本 7.0.0 或更高)——用于处理 JSON 数据(虽然本例中请求体为硬编码,但响应解析通常需要它)
* 官网:https://arduinojson.org/
*
* 配置说明:
*
* 1. 在 my_info.h 文件中填写您的 Wi-Fi 名称(ssid)和密码(password)。
* 2. 在 my_info.h 文件中将 ai_api_key 替换为您从 AI 平台获取的有效 API 密钥(切勿泄露!)。
* 3. 确保开发板已正确连接到电脑,并选择正确的开发板型号与端口。
*
* 使用方法:
* 将本程序上传至 ESP32 后,打开串口监视器(波特率设置为 115200),
* 程序会自动连接 Wi-Fi 并向 AI 平台发送两次请求,每次请求都会包含之前的对话历史,
* 从而实现上下文感知的多轮对话。
*
* 注意事项:
* - 本例使用 client.setInsecure() 跳过了 SSL 证书验证,仅适用于测试环境;
* 在生产环境中应使用有效证书以确保通信安全。
* - 请求仅在 setup() 中执行两次,loop() 为空,不会重复发送。
*
* 兼容性说明:
* 本程序已在 ESP32-S3-DevKitC-1 开发板上测试通过。
*
* 许可证:MIT License
*
* 程序源:
* 本程序源自太极创客团队精心开发的《AI创客项目开发教程》。该教程专为热爱科技创新、热衷于动手实践 * 创客爱好者与初学者量身打造,是一套完全免费、开源且注重实战的AIoT(人工智能物联网)入门学习资源。
*
* 通过本教程,您可以系统地掌握从项目构思、方案设计、软硬件选型,到实际搭建、系统集成与调试优化的 * 整开发流程。
* 您可以通过以下链接获得更多关于本教程的详细信息:
* http://ai.taichi-maker.com/index.php/homepage/ai-tutorial/
*/
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include "my_info.h"
// 创建一个安全的 Wi-Fi 客户端(用于 HTTPS 连接)
WiFiClientSecure client;
// 创建一个 HTTP 客户端对象,用于发送请求
HTTPClient https;
/*
* -------------- 带有上下文的对话请求体 --------------
*
* 此处使用 C++11 的原始字符串字面量(Raw String Literal)语法 R"rawliteral(...)rawliteral"
* 来定义一个多行 JSON 字符串,避免手动转义双引号和换行符。
*
* 该 JSON 符合 OpenAI API 兼容格式,包含以下关键字段:
* - model: 指定要调用的 AI 模型名称
* - messages: 对话历史,包含 system、user、assistant、user 四条消息
*
* 本请求体模拟了多轮对话中的"第二轮"场景:
* - system: 设定 AI 的身份
* - user(第一轮): 帮我计算2的2次方
* - assistant(第一轮回答): 2的2次方等于4。计算方法是:2 × 2 = 4。
* - user(第二轮): 那3呢
*
* 通过携带前面对话历史,AI 能够理解"那3呢"是指"3的2次方等于几"。
*/
const char* request_payload = R"rawliteral({
"model": "Qwen/Qwen3-VL-8B-Instruct",
"messages": [
{
"role": "system",
"content": "你是一个智能助理"
},
{
"role": "user",
"content": "帮我计算2的2次方"
},
{
"role": "assistant",
"content": "2的2次方等于4。计算方法是:2 × 2 = 4。"
},
{
"role": "user",
"content": "那3呢"
}
]
})rawliteral";
void setup() {
// 初始化串口通信,波特率为 115200
Serial.begin(115200);
delay(1000); // 短暂等待串口稳定
Serial.println();
Serial.println("---------- AI Platform Config ----------");
Serial.print("AI Platform API Endpoint: ");
Serial.print(ai_host);
Serial.println(ai_endpoint);
Serial.println();
Serial.println("---------- Procedures ----------");
Serial.println("Step 1: Connecting WiFi...");
// 开始连接 Wi-Fi
WiFi.begin(ssid, password);
// 循环等待直到成功连接
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("Step 2: WiFi Connected!");
Serial.println("Step 3: Initialize HTTPS Connection...");
// 【重要】跳过 SSL 证书验证(仅用于开发测试!)
// 在真实产品中应加载有效证书以防止中间人攻击
client.setInsecure();
// 设置SSL连接超时时间
client.setTimeout(15); // 15秒超时
Serial.println("Step 4: Send Request to AI Platform...");
Serial.println();
// 发送带有上下文的请求
sendAIRequest(request_payload, "带有上下文的对话请求");
Serial.println();
Serial.println("Step 5: Task Completed!");
}
// 主循环留空,因为本例只需发送一次请求
void loop() {
// 空
}
/*
* -------------- 向 AI 平台发送 HTTPS 请求的核心函数 --------------
*
* 该函数完成以下步骤:
* 1. 构造完整的 HTTPS 请求 URL(基于 my_info.h 中定义的主机、端口和路径)
* 2. 设置请求头:Content-Type 为 application/json,Authorization 为 Bearer + API 密钥
* 3. 发送 POST 请求,携带上述 JSON 请求体
* 4. 接收并打印 HTTP 响应状态码和响应内容
*
* 参数:
* - payload: 要发送的 JSON 请求体
* - description: 请求的描述名称,用于输出显示
*/
void sendAIRequest(const char* payload, const char* description) {
// 构造 Authorization 请求头:格式为 "Bearer <your-api-key>"
String auth = "Bearer ";
auth += ai_api_key;
// 初始化 HTTPS 连接(使用 client、主机名、端口、API 路径)
if (https.begin(client, ai_host, ai_port, ai_endpoint)) {
// 设置超时时间(毫秒)- 增加超时时间以处理更复杂的请求
https.setTimeout(20000); // 20秒超时
https.setConnectTimeout(10000); // 10秒连接超时
// 添加必要的 HTTP 请求头
https.addHeader("Content-Type", "application/json");
https.addHeader("Authorization", auth);
// 发送 POST 请求,并获取 HTTP 状态码
int httpCode = https.POST(payload);
Serial.println("---------- " + String(description) + " Response ----------");
if (httpCode > 0) {
// 打印 HTTP 响应状态码(如 200 表示成功)
Serial.print("HTTP Response Code: ");
Serial.println(httpCode);
// 如果响应成功(HTTP 200 OK)
if (httpCode == HTTP_CODE_OK) {
// 获取完整的响应字符串
String resp = https.getString();
Serial.println("AI Response : ");
Serial.println(resp); // 打印 AI 返回的完整 JSON(含模型生成的回答)
}
} else {
// 打印 HTTP 错误信息(如连接失败、超时等)
Serial.print("HTTP error: ");
Serial.println(https.errorToString(httpCode).c_str());
Serial.print("Error code: ");
Serial.println(httpCode);
}
Serial.println("========================================");
// 结束本次 HTTP 会话,释放资源
https.end();
} else {
// 如果无法建立 HTTPS 连接,打印错误提示
Serial.println("Unable to connect to server");
}
}
/*
* ========================================================================
* 【附录】本程序实际发送的 HTTP 请求内容(供参考)
* ========================================================================
*
* 请求内容:
* POST /api/v3/chat/completions HTTP/1.1
* Host: ark.cn-beijing.volces.com
* Content-Type: application/json
* Authorization: Bearer [你的API密钥]
*
* {
* "model": "Qwen/Qwen3-VL-8B-Instruct",
* "messages": [
* {
* "role": "system",
* "content": "你是一个智能助理"
* },
* {
* "role": "user",
* "content": "帮我计算2的2次方"
* },
* {
* "role": "assistant",
* "content": "2的2次方等于4。计算方法是:2 × 2 = 4。"
* },
* {
* "role": "user",
* "content": "那3呢"
* }
* ]
* }
*
* 说明:
* - 本程序请求包含完整的对话历史,模拟多轮对话中的"第二轮"场景
* - messages 数组中包含:
* 1. system: 设定 AI 身份
* 2. user(第一轮): 第一轮用户提问
* 3. assistant(第一轮回答): 第一轮 AI 回答
* 4. user(第二轮): 第二轮用户提问"那3呢"
* - AI 通过理解完整上下文,能够正确理解"那3呢"是指"3的2次方"
* - 通过这种方式,可以实现具有上下文感知能力的多轮对话
* ========================================================================
*/程序说明:
本程序演示了如何通过 assistant role 实现带有上下文的对话。
本程序仅执行一次请求,这次请求模拟了多轮对话中的”第二轮”场景,包含完整的对话历史:
- User: 帮我计算2的2次方
- AI: 2的2次方等于4。计算方法是:2 × 2 = 4。
- User: 那3呢
关键特点:
- 程序只发送一次请求,但请求中包含了完整的对话历史
- 通过 assistant role 携带 AI 的历史回答
- AI 能够理解上下文,正确理解”那3呢”是指”3的2次方等于几”
关键代码:带有上下文的请求体定义
const char* request_payload = R"rawliteral({
"model": "Qwen/Qwen3-VL-8B-Instruct",
"messages": [
{
"role": "system",
"content": "你是一个智能助理"
},
{
"role": "user",
"content": "帮我计算2的2次方"
},
{
"role": "assistant",
"content": "2的2次方等于4。计算方法是:2 × 2 = 4。"
},
{
"role": "user",
"content": "那3呢"
}
]
})rawliteral";这段代码定义了带有上下文的请求体,包含完整的对话历史,模拟多轮对话中的”第二轮”场景。
关键结构解析:
role: "system"– 设定 AI 的身份role: "user"(第一轮) – 第一轮用户提问role: "assistant"– 第一轮 AI 的回答role: "user"(第二轮) – 第二轮用户提问”那3呢”
为什么这样做?
- 通过携带历史对话,AI 才能理解”那3呢”是追问”3的2次方”
- 这种方式实现了上下文感知的连续对话
对话流程
以下展示的是示例程序请求和AI平台响应流程,请留意:请求中携带了之前的对话历史,使 AI 能够理解上下文
┌─────────────────────────────────────────────────────────────────┐
│ 带有上下文的对话请求 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ESP32 ──────► messages: │
│ [ │
│ {role: "system", content: "你是一个智能助理"}, │
│ {role: "user", content: "帮我计算2的2次方"}, │
│ {role: "assistant", content: "2的2次方等于4。"},│
│ {role: "user", content: "那3呢"} │
│ ] │
│ ▼ │
│ AI 平台理解上下文以及用户提问然后推理回应 │
│ ▼ │
│ ESP32 ◄────── AI 回答: │
│ { │
│ role: "assistant", │
│ content: "3的2次方等于9。" │
│ } │
│ │
└─────────────────────────────────────────────────────────────────┘带有上下文的AI交流关键机制解析
1. 历史记录累积
每完成一轮对话,新的 assistant role 就会被添加到 messages 数组中。随着对话轮次的增加,messages 数组会不断增长,包含越来越多的历史对话。
2. 上下文理解
AI 模型通过读取完整的 messages 数组,理解对话的完整脉络。如,在本示例中,当用户提到”那3呢”时,AI 会结合第一轮的”2的2次方”,理解用户是想问”3的2次方”。
3. 动态消息构建
在实际应用中,每一轮请求都需要重新构建 messages 数组,包含:
- System Role(固定不变)
- 所有的历史对话(User + Assistant)
- 当前的新问题(User)
思考题:
如果我们想要继续以上示例程序中的对话,实现新的一轮与AI交流,在这一轮里,我们需要问AI的问题是“那5呢”,也就是问AI“5的2次方等于几”。为了实现这一请求,我们该如何编写新一轮交流的请求体?
请先不要看以下答案,试着自己思考一下,并且尝试改写以上示例程序,验证你的请求体内容是否正确。
思考题答案:
const char* third_request_payload = R"rawliteral({
"model": "Qwen/Qwen3-VL-8B-Instruct",
"messages": [
{
"role": "system",
"content": "你是一个智能助理"
},
{
"role": "user",
"content": "帮我计算2的2次方"
},
{
"role": "assistant",
"content": "2的2次方等于4。计算方法是:2 × 2 = 4。"
},
{
"role": "user",
"content": "那3呢"
},
{
"role": "assistant",
"content": "3的2次方等于9。计算方法是:3 × 3 = 9。"
},
{
"role": "user",
"content": "那5呢"
}
]
})rawliteral";思考题请求体说明:
本请求体内容在两轮对话的基础上增加了一轮,演示更复杂的多轮对话场景:
- 第一轮对话:用户询问”2的2次方是多少”,AI 回答”4″
- 第二轮对话:用户追问”那3呢”,AI 回答”9″
- 第三轮对话:用户再追问”那5呢”,AI 回答”25″
关键特点:
- 三轮对话形成完整的上下文链
- 每轮请求都携带之前所有的对话历史
- AI 能够追踪多轮对话的脉络
Assistant Role 的实际应用场景
场景1:智能客服
// 第一轮
{ "role": "user", "content": "我想退货" }
// AI回答
{ "role": "assistant", "content": "请问您的订单号是多少?" }
// 第二轮(携带历史)
{ "role": "user", "content": "我想退货" }
{ "role": "assistant", "content": "请问您的订单号是多少?" }
{ "role": "user", "content": "订单号是12345" }
// AI回答(理解上下文,继续退货流程)
{ "role": "assistant", "content": "好的,12345订单正在为您办理退货..." }应用: 客服对话中保持上下文,用户无需重复说明情况
场景2:智能家居控制
// 第一轮
{ "role": "user", "content": "打开客厅的灯" }
// AI回答
{ "role": "assistant", "content": "已打开客厅的灯" }
// 第二轮(携带历史)
{ "role": "user", "content": "打开客厅的灯" }
{ "role": "assistant", "content": "已打开客厅的灯" }
{ "role": "user", "content": "调到最亮" }
// AI回答(理解上下文,操作客厅灯)
{ "role": "assistant", "content": "已将客厅灯调到最亮" }应用: 理解上下文,智能执行连续控制指令
总结
Assistant Role 的核心价值
- 实现上下文理解:通过携带对话历史,AI 能够理解多轮对话的完整脉络
- 支持连续对话:用户无需重复说明背景信息,对话更加自然流畅
- 构建智能应用:为客服、调试、控制等场景提供连贯的交互体验
Assistant Role 的使用要点
- 历史累积:每轮对话后,将 assistant 的回答添加到 messages 数组
- 顺序重要:严格按照时间顺序排列消息
- 成本控制:注意 token 消耗,避免对话过长
- 动态管理:在实际应用中,需要动态构建请求体