三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

小红书AI Agent一面凉经 !!!

小红书AI Agent一面凉经 !!!

面了70分钟,从Agent架构问到JVM类加载,最后扔一道算法题。我人没了。

上周面了小红书的AI Agent岗位。投的时候以为是聊Agent、聊LLM、聊Prompt优化,结果面试官后半程画风一转——Java线程池、MySQL两阶段提交、JVM类加载全给安排上了。直接裂开。

嗯,把还记得的21道题整理出来,答案也一并写了。希望对准备类似岗位的朋友有点帮助。

  1. 简单介绍一下自己的经历,以及为什么选择AI Agent方向?

这个问题基本是开场必问。别背简历,面试官想看的是你的思考过程。

我的回答思路:把经历串成一条线——之前做后端开发时遇到了哪些自动化难题,当时用传统规则引擎解决,但随着业务复杂度的上升发现规则根本维护不动。后来接触到LLM,发现用自然语言做任务拆解和决策的思路很自然,就转了Agent。

标准答案参考:AI Agent的核心价值在于它赋予了LLM与外部世界交互的能力。传统LLM只是被动回答问题,而Agent能主动调用工具、执行计划、完成复杂任务。选择这个方向是因为我认为下一代应用形态一定是“能做事”的模型,而不是“能聊天”的模型。从技术角度看,Agent涉及规划、记忆、工具调用、多智能体协作等多个维度,每个维度都有足够深的技术挑战。

  1. 平时开发过程中主要使用哪些AI Coding工具?比如Claude Code这类工具,通常有哪些使用习惯?

问这个是想看你是不是真的在用,还是停留在“听说过”。

我的回答:Claude Code和Cursor都在用。习惯上不会直接让它写完整模块,而是把大任务拆成小函数,逐个让它生成或重构。写之前会给清楚输入输出格式、边界条件,有时候还会故意给个错误示例告诉它“别这样写”。

标准答案参考:AI Coding工具的核心价值在于提升编码效率,但使用方式直接影响效果。比较好的实践包括:① 分而治之,单个Prompt控制在单一函数或类层面;② 提供充足上下文,包括相关代码路径、数据结构定义、已有接口签名;③ 迭代式优化,先让AI生成初版,再通过多轮对话逐步修正;④ 对生成的代码做Code Review,AI也会产生逻辑漏洞,尤其是在并发和异常处理上。

  1. 如何理解Spec Coding和Harness?你认为Harness为什么能够提升Agent完成复杂任务的能力?

这个问题答得一般,说实话平时更多是在业务里用Agent,对Harness的研究不够深。回来查了不少资料。

Spec Coding:先把任务写成一份结构化的规格说明(Spec),包含输入格式、输出格式、约束条件、验收标准。Agent照着Spec干活,而不是自由发挥。

Harness:可以理解为一个“Agent运行沙箱”。它把Agent的执行环境、工具集、上下文、日志全部封装起来。

Harness提升复杂任务能力的三个原因

  • 约束执行空间:不让Agent乱跑,每一步都在边界内。
  • 可观测性:每个中间步骤都被记录,方便定位失败点。
  • 反馈闭环:Agent执行完一个子任务后,Harness能自动校验结果是否符合预期,不符合就触发修正。

其实就是把Agent“关进笼子里训练”,容错率反而更高了。

  1. 如果让你从零开始设计一个Agent系统,你认为需要包含哪些关键模块?

面试官想看的不是背八股,而是你真正设计过系统。

我的回答:四个核心模块——感知模块(接收用户输入、解析意图)、规划模块(把大任务拆成子任务、决定调用哪些工具)、执行模块(实际调用工具/API、处理返回结果)、记忆模块(短期存对话上下文、长期存用户偏好和历史知识)。另外还需要一个监控层,记录每一步的输入输出,方便debug。

标准答案参考

