Agent 面试篇

1️⃣ 什么是 Agent?与传统大模型的区别?

传统大模型

  本质上是个 「问答机器」,你给它一个输入,它给你一个输出,然后就结束了。就算是多轮对话,它也只是在当前上下文里被动响应你,它不会主动去做任何事,也不知道自己上一步做了什么、下一步该做什么。

缺点:

  • 知识冻结: 模型的训练数据有截止日期,它没有任何途径去获取实时信息;
  • 不能行动: 传统大模型本质上是文本输出其,所有输出都是一段文字,无法帮用户去调用工具;
  • 对话失忆: 传统大模型没有持续性状态,每次调用之间它是完全失忆的

Agent

  本质上是个 「运作闭环」:感知 -> 规划 -> 行动 -> 再感知。

  • 感知: 获取当前环境、用户输入、工具返回结果、系统状态等信息。
  • 规划: 基于目标和当前状态,判断下一步该做什么。
  • 行动: 执行操作,比如调用工具、写代码、发请求、修改文件、回复用户。
  • 再感知: 观察行动后的结果,再决定是否继续、修正或结束。

关键特性:

  • 工具调用
  • 记忆机制
  • 自我纠错

2️⃣ Agent 基本架构

  Agent 的基本架构有四个核心组件:LLM工具记忆规划模块

  • LLM 不管是 用户指令工具返回结果 还是 记忆保存的内容,最终都要经过 LLM 来理解和决策。
  • 工具系统:
    • LLM 本身是个纯粹的「语言处理器」,它不能上网、不能读文件、不能执行代码,但这些限制都可以通过工具来突破;
    • LLM 会读取 用户问题工具描述LLM 决定要调哪个工具、参数填什么,把决策以 JSON 格式返回,本地代码去真正执行调用工具,结果再反馈给模型。
  • 记忆系统:
    • 短期记忆: 当前这轮对话的上下文,保存在 context window
    • 长期记忆: 通常用 向量数据库 来保存,把重要信息 embedding 之后存起来,下次用的时候做 语义检索 拿回来;
  • 规划模块: 依赖的是 LLM 的推理能力
    • 思维链 CoT 让模型「把思考过程写出来」,而不是直接输出最终答案;
    • 思维树 TOT 在每个推理节点上展开多个可能的分支,然后评估每个分支的质量,选出最优的路径继续往下走

3️⃣ Tools、Agent 和 WorkFlow 的区别?

  • Tools:本质上是一个 「按特定格式暴露给 LLM 的函数」,必须给 LLM 一份看得懂的 schema (名字、描述、参数类型)
  • Agent:本质上是一个 决策系统,内部用 LLM 做大脑, Agent 自己判断什么时候调哪个 Tool、要不要继续、什么时候结束;
  • WorkFlow
    • 程序员把整个执行流程的「骨架」写在代码里
    • LLMAgentTools 都只是这个流程里的 「节点」,每个节点负责完成自己那一步;
    • 整体走哪条路、下一步去哪里,全由开发者的代码决定,不是任何节点自己说了算;

