阿里巴巴 · 千问技术部

Agent 开发工程师一面面经

完整信息

31 条问法 · 30 道题

本篇目录

写在前面

【WeThinkIn出品】栏目专注于分享Rocky的认知思考与经验感悟,范围涵盖但不限于AI行业。

干货AIGC、AI Agent、LLM算法工程师/开发工程师面试面经秘籍分享(持续更新):WeThinkIn/AIGC-Interview-Book欢迎大家Star~

大家好,我是Rocky Ding。

一面

1. 个人介绍

回答:

个人介绍应让面试官迅速建立“能力、证据、岗位匹配”的关系。可以用一分钟左右说明教育或工作背景、主要技术方向,再选择一个最能体现后端工程与 Agent 能力的项目,讲清楚业务目标、个人负责模块、关键困难和验证结果。

针对这类面试,重点可以落在并发任务调度、可观测数据链路和 Agent 运行时:如何控制资源、怎样避免重复或丢失、任务状态如何保存、模型与工具怎样协同、修改后如何验证有效。技术栈名称应和职责绑定,而不是堆积名词。

必须区分个人贡献与团队方案,离线实验与线上收益。没有真实指标时可以说明评测口径和验证方法,不编造吞吐量、数据集规模或业务收益。最后用一句话说明希望继续解决的工程问题,让后续追问围绕自己真正理解的模块展开。

2. 里面有哪些项目/需求,是你从头到尾参与设计的?

回答:

选一个真实需求,按照“需求发现、方案比较、实现、上线、复盘”的完整过程回答。端到端参与意味着理解需求如何转化为系统约束,不意味着每行代码都必须由自己完成。

以异步任务平台为例,应交代任务类型、延迟目标、峰值负载、失败代价,再说明为什么采用任务队列、并发配额和持久化状态机。比较同步执行、数据库任务表、消息队列三种方案的适用条件,指出自己负责的接口、数据模型、并发控制和验收。

设计证据包括容量估算、状态迁移图、失败重试规则、幂等键、监控和回滚方案。上线后对照原先目标检查成功率、排队时长、处理延迟和成本;描述一次失败如何反馈到设计。只完成某个模块时应如实界定边界,再说明与上下游如何协作。

3. 手撕,实现一个线程安全的滑动窗口限流算法

回答:

先定义语义:单个限流器在任意时刻 $t$,只允许最近窗口 $(t-W,t]$ 内最多 $L$ 个请求通过。等于左边界的记录过期;被拒绝的请求不计入已放行数量。这里实现的是单进程、单配额键的精确滑动日志窗口,多实例全局限流需要额外协调。

核心不变量是“清理过期记录、判断容量、记录放行”必须在同一个临界区完成。 用固定容量环形队列保存最近放行的时间,容量等于限额;用 Go 的 sync.Mutex 保证线性化,并在锁内获取单调时间,避免排队前取时导致记录顺序倒置。

下面两个代码块组成同一个 Go 文件。第一个定义状态与初始化:

package limiter

import (
    "errors"
    "sync"
    "time"
)

type SlidingWindow struct {
    mu     sync.Mutex
    origin time.Time
    window time.Duration
    times  []time.Duration
    head   int
    size   int
}

func NewSlidingWindow(limit int, window time.Duration) (*SlidingWindow, error) {
    if limit <= 0 || window <= 0 {
        return nil, errors.New("limit and window must be positive")
    }
    return &SlidingWindow{
        origin: time.Now(), window: window,
        times: make([]time.Duration, limit),
    }, nil
}

第二个实现检查与放行。allowLocked 是内部辅助函数,调用方必须持有锁,时间参数必须单调不减:

func (s *SlidingWindow) Allow() bool {
    s.mu.Lock()
    defer s.mu.Unlock()
    return s.allowLocked(time.Since(s.origin))
}

func (s *SlidingWindow) allowLocked(now time.Duration) bool {
    cutoff := now - s.window
    for s.size > 0 && s.times[s.head] <= cutoff {
        s.head = (s.head + 1) % len(s.times)
        s.size--
    }
    if s.size == len(s.times) {
        return false
    }
    tail := (s.head + s.size) % len(s.times)
    s.times[tail] = now
    s.size++
    return true
}

time.Since 使用 time.Now 携带的单调时钟信息,避免通常的墙上时钟校时影响经过时长。对象应经构造函数创建,开始使用后不得按值复制,其中的锁和环形队列属于同一份状态。限额应有合理上限,避免配置错误一次分配过大内存。

每条放行记录入队、出队各一次,摊还时间为 $O(1)$;单次批量清理最坏为 $O(L)$,空间为 $O(L)$,锁竞争时间需另计。高吞吐按租户或资源分片;若改用时间桶计数,必须说明精度损失,而不能声称与精确窗口完全等价。

测试覆盖同一时刻的并发请求、窗口左右边界、拒绝后不延长窗口、环形回绕、长时间空闲、非法参数及竞态检测。这个限流器约束请求到达速率,不限制已经在执行的请求总数,耗时任务还应配合并发信号量。