Agent系统核心模块架构├── 感知层 (Perception)│ ├── 输入解析器:意图识别、实体抽取│ └── 上下文组装器:融合历史记忆和当前输入├── 规划层 (Planning)│ ├── 任务分解器:将复杂任务拆解为子任务DAG│ └── 决策引擎:基于当前状态选择下一步动作├── 执行层 (Execution)│ ├── 工具调用器:统一接口调用外部API│ └── 结果处理器:解析并标准化返回结果├── 记忆层 (Memory)│ ├── 短期记忆:对话上下文、当前任务状态│ └── 长期记忆:向量数据库、知识图谱└── 监控层 (Observability) ├── 链路追踪:记录每一步的输入输出 └── 异常告警:超时、重试、失败率监控
  1. Agent在执行任务时,如果调用外部工具或API出现超时、异常等情况,一般应该如何设计容错机制?

我的回答:说到了超时重试、指数退避、熔断器模式,还提到了需要区分“可重试异常”(如网络抖动)和“不可重试异常”(如认证失败)。

标准答案参考

容错机制设计可以从这几个层次入手:

  • 超时控制:为每次API调用设置合理的超时时间,不同接口超时阈值不同。
  • 重试机制:采用指数退避重试,避免雪崩。一般重试3次,间隔 2^i 递增。
  • 降级策略:主API不可用时切换备用方案,如主模型超时则换小模型快速响应。
  • 熔断器:错误率达到阈值后直接熔断,快速失败返回兜底话术。
  • 异常分类:区分临时性错误(网络超时、限流)和永久性错误(参数错误、认证失败),只有临时性错误才重试。
# 简易重试逻辑def call_with_retry(func, max_retries=3): for i in range(max_retries): try: return func() except TimeoutError: wait = 2 ** i # 指数退避 time.sleep(wait) except AuthError: raise# 不重试 raise Exception("Max retries exceeded")
  1. 是否考虑过让大模型参与错误分析和自动恢复?这种方案有什么优缺点?

我的回答:考虑过,但生产环境不太敢用。优点是灵活,大模型能理解各种奇怪的错误信息并给出修复建议;缺点是稳定性差,模型可能误判,最坏情况是把一个本可简单恢复的错误搞得更复杂。

标准答案参考

优点

  • 错误信息是非结构化的,传统规则很难覆盖所有情况,大模型的理解能力强。
  • 能提供修复建议,而不只是报错。

缺点

  • 大模型自身的幻觉问题,可能给出错误的分析结论。
  • 自动恢复操作有风险,比如误删数据或错误地重试了非幂等操作。
  • 额外调用大模型会增加成本和延迟。

折中方案:让大模型做错误分析和建议,但最终决策由人工或预设规则执行。或者只在低风险场景(如对话体验优化)中启用自动恢复,高风险操作(如数据库写入)必须人工确认。

  1. Agent中的短期记忆和长期记忆分别有什么作用?通常会如何实现?

我的回答:短期记忆存当前会话的上下文,保证多轮对话的连贯性;长期记忆存用户画像、历史行为、知识库。短期用Redis或内存缓存,长期用向量数据库加Embedding检索。

标准答案参考

短期记忆

  • 作用:维持当前任务的状态,记录已经完成哪些步骤、下一步要做什么。
  • 实现:会话窗口(Sliding Window),保留最近N轮对话;或者用Redis缓存当前会话的完整上下文。

长期记忆

  • 作用:跨会话的知识沉淀,比如用户的偏好设置、之前解决过的问题。
  • 实现:向量数据库(如Pinecone、Milvus)存储Embedding,配合语义检索召回相关内容。也可以结合传统数据库存储结构化信息。

两者配合的关键在于检索时机——不是每次对话都查长期记忆,而是先由Agent判断“这个任务是否需要历史知识”,再做检索,节省Token。

  1. 在Agent开发过程中,上下文为什么需要进行压缩?压缩后可能导致信息缺失,应该如何解决?

我的回答:主要原因是大模型的上下文窗口有限,长对话或复杂任务容易爆窗口。压缩的常见方法有摘要和剪枝。

