面完出来我在地铁上坐过了三站。不是难过,是脑子被掏空之后的那种呆滞。面试官揪着“记忆”这一个点,换了六种姿势盘问我,我差点以为自己没长脑子。

  1. 先说下背景

面的岗位是 Agent开发,方向是大模型应用落地。

面试官是典型的技术流,说话不快,但每个问题都像手术刀——先切进去,再搅一搅,看看你到底是真懂还是背的

最折磨人的是第7题,他问我“第11轮怎么处理总结”,我答完,他沉默了两秒,又换个方式问“那前10轮就不管了吗”,我补答,他又问“那你这总结是增量还是全量”……同一个坑,他看我掉进去三次

不废话了,上硬菜。

  1. 简单讲讲你的Agent项目?

基于大模型实现 ReAct 模式下的自主规划能力,解决长线任务,学习检索与记忆规划。

我的项目核心就是 ReAct 框架。ReAct 不是让模型一次性吐答案,而是把它塞进一个 **“思考→行动→观察”**的循环里。

实际工程里,这个循环是在代码里用 while实现的,每次循环把 Thought + Action + Observation拼成新的上下文喂给模型,直到模型输出 Final Answer或者达到最大步数限制。每一步的 Observation 都是真实环境的反馈,不是模型瞎编的——这就保证了长线任务的可靠性。

  1. 短期记忆的具体实现方式是什么?

这个问题面试官问得很细。短期记忆在工程上就是上下文窗口里当前正在用的那坨东西

我采用 **“滑动窗口 + 触发式总结”**策略:

  • 设定一个 Token 上限阈值(比如模型窗口是 16k,我设 12k 为警戒线);
  • 上下文里始终保留 System Prompt + 最近 2~3 轮完整对话
  • 一旦总 Token 超过警戒线,把历史对话丢给一个轻量级总结模型(或者用主模型自己总结),生成一段 200~300 Token 的摘要;
  • 然后把摘要塞进上下文,替换掉那些被总结的早期轮次。

这里有个细节:总结不是把对话“翻译”一遍,而是抽取关键信息——用户的目标是什么、已经完成了哪些步骤、当前卡在哪、有哪些重要约束。这样才能保证后续对话不跑偏。

  1. 什么叫“快到上限了”?对话是怎么逐步叠加的?

“快到上限”指的是 上下文当前累积的 Token 数逼近了模型接口的硬限制或者你自己设置的安全水位

对话的叠加逻辑,很多初学者会以为是“覆盖”,其实是 “追加”

轮次 1: [System] + [User_1] + [Assistant_1]       → 假设 1500 Token轮次 2: [System] + [User_1] + [Asst_1] + [User_2] + [Asst_2]  → 3000 Token轮次 3: ... 继续追加                                       → 4500 Token

每一轮都是把新产生的 query 和 response 拼接到已有上下文的末尾,然后整个包裹一起发给模型接口。模型没有“记忆”能力,它每次看到的都是这个拼接后的完整字符串。

所以如果一轮对话里工具调用特别多(比如调了 5 个工具,每个返回 500 Token 的日志),那这一轮可能直接吃掉 3000 Token,很快就把窗口撑爆。

  1. 如果对话轮次过多,你怎么去做优化?

我当时给了三层方案,面试官听完点了点头——但他后面绕着我这个方案又问了四五个问题,明显是觉得我“说得漂亮但经不起推敲”。

我的三层设计是:

Layer 1(System):包含角色设定、工具定义、输出格式约束。这部分绝对不能动,一动 Agent 的人设就崩了。

Layer 2(近期窗口):最近 2~3 轮完整对话,确保模型对“当前在干什么”有精准感知。为什么是 2~3 轮?因为大多数多步任务的核心上下文就在最近几轮里,再往前的已经被执行完了。

Layer 3(历史摘要):把更早的对话压缩成一个“进度报告”,包含已完成目标、未完成目标、关键中间结果。

  1. 什么时候去触发这个总结动作?

