Agent基础与架构¶
⚠️ 时效性说明:本章涉及前沿模型/价格/榜单等信息,可能随版本快速变化;请以论文原文、官方发布页和 API 文档为准。
深入理解AI Agent的核心概念、ReAct范式和设计模式,从零手写一个最简Agent框架。
📌 定位说明:本章从动手实践视角讲解Agent基础并手写框架。 - 框架视角(LangChain/LangGraph Agent开发)→ LLM应用/07-Agent开发基础 - 研究视角(智能体系统前沿)→ LLM学习/04-前沿探索/02-智能体系统
📖 章节导读¶
AI Agent是能够自主感知环境、推理决策、执行动作的智能系统。与传统的单次LLM调用不同,Agent具备循环推理和工具使用的能力,能够自动完成复杂多步任务。本章将从理论到实践,带你全面理解Agent的核心架构。
🎯 学习目标¶
- 理解Agent的定义与核心能力
- 掌握ReAct(Reasoning + Acting)范式
- 了解Agent四大核心组件:LLM/工具/记忆/规划
- 学习Agent设计模式(路由、反思、工具使用、提示链、并行化、编排者-Subagent)
- 手写一个完整的最简Agent框架
- 掌握Tool Calling的JSON Schema规范
📖 前置知识¶
- Python异步编程(async/await)
- OpenAI API基本调用
- JSON Schema基础
1. Agent概述¶
1.1 什么是AI Agent?¶
AI Agent(智能体) 是一种基于大语言模型的自主系统,能够:
- 🧠 推理:理解任务、分析问题、制定计划
- 🔧 行动:调用外部工具、API和服务
- 💾 记忆:存储和检索历史信息
- 🔄 迭代:根据执行结果调整策略
1.2 Agent vs 传统LLM应用¶
| 特性 | 传统LLM应用 | AI Agent |
|---|---|---|
| 执行模式 | 单次调用 | 多步循环 |
| 工具使用 | 无或有限 | 丰富的工具集 |
| 决策能力 | 预定义流程 | 自主决策 |
| 记忆 | 无状态/有限上下文 | 短期+长期记忆 |
| 复杂任务 | 难以处理 | 自动分解和执行 |
| 错误恢复 | 需人工干预 | 自动重试和调整 |
1.3 Agent的典型应用场景¶
# Agent应用场景示例
agent_applications = {
"代码助手": "理解需求 → 搜索文档 → 编写代码 → 运行测试 → 修复bug",
"研究助手": "接收课题 → 搜索文献 → 阅读论文 → 提取要点 → 生成报告",
"数据分析": "理解问题 → 查询数据库 → 分析数据 → 生成图表 → 撰写结论",
"客服系统": "理解问题 → 查询知识库 → 检索订单 → 生成回复 → 跟进满意度",
"自动化运维": "监控告警 → 分析日志 → 定位问题 → 执行修复 → 验证结果",
}
2. ReAct范式¶
2.1 ReAct原理¶
ReAct(Reasoning + Acting) 是目前最主流的Agent范式,由Yao et al. (2023)提出。核心思想是让LLM在推理(Thought)和行动(Action)之间交替进行:
循环开始:
1. Thought(推理): 分析当前状态,决定下一步
2. Action(行动): 选择并执行一个工具/动作
3. Observation(观察): 获取执行结果
4. 判断: 任务完成?→ 是: 返回结果 否: 回到步骤1
2.2 ReAct工作流程图¶
用户提问: "北京今天天气怎么样?推荐穿什么?"
│
▼
┌─────────────────────────────────────┐
│ Thought: 用户想知道北京天气和穿衣建议 │
│ 我需要先查询天气信息 │
│ Action: search_weather("北京") │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Observation: 北京今天晴,15-25°C │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Thought: 已获取天气信息,温差较大 │
│ 可以直接给出穿衣建议,无需调用更多工具 │
│ Action: finish(回答) │
└─────────────────────────────────────┘
│
▼
最终回答: "北京今天晴,15-25°C,建议穿薄外套..."
2.3 ReAct代码实现¶
"""
ReAct范式的基础实现
展示Thought-Action-Observation循环
"""
from openai import OpenAI
client = OpenAI()
REACT_SYSTEM_PROMPT = """你是一个有用的AI助手,你使用ReAct方法来回答问题。
对于每个步骤,你必须严格按照以下格式输出:
Thought: <你的推理过程>
Action: <工具名称>(<参数>)
当你已经有足够信息回答问题时,使用:
Thought: <你的推理过程>
Action: finish(<最终答案>)
可用工具:
- search(query): 搜索信息
- calculate(expression): 计算数学表达式
- get_weather(city): 获取城市天气
重要:每次只输出一个Thought和一个Action。"""
def parse_action(response_text: str) -> tuple[str, str]:
"""解析LLM输出中的Action"""
lines = response_text.strip().split("\n")
for line in lines:
if line.startswith("Action:"):
action_str = line[len("Action:"):].strip()
# 解析函数名和参数,容错处理格式异常
if "(" not in action_str or ")" not in action_str:
return action_str, "" # 无参数格式,返回整行作为函数名
paren_idx = action_str.index("(")
func_name = action_str[:paren_idx].strip()
args = action_str[paren_idx + 1:-1].strip()
return func_name, args
return "", ""
def execute_tool(func_name: str, args: str) -> str:
"""执行工具调用(模拟实现)"""
import ast
import operator
def _safe_calc(expr: str) -> str:
"""基于AST的安全数学表达式计算(仅允许数字和四则运算)。
不使用eval,通过遍历AST节点确保安全性。"""
# 定义允许的运算符(仅四则运算)
allowed_ops = {
ast.Add: operator.add, ast.Sub: operator.sub,
ast.Mult: operator.mul, ast.Div: operator.truediv,
}
def _eval_node(node):
"""递归求值AST节点"""
if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
return node.value
elif isinstance(node, ast.BinOp) and type(node.op) in allowed_ops:
return allowed_ops[type(node.op)](_eval_node(node.left), _eval_node(node.right))
elif isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.USub):
return -_eval_node(node.operand)
else:
raise ValueError(f"不支持的表达式: {expr}")
try:
tree = ast.parse(expr.strip(), mode='eval')
result = _eval_node(tree.body)
except (SyntaxError, ValueError) as e:
return f"计算错误: {e}"
return str(result)
# lambda是匿名函数:lambda 参数: 返回值,这里用作字典值实现工具分发
tools = {
"search": lambda q: f"搜索结果: {q}相关的信息...",
"calculate": lambda expr: f"计算结果: {_safe_calc(expr)}",
"get_weather": lambda city: f"{city}今天晴,温度15-25°C,湿度40%",
"finish": lambda answer: answer,
}
if func_name in tools:
return tools[func_name](args)
return f"未知工具: {func_name}"
def react_agent(question: str, max_steps: int = 5) -> str:
"""ReAct Agent主循环"""
messages = [
{"role": "system", "content": REACT_SYSTEM_PROMPT},
{"role": "user", "content": question},
]
for step in range(max_steps):
print(f"\n--- Step {step + 1} ---")
# 1. 让LLM推理并选择动作
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
temperature=0,
)
assistant_msg = response.choices[0].message.content
print(assistant_msg)
# 2. 解析动作
func_name, args = parse_action(assistant_msg)
# 3. 如果是finish动作,返回结果
if func_name == "finish":
return args
# 4. 执行工具并获取观察结果
observation = execute_tool(func_name, args)
print(f"Observation: {observation}")
# 5. 将结果加入对话历史
messages.append({"role": "assistant", "content": assistant_msg})
messages.append({"role": "user", "content": f"Observation: {observation}"})
return "达到最大步骤数,未能完成任务"
# 运行示例
if __name__ == "__main__":
result = react_agent("北京今天天气怎么样?如果温度超过20度,计算20*1.8+32等于多少华氏度")
print(f"\n最终结果: {result}")
3. Agent核心组件¶
3.1 组件架构总览¶
┌───────────────────────────────────────┐
│ AI Agent │
│ │
│ ┌─────────┐ ┌─────────────────┐ │
│ │ 🧠 LLM │ │ 📋 规划(Planning) │ │
│ │ (大脑) │ │ 任务分解/排序 │ │
│ └────┬─────┘ └────────┬────────┘ │
│ │ │ │
│ ┌────▼─────────────────▼────────┐ │
│ │ 🔧 工具(Tools) │ │
│ │ API调用 / 代码执行 / 搜索 │ │
│ └────────────────┬──────────────┘ │
│ │ │
│ ┌────────────────▼──────────────┐ │
│ │ 💾 记忆(Memory) │ │
│ │ 短期记忆 / 长期记忆 / 工作记忆 │ │
│ └───────────────────────────────┘ │
└───────────────────────────────────────┘
3.2 LLM(大脑)¶
LLM是Agent的核心推理引擎,负责理解任务、制定计划和生成响应。
"""
Agent的LLM组件 - 推理引擎
"""
from openai import OpenAI
from typing import Any
class AgentLLM:
"""Agent的LLM推理引擎"""
def __init__(self, model: str = "gpt-4o", temperature: float = 0):
self.client = OpenAI()
self.model = model
self.temperature = temperature
def think(self, messages: list[dict], tools: list[dict] | None = None) -> Any:
"""执行一次推理"""
kwargs = {
"model": self.model,
"messages": messages,
"temperature": self.temperature,
}
if tools:
kwargs["tools"] = tools
kwargs["tool_choice"] = "auto"
# **kwargs将字典解包为关键字参数,等价于create(model=..., messages=..., ...)
response = self.client.chat.completions.create(**kwargs)
return response.choices[0].message
def stream_think(self, messages: list[dict]):
"""流式推理(用于实时输出)"""
stream = self.client.chat.completions.create(
model=self.model,
messages=messages,
temperature=self.temperature,
stream=True,
)
for chunk in stream:
if chunk.choices[0].delta.content:
yield chunk.choices[0].delta.content
3.3 工具系统(Tools)¶
工具是Agent与外部世界交互的接口,让Agent能够获取信息、执行操作。
"""
Agent工具系统
"""
import json
from typing import Callable
from dataclasses import dataclass, field
@dataclass
class Tool:
"""工具定义"""
name: str
description: str
parameters: dict # JSON Schema格式
function: Callable # 实际执行的函数
class ToolRegistry:
"""工具注册中心"""
def __init__(self):
self._tools: dict[str, Tool] = {}
def register(self, name: str, description: str, parameters: dict):
"""装饰器:注册工具"""
def decorator(func: Callable):
self._tools[name] = Tool(
name=name,
description=description,
parameters=parameters,
function=func,
)
return func
return decorator
def execute(self, name: str, arguments: dict) -> str:
"""执行指定工具"""
if name not in self._tools:
return json.dumps({"error": f"工具 {name} 不存在"})
try:
result = self._tools[name].function(**arguments)
# 三元表达式: A if 条件 else B;isinstance第二个参数用元组表示"是其中任一类型"
return json.dumps(result, ensure_ascii=False) if isinstance(result, (dict, list)) else str(result)
except Exception as e:
return json.dumps({"error": f"工具执行失败: {str(e)}"})
def get_openai_tools(self) -> list[dict]:
"""导出为OpenAI Tool Calling格式"""
return [
{
"type": "function",
"function": {
"name": tool.name,
"description": tool.description,
"parameters": tool.parameters,
},
}
for tool in self._tools.values()
]
# === 使用示例 ===
registry = ToolRegistry()
@registry.register(
name="search_web",
description="搜索互联网信息",
parameters={
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "搜索关键词",
}
},
"required": ["query"],
},
)
def search_web(query: str) -> dict:
"""模拟网络搜索"""
return {"results": [f"搜索 '{query}' 的结果1", f"搜索 '{query}' 的结果2"]}
@registry.register(
name="calculate",
description="执行数学计算",
parameters={
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "数学表达式,如 '2+3*4'",
}
},
"required": ["expression"],
},
)
def calculate(expression: str) -> dict:
"""安全地计算数学表达式
⚠️ 安全提示: 即使做了字符白名单,eval() 仍存在安全隐患。
生产环境请使用 simpleeval 库:
from simpleeval import simple_eval
return {"result": simple_eval(expression)}
"""
allowed_chars = set("0123456789+-*/.() ")
# all(生成器): 检查expression每个字符是否都在白名单中,有一个不在就返回False
if not all(c in allowed_chars for c in expression):
return {"error": "不支持的字符"}
# 限制表达式长度,降低风险
if len(expression) > 100:
return {"error": "表达式过长"}
return {"result": eval(expression)} # noqa: S307 — 生产环境请替换为 simpleeval
# 查看生成的OpenAI格式工具定义
print(json.dumps(registry.get_openai_tools(), indent=2, ensure_ascii=False))
3.4 记忆系统(Memory)¶
记忆系统让Agent能够存储和检索历史信息,实现跨对话的上下文保持。
"""
Agent记忆系统
支持短期记忆(对话历史)和长期记忆(向量存储)
"""
from dataclasses import dataclass, field
from datetime import datetime
import json
@dataclass
class MemoryItem:
"""记忆条目"""
content: str
role: str # user/assistant/system/tool
# field(default_factory=函数): 每次创建实例时调用该函数生成默认值
# 不能直接写 timestamp: datetime = datetime.now(),否则所有实例共享同一个时间
timestamp: datetime = field(default_factory=datetime.now)
metadata: dict = field(default_factory=dict) # 每个实例独立的空字典,不会共享引用
class ShortTermMemory:
"""短期记忆 - 基于滑动窗口的对话历史"""
def __init__(self, max_messages: int = 20):
self.messages: list[MemoryItem] = []
self.max_messages = max_messages
def add(self, role: str, content: str, **metadata):
"""添加记忆"""
self.messages.append(MemoryItem(
content=content, role=role, metadata=metadata
))
# 超出限制时,保留system消息,裁剪早期消息
if len(self.messages) > self.max_messages:
# 列表推导式: [表达式 for 变量 in 可迭代对象 if 条件],从列表中按条件筛选
system_msgs = [m for m in self.messages if m.role == "system"]
other_msgs = [m for m in self.messages if m.role != "system"]
# 计算非system消息的保留数量,确保不为负数
keep_count = max(0, self.max_messages - len(system_msgs))
if keep_count > 0:
# 负数切片 [-n:] 表示取列表最后n个元素
self.messages = system_msgs + other_msgs[-keep_count:]
else:
# 极端情况:system消息已超过上限,只保留最近的system消息
self.messages = system_msgs[-self.max_messages:]
def get_messages(self) -> list[dict]:
"""获取OpenAI格式的消息列表"""
# 列表推导: 将MemoryItem对象列表转换为字典列表(OpenAI API要求的格式)
return [{"role": m.role, "content": m.content} for m in self.messages]
def clear(self):
"""清空记忆"""
self.messages.clear()
def summarize(self, llm) -> str:
"""使用LLM对历史对话进行摘要压缩"""
# "分隔符".join(列表): 用分隔符把列表元素拼接成一个字符串
history = "\n".join([f"{m.role}: {m.content}" for m in self.messages])
summary_prompt = f"请将以下对话历史压缩为简洁的摘要:\n{history}"
# 调用LLM生成摘要
return llm.think([{"role": "user", "content": summary_prompt}]).content
class LongTermMemory:
"""长期记忆 - 基于向量检索的持久化记忆"""
def __init__(self):
# 简化实现,实际应使用向量数据库(Chroma/Milvus等)
self.memories: list[dict] = []
def store(self, content: str, metadata: dict | None = None):
"""存储长期记忆"""
self.memories.append({
"content": content,
"metadata": metadata or {},
"timestamp": datetime.now().isoformat(),
})
def search(self, query: str, top_k: int = 5) -> list[dict]:
"""搜索相关记忆(简化版,实际应用向量相似度)"""
# 简单的关键词匹配,实际应使用embedding + cosine similarity
results = []
for memory in self.memories:
# any(生成器): 只要query中有任意一个词出现在记忆内容里,就返回True
if any(word in memory["content"] for word in query.split()):
results.append(memory)
return results[:top_k]
def save_to_file(self, filepath: str):
"""持久化存储到文件"""
with open(filepath, "w", encoding="utf-8") as f:
json.dump(self.memories, f, ensure_ascii=False, indent=2)
def load_from_file(self, filepath: str):
"""从文件加载"""
with open(filepath, "r", encoding="utf-8") as f:
self.memories = json.load(f)
# 使用示例
memory = ShortTermMemory(max_messages=10)
memory.add("system", "你是一个有用的AI助手。")
memory.add("user", "你好,请帮我查一下Python的最新版本。")
memory.add("assistant", "Python最新版本请以官方发布为准,建议查看python.org获取最新信息。")
print("对话历史:")
for msg in memory.get_messages():
print(f" {msg['role']}: {msg['content']}")
3.5 规划系统(Planning)¶
规划系统负责将复杂任务分解为可执行的子任务序列。
"""
Agent规划系统
支持任务分解和执行计划生成
⚠️ 关键设计:规划时必须将可用工具列表注入 Prompt,
否则 LLM 会幻觉出不存在的工具名,导致计划无法执行。
这与 LangGraph plan-and-execute、AutoGPT Commands 注入、
CrewAI tools 绑定等业界实践一致。
"""
import json
from openai import OpenAI
client = OpenAI()
PLANNING_PROMPT = """你是一个任务规划专家。请将用户的复杂任务分解为具体的执行步骤。
要求:
1. 每个步骤应该是原子化的、可执行的
2. 步骤之间的依赖关系要清晰
3. 每个步骤的 "tool" 字段只能从下方【可用工具】列表中选择
4. 输出JSON格式的计划
【可用工具】
{available_tools}
输出格式:
{{
"goal": "最终目标",
"steps": [
{{
"id": 1,
"action": "具体动作描述",
"tool": "需要使用的工具(必须从可用工具中选择)",
"depends_on": [],
"expected_output": "期望输出"
}}
]
}}"""
def create_plan(task: str, tools: list[dict] | None = None) -> dict:
"""使用LLM创建执行计划
Args:
task: 要规划的任务描述
tools: 可用工具列表,每个工具包含 name 和 description。
规划器只会使用此列表中的工具,避免幻觉出不存在的工具。
"""
# 格式化工具描述,注入到 Prompt 中
if tools:
# f-string中可以用['key']访问字典值;.join()拼接生成器产出的每一行
tools_text = "\n".join(
f"- {t['name']}: {t['description']}" for t in tools
)
else:
tools_text = "(无特定工具约束,所有步骤由LLM直接推理完成)"
prompt = PLANNING_PROMPT.format(available_tools=tools_text)
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": prompt},
{"role": "user", "content": f"请为以下任务制定执行计划:\n{task}"},
],
response_format={"type": "json_object"},
temperature=0,
)
return json.loads(response.choices[0].message.content)
# === 示例:定义可用工具并生成计划 ===
available_tools = [
{"name": "web_search", "description": "通过关键词搜索互联网信息"},
{"name": "sql_query", "description": "执行SQL查询获取结构化数据"},
{"name": "calculator", "description": "执行数学计算和财务指标分析"},
{"name": "document_writer", "description": "生成格式化的文档和报告"},
]
plan = create_plan(
"帮我分析某公司2024年的财务数据,并生成一份投资建议报告",
tools=available_tools,
)
print(json.dumps(plan, indent=2, ensure_ascii=False))
# 预期输出类似:
# {
# "goal": "分析公司财务数据并生成投资建议",
# "steps": [
# {"id": 1, "action": "搜索公司基本信息", "tool": "web_search", ...},
# {"id": 2, "action": "查询财务报表数据", "tool": "sql_query", ...},
# {"id": 3, "action": "计算关键财务指标", "tool": "calculator", ...},
# {"id": 4, "action": "生成投资建议报告", "tool": "document_writer", ...}
# ]
# }
4. Agent设计模式¶
4.1 路由模式(Router)¶
根据用户输入,选择不同的处理路径。
"""
路由模式:根据输入意图分发到不同的处理逻辑
"""
from openai import OpenAI
import json
client = OpenAI()
def route_request(user_input: str) -> str:
"""路由Agent - 根据输入意图分发处理"""
# 使用LLM判断意图
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": """分析用户输入的意图,返回JSON格式:
{"intent": "code|search|math|chat", "confidence": 0.0-1.0, "reason": "判断原因"}"""},
{"role": "user", "content": user_input},
],
response_format={"type": "json_object"},
)
intent_data = json.loads(response.choices[0].message.content)
intent = intent_data["intent"]
# 根据意图路由到不同处理器
handlers = {
"code": handle_code_request,
"search": handle_search_request,
"math": handle_math_request,
"chat": handle_chat_request,
}
# 第二个参数是默认值:当LLM返回了意料之外的intent时,降级为闲聊处理,避免KeyError
handler = handlers.get(intent, handle_chat_request)
return handler(user_input)
def handle_code_request(query: str) -> str:
"""处理编程相关请求"""
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "你是一个Python编程专家,提供高质量的代码解决方案。"},
{"role": "user", "content": query},
],
)
return response.choices[0].message.content
def handle_search_request(query: str) -> str:
return f"[搜索模块] 正在搜索: {query}"
def handle_math_request(query: str) -> str:
return f"[数学模块] 正在计算: {query}"
def handle_chat_request(query: str) -> str:
return f"[对话模块] 正在处理: {query}"
4.2 反思模式(Reflection)¶
Agent对自己的输出进行审查和改进。
"""
反思模式:Agent生成 → 自我审查 → 改进
适用于代码生成、文章写作等需要高质量输出的场景
"""
from openai import OpenAI
client = OpenAI()
def reflect_and_improve(task: str, max_iterations: int = 3) -> str:
"""反思改进循环"""
# 第1步:生成初始输出
generation_response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "你是一个专业的Python开发者。请根据任务要求编写代码。"},
{"role": "user", "content": task},
],
)
current_output = generation_response.choices[0].message.content
print(f"=== 初始生成 ===\n{current_output}\n")
for i in range(max_iterations):
# 第2步:自我审查
review_response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": """你是一个严格的代码审查专家。请审查以下代码,指出问题并给出具体改进建议。
如果代码已经足够好,回复"APPROVED"。
否则返回具体的问题列表和改进建议。"""},
{"role": "user", "content": f"任务: {task}\n\n代码:\n{current_output}"},
],
)
review = review_response.choices[0].message.content
print(f"=== 审查 {i + 1} ===\n{review}\n")
# 如果审查通过,退出循环
if "APPROVED" in review:
print("✅ 审查通过!")
break
# 第3步:根据审查意见改进
improve_response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "请根据审查意见改进代码。"},
{"role": "user", "content": f"原始任务: {task}\n\n当前代码:\n{current_output}\n\n审查意见:\n{review}"},
],
)
current_output = improve_response.choices[0].message.content
print(f"=== 改进 {i + 1} ===\n{current_output}\n")
return current_output
# 使用示例
result = reflect_and_improve("编写一个线程安全的LRU缓存类")
4.3 工具使用模式(Tool Use)¶
基于OpenAI Function Calling的标准工具使用模式。
"""
工具使用模式:基于OpenAI Tool Calling
这是最标准的Agent工具调用方式
"""
from openai import OpenAI
import json
client = OpenAI()
# 定义工具
tools = [
{
"type": "function",
"function": {
"name": "get_stock_price",
"description": "获取指定股票的当前价格",
"parameters": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "股票代码,如 AAPL, GOOGL",
},
"market": {
"type": "string",
"enum": ["US", "CN", "HK"],
"description": "市场,US=美股, CN=A股, HK=港股",
},
},
"required": ["symbol"],
},
},
},
{
"type": "function",
"function": {
"name": "analyze_sentiment",
"description": "分析文本的情感倾向",
"parameters": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "要分析的文本",
},
},
"required": ["text"],
},
},
},
]
def get_stock_price(symbol: str, market: str = "US") -> dict:
"""模拟获取股票价格"""
prices = {"AAPL": 198.5, "GOOGL": 175.2, "600519": 1680.0}
return {"symbol": symbol, "price": prices.get(symbol, 0), "market": market, "currency": "USD" if market == "US" else "CNY"}
def analyze_sentiment(text: str) -> dict:
"""模拟情感分析"""
return {"text": text[:50], "sentiment": "positive", "score": 0.85}
# 工具函数映射
tool_functions = {
"get_stock_price": get_stock_price,
"analyze_sentiment": analyze_sentiment,
}
def tool_use_agent(user_message: str) -> str:
"""工具使用Agent"""
messages = [
{"role": "system", "content": "你是一个金融助手,可以查询股票价格和分析市场情感。"},
{"role": "user", "content": user_message},
]
while True:
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
)
message = response.choices[0].message
# 如果没有工具调用,返回最终结果
if not message.tool_calls:
return message.content
# 处理所有工具调用(支持并行调用)
messages.append(message)
for tool_call in message.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
print(f"🔧 调用工具: {func_name}({func_args})")
# 执行工具
result = tool_functions[func_name](**func_args)
# 将结果返回给LLM
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result, ensure_ascii=False),
})
# 运行
answer = tool_use_agent("帮我查一下苹果股票现在多少钱?")
print(f"回答: {answer}")
4.4 提示链模式(Prompt Chaining)¶
将复杂任务分解为串行的多步LLM调用,每步的输出作为下一步的输入。与Agent的自主循环不同,提示链的流程是预定义的,适用于步骤明确、质量要求高的场景。
💡 与路由模式的区别:路由是"选一条路走",提示链是"按顺序走完所有步骤"。
"""
提示链模式:串行LLM调用管道
适用于流程固定、每步需要高质量输出的任务(如内容创作、数据处理)
参考:Anthropic "Building Effective Agents" (2025) — Prompt Chaining 模式
"""
from openai import OpenAI
import json
client = OpenAI()
def prompt_chain(topic: str) -> dict:
"""
内容创作提示链:大纲 → 草稿 → 审校 → 终稿
每一步专注于单一目标,通过"门控检查"决定是否进入下一步。
"""
# Step 1: 生成大纲
outline_resp = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "你是一个内容策划专家。请为给定主题生成详细的文章大纲。"},
{"role": "user", "content": f"请为以下主题生成大纲,包含3-5个一级标题和各自的要点:\n{topic}"},
],
temperature=0.7,
)
outline = outline_resp.choices[0].message.content
print(f"✅ Step 1 - 大纲生成完成")
# 门控检查:大纲质量验证
gate_resp = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": '判断大纲是否结构完整、逻辑清晰。返回JSON:{"pass": true/false, "reason": "..."}'},
{"role": "user", "content": outline},
],
response_format={"type": "json_object"},
)
gate = json.loads(gate_resp.choices[0].message.content)
if not gate.get("pass", False):
print(f"⚠️ 大纲未通过门控检查: {gate.get('reason')}")
# 可选:重新生成或人工修正
# 这里简化处理,继续执行
# Step 2: 基于大纲撰写草稿
draft_resp = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "你是一个专业技术写手。请基于大纲撰写完整文章。"},
{"role": "user", "content": f"大纲:\n{outline}\n\n请据此撰写完整文章,每个章节200-300字。"},
],
temperature=0.7,
)
draft = draft_resp.choices[0].message.content
print(f"✅ Step 2 - 草稿撰写完成")
# Step 3: 审校与优化
review_resp = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "你是一个资深编辑。请审校文章,修正事实错误、优化表达、统一风格。直接输出修改后的完整文章。"},
{"role": "user", "content": draft},
],
temperature=0.3,
)
final = review_resp.choices[0].message.content
print(f"✅ Step 3 - 审校优化完成")
return {"outline": outline, "draft": draft, "final": final}
# 使用示例
result = prompt_chain("AI Agent在企业客服中的应用")
print(f"\n📋 终稿:\n{result['final'][:500]}...")
提示链 vs ReAct的选择:
| 维度 | 提示链 | ReAct |
|---|---|---|
| 流程 | 预定义、线性 | 动态、循环 |
| 决策权 | 开发者设计流程 | LLM自主决定下一步 |
| 可控性 | 高(每步可审查) | 中(行为不完全可预测) |
| 适用场景 | 步骤明确的任务 | 需要探索的开放任务 |
| 门控检查 | 步骤之间可插入 | 需要额外实现 |
4.5 并行化模式(Parallelization)¶
对同一任务并行执行多个LLM调用,既能提升速度,也能通过多视角提升质量。两种核心子模式:
- 分段并行(Sectioning):将任务拆为独立子任务并行处理
- 投票并行(Voting):同一任务多次执行,通过聚合选最优
"""
并行化模式:多个LLM调用并行执行
子模式1 - 分段并行:不同子任务同时执行
子模式2 - 投票并行:同一任务多次执行取最优
参考:Anthropic "Building Effective Agents" (2025) — Parallelization 模式
"""
import asyncio # Python标准异步库,提供事件循环和async/await协程支持
from openai import AsyncOpenAI # OpenAI异步客户端,返回协程对象,需配合await使用
aclient = AsyncOpenAI()
# === 子模式1:分段并行 ===
# async def定义协程函数,必须在事件循环中通过await调用或用asyncio.run执行
async def analyze_parallel(text: str) -> dict:
"""
对同一段文本,并行执行多个独立分析任务
每个分析维度互不依赖 → 并行处理
"""
async def _call(system_prompt: str, user_prompt: str) -> str:
response = await aclient.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
],
temperature=0,
)
return response.choices[0].message.content
# 三个独立分析任务并行执行
sentiment_task = _call("你是情感分析专家,判断文本的情感倾向(正面/负面/中性)并给出理由。", text)
keyword_task = _call("你是关键词提取专家,提取文本的5个核心关键词及每个关键词的重要性说明。", text)
summary_task = _call("你是摘要专家,用3句话概括文本核心内容。", text)
# asyncio.gather 并发等待所有任务完成
sentiment, keywords, summary = await asyncio.gather(
sentiment_task, keyword_task, summary_task
)
return {"sentiment": sentiment, "keywords": keywords, "summary": summary}
# === 子模式2:投票并行 ===
async def vote_parallel(question: str, n_votes: int = 3) -> str:
"""
同一问题多次调用LLM(不同温度),通过聚合选最优
适用于需要高准确性的判断任务
"""
async def _vote(temperature: float) -> str:
response = await aclient.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "请简洁回答问题。只输出答案,不要多余解释。"},
{"role": "user", "content": question},
],
temperature=temperature,
)
return response.choices[0].message.content.strip()
# 不同温度并行调用,增加答案多样性
temps = [0, 0.3, 0.7][:n_votes]
answers = await asyncio.gather(*[_vote(t) for t in temps])
print(f"🗳️ 投票结果: {answers}")
# 聚合:让LLM综合判断最佳答案
aggregate_resp = await aclient.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "以下是多个专家对同一问题的回答。请综合判断,选择或合成最准确的答案。"},
{"role": "user", "content": f"问题: {question}\n\n" + "\n".join(f"专家{i+1}: {a}" for i, a in enumerate(answers))},
],
temperature=0,
)
return aggregate_resp.choices[0].message.content
# 使用示例
async def main():
# 分段并行
analysis = await analyze_parallel("苹果公司2024年第四季度营收创历史新高,iPhone销量超预期增长15%。")
print(f"📊 并行分析结果: {list(analysis.keys())}")
# 投票并行
best_answer = await vote_parallel("Python的GIL是什么?它对多线程有什么影响?")
print(f"🏆 投票最优答案: {best_answer[:200]}...")
asyncio.run(main()) # asyncio.run:创建事件循环并执行顶层协程,是异步程序的标准入口点
4.6 编排者-工作者模式(Orchestrator-Worker)¶
一个编排者Agent动态分析任务,将子任务委派给工作者Agent(Subagent) 执行,最后汇总结果。与提示链不同,编排者模式的子任务数量和类型是由LLM运行时决定的,而非预定义。
💡 Subagent的核心思想:把一个Agent包装成另一个Agent的"工具"来调用。编排者不直接完成任务,而是通过调用Subagent来完成。这是当前业界最热门的Agent架构模式。
"""
编排者-工作者模式(Orchestrator-Worker / Subagent模式)
编排者Agent动态分解任务 → 委派给专业Subagent → 汇总结果
参考:Anthropic "Building Effective Agents" (2025) — Orchestrator-Workers 模式
这也是 Claude Code、Cursor Agent、GitHub Copilot 等产品的核心架构
"""
from openai import OpenAI
import json
from typing import Callable
client = OpenAI()
class SubAgent:
"""子Agent:专注于单一领域的执行者"""
def __init__(self, name: str, system_prompt: str, model: str = "gpt-4o"):
self.name = name
self.system_prompt = system_prompt
self.model = model
def run(self, task: str) -> str:
"""执行子任务"""
response = client.chat.completions.create(
model=self.model,
messages=[
{"role": "system", "content": self.system_prompt},
{"role": "user", "content": task},
],
temperature=0,
)
return response.choices[0].message.content
class Orchestrator:
"""编排者:动态分析任务、委派Subagent、汇总结果"""
def __init__(self):
self.subagents: dict[str, SubAgent] = {}
def register(self, name: str, system_prompt: str, model: str = "gpt-4o"):
"""注册一个Subagent"""
self.subagents[name] = SubAgent(name, system_prompt, model)
def run(self, task: str) -> str:
"""编排者主流程"""
agent_names = list(self.subagents.keys())
agent_descriptions = "\n".join(f"- {name}" for name in agent_names)
# Step 1:让LLM动态分解任务——决定需要哪些Subagent、做什么
plan_resp = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": f"""你是一个任务编排专家。将用户任务分解为子任务,并分配给合适的Subagent。
可用的Subagent:
{agent_descriptions}
返回JSON格式:
{{"subtasks": [{{"agent": "agent名称", "task": "具体子任务描述"}}]}}"""},
{"role": "user", "content": task},
],
response_format={"type": "json_object"},
temperature=0,
)
plan = json.loads(plan_resp.choices[0].message.content)
subtasks = plan.get("subtasks", [])
print(f"📋 编排者分解出 {len(subtasks)} 个子任务:")
for st in subtasks:
print(f" → [{st['agent']}] {st['task']}")
# Step 2:依次调用Subagent执行(也可改为并行)
results = []
for st in subtasks:
agent_name = st["agent"]
agent = self.subagents.get(agent_name)
if not agent:
results.append({"agent": agent_name, "result": f"❌ 未找到Subagent: {agent_name}"})
continue
print(f"\n🔧 [{agent_name}] 执行中...")
result = agent.run(st["task"])
results.append({"agent": agent_name, "task": st["task"], "result": result})
print(f" ✅ [{agent_name}] 完成")
# Step 3:汇总所有Subagent的结果
results_text = "\n\n".join(
f"### {r['agent']}:\n{r['result']}" for r in results
)
synthesize_resp = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "你是一个高级分析师。请综合以下各专家的分析结果,生成一份完整、连贯的最终报告。"},
{"role": "user", "content": f"原始任务:{task}\n\n各Subagent结果:\n{results_text}"},
],
temperature=0,
)
return synthesize_resp.choices[0].message.content
# === 使用示例 ===
orchestrator = Orchestrator()
orchestrator.register("市场分析师", "你是一个市场分析专家。请从市场规模、竞争格局、增长趋势等角度分析。")
orchestrator.register("技术专家", "你是一个AI技术专家。请从技术可行性、架构方案、实现难度等角度分析。")
orchestrator.register("风险顾问", "你是一个风险管理专家。请识别潜在风险并提出缓解措施。")
report = orchestrator.run("评估在金融客服场景部署AI Agent的可行性")
print(f"\n📋 编排者最终报告:\n{report}")
4.7 设计模式全景:Anthropic分类法¶
上述模式并非孤立使用,实际项目往往组合多种模式。Anthropic在 "Building Effective Agents"(2025)中提出了一套被业界广泛采纳的Agent设计模式分类法,下表总结了6种核心模式与本教程内容的对应关系:
| Anthropic模式 | 本教程章节 | 核心思想 | 典型场景 |
|---|---|---|---|
| Prompt Chaining | 4.4 提示链 | 串行管道,每步输出→下步输入 | 内容创作、数据ETL |
| Routing | 4.1 路由 | 按意图分发到专用处理器 | 客服分流、多语言 |
| Parallelization | 4.5 并行化 | 多路并行后聚合 | 多维分析、投票表决 |
| Orchestrator-Workers | 4.6 编排者-工作者 | 主Agent动态委派Subagent | 复杂研究、项目规划 |
| Evaluator-Optimizer | 4.2 反思 | 生成→评估→改进循环 | 代码生成、写作优化 |
| Tool Use(Agentic Loop) | 4.3 工具使用 | LLM+工具的ReAct循环 | 数据查询、API编排 |
📌 Subagent是编排者模式的核心:当前最火的"Subagent"概念本质就是编排者-工作者模式——把专业Agent包装成编排者可调度的"工具"。Claude Code的
/agent命令、GitHub Copilot的子Agent调度、OpenAI Agents SDK的Handoff机制,底层都遵循这一模式。📖 深入学习:多Agent场景下Subagent的组织方式(层级/平等/市场/MoA)→ 04-多Agent系统与实战;Anthropic Agent产品的Skills机制 → LLM学习/04-前沿探索/08-新一代AI-Agent
5. 手写最简Agent框架¶
5.1 完整Agent实现¶
"""
SimpleAgent: 一个完整的最简Agent框架
支持工具注册、ReAct推理、记忆管理
"""
from openai import OpenAI
import json
from typing import Callable, Any
from dataclasses import dataclass
@dataclass
class AgentConfig:
"""Agent配置"""
model: str = "gpt-4o"
max_steps: int = 10
temperature: float = 0
system_prompt: str = "你是一个有用的AI助手,可以使用工具来帮助用户完成任务。"
class SimpleAgent:
"""最简Agent框架"""
def __init__(self, config: AgentConfig | None = None):
self.config = config or AgentConfig()
self.client = OpenAI()
self.tools: dict[str, Callable] = {}
self.tool_schemas: list[dict] = []
self.conversation_history: list[dict] = []
def tool(self, name: str, description: str, parameters: dict):
"""装饰器:注册工具"""
def decorator(func: Callable):
self.tools[name] = func
self.tool_schemas.append({
"type": "function",
"function": {
"name": name,
"description": description,
"parameters": parameters,
},
})
return func
return decorator
def _execute_tool(self, name: str, arguments: dict) -> str:
"""执行工具调用"""
if name not in self.tools:
return json.dumps({"error": f"未知工具: {name}"})
try:
result = self.tools[name](**arguments)
if isinstance(result, (dict, list)):
return json.dumps(result, ensure_ascii=False)
return str(result)
except Exception as e:
return json.dumps({"error": str(e)})
def run(self, user_input: str) -> str:
"""运行Agent"""
# 初始化消息
if not self.conversation_history:
self.conversation_history.append({
"role": "system",
"content": self.config.system_prompt,
})
self.conversation_history.append({
"role": "user",
"content": user_input,
})
for step in range(self.config.max_steps):
# 调用LLM
response = self.client.chat.completions.create(
model=self.config.model,
messages=self.conversation_history,
tools=self.tool_schemas if self.tool_schemas else None,
temperature=self.config.temperature,
)
message = response.choices[0].message
# 无工具调用 → 返回结果
if not message.tool_calls:
self.conversation_history.append({
"role": "assistant",
"content": message.content,
})
return message.content
# 有工具调用 → 执行工具
self.conversation_history.append(message)
for tool_call in message.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
print(f" 🔧 Step {step + 1}: {func_name}({json.dumps(func_args, ensure_ascii=False)})")
result = self._execute_tool(func_name, func_args)
self.conversation_history.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result,
})
return "达到最大执行步骤数"
def reset(self):
"""重置对话历史"""
self.conversation_history.clear()
# ===== 使用SimpleAgent =====
agent = SimpleAgent(AgentConfig(
model="gpt-4o",
max_steps=5,
system_prompt="你是一个研究助手,可以搜索信息和进行计算。",
))
@agent.tool(
name="web_search",
description="搜索互联网获取最新信息",
parameters={
"type": "object",
"properties": {
"query": {"type": "string", "description": "搜索查询"},
},
"required": ["query"],
},
)
def web_search(query: str) -> dict:
"""模拟网络搜索"""
return {"results": [{"title": f"关于{query}的信息", "snippet": f"这是{query}的相关内容..."}]}
@agent.tool(
name="calculator",
description="进行数学计算",
parameters={
"type": "object",
"properties": {
"expression": {"type": "string", "description": "数学表达式"},
},
"required": ["expression"],
},
)
def calculator(expression: str) -> dict:
"""安全计算
⚠️ 安全提示: 生产环境请使用 simpleeval 库替代 eval():
from simpleeval import simple_eval
return {"result": simple_eval(expression)}
"""
allowed_chars = set("0123456789+-*/.() ")
# all(生成器): 检查每个字符是否都在白名单中
if not all(c in allowed_chars for c in expression):
return {"error": "不支持的字符"}
try:
return {"result": eval(expression)} # noqa: S307 — 生产环境请替换为 simpleeval
except Exception as e:
return {"error": str(e)}
# 运行Agent
result = agent.run("帮我搜索一下GPT-5的最新消息,然后计算一下如果API价格降低30%,原价0.01美元/1k tokens现在是多少?")
print(f"\n📋 最终回答:\n{result}")
6. Tool Calling的JSON Schema规范¶
6.1 JSON Schema基础¶
Tool Calling使用JSON Schema定义工具的参数结构。掌握JSON Schema是Agent开发的基本功。
"""
Tool Calling JSON Schema 规范详解
"""
# === 基础类型示例 ===
# 字符串参数
string_param = {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "用户姓名",
},
"email": {
"type": "string",
"description": "邮箱地址",
"pattern": r"^[\w.-]+@[\w.-]+\.\w+$", # 正则验证
},
},
"required": ["name", "email"],
}
# 数字参数
number_param = {
"type": "object",
"properties": {
"temperature": {
"type": "number",
"description": "温度值",
"minimum": 0,
"maximum": 2,
},
"max_tokens": {
"type": "integer",
"description": "最大token数",
"default": 1000,
},
},
}
# 枚举参数
enum_param = {
"type": "object",
"properties": {
"language": {
"type": "string",
"enum": ["python", "javascript", "java", "go"],
"description": "编程语言",
},
"difficulty": {
"type": "string",
"enum": ["easy", "medium", "hard"],
"description": "难度等级",
},
},
}
# 数组参数
array_param = {
"type": "object",
"properties": {
"tags": {
"type": "array",
"items": {"type": "string"},
"description": "标签列表",
"maxItems": 5,
},
"scores": {
"type": "array",
"items": {"type": "number", "minimum": 0, "maximum": 100},
"description": "分数列表",
},
},
}
# 嵌套对象
nested_param = {
"type": "object",
"properties": {
"filter": {
"type": "object",
"description": "过滤条件",
"properties": {
"date_range": {
"type": "object",
"properties": {
"start": {"type": "string", "description": "开始日期 YYYY-MM-DD"},
"end": {"type": "string", "description": "结束日期 YYYY-MM-DD"},
},
"required": ["start", "end"],
},
"category": {
"type": "string",
"description": "分类",
},
},
},
},
}
6.2 完整的Tool Calling流程¶
"""
完整的OpenAI Tool Calling流程示例
包含并行工具调用处理
"""
from openai import OpenAI
import json
client = OpenAI()
# 定义一组工具
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "温度单位",
},
},
"required": ["city"],
},
},
},
{
"type": "function",
"function": {
"name": "send_email",
"description": "发送电子邮件",
"parameters": {
"type": "object",
"properties": {
"to": {"type": "string", "description": "收件人邮箱"},
"subject": {"type": "string", "description": "邮件主题"},
"body": {"type": "string", "description": "邮件正文"},
},
"required": ["to", "subject", "body"],
},
},
},
]
def process_tool_calls(messages: list, available_tools: list) -> str:
"""处理完整的Tool Calling流程(含多轮)"""
while True:
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=available_tools,
)
choice = response.choices[0]
message = choice.message
# 结束条件: stop或没有tool_calls
if choice.finish_reason == "stop" or not message.tool_calls:
return message.content
# 将assistant消息(含tool_calls)加入历史
messages.append(message)
# 并行处理所有工具调用
for tool_call in message.tool_calls:
name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
# 执行工具(这里用模拟数据)
if name == "get_weather":
result = {"city": args["city"], "temp": 22, "condition": "晴"}
elif name == "send_email":
result = {"status": "sent", "message_id": "msg_123"}
else:
result = {"error": f"未知工具: {name}"}
# 将工具结果加入消息
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result, ensure_ascii=False),
})
return "处理完成"
# 使用示例
messages = [
{"role": "system", "content": "你是一个智能助手。"},
{"role": "user", "content": "帮我查一下北京和上海的天气"},
]
result = process_tool_calls(messages, tools)
print(result)
6.3 Structured Outputs与Tool Calling结合¶
"""
结合Structured Outputs确保工具调用参数的严格类型安全
"""
import json
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI()
class SearchParams(BaseModel):
"""搜索参数的严格类型定义"""
query: str
max_results: int = 10
language: str = "zh"
include_images: bool = False
class AnalysisResult(BaseModel):
"""分析结果的结构化输出"""
summary: str
key_points: list[str]
sentiment: str
confidence: float
# 使用Pydantic模型生成JSON Schema
search_schema = SearchParams.model_json_schema()
print("搜索参数Schema:")
print(json.dumps(search_schema, indent=2, ensure_ascii=False))
# 使用response_format实现结构化输出
response = client.beta.chat.completions.parse(
model="gpt-4o",
messages=[
{"role": "system", "content": "请分析以下文本"},
{"role": "user", "content": "人工智能正在快速改变各行各业,带来了前所未有的机遇和挑战。"},
],
response_format=AnalysisResult,
)
result = response.choices[0].message.parsed
print(f"摘要: {result.summary}")
print(f"关键点: {result.key_points}")
print(f"情感: {result.sentiment}")
print(f"置信度: {result.confidence}")
7. 面试常考题¶
7.1 Agent和RAG的区别?¶
高频面试题 ⭐⭐⭐⭐⭐
参考答案:
| 维度 | RAG | Agent |
|---|---|---|
| 核心能力 | 检索+生成 | 推理+行动 |
| 执行模式 | 单次:检索→生成 | 多步循环:思考→行动→观察 |
| 工具使用 | 仅向量检索 | 任意工具(搜索/计算/API/代码执行) |
| 决策能力 | 无自主决策 | 自主决定使用什么工具、执行什么步骤 |
| 记忆 | 检索到的文档片段 | 短期记忆+长期记忆 |
| 适用场景 | 知识问答、文档查询 | 复杂任务自动化、多步推理 |
| 复杂度 | 较低 | 较高 |
| 可控性 | 高(流程固定) | 中(行为不完全可预测) |
关键区别:RAG是"给LLM提供参考资料",Agent是"让LLM自主完成任务"。Agent可以包含RAG作为其工具之一。
7.2 ReAct的工作流程?¶
高频面试题 ⭐⭐⭐⭐⭐
参考答案:
ReAct = Reasoning + Acting,交替执行推理和行动:
- Thought(推理):LLM分析当前情况,决定下一步该做什么
- Action(行动):选择并调用一个工具
- Observation(观察):获取工具执行结果
- 重复1-3直到任务完成
相比纯推理(CoT)的优势: - CoT可能产生"幻觉",ReAct通过实际工具调用获取真实数据 - ReAct的推理过程可追踪、可调试 - ReAct能动态调整计划
7.3 Agent的记忆系统如何设计?¶
面试题 ⭐⭐⭐⭐
参考答案:
三层记忆架构: - 工作记忆(Working Memory):当前对话上下文,存在于LLM的context window中 - 短期记忆(Short-term Memory):最近N轮对话历史,使用滑动窗口或摘要压缩 - 长期记忆(Long-term Memory):持久化存储,使用向量数据库(如Chroma/Milvus),通过embedding相似度检索
记忆管理策略: - 上下文窗口满时,使用LLM对历史进行摘要压缩 - 重要信息提取后存入长期记忆 - 检索时结合关键词匹配和语义搜索
7.4 Tool Calling和Function Calling的区别?¶
面试题 ⭐⭐⭐
参考答案:
Tool Calling可以视为Function Calling命名与能力上的演进: - Function Calling:早期命名,强调单函数调用语义 - Tool Calling:更通用的“工具”概念,支持并行调用多个工具 - Tool Calling使用 tools 参数而非 functions 参数 - 返回格式从 function_call 变为 tool_calls(数组)
7.5 如何保证Agent的安全性?¶
面试题 ⭐⭐⭐⭐
参考答案:
- 输入验证:对工具参数做严格的Schema校验
- 权限控制:限制Agent可访问的工具和资源
- 沙箱执行:代码执行类工具在沙箱环境中运行
- 输出审查:对Agent输出进行安全检查
- 人机协作:关键操作需要人工确认
- 速率限制:防止Agent无限循环或过度调用
- 审计日志:记录所有工具调用和决策过程
📝 本章小结¶
本章介绍了Agent开发的核心基础:
- ✅ 理解了Agent的定义和核心能力
- ✅ 掌握了ReAct范式的原理和实现
- ✅ 学习了Agent四大组件(LLM/工具/记忆/规划)
- ✅ 了解了六种Agent设计模式(含Anthropic分类法)
- ✅ 理解了Subagent/编排者-工作者架构
- ✅ 手写了一个完整的Agent框架
- ✅ 掌握了Tool Calling的JSON Schema规范
✅ 学习检查清单¶
- 能解释Agent和传统LLM应用的区别
- 能描述ReAct范式的完整工作流程
- 能说出Agent四大核心组件及其作用
- 理解六种Agent设计模式(路由/反思/工具使用/提示链/并行化/编排者-工作者)
- 能解释Subagent的核心思想及其与Anthropic分类法的关系
- 能独立手写一个SimpleAgent框架
- 能编写标准的JSON Schema工具定义
- 理解Tool Calling的并行调用机制
- 能回答Agent相关的面试题
🔗 下一步¶
下一章我们将学习主流Agent框架,包括OpenAI Agents SDK、LangGraph和CrewAI。
继续学习: 02-主流Agent框架
📚 参考资料¶
- "ReAct: Synergizing Reasoning and Acting in Language Models" - Yao et al., 2023
- OpenAI Function Calling Guide
- Anthropic: Building Effective Agents — 六大Agent设计模式分类(2025)
- OpenAI Agents SDK — Handoff/Subagent机制参考
- JSON Schema Specification
- "Toolformer: Language Models Can Teach Themselves to Use Tools" - Schick et al., 2023
- "A Survey on Large Language Model based Autonomous Agents" - Wang et al., 2023
祝你学习愉快! 🎉
最后更新日期:2026-02-12 适用版本:AI Agent开发实战教程 v2026



