面灵AI→

科大讯飞后端一面/三面/HR 面:Agent 状态流转、上下文压缩与 AI Coding 分工

轮次
一面、三面、HR面
时间
2026-10
来源
牛客网

《面试题目》

一面

  1. 简单做一下自我介绍。
  2. 采用预计算 + Redis 缓存的方案,设计时的瓶颈是什么?
  3. 缓存和真实中间结果存在数据差异,你们怎么解决?
  4. 用 binlog 监听做同步、用发 MQ 方式解决一致性,两种场景为什么选用不同方案?
  5. ThreadLocal 的 key 为什么设计成弱引用?用强引用会有什么问题?
  6. ThreadLocal 依然会出现内存泄漏,该如何解决?
  7. 线程池核心线程满、队列满、最大线程数也满,再提交任务会发生什么?拒绝策略有哪些?
  8. 说说你平时在团队里完整的工作流程是什么样的。
  9. 和其他团队是怎么合作对接的?
  10. 和外部团队协作遇到矛盾、问题,你是怎么处理的?举实际经历。
  11. 你的技术方案有没有被否定过?
  12. mentor 给调研方向,你是怎么调研、输出结论说服导师采用该方案的?
  13. 项目是课程项目还是导师项目?
  14. 项目里上下文压缩是怎么做的?怎么判断什么时候拉全文、什么时候不拉,降低 token 消耗?
  15. 实习中会用 AI Coding,怎么判断哪些交给 AI 写、哪些核心逻辑自己把控?
  16. 团队内部多人怎么协作使用 AI Coding?有没有参与过大型多人 AI 开发项目?
  17. 平时会不会沉淀可复用的 skill、复用组件?举例子。
  18. 改造开源项目时,遇到模型输出结果和预期不符的情况吗,怎么处理?
  19. 最近在学习哪些内容?
  20. 业务方只反馈一句话「对话服务打不准、不好用」,交给你处理,你会怎么做?
  21. 是否愿意长期在合肥工作?

三面

  1. 做一个简单的自我介绍。
  2. 实习过程中遇到过比较难的问题,你是怎么解决的?
  3. Agent 项目不同类别对应不同流程,如何保证路由准确性?如何保证处理流程按预期逻辑执行?
  4. 你们的 graph 具体指什么?是专门有人来画这个图吗,怎么实现的?
  5. Agent 跨请求长流程、状态流转、撤销相关,底层整体架构设计是什么、采用什么设计思路?
  6. Agent 运行的状态数据存储在哪里?
  7. AI Coding 在你的工作当中是怎么使用的?
  8. 收到产品需求,一方面如何让 AI 理解需求,另一方面如何控制 AI 生成代码的质量?
  9. 你们的 PRD 产品需求文档一般包含哪些内容?
  10. 平时和产品经理怎么沟通需求?中途发生需求变更你会怎么处理?
  11. 站在你的角度看,你参与过的团队在工作流程、机制上存在什么问题?有什么改进想法?
  12. 对科大讯飞有了解吗?
  13. 你的老家是哪里?
  14. 谈谈你个人的职业发展规划,是深耕技术还是往架构方向发展?
  15. 除后端之外,前端是已经开始学习,还是只是有想法?
  16. 对于中间件、数据库、底层存储、容器化这些基础设施,哪些已经学习了解、哪些还没有?
  17. 项目之外,有没有主动去了解学习其他相关知识?
  18. 深入学习过哪些相关技术?学习过哪些相关开源项目?
  19. 容器化、网络、操作系统这些底层内容,有没有深入学习?
  20. 你对开源 Agent 项目中原粗糙的上下文压缩做了优化,具体怎么优化?如何做到压缩同时尽量不丢失关键事实?

