科大讯飞后端一面/三面/HR 面:Agent 状态流转、上下文压缩与 AI Coding 分工
- 轮次
- 一面、三面、HR面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
一面
- 简单做一下自我介绍。
- 采用预计算 + Redis 缓存的方案,设计时的瓶颈是什么?
- 缓存和真实中间结果存在数据差异,你们怎么解决?
- 用 binlog 监听做同步、用发 MQ 方式解决一致性,两种场景为什么选用不同方案?
- ThreadLocal 的 key 为什么设计成弱引用?用强引用会有什么问题?
- ThreadLocal 依然会出现内存泄漏,该如何解决?
- 线程池核心线程满、队列满、最大线程数也满,再提交任务会发生什么?拒绝策略有哪些?
- 说说你平时在团队里完整的工作流程是什么样的。
- 和其他团队是怎么合作对接的?
- 和外部团队协作遇到矛盾、问题,你是怎么处理的?举实际经历。
- 你的技术方案有没有被否定过?
- mentor 给调研方向,你是怎么调研、输出结论说服导师采用该方案的?
- 项目是课程项目还是导师项目?
- 项目里上下文压缩是怎么做的?怎么判断什么时候拉全文、什么时候不拉,降低 token 消耗?
- 实习中会用 AI Coding,怎么判断哪些交给 AI 写、哪些核心逻辑自己把控?
- 团队内部多人怎么协作使用 AI Coding?有没有参与过大型多人 AI 开发项目?
- 平时会不会沉淀可复用的 skill、复用组件?举例子。
- 改造开源项目时,遇到模型输出结果和预期不符的情况吗,怎么处理?
- 最近在学习哪些内容?
- 业务方只反馈一句话「对话服务打不准、不好用」,交给你处理,你会怎么做?
- 是否愿意长期在合肥工作?
三面
- 做一个简单的自我介绍。
- 实习过程中遇到过比较难的问题,你是怎么解决的?
- Agent 项目不同类别对应不同流程,如何保证路由准确性?如何保证处理流程按预期逻辑执行?
- 你们的 graph 具体指什么?是专门有人来画这个图吗,怎么实现的?
- Agent 跨请求长流程、状态流转、撤销相关,底层整体架构设计是什么、采用什么设计思路?
- Agent 运行的状态数据存储在哪里?
- AI Coding 在你的工作当中是怎么使用的?
- 收到产品需求,一方面如何让 AI 理解需求,另一方面如何控制 AI 生成代码的质量?
- 你们的 PRD 产品需求文档一般包含哪些内容?
- 平时和产品经理怎么沟通需求?中途发生需求变更你会怎么处理?
- 站在你的角度看,你参与过的团队在工作流程、机制上存在什么问题?有什么改进想法?
- 对科大讯飞有了解吗?
- 你的老家是哪里?
- 谈谈你个人的职业发展规划,是深耕技术还是往架构方向发展?
- 除后端之外,前端是已经开始学习,还是只是有想法?
- 对于中间件、数据库、底层存储、容器化这些基础设施,哪些已经学习了解、哪些还没有?
- 项目之外,有没有主动去了解学习其他相关知识?
- 深入学习过哪些相关技术?学习过哪些相关开源项目?
- 容器化、网络、操作系统这些底层内容,有没有深入学习?
- 你对开源 Agent 项目中原粗糙的上下文压缩做了优化,具体怎么优化?如何做到压缩同时尽量不丢失关键事实?
HR 面
- 简单做一下自我介绍。
- 两段实习里,印象比较深刻的技术难题是什么?讲下解题思路和规划方式。
- 实习过程中有没有拒绝过需求?举可分享的例子。
- 做多模块开发优化时,怎么做项目进程规划,保证自己负责模块按时完成?
- 工作遇到自己不了解的技术/领域,如何快速学习并且推动工作进展?
- 会不会定期对工作、学习做总结?分享下近期的总结内容。
- 平时使用比较多的最新 AI 工具是什么?谈谈你的看法。
- 项目推进中,不同模块负责人对技术方案产生分歧,你如何沟通协调达成一致?
- 上级/导师分配过挑战性、边界模糊的工作吗?有没有主动争取过?争取到后如何保障落地完成?
- 你考虑留在合肥发展的主要原因是什么?选择讯飞的原因是什么?
《参考解析》
预计算 + 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 面的几个高频点。 拒绝需求要讲「不是不干,而是给出替代方案与代价」:说明当前排期与风险,提出分期或降级方案,让业务方在知情下选择。多模块规划讲「拆解 → 依赖排序 → 里程碑 → 风险缓冲」,并说清你怎么同步进度。分歧协调讲「先把事实和约束摆到桌面上,再找共同目标,最后用数据或小规模验证收敛」。留合肥的原因落到现实:产业与岗位匹配、生活成本、家庭距离;对公司的了解说具体业务线(语音、教育、办公、汽车)而不是空泛夸。