Chat Completions 格式
大模型 API 调用最核心的消息格式
1 | exampleMessages = [ |
这种写法非常常见,但并不是所有大模型调用都完全一样
每条消息都有:
- role:角色
- content:内容
role:目前主流 API(OpenAI、通义、DeepSeek、Claude 等)基本都有类似概念
| role | 含义 | 谁发送 | 优先级 |
|---|---|---|---|
| system | 系统指令 | 开发者 | 最高 |
| user | 用户输入 | 用户 | 中 |
| assistant | 模型回答 | AI | 中 |
| tool | 工具返回结果 | 外部工具 | 特殊 |
assistant:模型历史回答
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16messages=[
{
"role":"user",
"content":"介绍一下Python"
},
{
"role":"assistant",
"content":"Python是一门编程语言..."
},
{
"role":"user",
"content":"它适合做什么?"
}
]
于是模型知道:"它" = Python。tool:工具调用结果 这是 Agent 最重要的部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48你让 Agent 查询天气。
流程:
第一步
用户:
北京天气怎么样?
模型:
我要调用天气工具
消息:
{
"role":"assistant",
"tool_calls":[
{
"name":"weather",
"arguments":{
"city":"北京"
}
}
]
}
然后你的程序调用天气 API:
返回:
{
"role":"tool",
"content":"北京今天晴,25度"
}
再给模型:
[
user,
assistant(tool_call),
tool(result)
]
模型:
北京今天晴,25度,适合出行。
智能体范式ReAct (Reason + Act)
ReAct由Shunyu Yao于2022年提出[1],其核心思想是模仿人类解决问题的方式,将推理 (Reasoning) 与行动 (Acting) 显式地结合起来,形成一个“思考-行动-观察”的循环。
这种机制特别适用于以下场景:
- 需要外部知识的任务:如查询实时信息(天气、新闻、股价)、搜索专业领域的知识等。
- 需要精确计算的任务:将数学问题交给计算器工具,避免LLM的计算错误。
- 需要与API交互的任务:如操作数据库、调用某个服务的API来完成特定功能。
Plan-and-Solve
先规划 (Plan),后执行 (Solve)
Plan-and-Solve Prompting 由 Lei Wang 在2023年提出[2]。其核心动机是为了解决思维链在处理多步骤、复杂问题时容易“偏离轨道”的问题。
Plan-and-Solve 将整个流程解耦为两个核心阶段:
- 规划阶段 (Planning Phase): 首先,智能体会接收用户的完整问题。它的第一个任务不是直接去解决问题或调用工具,而是将问题分解,并制定出一个清晰、分步骤的行动计划。这个计划本身就是一次大语言模型的调用产物。
- 执行阶段 (Solving Phase): 在获得完整的计划后,智能体进入执行阶段。它会严格按照计划中的步骤,逐一执行。每一步的执行都可能是一次独立的 LLM 调用,或者是对上一步结果的加工处理,直到计划中的所有步骤都完成,最终得出答案。
Reflection
在 ReAct 和 Plan-and-Solve 范式中,智能体一旦完成了任务,其工作流程便告结束。然而,它们生成的初始答案,无论是行动轨迹还是最终结果,都可能存在谬误或有待改进之处。Reflection 机制的核心思想,正是为智能体引入一种事后(post-hoc)的自我校正循环,使其能够像人类一样,审视自己的工作,发现不足,并进行迭代优化。
Reflection 机制的灵感来源于人类的学习过程:我们完成初稿后会进行校对,解出数学题后会进行验算。这一思想在多个研究中得到了体现,例如 Shinn, Noah 在2023年提出的 Reflexion 框架[3]。其核心工作流程可以概括为一个简洁的三步循环:执行 -> 反思 -> 优化。
执行 (Execution):首先,智能体使用我们熟悉的方法(如 ReAct 或 Plan-and-Solve)尝试完成任务,生成一个初步的解决方案或行动轨迹。这可以看作是“初稿”。
反思 (Reflection)
:接着,智能体进入反思阶段。它会调用一个独立的、或者带有特殊提示词的大语言模型实例,来扮演一个“评审员”的角色。这个“评审员”会审视第一步生成的“初稿”,并从多个维度进行评估,例如:
- 事实性错误:是否存在与常识或已知事实相悖的内容?
- 逻辑漏洞:推理过程是否存在不连贯或矛盾之处?
- 效率问题:是否有更直接、更简洁的路径来完成任务?
- 遗漏信息:是否忽略了问题的某些关键约束或方面? 根据评估,它会生成一段结构化的反馈 (Feedback),指出具体的问题所在和改进建议。
优化 (Refinement):最后,智能体将“初稿”和“反馈”作为新的上下文,再次调用大语言模型,要求它根据反馈内容对初稿进行修正,生成一个更完善的“修订稿”。
习题
1、本章介绍了三种经典的智能体范式:ReAct、Plan-and-Solve 和 Reflection。请分析:
(1)这三种范式在”思考”与”行动”的组织方式上有什么本质区别?
三种智能体范式最大的区别在于:
思考发生在什么时候?行动是否立即执行?是否有事后检查和修正机制?
可以从以下几个角度比较:
| 范式 | 思考方式 | 行动方式 | 核心特点 |
|---|---|---|---|
| ReAct | 边思考边行动 | 思考一步,行动一步 | 强调实时交互和工具调用 |
| Plan-and-Solve | 先完整规划,再执行 | 按计划逐步行动 | 强调任务分解和长期规划 |
| Reflection | 行动后反思改进 | 根据反馈调整下一轮行动 | 强调自我纠错和优化 |
(2)如果要设计一个”智能家居控制助手”(需要控制灯光、空调、窗帘等多个设备,并根据用户习惯自动调节),你会选择哪种范式作为基础架构?为什么?
场景分析:智能家居助手具有几个特点
设备很多(灯光, 空调, 窗帘, 门锁, 摄像头, 音响)
环境实时变化
需要根据习惯自动调整
基于以上分析,选择 ReAct 作为基础架构
智能家居本质是:
感知环境 → 判断 → 执行动作 → 获取反馈 → 再调整
非常符合 ReAct:
1 | 用户请求 → Reason:理解用户意图 → Act:控制设备 → Observation:读取设备状态 → Reason:判断是否完成 → Act:继续调整 |
为什么不是 Plan-and-Solve?(因为智能家居环境变化快, ReAct 更适合动态环境)
为什么不是 Reflection?(Reflection 更适合:写代码、写文章、生成方案,智能家居更多关注:实时响应,而不是生成高质量文本。)
(3)是否可以将这三种范式进行组合使用?若可以,请尝试设计一个混合范式的智能体架构,并说明其适用场景。
可以,而且实际系统通常都会组合
单一范式都有缺陷:
- ReAct:缺少长期规划
- Plan:缺少环境适应
- Reflection:增加成本
组合后可以形成更强大的 Agent。
一个混合智能家居 Agent 架构设计:
1 | 用户 → Plan-and-Solve规划层(制定长期目标和任务计划) → ReAct执行层(实时控制设备和获取状态) → Reflection层(分析执行效果并优化策略) → 用户习惯模型 |
混合架构适合场景:
| 场景 | 推荐组合 |
|---|---|
| 智能家居 | Plan + ReAct + Reflection |
| 自动驾驶 | ReAct + Reflection |
| AI程序员 | Plan + ReAct + Reflection |
| 企业流程自动化 | Plan + ReAct |
| 搜索助手 | ReAct |
| 内容创作 | Reflection |
推荐以 ReAct 为核心,结合 Plan-and-Solve 负责长期任务规划,再加入 Reflection 优化用户习惯模型。
最终形成:
1 | 长期规划(Plan) |
在4.2节的 ReAct 实现中,我们使用了正则表达式来解析大语言模型的输出(如 Thought 和 Action)。请思考:
(1)当前的解析方法存在哪些潜在的脆弱性?在什么情况下可能会失败?
正则解析的问题:
| 问题 | 原因 |
|---|---|
| 格式敏感 | 依赖固定字符串 |
| 容易误匹配 | 自然语言不确定 |
| 复杂参数困难 | 无法理解结构 |
| 维护成本高 | 规则越来越复杂 |
| 容错能力弱 | LLM输出不可控 |
(2)除了正则表达式,还有哪些更鲁棒的输出解析方案?
方案1:JSON 格式输出
推荐
1 | 让模型输出: |
优势:结构明确,易解析,支持嵌套参数 方便调试
缺点:需要模型严格输出 JSON,老模型可能生成非法 JSON
方案2:Function Calling / Tool Calling
目前工业界更推荐的方法,模型不会自己编造格式,而是调用 API 定义好的函数
定义工具:
1 | tools = [ |
模型返回:
1 | { |
优点:类型安全,参数自动校验,工具管理方便
缺点:依赖模型支持,实现复杂一些
目前:OpenAI Agents、LangChain、AutoGen 都大量使用这种方式。
方案3:Structured Output(结构化输出)
1 | 定义: |
优势:比 JSON 更严格。
方案4:XML 格式
1 | <thought> |
优点:层级清晰,易解析
缺点:Token 消耗较高
(3)尝试修改本章的代码,使用一种更可靠的输出格式,并对比两种方案的优缺点
修改:
1 | # (此处省略 REACT_PROMPT_TEMPLATE 的定义)正则 |
输出:
1 | (hello-agents) PS E:\AI\hello-agents\code\chapter4> python ReAct.py |