面灵AI→

蚂蚁集团 AI Agent 开发复活赛二面:CR Agent 三级架构深挖

轮次
二面(复活赛)
结果
已过
时间
2026-10
来源
牛客网

《面试题目》

项目背景与记忆设计

  1. 你在 AI Agent 这块具体做了哪些事情?
  2. 介绍一下项目背景:做了什么、碰到什么问题、怎么解决的?
  3. 为什么选择用 Markdown 方案做记忆管理?
  4. 相比 RAG 方案有什么考虑?
  5. Agent 记忆更新过程中,如何保证语义匹配的准确性?
  6. 如果匹配错了会如何处理?

Agent 架构与工具调用

  1. 项目中为什么采用 Agent Teams 架构?
  2. 相比 Workflow 编排方式有什么优势?
  3. 如果线上要求 Agent 全流程自动化、不依赖人工审核,怎么保证稳定可靠?
  4. 一个 Agent 调用多个工具时,执行流程怎么设计?
  5. 如何管理工具调用的顺序?
  6. 大模型调用外部工具的底层机制是什么?
  7. 模型如何决定调用哪个工具?
  8. Agent 系统通常由哪些核心模块组成?
  9. 各模块分别承担什么职责?
  10. 如何理解 Agent 的短期记忆和长期记忆?
  11. 两者通常有哪些实现方式?
  12. MCP 是什么?主要解决 Agent 开发中的什么问题?

风控归因 Agent 的三级架构

  1. 风控归因 Agent 为什么设计成三级 Agent 架构?
  2. 第二层编排为什么还要单独设计成一个 Agent?
  3. 主 Agent、编排 Agent、原子子 Agent 的职责分别是什么?
  4. 各层 Agent 之间如何通信?
  5. 上下文如何传递?怎么保证不遗漏关键信息?
  6. 原来的纯 ReAct 方案只是工具调用不稳定吗?还有哪些问题?
  7. 直接采用 ReAct + Tool 是否也能满足需求?
  8. 引入多层 Agent 和多个子 Agent 后,执行效率会变慢吗?
  9. 三级架构是否提升了结果准确率?具体体现在哪些场景?

多模态与文档解析

  1. 多模态文档解析的流程是怎样的?
  2. 早融合、中融合、晚融合分别适合什么场景?
  3. 纯视觉模型改造成 VL 模型,哪些模块必须重新设计?

手撕代码

  1. 手撕:二叉树的最近公共祖先怎么实现?

《参考解析》

这场面试的风格:顺着一个项目往深里挖。整场没有八股式轮询,而是从「你在 Agent 这块做过什么」开始,围绕同一个项目换四个角度反复追问:先问设计选择(为什么这么做),再问反例与边界(匹配错了怎么办、不依赖人工审核怎么办),最后抽掉项目问通用机制(Agent 有哪些核心模块、模型怎么选工具)。面试官明确说会从很多不同角度深挖、看你有没有思考过,所以准备方式是:简历上的每个技术选择都要能答出「当时的替代方案、为什么没选、代价是什么」,而不是只背实现。

Markdown 记忆与 RAG 的取舍:Markdown / 文件式记忆把事实写成人类可读、可 diff、可版本管理的结构化文本,Agent 直接读全文,天然做到全量覆盖、可审计、可回滚,适合条目量不大但要求精确(规则、偏好、项目结论、配置)的场景,缺点是规模上去后无法全量进上下文、检索只能靠规则。RAG 走向量召回,适合条目多、以语义相似为主的场景,问题是召不回、chunk 切断语义、相似段落互相干扰、且结果难以人工核对。真实系统通常是混合:长期稳定事实落文件,大批量知识走检索;写入时同时落结构化字段与 embedding,检索先精确匹配(实体、ID、时间)再补一路语义召回。

语义匹配准确性与匹配错误的兜底:准确性来自三处——写入时做规范化(实体抽取、别名统一、补时间戳与来源),检索时混合召回(关键词加向量)再 rerank,判决时分档:高置信直接更新、中置信走合并或追问澄清、低置信只新增不覆盖。匹配错误靠两条兜底:写入采用 append-only 加生效时间,任何一次错误合并都能回滚,读取时把「这条记忆来自哪次对话、最近更新于何时」一并交给模型,让它有机会自我怀疑;对有副作用的动作(发消息、下单、改配置)再加幂等键和二次确认,把「记错」的影响限制在建议层而不是执行层。

