顺丰 AI 全栈一面:ReAct 循环、缓存命中率与知识库 pipeline
- 轮次
- 一面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 简单介绍一下 ReAct,它在具体实现上面的循环是怎么实现的?
- 在代码中怎么判断 AI 是否可以终止?除了最大迭代次数之外
- 如果 AI 没有输出 tool call,会表现为什么?是不是也是一种终止状态?
- 你设置的 20 次最大循环次数,是随便定的吗?
- 你实测的最复杂的任务大概是什么样的?
- 大模型 prompt caching、KV Cache 你有了解吗?在你的系统里面,如何提高 cache 的命中率?在 Spring AI 这一侧需要做哪些工程实现?
- 了解过 OpenAI 协议上的缓存控制吗?
- 你有没有做过大模型底层推理相关开发?
- 参与供应链知识库建设,只是做内容建设?有没有涉及知识库系统搭建?
- 怎么评估一个知识库的有效性、准确性?
- LM Wiki 有几层概念?它内部怎么从 raw 文档抽象出 concept、实体与边的关系?整个 pipeline 是怎么做的?
- 知识库做刷新/更新的时候,如果某一个节点变更,怎么评估相连的其他节点是否需要更新?
- 项目里的影响面分析是怎么做的?
- 多语言翻译插件里,为什么要用 ES 做语义召回?现在大模型翻译能力已经很强了。
- ES 里面召回几条记录?ES 里面总共有多少条翻译记录?每天新增多少?
- 日积月累不断新增翻译数据,翻译风格会趋于一致还是扩散?
- 谁来保证翻译入库的数据质量?翻译完成后的译文是直接写入 ES 吗?
《参考解析》
终止条件不能只有一个最大迭代次数。 面试官连续追问了「怎么判断可以终止」「没有 tool call 算什么」「20 次是不是随便定的」,指向的是同一件事:一个能上生产的 Agent loop 需要多路终止条件,而且要能解释每个阈值是怎么定的。可用的几条:模型给出最终答案或不再产生工具调用;达到预算上限(步数/总 token/总耗时/工具调用次数),强制收尾并回报「已完成什么、还差什么」;连续 N 轮没有产生新信息,或同一工具同参数反复报同样的错,判定为陷入循环主动中断;命中不可恢复错误或安全策略立即转人工。至于「没有输出 tool call」,它是一个终止信号但不是成功信号——可能是模型真的答完了,也可能是格式解析失败或模型退化,所以工程上要把它和「输出了最终文本」分开记账,并统计这类终止的占比。
「20 次是随便定的吗」这道题考的是工程判断。 合格答法是给出定阈值的依据:先看真实任务的步数分布(比如 P99 落在 8~12 步),再留出余量取整;同时说明这个上限是兜底而非目标,正常任务不该逼近它,所以还要配监控——如果大量任务卡在上限附近,说明该优化的是提示词/工具设计而不是把上限调大。没有依据的数字在面试里就是减分项。
prompt caching 与 KV Cache 要分层说。 KV Cache 是推理引擎内部的机制:自回归生成时把已算过的 Key/Value 张量缓存下来,避免每生成一个 token 就把整个前缀重算一遍,它存在于一次请求的生命周期内(跨请求复用要靠 prefix caching)。prompt caching 是服务侧/协议层的能力:如果相邻请求的前缀完全相同,这部分就可以命中缓存、按缓存价计费并跳过重复预填充。由此提高命中率的做法就很明确了:把稳定的内容(系统提示、工具定义、少样本示例、固定文档)放在最前面,把每次都变的内容(用户输入、时间戳、随机 ID)放到最后,并保证前缀字节级一致——一个动态的时间戳插在开头就会让后面全部 miss。Spring AI 侧的工程实现通常是:固定的 system message 与工具 schema 集中定义并复用以保证序列化结果稳定,避免在系统提示里拼时间/会话 ID,留意框架是否在请求前重排或注入字段,并把缓存命中 token 数暴露到监控里验证效果。OpenAI 协议上的缓存控制主要体现在响应里上报命中 token 数、以及部分厂商支持的显式缓存断点标记。
知识库的质量评估要落到可算的指标。 「怎么评估知识库的有效性和准确性」不该只答「人工检查」,可以分层:检索层看命中率、召回率和排序质量(用带标注的问题集测「该召回的文档有没有被召回、排在前几位」);内容层看事实准确率、覆盖率(业务问题里有多少能被现有条目覆盖)和一致性(同一概念在不同文档里的说法是否矛盾);应用层看端到端任务完成率与人工接管率。还要区分「检索不到」和「检索到了但答案错」——前者是覆盖问题,后者是内容或生成问题,责任层不同。
从 raw 文档到 concept/实体/边,本质是一条信息抽取流水线。 典型形态是:文档解析与切分(保留章节层级)→ 抽取(用模型抽实体、关系、以及更高层的概念,并强制结构化输出)→ 归一与消歧(同义词合并、同名实体区分)→ 关联与建图(生成边,落库或建向量索引)→ 人工校验与反馈回流。多层概念(如「概念—实体—关系」)的好处是检索时既能用高层概念做粗筛、也能落到具体实体上。这里最容易被追问的是归一化:不解决同义与歧义,图会迅速变脏。
节点变更的影响面分析。 面试官问的是「一个节点变了,怎么判断相邻节点要不要更新」。可行思路是把依赖关系显式化:建图时就记录边和引用来源,节点变更时沿这些关系做反向遍历拿到受影响集合,再用规则(引用强度、距离、节点类型)排序,最后只把候选送去重新抽取或人工复核,而不是整库重跑。判断「真的需要更新」还可以加一层内容比对——把新抽取结果与旧条目做相似度/一致性判断,只有在实质变化时才改动,这样能避免每次微调都引发全量重写。影响面分析之所以重要,是因为知识库的维护成本几乎全在「改一处、要连带改多少」上。
为什么还用 ES 做语义召回——这道题的答法要有取舍。 面试官的反问(「现在大模型翻译能力已经很强了」)是个陷阱,不能顺着说「确实没必要」。合理的辩护是:本地化翻译的核心诉求是术语一致性和可复用性,而不是单句翻译质量——同一个词在同一产品里必须始终译成同一个说法,历史译法要能被查到并复用,这属于「检索已有译文」而不是「重新生成」。ES 在这里承担的是记忆库的角色(可以是关键词加向量混合检索),召回后作为少样本或术语约束喂给模型,既保证一致性也降低成本。接着要能答出量级(召回几条、库多大、每天新增多少)——答不出量级就说明没真正负责过这条链路。
「翻译风格会趋同还是扩散」是个有意思的追问。 有明确结论可讲:如果每次都用「检索到的历史译法」作为参照并写回库,系统会形成正反馈,风格趋同(好的方面是术语稳定,坏的方面是错误也会被固化并放大);如果放任模型自由生成又不过滤,风格会扩散。所以质量门必须有:入库前做术语一致性校验、与现有记忆的冲突检测、低置信度人工复核,并定期抽样审计;译文不应该「翻译完直接写 ES」,而应经过校验环节再入库。