标准答案参考

为什么需要压缩

  • 成本:Token越多,调用成本越高。
  • 速度:输入越长,推理延迟越大。
  • 窗口限制:虽然现在模型上下文已经很大(如200K),但超长上下文的推理效果会下降。

压缩方法

  • 摘要压缩:用LLM对历史对话生成简短摘要。
  • 剪枝:去除冗余信息,比如重复的中间步骤。
  • 向量检索替代:不把全部历史塞进上下文,而是按需检索相关内容。

信息缺失的解决

  • 分层记忆:保留完整的原始日志,压缩的只是传入LLM的部分。如果发现信息不足,可以回溯原始日志。
  • 重要性评分:对每条信息打分,压缩时优先保留高分信息。
  • 渐进式披露:先给模型一个摘要,如果模型判断需要细节,再通过工具调用获取完整内容。
压缩前:[完整对话 50轮 + 工具调用记录 + 中间推理步骤] → 超长压缩后:[摘要:用户想订机票,已选好航班,等待支付] → 短信息缺失风险:支付方式偏好、用户特殊要求等细节可能丢失解决方案:关键信息用结构化字段单独提取,不与摘要混在一起
  1. Prompt优化除了添加规则约束之外,还有哪些常见的方法?你在实际使用中有哪些经验?

我的回答:Few-shot示例、结构化输出约束(JSON Schema)、思维链、角色设定、动态Prompt拼接。实际中最管用的是Few-shot,给两个高质量示例比写一堆规则效果好得多。

标准答案参考

  • Few-shot / In-context Learning:给2-3个高质量示例,比写规则更有效。示例要覆盖边界情况。
  • Chain-of-Thought(CoT):引导模型一步步推理,而不是直接给答案。
  • 结构化输出约束:指定输出格式(JSON Schema、XML标签),方便后续解析。
  • 角色设定(System Prompt):限定Agent的人格和知识边界,比如“你是一个MySQL专家,只回答数据库相关问题”。
  • 动态Prompt:根据任务类型动态拼接不同的Prompt片段,避免单一Prompt太臃肿。
  • 自我纠错指令:在Prompt里要求模型在不确定时主动说明,而不是瞎编。

实际经验:规则写太多反而让模型畏手畏脚,容易拒绝正常请求。通常保留3-5条核心约束,剩下的用示例来暗示效果更好。

  1. 当模型出现幻觉问题时,一般有哪些解决思路?

我的回答:幻觉的本质是模型在“猜”答案而不是“查”答案。解决思路分两条线——一是限制模型自由发挥,强制它引用外部知识源;二是在后置环节做校验,对明显不合理的输出进行拦截。

标准答案参考

  • RAG(检索增强生成):让模型基于检索到的外部文档回答,不要依赖参数化知识。关键是检索质量要高。
  • 约束解码:用JSON Schema或正则表达式约束输出格式,减少自由文本生成中的幻觉。
  • 自我一致性:多次采样,对多次生成结果取交集或投票。
  • 事实校验:对模型输出的关键事实,用外部工具(如搜索引擎、数据库查询)交叉验证。
  • 不确定性表达:要求模型在低置信度时明确说出“我不确定”,而不是强行回答。

  1. 如果Token消耗突然增加,你会如何定位原因并进行优化?

我的回答:先看是单次调用Token变大(Prompt太长或输出太长),还是调用次数变多(任务变复杂、有循环)。用日志分析工具统计Token分布,定位到具体环节后再针对性优化。

标准答案参考

定位步骤

  1. 分维度统计:按任务类型、时间段、用户、Agent版本等维度拆分Token消耗。
  2. 检查Prompt长度:是不是某个场景下拼接了过长的上下文或知识库内容。
  3. 检查输出长度:模型是不是在生成冗余信息(如重复解释)。
  4. 检查调用次数:是不是进入了死循环或过度规划。