面试官开始绕我了。他反复问“什么时候”,但我后来才明白,他想问的是触发条件的具体数值策略和触发后的原子操作

触发条件有两个维度:

**条件一:阈值触发。**我用 双阈值策略——硬阈值(接口上限的 90%)和软阈值(接口上限的 70%)。到达软阈值时,异步生成摘要并缓存;到达硬阈值时,同步阻塞当前对话,强制完成总结后再继续。同步阻塞会影响用户体验,所以软阈值提前准备是关键。

**条件二:步数触发。**当工具调用步数超过 5 步还没出结果,说明任务在绕远路,强制总结一次,帮模型“抬起头来看方向”。

触发之后的操作不是简单调个 API——要把当前上下文完整拷贝一份,在副本上做总结,然后原子性地替换上下文中的历史部分。绝对不能在线程里改到一半就发请求,否则并发场景下数据全乱。

  1. 是每一轮对话都要去做总结吗?

绝对不是。

每一轮都做总结的话,你会遇到三个问题:

  1. 计算开销爆炸:每次总结都是 1 次 LLM 调用,对话到 50 轮的时候你就得调 50 次额外的 LLM,成本直接翻倍;
  2. 信息衰减加速:摘要再摘要,信息损失是指数级的。第一轮总结可能保留 80% 信息,第二轮总结可能只剩 60%,到第五轮基本就剩“用户问了点啥”;
  3. 延迟不可接受:用户每说一句话都要等 2~3 秒的总结时间,产品直接凉了。

只在触发条件满足时才做——平时就是老老实实做追加。

  1. 假设已进行 10 轮并做了总结,第 11 轮开始时,总结怎么处理?是重算前 11 轮还是叠加?

这个问题我当时卡了两秒——因为我确实没仔细设计过这个场景。

正确做法是 “增量叠加,而非全量重算”

第 10 轮结束时,你有一个摘要 S_1-10,它已经消耗了比如 300 Token。第 11 轮的新对话 D_11有 800 Token。第 11 轮开始时,你直接把 S_1-10 + D_11拼在一起发给模型。

不是把 1~11 轮全部拿出来重新总结一遍。全量重算的时间复杂度是 O(n²),而且耗费的 Token 是增量方式的 10 倍以上。

但这里有个陷阱:如果 S_1-10本身已经占了 300 Token,加上 D_11又到了阈值,第 12 轮要触发新总结时,你需要S_1-10 + D_11做一次新的总结,生成 S_1-11,然后丢弃 S_1-10——这本质上是一个分层摘要树,每一层都是对上一层的压缩。

  1. 如果前 10 轮都变成了总结,那之前的原始上下文就不需要了吗?

面试官问这个问题的时候,我差点掉坑里——我说“不需要了”,他眉头一皱。

其实原始上下文必须持久化存储,但不发送给模型

存到数据库里的原始数据有什么用?

  • 审计溯源:当模型给出错误答案时,你得能回放“它当时看到了什么”;
  • 摘要重建:如果发现摘要质量太差,可以重新生成,不用从零开始积累;
  • 长期记忆检索:用户的某句关键指令可能在摘要里被压缩丢了,但原始数据里还有,后续按需检索能找回来。

发给模型的永远只是那个压缩后的摘要 + 最近几轮。

  1. 长期记忆可以按需检索召回,具体在什么情况下需要检索?

这个问题我答得不好,只说了“意图路由”。复盘一下:

长期记忆检索的触发时机取决于 “当前问题对历史信息的依赖程度”

我在项目里没做知识图谱,所以跨实体的复杂推理检索确实是我的短板。如果做了知识图谱,还能支持“用户 A 在 3 天前提到过的那个项目,和今天这个需求有什么关联”这类高阶检索。

  1. 每轮对话都要注入记忆吗?长短期记忆是同时注入吗?

都不是。

短期记忆是常驻上下文——每一轮都在,不需要额外“注入”,它就在那儿。