4. 你的这个并发处理耗时请求是怎么设计的?

回答:

耗时任务应采用有界队列与受控 worker,而不是每个请求到来就无限创建协程。接入层先鉴权、校验并生成幂等任务 ID;短任务可等待结果,长任务通常返回任务 ID,后续查询或订阅进度。

将限流、排队、并发和超时分开控制:入口按租户与资源限速;队列容量限制待执行数量;信号量限制正在占用数据库连接、GPU 或外部 API 的任务;全链路 deadline 控制总等待时间。队列满时显式拒绝、降级或返回可重试状态,不能把内存当作无限缓冲。

任务状态持久化为 pending、running、succeeded、failed、cancelled 等,并记录租约、尝试次数和结果引用。worker 领取任务、续租、执行与提交需要处理宕机重试;外部写入使用幂等键,避免任务重放产生重复副作用。协程退出时释放资源,取消要传播到下游调用。

容量估算可以借助稳定系统中的 Little 定律:

$N=\lambda T.$

其中 $N$ 是某个系统边界内的平均在途数量,$\lambda$ 是稳定吞吐,$T$ 是同一边界内平均逗留时长。它不是直接照搬的线程数公式;实际还要看尾延迟、资源瓶颈和余量。监控应分开记录排队与执行时间,并检查吞吐是否已经超过下游持续服务能力。

5. 假设现在我有一个训练集群,每个节点都有大量的mertics需要记录和分析,你怎么设计?

回答:

先按指标用途分层:节点与 GPU 基础设施指标、训练作业指标、模型训练质量指标、数据与通信指标。典型内容包括 GPU 利用率和显存、网络与磁盘、step time、吞吐、loss、梯度异常、checkpoint 耗时和分布式通信等待。

节点侧用 exporter 或采集 Agent 汇聚数据,训练进程通过轻量 SDK 上报;避免在训练关键路径同步写远端存储。采集端批量发送、有界缓冲,关键链路启用本地持久化队列与重试。集群网关做身份校验、限额、预聚合和转发,指标落入时序存储,详细日志与大规模诊断数据进入日志或对象存储。

高基数是主要容量风险。 cluster、job、node、rank、device、metric 的组合会放大时间序列数量;request ID、原始报错文本、样本 ID 等不应无界放入指标标签。训练作业标签也要控制生命周期和保留周期。trace ID 可以通过 exemplar 或日志关联,避免制造一条请求一条序列。

设活跃序列数为 $S$,采样间隔为 $\Delta$ 秒,每个样本有效写入字节为 $b$,粗略输入速率为:

$R\approx\frac{Sb}{\Delta}.$

估算还要乘上索引、复制、WAL、压缩与保留周期影响,不能只统计数值字段。热数据细粒度保留,冷数据降采样;告警使用业务阈值、持续时间和多指标关联,避免正常训练波动导致告警风暴。

数据质量同样要监控:采集延迟、丢弃数、队列年龄、时钟偏移和缺失率。分布式作业的 step time 常由最慢 rank 决定,平均 GPU 利用率不能代替瓶颈诊断。

6. 令牌是针对不同的资源吗?还是针对协程?

回答:

令牌应表达受限资源或配额,协程只是获得令牌后执行工作的载体。需要先确认讨论的是令牌桶,还是并发信号量,两者语义不同。

令牌桶按时间补充令牌,约束平均速率与突发额度;令牌消耗后通常不在请求完成时归还。信号量许可约束同时占用资源的数量,任务结束或取消时应归还。把信号量许可叫作令牌很常见,但面试中要说清楚。

配额键可以是租户、用户、API、模型、GPU 池或数据库连接池,也可以采用加权许可,让大任务消耗更多资源预算。多个限额同时生效时需要统一获取顺序或协调器,避免拿着一部分许可长期等待另一部分。

协程数量本身可以作为进程保护上限,但它不能准确表示 GPU 显存、外部 QPS 或数据库并发容量。设计时应把限额绑定真实瓶颈,并通过指标校准。

7. 假设我现在需要进行分布式的收集和聚合分析,整个处理链路你怎么设计?

回答:

可以采用“节点采集、区域网关、持久化缓冲、流式聚合、分层存储、查询告警”的链路:

训练进程 / GPU exporter
  -> 节点采集器:批量、过滤、限额、本地持久化缓冲
  -> 网关:鉴权、路由、背压
  -> 可选消息总线:分区、持久化、重放
  -> 流处理:去重、事件时间窗口、聚合
  -> 时序存储 / 分析存储 / 对象存储
  -> 看板、告警、作业诊断

消息总线并非所有监控系统都必需。若需要跨集群解耦、长时间缓冲、多消费者和可重放分析,可以引入 Kafka;简单指标链路可直接采用采集器到存储的模式。队列和持久化只能在配置容量、重试与保留边界内减少丢失,磁盘满或停机时间过长仍会丢数据。