HR 面

  1. 简单做一下自我介绍。
  2. 两段实习里,印象比较深刻的技术难题是什么?讲下解题思路和规划方式。
  3. 实习过程中有没有拒绝过需求?举可分享的例子。
  4. 做多模块开发优化时,怎么做项目进程规划,保证自己负责模块按时完成?
  5. 工作遇到自己不了解的技术/领域,如何快速学习并且推动工作进展?
  6. 会不会定期对工作、学习做总结?分享下近期的总结内容。
  7. 平时使用比较多的最新 AI 工具是什么?谈谈你的看法。
  8. 项目推进中,不同模块负责人对技术方案产生分歧,你如何沟通协调达成一致?
  9. 上级/导师分配过挑战性、边界模糊的工作吗?有没有主动争取过?争取到后如何保障落地完成?
  10. 你考虑留在合肥发展的主要原因是什么?选择讯飞的原因是什么?

《参考解析》

预计算 + Redis 缓存的瓶颈在哪。 四个方向:① 预计算的时间与存储成本——组合爆炸时不可能全量预热,要按热度分层;② 缓存与真实数据的时延——预计算是快照,业务数据在变,用户可能看到旧结果;③ 冷启动与热点倾斜——热点 key 打满单个分片,长尾 key 命中率低;④ 一致性维护——更新时要精确失效,漏删就会长期脏读。答这题时先给「瓶颈是组合维度与更新频率」,再说你怎么分层(热组合预计算、冷组合实时算 + 缓存)。

缓存与真实结果不一致怎么解。 分三类:① 能容忍短暂不一致的,用「先更新 DB 再删缓存」+ 延迟双删 + 消息重试,并给缓存设版本号,读时校验版本;② 不能容忍的,把缓存降级成「只读加速」,关键判断始终回源(或用 CQN/订阅变更);③ 有对账能力的,定时比对并修复,把差异做成指标。核心是「设计时就明确哪份数据是权威源」,别让缓存成为事实来源。

binlog 还是 MQ。 选 binlog 的场景:以数据库为唯一事实源、需要「所有变更都同步」、业务方不想改造写入路径(CDC 无侵入)。选 MQ 的场景:变更需要携带业务语义、需要跨系统编排、或者写入方本身就是异步流程。binlog 的优点是全覆盖、不漏;缺点是与业务语义脱节(拿到的是行变更,要自己还原意图)、有主从延迟。MQ 的优点是语义清晰、可路由;缺点是要业务自己保证「写完一定发出去」(本地消息表/事务消息),漏发就是数据缺失。所以常见组合是「核心表走 binlog 兜底 + 关键业务事件走 MQ」。

ThreadLocal 为什么用弱引用。 ThreadLocalMap 的 Entry 继承 WeakReference<ThreadLocal>,key 是弱引用、value 是强引用。用弱引用的目的:当外部不再持有 ThreadLocal 对象时,key 能被 GC 回收,避免「ThreadLocal 对象本身」长期占内存。但只解决了一半——key 被回收后 Entry 变成 key=null 的「陈旧条目」,value 仍然被 Entry 强引用、而 Entry 又被 Thread 的 map 持有,线程池里线程长期存活,value 就泄漏了。所以规范做法是 try { ... } finally { threadLocal.remove(); },尤其是在线程池场景;ThreadLocalMap 在 get/set 时也会顺带清理部分陈旧条目(启发式清理),但不能依赖它。

线程池全满之后。 提交顺序是先看核心线程是否已满 → 不满就建核心线程;满了进队列;队列满再看是否达到最大线程数 → 没到就建非核心线程;都满了才走拒绝策略。四种内置策略:AbortPolicy 抛 RejectedExecutionException(默认,适合必须感知失败的场景)、CallerRunsPolicy 由提交线程自己执行(天然回压,适合不能丢的任务)、DiscardPolicy 静默丢弃(危险,容易吞掉关键任务)、DiscardOldestPolicy 丢掉队列里最老的任务再重试。生产上更常用自定义策略:记录日志 + 指标 + 落库重试,或按任务优先级分流到不同池。

