九方智投 AI 应用开发一面:RAG 分块、混合检索与智能客服设计
- 轮次
- 一面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 请你大致做个自我介绍。
- 讲讲 HashMap。
- HashMap 线程安全吗?考虑线程安全用哪个?
- 说说 volatile 关键字。
- 了解 AQS 吗?大概讲一下。
- MySQL 用过吗?讲讲 InnoDB 的索引类型。
- B+ 树索引怎么搜索的?
- 消息队列一般用什么?RabbitMQ 的 exchange 有哪几种?
- Kafka 为什么快、性能高?
- 项目拷打:定时任务是怎么做的?
- 做 RAG 时,chunk size 和 overlap 怎么确定的?
- 向量检索和关键词检索分别解决什么问题?为什么要混合检索?
- 如果 RAG 检索效果差,怎么去区分是哪里出了问题?
- 响应速度和模型选择之间怎么取舍?
- LangChain 和 LangGraph 的核心差异是什么?
- checkpointer 存储怎么设计?
- 恢复任务时,模型版本、用户权限发生变化怎么处理?
- 设计一套智能客服系统,面向投资理财课程售卖,需要什么功能?怎么设计?如果员工不信任,该怎么说服他们?
《参考解析》
HashMap 与线程安全:JDK 8 的 HashMap 是数组加链表加红黑树,链表长度到 8 且容量不小于 64 时转红黑树,扩容按 2 倍 rehash。它本身不保证线程安全,并发扩容在 1.7 会成环、1.8 会丢数据;需要并发时用 ConcurrentHashMap(分段 CAS 加 synchronized 锁头节点),需要有序用 TreeMap,需要读写分离可以用 CopyOnWriteArrayList(写少读多场景)。
AQS 的核心:一个 volatile 的 state 加一个 FIFO 双向队列,独占模式用 CAS 抢 state,抢不到就入队并 LockSupport.park;释放时唤醒后继。ReentrantLock、Semaphore、CountDownLatch 都基于它,区别只在 state 的含义和 tryAcquire/tryRelease 的实现。
InnoDB 索引与 B+ 树:聚簇索引按主键组织,叶子节点存整行;二级索引叶子存主键值,需要回表。B+ 树只在叶子存数据、非叶子只做索引且节点是页(默认 16KB),所以树高通常 3 层就能支撑千万级数据;范围查询靠叶子节点的双向链表顺序扫描,这是它比 B 树更适合磁盘的原因。
Kafka 快的原因:顺序写磁盘加页缓存、零拷贝(sendfile)跳过用户态、批量发送与压缩、分区并行、稀疏索引定位。回答时把「写」「读」「并发」三条分开讲,比罗列名词更清楚。
chunk 与 overlap 怎么定:按文档结构切(标题层级、段落边界)优先于按固定字数切;先看业务问题的粒度——问条款级的用小块,问跨章节对比的用父子块;overlap 一般取块大小的 10%~20% 来缓解边界截断。真实做法是先拿一批线上问题做评测集,按召回率和答案正确率调,而不是凭感觉定死。
混合检索的意义:向量检索解决语义相近但字面不同的表达,关键词(BM25)解决专有名词、型号、数字、代码符号这类向量模型不敏感的精确匹配,两者用 RRF 融合再上 cross-encoder 精排,通常比单路召回的召回率高一截。
检索效果差怎么定位:分四层查——数据是否真的入库(拿已知答案的问题直接搜)、chunk 切得对不对(有没有把表格、标题切丢)、query 是否需要改写、召回后是否被 rerank 或上下文截断影响。能把这四层讲成可执行的排查顺序,是这道题真正的得分点。
LangChain 与 LangGraph:LangChain 是链式编排,适合线性流程;LangGraph 用图组织节点与边,支持环、条件分支、状态管理与中断恢复,适合多轮、需要人在环路里的 Agent。checkpointer 就是为这种有状态图做持久化——常见设计是按 thread_id 存每步的 state 快照,带上模型版本与 prompt 版本,恢复时先校验版本,不一致就走迁移或重跑而不是直接续上;权限变化则要用恢复时的最新权限做一次重鉴权。
智能客服设计的答题结构:先分场景(售前咨询、课程推荐、订单与退款、投诉),再定知识来源(课程库、FAQ、政策条款),然后给链路(意图路由 → 检索 → 生成 → 兜底转人工),最后谈可控性(敏感话术审核、留痕、人工接管、效果评估)。说服员工的关键不是讲技术,而是让它先在低风险场景跑、把每次转人工的会话做成复盘,用「它替我挡掉了多少重复问题」来建立信任。