面灵AI→

字节跳动 Agent 秋招一面(9.16):会话记忆压缩、文档更新幂等、Harness 对比与手撕二叉树

轮次
一面
时间
2026-09
来源
牛客网

《面试题目》

一、项目:企业 AI 助手

  1. 实习项目拷打(业务目标、执行链路、你负责的模块、困难与取舍、验证结果)。
  2. 企业 AI 助手项目中,基于滑动窗口和摘要压缩的会话记忆是怎么实现的?
  3. 滑动窗口大小是怎么确定的,大概设置多少轮?
  4. 哪些场景适合滑动窗口,哪些场景更适合直接用摘要做上下文压缩?

二、文档在线自动更新

  1. 文档在线自动更新时,如何保证并发更新的幂等性、避免多个任务相互覆盖?
  2. RocketMQ 在文档自动更新链路中的哪个位置?
  3. 为什么文档更新这里用 MQ,而不是直接在定时任务中处理?

三、Agent / Harness

  1. 你对业界其他 Agent / Agent Harness 有哪些了解?
  2. 展开介绍一下你了解的 DeepSeek Harness 和 Pi Agent。
  3. 如果把这些 Harness 和你实习中的 Agent 项目结合,你会怎么做?是否有必要替换当前方案?
  4. 除了开源 Agent,你是否调研或使用过其他厂商的 Agent 产品?
  5. 介绍一下你了解的 Claude Code 上下文压缩机制。
  6. 介绍一下你对 Computer Use 的了解情况。
  7. Computer Use 操作本地电脑的大致实现机制是什么?
  8. 是否了解操作本地电脑和操作云端电脑两种方案?

四、AI Coding

  1. 平时使用 AI Coding 工具开发时,遇到过哪些问题?
  2. 你平时使用 AI Coding 工具的完整开发工作流是什么?

五、八股

  1. 常见数据库有哪些类型?不同类型之间有什么区别?
  2. MySQL 底层索引使用什么数据结构?
  3. 为什么 MySQL 索引用 B+ 树,而不是其他树结构?

六、算法(要求先说思路再写代码)

  1. 判断二叉树 B 是否为二叉树 A 的子结构。
  2. 求两个有序 List 的相同元素。
  3. 分析第 22 题实现的时间复杂度。
  4. 如果两个 List 变成无法整体排序的无限序列,应该如何处理?
  5. 使用 Bitmap 时,如果元素值范围非常大,会有什么问题?
  6. 是否可以两个无限序列拆成局部、分批处理?

七、反问

  1. 团队 Agent 目前主要负责什么垂类业务方向?
  2. 团队内部是否比较鼓励使用 AI Coding?
  3. (面试官追问)你现在使用 AI Coding 的工作流是怎么样的?有没有更 AI Native 的做法?

《参考解析》

会话记忆:把它当成可恢复的任务状态,而不是一直拼字符串。 实用结构是三层——近期原文(保住指代与工具交互细节)、结构化摘要(目标、硬约束、已确认事实、关键决策、待办)、外部历史存储(大产物按需取回)。每次请求先算预算:模型上下文上限减去固定指令、工具定义、证据、输出预留与安全余量,剩下的才给历史;倒序装入完整交互单元,到预算即停。压缩只对「已经结束」的消息段做,绝不能把 tool_call 和它的结果截成不合法序列;提交摘要时用「摘要版本 + 覆盖序号」做 CAS,发现别人已提交就重读合并,否则并发摘要会互相覆盖。窗口大小以 token 为硬约束、轮数为辅助参数——4/8/12 轮只是离线消融的候选起点,真实取值要按任务类型评测指代正确率、任务成功率、约束保留率与延迟来定,自动压缩用高低水位避免抖动。

文档更新的幂等:幂等解决「重复执行」,版本控制解决「乱序完成」,两者不能互相替代。 事件带上租户、文档 ID、单调版本、事件 ID、内容哈希与流水线版本;用数据库唯一约束(tenant, doc_id, source_version, pipeline_version)去重任务。索引做成不可变代次:先为某个版本完整构建切片、向量与关键词索引,校验通过后原子切换 active_generation,分块 ID 带代次,绝不允许边算边覆盖在线索引。发布用条件更新 UPDATE ... WHERE source_version < :candidate,影响行数为 0 就说明是重复发布或已被更新版本替代。文档状态变更与事件写入用 outbox 或事务消息,解决「库改了消息没发」;删除也要版本化墓碑,否则迟到的更新会把已删文档复活。

为什么用 MQ: 定时任务擅长「发现变化」,MQ 擅长承接「独立、耗时、可重试」的活。解析、Embedding、索引写入耗时波动大,塞进扫描任务会让一个慢文档拖住整轮扫描,重启还容易丢进度。MQ 给的是持久化积压、削峰、消费者扩缩容、失败重试与生产消费解耦;代价是最终一致性、重复投递、乱序与运维复杂度——所以低流量、任务短、能整体重跑的场景,数据库任务表 + 定时 worker 就够了。

