10.9 360 AI 应用开发一面:知识库版本控制与 AI 工程链路
- 轮次
- 一面
- 结果
- 一面已过
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 自我介绍。
- 实习项目的细节追问(面试官会顺着简历往下问)。
- 知识库的版本控制是怎么设计的?解决什么业务场景的问题?
- ConcurrentHashMap 线程安全的原理是什么?JDK 1.7 与 1.8 有哪些差异?
- 为什么设计询盘模块的时候需要用到消息队列?解决什么问题?
- Harness 机制的作用是什么?
- MCP 跟 Skill 的区别?
- 当前的工作链路中怎么用 AI 提效?
- 持续集成商家商品到知识库是怎么设计的?
- 测试集怎么做?
- 收集线上用户的数据怎么样避免服务器的压力过大?
- 算法题:树的层序遍历。
- 算法题:最长不重复子序列。
《参考解析》
知识库版本控制:本质是「检索到的每一段内容都要能溯源到某个版本」。设计要点分四层。一是文档版本:同一份资料每次更新生成新版本号而不是覆盖,保留生效时间与失效时间,历史版本可回溯,这样出问题能定位到是哪一版内容答错了。二是切片与版本绑定:向量库里的每条记录要带 doc_id、version、chunk_index 和内容哈希,检索时只召回当前生效版本,同时用哈希做去重与增量更新——内容没变的切片不重新嵌入,能省下大量算力。三是发布流程:草稿、待审、生效、下架几个状态,支持灰度(先对小流量生效)与一键回滚(把生效指针指回上一版,而不是删数据)。四是业务场景:知识随政策、商品、价目表频繁变动,客服或导购类应用如果检索到过期内容就是事故,版本控制同时解决「更新滞后」和「错了无法回退」两个问题。答的时候可以补一句一致性:向量库与元数据库的更新要走同一事务或补偿流程,否则会出现元数据已更新、向量还是旧的错配。
ConcurrentHashMap:1.7 分段锁,1.8 变成 CAS + synchronized 加锁单桶。 JDK 1.7 的结构是 Segment 数组,每个 Segment 继承 ReentrantLock 并持有一个 HashEntry 数组,锁的粒度是「段」,并发度等于段数(默认 16),扩容只在段内进行;缺点是段数固定、内存开销大、并发度受限。JDK 1.8 取消了 Segment,结构变成 Node 数组 + 链表 + 红黑树:插入空桶用 CAS 无锁写入,桶内冲突时用 synchronized 锁住该桶的头节点,锁粒度细化到一个桶;链表长度超过 8 且数组长度达到 64 时转红黑树,查询从 O(n) 降到 O(log n);扩容支持多线程协同迁移(ForwardingNode 标记已迁移的桶,其他线程帮忙搬)。size 统计 1.7 用尝试多次计算加加锁兜底,1.8 用 baseCount 加 CounterCell 数组分散热点计数,类似 LongAdder。追问常考「为什么不用读写锁」「为什么锁头节点」,前者因为读写锁开销大且写少读多场景下 CAS 更快,后者因为锁头节点可以同时保护该桶的链表操作。
消息队列与 Harness 机制:一个解决流量与解耦,一个解决流程可控。询盘模块引入消息队列的动机可以按四点讲:削峰(询盘提交有突发性,直接同步写库加通知容易打满数据库)、解耦(提交后要触发通知、分配、线索同步等多个下游,同步串行会让主链路变长且一个下游故障就拖垮全流程)、异步(把非关键路径的耗时操作挪出用户等待窗口,接口响应时间从数百毫秒降到几十毫秒)、可靠(消息持久化加消费端幂等加死信队列,配合重试保证最终一致)。选型上要提到顺序性问题(同一询盘的多次状态变更是否需要按序消费)与重复消费(用业务唯一键或消息 ID 做幂等)。Harness 机制在这类 AI 应用里通常指一层可控的执行框架:统一编排模型调用、工具调用、提示词与上下文装配、重试与降级、日志与 Trace 埋点,让上层业务只描述「要做什么」,把「怎么执行、出错怎么办、怎么观测」收拢到框架内,好处是行为可复现、可评测、可回滚。
MCP 与 Skill 的区别:一个解决「能调用什么」,一个解决「该怎么做事」。 MCP(Model Context Protocol)是模型与外部工具、数据源之间的协议层,它规定服务端如何暴露工具、资源与提示模板,客户端如何发现与调用,目的是让接入标准化、可插拔——换一个模型或换一个客户端不用重写集成。Skill 是面向任务的知识与流程封装:把某类工作的方法、步骤、约束、示例组织成模型可加载的一组文件,本质是「程序性知识」,按需渐进式加载以节省上下文。用一句话概括:MCP 管连接与能力边界(有哪些工具可调、参数是什么),Skill 管策略与经验(这类任务该按什么顺序做、哪些坑要避开)。落到工程上,工具级权限与审计放在 MCP 这层做,任务级的操作规范放在 Skill 这层维护。AI 提效部分建议按研发全链路举实例:需求与方案阶段用模型做竞品与实现对比、编码阶段用它写样板代码与单测、排查阶段用它读日志与构造复现、上线后用 Trace 回流做评测与调优,每一环都要说清省了多少时间或提高了什么指标。
测试集与线上数据采集:一个要能回归,一个要能不压垮服务。测试集建议分层:核心回归集小而稳、每次改动都跑,业务场景集按域组织、发版前跑,探索集放新能力与新工具的用例。来源要覆盖人工构造、线上坏例回流、Oncall 工单沉淀,每条记录输入、期望、约束与来源,改完的低分 Case 必须回填成回归样本,否则修好的问题会再次出现。判定方式上,机器能判的(工具调用是否正确、参数是否合法、是否越权、耗时与 token 消耗)写成确定性断言,语义类的用模型评审加少量人工校准。线上数据采集的降压手段:客户端采样与降频上报、批量聚合后异步发送而不是每条都打点、采样率按用户与场景分层(异常路径全采、正常路径低采样)、上报走独立通道与限流降级开关、服务端先用消息队列缓冲再落库,并对大字段做截断或只在本地留存引用。要强调的原则是「可观测性不能反噬主链路」——采集通道必须能一键关闭且不影响业务。
两道算法题:层序遍历考队列,最长不重复考滑动窗口。树的层序遍历用队列迭代:根入队,循环取出当前层节点数,逐个出队时把左右子节点入队,每层结果存成一个列表。常见追问是之字形遍历(按层标记方向反转)、按层取最大值、以及用 DFS 记录深度来模拟,答的时候主动提 BFS 与 DFS 的取舍:BFS 空间与树的最大宽度相关,DFS 与树高相关。最长不重复子序列要注意,标准的「最长无重复字符子串」是滑动窗口:右指针扩张并把字符最新下标记入哈希表,遇到重复就把左指针跳到「上次出现位置 + 1」与当前位置的较大值,过程中维护最大长度,时间 O(n)。如果题目确实指子序列(可以不连续),那它等价于「字符种类数」,答案就是出现过的不同字符个数,答之前先跟面试官确认是子串还是子序列,这个澄清本身就是加分项。两者都要能当场手写并跑一个例子。