按租户与序列键分区,保持同一序列的顺序,避免多个写入者冲突。区分事件时间与处理时间,通过 watermark 和允许迟到策略决定何时关闭窗口;累计值与增量值转换需要处理进程重启和 counter reset。

聚合必须尊重指标语义:counter 计算速率时处理重置;gauge 按业务选择最后值、最大值或时间加权统计;平均值通过总和与总计数计算;分位数不能简单平均各节点 P99。经典 histogram 需兼容桶边界后聚合桶计数,再估计分位数;native histogram 也要使用支持其兼容与合并语义的实现。

高可用采集可能产生重复样本,应使用明确的副本标签、序列标识和后端去重策略。流处理状态、消费位点与输出的一致性要一起设计。监控系统自身也需要独立的健康检查,否则采集器宕机可能被误判为业务流量下降。

8. 实习中你的延迟队列是用来做什么的?底层是怎么实现的?

回答:

应先如实说明实际业务。常见用途包括任务超时检查、订单到期、失败退避、租约清理和延期通知。延迟消息通常表示“到时检查条件”,不能默认时间到了就无条件执行,因为业务状态可能已经变化。

单机可使用最小堆按到期时间排序,配合一个定时器等待堆顶;插入更早任务时唤醒并重设定时器。时间轮适合大量定时任务,以时间精度、跨度和层级换取更低调度开销;不能简单说所有时间轮在任意条件下都是严格常数复杂度。

分布式实现需要持久化和原子领取。例如 Redis ZSET 用到期时间作 score,但不能先查再由多个 worker 各自删除执行;可用 Lua 原子移动到处理中集合,附带租约、尝试次数和恢复扫描。直接弹出后执行,进程宕机会丢任务;需要成功确认和超时重投。可靠性还受 Redis 持久化、复制与故障配置影响。

如果采用数据库任务表,用到期索引、条件更新或支持的行锁机制领取任务,并为每次执行记录幂等键。到期只意味着具备执行资格,实际触发延迟还取决于扫描粒度、排队与负载,应监控调度偏差和最老待执行任务年龄。

9. 如果用kafka,RocketMQ这些,你会怎么做?

回答:

延续延迟队列问题,需要区分消息产品及具体版本的能力。RocketMQ 提供延迟或定时消息,5.x 的相关接口可以指定投递时间;4.x 常见机制为延迟级别。支持的时间范围、精度、消息类型与重试行为要依据部署版本确认,不能把不同版本接口混用。

使用 RocketMQ 时发送业务 ID、目标时间、事件版本与幂等键,消息到期后消费者重新读取业务状态,条件满足才执行。持久化、重试和死信都需要配置;延迟消息不是实时操作系统定时器,负载与故障会增加实际触发偏差。

不能把 Kafka 的记录 timestamp 直接当作通用“到期后才投递”的保证。对于常见消费模型,可通过外部持久化调度器或 Kafka Streams 状态存储和定时逻辑实现;也可按延迟等级设置 retry topic,再由调度组件转入就绪 topic。

避免在一个消费线程里对尚未到期的消息长时间 sleep,这会阻塞同分区其他消息并影响 poll 活性。Kafka Streams 的 stream-time 依赖事件推进,空闲时不一定前进;需要墙上时间触发的业务应使用对应机制,并接受非硬实时调度。取消或更新定时任务还需版本检查,防止旧到期事件执行。

10. 如何保证大流量下消息处理的鲁棒性?

回答:

先定义可靠性的范围:允许多长延迟、可容忍多少丢失、是否允许重复、消息保留多久,以及外部副作用能否幂等。大流量系统无法靠“不断重试”保证无限可靠。

生产端使用可靠确认、合理批量和幂等机制,并为业务状态与发消息设计 outbox 或事务消息。Broker 根据可用性要求设置复制、确认与保留策略,提前估算积压容量和磁盘水位。

消费者使用有界队列、受控并发和分区背压,必要时暂停拉取;按业务键串行保证有序,独立键并行。瞬时故障使用有限退避和抖动,永久错误进入隔离或死信流程;毒消息不能无限占用分区。死信仍需监控、修复和重放,不能把转入死信等同于业务成功。

消费确认与结果持久化协调,外部写入具备幂等性;处理崩溃、重平衡、超时和网络中断时都能恢复。持续监控 lag、最老消息年龄、处理成功率、重试率、重复副作用、线程池与连接池占用。故障注入应验证下游限流、Broker 重启、消费者退出、磁盘不足和突发流量。

11. 使用kafka,消费者在并发处理时,会导致丢消息吗?为什么?

回答:

并发本身不必然丢消息;典型问题是提交位点越过尚未完成的记录。Kafka 中消费者已拉取位置、业务完成位置和已提交位置是不同概念。

例如同一分区的 offset 100、101、102 被并行交给 worker,102 先完成,系统错误地提交 103。此时进程崩溃,消费者恢复后从 103 开始,100 和 101 虽然可能仍在 Broker 中,却不会被该消费组正常重放,形成业务上的跳过。

