字节跳动 Agent 秋招一面(9.16):会话记忆压缩、文档更新幂等、Harness 对比与手撕二叉树
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
一、项目:企业 AI 助手
- 实习项目拷打(业务目标、执行链路、你负责的模块、困难与取舍、验证结果)。
- 企业 AI 助手项目中,基于滑动窗口和摘要压缩的会话记忆是怎么实现的?
- 滑动窗口大小是怎么确定的,大概设置多少轮?
- 哪些场景适合滑动窗口,哪些场景更适合直接用摘要做上下文压缩?
二、文档在线自动更新
- 文档在线自动更新时,如何保证并发更新的幂等性、避免多个任务相互覆盖?
- RocketMQ 在文档自动更新链路中的哪个位置?
- 为什么文档更新这里用 MQ,而不是直接在定时任务中处理?
三、Agent / Harness
- 你对业界其他 Agent / Agent Harness 有哪些了解?
- 展开介绍一下你了解的 DeepSeek Harness 和 Pi Agent。
- 如果把这些 Harness 和你实习中的 Agent 项目结合,你会怎么做?是否有必要替换当前方案?
- 除了开源 Agent,你是否调研或使用过其他厂商的 Agent 产品?
- 介绍一下你了解的 Claude Code 上下文压缩机制。
- 介绍一下你对 Computer Use 的了解情况。
- Computer Use 操作本地电脑的大致实现机制是什么?
- 是否了解操作本地电脑和操作云端电脑两种方案?
四、AI Coding
- 平时使用 AI Coding 工具开发时,遇到过哪些问题?
- 你平时使用 AI Coding 工具的完整开发工作流是什么?
五、八股
- 常见数据库有哪些类型?不同类型之间有什么区别?
- MySQL 底层索引使用什么数据结构?
- 为什么 MySQL 索引用 B+ 树,而不是其他树结构?
六、算法(要求先说思路再写代码)
- 判断二叉树 B 是否为二叉树 A 的子结构。
- 求两个有序 List 的相同元素。
- 分析第 22 题实现的时间复杂度。
- 如果两个 List 变成无法整体排序的无限序列,应该如何处理?
- 使用 Bitmap 时,如果元素值范围非常大,会有什么问题?
- 是否可以两个无限序列拆成局部、分批处理?
七、反问
- 团队 Agent 目前主要负责什么垂类业务方向?
- 团队内部是否比较鼓励使用 AI Coding?
- (面试官追问)你现在使用 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 与稳定服务、把轨迹与人工接管记录回流到评测。