Agent Teams 与 Workflow:Workflow 是预先写死的确定性流程,链路可枚举时最好用——好调试、成本可控、结果稳定,缺点是分支要人工穷举,遇到未预期情况就断。Agent Teams / 多 Agent 把角色拆开(规划、执行、审阅),由模型在运行时决定下一步和分工,灵活、可扩展、能并行,代价是 token 与延迟上升、结果不确定、必须配更强的可观测性和终止条件。选择判据是流程的开放程度:稳定可枚举走 Workflow,开放或需要动态分解走多 Agent;工程上最常见的是混合——外层用固定流程保证可控,内部节点交给 Agent 自由决策。

全流程自动化的可靠性:不依赖人工审核时,可靠性靠三件事而不是靠「提示词写得更严」。第一是分层校验:每个子 Agent 的输出带 schema,关键字段用确定性规则校验(数值范围、引用是否存在、必填项),不让模型自评替代校验。第二是幂等与可回滚:外部副作用带幂等键、支持 dry-run、灰度放量与一键回滚,先影子跑再放真流量。第三是可观测与熔断:全链路 trace 落盘,按置信度分流,低置信降级为拒绝执行或转人工,并设置最大步数、token 预算、超时与死循环检测。上线前用离线评测集加影子流量做回归,缺一个都会在长尾上翻车。

多工具调用的执行流程与顺序:模型在一轮里可以并行发起多个无依赖的工具调用,有依赖的必须等上一轮结果回来后,由模型基于结果构造下一轮参数,所以「流程」本质是模型决策加调度层约束的配合。调度层要负责的事:解析依赖关系决定并行还是串行、按 schema 校验参数、超时与重试(只有幂等工具能重试)、把冗长的工具输出摘要化再回灌上下文、同参调用去重、限并发与熔断。调用顺序不能全靠模型自由发挥——业务上强顺序的步骤写成编排器或状态机,或者把前置条件写进工具描述里(「必须先调用 X 拿到 id 才能调用本工具」),这比事后纠错便宜得多。

Function calling 的底层机制:请求里带上工具列表,每个工具含名称、自然语言描述和参数的 JSON Schema;模型侧经过专门训练,能在需要时输出一个结构化的 tool_call(工具名加参数),客户端解析后执行真实函数,把返回值作为工具角色的消息拼回上下文,再请求模型继续。所以「模型如何决定调哪个工具」本质是一次基于当前上下文的下一 token 决策——工具名与描述就是提示词,写清「什么时候用、什么时候不要用、返回什么、参数含义」直接决定选择准确率;工具数量多时先做工具检索或按场景分组路由,避免几十个工具同场竞争注意力。

Agent 的核心模块与职责:推理层(模型调用、提示组装、流式与重试)、规划层(任务分解、状态机、进度管理)、记忆层(短期上下文管理与长期外部存储)、工具与环境接口(含 MCP、鉴权与权限边界)、执行控制(循环、终止条件、步数预算、幂等与重试)、可观测与评测(trace、token 与耗时、成功率、评测集回归)。划分职责的原则是「确定性的事交给程序,判断的事交给模型」:路由、校验、状态、重试、限额用代码写死,意图理解、选路、生成、归因交给模型,中间用结构化 schema 衔接。

短期记忆与长期记忆:短期记忆就是上下文窗口里的对话与中间状态,容量受上下文长度限制,管理手段是滑动窗口、摘要压缩、以及把任务清单和中间结果外置成结构化状态(TODO 文件、变量)而不是留在聊天记录里;长期记忆是外部存储(向量库、KV、文件、图数据库),按需检索召回,实现方式包括 embedding 语义检索、关键词或 BM25、结构化字段查询、知识图谱关系查询。真正的难点不在存和取,而在写入策略、冲突覆盖、过期与来源标注——写进去的噪声会一直污染后续所有召回。

MCP 解决什么:MCP(Model Context Protocol)把「有哪些工具和资源、参数长什么样、怎么调用」标准化:服务端按协议暴露 tools / resources / prompts,客户端(Agent 宿主)统一发现与调用。它解决的是每个 Agent 框架各写一套工具适配的重复建设和生态割裂,让一次实现能在多个宿主里复用,同时把鉴权与权限边界收到协议层。要补一句局限:协议不保证工具描述的质量,也不解决远程服务不可信带来的提示注入和越权风险,副作用工具仍要自己加校验、幂等和确认。