4️⃣ WorkFlow 编排模式

  Anthropic 在他们的 Agent 工程实践中总结了几种常见的 Workflow 编排模式

  • 提示链(Prompt Chaining): 把一个大任务拆成多个小步骤,前一步的输出作为后一步的输入,像流水线一样串起来;
  • 路由(Routing): 先用 LLM 做分类判断,然后根据分类结果把请求分发到不同的处理分支;
  • 并行化(Parallelization): 将任务拆分进行并行处理,最后汇总结果;
  • 编排者-工人(Orchestrator-Workers 中央编排者负责分配任务,多个 Worker 各自完成子任务;
  • 评估者-优化者(Evaluator-Optimizer): 一个 LLM 负责生成输出,另一个 LLM 负责评估这个输出的质量,如果评估不通过就把反馈给回生成者,让它改进后重新输出,如此循环直到评估通过或者达到最大重试次数

5️⃣ Agent 的设计范式

  目前主流的 Agent 设计范式有:ReActPlan-and-ExecuteReflection

  • ReAct 主要有由三个步骤形成一个完整的循环(Thought -> Action -> Observation
    • 循环过程:
      • Thought 阶段:LLM 先把当前的情况分析一遍,把推理过程写出来;
      • Action 阶段:LLM 根据思考的结论决定调用哪个工具、传什么参数;
      • Observation 阶段:工具返回的结果被反馈给 LLM,它读取这个结果,然后进入下一轮 Thought,重新分析当前局面、决定接下来怎么做。
    • 缺点: 每一步都是 局部最优 决策,处理特别复杂的、需要全局规划的任务时,容易在中间迷失方向。
  • Plan-and-Execute 分开 规划阶段执行阶段,先让一个 LLM 专门做规划,输出一个完整的步骤列表,然后由另一个 LLM 逐步执行
    • 关键机制:动态重规划
    • 执行器每执行完一步都会把结果反馈给规划器,规划器会判断:当前的执行结果和预期一致吗?后续的计划还适用吗?需不需要调整?如果发现某一步的结果和预期严重偏离,规划器会修改后续的步骤,甚至插入新的步骤来应对。
  • Reflection 在前两种范式的基础上加了一层「质量保障」
    • 做法:
      • Agent 完成一步或者完成整个任务之后,再让一个 LLM 来判断做得好不好、结果是否符合预期;
      • 如果评估不通过,就重试或者换一种策略。

范式选择 其实核心看两个维度:任务复杂度质量要求

  • 如果任务步骤不多、每步都比较独立,ReAct 就够了,简单直接;
  • 如果任务很复杂、步骤之间有依赖关系需要全局统筹,Plan-and-Execute 更合适;
  • 如果对输出质量要求特别高、允许多花一些时间和成本,就在前面的基础上叠加 Reflection

6️⃣ 复杂任务拆分

任务拆分: LLM 一次性处理太复杂的任务很容易出错,把大任务拆成小步骤,每步聚焦一件事,准确率会明显提升

分类:

  • 静态拆分: 提前把任务流程设计好,固定成一个确定的 Workflow,每一步是什么、按什么顺序执行,全部事先写死。

    • 优点:行为可预测,出了问题知道是哪一步的问题,好排查;
    • 缺点:灵活性低,遇到你没设计进流程的情况就容易卡住。
  • 动态拆分: 把「任务拆解」交给 LLM 来做。给它一个目标,让它先输出一个执行计划,再按计划一步步执行。

    • 重点:
      • 分析步骤之间的依赖关系,识别出可以 并行 的步骤,是降低总耗时的关键

      • 要让并行真正落地,前提是先把依赖关系画成一张 有向无环图(DAG)

        • 节点:步骤
        • 边:「依赖」。
        • 没有依赖的节点就能同时跑,依赖它们的节点要等父节点完成。

  • 拆分粒度:

    • 拆分太细:
      • 步骤越多,LLM 调用次数越多,总 token 消耗上升;
      • 步骤太碎,每步只做一件极小的事,LLM 看不到全局,产出的各部分也容易衔接生硬;
    • 拆分太粗:
      • 每步负责的事太多,出错概率上升,出了问题也无法定位是哪一步的责任

7️⃣ Agent 的记忆机制

  Agent 需要 记忆模块 才能在多步任务中保持状态、跨任务积累知识;

  • 分类:

    • 感知记忆: 表示「当前调用的原始输入」,包括 用户发来的这条消息上传的截图传入的文档
    • 短期记忆: 表示「当前任务执行过程中的完整状态」,包括 用户说了什么、模型输出了什么、工具调用返回了什么
    • 长期记忆: 表示「多轮任务保留的信息」,通常存放在 外部数据库,等在下次需要时去检索拿回来用;
    • 实体记忆: 提取「对话中出现的关键实体和事实」,存成结构化字段,包括 「用户偏好 Python」「客户预算是 5 万」「项目截止日是 3 月底」
  • 记忆压缩:

    • 定义: context window 是有 token 上限的。一个复杂的多步任务,对话历史越来越长,工具返回的结果越来越多,很快就会把 context window 塞满。
    • 种类:
      • 滑动窗口: 只保留最近 N 轮对话,更早的历史直接丢弃。
      • 摘要压缩: token 接近上限时,用 LLM 把早期的对话历史压缩成一段摘要,替换掉原始的冗长历史。
      • 外部存储: 执行过程中产生的中间结果,如果当前步骤不需要但后面可能用到,就先存到向量数据库里,从 context window 中移除,等后面某步需要时再检索回来。

LLM 面试篇

1️⃣ 什么是 Function Calling?

  • 定义:

    • 开发者用 schema工具描述 传给模型;
    • 模型判断是否需要 调用工具,返回结构化的 JSON 来表达 tool_calls,告诉开发者「需要调哪个函数、参数是什么」;
    • 本地代码拿到这段 JSON 去真正执行调用具体的工具,把 工具调用结果 塞回对话,模型再生成最终答案;
  • schema 案例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    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"]
    }
    }
    }
    ]