自动提交配合异步 worker 也容易出现这种情况:poll 已把数据交给应用,并不意味着业务已经完成。相反,如果业务完成后、提交前崩溃,恢复通常造成重复,而不是丢失。

官方 Java KafkaConsumer 不支持由任意多个线程同时调用其普通操作,通常由单一拥有者驱动 poll 与提交,worker 只处理业务。Go 客户端的线程安全边界需看各自契约,不能直接套用 Java 结论。重平衡时旧 worker 继续写外部系统也可能造成重复或过期写入,需额外处理分区所有权与任务代次。

12. 那你怎么处理丢消息的问题?

回答:

关闭不符合业务完成语义的自动提交,按分区维护“已经完整处理的前缀”,只提交该前缀之后的安全恢复位置。完成顺序可以乱,确认顺序不能越过尚未完成的记录。

一种方式是同分区串行处理、不同分区并行。需要同分区内并发时,按交付顺序登记在途记录,worker 完成后回报状态;从队首逐个移除已完成项,遇到未完成项就停止推进。提交的是下一次恢复应读取的位置。Kafka offset 可能有空洞,应使用实际交付记录和批次位置,不能等待每个整数 offset 都出现。

例如记录 100 未完成、101 和 102 完成时,不得提交 103;100 也完成后,才能推进。若实际交付为 100、104,处理完 100 后可以安全恢复到 104,而不是等待不存在的 101 至 103。

业务写入先持久化,再标记成功;通过唯一键、幂等接口或消费记录防止重放副作用。Kafka 内部的消费、处理、再生产可使用适当的事务与 read_committed 配置,但这些不自动覆盖外部数据库和 HTTP 调用。

重平衡时停止新任务派发,处理或取消在途工作,只提交已完成前缀;对旧 worker 的结果用分区代次、fencing 或业务版本校验,避免失去所有权后继续提交结果。已发生跳过时,先查明范围,再在保留期内回退位点或重放到修复消费组,并校验幂等性;消息过期后只能依赖上游权威数据或备份恢复。

13. 介绍一下你们的TSM平台和Agent功能

回答:

TSM 在不同组织里可能指不同平台,题目没有给出全称、用户和职责,不能据此断言它是某个公开产品。实际回答首先说明自己项目里的准确名称、服务对象和业务边界。

然后把平台能力与 Agent 能力分层:平台负责身份、资源、任务、配置、审计和数据管理;Agent 接收目标,读取授权上下文,选择工具,执行并验证任务。用一个真实场景说明 Agent 如何调用平台已有 API,而不是让模型绕过平台权限直接修改底层资源。

如果按运维或训练服务平台来设计,工具可能包括查询作业状态、检索错误日志、诊断资源瓶颈和生成操作方案;重启、扩缩容或修改配置属于更高风险动作,需要明确权限与审批。这里是条件性设计示例,不代表该 TSM 平台的真实功能。

回答还应交代上线范围、哪些能力只是建议、哪些可自动执行、失败如何转人工,以及成功率与误操作如何度量。未公开的内部实现只依据本人参与的事实说明。

14. 说一下一个用户发起一个对话时,底层执行的链路。

回答:

一次对话通常先经过网关鉴权、租户识别、限流和参数校验,再以幂等请求键创建 conversation_id、turn_id、run_id。消息先进入持久化会话日志,运行任务由调度器领取,避免 HTTP 连接生命周期成为任务状态的唯一载体。

运行时读取目标、近期对话、结构化记忆、工具 Schema 和相关知识,执行权限过滤与 Token 预算检查。模型适配器将内部消息映射为供应商协议,发起推理并接收文本或工具调用事件。

如果需要工具,服务端完成参数解析、Schema 校验、鉴权、预算和副作用检查,再执行工具;工具结果以对应的调用 ID 写入状态并进入下一轮。计划与验证器根据观察决定继续、重试、重规划、等待人工或结束,整个循环有步数、费用和 deadline 限制。

输出事件按 run 内递增序号持久化并推送客户端,完成后保存最终产物、引用和状态。端到端 trace 关联模型请求、工具调用与外部回执,分别统计首字延迟、总任务时长和真实业务完成结果。

15. 你们的这个plan能力是怎么和agent loop配合的?

回答:

Plan 表达任务的阶段目标、依赖和验收条件;Agent loop 负责在当前状态下执行一步、观察结果并推进。两者可以结合,但计划不能只是塞进 Prompt 的一段不会更新的文本。

将计划保存为版本化结构,每个步骤包含 step_id、goal、depends_on、status、expected_artifacts、acceptance,必要时记录资源预算和权限要求。loop 根据当前可执行步骤组装上下文,让模型提出行动,再由确定性运行时执行与校验。

一个步骤可能需要多轮工具调用,也可能不调用工具。只有验收条件满足才标记完成;独立步骤可并发,有依赖或共享副作用的步骤受控串行。模型提出的新计划需要检查依赖闭环、越权与预算,再以新版本提交。