三级 Agent 架构为什么这么分:主 Agent 面对用户,负责理解目标、判断该走哪条流程并把最终结论讲清楚;编排 Agent 单独抽出来,是因为它的职责是「分解、调度、收敛、校验」,跟主 Agent 的对话与决策耦合在一起会互相拖累——独立之后编排策略可以单独评测和替换(换模型、换分解模板、单独回归),上下文也更干净。原子子 Agent 每个只做一件确定性的事(查规则、捞数据、跑模型、生成归因结论),输入输出 schema 固定,因此可并行、可复用、失败可局部重试。这样分层的本质是把「长链路的不确定性」收敛到编排层,让每一层都能被单独验证。

层间通信与上下文传递:层间通信建议用结构化消息——JSON schema,包含 task_id、目标、约束、输入引用、期望产物和状态码,而不是自然语言对话(自然语言会丢字段且不可校验)。上下文传递用「引用加摘要」而不是整段透传:上游只把必要事实和产物句柄(文件 id、表 id、片段编号)传下去,下游按需读取全文,这样既控制 token 也避免无关信息干扰。防止遗漏靠机制而不是靠模型自觉:编排层维护任务清单与必填字段清单,每个子 Agent 产出后做 schema 校验与完整性检查,缺字段就打回补齐或标注不确定;同时在最终汇总时列出用到的证据来源,让结论可追溯。

纯 ReAct 的问题与多层架构的收益:ReAct 的「想一步做一步」在短任务上够用,长任务上会暴露几个结构性缺陷:上下文随步数滚动增长、早期关键约束被淹没;一次工具报错会污染后续推理并可能滚雪球;没有全局规划,容易在局部反复试错、步数爆炸;没有中间校验与回滚,副作用不可逆;每次轨迹不同,难以评测和定位。所以引入规划与专用子 Agent,把长链路拆成可验证的短链路。代价是肯定更慢、token 更多(每多一层就多一次模型往返),收益体现在复杂任务上的准确率与可维护性:上下文更短更聚焦、可并行、失败可局部重试、结果可校验;优化方向是并行执行、只传必要上下文、原子任务用小模型、把规则前置到代码里。

多模态文档解析与融合时机:解析流程一般是版面分析(切出文本块、表格、图片、公式区域)→ 按区域裁剪 → 分流识别(OCR、表格结构识别、图表理解)→ 按阅读顺序还原(多栏、跨页、表格跨页要合并)→ 结构化输出成 Markdown / HTML / JSON。融合时机:早融合在编码器早期就把各模态拼进同一个 Transformer,适合模态强关联、需要细粒度对齐的任务,但训练成本高、模态间容易互相干扰;中融合各自编码后用 cross-attention 或适配器交互(CLIP 加 projector 再接 LLM、Flamingo 一类),效果与成本平衡,是当前 VLM 的主流;晚融合各模态独立出结果再合并,实现简单、可以分别升级、延迟可控,适合模态弱耦合或对延迟敏感的场景。选型判据是「模态之间需不需要在特征层面对齐」,而不是哪个更新。

纯视觉模型改造成 VL 需要重设计什么:至少五块要动。一是语言侧从零开始——文本 tokenizer、词表与 embedding 原来根本不存在;二是连接器 / projector,把视觉特征投影到语言模型维度,还要适配 patch 数量变化;三是位置编码,图片是二维、视频是三维,高分辨率和长文档还要求外推能力;四是注意力结构与训练目标,纯视觉只有自监督,改 VL 后要走图文对齐加指令微调两阶段;五是分辨率与 token 压缩策略、以及图文对与 OCR 数据构成的数据 pipeline。可以复用的是视觉编码器的底层特征提取能力,但「接上语言」这一段的训练策略和数据处理基本要重做。

手撕:二叉树的最近公共祖先:递归是最标准的写法——后序遍历,函数返回「子树里是否找到 p 或 q」,若左右子树都返回非空,当前节点就是 LCA,否则把非空的那一侧往上传递,时间 O(n)、空间 O(h)(递归栈)。如果节点带 parent 指针,等价于求两条链表交点:分别从 p、q 走到根得到两条路径,再从后往前找最后一个公共节点。需要多次查询同一棵树时用倍增(二进制 lifting)预处理每个节点向上 2^k 级的祖先,单次查询 O(log n);或者用 Tarjan 离线算法配合并查集把所有查询一次跑完。如果树是 BST,可以按值域判断 p、q 是否分别落在当前节点的两侧,一路下行即可,时间降到 O(h)。