Agent模式测试题答案
📝 答案解析
🎯 本答案提供详细解析,帮助理解核心概念
第一部分:概念理解(30分)
1. 单选题答案(每题3分,共15分)
1.1 答案:C
解析: Agent的核心架构包括:
- Planning(规划层):负责任务分解和决策
- Memory(记忆层):存储对话历史和上下文
- Tools(工具层):提供外部能力
- Action(执行层):执行具体操作
Database(数据库)是存储方案的一种,但不是Agent架构的核心组成部分。
1.2 答案:B
解析: Function Call的核心作用是让LLM能够以结构化的方式调用外部函数。它不是为了提速(A错误),也不是主要为了减少Token(C错误),更不是直接提高推理能力(D错误),而是扩展LLM的能力边界,让它能够调用工具完成实际任务。
1.3 答案:B
解析: 多工具并行调用的核心特点是可以同时发起多个独立的工具调用请求,这些请求之间没有依赖关系。例如同时查询多个城市的天气,可以并行执行提高效率。选项A描述的是串行调用,C和D都是错误的。
1.4 答案:B
解析: Reflection(反思)步骤的目的是分析刚才执行的结果,判断:
- 工具调用是否成功?
- 返回的数据是否有用?
- 是否发现异常情况?
- 下一步应该做什么?
它不是重新执行(A),不是删除记录(C),也不是报告进度(D),而是为下一轮决策提供指导。
1.5 答案:B
解析: Redis的主要优势是:
- 快速读写(内存存储)
- 自动过期机制(TTL)
- 适合临时数据
选项A错误(Redis不是永久存储),C错误(Redis不擅长复杂查询),D不是主要优势。
2. 多选题答案(每题3分,共15分)
2.1 答案:A、B、C、E
解析:
- ✅ A:能调用外部工具是Agent的核心能力
- ✅ B:自主决策是Agent区别于简单LLM的关键
- ✅ C:端到端完成任务是Agent的目标
- ❌ D:错误!Agent仍需要人工设计和监督
- ✅ E:通过工具调用可以获取实时信息
2.2 答案:A、B、C、E
解析:
工具描述的标准结构包括:
- ✅ name:工具名称
- ✅ description:功能描述(非常重要,影响LLM是否选择该工具)
- ✅ parameters:参数定义(类型、描述)
- ❌ D:不需要包含实现代码
- ✅ required:必需参数列表
2.3 答案:B、C、E
解析:
链式调用适合"前一步的结果是后一步的输入"的场景:
- ❌ A:查询天气是单步操作
- ✅ B:搜索→生成报告→发邮件,典型的链式任务
- ✅ C:查订单→查物流,有依赖关系
- ❌ D:简单计算是单步操作
- ✅ E:查地址→查商家→推荐,多步依赖
2.4 答案:A、B、C、D
解析:
Messages列表中的标准角色:
- ✅ system:系统提示,定义Agent人设
- ✅ user:用户输入
- ✅ assistant:AI回复
- ✅ tool:工具执行结果
- ❌ admin:不是标准角色
2.5 答案:A、B、C、E
解析:
有效的优化措施:
- ✅ A:防止死循环
- ✅ B:提高工具选择准确率
- ✅ C:控制上下文长度
- ❌ D:工具不是越多越好,应该精简
- ✅ E:提高系统鲁棒性
第二部分:代码分析(30分)
3. 代码阅读题答案
3.1 答案:
问题1:缺少的关键步骤(5分)
缺少以下步骤:
- 检查是否有工具调用:判断
response.choices[0].message.tool_calls是否存在 - 执行工具函数:调用实际的
get_weather()函数 - 构造tool消息:将工具结果封装成tool角色的消息
- 第二次调用LLM:将工具结果发回给LLM生成最终回复
完整代码应该是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| # 第一次调用后
assistant_msg = response.choices[0].message
messages.append(assistant_msg)
if assistant_msg.tool_calls:
for tool_call in assistant_msg.tool_calls:
# 执行工具
result = get_weather(location="北京")
# 添加工具结果
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
})
# 第二次调用
final_response = client.chat.completions.create(
model="qwen-plus",
messages=messages,
tools=tools
)
|
问题2:response对象包含的信息(5分)
如果LLM决定调用工具,response中会包含:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| {
"choices": [{
"message": {
"role": "assistant",
"content": null, # 或空字符串
"tool_calls": [{
"id": "call_xxx", # 唯一标识
"type": "function",
"function": {
"name": "get_weather",
"arguments": '{"location": "北京"}' # JSON字符串
}
}]
}
}]
}
|
3.2 答案:
问题1:三个核心步骤(3分)
代码实现了ReAct的三个核心步骤:
- Reasoning(推理):
step_1_plan() - 规划下一步行动 - Acting(行动):
step_2_act() - 执行工具调用 - Reflecting(反思):
step_3_reflect() - 分析执行结果
问题2:history的作用(3分)
self.history的作用是:
- 存储完整的执行历史
- 记录每一步的思考、行动、观察和反思
- 作为下一轮Planning的上下文输入
- 帮助Agent理解"我已经做了什么,接下来该做什么"
问题3:去掉步数限制的风险(4分)
风险包括:
- 死循环风险:如果Agent陷入重复操作,会无限循环
- 资源耗尽:无限调用LLM会导致巨额费用和Token耗尽
- 用户体验差:任务永远无法结束,用户一直等待
- 系统崩溃:内存占用不断增长,可能导致程序崩溃
解决方案:必须设置合理的max_steps(如5-10步),并在超出时给出明确提示。
3.3 答案:
问题1:为什么使用json.dumps和json.loads(3分)
原因:
- Redis只能存储字符串或字节类型
- Python的字典(dict)无法直接存入Redis
json.dumps()将字典序列化为JSON字符串json.loads()将JSON字符串反序列化为字典- 这样可以保持数据结构的完整性
问题2:expire的作用(3分)
expire(self.session_id, 3600)的作用:
- 设置key的过期时间为3600秒(1小时)
- 如果用户1小时内不再对话,Redis会自动删除该会话
- 节省内存空间,避免无用数据堆积
- 每次
add_message都会刷新过期时间
问题3:只保留最近10轮对话(4分)
修改方案:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| def add_message(self, role, content):
message = {"role": role, "content": content}
redis_client.rpush(self.session_id, json.dumps(message))
# 保留最近10轮对话(1轮=user+assistant=2条消息)
# 加上system消息,总共保留21条
max_messages = 21
current_length = redis_client.llen(self.session_id)
if current_length > max_messages:
# 删除最旧的消息(但保留system消息)
redis_client.ltrim(self.session_id, current_length - max_messages, -1)
redis_client.expire(self.session_id, 3600)
|
或者使用滑动窗口:
1
2
3
4
| def get_messages(self):
# 只获取最近20条消息
raw_messages = redis_client.lrange(self.session_id, -20, -1)
return [json.loads(msg) for msg in raw_messages]
|
第三部分:实战设计(40分)
4. 系统设计题答案(20分)
4.1 工具函数设计(8分)
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
| # 工具1:查询订单状态
def query_order_status(order_id: str) -> dict:
"""
功能:查询订单的当前状态
参数:order_id - 订单编号
返回:订单状态、商品信息、金额等
"""
# 工具2:查询物流信息
def query_logistics(tracking_id: str) -> dict:
"""
功能:查询物流轨迹
参数:tracking_id - 物流单号
返回:物流公司、当前位置、历史轨迹
"""
# 工具3:提交退款申请
def submit_refund(order_id: str, reason: str, amount: float) -> dict:
"""
功能:创建退款工单
参数:order_id - 订单号, reason - 退款原因, amount - 退款金额
返回:退款单号、预计处理时间
"""
# 工具4:搜索知识库
def search_faq(question: str) -> str:
"""
功能:从常见问题库中搜索答案
参数:question - 用户问题
返回:最相关的FAQ答案
"""
# 工具5:查询用户信息
def get_user_info(user_id: str) -> dict:
"""
功能:获取用户基本信息和历史订单
参数:user_id - 用户ID
返回:用户姓名、联系方式、VIP等级等
"""
|
评分要点:
4.2 架构模式选择(6分)
推荐:ReAct-Reflection模式
理由:
任务复杂度高:客服场景需要多步推理
- 例如:查订单 → 发现异常 → 查物流 → 发现地址问题 → 联系用户
需要动态决策:无法预设固定流程
- 不同问题需要不同的工具组合
- 需要根据中间结果调整策略
需要错误处理:
- 如果查询失败,需要尝试其他方法
- Reflection步骤可以发现异常并调整
不适合Simple Workflow:
不需要中央调度:
架构示意:
1
2
3
4
5
6
7
| 用户提问 → Planning(分析问题,选择工具)
↓
Acting(执行工具调用)
↓
Reflecting(分析结果,判断是否需要继续)
↓
完成 or 回到Planning
|
4.3 记忆系统方案(6分)
方案设计:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| ┌─────────────────────────────────────┐
│ 记忆系统架构 │
├─────────────────────────────────────┤
│ 1. 短期记忆(Redis) │
│ - Key: session:{user_id} │
│ - 存储:对话历史messages │
│ - TTL: 2小时 │
│ - 结构:List类型 │
├─────────────────────────────────────┤
│ 2. 订单上下文(Redis) │
│ - Key: context:{session_id} │
│ - 存储:当前讨论的订单信息 │
│ - 内容:order_id, status等 │
│ - TTL: 2小时 │
├─────────────────────────────────────┤
│ 3. 长期记忆(MySQL) │
│ - 表:conversation_history │
│ - 字段:session_id, user_id, │
│ messages, created_at │
│ - 用途:历史记录查询、分析 │
└─────────────────────────────────────┘
|
具体实现:
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
| class CustomerServiceMemory:
def __init__(self, user_id):
self.user_id = user_id
self.session_key = f"session:{user_id}"
self.context_key = f"context:{user_id}"
# 对话历史
def add_message(self, role, content):
redis_client.rpush(self.session_key, json.dumps({
"role": role,
"content": content,
"timestamp": time.time()
}))
redis_client.expire(self.session_key, 7200)
# 订单上下文
def set_order_context(self, order_info):
redis_client.setex(
self.context_key,
7200,
json.dumps(order_info)
)
def get_order_context(self):
data = redis_client.get(self.context_key)
return json.loads(data) if data else None
# 持久化
def save_to_db(self):
messages = self.get_messages()
db.insert({
"user_id": self.user_id,
"messages": messages,
"created_at": datetime.now()
})
|
评分要点:
- Redis存储方案(2分)
- 订单上下文管理(2分)
- 持久化方案(2分)
第四部分:问题解决(20分)
5.1 调试问题答案(10分)
可能原因及解决方案:
原因1:工具描述不清晰(3分)
- 问题:description写的是"查询天气"而不是"查询物流"
- 解决:优化description为"查询订单的物流信息,包括运输状态和位置"
原因2:工具未正确注册(3分)
- 问题:tools列表中没有包含物流查询工具
- 解决:检查tools列表,确保包含正确的工具定义
原因3:参数定义问题(2分)
- 问题:参数名不匹配,如定义的是
order_id但函数需要tracking_id - 解决:统一参数命名,或在工具函数中做转换
原因4:System Prompt限制(2分)
- 问题:System消息中可能写了"你无法查询实时信息"
- 解决:修改System Prompt,明确告知Agent可以使用工具
示例修复:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| tools = [{
"type": "function",
"function": {
"name": "query_logistics",
"description": "查询订单的物流配送信息,包括当前位置、配送状态、预计送达时间等实时信息",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "订单编号,如123456"
}
},
"required": ["order_id"]
}
}
}]
|
5.2 优化问题答案(10分)
问题1:经常超过最大步数限制(3-4分)
原因分析:
优化方案:
优化Planning Prompt:
添加任务完成判断:
1
| "如果已经获得足够信息回答用户,立即输出finish"
|
增加步数限制并优化:
实现子目标机制:
问题2:Token消耗过大(3-4分)
优化方案:
压缩历史对话:
1
2
3
4
5
6
7
| # 只保留最近5轮对话
messages = messages[-10:] # user+assistant=2条
# 或使用摘要
if len(messages) > 20:
summary = llm_summarize(messages[:-10])
messages = [system_msg, summary_msg] + messages[-10:]
|
优化工具返回内容:
1
2
3
4
5
6
7
| # 工具只返回关键信息,不返回完整数据
def query_order(order_id):
full_data = db.query(order_id)
return {
"status": full_data["status"],
"key_info": full_data["summary"] # 只返回摘要
}
|
使用更小的模型:
1
2
3
4
5
| # Planning用大模型,简单任务用小模型
if task_complexity == "simple":
model = "qwen-turbo" # 更便宜
else:
model = "qwen-plus"
|
问题3:重复调用相同工具(3-4分)
优化方案:
添加调用历史检测:
1
2
3
4
5
6
7
8
9
10
| def step_1_plan(self, user_query):
# 检查是否已经调用过
called_tools = [h["action"] for h in self.history]
context = f"""
用户问题: {user_query}
已执行操作: {called_tools}
注意:不要重复执行已完成的操作!
"""
|
缓存工具结果:
1
2
3
4
5
6
7
8
9
10
11
| tool_cache = {}
def execute_tool(tool_name, args):
cache_key = f"{tool_name}:{json.dumps(args)}"
if cache_key in tool_cache:
return tool_cache[cache_key]
result = actual_execute(tool_name, args)
tool_cache[cache_key] = result
return result
|
改进Reflection逻辑:
1
2
3
4
5
6
7
8
9
10
| def step_3_reflect(self, plan, observation):
prompt = f"""
刚才执行了: {plan['tool_name']}
结果: {observation}
反思:
1. 这个结果是否已经足够?
2. 是否需要调用其他工具(不是重复调用)?
3. 如果信息完整,应该结束任务
"""
|
第五部分:开放题(10分)
6. AI编程助手Agent设计
6.1 需要的工具(3分)
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
| tools = [
# 1. 文档搜索工具
{
"name": "search_docs",
"description": "搜索编程文档、API参考、Stack Overflow",
"parameters": {"query": "string"}
},
# 2. 代码生成工具
{
"name": "generate_code",
"description": "根据需求生成代码",
"parameters": {"requirement": "string", "language": "string"}
},
# 3. 代码执行工具
{
"name": "execute_code",
"description": "在沙箱环境中运行代码",
"parameters": {"code": "string", "language": "string"}
},
# 4. 测试运行工具
{
"name": "run_tests",
"description": "运行单元测试",
"parameters": {"test_file": "string"}
},
# 5. 错误分析工具
{
"name": "analyze_error",
"description": "分析错误堆栈,提供修复建议",
"parameters": {"error_message": "string", "code": "string"}
},
# 6. 代码审查工具
{
"name": "code_review",
"description": "检查代码质量、安全性、最佳实践",
"parameters": {"code": "string"}
}
]
|
6.2 架构模式选择(3分)
推荐:ReAct + 错误重试机制
工作流程:
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
| ┌─────────────────────────────────────┐
│ Phase 1: 需求理解 │
│ - 分析用户需求 │
│ - 搜索相关文档 │
│ - 确定技术方案 │
├─────────────────────────────────────┤
│ Phase 2: 代码生成 │
│ - 生成初始代码 │
│ - 代码审查 │
│ - 优化改进 │
├─────────────────────────────────────┤
│ Phase 3: 测试验证(循环) │
│ ┌─────────────────────────┐ │
│ │ 运行代码 │ │
│ │ ↓ │ │
│ │ 成功?→ 是 → 完成 │ │
│ │ ↓ 否 │ │
│ │ 分析错误 │ │
│ │ ↓ │ │
│ │ 修复代码 │ │
│ │ ↓ │ │
│ │ 回到"运行代码" │ │
│ └─────────────────────────┘ │
│ 最大重试次数: 3次 │
└─────────────────────────────────────┘
|
6.3 错误处理方案(4分)
策略1:分级重试机制
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
| class CodingAgent:
def handle_execution_failure(self, error, code, attempt):
if attempt >= 3:
return {
"status": "failed",
"message": "已尝试3次修复,建议人工介入",
"last_error": error,
"code": code
}
# 分析错误类型
error_type = self.classify_error(error)
if error_type == "syntax_error":
# 语法错误:直接修复
fixed_code = self.fix_syntax(code, error)
return self.execute_code(fixed_code, attempt + 1)
elif error_type == "runtime_error":
# 运行时错误:分析并重新生成
analysis = self.analyze_error(error, code)
new_code = self.regenerate_code(analysis)
return self.execute_code(new_code, attempt + 1)
elif error_type == "logic_error":
# 逻辑错误:需要重新理解需求
clarification = self.ask_user_clarification()
new_code = self.generate_code(clarification)
return self.execute_code(new_code, attempt + 1)
|
策略2:降级方案
1
2
3
4
5
6
7
8
| # 如果完整实现失败,提供简化版本
def fallback_strategy(self, requirement, error):
return {
"full_implementation": None,
"simplified_version": self.generate_simple_version(requirement),
"manual_steps": self.generate_manual_guide(requirement),
"error_report": error
}
|
策略3:人机协作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 关键决策点询问用户
def execute_with_confirmation(self, code):
# 显示代码给用户
print(f"生成的代码:\n{code}\n")
# 询问是否执行
if self.ask_user("是否执行此代码?"):
result = self.run_code(code)
if result.has_error:
fix_suggestion = self.analyze_error(result.error)
if self.ask_user(f"发现错误,建议修复:{fix_suggestion},是否继续?"):
return self.fix_and_retry(code, fix_suggestion)
return result
|
评分要点:
- 工具设计合理性(3分)
- 架构选择及理由(3分)
- 错误处理方案完整性(4分)
总结
本测试题覆盖了Agent系统的核心知识点:
- ✅ 基础概念理解
- ✅ Function Call机制
- ✅ 系统架构设计
- ✅ 记忆管理
- ✅ 实战问题解决
学习建议:
- 理解概念后,动手实现简单Agent
- 逐步增加复杂度,尝试多工具协作
- 关注错误处理和优化
- 学习开源Agent框架(LangChain、AutoGPT等)
继续学习资源:
- [[Agent进阶:多Agent协作]]
- [[LangChain框架实战]]
- [[Agent性能优化技巧]]