简单任务直接用短循环更高效,复杂长任务再引入显式计划。规划的收益要抵消额外推理、过时计划和维护成本,不能把计划越长当作推理越好。

16. 执行过程中agent怎么知道要不要进行重规划?

回答:

重规划应由可观察状态触发,而不是每轮都重新生成计划。常见触发包括前置条件不成立、关键工具不可用、用户修改目标、证据推翻原假设、步骤验收失败,以及成本或时间预算即将超限。

先区分失败类型:短暂网络故障可有限重试;参数格式错误可局部修正;缺少授权应等待确认;核心路径不可达或任务目标变化才需要较大范围重规划。权限拒绝不是让模型寻找绕过路径的信号。

运行时检查错误码、产物、步骤状态和进展指标,模型负责解释新信息并提出候选方案,验证器检查新方案是否满足约束。设置重规划次数、最小进展要求和循环检测,避免在几个等价计划之间振荡。

新计划记录为什么修改、替换哪些未完成步骤、怎样处理已完成副作用。已执行的外部写入不能因为“换了计划”就当作没有发生,必要时走补偿或人工处理。

17. 你说有些模型不支持工具调用,那工具调用能力是怎么实现的?

回答:

先区分接口没有原生 tool calling 字段,与模型本身缺少可靠工具选择能力。前者可以通过结构化文本协议适配;后者即使能输出 JSON,也未必能够稳定选择工具和生成正确参数。

一种兼容方式是在提示中定义可用工具、参数 Schema 与输出协议,让模型输出 final 或 tool_call 类型的对象。若推理引擎支持 JSON Schema 或 grammar 约束,可限制结构;否则先解析,再做严格校验,有限次数纠正格式错误。不要依靠模糊正则匹配任意自然语言直接执行 Shell。

{
  "type": "tool_call",
  "name": "get_job_status",
  "arguments": {"job_id": "job-123"}
}

运行时从白名单解析工具名,补充不可由模型伪造的身份,检查类型、取值、权限和预算,再执行工具并写回 observation。循环中的结果关联 ID 由服务端管理,不能把模型编造的“执行成功”当成真实回执。

结构约束保证可解析性,不保证语义、权限或事实正确。对于可靠性不达标的模型,可以用专门路由器、确定性工作流或支持工具调用的模型承担动作决策;不要强行把所有模型适配为同等能力。

18. 更底层的实现有没有了解过?agent怎么知道要进行工具调用,以及选择哪个工具调用。

回答:

模型根据系统指令、用户目标、历史观察和工具定义生成条件分布。原生工具调用通常经过相关训练,使模型学会输出工具名称、参数及特定协议结构;具体供应商如何编码控制信息各不相同,不能假设都采用同一种特殊 Token。

可以把决策理解为在“继续回答、调用某工具、请求澄清、结束”等动作之间选择:

$a_t\sim\pi_\theta(a\mid x,s_t,\mathcal{T}),$

其中 $x$ 是当前目标,$s_t$ 是可见状态,$\mathcal{T}$ 是允许使用的工具集合。模型基于训练中学到的语义与当前上下文判断何时需要外部信息或动作;它并不天然知道工具调用一定正确。

工具名称、描述、参数定义和互斥边界会影响选择质量。工具很多时,先按权限与任务检索候选工具,再把小集合提供给模型;确定性业务规则可以直接路由。框架负责解析并执行调用,模型负责提出动作,二者职责不同。

评测拆成“是否该调用、选哪一个、参数是否正确、执行是否成功、结果是否被正确使用”。SFT、偏好或强化学习可以改善选择策略,但生产可靠性仍依赖运行时校验、幂等、超时和独立验证。

19. 你们的上下文是怎么组装的?

回答:

上下文是一次决策的输入视图,应从权威状态与可追溯证据构造。通常包括系统和安全规则、当前用户目标、计划状态、近期消息、历史摘要、检索证据、工具定义以及本轮工具结果。

先确定指令层级和信任边界:用户与工具返回的网页、日志、文档均不能覆盖系统权限。身份、租户和授权从服务端注入;检索先做权限与版本过滤,再按相关性选择。工具调用与结果保持合法配对,不能因为截断而遗留只有结果没有调用的历史。

预算可以表示为:

$T_{\mathrm{rules}}+T_{\mathrm{state}}+T_{\mathrm{history}}+T_{\mathrm{evidence}}+T_{\mathrm{tools}}+T_{\mathrm{output}}+T_{\mathrm{reserve}}\le C.$

输出和安全余量必须预留,图片和工具 Schema 也占用上下文。长期硬约束单独结构化保存,近期原文解决指代,较早历史用摘要与证据引用表示。大型工具结果应先做分页和字段投影。

记录此次上下文使用的消息范围、摘要版本、检索片段和模型配置,便于复现。拼接顺序与长度需要通过任务回放验证,不能只看 Prompt 是否“写得完整”。

20. 上下文长度爆了怎么办,你们是怎么处理的?

回答:

分成事前预算和事后恢复。发请求前按实际模型及消息协议估算 Token,接近上限时压缩工具输出、收缩检索证据、总结已完成历史并保留最近完整交互。固定轮数裁剪不足以覆盖一轮输出就超长的情况。

摘要必须保留目标、约束、数字、否定、未完成项、权限条件与证据位置;原始数据继续存储,必要时回读。长期任务可拆阶段,每个阶段从结构化 checkpoint 继续,而不是把所有历史重新发送。

若供应商仍返回上下文超限,应将其识别为可恢复的输入错误,调整上下文后有限重试,并保证未重新执行已完成的副作用工具。保留工具协议完整性,不能把不兼容的工具调用历史直接砍半。

切换长上下文模型是可选降级路径,但必须检查授权、协议、费用和能力,不能静默更换。若最小必要输入仍放不下,应拆任务、外置产物或请求缩小范围。评估压缩策略看后续成功率与约束保真,不能只看节省了多少 Token。

21. 你们用的底层模型有哪些?

回答:

具体使用清单属于项目事实,题目没有提供,不能代替候选人编造。回答时列出真实供应商、模型 ID 或版本、部署方式、承担任务和回退策略,区分线上默认、灰度实验与仅调研过的模型。

选型应覆盖工具调用、结构化输出、中文与代码能力、多模态、上下文上限、延迟、费用、数据边界与供应商稳定性。规划、摘要、检索改写和执行决策可以使用不同模型,但需要通过真实任务验证,而非仅根据通用榜单分工。

系统侧维护能力矩阵与版本化路由策略:是否支持流式工具调用、哪些 Schema 特性、最大输入输出、图像格式、取消能力与错误类型。相同“OpenAI 兼容接口”外观并不保证语义完全一致。模型更新后也要跑兼容性与任务回归,避免别名自动升级导致不可解释变化。

22. 用户在问到一半,切换了模型,你们怎么处理?

回答:

首先定义产品语义:切换从下一轮生效,还是中断当前执行并立即迁移。默认在清晰的轮次或步骤边界切换更容易保证一致性;不能让同一次工具动作被两个模型同时驱动。

每个 run 固定 model_id、model_version、generation_epoch。用户要求立即切换时,先标记旧 run 的取消或迁移意图,停止后续模型请求,等待或确认在途工具状态,再保存 checkpoint。已经发生的外部写入不能通过取消 HTTP 请求撤销。

将任务目标、状态、已完成步骤、工具回执和可迁移的消息转换为统一表示,再由新模型适配器生成合法输入。检查工具角色、调用 ID、Schema、上下文预算、图像能力和供应商专有内容。供应商的加密或签名推理块不能当作通用文本随意搬运。

启动新代次后,旧模型迟到的 Token 或工具建议不得继续推进任务;前端用 run 与代次标识隔离输出。动作仍使用业务幂等键,记录迁移原因与配置。历史不足或协议不兼容时,应让用户确认重启范围,而不是声称能无损继续。

23. 中途切换模型一定会有影响吗?具体可能有哪些影响?

回答:

不一定产生用户可见的错误。若在清晰步骤边界切换,完整状态可迁移,模型能力与协议兼容,任务可能正常继续;但不能承诺结果、成本和行为完全相同。

可能影响包括:上下文上限与 Tokenizer 不同导致预算变化;工具协议、Schema 支持和多模态格式不同;指令遵循、拒答、工具选择与规划策略改变;缓存无法复用导致延迟和费用变化;输出格式和语言风格变化。

连续生成中的隐藏状态或 KV Cache 通常不能直接跨不同模型复用,即使保留可见文本,也不代表延续完全相同的生成过程。若在有副作用工具执行中切换,风险还包括重复调用、迟到结果覆盖和动作状态不确定。

因此要区分可见状态兼容、执行状态一致与模型行为等价,分别验证。通过跨模型恢复集测试未完成计划、已调用工具、长上下文、取消与失败重试,量化成功率、重复副作用及延迟变化。

24. 等待模型输出时,用户刷新了页面或者关闭了页面,重新打开后你们怎么支持重连的?

回答:

把任务执行与前端连接解耦。客户端提交请求时携带幂等键,服务端创建持久化 run;关闭 SSE 或 WebSocket 连接只表示订阅断开,是否取消任务由独立业务策略决定。

服务端把事件保存为 run_id、event_seq、event_type、payload,终态和最终产物独立持久化。重新打开后,客户端先鉴权获取任务快照,再从最后确认的序号之后补播事件。SSE 可以使用事件 id 和 Last-Event-ID,但整页刷新后新建连接仍需应用保存并提交游标;WebSocket 需要应用层恢复协议。

快照带水位 $k$,客户端加载快照后消费序号大于 $k$ 的事件。补播与订阅应通过可读取的持久日志或缓冲衔接,避免“读完历史、订阅建立前”的事件空洞。重复事件按序号去重,已过保留期则返回明确的快照恢复方式。