上下文压缩。 目标是「在 token 预算内保住决策所需的事实」。常见分层:① 结构化摘要——把历史按「目标、已确认事实、已做动作、未决问题」四栏重写,丢弃寒暄与重复;② 分层记忆——最近 N 轮保留原文,更早的压缩成摘要,关键实体(人名、单号、金额、约束)单独存成结构化字段,永不压缩;③ 检索式回填——摘要里保留「原文指针」,模型需要细节时再按需拉取原文片段(工具化检索),而不是一次性全塞。判断「什么时候拉全文」:当问题涉及具体数字、条款、代码片段,或者摘要里出现「详见上文」这类不确定指代时,触发拉取。评估方法是对比「压缩后回答」与「全量上下文回答」在评测集上的一致率。

AI Coding 怎么分工。 一条可操作的界线:把「需要判断与负责」的部分留给自己——架构与接口设计、数据模型、并发与事务边界、安全与权限、错误处理策略;把「模式固定、可验证」的部分交给 AI——样板 CRUD、DTO/类型定义、测试用例、文档、重构改名、日志补全。判据是「出错后能否被自动化检查捕获」:能被类型、测试、lint 抓住的交给 AI,抓不住的自己写。多人协作上要统一规则文件(编码规范、目录约定)、禁止 AI 越界改无关文件、提交前必须过 CI 与人工读 diff。

路由准确性与流程可控。 路由本质是分类:先做意图分类(规则 + 小模型/大模型分类器),置信度低时走澄清问句而不是硬猜;分类结果映射到流程时用显式状态机或图,而不是让模型自由发挥。可控性靠三件事:每一步的输出做 schema 校验、每一步的转移条件写成代码(模型只提供参数)、异常与非法转移有兜底分支(回退到上一个稳定节点或转人工)。评测上要建混淆矩阵,看哪两类最容易混,再针对性补样例。

graph 指什么、状态存哪。 graph 是把流程显式表达成「节点 + 有向边 + 条件路由」的执行图,节点是一个可执行单元(调模型、调工具、人工确认),边是转移条件。可以是代码里写死的(推荐,可控可测),也可以是配置/画布生成的(灵活但难调试)。状态存储分三层:会话级(DB 存消息与变量快照)、执行级(Redis 存当前 run 的 checkpoint,带 TTL)、事件级(追加式日志,便于回放与审计)。撤销要能撤销,就必须把「副作用」与「状态变更」分开记录,撤销时按补偿动作逆序执行,而不是简单回滚状态。

需求到代码、如何控质量。 让 AI 理解需求:把 PRD 转成「验收标准 + 接口契约 + 数据示例」,要求它先复述并列出不确定点,人确认后再动手。控质量:小步提交、每步跑测试、限制改动范围(明确告知哪些文件可改)、对关键路径要求写测试、最后人工读 diff 并检查有没有吞异常/改无关文件。PRD 一般包含:背景与目标、用户与场景、功能清单与优先级、交互与状态流转、接口与数据字段、边界与异常、验收标准、上线与回滚方案。需求变更时先评估影响面(接口、数据、测试用例),把变更记录在案并同步给所有相关方,避免口头变更。

「打不准、不好用」这类模糊反馈怎么处理。 先把它变成可度量的问题:拉日志看是「答非所问」「答不全」「答太慢」还是「检索不到」,按类型分层统计;再抽样人工标注建一个小评测集,定位到具体环节(检索召回、提示词、模型、上下文长度);然后按影响面排序修复,每修一项就回归评测集。最后给业务方一份「问题分类 + 已修 + 待修 + 需要他们配合的部分」的清单,把模糊反馈变成可追踪的工单。

HR 面的几个高频点。 拒绝需求要讲「不是不干,而是给出替代方案与代价」:说明当前排期与风险,提出分期或降级方案,让业务方在知情下选择。多模块规划讲「拆解 → 依赖排序 → 里程碑 → 风险缓冲」,并说清你怎么同步进度。分歧协调讲「先把事实和约束摆到桌面上,再找共同目标,最后用数据或小规模验证收敛」。留合肥的原因落到现实:产业与岗位匹配、生活成本、家庭距离;对公司的了解说具体业务线(语音、教育、办公、汽车)而不是空泛夸。