教程_Agent与MCP 小测验答案
1. AI Agent 的五大核心模块分别是什么?它们各自的职责是什么?
- Planning(计划模块):理解目标任务,将复杂任务拆解为可执行的步骤,生成行动计划。例如判断用户的问题需要使用本地文档搜索还是网络搜索。
- Memory(记忆模块):存储与任务相关的历史记录和上下文信息,支持长期记忆与短期记忆。在代码中体现为
memory_global列表。 - Tools(工具模块):调用外部工具(如 RAG 检索、Web 搜索、API 接口),实现感知-行动闭环。
- Executor(执行模块):根据计划依次执行每一步操作,将结果存入 memory。对应代码中的
process_actions()函数。 - Output(输出模块):综合 memory 中的所有信息,调用 LLM 生成最终回答。对应
final_answer()函数。
2. 在 RAG 系统中,BGE-M3 模型能够同时生成哪两种向量表示?它们各自擅长什么?
- 稠密向量(Dense Vector):固定维度的浮点数向量,捕捉文本的语义信息,擅长语义相似度搜索。即使查询和文档使用不同的词汇,只要语义相关就能匹配。
- 稀疏向量(Sparse Vector):高维但大部分值为零的向量,类似 TF-IDF 或 BM25,擅长关键词精确匹配。当查询包含特定术语(如"以人为本的座舱")时,能精确找到包含这些关键词的文档。
3. 在 Milvus 混合检索中,WeightedRanker(0.7, 1.0) 的两个参数分别控制什么?如果想让关键词匹配的权重更高,应该如何调整?
- 第一个参数
0.7是**稀疏向量(关键词匹配)**的权重。 - 第二个参数
1.0是**稠密向量(语义匹配)**的权重。 - 如果想让关键词匹配的权重更高,应该增大第一个参数,例如
WeightedRanker(1.5, 1.0)或WeightedRanker(1.0, 0.5)。
4. 文本切块函数 chunk_text 中为什么要对表格做特殊处理?如果不做处理会怎样?
表格是一个语义完整的信息单元,行与行之间紧密关联。如果不做特殊处理,表格可能会被从中间切断,导致:
- 上半部分只有表头没有数据
- 下半部分只有数据没有表头
- 两个 chunk 各自都无法表达完整的信息
特殊处理通过检测 | 字符识别表格,将整个表格作为一个完整的 chunk 保存。
5. Web 搜索模块中,WebScraper 类的 extract_main_content 方法为什么只提取 h1-h6 和 p 标签,而不是所有 HTML 标签?
网页中包含大量非正文内容:导航栏、侧边栏、页脚、广告、脚本、样式等。这些内容通常使用 div、nav、footer、aside 等标签。h1-h6(标题)和 p(段落)标签通常包含网页的核心正文内容。此外,代码还通过 len(tag_text.split()) > 10 进一步过滤掉过短的文本片段(如按钮文字、菜单项),从而有效去除噪声。
6. Agent 的 Planning 模块在收到"比较一下和特斯拉的优劣势"这种查询时,为什么需要同时规划"本地文档搜索"和"网络搜索"两种工具?
因为这个查询涉及两个不同的信息源:
- 星辰电动 ES9 的信息:存在于本地产品文档中,应通过本地文档搜索(RAG)获取
- 特斯拉的信息:不在本地文档中,需要通过网络搜索获取
只使用一种工具无法同时获取双方的信息,因此 Planning 模块必须规划两种工具的组合使用。
7. 什么是 ReAct 框架?它如何解决 LLM 的幻觉问题?
ReAct(Reasoning + Acting)是一种将推理和行动交织在一起的框架。模型在每一步都先推理"应该做什么",然后执行行动(如调用搜索 API),再根据行动结果继续推理。
它解决幻觉问题的方式是:当模型不确定某个事实时,不是凭空编造(幻觉),而是通过调用外部工具(如搜索引擎、数据库)获取真实信息。外部信息为模型的推理提供了事实基础,从而减少了幻觉和错误传播。
8. Reflexion 机制中的三个角色(行动者、评估者、自我反思)分别对应 Agent 代码中的哪些函数?
- 行动者(Actor):对应
agent_plan()+process_actions(),负责规划和执行任务 - 评估者(Evaluator):嵌入在
reflection()函数中,评估已有信息(memory_global)是否足够回答用户问题 - 自我反思(Self-Reflection):也在
reflection()函数中,分析信息不足之处,生成补充查询(最多 3 个额外查询)
9. MCP 协议解决了什么问题?如果没有 MCP,M 个应用要对接 N 个工具需要多少适配器?有了 MCP 后呢?
MCP 解决的是 AI 应用与外部工具之间的标准化对接问题。
- 没有 MCP:M 个应用 x N 个工具 = M x N 个适配器
- 有了 MCP:每个应用实现 1 个 MCP Client + 每个工具实现 1 个 MCP Server = M + N 个适配器
这类似于 USB 协议对外设连接的标准化。
10. 在编写 MCP Server 时,@mcp.tool() 装饰器的函数 docstring 为什么重要?如果没有 docstring 会怎样?
Docstring 会被 MCP 框架自动提取并发送给 LLM,作为工具的功能描述。LLM 根据 docstring 来判断何时应该调用这个工具、如何传递参数。如果没有 docstring:
- LLM 无法理解工具的用途,可能永远不会调用它
- 即使调用,也可能传递错误的参数
- 整个自动工具发现机制将失效
11. MCP Client 的 initialize_mcp 方法中,session.list_tools() 返回的信息包含哪些字段?这些信息如何被转换为 OpenAI Function Calling 格式?
session.list_tools() 返回的每个工具包含:
name:工具名称description:工具描述(来自 docstring)inputSchema:参数的 JSON Schema(从函数的类型注解自动生成)
转换为 OpenAI 格式:
| |
12. 在 MCP Client 的 chat_with_tools 方法中,第二次调用 LLM 时为什么不传 tools 参数?
如果第二次调用仍传入 tools 参数,LLM 可能会再次决定调用工具,形成无限循环的工具调用链。不传 tools 参数可以确保 LLM 只基于已获取的工具结果生成文本回答,不会再次触发工具调用。同时还添加了一条系统消息:“请基于上述工具搜索结果,用中文为用户提供完整、准确的回答。不要再调用工具,直接回答即可。”
13. SalesPilot 项目中的 deduplicate_memory_global 函数的作用是什么?为什么需要对 memory 去重?
该函数对 memory 中所有检索结果按照 content_with_weight 字段进行全局去重。需要去重的原因:
- Planning 模块会生成多个相关查询(如"ES9的优势"和"ES9的技术规格"),这些查询可能从同一个文档中检索到相同的片段
- Reflexion 补充查询也可能重复检索到已有内容
- 重复的内容会浪费 LLM 的上下文窗口(token),且可能导致 LLM 过度强调某些信息
14. 在 MCP Client 的 build_system_prompt 方法中,为什么要区分"必须使用工具"和"不要使用工具"两种情况?如果不做区分会有什么问题?
如果不做区分,LLM 可能会对每个问题都调用工具,包括"Python是什么"这类常识性问题。这会导致:
- 不必要的 API 调用,增加延迟和成本
- 搜索结果可能比 LLM 自身知识更差(搜索结果可能包含低质量内容)
- 用户体验下降(简单问题也需要等待搜索)
通过明确区分,LLM 只在确实需要实时/最新信息时才调用工具。
15. SalesPilot 项目使用 SSE(Server-Sent Events)进行流式输出有什么优势?"role": "agent" 类型的消息有什么作用?
SSE 流式输出的优势:
- 用户不需要等待整个回答生成完毕,可以实时看到回答逐步呈现
- DeepSeek-R1 等推理模型的思考过程也可以实时展示
- 提高用户体验,减少感知等待时间
"role": "agent" 消息的作用:
- 在 Agent 执行搜索操作时,向前端推送当前正在执行的动作(如"正在执行本地文档搜索: ‘星辰ES9的技术规格’")
- 让用户了解 Agent 的工作进度和决策过程
- 增加系统的透明性和可信度