客户端重连不能再次创建同一任务;旧代次输出不能混入新模型的 run。多标签页、代理超时、断线期间任务完成、游标过期和服务端重启都需要测试。前端断线重连与模型供应商流式请求断线是两个问题,后者不能简单从客户端游标恢复模型推理。

25. 你们有对agent进行评测吗?

回答:

应如实说明已经落地到哪一层:人工抽检、离线自动回放、回归门禁还是线上 A/B。如果尚未建立完整体系,应明确缺口,并解释准备如何补齐。

Agent 评测至少包括任务结果、执行轨迹和工程表现。任务结果通过环境终态、产物和业务规则验收;轨迹检查工具选择、参数、授权、重复调用和恢复;工程层统计延迟、成本、稳定性及人工接管。模型说“操作完成”不能替代数据库回执或真实产物。

每个样本保存输入、初始环境、允许工具、成功标准与评分器版本。多步任务使用可重置环境和多次试验,区分一次运行与一个任务,避免随机性被单次结果掩盖。开发集用于迭代,隔离测试集用于接受或拒绝版本,线上观测验证离线结论是否成立。

26. 那agent本身修改后,你们如何去衡量此次修改的好坏?

回答:

先明确变更是什么:Prompt、工具 Schema、计划策略、记忆压缩、模型、检索或运行时。如果多项同时改变,难以归因,应通过分组实验或消融拆分影响。

在相同任务集、初始环境和预算下,对新旧版本做配对回放,并进行适量重复试验。记录任务级成功、错误类型、尾延迟、成本和高风险违规。利用配对差异、置信区间或 bootstrap 判断改进是否稳定;对同一任务的多次试验,应按任务聚合或分组抽样,避免伪增大样本量。

上线门禁除了整体平均提升,还应要求核心场景和安全约束不明显退化。检查失败是否集中到某类用户、工具或长任务。离线通过后再做受控灰度或按用户/会话分配的 A/B,明确终止与回滚条件。

最终判断是相同约束下的质量、时延和成本取舍,而不是只看一个总分。省 Token 但提高错误操作率,不能直接算作优化。

27. 说一下RSI,以及如果你去设计,怎么在你们现有的agent里加上RSI?

回答:

RSI 不是所有 Agent 项目中唯一固定的缩写,首先应确认面试中的含义。若这里指 Recursive Self-Improvement,即递归式自我改进,可以理解为系统利用执行反馈提出并验证改进,再把通过验证的变化应用到后续版本。它不等于多写一段反思,也不意味着必须在线修改模型权重。

在现有 Agent 中,可先实现受控的外层改进循环:收集失败轨迹与真实结果,按根因聚类,生成 Prompt、工具说明、Skills、计划策略或代码补丁候选;候选在隔离环境回放,经过回归、安全与成本评估后,由发布流程接纳。在线 loop 负责完成任务,外层循环负责改进版本,两者状态和权限分开。

执行轨迹与业务结果
  -> 失败归因 -> 候选改进
  -> 沙箱验证 -> 隔离测试集 -> 人工或确定性门禁
  -> 小流量发布 -> 监控与回滚

关键约束是评分器、保留测试集、权限和发布门禁不能被同一个改进 Agent 随意修改,否则容易优化评分规则而非真实能力。持续反复使用同一测试集也会过拟合,需要轮换与独立保留集。

先选择低风险、容易验证的改进范围,限制候选数量与总预算,并保留版本差异、证据和回退。这种外层自动改进是可落地的工程方案;是否形成严格意义上的递归能力提升,需要持续证据,不能从一次自我反思成功直接推断。

28. 你们现有的评测里面用了哪些指标?为什么选这些指标?

回答:

实际指标清单应以项目为准。一个可落地的设计应把业务结果、风险和资源开销分开,避免将所有信号压成不可解释的单一总分。

维度 指标举例 选择原因
任务结果 环境终态验收成功率、产物正确率 衡量是否完成用户目标
工具行为 工具选择准确率、参数正确率、调用成功率 定位决策、协议与执行层故障
证据质量 引用支持率、关键事实正确率 防止流畅回答掩盖无依据结论
风险 越权率、约束违反率、重复副作用率 捕捉不能被平均收益抵消的错误
可靠性 恢复成功率、人工接管率、重复循环率 评价长任务和异常处理能力
性能成本 首字与完成时延 P95、每次成功任务成本 连接体验和服务经济性

每个指标必须写清分母。例如工具调用成功率的分母是调用次数,任务成功率的分母是任务试验次数,不能混用。人工接管有时是正确的风险控制,应结合“该接管是否接管”评估,不能机械追求越低越好。

对任务 $i$ 进行多次试验,结果可记作 $y_{ij}\in{0,1}$。先计算每个任务的平均成功,再按任务权重汇总;避免某些任务被重复运行更多次后主导总分。若讨论独立同分布尝试、单次成功概率为 $p$,则:

$\Pr(\text{at least one success in }k)=1-(1-p)^k,\qquad \Pr(\text{all }k\text{ succeed})=p^k.$