长期记忆是按需动态注入——先走意图路由,路由判断“需要查历史”时,才去向量库检索 Top-K,把检索结果作为前缀拼到当前上下文里。

如果同时注入长短期记忆,那上下文里会塞满无关信息。比如用户问“给我订个外卖”,你同时把三个月前的聊天记录也塞进去,纯属浪费 Token 而且增加干扰。

  1. 如何减少工具过多带来的 Token 消耗?

这是一道很实战的题。工具多了,工具描述(schema)本身就能吃掉你一半的上下文

举个例子,一个完整的工具定义(带参数 JSON Schema)通常 200~5000 Token,如果你有 30 个工具,光 tool descriptions 就占 6000~15000 Token,留给对话的就所剩无几了。

我的方案是 “意图识别 + 渐进式披露”

关键数据:50 个工具,用完整加载需要 50 × 400 = 20000 Token。用渐进式披露,第一轮只消耗 50 × 20 = 1000 Token,第二轮加载 3 个完整 Schema 消耗 3 × 400 = 1200 Token。总计 2200 Token,节省了 89%

而且这个方法还有额外好处:模型在第一步看到的是精简列表,选择工具的准确率反而上升了——因为干扰项少了,注意力更集中。

  1. 你的 RAG 是用什么技术实现的?

标准的 RAG 链路,但每一步都有工程细节:

  1. 文档预处理:按语义边界切分(不是暴力按 500 字切),用 RecursiveCharacterTextSplitter保留段落完整性,chunk size 512,overlap 64;

  2. Embedding 模型:用的是 BGE-large-zh-v1.5,1024 维,对中文语义支持好;

  3. 向量索引:存到 Milvus 里,建 IVF_FLAT 索引,平衡速度和召回;

  4. 检索:query embedding 后用余弦相似度召回 Top-20;

  5. Rerank:用 BGE-reranker-v2 对 Top-20 做精细排序,取 Top-5 送入 LLM;

  6. 生成:把 Top-5 的原文拼接成上下文,加上“如果你不知道就说不知道”的 instruction,送进主模型。

  7. 如何判断向量的相似度?


我用 余弦相似度

公式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本质是计算两个向量在高维空间里的夹角余弦值,值越接近 1 说明方向越一致,语义越相近。

  1. 除了余弦相似度,还了解其他相似度算法吗?

欧几里得距离

公式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

值域 [0, +∞),越接近 0 越相似。

  1. 听不懂,说人话?

面试官这句话直接把我整不会了。他让我“说人话”解释余弦相似度。

我当时有点慌,说“反正 RAG 用余弦就对了”——这个回答不合格

正确的“人话”解释应该是:

**你把每个文本想象成高维空间里的一根箭。余弦相似度不看这根箭有多长,只看它指向的方向。两根箭指向越接近同一个方向,它们的意思就越像。**比如“猫”和“老虎”这两根箭方向很近,但“猫”和“汽车”的方向就岔开了。RAG 里我们只关心“意思像不像”,不关心“词多不多”,所以用看方向的余弦,不用看距离的欧氏。

  1. 余弦相似度与欧几里得距离在工程应用中的具体区别是什么?

这道题我跪得最彻底。回来之后我把数学彻底补了一遍。

核心差异不是“一个看方向一个看距离”这么简单——真正的关键在于 Embedding 向量在训练时已经被归一化了。

绝大部分 Embedding 模型(包括 BGE、OpenAI Ada)输出的向量都是 L2 归一化的——也就是每个向量的模长 ||V|| = 1

在归一化前提下,余弦相似度和欧氏距离是数学等价的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所以当你用归一化向量时,按余弦排序和按欧氏排序的结果完全一样

那为什么业界都选余弦不选欧氏?

余弦相似度 欧几里得距离
对向量模长敏感吗 不敏感 敏感
在归一化场景下 等价于点积,计算最快 需要开方,略慢
直观理解 “语义方向是否一致” “空间位置是否接近”
高维稳定性 相对稳定 易受维度灾难影响

