蚂蚁 Agent 开发一面:ReAct 与 Plan-Execute、切块策略与上下文压缩
- 轮次
- 一面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 请介绍一个你深度参与的 Agent 项目:它解决什么问题?你负责的部分是什么?遇到的主要技术难点是什么,你是怎样处理的?
- 判断一个 Agent 是否适合进入企业生产环境,你会重点检查哪些能力和指标?
- 当你拿到来源多样、格式不一的外部资料时,会怎样处理它们,让后续检索能稳定找到有效内容?
- ReAct 和 Plan-Execute-Replan 在任务拆解、执行和调整策略上有什么不同?你会怎样判断该用哪一种?
- 哪些知识适合通过 RAG 动态检索,哪些更适合整理为 Skill 供 Agent 使用?你会依据什么做选择?
- 请从用户提交问题开始,说明项目中的检索链路:问题经过哪些处理,最终怎样转化为 Agent 可用的上下文?
- 文档切块时,你会如何确定 Chunk 的长度和边界?哪些因素会影响这个选择?
- 如果某个 Chunk 虽然包含答案相关内容,但也混入了很多无关信息,你会怎样减少噪声对回答的影响?
- 同一问题采用关键词、向量等多种检索方式后,系统怎样合并、排序并选出最终结果?
- 你会通过哪些数据和测试证明检索质量达到要求?如何区分检索问题和生成问题?
- Agent 的记忆可以怎样分层?每一层适合保存什么、服务哪些场景,又有哪些读取或写入限制?
- 项目中的上下文压缩在什么条件下触发?压缩时会怎样整理历史内容,并保证关键事实与约束仍然可用?
- 哪些信息必须在上下文压缩后保留下来?你会怎样把这些保留要求落实为代码或流程约束?
- 你了解 Claude Code 的上下文压缩机制到什么程度?它会怎样处理对话历史,以及压缩后的内容如何继续影响后续工作?
- 如果要重新设计一个你参与过的 Agent 项目,你会先重构哪一部分?为什么它比其他部分更值得优先处理?
- 怎样比较 DeepSeek harness 和 pi 的设计思路?你会从哪些方面分析它们的执行循环、工具调用和扩展方式?
- 在一个实际开发任务中,你会怎样把 AI Coding 与 Agent 能力结合起来?从需求理解、实现到验证,哪些环节适合交给 AI,哪些需要额外把关?
《参考解析》
企业级 Agent 的准入检查看四类指标:效果(任务成功率、需要人工介入的比例)、可靠性(同类输入输出是否稳定、失败是否可复现)、成本与延迟(单任务 token 与时长、P95 延迟)、可运维性(每一步有没有留痕、出错能不能定位到具体工具调用)。最容易被忽略的是第二类:演示能跑通和稳定跑通之间隔着大量边界情况,准入检查要专门准备一批「刁钻输入」来看它是明确失败还是胡编。
异构资料的清洗顺序决定了后面所有环节的天花板。实践顺序是:统一格式(PDF/HTML/Word 抽文本,保留标题层级)→ 去噪(页眉页脚、导航、广告、重复段落)→ 去重(同一份文档的多个版本只留最新的,否则检索结果会被旧版本占满)→ 结构化(表格还原成表格、代码块标记语言)→ 保留出处(每段能回溯到原文位置,后面评估和引用都靠它)。如果不做去重,很多「检索质量差」的问题其实是同一内容的多份副本挤占了召回名额。
ReAct 与 Plan-Execute-Replan 的差别在「计划何时固定」。ReAct 是边想边做,每一步根据上一步的观察决定下一步,灵活但容易在长任务里跑偏、也容易重复劳动;Plan-Execute-Replan 先生成完整计划再执行,执行中发现问题才重规划,好处是全局视角、可并行、可把计划给人看,代价是计划质量依赖首轮理解,环境变化快时会浪费。判断依据是任务的可预测性:步骤固定、依赖清晰的选计划式;需要探索、每步结果都会改变后续策略的选 ReAct。实际系统里常见的是分层——顶层用计划式拆解,每个子任务内部用 ReAct。
RAG 与 Skill 的边界是「知识的体量与更新方式」。RAG 适合体量大、会变、需要精确引用出处的知识(产品文档、工单、代码库);Skill 适合体量小、需要模型「照着做」的操作规程(某类任务的步骤、输出格式、判据)。分界线可以这样问自己:这份内容是需要被检索出来的事实,还是需要被遵循的指令?前者进 RAG,后者进 Skill。
检索链路的完整路径:问题进来 → 改写(把口语化的追问补全成独立问题,多轮场景必需)→ 意图判断(要不要检索、检索哪个库)→ 多路召回(向量 + 关键词 + 结构化过滤)→ 融合排序(RRF 或加权,再上重排模型)→ 上下文装配(按预算裁剪、去重、加出处)。每一步都可能成为瓶颈,所以要有分步指标。
Chunk 长度没有通用最优值,看三件事:内容的自然边界(章节、段落、代码块,切断表格和代码是常见事故)、检索粒度(问题通常指向一个具体事实,chunk 太长会稀释相关性)、上下文预算(要放几个 chunk 进 prompt)。工程上的做法是分层:小的子块用于检索,命中后把它所在的父块送进上下文,兼顾召回精度和上下文完整性。重叠窗口用来避免边界处的答案被切断,但重叠太多会造成重复召回。
噪声抑制有几种手段可以组合:句子级过滤(把 chunk 里与问题无关的句子剔除,只留有支撑关系的)、重排(用交叉编码器对候选重打分,比向量相似度准得多)、引用约束(要求回答必须标注出自哪个 chunk 的哪一句,模型不容易编)、以及多 chunk 交叉验证(同一事实在多个来源出现才采信)。
多路检索融合的标准做法是 RRF(Reciprocal Rank Fusion):不看各路分数的绝对值(不同检索器的分数量纲不可比),只看排名,score = Σ 1/(k + rank),k 一般取 60。融合后再上重排模型取 top-k。这样做的稳健性来自「不同检索器都排在前面的结果大概率相关」。
区分检索问题和生成问题,靠分层评估。检索侧看 recall@k 和 MRR(标准答案所在的 chunk 有没有被召回、排在第几);生成侧在给定正确 chunk 的前提下看答案正确率(把正确的 chunk 直接喂给模型,如果这时还答错,就是生成的问题)。这两套指标要分开跑,否则一个「答错了」的 case 永远不知道该修检索还是修 prompt。
记忆分层的常见切法:工作记忆(当前任务的中间状态,随任务结束丢弃)、会话记忆(本次对话的历史,按轮次或摘要压缩)、长期记忆(跨会话的用户偏好与事实,需要显式写入和召回)、领域知识(不属于记忆,走 RAG)。每层的读写限制不同:长期记忆写入要慎重(避免污染),读取要按相关性召回而不是全量塞进去。
上下文压缩的触发条件通常是三条之一:token 数超阈值、轮次超阈值、或者任务阶段切换(比如从探索进入执行)。压缩的做法是保留最近若干轮原文 + 更早的内容做摘要,摘要里必须保留的是:用户明确给出的约束与偏好、已确认的事实与数字、已经做过的决定与理由、未完成的待办。把这些要求落实成代码的办法是结构化——压缩时不是让模型自由写摘要,而是按固定字段填(目标、约束、已完成、待办、关键事实),字段缺失就重试。
关于 Claude Code 的压缩机制:它在上下文接近上限时自动总结历史,把摘要作为新的起点继续;同时保留最近若干轮原始消息和文件读取记录,避免摘要丢掉刚用到的细节。压缩后的影响是双向的——省下了 token,但也可能丢掉早期约定的细节,所以重要的约束要在系统提示或项目配置文件里落地,而不是只依赖对话历史。
重设计的优先级排序:先改「错了会一路错下去」的部分,通常是上下文装配和验证环节,而不是模型或 prompt。理由是前者决定模型看到什么,后者决定错误能不能被拦住,这两处改动收益最确定。
DeepSeek harness 与 pi 的对比维度:执行循环的粒度(一步一调用还是批处理)、工具调用的协议与错误反馈方式、扩展机制(插件、配置文件、还是代码级接入)、以及上下文管理的策略。对比时不要只比功能列表,要看「同样的任务在两边跑,中间态长什么样、失败时能拿到什么信息」。
AI Coding 与 Agent 的分工:需求理解与方案评审留给人(这决定了做对的事),实现和重复性改造适合交给 AI,验证必须由程序兜底(测试、类型、lint)。把关点设在「产出可评审的中间物」——spec、diff、测试结果,而不是在最后一步才看整体效果。