2️⃣ LLM 是如何学会调用外部工具的?

  • 模型主要靠以下这两个阶段被训练出调用工具的能力

    • 监督微调: Supervised Fine-Tuning
    • 基于人类反馈的强化学习: Reinforcement Learning from Human Feedback
  • 监督微调

    • 背景:
      • LLM 在预训练阶段,主要学习的是给定前面的文字预测下一个 token,整个训练过程完全是在 文本空间 里进行的,模型从未见过「工具调用」这件事。
    • 定义:
      • LLM 喂大量「工具调用示范对话」,让它通过模仿学会「看到工具描述 -> 判断要不要调 -> 输出结构化 JSON 请求」这整套流程。
    • 缺点:
      • SFT 让模型学会了「调工具」这个动作,但模型不知道什么时候该调、什么时候不该调。
  • 基于人类反馈的强化学习:

    • 特点:
      • 生成多样回答: 针对同一个问题让 LLM 生成几种不同的处理方式,有的调了工具,有的直接回答,覆盖各种情况;
      • 人类打分: 标注员评判哪种回答更合理;
      • 训练奖励模型: 利用打分数据,单独训练一个小模型,专门负责打分,它不回答问题,只判断「这个回答人类会喜欢吗」
      • 强化学习优化主模型: 拿奖励模型的打分不断调整主模型的参数,让主模型越来越倾向于产出「高分回答」,也就是边界感更准确的工具调用行为

3️⃣ 什么是 MCP

  • 定义: MCPAnthropic 在 2024 年底推出的开放协议,主要解决的是 「模型接工具太碎片化」 的问题。
  • 思路: 工具提供方按协议实现一个 MCP Server,任何支持 MCP 的 AI 客户端就能直接接进来,一次实现到处复用;
  • 三种主要能力:
    • Tools: 「有副作用的操作」,执行之后会改变外部世界的状态,正因为如此,Tools 通常需要用户授权确认才能执行,不能让模型想调就调;
    • Resources: 「数据提供给模型看」,比如:读取日志文件、查询数据库记录、获取文档内容;
    • Prompts: 「预定义的提示词模板」,带参数占位符,解决的是「每次都要手写重复 prompt」的问题
  • 底层通讯: JSON-RPC
    • stdio(标准输入输出): Server 作为本地子进程运行,Client 通过管道和它通信,Serverstdin 读消息,把结果写到 stdout
    • Streamable HTTP Server 作为 HTTP 服务部署在远程,Client 通过 HTTP 连接和它通信。

4️⃣ 什么是 SKILL

  • 定义:

    • Agent Skill 是把「指令、脚本、模板」一体化打包成可复用能力包的机制。
    • 关键在于三件事:**Agent 能自动发现它按需加载它在需要时调用里面的脚本和资源**。
    • 每个 Skill 是一个文件夹,里面有一份 SKILL.md 指令文件,还可以带上脚本、模板、参考文档这些资源。
  • 案例:

    1
    2
    3
    4
    5
    6
    7
    8
    code-review/                  # Skill 文件夹,名字就是这个 Skill 的标识
    ├── SKILL.md # 核心指令文件(必须有)
    ├── scripts/ # 可选:可执行的脚本
    │ └── check_security.py # 比如一个安全检查脚本
    ├── references/ # 可选:参考文档
    │ └── review_standards.md # 比如团队的审查标准文档
    └── assets/ # 可选:模板、资源文件
    └── report_template.md # 比如审查报告的输出模板

  • 设计思想: 渐进式加载

    • 第一层: Agent 启动的时候,只加载每个 Skill 中的 Skill.md 中的 namedescription 这两个字段;
    • 第二层: Agent 判断「当前任务和某一个 Skill 相关」,这时候才会把这个 SkillSKILL.md 正文完整加载进来;
    • 第三层: Agent 在执行过程中,如果指令里提到了「使用 assets/report_template.md 的模板」,Agent 才会在那个时刻去读取这个模板文件。

参考资料