海康威视 AI Agent 一面:工具编排与上下文压缩
- 轮次
- 一面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 自我介绍,然后讲讲你那个私人助理项目。
- Agent 如何完成一个完整任务?完整流程是什么?从用户输入到输出。
- 接收用户输入后,上下文怎么构造?包含哪些信息?怎么组织?
- 意图判断怎么做?什么时候需要调用工具?谁来决策?
- 工具调用参数怎么生成?结构化输出怎么保证?格式错了怎么办?
- 工具执行失败怎么处理?重试策略是什么?重试几次?
- 工具返回结果怎么注入上下文?放在哪个位置?为什么放那里?
- 怎么判断任务完成?终止条件是什么?谁来定义?
- 未完成怎么继续规划?谁来做决策?模型还是代码?
- 最终结果怎么做格式化和安全检查?有没有敏感词过滤?
- 如果用户说「我赶时间」,Agent 怎么快速响应?怎么降级?
- 如果用户说「帮我叫一辆车去机场」,需要调用哪些工具?怎么编排?
- 这些工具怎么编排?先后顺序怎么定?依赖关系怎么处理?
- 高峰期车辆紧张,Agent 怎么和用户沟通?话术怎么设计?
- 兜底方案怎么设计?有没有人工介入?什么时候转人工?
- 你怎么评估出行 Agent 的服务质量?除了准确率还有哪些指标?
- 如果让你设计行程规划 Agent,结合天气、路况、预算,你会怎么做?
- 多轮对话中用户改了需求,怎么处理?之前的计划怎么回滚?
- 上下文无限增长怎么控制?压缩策略是什么?压缩多少?
- 记忆压缩会丢信息,怎么评估损失?有没有量化方法?
- 多 Agent 协作时状态怎么同步?有没有共享状态机?
- 如果某个子 Agent 返回了错误结果,主 Agent 怎么发现?怎么纠正?
- 你怎么做链路追踪和可观测性?Trace 里记录哪些字段?
- 线上出问题怎么排查?先看什么?怎么定位到具体环节?
- 如果 Agent 调用外部服务超时,重试策略是什么?会不会重复操作?
- 重试会不会导致重复操作?幂等怎么做?key 怎么设计?
- 你怎么控制 Token 成本?有哪些具体手段?省了多少?
- 如果让你设计一个多轮对话状态管理,你会怎么做?状态存哪里?
- 你那个私人助理项目里,长期记忆怎么做的?存了什么?
- 用户偏好怎么抽取?怎么判断哪些值得长期存?谁来决定?
- 反问:团队现在做的是出行场景的哪一块?
- 手撕:给定一个数组,求最长子数组和为 k 的长度。
《参考解析》
上下文要按「用途分区、按重要性排序、可裁剪」来组织。 一段完整的上下文通常有五块:稳定的 system 段(角色、约束、工具清单摘要)、会话段(最近若干轮原文)、记忆段(长期偏好与已知事实,带来源与时间)、任务段(当前计划、待办、已完成的观察)以及检索段(外部知识,带出处)。这样分区的好处是压缩时能按优先级动手——system 与当前任务段不能动,会话段按新旧裁剪,检索段按相关性丢弃。工具返回结果的注入位置也有讲究:结构化数据(价格、时长、订单号)要提炼成短字段放在靠近模型决策点的位置,超长原始响应截断或落盘只留摘要与引用,否则关键结论会被淹没在噪声里。经验法则是「结论前置、证据可追溯」——模型更容易被它最近读到的内容影响,把要用的数字放到最后一段通常比埋在中间有效。
意图判断用分层路由,工具决策要区分「谁决策」与「谁兜底」。 推荐结构是:规则或小模型做最外层分类(闲聊、知识问答、需要工具的任务),再让主模型在缩小后的候选工具集里选择并按 schema 填参数。直接让大模型面对上百个工具做选择会显著抬高选错率。参数生成靠结构化输出保证——优先用厂商原生的 function calling 或受限解码,再叠一层 JSON Schema 校验;格式错时把校验错误的原文回灌一次让它改,第二次还错就用默认值、跳过该工具或转人工。这里要明确回答「最终谁兜底」:模型只负责生成候选动作,正确性的最终责任必须在代码这一侧,因为模型的输出是概率性的,把兜底交给它等于没有兜底。
失败要分类处理,重试的前提是幂等。 失败分三类:参数错(不该重试,回灌错误让模型改)、瞬时错(超时、限流、网络抖动,指数退避加随机抖动重试,通常两到三次封顶)、业务错(无车可派、余额不足,直接翻译成用户能懂的话术,重试一万次也没用)。超时时间按该工具的历史 P99 延迟设并留余量,不要用一个全局值;超时之后的正确动作是先查询状态再决定是否重发,而不是立刻重发。写操作必须带幂等键:由代码用稳定的业务字段生成(用户、操作类型、关键参数指纹),服务端用唯一约束或状态机去重,重试前先查上次结果。幂等键的生成规则和存储位置要能说清,否则「我们做了幂等」就是一句空话。
压缩与记忆的关键是「关键事实不能只存在摘要里」。 压缩策略通常是组合:保留 system 与最近几轮原文,更早的对话压成摘要,同时把订单号、地址、时间、金额、用户明确约束这些槽位抽成结构化字段独立保存,必要时用检索召回相关历史片段。评估损失要用回放集:拿一批长会话,比较压缩前后在任务成功率、关键槽位召回率、约束违反率三个指标上的差异;上线后靠 A/B 或灰度观察。多轮中用户改需求时,「回滚」这个词要拆开答:未执行的步骤直接改计划;已执行但可撤销的走补偿操作(比如取消已下的单);已执行且不可撤销的要显式告知用户当前状态并重新规划后续,同时所有写操作靠幂等键对账,避免补偿动作重复执行。长期记忆的写入由三类触发:用户显式要求、跨会话重复出现的偏好、任务结束的结构化总结;冲突时当前指令优先,长期偏好只当默认值。
出行场景的题考的是编排与「不要瞎承诺」。 「帮我叫一辆车去机场」的解法是先做槽位确认(起点、终点、时间、人数、车型偏好),缺什么问什么;然后按依赖图编排工具:先查路况估时与预估价,再查可用车型,最后才下单——下单这类有副作用的动作要用户确认,且只能在拿到确定结果后才算完成。高峰期无车时的话术设计原则是「给确定信息 + 给可选方案」,比如告知预计等待时间并给出加价、换车型、改时间三个选项,而不是让模型自由发挥说「马上就来」。降级路径要分层:换车型 → 改时间 → 换出行方式 → 转人工,并明确定义转人工的触发条件(用户明确要求、连续失败、涉及金额或纠纷、安全相关)。行程规划 Agent 的难点是多目标约束(时间、天气、路况、预算、偏好),实现上是先过滤硬约束,再对软约束打分排序,最后给出两三个方案让用户选择——把取舍摊开比给一个「最优解」更可信。
多 Agent 的状态同步与错误发现,靠状态机加证据校验。 共享内存只适合同进程的短任务,跨进程跨机的可靠做法是「状态落库 + 事件消息」:任务与步骤状态写在数据库里,Agent 之间只传事件,任何时刻都能从库中重建当前进度。子 Agent 的结果要带可验证证据(工具原始返回、引用、执行日志),主 Agent 不能只读它的自然语言结论;校验方式包括格式与 schema 校验、与已知事实的冲突检查(时间、地点、金额是否与已有槽位矛盾)、以及关键动作的二次确认。发现错误后的顺序是:重试该子任务 → 换工具或换子 Agent → 降级(跳过或简化)→ 转人工,并且每次降级都要打点。
可观测性决定线上能不能定位问题,字段设计比工具选型重要。 一条 Trace 至少要串起:请求 ID 与会话 ID、每一步的模型名与提示词版本、输入输出 token 数、工具名与参数摘要、工具耗时与错误码、以及最终任务状态。指标分三层:模型侧(时延、token、失败率、重试率)、工具侧(成功率、P95 时延、超时率、限流次数)、业务侧(任务成功率、平均轮次、人工介入率、用户放弃率)。线上排查的顺序是:先定位第一个异常环节(不是最后一个报错),再对齐时间线看是否有发布或配置变更,最后用固定输入换模型或换工具重跑来二分公司。成本控制分省 token 与省次数两条线:模型分层路由(意图识别用便宜模型)、前缀缓存、工具结果结构化与截断、并行工具调用减少轮次、中间结果缓存;「省了多少」这类问题必须有前后对照口径,否则不如说清策略与监控方式。
手撕:最长子数组和为 k,有负数时滑动窗口就失效了。 之所以不能照搬「最短无重复子串」那套双指针,是因为窗口右移时区间和不再单调,左指针不知道该往哪走。标准解法是前缀和加哈希表:遍历时维护 prefix,用哈希表记录每个前缀和最早出现的下标,查询 prefix - k 是否出现过,出现过就用当前下标减去它取最大长度;复杂度 O(n) 时间、O(n) 空间。常见追问方向:数组全为正时可以直接用双指针(右移扩张、超了左缩),空间更省;求「个数」时哈希表记录出现次数;求「最短」时要记录最近出现的下标而不是最早的;注意先查表再写入当前前缀和,且要预先放入 (0, -1) 处理从头开始的区间。写的时候把「为什么不能滑动窗口」讲在代码之前,是这道题最容易拿分的地方。