优化手段

  • Prompt压缩:去除冗余指令,合并重复约束。
  • 输出长度限制:用max_tokens参数强制限制。
  • 缓存机制:对相同或相似的Query,缓存之前的回答。
  • 模型降级:简单任务用小模型,复杂任务才用大模型。
  • 工具调用精简:减少不必要的工具调用,合并多个操作为一个调用。
  1. 你有没有设计过Agent Skill?一个Skill从设计到上线通常需要考虑哪些因素?如何判断效果好坏?

我的回答:实际项目中设计过类似插件。关键考虑因素包括Skill的职责边界、输入输出Schema、错误处理、调用频率限制。

标准答案参考

设计阶段考虑

  • 职责单一:一个Skill只做一件事,不要大而全。
  • 输入输出Schema:明确定义参数类型、必填/可选、格式约束。
  • 异常处理:Skill内部异常要优雅降级,不能拖垮整个Agent。
  • 幂等性:同一个请求多次调用结果一致,尤其是涉及写操作的Skill。
  • 超时设置:不同Skill的超时阈值不同,查询类可长一点,写操作类要短。

上线考虑

  • 版本管理:Skill升级要兼容旧版调用方式。
  • 灰度发布:先小流量验证,再全量。
  • 监控告警:成功率、延迟、调用量三个核心指标。

效果判断

  • 客观指标:调用成功率、平均响应时间、Token消耗。
  • 主观指标:用户反馈、任务完成率。
  • 对比测试:有Skill和无Skill的完成质量差异。
  1. 介绍一下之前做过的相关项目,这个项目是完全自主开发,还是基于已有开源方案进行改造?

如实回答就好,关键是要说清楚哪些是自研、哪些是借鉴、自己的贡献是什么。

我的回答:项目是基于开源框架(LangChain)做的二次开发,但核心的调度逻辑和多Agent协作协议是自研的,因为开源方案在任务编排上不够灵活。

面试官关注点:不是考你“能不能造轮子”,而是看你有没有技术判断力——什么场景该自研、什么场景该复用。如果每个项目都从零开始写,反而是减分项。

  1. 在项目过程中遇到过哪些比较困难的问题?你主要负责哪些部分?最后取得了什么结果?

又是老生常谈的“项目难点”问题,但Agent项目确实有些特殊的坑可以讲。

我的回答:最头疼的是多Agent协作时的死锁问题——Agent A等Agent B的结果,Agent B又在等Agent A。解法是引入超时机制和优先级调度,超时未返回的Agent直接跳过,由主Agent做兜底决策。

标准回答框架:问题是什么 → 当时怎么想的 → 尝试了什么方案 → 最终怎么解决的 → 量化结果。

  1. Java线程池的核心参数有哪些?线程提交任务后的执行流程是怎样的?

从这里开始画风突变,从AI Agent直接跳到Java基础。

我的回答:七个核心参数——corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler。提交任务后的流程是:核心线程数未满则新建线程执行,满了则入队,队列满了则新建非核心线程,线程数达到最大值则触发拒绝策略。

标准答案参考

// Java线程池核心构造参数public ThreadPoolExecutor( int corePoolSize, // 核心线程数 int maximumPoolSize, // 最大线程数 long keepAliveTime, // 空闲线程存活时间 TimeUnit unit, // 时间单位 BlockingQueue<Runnable> workQueue, // 任务队列 ThreadFactory threadFactory, // 线程工厂 RejectedExecutionHandler handler // 拒绝策略)

执行流程

  1. 如果让你重新设计一个线程池,你会重点考虑哪些问题?

我的回答:这个问题考察的是对线程池本质的理解,而不是背参数。核心问题是“线程数设多少”。IO密集型和CPU密集型的线程数配置差异很大。

