Appearance
Agent 面试专题
AI Agent 面试主线:什么是 Agent → 架构组件 → 设计范式(ReAct/Plan-Execute/Reflection)→ 记忆机制 → 多 Agent 协作 → 工程实践。
Q1: 什么是 Agent?与大模型有什么本质不同? 「🟢 校招/初级」
考察点:Agent 的基本概念和与 LLM 的区别。
参考答案:
Agent = LLM + 规划 + 记忆 + 工具 + 执行
大模型(LLM)是一个被动的文本生成器,你给它一个 Prompt,它返回一段文本,交互就结束了。而 Agent 是一个自主的 AI 系统,它能够感知环境、自主决策、调用工具、执行动作,并在多轮交互中完成复杂目标。
| 维度 | 大模型(LLM) | AI Agent |
|---|---|---|
| 交互模式 | 单轮:Prompt → Response | 多轮:目标 → 规划 → 执行 → 观察 → 调整 |
| 自主性 | 被动响应,不会主动行动 | 自主决策,能拆分任务、选择工具 |
| 记忆 | 无状态(除上下文窗口) | 有长期/短期记忆,可跨会话 |
| 工具 | 不能调用外部工具 | 可调用搜索、代码执行、API 等 |
| 执行 | 只输出文本 | 能执行实际动作(发邮件、写文件等) |
| 终止 | 生成完就结束 | 自主判断任务是否完成 |
python
# LLM:单轮交互
response = llm.chat("帮我订一张明天北京到上海的机票")
# → 返回一段文本:"好的,您可以..."(实际上什么都没做)
# Agent:自主执行
agent.run("帮我订一张明天北京到上海的机票")
# → 规划:1. 查航班 2. 选航班 3. 下单 4. 支付
# → 调用航班查询 API → 获得结果
# → 调用下单 API → 完成预订
# → 调用支付 API → 完成支付
# → "已为您预订明天 08:00 北京→上海 航班,订单号 XXX"Agent 的核心特征:
- 自主性(Autonomy):不需要人类每步指挥,能自己规划并执行
- 反应性(Reactivity):能感知环境变化(工具返回的结果)并调整策略
- 主动性(Proactivity):不只是被动响应,能主动发起行动
- 社交性(Social Ability):多 Agent 场景下能与其他 Agent 协作
一句话总结:LLM 是 Agent 的「大脑」,但 Agent 不仅有大脑,还有手脚(工具)、记忆和规划能力。
追问延伸:
- Agent 和传统的规则引擎/脚本有什么区别?(Agent 用 LLM 做决策,更灵活)
- Copilot 算不算 Agent?(辅助型 Agent,自主性较低)
Q2: Agent 的基本架构由哪些核心组件构成? 「🟢 校招/初级」
考察点:Agent 架构的系统性理解。
参考答案:
Agent 的经典架构包含 5 大核心组件:
┌─────────────────────────────────────────────────┐
│ AI Agent │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 规划模块 │ │ 记忆模块 │ │ 工具模块 │ │
│ │ (Planning)│ │ (Memory) │ │ (Tools) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └──────────────┼──────────────┘ │
│ │ │
│ ┌───────┴───────┐ │
│ │ LLM(大脑) │ │
│ └───────┬───────┘ │
│ │ │
│ ┌───────┴───────┐ │
│ │ 执行模块(Action)│ │
│ └───────────────┘ │
└─────────────────────────────────────────────────┘1. LLM(大脑):
- Agent 的核心决策引擎
- 负责理解任务、推理规划、生成行动指令
- 选择什么模型决定 Agent 的能力上限
2. 规划模块(Planning):
- 任务拆分:将复杂任务分解为子任务
- 推理决策:决定下一步做什么
- 反思调整:根据执行结果调整计划
用户目标:"写一篇关于 AI Agent 的技术博客"
→ 拆分:
1. 搜索 AI Agent 最新资料
2. 整理大纲
3. 撰写初稿
4. 校对润色
5. 发布3. 记忆模块(Memory):
- 短期记忆:当前对话上下文(Context Window)
- 长期记忆:历史交互、用户偏好、知识库(向量数据库)
4. 工具模块(Tools):
- 搜索引擎、代码执行器、数据库查询
- API 调用(天气、地图、支付等)
- 文件操作(读写、创建)
python
# 工具定义示例
tools = [
Tool(name="search", func=web_search, description="搜索网络信息"),
Tool(name="python", func=code_execute, description="执行 Python 代码"),
Tool(name="sql_query", func=db_query, description="查询数据库"),
]5. 执行模块(Action):
- 将 LLM 的决策转化为具体动作
- 调用工具并获取结果
- 将结果反馈给 LLM 进行下一步推理
核心循环(Agent Loop):
while not task_complete:
1. LLM 思考 → 决定下一步行动
2. 执行行动 → 调用工具
3. 观察结果 → 工具返回
4. 更新记忆 → 存入上下文
5. 判断完成 → 是否达到目标追问延伸:
- 这 5 个组件中哪个最重要?(LLM 是上限,规划是下限,工具是能力边界)
- 如果 LLM 能力不够强,怎么补偿?(更好的 Prompt + 更强的工具 + 更细的任务拆分)
Q3: Workflow,Agent,Tools 这三个的概念和区别介绍一下? 「🟡 中级」
考察点:三个核心概念的辨析和关系理解。
参考答案:
| 概念 | 本质 | 特点 | 类比 |
|---|---|---|---|
| Tools | 能力扩展 | LLM 调用的具体函数/API | 工人的工具箱 |
| Workflow | 固定流程 | 预定义的步骤编排,路径确定 | 流水线 |
| Agent | 自主决策 | LLM 动态决定下一步做什么 | 独立工作者 |
Tools(工具):
工具是 LLM 的「手和脚」,扩展了 LLM 的能力边界。
python
# 工具是最小单位
@tool
def search_web(query: str) -> str:
"""搜索网络获取最新信息"""
return web_search(query)
@tool
def execute_code(code: str) -> str:
"""执行 Python 代码并返回结果"""
return run_python(code)- 工具本身不做决策,只是执行
- LLM 决定调用哪个工具、传什么参数
- 工具是 Agent 和 Workflow 都可以使用的
Workflow(工作流):
Workflow 是预定义的流程编排,步骤和路径在运行前已确定。
RAG Workflow(固定流程):
用户提问 → Query 改写 → 向量检索 → 重排序 → 组装 Prompt → LLM 生成 → 返回
每一步做什么、下一步走哪里,都是写死的。python
# Workflow:路径固定,每一步都确定
def rag_workflow(query):
rewritten = query_rewrite(query) # Step 1
docs = vector_search(rewritten) # Step 2
reranked = rerank(docs) # Step 3
prompt = build_prompt(rewritten, reranked) # Step 4
answer = llm.generate(prompt) # Step 5
return answerAgent(智能体):
Agent 是自主决策的系统,LLM 根据当前状态动态决定下一步做什么。
Agent(动态决策):
用户提问 → LLM 思考:
"这个问题需要查数据库" → 调用 SQL 工具
"结果不够,再搜一下" → 调用搜索工具
"数据拿到了,分析一下" → 调用代码执行工具
"结果不对,换个方法" → 调整策略
"好了,可以回答了" → 生成最终回答三者的关系:
Tools ⊂ Agent (Agent 使用工具)
Tools ⊂ Workflow (Workflow 使用工具)
Agent ≠ Workflow (决策方式不同)
Agent:LLM 决定流程(动态)
Workflow:人决定流程(静态)
两者都可以调用 Tools| 维度 | Workflow | Agent |
|---|---|---|
| 决策方式 | 预定义,路径固定 | LLM 动态决策,路径不确定 |
| 可控性 | 高(每步可预测) | 低(LLM 可能走偏) |
| 灵活性 | 低(新场景需改代码) | 高(LLM 自适应) |
| 适用场景 | 流程明确的重复任务 | 开放式、复杂任务 |
| 调试难度 | 低(确定路径) | 高(非确定路径) |
| 成本 | 低(固定 LLM 调用次数) | 高(循环调用,次数不定) |
实际选型建议:
流程明确 → Workflow(如 RAG、文档摘要)
流程不明确 → Agent(如研究分析、复杂任务)
混合 → Workflow + Agent(主流程用 Workflow,子任务用 Agent)追问延伸:
- 能不能在 Workflow 里嵌套 Agent?(可以,子任务交给 Agent)
- 为什么不全都用 Agent?(成本高、可控性差、延迟大)
Q4: 了解哪些其他的 Agent 设计范式?Agent 和 Workflow 的区别是什么? 「🟡 中级」
考察点:Agent 设计范式的广度和深度理解。
参考答案:
主流 Agent 设计范式:
| 范式 | 核心思想 | 代表 | 适用场景 |
|---|---|---|---|
| ReAct | 推理+行动交替 | Thought→Action→Observation | 通用任务 |
| Plan-and-Execute | 先规划再执行 | Plan → Execute step by step | 复杂多步任务 |
| Reflection | 自我反思改进 | Generate → Critique → Improve | 质量要求高 |
| Tool-Use | 工具调用 | Function Calling / MCP | 需要外部能力 |
| Multi-Agent | 多角色协作 | Coder + Reviewer + Tester | 复杂工程项目 |
| Router | 路由分发 | 分类 → 对应 Agent | 多领域问答 |
| Chain | 链式调用 | A → B → C | 线性流程 |
各范式详解:
1. ReAct(Reasoning + Acting):
Thought: 用户想知道明天的天气,我需要调用天气 API
Action: get_weather(city="北京")
Observation: 明天北京晴,25-35°C
Thought: 获得了天气信息,可以回答用户了
Answer: 明天北京晴天,气温 25-35 度,适合出行。2. Plan-and-Execute:
Plan:
1. 搜索 AI Agent 最新论文
2. 提取关键技术点
3. 对比现有方案
4. 撰写综述
Execute:
Step 1: search("AI Agent 2025") → 10 篇论文
Step 2: extract_keypoints(papers) → 5 个技术点
Step 3: compare(existing_solutions, keypoints) → 对比表
Step 4: write_summary(comparison) → 综述文档3. Reflection(反思):
Generate: 写了一段代码
Critique: 检查代码,发现没有处理异常
Improve: 加入 try-catch 异常处理
Critique: 再次检查,发现性能可以优化
Improve: 优化算法复杂度
→ 最终输出4. Multi-Agent:
用户:"帮我开发一个 Web API"
Planner Agent → 拆分任务
Coder Agent → 编写代码
Reviewer Agent → 代码审查
Tester Agent → 编写测试
Deployer Agent → 部署上线Agent 和 Workflow 的核心区别:
Workflow(确定性流程):
定义:A → B → C → D(路径写死)
特点:可复现、可预测、可调试
LLM 角色:流程中的某个节点
Agent(非确定性流程):
定义:LLM 决定 A → ? → ? → 完成(路径动态)
特点:灵活、自适应、但不可预测
LLM 角色:决策中枢,控制流程走向| 维度 | Workflow | Agent |
|---|---|---|
| 控制流 | 代码控制 | LLM 控制 |
| 确定性 | 确定(同样输入→同样输出) | 不确定(LLM 可能走不同路径) |
| 错误处理 | 预定义的异常分支 | LLM 自主决定如何处理 |
| 成本 | 固定(N 步 = N 次 LLM 调用) | 不固定(可能循环很多次) |
| 适用场景 | 流程明确、重复执行 | 开放式、探索性 |
实际项目中的选择:
能用 Workflow 解决的 → 用 Workflow(成本低、可控)
Workflow 不够的 → 加 Agent(在关键决策点引入 LLM 动态决策)
两者结合 → Workflow 做主流程,Agent 做子任务追问延伸:
- ReAct 和 Plan-and-Execute 能不能结合?(先规划,执行时用 ReAct)
- 什么场景下 Agent 比 Workflow 好很多?(需要根据中间结果动态调整策略时)
Q5: Agent 推理模式有哪些?ReAct 是啥?具体是怎么实现的? 「🟡 中级」
考察点:ReAct 范式的原理和实现细节。
参考答案:
Agent 推理模式总览:
| 推理模式 | 核心思想 | 循环结构 |
|---|---|---|
| ReAct | 推理与行动交替 | Thought → Action → Observation |
| Plan-and-Execute | 先全局规划,再逐步执行 | Plan → Execute (→ Replan) |
| Reflection | 生成后反思改进 | Generate → Critique → Refine |
| Chain-of-Thought | 链式思维推理 | Step1 → Step2 → Step3 |
| Tree-of-Thought | 树状多路径探索 | 分支 → 评估 → 剪枝 → 最优路径 |
ReAct(Reasoning + Acting)详解:
ReAct 的核心思想是让 LLM 交替进行推理(Thought)和行动(Action),根据行动的观察结果(Observation)决定下一步推理。
ReAct 循环:
Thought 1 → Action 1 → Observation 1
↓
Thought 2 → Action 2 → Observation 2
↓
Thought 3 → Action 3 → Observation 3
↓
Thought N → Final AnswerReAct 的 Prompt 模板:
You are an AI assistant. Use the following tools to answer the question.
Available tools:
- search(query): Search the web
- calculator(expression): Calculate math
- python(code): Execute Python code
Question: {user_question}
Follow this format:
Thought: <your reasoning>
Action: <tool_name>(<arguments>)
Observation: <tool result>
... (repeat as needed)
Thought: I now know the answer
Final Answer: <your answer>ReAct 具体实现示例:
python
import re
class ReActAgent:
def __init__(self, llm, tools):
self.llm = llm
self.tools = {t.name: t for t in tools}
self.max_iterations = 10
def run(self, question):
prompt = self._build_prompt(question)
history = ""
for i in range(self.max_iterations):
# LLM 生成 Thought + Action
response = self.llm.generate(prompt + history)
# 解析 Action
action_match = re.search(r'Action:\s*(\w+)\((.*?)\)', response)
if not action_match:
# 没有 Action,说明是最终回答
final_answer = re.search(r'Final Answer:\s*(.*)', response)
return final_answer.group(1) if final_answer else response
tool_name = action_match.group(1)
tool_args = action_match.group(2)
# 执行工具
if tool_name in self.tools:
observation = self.tools[tool_name].run(tool_args)
else:
observation = f"Error: Tool '{tool_name}' not found"
# 拼接历史
history += f"\n{response}\nObservation: {observation}\n"
return "Max iterations reached without final answer"
def _build_prompt(self, question):
tools_desc = "\n".join(
f"- {t.name}({t.args}): {t.description}"
for t in self.tools.values()
)
return f"""You are an AI assistant. Use tools to answer.
Available tools:
{tools_desc}
Question: {question}
Follow this format:
Thought: <reasoning>
Action: <tool>(<args>)
Observation: <result>
...(repeat)
Final Answer: <answer>
"""ReAct 的优缺点:
| 优点 | 缺点 |
|---|---|
| 推理过程透明可解释 | 每步都要 LLM 调用,成本高 |
| 能根据中间结果调整策略 | 可能陷入循环(重复调用同一工具) |
| 通用性强,适合多种任务 | 依赖 LLM 的指令遵循能力 |
| 错误可追溯(看每步 Thought) | 延迟高(串行执行) |
ReAct 的变体:
标准 ReAct:Thought → Action → Observation
带反思的 ReAct:Thought → Action → Observation → Reflection → Adjustment
带记忆的 ReAct:历史记忆 + 当前 Thought → 更好的决策
带规划的 ReAct:先 Plan,再对每个子任务用 ReAct追问延伸:
- ReAct 为什么比纯 CoT 好?(CoT 只推理不行动,ReAct 能与环境交互)
- ReAct 的最大瓶颈是什么?(LLM 的指令遵循能力、循环终止判断)
Q6: ReAct、Plan-and-Execute、Reflection 三种范式有什么核心区别?实际项目中该如何选型? 「🔴 高级」
考察点:三种范式的深度对比和工程选型能力。
参考答案:
三种范式的核心对比:
| 维度 | ReAct | Plan-and-Execute | Reflection |
|---|---|---|---|
| 核心思想 | 边想边做 | 先想后做 | 做完再改 |
| 决策粒度 | 每步决策 | 先全局规划 | 事后改进 |
| LLM 调用次数 | 多(每步一次) | 少(规划一次+执行多次) | 最多(生成+批判+改进) |
| 延迟 | 高(串行循环) | 中(并行执行) | 最高(多轮改进) |
| 成本 | 高 | 中 | 最高 |
| 质量 | 中 | 中 | 高(多次改进) |
| 可控性 | 低(动态路径) | 高(有明确计划) | 中 |
ReAct 详解:
特点:一步一决策,走一步看一步
适用:信息不完全、需要探索的任务
示例:搜索+分析+综合 → 研究型任务
User: "分析 2025 年 AI Agent 领域的技术趋势"
Thought: 先搜索最新信息
Action: search("AI Agent 2025 trends")
Observation: [10 篇文章]
Thought: 读取关键文章
Action: read_article(url)
Observation: [文章内容]
Thought: 信息足够了,综合分析
Final Answer: ...Plan-and-Execute 详解:
特点:先制定完整计划,再逐步执行
适用:任务复杂但结构清晰
示例:开发+测试+部署 → 工程型任务
Plan:
1. 搜索需求文档
2. 设计 API 接口
3. 编写代码
4. 编写测试
5. 部署
Execute:
Step 1: search() → 完成
Step 2: design() → 完成
Step 3: code() → 失败!→ Replan
New Plan: 3a. 修复依赖 → 3b. 编写代码
Step 3a: fix() → 完成
Step 3b: code() → 完成
Step 4: test() → 完成
Step 5: deploy() → 完成Reflection 详解:
特点:生成 → 自我批判 → 改进
适用:质量要求高的任务
示例:代码编写、文档撰写
Generate:
"这是一个快速排序的实现..."
Critique:
"代码缺少边界条件处理,数组为空时会报错"
"变量命名不够清晰"
"没有注释"
Improve:
"修复了边界条件..."
Critique:
"可以进一步优化空间复杂度"
Improve:
"使用原地排序..."
→ 最终版本选型决策树:
任务特点是什么?
├── 需要探索,信息逐步获取 → ReAct
├── 任务复杂但结构清晰 → Plan-and-Execute
├── 质量要求极高 → Reflection
└── 多种特点都有 → 组合使用
└── Plan-and-Execute + ReAct(子任务)+ Reflection(关键步骤)实际项目选型示例:
| 场景 | 推荐范式 | 原因 |
|---|---|---|
| 搜索+综合分析 | ReAct | 需要根据搜索结果决定下一步 |
| 自动化开发 | Plan-and-Execute | 开发流程明确(设计→编码→测试) |
| 代码质量保证 | Reflection | 需要多次改进达到高质量 |
| 客服 Agent | ReAct | 根据用户反馈动态响应 |
| 报告生成 | Plan + ReAct | 先规划大纲,每部分用 ReAct 撰写 |
| 数学解题 | CoT + ReAct | 推理+计算器工具交替 |
组合范式实践:
python
class HybridAgent:
def run(self, task):
# 1. Plan-and-Execute:先规划
plan = self.planner.create_plan(task)
results = []
for step in plan.steps:
# 2. ReAct:每个子任务用 ReAct 执行
result = self.react_agent.run(step)
# 3. Reflection:关键步骤反思改进
if step.requires_high_quality:
result = self.reflector.improve(result)
results.append(result)
# 4. Replan:如果执行失败,重新规划
if result.failed:
plan = self.planner.replan(task, results)
return self.synthesize(results)追问延伸:
- Reflection 能不能用另一个 LLM 来做批判?(可以,Cross-Model Critique)
- Plan-and-Execute 在什么情况下需要 Replan?(执行结果与预期不符时)
Q7: 复杂任务怎么做的任务拆分?为什么要拆分?效果如何提升? 「🔴 高级」
考察点:任务拆分策略和工程效果评估。
参考答案:
为什么要拆分:
不拆分的问题:
1. LLM 上下文有限 → 复杂任务信息量超出 Context Window
2. 单次生成质量低 → 任务越复杂,LLM 越容易遗漏或出错
3. 不可控 → 一次性生成,出错无法定位和修复
4. 不可并行 → 串行执行,延迟高
5. 不可复用 → 每次从头开始
拆分后的好处:
1. 每个子任务聚焦 → LLM 在小任务上质量更高
2. 可并行 → 多个子任务同时执行
3. 可控 → 每步可检查、可回退
4. 可复用 → 相同子任务可缓存
5. 可组合 → 不同子任务用不同 Agent/工具任务拆分策略:
1. 按流程拆分(Pipeline Decomposition):
任务:写一篇技术博客
拆分:
1. 调研 → 搜索资料、整理要点
2. 大纲 → 列出文章结构
3. 初稿 → 逐段撰写
4. 校对 → 检查错误
5. 润色 → 优化表达
6. 发布2. 按维度拆分(Dimensional Decomposition):
任务:分析一个公司
拆分:
1. 财务分析 → 营收、利润、现金流
2. 技术分析 → 技术栈、专利、研发投入
3. 市场分析 → 市场份额、竞争对手
4. 管理分析 → 组织架构、人才
→ 最后综合3. 递归拆分(Recursive Decomposition):
任务:开发一个 Web 应用
├── 1. 后端开发
│ ├── 1.1 API 设计
│ ├── 1.2 数据库设计
│ ├── 1.3 业务逻辑
│ └── 1.4 接口测试
├── 2. 前端开发
│ ├── 2.1 页面设计
│ ├── 2.2 组件开发
│ └── 2.3 状态管理
└── 3. 部署运维
├── 3.1 CI/CD
└── 3.2 监控告警4. 按依赖关系拆分(Dependency-based):
任务链:A → B(依赖 A)→ C(依赖 B)→ D(依赖 B)
并行:A → B → [C || D] → 合并
任务图:
A → B → C
↘ D
A、B 串行;C、D 并行LLM 做任务拆分的 Prompt:
你是一个任务规划专家。请将以下任务拆分为可执行的子任务。
任务:{task}
要求:
1. 每个子任务明确、可执行、可验证
2. 标注子任务之间的依赖关系
3. 标注哪些子任务可以并行
4. 为每个子任务推荐合适的工具/方法
输出格式:
[
{
"id": 1,
"task": "...",
"depends_on": [],
"parallel_with": [],
"tool": "...",
"verify": "..."
}
]拆分粒度的权衡:
粒度太粗:
子任务仍然复杂 → LLM 质量不高
→ 需要继续拆
粒度太细:
管理开销大 → 大量 LLM 调用
上下文丢失 → 子任务间信息传递困难
→ 合并相近任务
经验法则:
- 每个子任务可在 1-3 次 LLM 调用内完成
- 每个子任务有明确的成功标准
- 子任务数量 3-7 个为宜(不超过 10)效果提升的量化:
| 指标 | 不拆分 | 拆分后 | 提升 |
|---|---|---|---|
| 任务完成率 | 40-60% | 70-90% | +30% |
| 输出质量 | 6/10 | 8/10 | +33% |
| 错误定位 | 不可定位 | 精确定位到子任务 | - |
| 并行执行 | 不支持 | 多子任务并行 | 延迟 -40% |
| 可复用性 | 无 | 相同子任务可缓存 | 成本 -20% |
追问延伸:
- 拆分后子任务的结果怎么传递?(上下文传递 / 共享状态 / 消息传递)
- 拆分的子任务失败了怎么办?(重试 / Replan / 降级 / 人工介入)
Q8: 请你介绍一下 AI Agent 的记忆机制,并说明在实际开发中应该如何设计记忆模块? 「🔴 高级」
考察点:Agent 记忆系统的设计和工程实践。
参考答案:
人类记忆 → Agent 记忆的映射:
| 人类记忆 | Agent 记忆 | 存储 | 持久化 |
|---|---|---|---|
| 工作记忆(短期) | 上下文窗口 | LLM Context | 会话内 |
| 情景记忆 | 对话历史 | 数据库/向量库 | 跨会话 |
| 语义记忆 | 知识库 | 向量数据库 | 长期 |
| 程序记忆 | 技能/工具 | 代码/配置 | 永久 |
Agent 记忆的三个层次:
┌──────────────────────────────────┐
│ 短期记忆(Working Memory) │ ← LLM 上下文窗口
│ - 当前对话上下文 │
│ - 当前任务状态 │
│ - 最近几轮交互 │
├──────────────────────────────────┤
│ 中期记忆(Episodic Memory) │ ← 对话历史存储
│ - 本次会话的完整历史 │
│ - 之前的任务执行记录 │
├──────────────────────────────────┤
│ 长期记忆(Long-term Memory) │ ← 向量数据库
│ - 用户偏好和习惯 │
│ - 历史交互摘要 │
│ - 知识库 │
└──────────────────────────────────┘记忆模块设计:
python
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional
@dataclass
class Memory:
content: str
timestamp: datetime = field(default_factory=datetime.now)
importance: float = 0.5 # 0-1,重要性分数
embedding: Optional[list] = None # 向量表示
metadata: dict = field(default_factory=dict) # 额外信息
class AgentMemory:
def __init__(self, llm, vector_store):
self.short_term = [] # 短期:列表
self.episodic = [] # 中期:对话历史
self.long_term = vector_store # 长期:向量库
self.llm = llm
def add(self, content, importance=0.5, **metadata):
"""添加记忆"""
mem = Memory(
content=content,
importance=importance,
metadata=metadata
)
# 短期记忆直接加入
self.short_term.append(mem)
# 重要的记忆同时存入长期
if importance > 0.7:
mem.embedding = self.llm.embed(content)
self.long_term.add(mem)
def recall(self, query, top_k=5):
"""回忆相关记忆"""
# 从短期记忆中取最近 N 条
recent = self.short_term[-top_k:]
# 从长期记忆中检索相关内容
query_embedding = self.llm.embed(query)
long_term_results = self.long_term.search(
query_embedding, top_k=top_k
)
# 合并 + 去重 + 按重要性排序
all_memories = recent + long_term_results
all_memories.sort(key=lambda m: m.importance, reverse=True)
return all_memories[:top_k]
def compress(self):
"""压缩短期记忆到中期"""
if len(self.short_term) > 20:
# 用 LLM 总结近期记忆
summary = self.llm.generate(
f"总结以下内容的关键信息:\n"
f{chr(10).join(m.content for m in self.short_term)}"
)
self.episodic.append(Memory(
content=summary,
importance=0.8,
metadata={"type": "summary"}
))
# 只保留最近 5 条
self.short_term = self.short_term[-5:]
def forget(self):
"""遗忘机制:删除低重要性记忆"""
self.short_term = [
m for m in self.short_term if m.importance > 0.3
]记忆的存储介质:
| 记忆类型 | 存储介质 | 检索方式 | 特点 |
|---|---|---|---|
| 短期 | 内存/Context | 直接访问 | 快但容量有限 |
| 中期 | Redis/数据库 | 时间排序 | 可持久化 |
| 长期 | 向量数据库 | 语义检索 | 容量大但检索有延迟 |
记忆的写入策略:
什么信息值得记住?
1. 用户明确要求记住的 → "记住我喜欢简洁风格"
2. 关键决策和结果 → "选择了方案 A 因为..."
3. 错误和教训 → "上次用 X 方法失败了"
4. 用户偏好 → 从交互中推断
5. 任务执行过程 → 成功的执行路径
什么信息可以遗忘?
1. 重复信息 → 合并去重
2. 过时信息 → "当前时间是 2024 年"(过了就无意义)
3. 低重要性信息 → "好的" "收到" 等无实质内容追问延伸:
- 记忆太多导致检索变慢怎么办?(压缩 + 分层 + 索引优化)
- 怎么衡量记忆系统的效果?(记忆命中率、任务完成率提升)
Q9: Agent 的长短期记忆系统怎么做的?记忆是怎么存的?粒度是多少?怎么用的? 「🔴 高级」
考察点:记忆系统的工程实现细节。
参考答案:
短期记忆实现:
短期记忆 = LLM 上下文窗口
存储:LLM 的 Context(无独立存储,就是 Prompt 的一部分)
粒度:每轮对话(user message + assistant message + tool result)
容量:受 LLM 上下文窗口限制(4K-200K tokens)
淘汰:FIFO(超出窗口的从前面截断)python
class ShortTermMemory:
def __init__(self, max_tokens=8000):
self.messages = []
self.max_tokens = max_tokens
def add(self, role, content):
self.messages.append({"role": role, "content": content})
self._truncate()
def _truncate(self):
"""超出 token 限制时截断旧消息"""
while self._count_tokens() > self.max_tokens and len(self.messages) > 2:
# 保留第一条(系统提示)和最近的
self.messages.pop(1) # 删除第二条
def _count_tokens(self):
return sum(len(m["content"]) // 4 for m in self.messages)
def get_context(self):
return self.messages长期记忆实现:
长期记忆 = 向量数据库 + 结构化存储
存储介质:
- 向量数据库(Milvus/Pinecone/Chroma)→ 语义记忆
- 关系数据库(PostgreSQL)→ 结构化记忆(用户偏好、任务记录)
- 图数据库(Neo4j)→ 关系记忆(实体关系、知识图谱)
存储粒度:
- 粗粒度:整个对话/文档 → 检索准确度低,但数量少
- 细粒度:每句话/每个事实 → 检索准确度高,但数量多
- 推荐:中等粒度(一个事实/一段交互 = 一条记忆)python
class LongTermMemory:
def __init__(self, embed_model, vector_store, db):
self.embed_model = embed_model
self.vector_store = vector_store # 向量库
self.db = db # 结构化存储
def store(self, content, mem_type="episodic", **metadata):
"""存储长期记忆"""
# 1. 生成 embedding
embedding = self.embed_model.embed(content)
# 2. 存入向量库(语义检索用)
vec_id = self.vector_store.add(
embedding=embedding,
payload={
"content": content,
"type": mem_type,
"timestamp": datetime.now().isoformat(),
**metadata
}
)
# 3. 同时存入关系库(精确查询用)
self.db.execute(
"INSERT INTO memories (id, content, type, metadata) VALUES (?, ?, ?, ?)",
(vec_id, content, mem_type, json.dumps(metadata))
)
def retrieve(self, query, top_k=5, mem_type=None):
"""检索长期记忆"""
# 1. 向量语义检索
query_emb = self.embed_model.embed(query)
results = self.vector_store.search(
query_emb,
top_k=top_k,
filter={"type": mem_type} if mem_type else None
)
# 2. 可选:关键词补充检索(混合检索)
keyword_results = self.db.execute(
"SELECT * FROM memories WHERE content LIKE ? LIMIT ?",
(f"%{query}%", top_k)
)
# 3. 合并 + 去重 + 重排序
return self._merge_and_rerank(results, keyword_results)记忆的使用方式:
python
class AgentWithMemory:
def __init__(self, llm, memory):
self.llm = llm
self.memory = memory # AgentMemory 实例
def chat(self, user_input):
# 1. 从长期记忆中检索相关信息
relevant_memories = self.memory.recall(user_input, top_k=5)
memory_context = "\n".join(
f"- {m.content}" for m in relevant_memories
)
# 2. 获取短期记忆(当前对话上下文)
short_term = self.memory.get_short_term()
# 3. 组装 Prompt
prompt = f"""
系统:你是一个有记忆的 AI 助手。
相关记忆:
{memory_context}
对话历史:
{short_term}
用户:{user_input}
"""
# 4. LLM 生成
response = self.llm.generate(prompt)
# 5. 存入记忆
self.memory.add(user_input, importance=0.5, type="user")
self.memory.add(response, importance=0.6, type="assistant")
# 6. 定期压缩
self.memory.compress()
return response记忆粒度的选择:
| 粒度 | 内容 | 示例 | 适用场景 |
|---|---|---|---|
| 对话级 | 整轮对话 | "用户问了 X,我回答了 Y" | 简单对话 |
| 事实级 | 单个事实 | "用户偏好简洁回答" | 知识型记忆 |
| 动作级 | 每个动作 | "调用了搜索工具,找到了 X" | 执行过程 |
| 摘要级 | 多轮摘要 | "讨论了 AI Agent 架构设计" | 长期归档 |
推荐粒度:事实级 + 动作级混合
一条记忆 = 一个事实/一个动作 + 上下文 + 时间戳 + 重要性
示例记忆条目:
{
"content": "用户是 Java 开发者,偏好使用 Spring AI 框架",
"type": "preference",
"timestamp": "2025-08-25T10:00:00",
"importance": 0.8,
"source": "inferred_from_interaction"
}追问延伸:
- 怎么给记忆打重要性分数?(LLM 评估 + 频率 + 时效性)
- 记忆冲突怎么办?(最新优先 + 来源可信度 + 人工确认)
Q10: 什么是 Multi-Agent? 「🟢 校招/初级」
考察点:Multi-Agent 的基本概念。
参考答案:
Multi-Agent = 多个 Agent 协作完成一个复杂任务
Single-Agent:一个 Agent 做所有事
User → Agent(规划+执行+检查)→ Result
Multi-Agent:多个 Agent 分工协作
User → Planner Agent → Coder Agent → Reviewer Agent → Tester Agent → Result为什么需要 Multi-Agent:
| 原因 | 说明 |
|---|---|
| 单 Agent 能力有限 | 一个 Agent 难以精通所有领域 |
| 上下文限制 | 复杂任务信息量超出单个 Context |
| 专注度 | 每个 Agent 只负责一件事,质量更高 |
| 并行执行 | 多个 Agent 可以同时工作 |
| 角色分离 | 规划、执行、审查分离,互相制约 |
| 可扩展性 | 新增能力只需增加新 Agent |
Multi-Agent 的常见模式:
1. 线性流水线模式:
Agent A → Agent B → Agent C → Result
(每个 Agent 负责一个阶段)
2. 协作讨论模式:
Agent A ←→ Agent B ←→ Agent C
(多轮讨论达成共识)
3. 主管-工人模式:
Supervisor Agent
├── Worker Agent 1
├── Worker Agent 2
└── Worker Agent 3
(主管分发任务,工人执行)
4. 竞争模式:
Agent A → Result A
Agent B → Result B → 选最好的
Agent C → Result C
(多个 Agent 各自完成,选最优)
5. 层级模式:
CEO Agent
├── Manager Agent 1
│ ├── Worker Agent 1
│ └── Worker Agent 2
└── Manager Agent 2
└── Worker Agent 3Multi-Agent 框架对比:
| 框架 | 特点 | 语言 | 适用场景 |
|---|---|---|---|
| AutoGen | 对话式多 Agent | Python | 研究、原型 |
| CrewAI | 角色扮演式 | Python | 团队协作模拟 |
| MetaGPT | SOP 驱动 | Python | 软件开发 |
| LangGraph | 图状态机 | Python/JS | 复杂流程控制 |
| LangChain4j | Java 生态 | Java | 企业级应用 |
一个 Multi-Agent 示例:
python
# 软件开发 Multi-Agent 系统
class DevTeam:
def __init__(self):
self.product_manager = Agent(
role="产品经理",
goal="明确需求,输出 PRD",
tools=["search", "write_doc"]
)
self.architect = Agent(
role="架构师",
goal="设计技术方案",
tools=["search", "draw_diagram", "write_doc"]
)
self.developer = Agent(
role="开发工程师",
goal="编写代码",
tools=["code_editor", "search", "test_runner"]
)
self.tester = Agent(
role="测试工程师",
goal="编写和执行测试",
tools=["test_runner", "bug_reporter"]
)
def run(self, requirement):
# 1. 产品经理出 PRD
prd = self.product_manager.run(f"分析需求:{requirement}")
# 2. 架构师出方案
design = self.architect.run(f"根据 PRD 设计方案:{prd}")
# 3. 开发编码
code = self.developer.run(f"根据设计编写代码:{design}")
# 4. 测试验证
test_result = self.tester.run(f"测试代码:{code}")
# 5. 根据测试结果决定是否返工
if test_result.has_bugs:
code = self.developer.run(f"修复 bug:{test_result.bugs}")
return {"prd": prd, "design": design, "code": code, "test": test_result}追问延伸:
- Multi-Agent 怎么保证一致性?(共享状态 + 消息传递 + 冲突检测)
- 多 Agent 通信成本怎么控制?(控制 Agent 数量 + 共享 Context + 消息压缩)
Q11: 说说 Single-Agent 和 Multi-Agent 的设计方案? 「🔴 高级」
考察点:单/多 Agent 架构的对比和方案设计。
参考答案:
Single-Agent 设计方案:
┌────────────────────────────────────┐
│ Single-Agent │
│ │
│ ┌──────────────────────────────┐ │
│ │ LLM(大脑) │ │
│ │ 规划 + 推理 + 决策 │ │
│ └──────────┬───────────────────┘ │
│ │ │
│ ┌──────────┴───────────────────┐ │
│ │ 工具集 │ │
│ │ 搜索 | 代码 | SQL | API │ │
│ └──────────────────────────────┘ │
│ │
│ ┌──────────────────────────────┐ │
│ │ 记忆 │ │
│ │ 短期(上下文) + 长期(向量库)│ │
│ └──────────────────────────────┘ │
└────────────────────────────────────┘python
# Single-Agent:一个 Agent 通过 ReAct 循环完成所有任务
class SingleAgent:
def __init__(self, llm, tools, memory):
self.llm = llm
self.tools = tools # 丰富的工具集
self.memory = memory
self.max_steps = 15
def run(self, task):
for step in range(self.max_steps):
# 1. 检索记忆
context = self.memory.recall(task)
# 2. LLM 决策下一步
thought, action = self.llm.decide(task, context, self.history)
# 3. 执行工具
if action is None:
return thought # 最终回答
result = self.tools[action.name].run(action.args)
# 4. 记录历史
self.history.append((thought, action, result))
return "达到最大步数限制"Single-Agent 的特点:
| 优点 | 缺点 |
|---|---|
| 架构简单 | 单个 LLM 上下文限制 |
| 调试方便 | 难以处理多领域复杂任务 |
| 成本可控 | 串行执行,延迟高 |
| 状态管理简单 | Agent 角色冲突(又要规划又要执行) |
| 无通信开销 | 无法并行 |
Multi-Agent 设计方案:
┌──────────────────────────────────────────────┐
│ Multi-Agent │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Planner │ │ Executor │ │ Reviewer │ │
│ │ Agent │ │ Agent │ │ Agent │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └──────────────┼──────────────┘ │
│ │ │
│ ┌───────┴───────┐ │
│ │ 共享状态/消息总线 │ │
│ └───────────────┘ │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ 工具池(共享或独立) │ │
│ └──────────────────────────────────────┘ │
└──────────────────────────────────────────────┘python
# Multi-Agent:Supervisor 模式
class MultiAgentSystem:
def __init__(self, llm):
self.supervisor = Agent(
llm=llm,
role="Supervisor",
system_prompt="你是任务管理者,负责拆分任务和分发给合适的 Agent"
)
self.workers = {
"researcher": Agent(
llm=llm,
role="Researcher",
tools=["search", "read_url"],
system_prompt="你是研究员,擅长搜索和整理信息"
),
"coder": Agent(
llm=llm,
role="Coder",
tools=["code_execute", "file_write"],
system_prompt="你是程序员,擅长编写和调试代码"
),
"writer": Agent(
llm=llm,
role="Writer",
tools=["search"],
system_prompt="你是技术作家,擅长撰写文档"
),
}
self.shared_state = {} # 共享状态
def run(self, task):
# 1. Supervisor 拆分任务并分配
plan = self.supervisor.run(
f"将以下任务拆分并分配给 researcher/coder/writer:\n{task}"
)
# 2. 并行执行可并行的子任务
results = {}
for subtask in plan.subtasks:
agent = self.workers[subtask.assigned_to]
result = agent.run(subtask.description)
results[subtask.id] = result
self.shared_state[subtask.id] = result
# 3. Supervisor 综合结果
final = self.supervisor.run(
f"综合以下结果给出最终回答:\n{results}"
)
return final对比分析:
| 维度 | Single-Agent | Multi-Agent |
|---|---|---|
| 架构复杂度 | 低 | 高 |
| 开发成本 | 低 | 高 |
| 任务质量 | 中(单 Agent 精力分散) | 高(每个 Agent 专注) |
| 延迟 | 高(串行) | 可并行降低延迟 |
| LLM 调用成本 | 中(单循环) | 高(多 Agent + 通信) |
| 调试难度 | 低 | 高(多 Agent 状态追踪) |
| 上下文利用 | 集中 | 分散(每个 Agent 有自己的上下文) |
| 适用任务 | 中等复杂度 | 高复杂度、多领域 |
选型建议:
选 Single-Agent:
- 任务步骤 < 10 步
- 单一领域
- 快速原型验证
- 成本敏感
选 Multi-Agent:
- 任务复杂度高(需要多种能力)
- 多领域知识(搜索+编码+写作)
- 需要并行
- 质量要求高(有 Reviewer)
- 可接受较高成本追问延伸:
- 多 Agent 之间怎么通信?(消息传递 / 共享内存 / 黑板模式)
- 怎么避免 Multi-Agent 陷入死循环?(设置最大轮数 + 超时 + 冲突检测)
Q12: Agent 记忆压缩通常有哪些方法? 「🟡 中级」
考察点:记忆压缩策略的系统性理解。
参考答案:
记忆压缩的目的是在有限的上下文窗口内保留最重要的信息。
1. 摘要压缩(Summarization):
原始记忆(10 条对话):
User: 帮我设计一个用户注册系统
Assistant: 好的,需要哪些字段?
User: 用户名、密码、邮箱、手机号
Assistant: 建议用 BCrypt 加密密码...
User: 用什么数据库?
Assistant: 推荐 PostgreSQL...
...(还有 5 条)
压缩后(1 条摘要):
"讨论了用户注册系统设计:字段包括用户名/密码/邮箱/手机号,
密码用 BCrypt 加密,数据库选 PostgreSQL"python
def summarize_memories(memories, llm):
"""用 LLM 将多条记忆压缩为摘要"""
combined = "\n".join(f"- {m.content}" for m in memories)
summary = llm.generate(
f"请将以下对话记录压缩为关键信息摘要,保留重要事实和决策:\n{combined}"
)
return Memory(content=summary, type="summary")2. 提取压缩(Extraction):
原始记忆:
"用户问了很多关于 RAG 的问题,包括文档切割策略、向量检索优化、
重排序方法,还讨论了评估指标"
提取后:
- 用户关注领域:RAG
- 讨论要点:文档切割、向量检索、重排序、评估指标
- 用户水平:中高级(问题较深入)python
def extract_key_info(memories, llm):
"""提取结构化关键信息"""
extraction_prompt = """
从以下对话中提取关键信息,格式:
- 用户偏好:
- 关键决策:
- 重要事实:
- 待办事项:
"""
return llm.generate(extraction_prompt + "\n".join(m.content for m in memories))3. 滑动窗口(Sliding Window):
保留最近 N 轮对话,丢弃更早的
记忆队列:[m1, m2, m3, m4, m5, m6, m7, m8]
窗口大小 = 5
保留:[m4, m5, m6, m7, m8]
丢弃:[m1, m2, m3] → 但可以先压缩后存入长期记忆4. 重要性过滤(Importance Filtering):
所有记忆都有重要性分数(0-1)
过滤前:[m1(0.3), m2(0.8), m3(0.5), m4(0.9), m5(0.2), m6(0.7)]
阈值 = 0.6
过滤后:[m2(0.8), m4(0.9), m6(0.7)]python
def filter_by_importance(memories, threshold=0.6):
"""按重要性过滤"""
return [m for m in memories if m.importance >= threshold]5. 聚类压缩(Clustering):
将相似记忆合并,每类保留代表
原始记忆:
"用户问了 RAG 文档切割"
"用户问了 RAG 向量检索"
"用户问了 RAG 重排序"
"用户问了 Agent 架构"
"用户问了 Agent 记忆"
聚类后:
RAG 类 → "用户深入讨论了 RAG 的文档切割、向量检索和重排序"
Agent 类 → "用户讨论了 Agent 架构和记忆机制"6. 层级压缩(Hierarchical):
Level 0:原始对话(每句话)
→ 压缩
Level 1:段落摘要(每 N 轮一个摘要)
→ 压缩
Level 2:会话摘要(整个会话一个摘要)
→ 压缩
Level 3:用户画像(跨会话总结)python
class HierarchicalMemory:
def __init__(self):
self.levels = {
0: [], # 原始消息
1: [], # 段落摘要
2: [], # 会话摘要
3: [], # 用户画像
}
def compress(self):
"""逐层压缩"""
# Level 0 → 1:每 5 条压缩为 1 条
while len(self.levels[0]) >= 5:
chunk = self.levels[0][:5]
self.levels[0] = self.levels[0][5:]
self.levels[1].append(summarize(chunk))
# Level 1 → 2:所有段落压缩为会话摘要
if len(self.levels[1]) >= 3:
self.levels[2].append(summarize(self.levels[1]))
self.levels[1] = []
# Level 2 → 3:跨会话压缩为用户画像
if len(self.levels[2]) >= 3:
self.levels[3].append(extract_profile(self.levels[2]))
self.levels[2] = []各方法对比:
| 方法 | 压缩率 | 信息损失 | 计算成本 | 适用场景 |
|---|---|---|---|---|
| 摘要 | 高 | 中 | 高(LLM) | 通用 |
| 提取 | 高 | 低(结构化) | 高 | 事实提取 |
| 滑动窗口 | 中 | 高(直接丢弃) | 低 | 短期记忆 |
| 重要性过滤 | 中 | 低(丢不重要) | 低 | 混合策略 |
| 聚类 | 中 | 中 | 中 | 话题分类 |
| 层级 | 高 | 低 | 高 | 长期系统 |
实际组合策略:
python
def compress_memory(memories):
# 1. 先过滤低重要性
important = filter_by_importance(memories, threshold=0.4)
# 2. 相似记忆聚类合并
clusters = cluster(important)
# 3. 每个聚类生成摘要
summaries = [summarize(c) for c in clusters]
# 4. 超长时层级压缩
if len(summaries) > 10:
summaries = hierarchical_compress(summaries)
return summaries追问延伸:
- 压缩后的记忆怎么保证不丢关键信息?(保留原始索引 + 按需检索原文)
- 实时压缩 vs 定时压缩哪个好?(实时更及时但成本高,定时更经济)
Q13: 在工程实践中,为什么有时候选择「手搓」Agent,而不是直接用成熟框架? 「🟡 中级」
考察点:工程选型的权衡思考。
参考答案:
成熟框架的局限性:
| 问题 | 说明 |
|---|---|
| 黑盒化 | 框架封装太深,出问题难以定位和修复 |
| 灵活性不足 | 框架的抽象不一定匹配业务需求 |
| 性能开销 | 通用框架有额外抽象层,延迟和成本更高 |
| 版本绑定 | 框架升级可能引入 breaking change |
| 定制困难 | 深度定制需要理解框架源码,成本高 |
| 技术栈不匹配 | Java 项目用 Python 框架不现实 |
选择「手搓」的场景:
1. 业务逻辑特殊 → 框架的通用模式不适用
"我们的 Agent 需要特定的审批流程 + 合规检查,框架不支持"
2. 性能要求极高 → 框架开销不可接受
"每秒处理 1000+ 请求,框架的序列化/反序列化开销太大"
3. 深度定制 → 需要控制每个细节
"我们需要自定义记忆策略 + 自定义工具调用协议 + 自定义反思逻辑"
4. 技术栈限制 → Java/Go 项目不能直接用 Python 框架
"我们的技术栈是 Java + Spring AI,需要自己实现 Agent 逻辑"
5. 学习和掌控 → 团队需要深入理解 Agent 原理
"团队刚开始做 AI,手搓一遍才能真正理解"
6. 安全合规 → 不能引入外部依赖
"金融场景,所有代码必须可审计"手搓 Agent 的核心代码(Java 示例):
java
public class SimpleAgent {
private final ChatClient llm;
private final Map<String, Tool> tools;
private final Memory memory;
private final int maxIterations;
public AgentResult run(String task) {
var context = memory.recall(task);
var history = new ArrayList<Step>();
for (int i = 0; i < maxIterations; i++) {
// 1. LLM 决策
var decision = llm.prompt()
.system(buildSystemPrompt(tools))
.user(buildUserPrompt(task, context, history))
.call()
.getContent();
// 2. 解析决策
var action = parseAction(decision);
if (action == null) {
// 最终回答
memory.store(task, decision, 0.7);
return new AgentResult(decision, history);
}
// 3. 执行工具
var result = tools.get(action.name()).execute(action.args());
// 4. 记录步骤
history.add(new Step(decision, action, result));
}
return new AgentResult("达到最大步数限制", history);
}
private String buildSystemPrompt(Map<String, Tool> tools) {
var toolDesc = tools.entrySet().stream()
.map(e -> "- " + e.getKey() + ": " + e.getValue().description())
.collect(Collectors.joining("\n"));
return """
你是一个 AI Agent。使用以下工具完成任务。
工具:%s
格式:Thought: <推理> / Action: <工具>(<参数>) / Final Answer: <回答>
""".formatted(toolDesc);
}
}手搓 vs 框架的对比:
| 维度 | 手搓 | 框架(如 LangChain) |
|---|---|---|
| 开发速度 | 慢(自己写) | 快(开箱即用) |
| 灵活性 | 高(完全可控) | 中(受框架约束) |
| 可维护性 | 取决于代码质量 | 框架有文档和社区 |
| 调试 | 容易(自己写的) | 难(黑盒) |
| 性能 | 可优化到最优 | 有额外开销 |
| 学习成本 | 需要深入理解 | 上手快 |
| 生态 | 无(自己建) | 丰富(插件/集成) |
混合方案(推荐):
核心逻辑手搓 + 非核心用框架
- Agent 循环、决策逻辑:手搓(需要完全可控)
- 工具定义、向量检索:用框架库(不需要自己造轮子)
- LLM 调用:用 SDK(直接调 API)
- 记忆管理:混合(核心逻辑手搓,存储用现成方案)追问延伸:
- 手搓 Agent 最容易踩什么坑?(错误处理、循环终止、上下文管理)
- 什么时候该从手搓迁移到框架?(团队扩大、需求复杂度上升)
Q14: 如何赋予 LLM 规划能力? 「🔴 高级」
考察点:LLM 规划能力的实现方法。
参考答案:
LLM 本身没有规划能力,需要通过以下方法「赋予」:
1. Prompt Engineering(提示工程):
方法:在 System Prompt 中明确要求 LLM 做规划
System Prompt:
"你是一个任务规划专家。面对任何任务,请先制定详细计划:
1. 将任务拆分为可执行的子任务
2. 标注每个子任务的依赖关系
3. 为每个子任务选择合适的工具
4. 定义每个子任务的成功标准
然后再逐步执行。"2. Few-Shot 示例(示例学习):
给 LLM 展示规划示例,让它学习规划模式
示例 1:
任务:写一篇技术博客
计划:
1. 调研 → search 工具 → 成功标准:收集 5+ 参考资料
2. 大纲 → write_doc → 成功标准:大纲包含 5+ 章节
3. 初稿 → write_doc → 成功标准:每章 500+ 字
4. 校对 → review → 成功标准:无语法错误
5. 润色 → write_doc → 成功标准:表达流畅
示例 2:
任务:分析竞品
计划:
1. 收集信息 → search → 竞品列表和特点
2. 对比分析 → analyze → 对比表格
3. 撰写报告 → write_doc → 分析报告3. 结构化输出(Structured Output):
python
# 用 JSON Schema 约束 LLM 输出规划结构
planning_prompt = """
你是一个规划专家。将任务拆分为结构化计划。
任务:{task}
输出 JSON 格式:
{{
"goal": "任务目标",
"steps": [
{{
"id": 1,
"action": "具体行动",
"tool": "使用的工具",
"depends_on": [],
"success_criteria": "成功标准"
}}
],
"estimated_steps": 5
}}
"""
# 使用 Function Calling 确保结构化
response = llm.functions.create(
name="create_plan",
description="创建任务执行计划",
parameters={
"type": "object",
"properties": {
"goal": {"type": "string"},
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {"type": "integer"},
"action": {"type": "string"},
"tool": {"type": "string"},
"depends_on": {"type": "array", "items": {"type": "integer"}},
"success_criteria": {"type": "string"}
}
}
}
}
}
)4. 分层规划(Hierarchical Planning):
第一层:粗粒度规划(3-5 大步)
Step 1: 信息收集
Step 2: 分析处理
Step 3: 输出结果
第二层:每个大步细化为子步骤
Step 1 细化:
1.1 搜索关键词
1.2 读取相关文档
1.3 提取关键信息
第三层:子步骤执行
1.1 → search("关键词") → 结果5. 规划+自适应调整(Replan):
python
class AdaptivePlanner:
def plan_and_execute(self, task):
# 初始规划
plan = self.llm.create_plan(task)
results = {}
for step in plan.steps:
# 执行
result = self.execute_step(step)
results[step.id] = result
# 检查是否需要重新规划
if not self._check_success(result, step.success_criteria):
# 自适应重新规划
new_plan = self.llm.replan(
task=task,
completed=results,
failed_step=step,
reason=result.error
)
plan = self._merge_plan(plan, new_plan)
return results
def _merge_plan(self, old_plan, new_plan):
"""合并旧计划的已完成部分和新计划"""
completed = [s for s in old_plan.steps if s.id in self.completed]
return Plan(steps=completed + new_plan.steps)6. 外部知识增强规划:
方法:用 RAG 检索历史成功规划模板
规划时:
1. 从记忆/知识库中检索类似任务的历史规划
2. 参考成功规划模板
3. 结合当前任务特点调整
Prompt:
"以下是类似任务的成功规划参考:
{retrieved_plans}
请参考这些规划模式,为当前任务制定计划:
{current_task}"规划能力评估:
| 指标 | 说明 |
|---|---|
| 拆分合理性 | 子任务是否覆盖目标且不过度拆分 |
| 依赖正确性 | 依赖关系是否正确 |
| 工具选择 | 是否选择了合适的工具 |
| 可执行性 | 子任务是否可执行 |
| 自适应性 | 执行失败能否合理调整 |
追问延伸:
- 不同 LLM 的规划能力差异大吗?(GPT-4/Claude > 开源模型,需要更好的模型)
- 规划太细或太粗怎么判断?(看执行成功率,太粗执行失败率高,太细成本高)
Q15: 讲讲 Agent 的反思机制?为什么要用反思?具体怎么实现? 「🔴 高级」
考察点:反思机制的原理和工程实现。
参考答案:
为什么要用反思:
没有反思的问题:
1. LLM 一次生成质量不稳定 → 可能有错误
2. 错误会传递到后续步骤 → 错误放大
3. LLM 不会主动发现自己的问题 → 缺乏自我纠错
4. 相似错误会重复犯 → 没有学习和改进
反思的价值:
1. 自我纠错 → 发现错误并修复
2. 质量提升 → 多轮改进逐步提升
3. 经验积累 → 从错误中学习
4. 可信度评估 → 反思分数可作为置信度反思机制的实现:
1. 自我批判(Self-Critique):
python
class ReflectionAgent:
def __init__(self, llm):
self.llm = llm
def run(self, task, max_rounds=3):
result = self._generate(task)
for round_i in range(max_rounds):
# 反思:评估当前结果
critique = self._critique(task, result)
if critique.is_perfect:
break # 已经足够好
# 改进:根据反思修复问题
result = self._improve(task, result, critique)
return result
def _generate(self, task):
"""初始生成"""
return self.llm.generate(f"完成以下任务:{task}")
def _critique(self, task, result):
"""反思:批判当前结果"""
critique_prompt = f"""
任务:{task}
当前结果:{result}
请作为审查者,评估这个结果:
1. 是否完全满足任务要求?
2. 有没有事实错误?
3. 有没有逻辑漏洞?
4. 有没有遗漏的边界情况?
5. 质量评分(1-10)?
如果评分 >= 8,输出"PASS"。
否则输出"FAIL"并列出具体问题。
"""
response = self.llm.generate(critique_prompt)
return self._parse_critique(response)
def _improve(self, task, result, critique):
"""改进:根据反思修复"""
improve_prompt = f"""
任务:{task}
当前结果:{result}
审查意见:{critique.issues}
请根据审查意见改进结果,修复所有问题。
"""
return self.llm.generate(improve_prompt)2. 交叉模型批判(Cross-Model Critique):
python
class CrossModelReflection:
def __init__(self, generator_llm, critic_llm):
self.generator = generator_llm # 生成模型(如 GPT-4)
self.critic = critic_llm # 批判模型(如 Claude)
def run(self, task):
result = self.generator.generate(task)
for _ in range(3):
# 用不同模型批判,避免同模型自评偏差
critique = self.critic.generate(
f"审查以下结果的质量,指出问题:\n任务:{task}\n结果:{result}"
)
if "PASS" in critique:
break
result = self.generator.generate(
f"根据以下意见改进:\n{critique}\n改进结果:"
)
return result3. 工具验证反思(Tool-Verified Reflection):
python
class ToolVerifiedReflection:
def __init__(self, llm, tools):
self.llm = llm
self.tools = tools
def run(self, task):
result = self.llm.generate(task)
# 用工具验证结果的正确性
if "代码" in task:
# 代码任务:执行验证
test_result = self.tools["code_execute"].run(result)
if test_result.has_error:
result = self.llm.generate(
f"代码有错误:{test_result.error}\n修复:{result}"
)
if "事实" in task:
# 事实任务:搜索验证
search_result = self.tools["search"].run(task)
if not self._fact_check(result, search_result):
result = self.llm.generate(
f"事实有误,参考信息:{search_result}\n修正:{result}"
)
return result4. Reflexion 框架(带记忆的反思):
python
class ReflexionAgent:
"""每次失败后总结教训,存入记忆,下次避免"""
def __init__(self, llm, memory):
self.llm = llm
self.memory = memory # 记忆中存储反思教训
def run(self, task, max_attempts=3):
for attempt in range(max_attempts):
# 获取历史反思教训
lessons = self.memory.recall(task)
# 带着教训执行
result = self.llm.generate(
f"任务:{task}\n\n历史教训:{lessons}\n\n请执行任务。"
)
# 评估结果
if self._is_successful(result):
return result
# 反思失败原因
reflection = self.llm.generate(
f"任务:{task}\n尝试结果:{result}\n\n"
f"这次为什么失败了?总结教训,避免下次再犯。"
)
# 存入记忆
self.memory.store(
content=reflection,
importance=0.9,
type="lesson"
)
return result反思的效果:
| 场景 | 无反思 | 有反思 | 提升 |
|---|---|---|---|
| 代码生成 | 55% 通过率 | 75% 通过率 | +36% |
| 数学推理 | 40% 正确率 | 60% 正确率 | +50% |
| 文本质量 | 6.5/10 | 8.2/10 | +26% |
| 事实准确率 | 75% | 88% | +17% |
反思的代价:
| 维度 | 代价 |
|---|---|
| LLM 调用次数 | 2-4 倍(生成+批判+改进) |
| 延迟 | 2-4 倍 |
| 成本 | 2-4 倍 |
| 复杂度 | 增加(需要管理反思循环) |
追问延伸:
- 反思会不会越改越差?(可能,需要设置最大轮数和回退机制)
- 怎么判断反思应该停止?(评分达标 / 改进幅度递减 / 达到最大轮数)
Q16: 如何设计多 Agent 的协作与动态切换机制? 「🔴 高级」
考察点:Multi-Agent 协作架构和动态路由的设计。
参考答案:
多 Agent 协作的核心问题:
1. 怎么分工? → 每个 Agent 负责什么
2. 怎么通信? → Agent 之间怎么传递信息
3. 怎么路由? → 任务分给哪个 Agent
4. 怎么协调? → 冲突怎么处理
5. 怎么终止? → 什么时候算完成1. Supervisor 模式(主管分发):
python
class SupervisorSystem:
"""一个 Supervisor 管理多个 Worker Agent"""
def __init__(self):
self.supervisor = Agent(role="supervisor")
self.workers = {
"research": Agent(role="researcher", tools=["search"]),
"code": Agent(role="coder", tools=["python"]),
"write": Agent(role="writer", tools=["doc"]),
}
self.shared_state = SharedState()
def run(self, task):
# Supervisor 分析任务并分配
assignment = self.supervisor.run(
f"分析任务并分配给合适的 Agent(research/code/write):{task}"
)
results = {}
for subtask in assignment.subtasks:
agent = self.workers[subtask.agent]
result = agent.run(subtask.description)
results[subtask.id] = result
self.shared_state.set(subtask.id, result)
# Supervisor 综合
final = self.supervisor.run(f"综合结果:{results}")
return final2. 动态路由切换:
python
class DynamicRouter:
"""根据任务特征动态路由到不同 Agent"""
def __init__(self, llm):
self.llm = llm
self.agents = {
"technical": Agent(system_prompt="你是技术专家,擅长编程和系统设计"),
"business": Agent(system_prompt="你是商业分析师,擅长市场分析和商业模式"),
"creative": Agent(system_prompt="你是创意总监,擅长文案和设计"),
"research": Agent(system_prompt="你是研究员,擅长信息搜集和分析"),
}
def route(self, query):
"""用 LLM 分类,动态选择 Agent"""
route_prompt = f"""
将以下问题分类到最合适的 Agent:
- technical: 技术问题(编程、架构、系统设计)
- business: 商业问题(市场、战略、运营)
- creative: 创意问题(文案、设计、品牌)
- research: 研究问题(信息搜集、数据分析)
问题:{query}
只输出类别名。
"""
category = self.llm.generate(route_prompt).strip().lower()
return self.agents.get(category, self.agents["research"])
def run(self, query):
agent = self.route(query)
return agent.run(query)3. 对话式协作(Conversation-based):
python
class ConversationalMAS:
"""多个 Agent 通过对话协商完成任务"""
def __init__(self):
self.agents = [
Agent(role="产品经理", goal="确保需求合理"),
Agent(role="技术负责人", goal="确保技术可行"),
Agent(role="测试负责人", goal="确保质量可控"),
]
def run(self, task, max_rounds=5):
discussion = [{"role": "user", "content": task}]
for round_i in range(max_rounds):
round_messages = []
for agent in self.agents:
# 每个 Agent 看到完整讨论历史,发表意见
response = agent.run(
f"讨论历史:{discussion}\n请发表你的看法。"
)
round_messages.append({
"role": agent.role,
"content": response
})
discussion.extend(round_messages)
# 检查是否达成共识
if self._check_consensus(discussion):
break
# 主持人总结
return self.moderator.run(f"总结讨论结果:{discussion}")4. 状态机驱动(State Machine):
python
class StateMachineMAS:
"""用状态图控制 Agent 协作流程"""
def __init__(self):
self.graph = StateGraph()
# 定义节点(每个节点是一个 Agent)
self.graph.add_node("plan", planner_agent)
self.graph.add_node("research", researcher_agent)
self.graph.add_node("code", coder_agent)
self.graph.add_node("review", reviewer_agent)
self.graph.add_node("test", tester_agent)
# 定义边(转移条件)
self.graph.add_edge("plan", "research")
self.graph.add_conditional_edge("research", "code", condition="has_code_task")
self.graph.add_edge("code", "review")
self.graph.add_conditional_edge("review", "code", condition="needs_revision")
self.graph.add_conditional_edge("review", "test", condition="approved")
self.graph.add_conditional_edge("test", "code", condition="has_bugs")
self.graph.add_edge("test", "END", condition="all_pass")
def run(self, task):
return self.graph.execute(task)5. 拍卖机制(Auction-based):
python
class AuctionMAS:
"""多个 Agent 竞标任务,选最优"""
def __init__(self):
self.agents = [Agent1(), Agent2(), Agent3()]
def run(self, task):
# 每个 Agent 评估自己的能力和信心
bids = []
for agent in self.agents:
confidence = agent.estimate(task) # 0-1
bids.append((agent, confidence))
# 选信心最高的
best_agent, _ = max(bids, key=lambda x: x[1])
result = best_agent.run(task)
# 如果最好的不够好,多个 Agent 各做一份,选最优
if best_confidence < 0.7:
results = [agent.run(task) for agent in self.agents]
return self.judge.select_best(results)
return result协作中的冲突处理:
| 冲突类型 | 解决方案 |
|---|---|
| 结果冲突 | 投票 / 仲裁 Agent / 选最高信心 |
| 资源冲突 | 排队 / 优先级 / 锁机制 |
| 观点冲突 | 多轮讨论 / 妥协 / 人工介入 |
| 死循环 | 最大轮数 / 超时 / 强制终止 |
动态切换的关键设计:
1. 能力注册:每个 Agent 注册自己的能力描述
2. 任务分析:分析任务需要什么能力
3. 匹配路由:能力与任务匹配,选最合适的 Agent
4. 动态加载:按需加载 Agent(节省资源)
5. 降级策略:首选 Agent 失败时,降级到备选
6. 结果评估:评估 Agent 输出质量,用于路由优化追问延伸:
- 怎么避免多 Agent 讨论陷入死循环?(最大轮数 + 共识检测 + 仲裁机制)
- Agent 数量怎么决定?(3-5 个为宜,太多通信成本高,太少不够专业)