前者衡量多次尝试找到解的可能性,后者强调重复执行的一致可靠性。真实 Agent 试验可能相关,且重试有成本与副作用,不能直接把独立性公式当作无条件业务保证。

29. review agent怎么确保他的评价是正确的?

回答:

不能保证一个 review Agent 的评价天然正确,应将它视为需要校准的测量工具。首先定义评分标准、证据要求和不确定性处理,再用人类金标与确定性检查验证它。

能用程序验证的部分优先用程序:测试是否通过、文件是否存在、数据库状态是否满足、是否越权、数字是否一致。语言质量、解释完整性等难以完全程序化的部分,再使用模型评分,并要求引用可核验的证据位置。

建立双人独立标注与分歧仲裁的校准集,覆盖短答案、长答案、不同风格、边界失败与对抗样本。测评分器对错误的漏检、对正确结果的误杀和与人工判断的一致性;高一致性也不是绝对正确,应结合业务错误成本。

控制位置偏差、长度偏好、同模型自我偏好与提示注入:比较答案时随机交换顺序,隐藏不必要的模型身份,将被评内容明确视为数据,并固定评分器版本。多评审或跨模型复核可以减少部分相关错误,但不能替代独立证据。高风险或低置信结果进入人工审查。

30. 你们的数据集是怎么构建的?有多少?

回答:

“有多少”是项目事实,应从实际清单与版本统计中回答,不能凭题目补出一个数字。报告独立任务数、每任务试验次数、任务类别和环境版本,区分开发、回归、保留测试以及线上抽样集。

数据可以来自脱敏真实任务、人工设计边界案例、历史事故和受控合成。每个样本应包含目标、必要上下文、初始环境、允许操作、成功条件与评分方法;多轮任务保留交互与工具状态,不能只有一个问题和一段参考答案。

按业务重要性与失败代价分层,覆盖长任务、超时、工具异常、权限拒绝、上下文压缩、模型切换和重连。按用户、项目、时间或语义簇划分集合,防止同一任务的改写版本跨开发集与测试集泄漏。样本变更和标注仲裁都要版本化。

规模由覆盖与统计精度共同决定。对于独立二项样本估计成功率,正态近似下可粗略用:

$n\approx\frac{z^2p(1-p)}{\epsilon^2}.$

例如 95% 置信、最保守取 $p=0.5$、希望误差约为 5 个百分点,得到约 385 个独立样本。这只是估计总体比例的示例,不是项目真实规模,也不保证稀有故障得到充分覆盖;聚类相关、配对比较和高风险场景需要另外设计样本量。

31. 回顾一下你们整个agent的开发和设计,如果让你重新开发,你会有哪些方面的优化或者修改?

回答:

复盘应从已观察到的失败和维护成本出发,按影响与投入排序。可以先统一任务、会话、步骤和事件模型,明确终态、取消、重试、检查点与副作用;这样上下文压缩、断线重连和模型切换才能共享可靠状态基础。

其次建立模型与工具能力适配层:业务逻辑不绑定某个供应商的原始消息对象,工具接口版本化,鉴权与幂等放在运行时。对简单确定任务使用工作流,对开放探索任务使用受控 loop,避免所有请求都经过昂贵规划。

第三,把评测与可观测性前置。每个变更都有回归任务、真实结果校验和成本记录;历史事故进入故障注入集,长任务保留可恢复产物。第四,优化上下文和数据链路:按预算检索、按需加载工具、限制高基数指标、统一队列背压与版本管理。

推进时采用逐模块迁移与灰度,保留可用基线和回滚路径。优先修复高频失败与不可恢复状态,再优化局部 Token 或推理耗时。框架替换只有在明确减少维护成本或提升指标时才值得做。

32. 反问

回答:

可以围绕真实工作与反馈机制提问:团队当前主要服务哪些用户、Agent 能执行哪些业务操作、线上成功如何定义,以及最迫切的工程瓶颈是什么。

进一步确认岗位职责更偏 Go 后端、模型服务、Harness、工具平台还是评测;新人能否参与设计、上线与故障复盘;团队如何管理模型升级、数据权限和高风险操作。

对于千问相关团队,也可以问产品能力与平台能力怎样协作、工具生态和可观测基础设施由谁维护。避免假设团队已经采用某个未公开方案,用开放问题获取具体边界。最后请面试官指出本次回答最值得补强的一项能力,让反馈转化为后续学习计划。

本篇目录
  1. 01
  2. 02
  3. 03
  4. 04
  5. 05
    假设现在我有一个训练集群,每个节点都有大量的mertics需要记录和分析,你怎么设计?
  6. 06
  7. 07
  8. 08
  9. 09
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
    追问
    更底层的实现有没有了解过?agent怎么知道要进行工具调用,以及选择哪个工具调用。
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
    回顾一下你们整个agent的开发和设计,如果让你重新开发,你会有哪些方面的优化或者修改?

同作者面经

展开其余 6 篇收起其余 6 篇

相关公司