标准答案参考

  • 线程数动态调整:根据系统负载自动调整线程数,而不是固定值。可以基于CPU利用率、队列深度等指标动态扩缩。
  • 任务分类隔离:不同类型的任务(IO密集型 vs CPU密集型)使用不同的线程池,避免互相影响。
  • 队列策略选择:有界队列防OOM,但无界队列可能堆积任务,需要根据场景权衡。
  • 优雅关闭:shutdown()和shutdownNow()的合理使用,确保任务能安全终止。
  • 可观测性:线程池的活跃线程数、队列大小、完成任务数等指标需要暴露出来。

线程数配置公式

  • CPU密集型:线程数 = CPU核数 + 1
  • IO密集型:线程数 = CPU核数 * (1 + 等待时间/计算时间)
  1. JVM加载一个class文件的完整过程是什么?

我的回答:加载 → 验证 → 准备 → 解析 → 初始化,五个阶段。面试官追问了“准备阶段做了什么”,回答是给类变量分配内存并设置初始值(不是赋值)。

标准答案参考

加载:通过全限定名查找并加载class文件,生成Class对象。

验证:确保class文件的字节流符合JVM规范,防止恶意代码。

准备:为类变量(static变量)分配内存,并设置默认初始值(int为0,引用为null)。注意不是赋值阶段,赋值在初始化阶段。

解析:将常量池中的符号引用替换为直接引用(内存地址)。

初始化:执行类构造器<clinit>方法,初始化静态变量和静态代码块。

  1. MySQL中的undo log、redo log和binlog分别解决什么问题?它们之间有什么区别?

我的回答:undo log做事务回滚和多版本并发控制(MVCC),redo log做崩溃恢复(保证事务持久性),binlog做主从复制和数据恢复。

标准答案参考

undo logredo logbinlog
层次InnoDB存储引擎层InnoDB存储引擎层MySQL Server层
作用事务回滚、MVCC(多版本并发控制)崩溃恢复(保证持久性)主从复制、数据恢复
内容逻辑日志,记录数据变更前的旧值物理日志,记录数据页的物理修改逻辑日志,记录SQL语句或行变更
写入时机事务执行过程中写入事务执行过程中写入(WAL机制)事务提交时写入
循环/追加循环写入循环写入追加写入
  1. 什么是MySQL两阶段提交?为什么需要这个机制?

我的回答:两阶段提交是保证redo log和binlog数据一致性的机制,分Prepare阶段和Commit阶段。如果不做两阶段提交,数据库崩溃恢复后可能出现主从数据不一致。

标准答案参考

两阶段提交(2PC)发生在事务提交时:

为什么需要2PC:因为redo log和binlog是两个独立的日志,写入时机不同。如果只写redo log不写binlog,主从同步会丢数据;如果只写binlog不写redo log,数据库崩溃后事务无法恢复。两阶段提交确保要么两个日志都写成功,要么都不算成功。

  1. 算法题:合并两个有序数组

LeetCode 88题,经典双指针。面试时写出来了,但因为在前面Java和MySQL花了太多精力,写的时候思路有点卡。

标准答案

public void merge(int[] nums1, int m, int[] nums2, int n) { int p1 = m - 1; int p2 = n - 1; int p = m + n - 1; while (p1 >= 0 && p2 >= 0) { if (nums1[p1] > nums2[p2]) { nums1[p] = nums1[p1]; p1--; } else { nums1[p] = nums2[p2]; p2--; } p--; } // nums2剩余元素直接copy while (p2 >= 0) { nums1[p] = nums2[p2]; p2--; p--; }}
  1. 反问环节

问了一个问题:Agent方向的工程落地和前沿研究,这个岗位更侧重哪个方向?

面试官说两者都涉及,但当前阶段更关注工程落地能力——能稳定、高效地把Agent系统部署到生产环境,比单纯追求SOTA模型更重要。

这个回答其实也解释了他为什么后半程全在问Java和MySQL——Agent系统的稳定性严重依赖后端基础设施。

学AI大模型的正确顺序,千万不要搞错了

🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!

有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!

就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇

学习路线:

✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经

以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!

我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

← 返回列表