工程上选余弦的真正原因:余弦相似度在未归一化场景下也能工作,而欧氏在未归一化场景下会被模长差异主导,导致“高频词向量”永远比“低频词向量”距离更近。为了安全,大家都用余弦。

  1. 项目中一共使用了几个模型?分别是什么?

4 个

  1. Embedding 模型(BGE-large-zh):1024 维,把文本转稠密向量,用于 RAG 索引和检索;
  2. 路由分类模型(BERT-base 微调):轻量级 110M 参数,跑意图识别——因为它太小了,可以做到毫秒级响应,不占用主模型的宝贵上下文;
  3. 主 LLM(Qwen-72B 或 Claude 3.5):负责所有推理、规划、生成;
  4. Rerank 模型(BGE-reranker-v2):Cross-encoder 结构,对召回的 Top-20 做精细打分。

分工明确:小模型干脏活累活(路由、向量化),大模型干脑力活(推理生成),Rerank 做连接器。

  1. 如何控制模型的幻觉问题?

我当时答非所问了,说“看 RAG 召回准确性”。回来把完整防御体系梳理出来了:

分层解释

  • 输入层:RAG 检索到的文档质量是防幻觉的根本。如果召回的都是垃圾,模型再怎么约束都白搭。所以 Rerank 那一步至关重要。
  • 推理层:温度调低到 0.1~0.3,减少模型的“创造性发散”。用 Chain-of-Thought 强制模型在输出最终答案前先写“推理过程”——一旦推理过程出现矛盾,可以在后处理里拦截。
  • 上下文层:System Prompt 里明确写“如果上下文中没有明确信息,直接回答‘我不知道’,不要编造”。实测这句话能降低 30% 的幻觉。
  • 输出层:要求模型在回答中标注引用来源 [Doc_3],后处理里校验这个 Doc_3 是否真的在上下文中。如果引用了不存在的文档,直接拒答。
  1. 如何观察模型召回了哪些块?

这就是 RAG 的可观测性

我在项目里做了一个 “检索审计日志”,每次 query 都记录四样东西:

  1. Query 原文;
  2. 向量检索召回的 Top-20 文档 ID 及其 cosine 分数;
  3. Rerank 之后的 Top-5 文档 ID 及其 rerank 分数;
  4. 最终拼进上下文的那 5 段原文。

有了这个日志,线上如果出了 bad case,可以直接回放:是检索没召回到相关文档(召回率问题)?还是召回了但 rerank 排下去了(排序问题)?还是召回了也排上去了但模型没用好(生成问题)?

三层归因,一层层查。

  1. 简历别的项目随便问了问主要工作

常规的 STAR 法则介绍,没展开。面试官明显对 Agent 那块更感兴趣。

  1. 算法题:Leetcode 143. 重排链表

这是全场的翻车点,我自愿认领。

题目:L0 → L1 → ... → Ln重排为 L0 → Ln → L1 → Ln-1 → ...

我的骚操作:先把链表节点存到 Python 列表里,然后双指针取数,再重新串起来。

写到一半,面试官探头看了一眼屏幕:

“你这是用数组解的。这题考的是链表原地操作,你偷懒了吧。”

当场社死。

正确的 O(1) 空间解法分三步走:

def reorderList(head):    if not head or not head.next:        return        # 第一步:快慢指针找中点    slow, fast = head, head    while fast and fast.next:        slow = slow.next        fast = fast.next.next        # 第二步:反转后半段    prev, curr = None, slow    while curr:        nxt = curr.next        curr.next = prev        prev = curr        curr = nxt        # 第三步:交替合并    first, second = head, prev    while second.next:        tmp1, tmp2 = first.next, second.next        first.next = second        second.next = tmp1        first, second = tmp1, tmp2

为什么不能用数组?因为这题考察的是链表指针操作能力——找中点(快慢指针)、反转(三指针)、合并(指针交错)。用数组把节点存起来,复杂度虽然也是 O(n),但面试官要看的是你操作指针的手艺,不是 Python 列表的 API 熟练度

