小红书 AI Agent 开发岗面经合集:HashMap 并发、RAG 与 Agent 工程
- 轮次
- 多轮面试合集
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
面经 01 · 小红书 AI Agent开发岗(2026-04-03)
- 项目或者实习中和 AI 结合的点有哪些?
- 了解 harness engineering 吗?
- 谈谈你对 vibe coding 的理解。
- 怎么保证生成代码的质量?
- HashMap 的数据结构是什么样的?
- 哈希表是数组吗?数组里面存储的是什么?
- HashMap 存和取的流程是怎样的?
- HashMap 怎么才能做到线程安全?
- ConcurrentHashMap 是怎么保证线程安全的?
- CAS 和 Unsafe 是什么关系?
- 还了解哪些其他的锁?
- 说说 ReentrantLock。
- HTTPS 中 TLS 的握手过程是怎样的?
- 了解中间人攻击吗?
- 有客户端开发或前端开发的经验吗?
- 手撕:岛屿数量
面经 02 · 小红书 AI Agent开发岗(2026-04-03)
- 乐观锁和悲观锁的原理是什么?
- 如何降低大模型幻觉?
- RAG 和 Agent 的区别是什么?
- Agent 的整体架构设计是什么?
- 如何防范 prompt 注入?
- 说说小红书的 AI,使用体验如何?
- 引入 AI 会让小红书丢失「活人感」吗?
- 手撕:数组中第 K 个最大的元素
- 手撕:环形链表
面经 03 · 小红书 AI Agent开发岗(2026-04-03)
- 项目的 prompt 工程结构是怎么设计的?
- 常见的 Agent 范式有哪些?
- RAG 的流程怎么优化?
- 多模态对齐的流程是怎样的?
- 你对 OpenClaw 的看法是什么?
- 手撕:分批淘汰
面经 04 · 小红书 AI Agent开发岗(2026-04-03)
- Agent 的上下文与长短期记忆是怎么设计的(八股)?
- 讲一下 OpenClaw 的记忆本地存储怎么设计?
- SDD 是什么?OpenSpec 的设计思路和优缺点是什么?
- 手撕:K 个一组反转链表
面经 05 · 小红书 AI Agent开发岗(2026-04-02)
- 本科时是否做过服务端相关的项目?
- Java 的垃圾回收机制是怎样的?
- 会存在内存碎片化之类的问题吗?
- Java Spring 的 Bean 生命周期是什么样的?
- 介绍一下 Java 多线程。
- 轻量级锁自旋失败后转换为重量级锁的过程是什么样的?
- 如果要设计一个高并发的订单号生成器,要求全局唯一且可以递增,应该怎么设计?
- 能介绍一下上下文工程和 Harness 工程的区别吗?
- 上下文 summary 的策略是什么样的?
- 怎么缓解内容被压缩导致结果失真的问题?
- RAG 文档的分片策略是怎样的?
- 假设召回的一个片段不足以解决问题,怎么优化?
- 对于更深入的场景,比如文档有语义或组织关系,召回的片段可能指向别的文档,怎么优化?
- 了解过 Agentic search 吗?
- ReAct 和 Plan-Execute 模式的区别是什么?
- 如果是比较复杂的场景,既需要 Plan-Execute,又需要 ReAct 及时感知进度或外界信息并做反馈调整,这种场景需要怎么设计?
- 项目是否拿到上线后的测试数据?
- 假设项目需要升级,要定位到具体出问题的代码,怎么做?
- 假设没有堆栈报错,怎么做?
- 现在需要做成通用平台或工具给所有业务使用,怎么设计这样一套工具?
- 怎么把人在排查问题中积累的经验给到系统?
- 大模型的工具调用能力是什么?
- MCP 和 Skill 的区别是什么?
- 介绍 CNN 和 Transformer 的区别。
- 为什么位置编码能够体现句子中分词的关系?
- 为什么说模型有上下文限制?
- 像 Claude 这类模型上下文窗口只有 200K,并不大,为什么不做得更大一些呢?
- 模型的参数量是什么时候定的?
- 为什么提供这么多不同参数量的模型?
- 像模型上层的 SFT、LoRA 这些微调,之前有做过吗?
- RL 和 SFT 的区别是什么?
- RL 的数据源从哪里来?
- 鸿蒙的 ArkTS 你觉得和安卓有什么区别?
- 它的整个应用启动链路是怎么样的?
面经 06 · 小红书 AI Agent开发岗(2026-03-31)
- 如果知识库的原始数据不是 markdown,而是 PDF、PPT、图片或者网页,你会怎么处理进 RAG 系统?
- 在 RAG 检索过程中,常用的检索机制有哪些?
- RAG 评价指标一般怎么设计?
- 为什么很多场景会优先选 RAG,而不是直接微调大模型?
- MCP 和 Function Call 的区别是什么?
- 为什么 AI 应用里经常需要做两级缓存?
- 如果要做一个智能客服类 AI 应用,整体链路怎么设计?
- 为什么有些场景会选 PGVector,而不是直接用 ES 做向量检索?
- MySQL 和 Elasticsearch 的区别是什么?AI 应用里怎么分工?
- 为什么 Elasticsearch 要使用倒排索引,而不是顺序扫描?
- Spring 框架里常用的注解有哪些?
面经 07 · 小红书 AI Agent开发岗(2026-03-31)
- 介绍一下项目。
- 项目有没有用户或者落地?
- 布隆过滤器的概念是什么?怎么解决缓存穿透?
- 如果有黑客通过肉鸡生成大量商品 id 攻击详情接口怎么办?发生误判怎么办?怎么过滤?
- 讲讲 APT 框架相关的内容。
- 怎么通过你这个框架把性能提高十倍?
- 是否考虑过 APT 能力的插件化设计,比如用装饰器增强日志采集和错误收集?
- 项目的前端模块是否全由 AI 开发?
- 有没有用 AI 实践过前端的工程化?
- 普通前端页面和工程化页面的区别是什么?
- AI 在工程化中的局限性是什么?
- 你说你参加过携程前端训练营,那你是怎么结合 AI 做前端项目落地的?
- 如果要把一个电商项目面向 AI 设计并 MCP 化,怎么做?或者说要做哪个方向?
- 电商场景下需要更精细的用户消费习惯设计,要结合用户画像和语义理解做搜索推荐,使用 MySQL 数据库是否合适?
- PG 数据库的横向扩展和 pg vector 能力更适合语义相似度检索,有没有深入了解过这方面或使用过?
- Agent 是否需要有读数据库的能力?
- Agent 调工具的实现方式有哪些?
- Skill 和 MCP 有什么区别?
- PE 全栈这个岗是做什么的?
- 面试表现怎么样?
面经 08 · 小红书 AI Agent开发岗(2026-03-31)
- 这个 Deep Research 是多轮检索,那你会进行到什么程度才停止?用什么判断?
- 你说有三类判断,那具体在使用过程中,这些判断的阈值是怎么设置的?
- 你们上下文是怎么管理的?
- 上下文是共享的对吧?具体会共享哪些信息?
- 现在的 Agent 是多 Agent 吗?具体是怎么设计的?
- 多 Agent 协同是通过什么机制实现的?
- 这些状态以及 Agent 之间同步的数据是存在哪里的?
- 这个平台只是内部员工用的,会需要这么复杂的架构吗?
- 这个 AI 平台是怎么部署的?
- 实际用的是哪家的大模型?
面经 09 · 小红书 AI Agent开发岗(2026-03-26)
- 为什么做开源社区内核开发?
- Rust 相比 C++ 的优劣势是什么?
- Rust 如何保证内存安全?
- Rust 与 Go / Python 的区别是什么?
- 进程、线程、协程的区别是什么?
- 用户线程与内核线程的调度开销有什么区别?
- 开发中怎么使用 AI?是否能辅助内核开发?
- 沉淀了多少个 skill?
- 这些 skill / agent 是怎么编排起来的?
- AI 翻车的场景与处理方式有哪些?
- AI 生成代码的可用率有多少?
- 如何进一步提升 AI Coding 效率?
- 哪些模型擅长什么事情?
- 如果给 Cgroup 做一个 Web 管理界面,你怎么设计前后端交互?
- 社区有哪些产品可以做 Agent 化改造?
- 手撕:写一个线程安全的 LRU。
- 未来方向规划是怎样的?
- 反问:您是哪个业务线的?实习生进去主要做什么?能否给一下这次面试评价?
面经 10 · 小红书 AI Agent开发岗(2026-03-24)
- 在这个产品的研发过程中,你承担了什么角色?主要完成了哪些任务?
- 从技术层面来讲,你在设计这个平台的 Multi-Agent 架构时是怎么设计的?
- 你提到有 Deep Research 能力还有推理能力,能详细介绍一下深度研究这部分吗?
- 这个 Deep Research 是多轮检索,那你会进行到什么程度才停止?用什么判断?
- 你说有三类判断,那具体在使用过程中,这些判断的阈值是怎么设置的?
- 你们上下文是怎么管理的?
- 上下文是共享的对吧?具体会共享哪些信息?
- 现在的 Agent 是多 Agent 吗?具体是怎么设计的?
- 多 Agent 协同是通过什么机制实现的?
- 这些状态以及 Agent 之间同步的数据是存在哪里的?
- 这个平台只是内部员工用的,会需要这么复杂的架构吗?
- 这个 AI 平台是怎么部署的?
- 实际用的是哪家的大模型?
- 会根据不同问题切换不同模型吗?
- 那你是怎么判断一个问题是简单还是复杂的?
- 这个意图识别是用什么模型实现的?
- 这个平台现在是什么状态?已经上线了吗?
《参考解析》
HashMap:数组分桶,链表与红黑树兜底
HashMap 内部是 Node[] table,下标由 key 的 hash 高 16 位与低 16 位异或后对长度取模,扰动是为了让高位参与运算、减少碰撞;数组里存的是链表或红黑树的头节点,所以数组只是分桶的骨架。put 先定位桶,空则直接放,否则遍历比较 hash 与 equals,命中覆盖、不命中尾插,链表到 8 且容量到 64 才树化(不到 64 先扩容);size 超过容量乘 0.75 就成倍扩容,元素只可能留在原位或搬到「原位加旧容量」,这正是长度取 2 的幂带来的便利。get 同样定位后沿链表或树比对,最好 O(1)、最差 O(log n)。追问点常在负载因子为什么是 0.75(空间与碰撞率的折中)、扩容为什么要重新计算下标、以及 1.7 头插在并发扩容下会成环把查询变成死循环。
并发安全:问题在复合操作,ConcurrentHashMap 靠 CAS 加桶级锁
两个线程同时对同一个桶做「读-改-写」就会丢数据,扩容时共享的 table 引用与链表指针被并发改写还会让结构损坏。Collections.synchronizedMap 和 Hashtable 用一把大锁把读也串行化了;ConcurrentHashMap 桶为空时用 CAS 插入、桶非空只对桶头节点加锁,扩容允许多线程协助迁移,size 用分片计数避免单点热点。追问会落到 CAS 与 Unsafe:CAS 是一条带 lock 前缀的原子指令,Java 通过 Unsafe 的 compareAndSwap 系列方法暴露出来,原子类与 AQS 的 state 更新都建立在它之上,代价是 ABA 问题、自旋开销、以及只能保证单个变量的原子性。其他锁要能横向铺开:自旋锁、偏向锁(新版 JDK 已废弃)、轻量级到重量级的升级路径,读写锁与 StampedLock 在读多写少下的优势,以及 ReentrantLock 基于 AQS 的可重入、公平与非公平、可中断、超时获取与条件队列——这些正是它比 synchronized 多出来的能力。
TLS 握手与中间人攻击
握手要做两件事:协商双方都支持的算法套件,并安全地生成只有两端知道的会话密钥。1.2 是两趟往返:ClientHello 带随机数与套件列表,服务端回 ServerHello、证书与 ECDHE 参数;客户端验完证书链用公钥加密 pre-master 发回,两端由两个随机数加 pre-master 推导主密钥,再互发 Finished 校验握手完整性。1.3 压到一趟往返,砍掉 RSA 密钥交换与弱套件,只保留前向安全的 (EC)DHE。中间人攻击成立的前提是客户端接受了攻击者签发的证书,所以防线是证书链校验(信任根、域名匹配、有效期、吊销状态)加主机名校验——客户端被装了自签根证书就破防,遇到证书告警直接放行等于把中间人请进门。追问常见的是前向安全为什么靠临时密钥(长期私钥泄露也解不开历史流量),以及 HTTPS 下仍可能被 DNS 劫持与内容注入攻破。
Agent 范式、RAG 的边界与上下文工程
范式要按「控制流在哪」讲:ReAct 想一步、做一步、看结果,适合目标明确但路径不确定;Plan-Execute 先出计划再逐步执行,适合步骤可预判、需要并行与成本可控;Reflection 在执行后自我批判再来一轮;把角色拆开就是 Multi-Agent。RAG 与 Agent 的区别一句话切开:RAG 是单轮把检索到的知识拼进上下文的固定链路,Agent 是带工具循环的决策器,检索只是它的一种工具;前者便宜、可缓存、可解释但只能答知识库里有的,后者灵活但延迟与 token 成本高、路径不可预测。MCP 与 Function Call 也不在一个层次:Function Call 是模型侧的能力,解决「模型怎么表达一次调用」;MCP 是工具侧的协议,解决「工具与资源怎么被发现、接入与复用」,支持 stdio 与 HTTP 等传输,所以它能跨应用共享,而函数调用通常与具体宿主绑定。多 Agent 场景还要回答「状态放在哪、怎么同步」:状态可以是内存里的共享对象、共享存储(数据库或缓存)或消息总线上的事件,共享越多协同越容易、耦合与冲突也越多,所以要按「只读可以共享、写入必须有明确归属」来划分;上下文则按任务隔离,只把子任务需要的片段传下去。模型路由不要靠模型自己「感觉」问题难不难——用可解释的规则(问题类型、上下文长度、是否要工具)加上小模型分类器或关键词路由,并留一条兜底链路,把「简单还是复杂」变成可观测、可回归的策略。上下文工程管的是有限窗口里放什么:常驻指令与约束、近期原文、历史摘要、按需检索片段、工具结果各占多少预算。summary 的常规做法是滑动窗口加分层结构化摘要,只保留结论、决策、待办与关键实体;压缩失真的缓解手段是把硬信息(ID、数字、路径、约束)强制写进摘要、把结论落到外部文件下一轮读回、压缩后让模型回读校验。Harness 工程与它不是一层:Harness 是模型外面那套运行骨架(循环、工具注册、重试、权限、日志与评测),上下文工程是骨架里专管窗口内容的那一层。
RAG 的分片、召回与评测
非 markdown 的原始数据要按格式分诊:PDF 先做版面分析(区分单双栏、表格、公式)再抽文本,扫描件走 OCR 加纠错;PPT 按页与文本框拆、保留标题层级;图片交给多模态模型生成描述;网页先做正文抽取、去掉导航与广告。统一原则是先保结构再切块,表格还原成结构化行、公式转 LaTeX,否则检索到的片段无法被正确理解。分片粒度的取舍是「查得准」与「答得全」的拉扯:太碎则语义不完整、指代断裂,太大则向量被稀释、还挤占上下文。常见做法是按标题层级、段落、代码块这类结构切并留少量重叠;更实用的是父子块——小块建索引做召回,命中后回溯到父块送进生成。召回机制要能铺开:BM25 保精确匹配、向量检索保语义泛化、两者融合做混合召回,再上路重排(交叉编码器逐对打分),最后按分数与预算截断 TOP K。评测分三层:检索层看 Recall@K、Hit@K、MRR、NDCG;生成层看答案正确性、忠实度、引用准确率与拒答率;系统层看时延、成本与线上反馈,前提是先有一套带标准答案与证据标注的小评测集。为什么优先 RAG 而不是微调:知识更新快时 RAG 只需重建索引、不必重训,还能给引用、按权限过滤、可灰度回滚;微调更适合对齐风格与固定技能,训练贵、知识写入不可控。实务上是「微调管行为、RAG 管知识」。两级缓存指本地缓存加分布式缓存,AI 应用里通常检索结果与最终回答各缓存一层,关键是缓存键要归一化问题并带上租户与权限维度。
检索与存储的分工:倒排索引、PGVector 与布隆过滤器
MySQL 是行式存储加 B+ 树索引、有事务与强一致,适合精确查询、状态变更与事务写入;ES 是倒排索引加列式 doc_values,擅长全文检索、多维过滤与聚合,弱在事务,所以 AI 应用里的常见分工是「MySQL 存事实、ES 存检索副本」,靠 binlog 异步同步并接受秒级延迟。倒排索引之所以比顺序扫描快,是因为它把「文档到词」翻成「词到文档列表」,查询时只在命中的倒排链上求交合并(跳表加速),代价与命中量相关而不是文档总量相关;顺序扫描要读全部文档逐个匹配,成本随数据量线性增长,无法满足毫秒级。PGVector 与 ES 的取舍看两件事:数据本来就在 PostgreSQL、量级中小、想少维护一套系统时选 PGVector(有事务、能用 SQL 过滤、支持 HNSW 等向量索引);需要大规模混合检索与横向扩展时选 ES 或专门的向量库,代价是多一套同步链路。布隆过滤器是一段位数组加多个哈希函数,能判定「一定不存在」但不能判定「一定存在」——有假阳性、无假阴性,所以放在缓存之前挡掉不存在的 key,缓解缓存穿透;假阳性的代价是一次无意义回源,可以通过加大位数组、按目标误判率算最优哈希个数来控制。被肉鸡刷大量不存在的商品 id 时,要叠加鉴权与频控、对不存在的 id 做带短 TTL 的空值缓存、按热度分片并定期重建过滤器。
大模型基础:位置编码、上下文窗口与训练阶段
CNN 与 Transformer 的差别是归纳偏置:CNN 把「局部相关、平移不变」写进结构,样本效率高但长依赖要靠堆层;自注意力让任意两位置直接交互、训练可并行,代价是随长度的平方复杂度与对位置编码的依赖。位置编码能体现分词间的关系,是因为自注意力本身置换不变,加了位置标签后注意力分数才同时依赖内容相似度与位置差;正弦编码里不同频率的分量让模型能学到相对位移,RoPE 直接在 Q、K 上做旋转使点积只依赖相对距离,外推性更好。上下文窗口做不大是成本问题:注意力的显存与计算随长度平方增长、KV 缓存线性膨胀,还要有大量长文本训练数据教会模型「用得上」,位置编码外推到超长又会掉点。参数量在设计阶段由层数、宽度、头数、词表等超参定死,提供多档是为了匹配算力与场景——大模型管复杂推理,小模型管高并发与私有化部署。SFT 用示范教模型「怎么答」,LoRA 冻结主干只训低秩矩阵、省显存易切换;RL 用奖励信号优化「答得好不好」,数据来自可自动判分的任务(数学、代码)与偏好对比。
Java 与服务端:GC、锁升级、订单号与注解处理
GC 按分代讲:新生代用复制算法,Eden 加两块 Survivor,存活对象来回复制并按年龄晋升老年代;老年代按收集器不同用标记-清除(CMS,低延迟但有碎片)、标记-整理(Parallel Old,无碎片但停顿长),或 G1、ZGC 这类区域化并发收集。碎片确实是标记-清除的代价:可用空间被切成许多小洞,大对象分配不下就触发 Full GC 甚至 OOM,所以延迟敏感的服务要选能整理或压缩的收集器,并控制大对象分配。轻量级锁自旋失败后,CAS 把对象头 Mark Word 换成指向 ObjectMonitor 的指针、升级为重量级锁,线程被挂起进等待队列由操作系统调度唤醒,代价是一次用户态到内核态的切换。订单号生成器要同时满足全局唯一与递增:雪花式的时间戳加机器标识加序列,或号段模式一次取一批号在本地自增,把数据库压力降到 1/N,同时处理时钟回拨与重启后的号段浪费。Spring 注解按用途记:组件声明、依赖注入、配置类与配置项、请求映射与参数绑定、事务与切面、条件装配与生命周期回调。APT 在编译期生成代码,把运行期反射换成编译期预处理(Bean 拷贝、序列化、路由表在编译期产出),启动更快、没有反射开销,代价是构建变慢、调试更绕;插件化的价值是让日志采集、错误收集这类横切能力以处理器形式挂上去,难点是处理器之间的顺序与命名冲突要显式约定。
Agent 评测、工具权限与注入防护
评测先分层:能力维度(准确性、指令遵循、工具调用正确率、时延与成本)、评测方式(规则断言、模型裁判加 rubric、人工抽检)、数据集来源(线上失败回流加自建集)。过程与结果之争的稳妥答案是「结果定成败、过程定归因」——上线看端到端成功率,出问题看 trace 定位是检索没召回、参数填错还是规划走偏。工具调用能力这块还要讲清「Agent 是否需要读数据库」:需要,但不能直连——用只读账号加白名单视图、把查询包装成受限工具(限定表、强制 limit、超时与行数上限),由模型产出查询、由程序校验后再执行,敏感字段脱敏;比让模型自由写 SQL 更稳的是暴露语义化的查询接口。调工具的实现方式有三种形态:函数调用(模型输出结构化意图、宿主执行,最轻)、MCP 这类标准协议(工具与资源抽象成服务端,便于跨应用复用)、以及工作流里写死的调用节点(最可控但不灵活)。降幻觉是组合拳:提高召回与重排质量、要求引用原文片段、给「不知道就说不知道」的出口;约束结构化输出、降低采样温度、做一致性校验;关键数字与实体直接从工具结果里取,不让模型复述。Prompt 注入的防线同样分层:把不可信内容用定界符标出并声明其中指令无效、对工具调用做权限与白名单校验、架构上最小权限、对越权取数做审计与限流——完全防住不现实,目标是压低成功率与影响面。