Harness 对比要落到「六个问题」。 评估任何 Agent 运行时都该问:模型看到的上下文怎么生成、工具怎么鉴权校验重试、任务状态怎么持久化、超时与取消怎么传播、结果怎么验证、故障怎么回放。DeepSeek Harness 走「一切皆插件」(Cordis 底座),模型适配器、工具注册、会话日志乃至 Agent loop 都可替换,会话日志是持久事件、模型历史由日志派生;Pi 是精简的终端 Coding Harness,默认 read/write/edit/bash,压缩机制具体可检查(选历史边界、生成结构化摘要、追加 CompactionEntry、用 firstKeptEntryId 标记保留起点)。Claude Code 的压缩是「接近上限时先清理较旧工具输出、再总结对话」,用户也能手动 /compact 指定重点——它是有损的,所以长期规则要落到 CLAUDE.md、状态与产物要落盘。要区分对话压缩、Prompt Caching 和模型内部 KV Cache 三件不同的事。同一个模型换不同 Harness,完成率与成本可能差很多,比较时固定任务集、模型与工具权限。

Computer Use 的闭环与坐标。 执行器采集截图(或可访问性树)→ 模型返回点击/输入/滚动等结构化动作 → 执行器校验坐标、权限后调用系统接口 → 把新观察送回模型。截图若裁剪缩放,坐标要换算回真实屏幕(乘以缩放比再加裁剪原点),并处理 Retina/DPI、多显示器、窗口移动。控制层要有前台窗口确认、等待界面稳定、动作超时、步数预算、取消、重复操作检测与执行后验证——点击超时不能盲目重试,因为它可能已经产生了副作用。本地方案能访问用户真实文件和已登录应用,但受抢焦点、休眠影响、误操作影响真实工作区;云端隔离桌面环境统一、可快照重置,但共享账号、多租户残留与长期 cookie 仍有风险。存在稳定 API 或 DOM 时优先用结构化接口,视觉交互作补充。

B+ 树。 InnoDB 的聚簇索引叶子存完整行、按主键组织,二级索引叶子存「索引键 + 主键」,查非覆盖列要回表。选 B+ 树的理由是按页访问的外存结构需要大扇出、低树高:内部节点只放分隔键和子页指针,一页能容纳几百个分支,三到四层就能覆盖上亿行;叶子有序且相连,等值、范围、排序都友好。相比平衡二叉树层数太多、随机 I/O 放大;相比 B 树,数据集中到叶子让内部节点更紧凑、范围扫描更统一;哈希只适合等值查询,不支持范围与排序。补充一句:树高不等于磁盘 I/O 次数,根和上层页通常在 Buffer Pool 里。

手撕二叉树子结构。 关键是先讲清「子结构」与「完全相同的子树」的区别:B 只要求它有的节点在 A 对应位置存在且值相同,A 可以多出后代;通常约定空树 B 不是任何树的子结构。实现分两层:外层遍历 A 的每个节点作为起点,内层成对比较(B 为空即该分支匹配成功,A 为空或值不等即失败)。递归写法在退化成长链时会爆栈,可以改成显式栈的迭代。复杂度最坏 O(n·m)(每个起点都可能比对到 B 的深处),栈空间 O(n)。

两个有序 List 的交集。 双指针:小的一侧前进,相等就输出并同时前进;去重交集与多重集交集用「是否允许重复输出」区分。时间 O(n+m)、辅助空间 O(1)(不算输出)。若 List 指链表,指针直接推进即可,别按下标随机访问,否则丢掉线性复杂度。

无限流与超大值域。 双指针的前提是「较小值不可能与对方更后面的更大值相等」,这在无限无序流上不成立:没到来的元素不能宣告永远不出现,所以要先定义有序性、时间窗口与结果语义。工程上通常是三种明确契约之一:限定事件时间窗口 + watermark + 允许迟到;把全历史状态放进可扩展的持久化 KV;或业务允许时先近似过滤(Bloom)再精确复核。分批不等于可丢弃:反例是 A=[7]、B=[2] 第一轮交集为空,第二轮 A=[3]、B=[7],全历史交集含 7,但 7 在第一轮已被丢掉——所以要么按值边界保留未匹配尾部,要么按 key 分区维护两侧出现标记。Bitmap 的问题在空间由取值范围而不是元素个数决定:覆盖整个 64 位域需要 2 EiB,稀疏大跨度 ID 要用 Roaring 之类压缩位图、Hash Set 或按范围分片。

AI Coding 的问题与工作流。 常见坑:只修表面报错而忽略调用方契约、生成不存在的 API、模型自己写测试又写实现导致「迎合式通过」、改动范围失控与多 Agent 抢同一文件、长任务漂移(摘要丢约束、反复试同一命令、把命令成功当任务成功)。稳定的工作流是「明确目标 → 建立证据 → 受控实现 → 独立验证 → 持续反馈」:先写清验收条件与最小复现,让 Agent 读目录约定与依赖版本形成影响范围,在独立分支小步实现,按风险分层验证(类型检查、针对性单测、必要集成、真实回放),最后由人确认迁移、权限、幂等与性能风险,灰度并保留回滚。更 AI Native 的做法不是多开几个聊天窗口,而是把需求写成可执行验收条件、让失败样本直接进回归集、把规范和工具沉淀成 Skills 与稳定服务、把轨迹与人工接管记录回流到评测。