更惨的是,输入输出全得自己写。我花了 20 分钟建链表、写打印函数,最后跑起来还报错。早知道直接跟面试官坦白“我不太熟链表的输入输出构造”,说不定还能混个思路分。

  1. 你平时调试代码怎么调试的?

我说“断点 + AI”。

  1. 不对吧,最简单的方式不是打印一下吗?

面试官一句话把我点醒了:

“你把你写的代码打印一下,不就能找哪个地方出问题了吗?”

他说得对。Print debugging 是最原始最有效的手段,尤其在算法题这种单文件场景下。我发现自己被 AI 惯坏了——遇到 bug 第一反应是“贴给 AI 帮我看”,而不是自己加几行 print追变量。

两种场景:

  • 业务工程:断点 + 日志系统 + AI 辅助;
  • 算法题/脚本:print 是王道,秒级反馈,无需任何环境依赖。

我这个习惯得改。

  1. 最近了解的 AI 内容?

我说了 OpenClawClaude Code 源码

OpenClaw 是一个开源 AI 智能体,核心能力是让大模型获得本地 Shell 权限,自主执行终端命令。它的工作流完全是 ReAct 范式,但加了一层安全沙箱——所有系统调用都要经过一个权限审批模块。

  1. 讲一下 Claude Code 架构

这块我纯属吟唱,压根没看过源码。回来补了课:

Claude Code 是 Anthropic 的编码 Agent,背后是 50 万行 TypeScript。它的核心设计理念是 “工具隔离 + 无共享可变状态”

  • 40+ 个独立工具模块(文件读写、Bash 执行、代码搜索、测试运行等);
  • 每个工具有自己的输入 Schema、权限级别、执行逻辑;
  • 不存在跨工具共享的全局可变状态——所有状态通过上下文显式传递;
  • 查询引擎会把用户需求转成结构化的工具调用序列,然后在一个循环里顺序执行。

这其实是一种 “微服务化”的 Agent 架构——每个工具可以单独升级、单独测试、单独做权限管控,避免了一个工具出错把整个 Agent 拖垮。

  1. 建议下去再补一点 Harness 的知识

Harness 是一个 Agent 工程化框架,核心思想是通过 分层规范文档来约束编码 Agent 的行为:

  • AGENTS.md:定义 Agent 的角色边界和能力范围;
  • ARCHITECTURE:定义代码仓库的架构约束;
  • TASKS.md:定义当前任务拆解。

它的本质是把“提示词工程”升级为“规范工程”——让 Agent 不是靠一段又长又臭的系统提示词来理解任务,而是通过读取结构化文档来获得上下文。这样更可控、更可审计。

  1. 反问业务

我问了业务方向——安全风险相关的 AI

主要是用大模型做内容安全审核、违规行为识别、风险态势感知。属于 ToB 的合规方向,业务复杂度高,而且对模型的可解释性和低幻觉要求极为苛刻——因为误判会产生法律风险。这也解释了为什么面试官对幻觉问题追着问了那么久。

最后说两句复盘

这场面试,我暴露的问题很清晰:

**一是基础数学不扎实。**余弦和欧氏的区别,属于最底层知识,我没答透。

**二是被工具惯坏了。**刷题偷懒用数组解链表、debug 依赖 AI——面试官看这些细节就像看透明人。

三是系统设计的颗粒度不够。记忆管理策略我说得出“总结+最近几轮”,但面试官一问“触发条件的具体数值策略”、“第 11 轮是增量还是全量”、“原始数据存不存”,我就卡了。这暴露了我只做过 Demo 级别的 Agent,没上过生产

**四是手撕代码真得练。**链表题用数组偷懒,被当场识破,输入输出都不会写——这波不冤。

面完出来,我在地铁上把这些问题从头到尾过了一遍,然后掏出手机记了 3000 字的笔记。

学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%免费

在这里插入图片描述

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