# AI 大模型与 Agent 面试题汇总

这份题库是给正在或准备做 AI 方向的前端 / 全栈工程师准备的,重点放在真实面试常考、能直接用上工程的题目,而不是 ChatGPT 拽词汇说一遍就完事的概念题。

几条原则:

  1. 每道题都标了「考察点」,知道面试官真正想确认什么,比记标准答案更值钱。
  2. 答案尽量按面试节奏写:先用一两句话把结论说清,再补关键细节,再补一个能让对方点头的延伸或例子。
  3. 实在通用的概念题不会写得太啰嗦,真正决定差异化的,是工程实战那几节(Agent 架构、RAG、MCP、LangChain/LangGraph、前端集成、AI 提效)。

题量按主题排布,越往后越偏工程实操:

  • 一、大模型基础(先把"是什么"打通)
  • 二、Prompt 工程(最该练的硬功夫)
  • 三、AI Agent 架构(高频且能拉开差距)
  • 四、RAG 检索增强生成(ToB 项目几乎必问)
  • 五、Function Calling 与 MCP(新一年最火的实战题)
  • 六、Memory 与上下文管理(Agent 真正难的部分)
  • 七、LangChain / LangGraph 框架(开源生态主战场)
  • 八、模型微调 / 私有化部署 / ToB 落地(资深岗常问)
  • 九、前端 AI 集成与工程化(前端的主场)
  • 十、AI 提效篇(怎么用 AI 反过来帮自己干活)
  • 十一、综合追问 & 场景题(拉差距的部分)

# 一、AI 与大模型基础

这一节别背太多概念,面试官真正想确认的是:你有没有过手感。每个点能说出一个自己见过的现象,胜过把维基百科背一遍。

# 1. 什么是大语言模型(LLM)?它和过去的 NLP 模型本质区别是什么?

考察点:能否用一句话讲清,并知道它不是「智能」而是「概率」。

LLM 本质上是一个只会做一件事的概率模型:给一段上文,预测下一个 token 最可能是什么。把这个动作循环执行,就能输出一句话、一段代码、一篇文章。

它和过去 NLP 的区别有两点最关键:

  • 不再针对单一任务训练。过去要做分类训分类,做翻译训翻译;现在一个模型靠 prompt 切换几十种任务。
  • 规模带来质变。参数量到一定规模后,会涌现出推理、代码、跨语言能力,这是小模型里不存在的。

一句话总结:本质是「自回归概率分布」+「大力出奇迹」,不要把它当成会思考的人。

# 2. GPT、Claude、Gemini、LLaMA、DeepSeek、通义、Kimi 这些怎么选?

面试时别背版本号,记住选型口径

选型角度 倾向哪家
Agent / 工具调用 / 长任务稳定 Claude(Anthropic)
通用 + 生态最广 + 多模态 GPT / OpenAI
超长上下文 / 多模态 Gemini
开源 + 微调研究的事实标准 LLaMA(Meta)
开源 + 推理 / 代码 / 数学 DeepSeek
中文场景 / 国内私有化 Qwen(阿里)、GLM(智谱)
中文长文档 / 阅读理解 Kimi(Moonshot)
轻量 / 边缘 / 端侧部署 Mistral / Phi / Gemma

被追问"为什么这么选"时一定要说业务场景

  • 我们做企业内部 Agent,链路 10 步以上,所以选 Claude,工具调用更稳;
  • 我们做 RAG + 长文档,所以选 Kimi / Gemini,长上下文成本比切片好控;
  • 我们做合规私有化,所以选 Qwen / DeepSeek 自部署;
  • 我们要做学术微调实验对比开源底座,所以选 LLaMA 系;
  • 我们要把模型塞进 IoT / 浏览器端,所以选 Phi / Gemma 这种 1B-4B 的小模型。

# 3. Token 是什么?为什么按 token 计费而不是字符?

Token 是模型实际处理的最小单元,由 tokenizer 把文本切成一串整数 id。模型从头到尾看到的都是 token id,不是字符。

按 token 计费的真正原因:模型的算力消耗和 token 数线性相关,和字符数不是。比如同一句话英文 4 token、中文可能 8 token,按字符算就不公平了。

常用换算(够你在面试里给个数):

  • 英文:1 token ≈ 4 字符 ≈ 0.75 个单词
  • 中文:1 token ≈ 1.5 个汉字(不同模型差别不小)
  • 代码:和英文接近,但符号多的语言会更碎

实战经验:估成本时给 1.3 倍 buffer,因为输入和输出都会算,且 system prompt 在多轮里会反复带。

# 4. 上下文窗口(Context Window)是什么?越大越好吗?

窗口 = 模型一次能塞进去的 token 总额 = system + 历史对话 + 当前输入 + 留给输出的预算。超过就要截断、报错或者换策略。

不是越大越好,几个反常识的点:

  • 大窗口 ≠ 注意力均匀。模型对开头和结尾的内容关注更高,中间段容易被忽略,叫「Lost in the Middle」。
  • 成本和延迟一起涨。1M token 上下文每次调用都极贵,而且首 token 时间会肉眼可见地变慢。
  • 大窗口不能完全替代 RAG。把 50 篇文档全塞进去,效果通常不如 RAG 检索出最相关的 5 段塞进去。

工程上反而要主动控制:滑动窗口、摘要压缩、向量检索拼接才是常态。

# 5. Temperature、top_p、top_k、seed 这几个参数怎么调?

记住一句话:调一个就够,别全都调。最常用的是 temperature

参数 控制什么 代码 / 抽取场景 创意 / 闲聊
temperature 整体随机性 0 - 0.3 0.7 - 1.0
top_p 截断到累计概率 p 默认 0.9 不动 同上
top_k 截断到前 k 个候选 一般不调 一般不调
seed 复现性(部分模型支持) 固定 seed + temperature=0

要让结果完全可复现:固定 seed + temperature=0 + top_p=1,且不要打开 streaming(部分 SDK streaming 有微差)。

# 6. Embedding 是什么?和 LLM 的关系?

Embedding 模型是专门把一段文本压成一个固定长度向量(比如 1024 / 1536 / 3072 维)的模型,向量距离反映语义相似度。

它和 LLM 是两个独立模型

  • LLM:处理理解 + 生成
  • Embedding 模型:只做表示,不生成

典型用途:语义搜索、RAG 检索、聚类、推荐、查重、相似工单合并。

面试常被追问的细节:

  • 维度越高 ≠ 效果越好,主流 1024 / 1536 已经够用,维度高会让向量库存储和检索都变贵;
  • 同一份语料要用同一个 embedding 模型,换模型必须全量重建索引;
  • 中文场景优先选支持中文的模型(bge-m3、Qwen-embedding、jina-zh),用英文 embedding 在中文上效果会折损。

# 7. 余弦相似度 vs 欧氏距离怎么选?

向量检索里 99% 用余弦相似度:只看方向不看长度,对文本归一化更友好。

欧氏距离会受向量模长影响,多用在「位置 / 物理量 / 图像特征」这种长度本身有意义的场景。

实战记一句话:embedding 都归一化之后,余弦相似度和欧氏距离结果基本等价(差一个常数变换),所以选哪个看库支持。

# 8. 模型「幻觉」(Hallucination)的根因是什么?

不是 bug,是架构决定的特性

LLM 在做"下一个 token 概率最大化",并不会去查事实。当训练里没见过对应内容,它会按统计相关性继续编——表达通顺、事实瞎说。

减少幻觉是组合拳,没有单点药方:

  1. 接 RAG,让答案有据可查(这是最有效的一招);
  2. 在 system prompt 显式要求 "不知道就说不知道,不要编",并给一个示范;
  3. 强约束输出格式,比如必须 JSON + 必须带引用片段编号;
  4. 用代码或第二个 LLM 做后置校验(金额、日期、URL 这类容易瞎编的字段重点查);
  5. temperature 拉到 0 - 0.3;
  6. 实在不行才上微调(成本最高)。

# 9. 自回归(Decoder-only)和 Encoder-Decoder 区别?

自回归:从左到右一个 token 一个 token 生成,代表 GPT / Claude / Llama / Qwen,现在主流 LLM 都是这个架构

Encoder-Decoder:先把整个输入编码成中间表示,再解码出来,代表 T5 / BART,输入输出有明确对应的任务(翻译、摘要、纠错)历史上效果好。

为什么现在都偏向 Decoder-only?工程上更简单:一个模型搞定所有任务,只看 prompt。

# 10. KV Cache 是什么?为什么能加速生成?

自回归生成时,每个新 token 都依赖前面所有 token 的 Key/Value。如果每生成一个 token 都重算一遍前面的 KV,复杂度 O(n²) 极慢。

KV Cache 的本质:把已经算过的 K、V 存下来,新 token 只追加计算,复杂度降到接近 O(n)。

附带几个延伸:

  • Prompt Caching(Anthropic / OpenAI 都支持)就是把不变的 system prompt 部分 KV 复用,对长 system + 多轮对话的场景能省很多钱;
  • KV Cache 占显存,所以推理服务的并发上限就被显存卡住。

# 11. 什么是 Streaming(流式输出)?

模型每生成一个 token 就推到客户端,不等整段生成完。体感上和 ChatGPT 一样:边生成边显示。

为什么必须做?

  • 首 token 出现快(TTFT < 1s),用户感知到"它在响应";
  • 长回答(几千 token)总时长好几秒,等完再显示体验灾难。

前端三种实现:

  1. SSE(Server-Sent Events):HTTP 单向流,最简单也最普遍;
  2. HTTP Chunked:底层和 SSE 类似,自己拼协议;
  3. WebSocket:双向场景(比如可以中途打断 / 多用户协作)。

前端读 SSE 的标准模板:

const res = await fetch('/api/chat', { method: 'POST', body, signal })
const reader = res.body.getReader()
const decoder = new TextDecoder()
let buffer = ''
while (true) {
  const { value, done } = await reader.read()
  if (done) break
  buffer += decoder.decode(value, { stream: true })
  // 按 \n\n 分包,解析 data: 字段
  let idx
  while ((idx = buffer.indexOf('\n\n')) !== -1) {
    const chunk = buffer.slice(0, idx)
    buffer = buffer.slice(idx + 2)
    onDelta(JSON.parse(chunk.replace(/^data: /, '')))
  }
}

# 12. System Prompt 是干什么的?应该放些什么?

System Prompt 是整段对话的"底色",模型每轮回答前都会先读它。

四要素,最好按顺序写:

  1. 角色定位:你是谁、你的专业是什么;
  2. 任务边界:能做什么、不能做什么;
  3. 风格 / 格式:语气、长度、是否带代码、是否带引用;
  4. 兜底规则:不知道就说不知道、敏感问题怎么处理、什么时候让用户兜底。

实战经验:

  • 把"重要约束"放在 system 的开头和结尾,中间放细节,因为中间最容易被模型忽略;
  • 不要在 system 里塞知识,那是 RAG 的工作;
  • system 不变的部分尽量复用,触发 Prompt Caching。

# 13. 多模态模型是什么?前端怎么用?

多模态 = 能处理文本之外的东西。常见组合:

  • 文本 + 图(GPT-4o、Claude 4 Vision、Gemini、Qwen-VL)
  • 文本 + 音频(Whisper STT、Realtime API)
  • 文本 + 视频(Gemini、Sora 类的生成)

前端场景:

  • 上传截图问"这块 UI 该用什么组件"
  • 把设计稿喂给模型生成 HTML / Tailwind
  • 录音转文字、做语音输入
  • 把后端长报表截图扔上去做摘要

注意 token 计费:一张图常常等于 1k - 2k token,比文本贵很多,要做大小压缩和 base64 vs URL 的取舍。

# 14. 模型的「知识截止时间」(Knowledge Cutoff)是什么?

模型训练数据冻结的日期。过了这个日期发生的事它全不知道(昨天发布的 Vue 新版本、上周的政策、今天的股价)。

工程上三种应对:

  1. RAG / 联网检索补最新信息;
  2. system prompt 显式告诉它今天是几月几号,避免它瞎猜;
  3. 让它不确定就说不确定,不要装懂。

# 15. RLHF、DPO、Constitutional AI 三个是什么?

都是对齐(Alignment)的方法,让预训练完只会"猜 token"的模型变得"会听人话"。

  • RLHF:让人给模型多个回答打分,训一个奖励模型,再用 PPO 强化学习。流程长、训练贵;
  • DPO / ORPO:跳过奖励模型,直接用「选中 / 拒绝」对来做监督学习。简单、稳定,现在主流团队偏好 DPO
  • Constitutional AI(Anthropic 提的):用一组人写的「宪法原则」让模型自己批改自己的输出,再用改后的数据再训一遍,减少人工标注

# 16. 推理(Inference)和训练(Training)的成本结构差异?

  • 训练:一次性、超贵。GPT 级模型一次训练上千万到上亿美元;
  • 推理:单次便宜,累计巨贵。生产环境跑半年,推理成本会远远超过训练。

前端调 API 付的是推理成本,所以省 token 才是日常的钱:Prompt Caching、压缩历史、控制 max_tokens、用小模型分流、复用 Embedding 索引。

# 17. 涌现能力(Emergent Ability)是真的吗?

是真的,但也被一部分论文质疑过(说是因为评估指标不连续造成的错觉)。

工程上重要的不是争论它真假,而是记住一个直觉:当某个任务在 7B 上做不了,先想想 70B 能不能做了再说,不要立刻去微调。

# 18. MoE(专家混合)和稠密模型的区别?

稠密模型:每次推理所有参数都激活。

MoE:模型里有 N 个「专家」子网络,每个 token 只路由到 K 个专家(比如 8 选 2),参数总量大但激活量小,所以 700B 的 MoE 推理速度可以接近 70B 稠密模型。

代表:Mixtral、DeepSeek-V3、GPT-4 据传也是。

前端做接入时一般感知不到差异,主要影响私有化部署时的显存和路由策略。

# 19. 模型的"温度墙"为什么 temperature=0 也不稳定?

temperature=0 表示总是取概率最高的 token,理论上应该完全确定。但实际还是会有微小差异,原因:

  • 浮点运算非结合律,多卡 / batch 内顺序变化导致最大值的并列 token 被选中的方式不一样;
  • 服务端可能有并行调度带来的非确定;
  • 某些 SDK 默认 top_p < 1,需要显式设置。

要求严格可复现:固定 seed + temperature=0 + top_p=1 + 单条请求 + 关 streaming,而且不同服务商之间不能跨着复现

# 20. 国产模型和海外模型在工程上最大的差异是什么?

不是"中文好不好"那种泛泛回答,要给点真实落地痕迹:

  1. 网关稳定性 / 限流策略不一样,国产更宽松、海外更严格;
  2. 合规要求不一样,国内要求大模型生成内容备案 + 关键词过滤;
  3. 私有化部署能力国产更普遍(Qwen、DeepSeek、ChatGLM 都有完整开源生态);
  4. 价格曲线国产明显更便宜,DeepSeek-V3 等价位经常打到 GPT-4 的 1/10;
  5. 工具调用 / 多模态成熟度整体还是 Claude / GPT 领先,国产追得最快的是 Qwen。

# 二、Prompt 工程

别小看 Prompt 工程。90% 让人惊艳的 AI 项目,本质上都是 prompt 调得好。 微调是没办法的最后手段。

# 21. Prompt 工程到底是什么?为什么花时间在它上面值得?

朴素一句话:用结构化、可复用的输入文本,引导模型给出可控、稳定的输出

为什么值得:

  • 同一个模型,一个写糟的 prompt 和一个写好的 prompt,效果可能差 5 倍以上;
  • Prompt 是最便宜的优化手段,比微调快 1000 倍,比换模型省几十倍钱;
  • Prompt 出问题最常见的不是"模型不行",而是"指令没写清"。

# 22. Zero-shot / One-shot / Few-shot 的区别和适用边界?

  • Zero-shot:直接问,不给例子。模型已经擅长的任务(翻译、改写、总结)够用;
  • One-shot:给一个范例。让模型知道"输出长这样";
  • Few-shot:给 2-5 个范例。对输出格式特殊 / 业务规则复杂的场景特别有效。

经验值:

  • 简单任务 0-1 例;
  • 复杂格式 3-5 例就够,超过 5 个收益快速衰减还涨 token;
  • 例子要覆盖边界,比如带空值、异常输入的例子各放一个;
  • 例子顺序有影响,和真实输入相近的放最后

# 23. CoT(Chain of Thought)是什么?什么时候要 / 不要?

让模型先想再答,把推理过程显式写出来,再给结论。

最简单的触发:在 prompt 末尾加一句 Let's think step by step.,或者用 Claude 风格的 <thinking>...</thinking>

适合:数学、多步推理、规则复杂的判定题(合规审查、合同抽取)。

不适合

  • 简单任务(翻译、改写、抽取一个字段),CoT 反而拖慢且无收益;
  • 追求最低延迟的场景,CoT 让输出变长 5-10 倍;
  • 现在很多新模型(Claude / o1 / DeepSeek-R1)内部已经做了隐式推理,再手动加 CoT 收益不大反而干扰。

# 24. ReAct 是什么?和 CoT 的区别?

ReAct = Reason + Act:让模型按 思考 → 行动 → 观察 → 再思考 的循环走,是 Agent 的基础范式

CoT 只有「想」,ReAct 多了「想完之后调工具,把工具结果带回来继续想」这一步。

简化的输出格式:

Thought: 我需要查今天天气
Action: get_weather
Action Input: {"city": "北京"}
Observation: 26°C 晴
Thought: 已经拿到,可以回答了
Final Answer: 北京今天 26 度,晴

实际工程里很少手写 ReAct,LangChain / Agent SDK / 大模型自带的 Tool Calling 就是 ReAct 的工程化封装

# 25. 怎么让模型严格输出 JSON?

按可靠性从低到高:

  1. Prompt 描述格式:最弱,模型经常多说一句话或把 JSON 包在 Markdown 里;
  2. JSON Mode:大多数 SDK 支持 response_format: { type: 'json_object' },强制输出合法 JSON;
  3. Function Calling / Tool:把你要的字段定义成函数参数 schema,模型必须按 schema 填。最稳,强烈推荐
  4. Structured Output(OpenAI / Anthropic 都有):在 Tool Calling 基础上加 JSON Schema 强约束;
  5. 约束解码:在推理引擎层面卡 token,只允许输出符合语法的 token,私有部署常用(outlines、jsonformer)。

兜底策略:解析失败时,把错误信息 + 原始输出一起塞回模型让它修,或者用 jsonrepair / partial-json 这种容错解析库。

# 26. Prompt 写长了为什么效果反而变差?

三个根因,按重要性排序:

  1. Lost in the Middle:长上下文中间段的信息被忽略;
  2. 指令冲突:写多了容易自相矛盾,比如前面说"简短"后面又写"详细";
  3. 稀释效应:核心指令在大量背景文字里被淹没。

优化:

  • 关键指令放开头和结尾两次(甚至复述);
  • 用 XML 标签或分隔符显式分块<context>...</context><task>...</task><output>...</output>
  • 把静态背景知识挪到 RAG,prompt 里只留当前任务。

# 27. 怎么写一个高质量的 Prompt?给你一个能直接套的骨架。

# 角色
你是一名 [具体角色,越具体越好]。

# 任务
[要做什么,一句话讲清楚]

# 输入
{{user_input}}

# 步骤(可选,复杂任务必加)
1. ...
2. ...
3. ...

# 输出格式
[JSON schema / Markdown 模板 / 自由文本]

# 约束
- 必须 ...
- 不能 ...
- 当 [边界情况] 时,[怎么做]

# 示例(可选,复杂任务必加)
输入:...
输出:...

把这个骨架记下来,95% 业务 prompt 都能套出来。

# 28. 为什么"不要做某件事"经常没效果?

这是模型的特性:它对正向指令敏感得多。否定指令需要"想完该做什么,再否定它",路径更长。

错误写法:不要使用复杂的词。

更好的写法:使用日常生活中的简单词,每句话不超过 15 个字,避免行业术语。

经验上能用「做什么」就别写「不要做什么」。

# 29. Prompt 注入(Prompt Injection)和越狱(Jailbreak)的区别?

  • Prompt Injection:用户输入里夹带恶意指令,让模型偏离 system prompt。攻击的是"信任边界";
  • Jailbreak:突破模型自身的对齐和安全限制,让它输出本不该输出的内容。攻击的是"对齐策略"。

两者经常组合:先注入再越狱。

前端要做的防御:

  1. 结构化分隔:用 XML / 特殊 token 把用户输入和系统指令分开;
  2. 输入审核:先用一个轻量模型判断输入是否包含可疑指令;
  3. 输出审核:敏感关键词过滤、PII 检测;
  4. 限制权限:哪怕被越狱,工具调用、数据访问也要有独立的鉴权层;
  5. 不要把密钥 / 内部链接放进 prompt

# 30. 模型不听话怎么排查?

按顺序排查,命中一个就停:

  1. 指令是否冲突?system 和 user 互相矛盾时模型会随机挑一个听;
  2. few-shot 例子是不是带错?例子比指令权重高,例子错了就跟着错;
  3. 格式约束是否过严?比如要求 JSON 还要求 Markdown,模型会放弃;
  4. temperature 是否太高?业务任务 0-0.3 就好;
  5. 能不能换模型试试?有些任务 Claude 强、有些 GPT 强、有些 Qwen 反而稳;
  6. 是不是 prompt 太长了?关键指令被埋在中间。

# 31. 怎么调试 / 评估一个 Prompt?

不要靠"我自己点几下感觉还行"。最少要做:

  1. 写一组测试用例(10-30 条),每条包含输入、期望输出、判定方式;
  2. 用脚本跑全量,统计通过率、token 消耗、平均耗时
  3. 改完 prompt 重新跑,对比指标,优化前后看趋势
  4. 可视化错误样本:失败的 case 单独看,找模式;
  5. LangSmith / Helicone / Phoenix 一类的可观测平台,把线上请求都记下来,回放调优。

# 32. Few-shot 例子放几个最合适?放哪里?

  • 简单任务:0-2 个;
  • 复杂格式:3-5 个;
  • 涉及边界情况:每种边界 1 个例子。

放在哪里?system prompt 后、user input 前。如果在多轮对话里,例子要保持稳定,别让用户输入混在里面

# 33. 什么是 Prompt 模板?怎么管理?

把变量从 prompt 里抽出来:

const tpl = `请把下面的中文翻译成 {{lang}}:

<text>
{{text}}
</text>`

const prompt = tpl
  .replaceAll('{{lang}}', 'English')
  .replaceAll('{{text}}', '你好')

工程上别自己拼字符串:

  • LangChain PromptTemplate:最常见;
  • Anthropic / OpenAI 自带的模板能力
  • Mustache / Handlebars:纯文本场景;
  • Prompt 库 / Prompt 平台(LangSmith Hub、PromptLayer):团队级版本控制 + A/B + 灰度。

不要把 prompt 写死在代码里,把它当成代码一样版本化,A/B 测试、回滚、灰度都靠它。

# 34. Prompt Caching 是什么?为什么能省钱?

Anthropic / OpenAI / Gemini 都支持。原理:把 prompt 的**前缀(不变的部分,比如长 system + 工具描述 + few-shot)**对应的 KV Cache 缓存下来,下次同样前缀直接命中。

收益:

  • 命中部分 token 计费 打折到 1/10 - 1/2
  • TTFT(首 token 时间)大幅下降。

工程上怎么用好:

  1. system prompt 不要每次拼新内容,把变量放在末尾
  2. few-shot 例子放在 system 末尾、用户输入前;
  3. 监控命中率,命中率低就反推哪里在变。

# 35. Persona 是什么?什么时候要慎用?

Persona = 给模型设定的人格。比如「你是一个温柔耐心的客服小可,自称『小可』」。

好处:风格一致、用户体验稳定。

慎用的场景:

  • 涉及专业判断的(医疗、法律),人格化会让用户错误信任;
  • 容易被用于 越狱(DAN 那类);
  • 多语言场景容易翻车(人格可能只在中文里起作用)。

# 36. 怎么压缩太长的 Prompt?

四个维度,按优先级:

  1. 历史消息摘要:旧轮次用一段总结代替;
  2. RAG 化静态背景:把"产品介绍 / 政策条款"这类放向量库,只在需要时拼回来;
  3. 缩写约定:在 system 里告诉模型「PR = Pull Request、SOP = 操作规程」,正文用缩写;
  4. Prompt Caching:不动 prompt 内容,让重复的部分免费。

不要靠"删表情符号、删空行"这种节省,省下的 token 杯水车薪。

# 37. 什么时候不调 Prompt,直接微调?

判断口径:

场景 Prompt 微调
输出格式固定且复杂 不行
内化大量企业内部知识 不行(也可 RAG)
高频调用想压缩 prompt 省钱
业务规则会频繁变 不行(要频繁重训)
数据少(< 200 条) 不行(不够)

一句话:业务规则变得快、数据少 → Prompt + RAG;业务规则稳定 + 数据多 + 调用量大 → 微调

# 38. Self-Consistency 和 Tree of Thoughts 是什么?

  • Self-Consistency:CoT 跑多次(temperature 拉高一点),看多数投票。复杂数学 / 推理题准确率能提 5-10%。
  • Tree of Thoughts:让模型生成多个推理分支,每个分支再展开,树状探索最终选一条最好的。

代价都是 token 倍增,工程上很少跑全量,多用在评估、复杂决策点。

# 39. Prompt 工程会不会被淘汰?

不会,但会演化。

  • 简单任务的 prompt 越来越不需要精雕细琢(模型变聪明了);
  • 复杂工作流的 prompt 编排(system / 工具描述 / few-shot / 输出约束的组合)反而变重
  • "Prompt 工程师"作为单一岗位会被合并到 AI Engineer 里,但写好 prompt 是 AI 工程师的基本功

# 40. 给一个真实场景:让模型把用户聊天记录里的退款诉求抽取成结构化 JSON。

# 角色
你是一名客服质检员。

# 任务
从用户和客服的对话中,抽取**退款相关的关键信息**,输出 JSON。
对话可能包含和退款无关的闲聊,请忽略。

# 输入
&lt;conversation>
{{conversation}}
&lt;/conversation>

# 输出格式
```json
{
  "has_refund_request": true | false,
  "order_id": "string | null",
  "refund_reason": "string | null",
  "refund_amount": number | null,
  "agreed_by_agent": true | false | null,
  "evidence_quotes": ["原文片段1", "原文片段2"]
}
```

# 约束
- 不在对话里出现的字段一律返回 null,不要编。
- evidence_quotes 必须是对话原文,不要改写。
- 只输出 JSON,前后不要任何说明文字。

# 示例
输入:
&lt;conversation>
用户:我之前买的耳机想退,订单是 A100,没什么问题就是不想要了
客服:可以的,明天处理
&lt;/conversation>
输出:
{"has_refund_request": true, "order_id": "A100", "refund_reason": "不想要了", "refund_amount": null, "agreed_by_agent": true, "evidence_quotes": ["想退,订单是 A100", "可以的,明天处理"]}

面试常被追问的两点:

  1. 为什么用 evidence_quotes?—— 强迫模型在原文中找证据,减少幻觉
  2. 为什么字段类型写在注释里?—— 实战里建议升级到 JSON Schema + Tool Calling,注释只是 fallback。

# 三、AI Agent 架构与设计模式

这一节是面试最能拉差距的部分。能讲清"为什么需要 Agent"和"Agent loop 的常见坑",比背 LangChain API 强一百倍。

# 41. 什么是 AI Agent?和普通 LLM 调用的区别?

一句话:Agent = LLM + 工具 + 记忆 + 规划,能自己做决策、自己跑工具、自己修正错误。

和普通 LLM 调用的区别用表格更清楚:

普通调用 Agent
控制流 单次问答 循环(直到任务完成)
工具 有,且能自己选
状态 有上下文 / 记忆
错误处理 失败就退出 自己重试 / 换路
适合任务 翻译、改写、抽取 写代码、跑命令、查数据、写报告

经典例子:你让普通模型"创建一个 React + Vite 项目",它只会告诉你命令;Cursor / Claude Code 这种 Agent 会自己写文件、跑命令、看报错再改——这才叫 Agent。

# 42. ReAct Agent 怎么实现的?给个最小可运行骨架。

def run_agent(user_input, tools, max_steps=10):
    history = [{"role": "system", "content": SYSTEM_PROMPT}]
    history.append({"role": "user", "content": user_input})

    for step in range(max_steps):
        resp = llm.chat(messages=history, tools=tools)
        msg = resp.choices[0].message
        history.append(msg)

        if not msg.tool_calls:
            return msg.content  # 最终回答

        for call in msg.tool_calls:
            result = tool_registry[call.name](**call.arguments)
            history.append({
                "role": "tool",
                "tool_call_id": call.id,
                "content": str(result)
            })

    raise RuntimeError("达到最大步数仍未完成")

关键点:

  • LLM 决定调工具还是直接给答案
  • 每次调工具的结果都要塞回 history;
  • 必须有 max_steps,否则可能无限循环;
  • 工具的 schema 是模型理解工具的唯一信息来源,描述要写好

# 43. Plan-and-Execute Agent 和 ReAct 的区别?

  • ReAct:边想边做。优点灵活,缺点中间一旦判断错容易跑偏;
  • Plan-and-Execute先一次性规划出所有步骤,再按计划执行,必要时回头改计划。优点路径稳定,缺点对长程任务一次规划容易遗漏。

工程上常用混合:先 plan 出粗粒度大步骤,每个大步骤内部跑 ReAct 小循环。

# 44. Agent Loop 在工程里有哪些常见坑?

跑过的人都被坑过:

  1. 死循环 / 振荡:模型反复调同一工具或在两个工具之间来回横跳;
  2. Token 烧得飞快:每轮都把全量上下文带过去,几轮翻好几倍;
  3. 错误放大:第一步观察就理解错了,后面跟着错的方向越走越远;
  4. 越权 / 安全风险:没限制的话模型会调危险工具(删库、发邮件、rm -rf);
  5. 不会停:自我反思没有终止条件,永远在"再确认一下"。

兜底动作(必做):

  • 设硬上限:max_steps、max_tokens、max_duration
  • 重复检测:同一工具同一参数连续 N 次直接停;
  • 工具白名单 + 危险操作二次确认
  • 全链路日志:每步 prompt / tool_call / result 都落盘,事后能回放;
  • 上下文压缩:旧轮次定期摘要。

# 45. Agent 怎么自己判断"任务完成了"?

几种常见判定,按工程靠谱程度:

  1. 显式工具返回 final_answer:模型主动调"完成"工具;
  2. 没有 tool_calls 的回答:模型直接给文本输出(最常见);
  3. 触发停止词 / 标签:比如输出 <done> 后中断;
  4. 外部判定:跑一个评测 LLM 判断"够不够";
  5. 轮次上限:兜底,不能省。

不要只靠"模型自己判断"。

# 46. 单 Agent vs 多 Agent 怎么选?

复杂 Agent 产品基本是多 Agent 架构。原因:

  1. 决策准确率更高:每个子 Agent 只看自己需要的 prompt,没有无关信息干扰;
  2. Token 更省:不是每次都把所有工具描述塞进去,调用变多但单次更便宜;
  3. 可并行:主 Agent 派活,子 Agent 并发处理;
  4. 多角色互相纠错:A 写代码 B 评审 C 验证,比单 Agent 自反思靠谱。

什么时候不要多 Agent?

  • 任务简单、步骤少、用户期待秒级响应;
  • 团队还没把单 Agent 跑稳就上多 Agent,反而更难调试。

拿 Cursor / Claude Code 类比:早期是单 Agent,现在内部分了 plan、edit、verify、search 多个角色。

# 47. Reflexion / Self-Reflection 是什么?

让 Agent 跑完一轮后自己评估这次结果好不好,如果不好就调整策略再跑一遍。

简化流程:

1. 跑一遍任务 → 拿到 result_v1
2. 让 LLM 评估 result_v1 哪些地方不对 → 拿到 critique
3. 把 critique 注入 prompt → 再跑 → result_v2

适合复杂推理 / 代码生成场景,对延迟敏感的不适合。

# 48. Agent 怎么处理"用户中途打断"?

前端这边几个动作必须做:

  1. 给请求加 AbortController,能取消正在跑的 fetch;
  2. 服务端识别到客户端断连,立刻停止 LLM 调用 / 工具执行(OpenAI / Anthropic SDK 都支持中断);
  3. 已经写入的状态(数据库、文件)要有回滚或标记为中断的机制;
  4. 重新拉对话时,把"被打断的轮次"作为状态显示给用户,让他决定继续还是重做。

# 49. Anthropic Agent SDK / Claude Code 这种 Agent 框架做了什么?

把"Agent 工程的脏活"封装成开箱即用:

  • Tool Calling 标准协议:统一的 schema / 错误处理;
  • 多步骤循环:自动跑直到任务完成;
  • 工具集合:内置 Read / Write / Edit / Bash / Search / WebFetch;
  • 可观测:每步日志、回放、调试;
  • 权限模型:哪些工具可以无确认跑、哪些必须用户点确认;
  • 子 Agent / 多角色:内置 dispatch 能力。

前端工程师拿来即用,重点研究它的 system prompt 和工具 schema,比写自己的 Agent 框架更值

# 50. LangChain、LangGraph、CrewAI、AutoGen、Vercel AI SDK 选哪个?

按需选:

场景 推荐
前端 / Next.js 项目快速做 Chat / 流式 Vercel AI SDK
后端做 Agent 工作流、链式调用 LangChain
多 Agent + 图编排 LangGraph
多角色协作(CEO / Eng / QA)模拟 CrewAI / AutoGen
企业内部用应用、可视化拖拽 Dify / Coze / FastGPT

别问"哪个最好",问你的用户是谁、任务多复杂、要不要私有化

# 51. Agent 工具描述写不好会怎样?

模型理解工具靠的就是描述。描述写不好直接表现为:

  • 模型该调没调(不知道这个工具能解决);
  • 调错工具(两个工具描述太像);
  • 传错参数(schema 字段名 / 必填项 / 枚举值没写清);
  • 传冗余参数(描述太长,模型脑补出不存在的字段)。

工具描述模板(亲测好用):

name: search_user_orders
description: 根据用户 ID 查询该用户最近 30 天的订单列表,
  返回订单 ID、状态、金额。**仅用于查询,不能创建或修改订单**。
parameters:
  user_id (string, required): 用户的唯一 ID,类似 'U-12345'。
  limit (number, optional, default=10): 返回数量,最大 50。

经验:

  • 明确"能做什么"和"不能做什么"
  • 给一个典型用法例子(用 # example 字段);
  • 字段写取值范围、单位、格式
  • 工具数量超过 15 个就要分组 / 分层加载,否则模型选错率飙升。

# 52. Agent 怎么调试?看哪些指标?

最少四件套:

  1. 每步 prompt + tool_call + result 日志(落盘 + 可搜索);
  2. 步数分布:均值、p95、超过 N 步的 trace;
  3. Token 消耗分布:哪些工具调用 token 异常高;
  4. 失败模式聚合:把失败 trace 按错误类型聚类,看是 prompt 问题 / 工具问题 / 模型问题。

工具推荐:LangSmith(最常见)、Helicone、Phoenix、Langfuse。

# 53. Human-in-the-loop(HIL)是什么?什么时候必加?

让用户在 Agent 关键步骤介入决策

必加的场景:

  • 不可逆操作:发邮件、付款、删数据;
  • 金额超阈值:比如退款 > 500;
  • 跨权限操作:访问别的部门数据;
  • 法律 / 合规风险点

实现方式:Agent 跑到关键节点时,返回一个 pending 状态给前端,前端展示"是否继续"按钮,用户确认后再继续。状态保存到 DB,断线能恢复。

# 54. Agent 的成本怎么优化?

一套组合拳:

  1. 小模型分流:简单分类 / 路由用 7B 小模型,复杂任务才给大模型;
  2. Prompt Caching:长 system + 工具描述全部缓存;
  3. 工具结果裁剪:返回前砍掉不必要字段,别让模型读完整 SQL 输出;
  4. 历史摘要:旧轮次定期压成几句话;
  5. 并行 vs 串行:能并行的工具调用一定要并行(多数 SDK 支持);
  6. 缓存层:常见问答先查缓存 / 向量库再决定要不要调模型。

# 55. LLM-as-Judge 是什么?

用一个 LLM 评估另一个 LLM 的输出。

典型场景:

  • 跑 prompt 改进 A/B,让"裁判模型"对比两个回答打分;
  • Agent 跑完后,让裁判模型判断"是否完成任务";
  • 给数据集打偏好标签,省人工。

注意:

  • 裁判模型要比被评估模型更强(GPT-4 当 Claude 4 的裁判没问题,反过来不行);
  • 明确评估维度(准确性 / 相关性 / 格式 / 礼貌),别让它笼统打个分;
  • 跑多个裁判取平均,减少裁判模型本身的偏差

# 56. Agent 的延迟(Latency)怎么优化?

最影响体感的几个动作:

  1. streaming:首 token 时间从几秒降到 1 秒内;
  2. 并行工具调用:多个工具同时跑而不是串;
  3. 小模型预筛 + 大模型精排
  4. 预热 / Keep-alive:减少连接建立开销;
  5. Prompt Caching 命中率
  6. 边缘部署 / CDN:让首跳 RTT 更短。

# 57. Agent 怎么测?写得了单元测试吗?

写得了,但要换思路:

  • 确定性部分:工具函数、parser、router 当普通函数测;
  • LLM 调用部分:mock 掉,或者用录制 / 回放(vcr 模式);
  • 整体端到端:写一组业务测试用例,跑全量,用 LLM-as-Judge 判通过,统计通过率作为回归指标。

不要追求 100% 通过,AI 系统天然有不确定性,关注趋势:每次改完通过率涨还是跌。

# 58. AutoGPT、BabyAGI、Devin 这类"全自主 Agent"为什么不实用?

理论很美,工程上一堆问题:

  • 目标偏移:开放性任务模型容易越走越远;
  • token 爆炸:跑几小时一两千美元下去了;
  • 错误传播:早期错误后期放大;
  • 没有 HIL 节点,跑错也没人能拦;
  • 可观测差:跑完不知道为啥成 / 为啥败。

教训:生产用的 Agent 都是"半自主 + 有边界 + 有 HIL",不是完全放飞。

# 59. 怎么把现有产品改造成 Agent?

务实步骤:

  1. 找一个高价值的 workflow(比如客服处理退款),不要一上来全产品 Agent 化;
  2. 梳理这个 workflow 的所有手动步骤:每一步用了哪个内部接口;
  3. 把这些接口包成 Tool(写好 schema + 描述);
  4. 写一个严格的 system prompt,限制 Agent 只能在这个 workflow 内做事;
  5. HIL 卡关键节点(涉及钱、涉及不可逆);
  6. 小流量灰度(5% → 20% → 50% → 100%),看转化和投诉。

不要"先做个 Agent 框架再说"。

# 60. 一个 Agent 的"思考预算"应该怎么设?

三个维度:

  • 最大步数(max_steps):8 - 20 是常见范围,超过基本是死循环;
  • 最大 token(max_total_tokens):按业务任务复杂度估,比如 50k;
  • 最大耗时(max_duration):用户能忍受的上限,通常 60-120 秒。

任何一个达到上限就优雅终止:返回部分结果 + 说明"任务未完成",不要让用户等永远

# 61. Computer Use Agent 是什么?

Anthropic 在 Claude 上开放的能力:模型直接看屏幕截图、移动鼠标、敲键盘,跨任意 GUI 应用操作。

工作流:

  1. 客户端截屏给模型;
  2. 模型返回 screenshot / mouse_move / mouse_click / key / type 等动作;
  3. 客户端执行动作,再截屏;
  4. 循环直到任务完成。

适合:

  • 没有 API 的老软件操作;
  • 跨多个软件协作的流程;
  • 浏览器自动化(替代 Selenium)。

风险:

  • 慢(每步都要看截图);
  • 贵(每次截图都是几千 token);
  • 安全(模型实际在你电脑上操作)。

生产 Agent 优先选 API / MCP,Computer Use 是兜底

# 62. Agent 评测有哪些常用 benchmark?

benchmark 测什么
SWE-bench 真实 GitHub issue 修复,软件工程能力
GAIA 多步真实世界任务(搜索、计算、推理)
AgentBench 多种工具调用场景
WebArena 浏览器操作能力
OSWorld 桌面 GUI 操作能力
τ-bench 客服 / 业务流程 Agent
HumanEval / MBPP 单函数代码生成(偏基础)

工程上常见:不直接跑 benchmark,而是自己造业务 case 集 + 用 LLM-as-Judge 跑回归。

# 63. Agent 的 Context Engineering 是什么?

2026 年新词,本质是「精心构造 Agent 每一轮的输入」,被认为是比 Prompt Engineering 更高维的工作。

包括:

  • System Prompt 设计:角色、能力边界、风格;
  • 工具描述精炼:哪些工具该加进来、怎么排序;
  • 历史压缩 / 摘要:哪些保留、哪些丢;
  • 检索结果拼接:RAG 召回片段放哪儿、怎么排版;
  • 思考预算控制:CoT、reasoning 用不用;
  • 格式约束:JSON Schema、XML 标签;
  • 示例选择:动态 few-shot 检索最相关样例。

Claude Code、Cursor 这类工具内部最复杂的不是模型,而是 Context Engineering。

# 64. Background Agent 和 Foreground Agent 区别?

  • Foreground:用户直接对话的 Agent,重 TTFT、重交互、重打断;
  • Background:跑在后台的 Agent,时长可能几分钟到几小时(爬数据、跑测试、生成报告、监控告警)。

工程差异:

维度 Foreground Background
延迟 关键 不关键
状态 内存 / Redis 必须持久化(DB / Checkpoint)
中断恢复 不需要 必须支持
失败重试 用户重发 自动重试
可观测 用户能看 必须有 dashboard
成本上限 较低 容易跑爆

Background Agent 必须有预算守门员:超步数 / 超 token / 超耗时自动停。

# 65. Agent 的 Tool Selection 怎么优化?

工具一多模型选错率飙升。优化套路:

  1. 静态分组:按业务域分组,先路由再加载;
  2. 动态加载:用轻量分类器先选 top 5 工具再喂主 Agent;
  3. MCP Resources / Skills:把工具按粒度分层;
  4. 工具描述加例子:模型容易抓「example 里的关键词」;
  5. 工具名加前缀order_*user_*payment_*,命名上分组;
  6. 历史命中加权:用户上下文里最近用过的工具优先级提高。

# 66. Agent 出错后怎么定位?看 trace 看什么?

trace 是 Agent 的「飞行记录仪」,按步骤回放:

  1. 每步的 prompt(system + history + tools) ;
  2. 模型输出(tool_calls 或 final);
  3. 工具执行入参 / 出参 / 耗时;
  4. 上下文 token 用量。

常见排错路径:

  • 第一步就跑偏 → system prompt / 工具描述问题;
  • 某步工具选错 → 工具描述太相似 / 排序错;
  • 工具调对了但执行错 → 业务接口 bug;
  • 跑到死循环 → 工具结果格式让模型困惑,反复确认;
  • 过早 final → 终止条件太宽松。

工具:LangSmith / Langfuse 看 trace 是基本功。

# 67. Agent 怎么做 retry / fallback?

不是简单的 try-catch。分层处理:

  • 工具调用失败:把 error 信息塞回 messages,让模型自己决定;
  • 模型超时 / 限流:客户端重试(指数退避),切到备用模型;
  • 整段步数耗尽:保存进度,返回"任务未完成 + 已完成的部分";
  • 格式解析失败:把错误塞回去让模型修;
  • 检测到死循环:强制中断 + 报警 + 人工兜底。

不要让 Agent 静默失败。所有失败都要落日志 + 告警


# 四、RAG 检索增强生成

ToB 项目几乎必问 RAG。能讲清"为什么 RAG 比微调更常用"和"切片 / Embedding / 检索 / 重排"四个环节的优化,就拉开差距了。

# 68. 什么是 RAG?为什么要发明它?

RAG = Retrieval-Augmented Generation:用户提问 → 先去知识库检索相关片段 → 把片段塞进 prompt 增强上下文 → 模型基于这些生成回答。

为什么需要它:

  • 模型不知道你公司的内部文档;
  • 模型有知识截止日期,最新政策 / 数据它不知道;
  • 模型会幻觉,没有依据时会瞎编;
  • 微调成本高且对频繁更新的知识不友好。

RAG 用最便宜的方式,让模型"外挂"了知识库。

# 69. RAG 标准流程拆解?

离线(建索引):

  1. 加载(Loader):读 PDF / Word / Markdown / Notion / 数据库;
  2. 切片(Splitter):按 token / 段落 / 语义切成小块;
  3. Embedding:每块算向量;
  4. 入库:向量 + 元数据进向量库。

在线(查询):

  1. Query 预处理:改写、拆解、补全;
  2. 检索:向量召回 + 关键词召回(Hybrid Search);
  3. 重排(Rerank):用 Cross-Encoder 重新打分排序;
  4. 拼接:把 top-N 片段填入 prompt;
  5. 生成:LLM 输出回答(带引用)。

每一步都有调优空间,90% 的 RAG 问题出在切片和检索

# 70. 文档怎么切片(Chunking)?什么大小合适?

切片是 RAG 里最容易出问题的环节。常见策略:

策略 说明 适合
固定 token 比如每 500 token 切一块 简单粗暴,通用
按段落 / 标题 \n\n# Markdown / 结构化文档
递归切分 大→小,多级 fallback LangChain 默认
语义切分 按句子向量相似度切 长文、效果好但慢
Late Chunking 先 embedding 整段再切 新方法,召回更好

切片大小

  • 太小(< 100 token):每块语义不完整,检索召回散;
  • 太大(> 1000 token):召回准了但塞进 prompt 浪费 token;
  • 常用:300 - 600 token + 50 - 100 overlap

实战建议:先用默认 500/50 跑通,根据召回质量再调

# 71. Embedding 模型怎么选?

按场景:

  • 中文场景:bge-m3、Qwen-embedding、jina-zh;
  • 英文 / 多语言:text-embedding-3-large、bge-large-en;
  • 私有化:bge / m3e(开源、自己部署);
  • 资源紧 / 维度敏感:bge-small(384 维)。

几个易错点:

  • 一份索引必须绑定一个 embedding 模型,换模型必须全量重建;
  • 维度越高存储和检索越贵,1024 / 1536 是甜点
  • query 和 document 用同一个 embedding 模型,且 query 端经常需要前缀(Query: ...)。

# 72. 向量数据库怎么选?

选型 推荐
已有 PostgreSQL,量不大 pgvector
中量、需要快速上手 Chroma(本地 / 内存)
中大型 + 多语言 + 高性能 QdrantWeaviate
大型 + 企业级 / 国内开源 Milvus(生态最全)
Serverless 托管 Pinecone、Vercel Vector
不想引入新组件 Elasticsearch dense_vector

记住:别一上来就上 Milvus,量小时 pgvector 完全够用,运维成本低一个数量级。

# 73. 检索召回准不准?怎么改进?

如果用户问 X 但召回的都是 Y,检查顺序:

  1. 切片是否合理(最常见根因):太碎 / 太大都会出问题;
  2. Embedding 模型是否适合中文 / 业务领域
  3. Query 改写:把用户口语化的 query 改成更标准的检索 query;
  4. 加入 BM25 / 关键词召回做 Hybrid:向量召回擅长语义、BM25 擅长精确词,结合更稳;
  5. Reranker 重排:召回 50 条 → 重排 top 5 → 塞 prompt;
  6. 元数据过滤:按部门 / 时间 / 文档类型先过滤再向量检索;
  7. 检查文档本身:很多时候是文档质量太差,不是 RAG 不行。

# 74. 什么是 Hybrid Search(混合检索)?

向量检索 + 关键词检索(BM25 / Elasticsearch)两路同时召回,再合并打分

为什么有效?

  • 向量召回擅长语义相似但用词不同("忘记密码" ↔ "登录不上");
  • BM25 擅长精确匹配(产品编号、报错代码、专有名词);
  • 合并起来覆盖更全。

合并算法常用 RRF(Reciprocal Rank Fusion),简单稳定。

# 75. Reranker 是什么?为什么向量召回还不够?

向量召回用的是 bi-encoder:query 和 doc 各自编码后比相似度,速度快但精度有限。

Reranker 是 cross-encoder:把 query 和 doc 拼起来一起进模型,输出一个相关性分数。精度高,但每对都要算一次,慢

工程标准做法:

  1. 用向量召回召出 30-100 条候选
  2. 用 reranker 重排选 top 5-10
  3. 把 top 拼进 prompt。

常用模型:bge-reranker、Cohere Rerank、Jina Reranker。

# 76. 什么是 GraphRAG / Agentic RAG?

进阶 RAG 思路:

  • GraphRAG:把文档抽成「实体 + 关系」的知识图谱,回答时不仅检索片段,还检索实体关系。适合"涉及人物 / 公司 / 关系网络"的复杂问答。微软研究院推得多。
  • Agentic RAG:用 Agent 来跑 RAG,模型自己决定:要不要查、查几次、查完够不够、要不要再查。适合多跳推理(A → 找 B → 再查 C)。LangGraph 的图编排能直接干这事。

普通 RAG 一问一答,Agentic RAG 可以反复检索

# 77. RAG 怎么评估效果?

最少四个指标:

  1. 召回率(Recall):理论上应该被检索到的片段,实际有多少被检索到;
  2. 精确率(Precision):检索到的片段里有多少真的相关;
  3. 回答正确率:用 LLM-as-Judge 判断回答是否准确(需要 ground-truth 集合);
  4. 引用准确率:回答里引的片段是不是真的支持这个回答。

工具:RAGAS(最常见)、TruLens、DeepEval。

# 78. RAG 中怎么减少幻觉?

不是 RAG 自动就不幻觉,工程上要做:

  1. 强制要求引用回答中每个事实必须用 [片段编号] 注明出处
  2. 拒答提示如果检索片段中没有相关内容,必须回答"不知道"
  3. 后置校验:用第二个 LLM 检查引用片段是否真的支持回答;
  4. 检索阈值:相似度低于 X 的片段不参与生成;
  5. Self-RAG / 反思 RAG:模型先判断需不需要检索、再判断结果够不够。

# 79. 长文档怎么处理?

长文档(论文、合同、手册)的几个套路:

  1. 层次摘要:每章 / 每节先做摘要存起来,问答时先用摘要定位章节,再下钻到具体片段;
  2. 结构化目录:把目录抽出来当索引,用户问题先定位章节再精检索;
  3. 多粒度索引:句子级 + 段落级 + 章节级都建索引,按问题类型选;
  4. 元数据驱动:用文档类型 / 章节 / 日期等元数据缩小检索范围;
  5. 超长上下文模型补刀:定位到某一章后,把整章塞进 200k 上下文一次性问。

# 80. RAG 的 prompt 模板长什么样?

你是一名 [角色],根据以下检索到的资料回答用户问题。

# 规则
1. 仅基于下面的资料回答,资料里没有的内容请回答"我不确定"。
2. 每个事实都要标注引用编号,如 [1]、[2]。
3. 如果资料之间有冲突,请同时列出并说明。

# 资料
[1] {{chunk_1}}
[2] {{chunk_2}}
[3] {{chunk_3}}

# 用户问题
{{question}}

# 输出格式
回答:...
引用:[1], [2]

记住三点:强约束、强引用、强拒答

# 81. 长上下文模型出来后 RAG 还需要吗?

需要,原因:

  • 成本:1M 上下文一次几美元,RAG 一次几分;
  • 延迟:长上下文 TTFT 慢得多;
  • 效果:Lost in the Middle,关键信息不一定能用上;
  • 可解释性:RAG 能告诉用户"答案出自哪个文档",长上下文做不到;
  • 数据范围:企业知识动辄 GB / TB 级,根本塞不进任何上下文。

长上下文是 RAG 的互补,不是替代。

# 82. RAG 的离线评估和在线评估区别?

  • 离线:准备一组标注好的 query + 期望答案,每次迭代跑全量,看指标趋势。便宜、可重复
  • 在线:用真实用户流量看转化率、点踩率、停留时间、问完是否追问。贵但真实

工程上的标准做法:离线主导迭代 + 在线小流量验证 + 用户反馈回灌

# 83. Contextual Retrieval 是什么?

Anthropic 2024 年推的检索增强技巧。核心:切片之前,先用 LLM 给每个 chunk 加一段「上下文说明」,把它在原文里的位置 / 关系交代清楚。

例子:

  • 原 chunk:"上一财年净利润同比下降 3.4%。"
  • 加上下文:"以下内容来自 ABC 公司 2025 年 Q4 财报中关于经营业绩的章节:上一财年净利润同比下降 3.4%。"

效果:

  • 检索召回率显著上升(论文 +35%-50%);
  • 重排 + 上下文检索叠加效果更好;
  • 代价是预处理多调一遍 LLM,靠 Prompt Caching 把成本压住

适合碎片化文档 / 简短切片的场景。

# 84. 父子切片(Parent-Child Chunking)是什么?

矛盾:切片太小召回不准、切片太大占 token。

父子切片的做法:

  • 小 chunk 用于检索(200 token,语义精确);
  • 大 chunk 用于喂模型(800 token,上下文完整);
  • 每个 small chunk 有 parent_id 指向 large chunk。

流程:用 query 召回 small chunks → 找它们的 parent → 用 parent 内容喂模型。

效果:召回更准、上下文更全,生产 RAG 常用套路

# 85. 多向量检索(Multi-Vector Retrieval)是什么?

一个 chunk 不止存一个向量,而是存多个:

  • 原文向量;
  • 用 LLM 抽取的"假设问题" 向量;
  • 摘要向量;
  • 关键词向量。

检索时这些向量都参与召回,最后合并去重。

好处:

  • 用户问题和文档表述不一致时,"假设问题"能命中;
  • 长文档对应的多个角度都能召回。

代价是存储多倍 + 入库慢,适合关键文档

# 86. ColBERT 和 Dense Retrieval 区别?

  • Dense Retrieval(普通向量检索):query 和 doc 各压成 1 个向量,比相似度;
  • ColBERT:query 和 doc 都保留每个 token 的向量,检索时 token-级别匹配(MaxSim)。

ColBERT 优势:

  • 召回精度更高(token 级匹配能抓细节);
  • 比 cross-encoder 重排快很多。

劣势:

  • 存储成本几十倍上升;
  • 索引复杂;
  • 工程实现少(生产用得不多)。

记一句话:精度 > 速度 → cross-encoder rerank;速度 + 中精度 → ColBERT;速度 + 低成本 → Dense

# 87. RAG 的"幻觉引用"怎么处理?

模型答出来的内容里引用了根本不在召回片段里的事。两步处理:

  1. 结构化输出强约束引用:每个事实必须带 [N] 编号;
  2. 后置校验:用代码 / 第二个 LLM 检查引用编号对应的 chunk 是否真的支持这条事实。

校验失败两种处理:

  • 软:标红显示"此条未找到出处";
  • 硬:直接删掉无引用的句子。

不要相信"我已经在 prompt 里要求带引用",模型还是会编

# 88. RAG 的索引更新策略?

文档会改、会删、会加。常见策略:

策略 说明 适合
全量重建 定期(每天 / 每周)完全重新算 文档变化不频繁
增量更新 监听 webhook,文档改了就单独更新对应 chunk 文档变化快
软删除 标记 deleted,检索过滤 频繁删除
版本化 每篇文档保留多个版本,按时间查 法规 / 历史溯源

工程上要点:

  • chunk 必须有 doc_id 元数据,便于按文档操作;
  • 删除 / 更新走异步队列,不阻塞业务写
  • 检索时按 valid=true 过滤;
  • 大量更新后跑回归测试,召回质量可能波动

# 89. RAG 的"冷启动"问题怎么解?

新业务、文档少、用户问的常常超出知识库范围,回答质量差。

解法:

  1. 承认局限:拒答 + 转人工,比瞎答好;
  2. FAQ 补齐:让运营手写常见问题 + 答案,直接进知识库;
  3. 从客服日志 / 历史工单蒸馏:把已答问答对入库;
  4. 联网检索兜底:库里没有的允许走搜索 API;
  5. 缩小用户期望:UI 文案明确"我能回答 XX 类问题"。

# 90. RAG 的"重排"什么时候必须做?

下面情况几乎必加 Reranker:

  • 召回 top-k 中相关度参差不齐;
  • 业务专有名词多(产品编号、报错码);
  • 多语言混合;
  • 文档质量不均;
  • 用户问题口语化严重。

跳过 Reranker 的成本:召回的 chunk 顺序差 → LLM 看 prompt 时把"无关 chunk"也当成事实 → 幻觉。多花 200ms 一次重排,省一堆幻觉


# 五、Function Calling / 工具调用 / MCP

这一年面试问得最多的实战题之一。能讲清"Function Calling 怎么走完一轮"和"MCP 解决了什么问题",就证明你真的写过 Agent。

# 91. Function Calling 是什么?背后的机制?

模型不会直接执行任何函数,它做的事是:

  1. 收到 prompt 和工具列表(包含 name / description / parameters schema);
  2. 模型判断该调用哪个工具、参数是什么,以 JSON 形式吐出来
  3. 你的代码读到这个 JSON → 实际执行函数 → 把返回值拼成 ToolMessage 喂回模型;
  4. 模型基于新结果继续决策。

本质上 Function Calling = 模型负责"决策 + 参数生成",你的代码负责"执行 + 反馈"

# 92. Function Calling 一次完整流程?

tools = [{
  "name": "get_weather",
  "description": "查询某城市当前天气,返回温度和天气状况。",
  "parameters": {
    "type": "object",
    "properties": {
      "city": {"type": "string", "description": "城市名,如'北京'"}
    },
    "required": ["city"]
  }
}]

messages = [{"role": "user", "content": "北京今天天气怎么样?"}]

# 第一次调用:模型决定调工具
resp = llm.chat(messages, tools=tools)

if resp.tool_calls:
    for call in resp.tool_calls:
        result = TOOLS[call.name](**call.arguments)
        messages.append(resp.message)
        messages.append({
          "role": "tool",
          "tool_call_id": call.id,
          "content": str(result)
        })

# 第二次调用:模型基于工具结果继续
final = llm.chat(messages)
print(final.content)  # 北京今天 26 度,晴

要点:

  • 同一次回答可能返回多个 tool_calls(并行执行更快);
  • tool_call_id 要对得上,否则模型会蒙;
  • 工具执行失败也要把错误塞回去,让模型自己决定怎么办(重试 / 换工具 / 报错)。

# 93. 工具描述写得好不好直接决定调用准不准?

模型理解工具只靠你写的 description + parameters schema。写得不好会出三类问题:

  1. 该调没调:描述模糊,模型没意识到这个工具能解决;
  2. 调错工具:两个工具描述相似,模型抓阄;
  3. 参数错:字段名 / 必填 / 枚举值 / 单位没说清。

实战经验:

  • 描述写"能做什么"+ "不能做什么" + "典型用法";
  • 参数字段加 取值范围、单位、格式、示例
  • 必填的字段 description 里再强调一遍 "Required";
  • 工具数量超过 15 个就分组加载,不要全部塞 system

# 94. Function Calling 和 JSON Mode 有什么区别?

JSON Mode Function Calling
目的 让输出是合法 JSON 让输出符合特定函数 schema
用法 一个布尔开关 定义 tools 列表
严格度 只保证合法 JSON 保证字段 / 类型 / 必填
适合 自由 schema 输出 精确控制结构
是否触发调用流程 不会 会进入 tool_calls 循环

需要结构化输出但不需要后续调函数:用 Structured Output / JSON Schema 即可,不用走完整 Tool Calling 循环。

# 95. 多个工具同时调用怎么管?

现代模型(GPT-4o / Claude / DeepSeek-V3)一次回答可以返回多个 tool_calls

工程上:

  1. 检查是否可并行:纯读 / 无依赖的工具直接 Promise.all 并发;
  2. 有依赖的串行:比如"先查订单再退款",必须等订单查完;
  3. 合并结果:所有结果都加进 messages 后再调下一轮 LLM;
  4. 失败处理:单个工具失败不要影响其他,把失败信息也塞回去让模型决定

# 96. 工具调用失败怎么处理?

不要直接 throw 给 Agent 框架。统一格式塞回去:

try:
    result = tools[call.name](**call.arguments)
    content = json.dumps({"success": True, "data": result})
except ValidationError as e:
    content = json.dumps({"success": False, "error": "invalid_params", "msg": str(e)})
except TimeoutError:
    content = json.dumps({"success": False, "error": "timeout"})
except Exception as e:
    content = json.dumps({"success": False, "error": "internal", "msg": str(e)})

让模型看到错误后自己决定

  • 重试(参数错的话改参数再试);
  • 换工具;
  • 跟用户解释。

# 97. 工具结果太大怎么办?

工具返回 50k token 直接塞回 LLM 就炸了。常见做法:

  1. 裁剪:只取前 N 行 / 关键字段;
  2. 摘要:用小模型把结果摘成 1k token 以内;
  3. 分页:让模型自己决定要不要看后面几页;
  4. 存档 + 引用:完整结果存对象存储,工具返回一个引用 ID,需要详情时再单独取;
  5. 结构化裁剪:根据请求里的字段筛选返回内容。

# 98. 工具调用的"幂等性"为什么重要?

Agent 有时会重试 / 重复调同一个工具。如果不是幂等的:

  • 重复扣款;
  • 重复发短信;
  • 重复创建订单。

要做的事:

  • 写操作必须支持 idempotency_key(前端生成 UUID 传给工具);
  • 服务端用这个 key 做去重;
  • 危险操作(删除 / 转账)走 HIL,让用户确认。

# 99. MCP 是什么?为什么需要它?

MCP = Model Context Protocol(模型上下文协议,Anthropic 提出,OpenAI / Google 等厂商陆续支持)。

要解决的问题:Function Calling 没有跨厂商 / 跨进程 / 跨语言的标准协议

每个厂商自己定义 Tool Calling 的格式,工具是用 Python 写的还是 Node 写的都得重新接一遍。MCP 把这件事协议化

  • 工具方实现 MCP Server(用什么语言无所谓,按协议跑就行);
  • 客户端(Claude Code / Cursor / 自研 Agent)通过 MCP 协议连这些 Server;
  • 协议规定了 list_tools、call_tool、list_resources、list_prompts 等标准接口(底层基于 JSON-RPC)。

效果:写一次工具,所有支持 MCP 的客户端都能用

# 100. MCP 的三层核心结构(Server / Client / Bridge)

很多面试官会追问 MCP 的结构,按三角色记:

  • Server(工具服务端):提供一组可用的工具 / 资源 / Prompt(如文件读写、数据库、HTTP 请求、图像生成);
  • Client(模型 / IDE / Agent):通过协议访问 Server,把工具能力暴露给 LLM;
  • Bridge(中间层):负责协议转发、权限校验、上下文同步、日志审计。Claude Code / Cursor 自身就充当 Bridge 角色。

调用链路:

LLM → Function Calling → MCP Client → (Bridge) → MCP Server → 真实外部资源

工程上:Server 由工具方独立维护,Client 由 Agent 框架实现,Bridge 决定了"哪些工具能被哪个用户哪个会话调用",是企业级权限和审计的关键点。

# 101. MCP 和 Function Calling 是替代关系吗?

不是。

  • Function Calling 是模型理解工具的方式(schema → JSON 调用);
  • MCP 是工具进程间通信的协议(stdio / HTTP / SSE)。

模型还是用 Function Calling 调工具,只是工具的实现可以放在另一个 MCP Server 里,跨语言、跨进程、跨机器。

类比 HTTP 和 RESTful:HTTP 是协议,RESTful 是风格,MCP 让"工具的封装"也变得跨生态可复用。

# 102. Function Calling vs MCP 全维度对比

维度 Function Calling MCP
定义者 OpenAI(2023) Anthropic(2024,事实标准)
核心目标 模型调用外部函数 模型与外部环境标准化交互
注册方式 静态注册(请求时塞 tools 列表) 动态发现 / 热加载
协议层 SDK 私有格式 JSON-RPC(任意语言)
工具描述 每次请求都拼进 system,token 暴涨 Client 启动时拉一次,可复用
安全机制 完全靠开发者自管 协议内建权限 + Bridge 兜底
跨语言 / 跨进程 受 SDK 限制 任意语言 + 跨进程(stdio / SSE / HTTP)
工具结果中转 必须人工塞回 messages 协议直接返回
适合场景 单 Agent 单语言、简单工具 多 Agent 协作 / IDE 集成 / 系统级控制

一句话:Function Calling 是模型协议,MCP 是生态协议。前者解决"模型怎么调函数",后者解决"函数怎么跨边界提供给模型"。

# 103. MCP Server 一般怎么实现?

最小 MCP Server(TypeScript):

import { Server } from '@modelcontextprotocol/sdk/server/index.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'

const server = new Server({ name: 'demo', version: '0.0.1' }, { capabilities: { tools: {} } })

server.setRequestHandler({ method: 'tools/list' }, async () => ({
  tools: [{
    name: 'echo',
    description: '把输入原样返回',
    inputSchema: {
      type: 'object',
      properties: { text: { type: 'string' } },
      required: ['text']
    }
  }]
}))

server.setRequestHandler({ method: 'tools/call' }, async ({ params }) => {
  if (params.name === 'echo') {
    return { content: [{ type: 'text', text: params.arguments.text }] }
  }
  throw new Error('unknown tool')
})

const transport = new StdioServerTransport()
await server.connect(transport)

跑起来 + 在 Claude Code / Cursor 的配置里注册 → 模型就能调你的工具。

# 104. MCP 三种传输方式(stdio / HTTP / SSE)怎么选?

  • stdio:通过子进程的标准输入输出通信。简单可靠、本地 / Claude Code / Cursor 默认
  • HTTP:远程服务的常规调用,无状态;
  • SSE:HTTP + 服务端推送,支持长连接 / 流式工具

工程上 90% 选 stdio。需要远程共享 / 跨机器才上 HTTP / SSE。

# 105. MCP 和 LangChain Tool 怎么共存?

实战做法:

  • 团队内部工具用 MCP Server 写,跨多个 Agent 客户端复用
  • LangChain 项目里可以装 @langchain/mcp 或类似适配器,把 MCP Server 自动转换成 LangChain Tool;
  • 反向也成立:LangChain Tool 也可以包成 MCP Server 暴露给外部客户端。

整体趋势:MCP 在成为事实协议,LangChain 不会消失但会从"封装一切"变成"和 MCP 互通"。

# 106. 工具调用的 token 怎么算?

容易被忽略:

  • 工具描述本身计费:所有工具的 description + parameters 都拼进 system,每次调用都计费;
  • tool_call 输出:模型吐的 JSON 算 output;
  • tool_result 输入:你回填的结果算 input;
  • 多轮调用:每轮所有历史都重新计费(除非命中 Prompt Caching)。

优化:工具描述精炼、结果裁剪、用 Prompt Caching、按需加载工具。

# 107. 工具权限 / 越权怎么控制?

模型本身没有权限概念,全靠你的代码兜底

至少做这几层:

  1. 工具白名单:当前会话 / 当前用户能看到哪些工具;
  2. 参数校验:执行前用 zod / JSON Schema 校验,类型不对直接拒;
  3. 数据范围隔离:工具内部根据 user_id 限定能查 / 写的数据范围;
  4. 危险操作 HIL:删除、转账、对外发消息都走人工确认;
  5. 审计日志:每次工具调用记录 who / when / what。

不要相信"模型不会调危险工具"。要假设它一定会调。

# 108. 工具集合怎么管理(工具一多模型选错)?

工具数量超过 10-15 个时模型选错率明显上升。常见策略:

  1. 分组:按业务域分组(订单组、商品组、用户组),用户问题先路由到组;
  2. 动态加载:根据用户问题用一个轻量分类器选出 top 3-5 个工具,再传给主 Agent;
  3. 多 Agent 分工:每个子 Agent 只看自己负责的工具;
  4. MCP Resources / Prompts:MCP 不只能注册 tools,还能注册 resources / prompts,把工具按粒度分层。

# 109. Skills 和 Function Calling 是什么关系?

Anthropic 提出的 Skills(技能)是更高一层的封装:

  • 一个 Skill 包含:一组工具 + 配套 prompt + 示例 + 触发条件
  • 模型按用户意图自动加载对应的 Skill;
  • 让 Agent 能力可以像插件一样发布、共享、复用。

可以理解为:Function Calling 是单工具,Skill 是工具 + Prompt 的组合包

# 110. 工具调用的"自描述"为什么重要?

工具的 schema 是模型理解工具的唯一信息源。模型看不到你的代码,只看 description + parameters。

自描述好 = 描述清楚 + 字段有约束 + 示例齐全。

不自描述(比如 description: "do thing")= 模型只能瞎调。

# 111. 一个常被问的场景:让 Agent 自动写代码并跑测试,应该怎么设计工具集?

最小工具集:

- list_directory(path): 看目录结构
- read_file(path): 读文件
- write_file(path, content): 写文件
- edit_file(path, old, new): 局部修改
- run_command(cmd): 执行命令
- search_code(pattern): 搜代码

关键设计:

  • edit_file 比 write_file 更安全,全量重写容易丢东西;
  • run_command 必须做白名单,禁止 rm -rfsudo 等;
  • 写文件必须先 read 再 write,避免误覆盖;
  • 每次工具调用都打日志,便于回放。

这就是 Cursor / Claude Code 内部的最小工具集形态。

# 112. 同一个 LLM 既给前端又给 Agent 用,工具怎么设计?

抽两层:

  • 底层业务接口:纯后端,保持原样不要污染;
  • AI 工具层:在业务接口外面套一层封装,做参数转换、权限收敛、错误格式化、结果裁剪。

不要直接把后端接口暴露给 Agent,否则:

  • 权限漏;
  • 错误信息泄露内部细节;
  • 返回数据太大;
  • 参数命名前后端不一致让模型困惑。

# 113. Anthropic Skills 是什么?和 MCP 什么关系?

Skills 是 Anthropic 提的 Agent 能力封装单元,比 MCP Tool 高一层

一个 Skill 包含:

  • 能力描述(什么时候用我);
  • 一组工具(怎么做);
  • prompt 模板 / 示例(具体怎么调);
  • 触发条件(什么场景自动加载)。

类比:MCP Tool 是函数,Skill 是「函数 + 调用手册 + 触发器」打包。

Claude Code 的 .claude/skills/ 目录就是 Skills 的物理形态,每个 Skill 一个 markdown + 配套脚本。

# 114. MCP 的 Resources、Tools、Prompts 三种能力区别?

MCP Server 能暴露三类东西:

类型 是什么 例子
Tools 模型主动调的函数 read_filerun_sql
Resources 模型可以读的"资料" 一个 README、一份 schema、一份配置
Prompts 预设的 prompt 模板 "用 X 风格生成 Y"

工程区别:

  • Tools 由模型决定何时调,Resources 由 Client 决定何时读
  • Resources 不消耗工具调用预算,但占 context;
  • Prompts 让用户能"选择 prompt 模板"而不是手敲。

实战 90% 用 Tools,Resources / Prompts 用得少但很有用。

# 115. MCP 有哪些常见的安全风险?

工具被模型自动调,安全模型必须有:

  1. 凭据泄露:MCP Server 持有 API key / DB 密码,被 prompt injection 套出来;
  2. 越权:Server 给所有 client 看同样工具,租户隔离没做好;
  3. 数据泄露:Resources 暴露了不该看的文件;
  4. 危险操作:模型自动 rm -rf、删数据库;
  5. 供应链攻击:第三方 MCP Server 里有恶意代码。

防御:

  • Bridge 层做权限:哪些用户能调哪些工具;
  • 白名单 + 危险操作 HIL
  • 审计日志:每次调用记录 who / when / what;
  • 第三方 Server 必须 review,不要随便装。

# 116. 常用的 MCP Server 有哪些?

2026 年生态已经丰富,按用途:

类别 代表 Server
文件 / Shell filesystem、shell、git
数据库 postgres、mysql、sqlite、mongodb
浏览器 puppeteer、playwright、chrome-devtools
搜索 brave、google、tavily
GitHub / GitLab github、gitlab
协作 slack、notion、linear、jira
设计 figma
监控 sentry、datadog
云服务 aws、gcp、azure

实战流程:能用现成的就用现成的,自研只在内部业务工具。

# 117. Computer Use 和 MCP 是什么关系?

不是替代,是互补:

  • MCP:通过协议调函数,精确、快、成本低
  • Computer Use:模型直接操作屏幕,通用但慢且贵

工程上的策略:

  1. 优先用 MCP(接 API / SDK 的场景);
  2. 没有 API 的老软件、跨多软件的复杂流程 → Computer Use 兜底;
  3. 混用:让 MCP 做主流程,Computer Use 处理零星 GUI 操作。

# 118. 怎么用 Python 写一个 MCP Server?

最小可运行(基于 mcp SDK):

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("demo")

@mcp.tool()
def add(a: int, b: int) -> int:
    """两数相加。"""
    return a + b

@mcp.tool()
def search_user(name: str) -> dict:
    """按用户名查询用户信息。"""
    return {"name": name, "email": f"{name}@example.com"}

if __name__ == "__main__":
    mcp.run()

Claude Code 配置:

{
  "mcpServers": {
    "demo": {
      "command": "python",
      "args": ["server.py"]
    }
  }
}

启动 Claude Code → 工具自动出现 → 模型能直接调用。

# 119. Function Calling 在 Agent 框架里的位置?

容易混淆:Function Calling、Tool、Agent 是不同层。

Agent  ← 整个跑循环的框架(决定顺序、错误处理、终止)
 └─ Tool(业务函数封装)
     └─ Function Calling(模型调用 Tool 的协议)
         └─ Model(LLM 本体)

实战:你写代码时直接写 Tools(业务函数),Agent 框架(LangChain / Agent SDK)负责处理 Function Calling 协议和循环。Function Calling 你基本不直接接触。


# 六、Memory 与上下文管理

大模型本质是无状态的。所谓"它记得我之前说过什么",其实都是你做的 Memory 管理。这一节决定 Agent 能不能跑长。

# 120. 大模型本身是无状态的,为什么 ChatGPT 能记住上文?

因为客户端 / 服务端帮它把历史 messages 拼回去了。每次请求都把整段对话历史塞进 prompt。

模型本身永远在做"看这次输入 → 产生这次输出"。你看到的"记忆"全是外部状态管理

这也解释了为什么对话长了会慢、会贵:每轮都重新带全量历史。

# 121. Memory 管理的核心矛盾是什么?

上下文窗口是有限的,但对话可能无限长

直接往 messages 里 push 早晚撞墙。所以要做有损压缩

  • 保留近期上下文(精确);
  • 把远期上下文压缩成摘要(粗糙);
  • 把"事实性内容"抽取出来存进结构化记忆 / 向量库(可检索)。

# 122. 短期记忆有哪几种实现?各自适合什么?

  1. 全量 messages:最简单,对话一两轮够用;
  2. 滑动窗口:只保留最近 N 轮,超过的丢掉。简单粗暴;
  3. 滑动窗口 + 摘要:丢掉前先摘要,最常用
  4. Token 上限驱动:按 token 数(不是轮数)滚动;
  5. 关键消息标注:用户标记的"重要消息"始终保留,其他可丢。

# 123. 长期记忆怎么做?

短期记忆只活在当前会话,长期记忆要跨会话

常见实现:

  1. 结构化记忆:抽取出"用户偏好 / 历史事件 / 关键事实"存数据库(user_id → JSON);
  2. 向量记忆:把每段重要对话 embedding 入向量库,下次提问时检索相关历史拼回 prompt;
  3. 图谱记忆:实体 + 关系存图数据库(Neo4j),适合"人物关系 / 项目关系";
  4. 文件 / 文档:让 Agent 把"我学到的东西"写成 markdown 文件,下次开会话先 read。

Claude Code 的 memory 系统就是文件型 + 索引型混合。

# 124. 滑动窗口的 N 怎么定?

经验值:

  • 简短闲聊:保留最近 8-12 轮;
  • 任务对话:保留最近 5-8 轮;
  • 长任务 / 编程:按 token,保留最近 10k-20k token。

要紧的不是 N,而是:

  • 超过 N 时先摘要再丢,别直接扔;
  • 关键消息(用户确认过的、Agent 写过文件的)独立保留。

# 125. 摘要压缩什么时机做?

不要"对话长了再说",否则用户会卡顿。常见两种时机:

  1. 定时:每 5 轮 / 每 N 个 token 就摘要一次(异步);
  2. 触发式:上下文剩余 token 不足 X 时强制摘要;
  3. 结束时:会话结束写一份"长期记忆"入库。

异步做摘要的好处是不阻塞主线程,用户感知不到。

# 126. 摘要丢关键信息怎么办?

工程上几条经验:

  1. 抽取式摘要 + 关键事实清单双轨:摘要负责"语义连贯",事实清单负责"不丢细节";
  2. 强约束 prompt:明确告诉摘要 LLM "用户确认过的事情、订单号、金额、时间等必须保留";
  3. 多级摘要:粗摘要 + 细摘要,按需取;
  4. 关键消息独立保留:不进摘要,永远在 messages 末尾。

# 127. 多用户怎么隔离记忆?

最起码三层:

  1. 会话级:session_id 隔离,每个会话独立 messages;
  2. 用户级:user_id 隔离,跨会话的长期记忆只能本人访问;
  3. 租户级(ToB):tenant_id 隔离,企业之间数据完全不可见。

实现上要点:

  • 向量库的查询必须带 metadata 过滤 user_id == 当前用户
  • 缓存层别误共享:模型缓存 / 工具缓存如果按 prompt key 命中,可能跨用户串数据;
  • 审计:所有记忆写入都记录 who + when + what。

# 128. 用户改主意了,记忆怎么处理?

例子:用户先说"我要订北京的酒店",几分钟后改成"算了改去上海"。

工程上:

  1. 覆盖式更新:用户最近一次表述优先,旧的标记为 outdated;
  2. 冲突检测:定期让 LLM 扫描记忆,发现冲突时提醒用户确认;
  3. 版本化:所有记忆带版本号 + 时间戳,回溯也方便;
  4. 不要悄悄"合并":合并意图容易出错,明确"以新为准"。

# 129. Agent 的"工作记忆"(Working Memory)是什么?

工作记忆 = 当前任务正在用的临时变量,区别于:

  • 短期记忆(对话历史);
  • 长期记忆(用户偏好 / 历史事件)。

例子:Agent 正在处理一个退款流程,工作记忆里临时存"订单号 = A100、退款金额 = 200、客户已同意 = true"。任务结束就丢。

实现上常见:

  • 用一个 dict / Redis 存当前 task_id → state;
  • 把工作记忆显式注入 prompt,让模型每步都能看到。

# 130. Memory 系统设计有哪几条铁律?

工程上踩过坑总结:

  1. 不要把所有 messages 都送给大模型:超贵且效果反而差;
  2. 可读性 > 完整性:摘要是为了让模型理解,不是给人看的;
  3. 写入读取分离:写入异步、读取同步;
  4. 可观测:能查每段记忆是怎么产生的、用过几次;
  5. 可撤销:用户能"清除我的记忆",符合 GDPR / 个保法。

# 131. 怎么让 Agent 记住"用户偏好"?

最常见两种:

  1. 显式存储:用户说"我以后回答都用中文",Agent 把这条写入 user_preferences 表,每次 system prompt 拼回去;
  2. 隐式学习:定期扫描历史对话,让 LLM 抽取偏好("用户喜欢简短回答"、"用户喜欢代码带注释"),更新偏好库。

不要靠"模型自己记住",模型不持久化任何东西。

# 132. 记忆系统的隐私和合规怎么做?

涉及 PII(个人身份信息)的:

  1. 采集前告知 + 同意
  2. 敏感字段加密存储(身份证、手机号、邮箱);
  3. **支持"删除我的所有数据"**接口;
  4. 导出我的数据接口;
  5. 审计日志:谁访问了我的记忆;
  6. 跨境传输合规:用海外模型时要考虑数据出境问题。

# 133. Memory 演进路线(从 demo 到生产)?

四步:

  1. 全量 messages:能跑就行;
  2. 滑动窗口 + 异步摘要:能跑长任务;
  3. 向量长期记忆:能跨会话;
  4. 图谱 / 结构化记忆 + 多层级:企业级 Agent。

不要一上来上第 4 步,对中小项目就是过度设计。

# 134. Claude Code 的 memory 系统怎么实现的?

Claude Code 的 memory 是「文件型 + 索引型混合」:

  • 每个会话 / 项目可以有 memory/ 目录;
  • 子目录按类型分:user.md(用户偏好)、feedback.md(修改习惯)、project.md(项目状态)、reference.md(外部资源);
  • 一份 MEMORY.md 索引每个 entry 的 title + 1-2 句话;
  • 模型按需 Read 索引或具体文件。

设计精髓:

  • 可读性强(人能看 / 改 / 删);
  • 可版本化(git 跟踪);
  • 可选读(不像全量 messages 那样必须带);
  • 支持显式编辑(用户能精准纠错)。

这种"显式可控的 memory"是 LLM 时代 memory 系统的主流思路。

# 135. Episodic Memory vs Semantic Memory 区别?

借自认知科学:

  • Episodic(情景)记忆:记得"具体发生过什么事"。例子:用户上次说想退款;
  • Semantic(语义)记忆:抽象出来的知识 / 偏好。例子:用户喜欢简短回答。

Agent 系统里这两种都要:

  • Episodic 适合当前任务推理("我和你之前说过 X");
  • Semantic 适合个性化定制(用户偏好、风格、规则)。

实现上:Episodic 用对话历史 + 向量库,Semantic 用结构化 key-value。

# 136. 多 Agent 共享 memory 怎么设计?

多个子 Agent 协作时,信息怎么传递

  1. 共享 state(LangGraph 做法):所有 Agent 都能读写一个 state 字典;
  2. Message Passing:子 Agent 之间发消息,主 Agent 协调;
  3. 共享存储 + 锁:Redis / DB 加分布式锁;
  4. 写一份事件流(Event Log):所有 Agent 看同一份事件流,各取所需。

最佳实践:

  • 别让所有 Agent 都看全量 memory,按角色过滤
  • 写入要有"是谁写的"标签,方便追责;
  • 多 Agent 并发写要序列化或加锁。

# 137. Memory 的访问控制(哪些 Agent 能读 / 能写)?

不同 Agent 信任级别不一样。常见做法:

  • 角色 = 权限:QA Agent 只读,Edit Agent 可写,Auditor Agent 全只读;
  • 白名单:每个工具 / memory 字段都列出允许的 Agent;
  • 审计:所有写入记录 actor + reason;
  • 回滚:保留写入历史,能 undo。

ToB 场景这是合规硬要求。

# 138. 用户偏好 Memory 怎么实战?

最常用方案:

// 结构化偏好表
interface UserPrefs {
  user_id: string
  language: 'zh' | 'en' | 'auto'
  response_style: 'concise' | 'detailed'
  preferred_models: string[]
  custom_instructions: string  // 用户自己写的"对我说话要..."
  topics_of_interest: string[]
}

注入方式:

  • 每次 system prompt 拼一段 ## 用户偏好\n{prefs}
  • 模型回答前能感知;
  • 用户能在 UI 上显式编辑这份偏好。

不要让模型"自己猜偏好",给用户编辑入口才合理。

# 139. 怎么判断一段记忆该不该写?

不是所有对话都值得长期记忆。判定规则:

  • 用户明确说"记住这个":必写;
  • 用户偏好性表达("我以后都用中文回答"):必写;
  • 关键事实(订单号、地址、ID):必写;
  • 闲聊 / 重复确认:不写;
  • 会过期的状态("我现在很忙"):不写或加 TTL。

简单粗暴的"全写"会把记忆库污染。让一个轻量 LLM 做记忆筛选是常见做法。


# 七、LangChain / LangGraph 框架

不是所有团队都用 LangChain,但面试官几乎都会问。能讲清"LangChain 解决了什么"和"什么时候用 LangGraph",比背 API 强。

# 140. LangChain 是什么?它真正帮你做了什么?

LangChain 把"LLM 应用开发的常见动作"封装成可组合的组件:

  • Models:统一调多家 LLM 的接口;
  • Prompts:模板、变量、few-shot 管理;
  • Output Parsers:把模型输出解析成结构化数据;
  • Tools / Toolkits:工具定义 + Function Calling 流程;
  • Memory:对话历史 / 长期记忆封装;
  • Retrievers:向量库 / RAG 检索抽象;
  • Chains / LCEL:把上面这些链式拼起来
  • Agents:常见 Agent 模式(ReAct、Plan-and-Execute 等)。

简单说:它让你不用从零写 prompt 拼接、工具调度、错误重试这些脏活

# 141. LCEL(LangChain Expression Language)是什么?

LangChain 的管道语法,用 | 把组件串起来:

const chain = promptTemplate
  .pipe(model)
  .pipe(outputParser)

const result = await chain.invoke({ topic: 'AI' })

好处:

  • 写起来像 Unix pipeline,直观;
  • 自动支持 batch / stream / async;
  • 容易换组件(换模型只改 .pipe(model))。

LCEL 适合线性流程,分叉 / 循环 / 条件就该上 LangGraph。

# 142. LangGraph 是什么?为什么有了 LangChain 还要它?

LangChain 的 chain 是线性管道,无法表达:

  • 条件分支(这步成功才走下一步);
  • 循环(不达标就回头);
  • 多 Agent 并行 / 协作;
  • 显式状态管理。

LangGraph 是图编排引擎,节点 = 一个动作(LLM 调用 / 工具调用 / 自定义函数),边 = 转移规则。

适合:

  • 多 Agent 协作;
  • Agentic RAG(要不要再查一次);
  • 复杂工作流(审批、订单、客服路径);
  • 显式可视化整个 Agent 流程。

# 143. 用 LangGraph 写一个最小图怎么写?

import { StateGraph, END } from '@langchain/langgraph'

const graph = new StateGraph<{ input: string; output?: string }>({
  channels: { input: null, output: null }
})

graph.addNode('plan', async (state) => ({ output: `planned: ${state.input}` }))
graph.addNode('execute', async (state) => ({ output: `done: ${state.output}` }))

graph.addEdge('plan', 'execute')
graph.addEdge('execute', END)

graph.setEntryPoint('plan')

const app = graph.compile()
const result = await app.invoke({ input: 'hello' })

关键概念:

  • State:所有节点共享的状态(合并而非覆盖);
  • Node:一个动作;
  • Edge:节点间转移;
  • Conditional Edge:根据 state 决定走哪条边;
  • Checkpoint:每步状态可以存到 DB,支持中断 + 恢复(HIL 神器)。

# 144. Runnable 是什么?为什么所有组件都是 Runnable?

LangChain 给所有组件定义了一个统一接口 Runnable:

interface Runnable<I, O> {
  invoke(input: I): Promise<O>
  stream(input: I): AsyncIterable<O>
  batch(inputs: I[]): Promise<O[]>
}

任何组件(Prompt、Model、Parser、Tool、Chain)都实现这个接口,所以才能用 | 串起来。

类比 React 的 component:只要符合接口,就能复用 / 组合。

# 145. Output Parser 和 Tool Calling 怎么选?

  • Output Parser:模型输出文本,你写正则 / JSON 解析。适合输出格式相对自由 + 不需要严格 schema 的场景;
  • Tool Calling / Structured Output:模型按 schema 输出。适合严格 JSON / 字段必填 / 类型检查

经验:

  • 简单解析(提取一段总结、抽几个关键词)→ Output Parser;
  • 复杂结构化(多字段、嵌套、必填)→ Tool Calling;
  • 流式场景:Output Parser 支持流式增量解析,Tool Calling 通常等完整 JSON。

# 146. Prompt Template 和写字符串拼接的区别?

字符串拼接看起来够用,但写多了会有:

  • 变量散在各处难追踪;
  • 多语言 / 模板复用难;
  • 没法自动绑定 few-shot;
  • 没法集成版本管理 / 灰度。

PromptTemplate 把 prompt 当一等公民:变量声明清晰、可继承、可序列化、可版本化。

# 147. LangChain 全部 Splitter,挑哪个用?

90% 场景用一个就够:RecursiveCharacterTextSplitter

它会按 \n\n → \n → " " → "" 递归切分,尽量保持段落完整。

其他特殊场景:

  • 代码:Language.PYTHON / JS / ... 专用 splitter;
  • Markdown:MarkdownHeaderTextSplitter,按标题层级切;
  • HTML:HTMLHeaderTextSplitter
  • 语义:SemanticChunker(嵌入模型驱动,慢但效果好)。

# 148. 怎么把 LangChain 的链接到 Nest / Next API?

Nest 后端最小骨架:

@Controller('chat')
class ChatController {
  @Post('stream')
  async stream(@Body() body: { input: string }, @Res() res: Response) {
    res.setHeader('Content-Type', 'text/event-stream')
    res.setHeader('Cache-Control', 'no-cache')

    const chain = prompt.pipe(model).pipe(parser)
    const stream = await chain.stream({ input: body.input })

    for await (const chunk of stream) {
      res.write(`data: ${JSON.stringify(chunk)}\n\n`)
    }
    res.end()
  }
}

前端用前面给的 SSE 模板读就行。

# 149. LangSmith 是什么?为什么所有 LangChain 项目都建议接?

LangSmith = LangChain 的可观测平台

接入只要加三个环境变量:

LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=...
LANGCHAIN_PROJECT=my-project

跑起来后所有 Chain / Agent 调用都自动上报,可以看:

  • 每一步的 prompt、输入、输出;
  • 每步 token、耗时、cost;
  • Agent 的完整调用树;
  • 失败 trace 一键回放;
  • 历史调用打 dataset,跑评估。

工程上没有可观测 = 没法调优 = 没法上线。强烈建议从第一天就接

# 150. LangGraph 的 Checkpoint 怎么用?

Checkpoint 是 LangGraph 的杀手锏:每步状态都能保存到 DB,所以可以:

  • 中断后恢复(用户离开几小时后接着跑);
  • HIL(跑到关键节点暂停,等用户确认);
  • 时间旅行(回到之前某一步重新执行);
  • 多用户并行运行不同 thread。

最简单 sqlite checkpoint:

import { SqliteSaver } from '@langchain/langgraph-checkpoint-sqlite'

const checkpointer = SqliteSaver.fromConnString('./checkpoints.db')
const app = graph.compile({ checkpointer })

const config = { configurable: { thread_id: 'user-123' } }
await app.invoke({ input: 'hello' }, config)
// 后面任何时候用同一个 thread_id 都能从上次断点继续

# 151. LangChain vs LlamaIndex 怎么选?

维度 LangChain LlamaIndex
定位 通用 LLM 应用框架 RAG 专精
强项 Agent、工具调用、链编排 文档加载、索引、检索
学习曲线 偏陡 相对简单
文档生态 庞大 聚焦
适合 复杂 Agent / 多步骤工作流 纯 RAG 场景

实战常见组合:LlamaIndex 做索引 + LangChain 做 Agent。两者也都能独立做完所有事。

# 152. LangChain 内置的 Agent 类型有哪些?怎么选?

Agent 类型 工作方式 适合
ReAct Agent 边想边调工具 通用
OpenAI Functions Agent 用 Function Calling 标准 OpenAI / Claude 系列
Plan-and-Execute 先规划再执行 长程任务
Self-Ask 自问自答分解问题 推理 / 多跳问答
Structured Chat 多工具结构化输出 工具数量多

2026 年趋势:直接用 Tool Calling Agent(基于模型自带 Function Calling),不用旧的 ReAct prompt-based Agent。

# 153. LangGraph 怎么做 Human-in-the-loop?

LangGraph 用 interrupt + Checkpoint 实现 HIL:

graph.addNode('confirm_payment', async (state) => {
  // 等待用户确认
  return await interrupt({ amount: state.amount, action: 'approve_or_reject' })
})

graph.addConditionalEdges('confirm_payment', (state) => {
  return state.approval === 'yes' ? 'execute' : 'cancel'
})

效果:跑到 confirm_payment 节点时保存当前状态 + 暂停,前端拿到状态展示给用户确认 → 用户决定 → 用 app.invoke({...}, { resume: 'yes' }) 继续。

适合所有"需要二次确认"的场景(付款、删除、对外发消息)。

# 154. LangGraph 的多 Agent 模式有哪些?

模式 拓扑 适合
Supervisor 主 Agent 派活,子 Agent 干完汇报 任务可拆解
Network 多 Agent 互相调用 复杂协作
Hierarchical 多层 supervisor 超大规模
Swarm Agent 之间 handoff 客服路由

Supervisor 是最常用的。Swarm(基于 OpenAI Swarm)适合"客户被不同专家接力服务"的场景。

# 155. LangChain 的 Memory 类型对比?

Memory 怎么用 适合
ConversationBufferMemory 全部带 demo
BufferWindowMemory 最近 N 轮 简单对话
SummaryMemory 用 LLM 摘要 长对话
SummaryBufferMemory 摘要 + 窗口混合 实战首选
VectorStoreMemory 向量检索历史 长期记忆
EntityMemory 抽取实体 + 关系 用户画像

生产用 SummaryBufferMemory 或者干脆自己写(LangChain Memory 抽象偶尔不够灵活)。

# 156. Vercel AI SDK 和 LangChain 是什么关系?

  • Vercel AI SDK:前端 / Edge / Node 全栈 SDK,主打流式 UIuseChatuseCompletion)、模型抽象(generateText / streamText)、Tool Calling 简化。前端友好,复杂 Agent 弱
  • LangChain:后端 Agent 框架,长链 / 多 Agent / 复杂工作流强。

实战常见组合:

  • 前端(Next.js)用 Vercel AI SDK 处理 UI / 流式 / 简单工具;
  • 复杂业务后端跑 LangChain / LangGraph Agent,通过 SSE 给前端推结果。

两个其实是不同层,不冲突

# 157. LCEL Streaming 怎么实现?

LangChain 所有 Runnable 都自带 .stream()

const chain = prompt.pipe(model).pipe(new StringOutputParser())

for await (const chunk of await chain.stream({ input: 'hi' })) {
  process.stdout.write(chunk)
}

后端给前端流式(Next.js Route Handler):

export async function POST(req: Request) {
  const { input } = await req.json()
  const stream = await chain.stream({ input })
  return new Response(stream.pipeThrough(new TextEncoderStream()), {
    headers: { 'Content-Type': 'text/plain' }
  })
}

或者用 Vercel AI SDK 的 LangChainAdapter.toDataStreamResponse(stream) 适配。

# 158. LangChain 怎么写一个完整 RAG chain?

最小骨架:

import { createRetrievalChain } from 'langchain/chains/retrieval'
import { createStuffDocumentsChain } from 'langchain/chains/combine_documents'

const ragPrompt = ChatPromptTemplate.fromTemplate(`
基于以下检索资料回答问题:
{context}

问题:{input}
`)

const docChain = await createStuffDocumentsChain({ llm: model, prompt: ragPrompt })
const ragChain = await createRetrievalChain({ retriever, combineDocsChain: docChain })

const result = await ragChain.invoke({ input: '什么是 RAG?' })
console.log(result.answer)

复杂场景(重排、Hybrid、HyDE)用 LCEL 拼,或者直接上 LangGraph 写图。


# 八、模型微调 / 私有化部署 / ToB 落地

资深岗 / ToB 岗常问。前端工程师不一定要会训练,但必须知道什么时候要微调、什么时候不要

# 159. 大模型在 ToB 业务里落地有哪些核心难点?

直接拿通用模型给企业用会撞上这些坑:

  • 不懂业务:训练语料是公网通用知识,对企业内部规章、产品文档一无所知;
  • 幻觉风险:不知道时不会闭嘴,会"看着像那么回事"地编;
  • 数据合规:员工 / 客户敏感信息不能直接送外部 API;
  • 响应慢、单价高:交互密集业务直接调外部模型不友好;
  • 可控性差:用户问答风格不符合公司话术。

主流解法:

  1. RAG:把企业知识向量化,给模型外挂记忆;
  2. 私有化部署:选开源模型(Qwen / DeepSeek / LLaMA)在自己机器上跑;
  3. 微调:把客服话术、产品规则训进模型;
  4. 工作流编排:Dify / Coze / FastGPT 把 Prompt + RAG + 工具串起来。

# 160. 模型幻觉的深层原因(再追问版)?

不只是"瞎说",拆开看:

  1. 概率模型的天然倾向:在"算最可能的下一个 token",不是"查事实";
  2. 训练语料噪声:互联网真假混杂;
  3. 没有事实校验:出结果时不会回头验证;
  4. 上下文断裂:检索片段不全时会自动"补缝";
  5. 任务边界模糊:开放性问题模型倾向于"展开发挥"。

减少幻觉是组合拳:RAG + 引用 + 二次校验 + 低温 + 拒答指令。

# 161. 微调(Fine-tuning)核心是什么?什么时候才该用?

在已经预训练好的模型上用领域数据继续训练,把权重调整到对该领域更敏感。理解成"再上岗培训",不是"重新培养"。

适合:

  • 输出格式 / 风格特别固定(客服话术、报告模板);
  • 行业术语 / 知识体系密集(医疗、法律、金融);
  • prompt 膨胀到不可控,希望把规则"内化"省 token;
  • 闭源场景下本地化部署。

不适合

  • 业务规则会频繁变(每次都重训性价比低);
  • 数据少(< 200 条);
  • 短期内 RAG / Prompt 还能优化。

# 162. 全参微调 vs PEFT(LoRA / QLoRA)区别?

Full Fine-tuning PEFT
训练对象 全部权重 一小部分(增量矩阵)
显存 极高(70B 几百 G) 单卡 24G 也能玩
训练速度 快几倍到十几倍
效果上限 最好 略弱,95% 场景够用
过拟合 / 灾难性遗忘 容易 影响小
适合 大厂底座 中小团队业务定制

99% 应用层用 PEFT 就够,LoRA / QLoRA 是甜点

# 163. LoRA 为什么能省显存?

核心思想:别动原矩阵,旁边加两个小矩阵

数学上:原权重 W 冻结,新增低秩矩阵 A、B(rank 通常 8 - 64),让 W' = W + A·B。训练只更新 A、B(参数量小一两个数量级),推理时把 A·B 合并回去。

收益:

  • 显存占用大幅下降;
  • 训练速度快几倍;
  • 训完只存 A、B(几十 MB),换底座或叠加多个 LoRA 都方便;
  • QLoRA 进一步把基座量化到 4bit,单卡能玩 70B。

# 164. 微调要准备什么数据?格式怎么定?

数据类型

类型 形态 适合
指令数据 {instruction, input, output} 让模型听特定指令
对话数据 messages: [{role, content}] Chat 类模型
知识 QA 上下文 + 问答对 强化领域问答
偏好数据 {prompt, chosen, rejected} DPO / RLHF 对齐

质量比数量重要

  • 1000 条干净 > 10 万条杂乱;
  • 去重、去矛盾、去低质;
  • 风格 / 长度 / 格式统一(模型很会学风格);
  • 留 5-10% 做验证集;
  • token 长度尽量贴近实际推理分布。

# 165. 私有化部署有哪些选项?

按规模:

规模 推荐
单机 / 玩具 Ollama、LM Studio、llama.cpp(CPU/Metal)
单卡生产 vLLM + 14B-32B 量化模型
多卡 / 高并发 vLLM / SGLang + 70B 模型
集群 TGI / Triton + K8s
企业一体机 阿里 / 腾讯 / 火山 / 智谱的私有化解决方案

vLLM 是事实标准,PagedAttention 让吞吐高出传统几倍。

# 166. Dify / Coze / FastGPT 这类平台怎么选?

维度 Dify Coze FastGPT LangFlow
开源 否(字节托管)
私有部署
国内合规 看部署 友好 友好 看部署
工作流可视化 是(LangChain 底)
Agent / 多 Agent 灵活但要写
模型支持 主要豆包 / GPT
适合 通用快速搭建 字节生态 / 抖音渠道 知识库为主 已用 LangChain

选型小结:

  • 想完全自控 + 私有化:Dify / FastGPT;
  • 抖音 / 飞书 / 公众号:Coze;
  • 重 RAG 知识库:FastGPT 起步快;
  • 已用 LangChain + 想可视化:LangFlow。

# 167. 自己搭 LLM 应用平台 vs 用 Dify?

自己搭 用 Dify
上手
定制 自由 受抽象限制
维护 全自己 跟社区版本
性能 可极致优化 中规中矩
适合 超大流量 / 强定制 中小项目 / 内部工具 / MVP

务实结论:MVP / 内部工具用 Dify 先跑通,核心业务自研,混合最常见

# 168. Function Calling 的优缺点?为什么很多团队转 MCP?

优点:上手快、几乎所有 SDK 都支持、模型生态成熟。

缺点

  • 没有跨厂商标准;
  • 工具描述全靠塞 prompt,工具多了 token 暴涨;
  • 没内建权限模型;
  • 跨语言 / 跨进程不友好;
  • 工具发现 / 热加载难。

这些短板正是 MCP 想解的,所以 2026 年明显朝 MCP 倾斜。

# 169. Agent Loop 在工程里有哪些坑?

跑过 Agent 的人都被这些坑过:

  • 死循环 / 振荡;
  • Token 烧得飞快;
  • 错误被放大;
  • 越权风险;
  • 不会停。

兜底必做:

  1. 设硬上限(步数 / token / 时间);
  2. 重复检测;
  3. 工具白名单 + 危险操作二次确认;
  4. 全链路日志;
  5. 上下文压缩。

# 170. ElasticSearch / 倒排索引在 AI 场景的作用?

向量检索擅长语义,倒排索引擅长精确匹配 / 关键词 / 字段过滤

在 RAG 场景下,最佳实践是 ElasticSearch + 向量库混合检索

  • ES 做 BM25 召回 + 字段过滤(按部门、时间、标签);
  • 向量库做语义召回;
  • RRF 合并结果。

如果团队已经有 ES 集群,可以直接用 ES 的 dense_vector + KNN,少引入一个组件。

# 171. Neo4j / 知识图谱在 AI 场景的作用?

把"实体 + 关系"显式建模成图:

  • 节点:人、公司、产品、订单;
  • 边:归属、关联、引用、合作。

适合:

  • 多跳推理("客户 A 的关联公司在哪些行业有业务?");
  • 反洗钱 / 合规审查(关系穿透);
  • 个性化推荐(基于关系)。

GraphRAG 就是基于知识图谱的 RAG,适合关系复杂、单文档语义不够的场景

# 172. Docker Compose 在 AI 开发提效里能做什么?

本地一键起依赖(向量库 + Redis + Postgres + 监控):

services:
  milvus:
    image: milvusdb/milvus
    ports: ['19530:19530']
  redis:
    image: redis:7-alpine
  postgres:
    image: pgvector/pgvector:pg16
  langfuse:
    image: langfuse/langfuse

docker compose up -d 一秒起完,免去手动安装。

生产场景一般会上 K8s,但 dev / 测试 / 小型企业一直用 Compose 也合理。

# 173. LangSmith / Helicone / Langfuse 选哪个?

LangSmith Helicone Langfuse
开源
自部署 部分
和 LangChain 集成 原生 通用 原生
数据集 / 评估
价格 自部署免费

中小项目 / 合规要求高 → Langfuse 自部署;已用 LangChain + 不在意合规 → LangSmith。

# 174. vLLM 为什么吞吐高?

vLLM 推理引擎的两个核心创新:

  1. PagedAttention:把 KV Cache 按页存(类似操作系统虚拟内存),消除显存碎片,能塞更多并发;
  2. Continuous Batching:新请求随时插入批次,不等慢的请求。传统 batching 一个慢拖一片。

效果:单卡吞吐比 transformers + naive batching 高 5-10 倍。

竞品:SGLang(更激进的优化)、TGI(HuggingFace 出品)、TensorRT-LLM(NVIDIA 官方,最快但配置复杂)。

# 175. 模型量化(INT8 / INT4 / AWQ / GPTQ)是什么?

模型权重从 FP16 / BF16 压缩到更低精度,显存和延迟下降,精度有少量损失

类型 精度 显存压缩 典型损失
FP16 / BF16 原始
INT8 8 位整数 < 1%
INT4 4 位整数 2-5%
AWQ 4 位,关键权重保护 < 2%
GPTQ 4 位,基于梯度优化 < 2%

实战:

  • 推理优先 AWQ(性能稳定、社区生态好);
  • 端侧 / 极端资源紧用 INT4 / GGUF;
  • 训练阶段一般不量化(影响梯度)。

# 176. 模型蒸馏(Distillation)是什么?

用大模型(Teacher)"教"小模型(Student):

  1. 让 Teacher 生成大量高质量样本(包含 logits / token 概率);
  2. 训练 Student 模仿 Teacher 的输出分布。

效果:

  • Student 参数量 1/10,但效果接近 Teacher;
  • 推理速度快好几倍;
  • 经典案例:DistilBERT、DeepSeek-V3 蒸馏出来的小模型。

适合:业务场景固定、追求极致延迟 / 成本的生产环境。

# 177. 私有化部署 GPU 选什么?

显存 适合
RTX 4090 24G 个人 / 试验,14B 模型量化版
A10 / A30 24G 中小生产,32B 量化版
L40S 48G 70B 模型量化版
A100 80G 80G 70B 全精度、训练
H100 80G 主流大模型推理 / 训练
H200 / B200 141G+ 旗舰生产,175B+

国内合规:A100/H100 受出口管制,替代方案为 A800/H800(被砍 NVLink 带宽)或华为 910B。

# 178. 模型评测常见 benchmark?

benchmark 测什么
MMLU 57 学科多选题,知识广度
GSM8K 小学数学题,多步推理
MATH 高难度数学
HumanEval / MBPP Python 代码生成
SWE-bench 真实软件工程
MT-Bench / AlpacaEval 多轮对话质量
C-Eval / CMMLU 中文综合能力
GAIA / AgentBench Agent 能力

注意:benchmark 分数和实际业务效果不一定一致,最终还是要拿业务数据测。

# 179. 私有化模型怎么更新?

不像调 API 那样无感升级。常见策略:

  1. 灰度切换:新模型挂上来,按流量比例分流,对比指标;
  2. 双跑评估:旧 / 新模型同时跑,离线对比答案差异;
  3. 回归测试集:维护一组业务测试 case,新版必须通过;
  4. 可快速回滚:模型版本管理 + 一键切回旧版本;
  5. 保留旧版本一段时间:用户反馈"上次回答更好"时能回查。

不要"周末偷偷换新模型"。

# 180. ToB 项目灰度发布有什么特殊?

ToC 灰度按用户 ID hash,ToB 不行:

  • 一个客户的几百用户必须同时升级(避免同公司内体验割裂);
  • 必须支持按客户灰度(先小客户 / 试点客户 / 大客户);
  • 部分客户合同里写明"不要给我用新版",要尊重;
  • 告知机制:升级前邮件 + 站内信通知,让客户管理员有准备;
  • 回滚要在合同 SLA 内

# 181. ToB 项目的成本怎么算给客户看?

客户最关心的不是技术,是钱。展示口径:

  • 按 token 计费透明:每次调用 input/output token 给出;
  • 月度账单:按租户 / 按用户 / 按使用场景;
  • 预算告警:超过 X% 自动通知;
  • 模型分级:便宜模型默认、贵模型按需开;
  • 缓存命中率告诉客户"省了多少钱"。

成本可见性是 ToB 续费的关键。


# 九、前端 AI 集成与工程化

前端的主场。AI 应用最终都要落到一个 UI 上,怎么把流式输出做丝滑、怎么管理多会话状态、怎么处理用户中断,这些是前端真正能拉差距的部分。

# 182. 前端调 LLM API 怎么做流式输出?

不要用 axios,用 fetch + ReadableStream

async function streamChat(input: string, onDelta: (text: string) => void) {
  const controller = new AbortController()
  const res = await fetch('/api/chat', {
    method: 'POST',
    body: JSON.stringify({ input }),
    headers: { 'Content-Type': 'application/json' },
    signal: controller.signal
  })

  if (!res.body) throw new Error('no body')
  const reader = res.body.getReader()
  const decoder = new TextDecoder()
  let buffer = ''

  while (true) {
    const { done, value } = await reader.read()
    if (done) break
    buffer += decoder.decode(value, { stream: true })

    let idx
    while ((idx = buffer.indexOf('\n\n')) !== -1) {
      const block = buffer.slice(0, idx)
      buffer = buffer.slice(idx + 2)
      if (block.startsWith('data: ')) {
        const data = block.slice(6)
        if (data === '[DONE]') return
        const { delta } = JSON.parse(data)
        onDelta(delta)
      }
    }
  }

  return controller
}

记得:

  • 返回 controller 给上层做中断
  • 错误要单独处理(一段 chunk 解析失败别拉垮整个流);
  • TextDecoder 必须用 { stream: true },否则中文截断会乱码。

# 183. 为什么不能在前端直接调 OpenAI / Claude?

理论上能,实际上不能:

  1. API key 暴露:放前端等于公开发钱;
  2. 没法做权限 / 速率限制:被人薅羊毛;
  3. 没法统计 / 计费:哪个用户花了多少钱;
  4. 没法注入 system prompt:用户能改请求;
  5. CORS / 跨域:很多家不支持浏览器直连;
  6. 没法做合规过滤

必须走自己的后端 BFF / API 网关代理。

# 184. 流式输出在 React 里怎么处理?

最简单:

function Chat() {
  const [text, setText] = useState('')
  const controllerRef = useRef<AbortController>()

  const send = async (input: string) => {
    setText('')
    controllerRef.current = new AbortController()
    await streamChat(input, (delta) => {
      setText((prev) => prev + delta)
    }, controllerRef.current.signal)
  }

  const stop = () => controllerRef.current?.abort()

  return (...)
}

注意:

  • 每个 token 都 setState 会卡,用 useReducer 或 ref 缓冲再批量 flush 在 60fps 内更新;
  • 长文章场景上 react-window 虚拟列表;
  • 别每个字都触发 layout / scroll 计算。

# 185. 大段文字流式渲染卡顿怎么办?

罪魁祸首通常是 Markdown 增量解析。优化:

  1. 节流渲染:每 30-50ms flush 一次缓冲区,不要每 token 重渲染;
  2. Markdown 流式解析:用 react-markdown + memo,或专门的 streaming-markdown 库;
  3. 代码高亮异步化:shiki / Prism 跑在 Web Worker;
  4. 避免大组件树重渲染:消息列表只追加,最新一条单独组件;
  5. 滚动跟随节流:scrollToBottom 防抖。

# 186. SSE 和 WebSocket 哪个适合 LLM 流式?

SSE WebSocket
方向 单向(服务端 → 客户端) 双向
协议 HTTP,简单 升级握手,复杂
自动重连 原生支持 自己写
代理 / CDN 友好 友好 一般
适合 流式输出(LLM 99% 场景) 多人协作 / 双向打断

LLM 默认上 SSE,**有"实时打断 / 多端协同 / 服务端主动推送"**才上 WS。

# 187. 怎么取消正在流式的请求?

前端用 AbortController,后端要识别到客户端断开立即停止 LLM 调用

  • OpenAI / Anthropic SDK 都支持传 AbortSignal;
  • Node http 监听 req.on('close') 触发 cleanup;
  • 已经调过的工具结果要做事务处理或标记中断。

不要让用户点了"停止"还在烧钱。

# 188. Token 预算怎么在前端做提示?

实战经验:

  • 输入框旁边显示估算 token 数(前端用 tiktoken-js / cl100k_base 估);
  • 长度临近上限时变红 + 提示"内容过长,可能截断";
  • 上传文件 / 长 prompt 时显示预估成本(按用户套餐计算)。

库选:gpt-tokenizertiktoken-js@anthropic-ai/tokenizer

# 189. 错误怎么向用户展示?

LLM 错误分几类,UI 表达要区分:

错误 用户感知 建议表达
速率限制 (429) 服务忙 "请求过于频繁,请稍后重试"
配额耗尽 额度问题 "今日额度已用完,明日恢复 / 升级套餐"
上下文超长 内容过长 "对话过长,建议开新会话"
服务异常 后端问题 "服务暂时不可用" + 自动重试
模型拒答 触发安全 "无法回答此类问题"
网络中断 本地问题 "网络异常" + 自动重连

每种都要有重试按钮 + 错误码便于排查。

# 190. ChatGPT 那种"消息列表"怎么实现?

数据结构:

type Message = {
  id: string
  role: 'user' | 'assistant' | 'system' | 'tool'
  content: string
  reasoning?: string  // 思考过程(CoT 显示)
  toolCalls?: ToolCall[]
  attachments?: File[]
  createdAt: number
  status: 'pending' | 'streaming' | 'done' | 'error'
}

UI 关键:

  • 流式追加:最后一条 message 是 streaming 状态时不断更新 content;
  • 虚拟列表:消息多了用 react-window;
  • 滚动控制:用户手动滚动后停止自动滚到底;
  • 重新生成 / 编辑:编辑某条 user 消息后,从这条开始的所有后续 message 清空 再重新跑。

# 191. 怎么管理多个会话状态?

类似 ChatGPT 的左侧会话列表:

  • 会话表 conversations(id, title, created_at, user_id)
  • 消息表 messages(id, conversation_id, role, content, ...)
  • 前端状态:当前 conversation_id + 当前 messages 数组
  • 路由 /c/[conversationId] 反映在 URL 上,方便分享 / 刷新

进阶:

  • 会话标题用 LLM 自动从第一条对话生成;
  • 软删除(标记 deleted_at)+ 30 天后真删;
  • 大对话支持分页加载;
  • 多端同步用 WebSocket / 长轮询。

# 192. AI 对话用 Edge Runtime 还是 Node?

场景 Edge Node
纯流式代理 推荐 也行
复杂业务 / 数据库重 不行 推荐
全球低延迟 Edge 完胜 受机房限制
大依赖 / 二进制包 Node 才能跑 灵活

Vercel / Cloudflare 上的 LLM 代理大多 Edge,复杂 Agent 后端用 Node(要操作数据库、调多工具、跑长任务)。

# 193. 怎么实现"图片 + 文字"混合输入?

数据格式(OpenAI / Anthropic / Qwen-VL 类似):

{
  "role": "user",
  "content": [
    { "type": "text", "text": "这张设计稿对应哪些组件?" },
    { "type": "image_url", "image_url": { "url": "data:image/png;base64,..." } }
  ]
}

前端:

  • 支持粘贴 / 拖拽 / 文件选择多种方式;
  • 图片前端压缩到 1MB 以内再传(base64 太大很贵);
  • 上传到对象存储拿 URL 比 base64 便宜(前提是模型能访问到);
  • 显示缩略图 + 移除按钮让用户可以删;
  • 多图按顺序排列。

# 194. Markdown 增量渲染怎么处理?

直接每次都 re-parse 整段会卡。三个套路:

  1. Streaming Markdown:用支持流式的 parser(marked / micromark + 增量插件),只 parse 新增片段;
  2. 代码块缓存:代码高亮的输出按内容 hash 缓存,重复不重 parse;
  3. DOM diff 友好:用 React key 让 DOM 复用而不重建。

记得:未闭合的代码块要做容错(用户还没输入 ``` 结尾),不要让一半的代码把后面渲染全搞乱。

# 195. AI 应用的埋点要监控什么?

不只是 PV / UV,还要 AI 特有的:

  • TTFT(First Token Time):用户感知响应速度的关键;
  • 完成耗时:整个回答从发出到结束;
  • Token 消耗:每用户 / 每会话 / 每模型;
  • 成本:折算成钱;
  • 中断率:用户主动停的比例;
  • 重试率 / 重新生成率:暗示回答质量;
  • 拒答率:触发了安全过滤;
  • 错误码分布
  • 多轮深度:用户问到第几轮;
  • 点赞 / 点踩:用户反馈最直接信号。

# 196. AI 应用的"灰度发布"怎么做?

新 prompt / 新模型 / 新 RAG 配置上线要灰度:

  1. 配置中心驱动:prompt、模型、RAG 参数从配置中心动态加载,不发版;
  2. 用户分组:按 user_id hash 取模,5% → 20% → 50% → 100%;
  3. AB 对照:旧版 vs 新版同时跑,对比关键指标(满意度、token 成本、TTFT);
  4. 影子流量:新版本只跑不返回,只是为了拿数据;
  5. 快速回滚:发现问题 5 分钟内切回旧版本。

# 197. AI 应用的成本怎么算和优化?

公式:成本 = Σ(每次调用的 input_tokens × in_price + output_tokens × out_price)

优化思路:

  • 更便宜的模型分流(简单任务用小模型);
  • Prompt Caching(命中率打 1-5 折);
  • 缩短 prompt + 工具描述
  • 结果裁剪 / 摘要
  • 多轮压缩(旧轮次摘要);
  • 业务侧缓存(同问题先查 KV);
  • 限流 + 套餐(防止个别用户跑爆)。

# 198. AI 应用的"国际化"(i18n)有什么特别?

不只是把文案翻译:

  • system prompt 多语言:每种语言一份;
  • 输出语言:用户的浏览器语言 / 用户偏好;
  • 不要混用语言:在 prompt 里告诉模型"全程用同一种语言";
  • 错误信息 i18n:拒答信息、错误码都要翻;
  • 数字 / 日期 / 货币格式按 locale;
  • RTL 语言(阿拉伯语)UI 也要 RTL。

# 199. AI 应用的"乐观更新"怎么做?

用户发送消息后立刻显示在列表里,不等服务端确认:

const send = (input: string) => {
  const tempMsg = { id: nanoid(), role: 'user', content: input, status: 'pending' }
  appendMessage(tempMsg)
  // 异步调用 API
  api.chat(input).then((real) => replaceMessage(tempMsg.id, real))
    .catch(() => markFailed(tempMsg.id))
}

注意:

  • 失败时用红色 + 重试按钮;
  • 不要让"乐观"骗用户:服务端真失败要明确告知;
  • 多端同步时小心冲突。

# 200. AI 自动补全代码(类似 Copilot)怎么实现?

前端流程:

  1. 编辑器 cursor 位置 + 上下文(前后 200 行 / token)通过 debounce(300-500ms)发给后端;
  2. 后端 FIM(Fill-in-the-Middle)prompt 调模型;
  3. 流式返回,前端 ghost text 渲染;
  4. Tab 接受 / Esc 拒绝 / 编辑中放弃。

要点:

  • FIM 友好的模型(DeepSeek-Coder、Qwen-Coder、StarCoder 等);
  • AbortController 让新一次输入立刻取消上一次;
  • 接受率 / 拒绝率打点优化模型;
  • 长函数不要一次全补,让用户分阶段确认。

# 201. AI 应用要不要 PWA / 离线支持?

实战经验:

  • 离线 LLM 一般不支持(模型太大,浏览器跑不动);
  • 历史会话可以做离线只读:IndexedDB 存历史,无网时也能看;
  • 草稿离线写,回到在线再发送;
  • 不要让 ServiceWorker 缓存 LLM API 接口,必须 NetworkOnly;
  • 静态资源走标准 PWA 缓存就好。

# 202. Vercel AI SDK 的 useChat 怎么用?

最简化的 Next.js 集成:

'use client'
import { useChat } from 'ai/react'

export default function Chat() {
  const { messages, input, handleInputChange, handleSubmit, isLoading, stop } = useChat({
    api: '/api/chat'
  })

  return (
    <>
      {messages.map(m => (
        <div key={m.id}>
          <strong>{m.role}:</strong> {m.content}
        </div>
      ))}
      <form onSubmit={handleSubmit}>
        <input value={input} onChange={handleInputChange} disabled={isLoading} />
        <button type="submit">发送</button>
        {isLoading && <button type="button" onClick={stop}>停止</button>}
      </form>
    </>
  )
}

后端:

import { openai } from '@ai-sdk/openai'
import { streamText } from 'ai'

export async function POST(req: Request) {
  const { messages } = await req.json()
  const result = await streamText({ model: openai('gpt-4o'), messages })
  return result.toDataStreamResponse()
}

省去了流式协议处理、状态管理、停止逻辑的大量样板。

# 203. 消息编辑 / 重新生成怎么实现?

设计要点:

  • 编辑 user 消息:编辑后,从这条开始的所有后续消息全清空,从这条重新跑;
  • 重新生成 assistant 消息:保留 user 消息,重新调用模型生成新回答,前一次答案要么覆盖、要么作为历史版本保留;
  • 历史版本切换:UI 上 < 1/3 > 形式让用户在版本间切换;
  • 状态机:消息有 editing | streaming | done | error 几种状态,UI 分别处理。

数据库 schema:

message {
  id, conversation_id, role, content,
  parent_id,   // 编辑后的新分支
  version,     // 同一节点的多版本
  is_active    // 当前显示的版本
}

# 204. 对话分支 / Fork 怎么做?

ChatGPT / Claude 都支持"从某条消息分叉重问"。

实现:

  • 数据结构从"线性 list"改成"树":每条 message 有 parent_id
  • UI 在分叉点展示版本切换;
  • 默认只显示一条线性路径(最新分支);
  • URL 带 ?branch=xxx 让分享和回访能恢复对应分支。

收益:用户能探索不同问法,避免反复开新会话浪费上下文

# 205. 语音输入 / TTS 怎么集成?

输入侧(STT,语音转文字):

  • 浏览器原生 webkitSpeechRecognition(兼容性一般);
  • 接 Whisper API / 阿里云 NLS / 讯飞,自己录音 + 上传;
  • 实时流式 STT 用 WebSocket 推送音频流。

输出侧(TTS,文字转语音):

  • 浏览器原生 speechSynthesis(音色差);
  • 接 OpenAI TTS / Azure Speech / 火山 / 阿里 TTS;
  • 流式 TTS:边生成边播(豆包同款)。

工程要点:

  • 录音前先申请权限,UI 提示;
  • 静音检测自动结束录音;
  • 实时 STT 用 SSE / WebSocket 流式更新 UI;
  • TTS 队列管理:一句一句播,能跳过 / 暂停。

# 206. 文件上传 + 处理流怎么做?

复杂场景常见:

  1. 前端:File API 读文件 → 压缩 / 切片 → 上传到对象存储;
  2. 后端:拿到文件 URL → 用 Loader 解析(PDF / Word / Excel) → 切片 + embedding → 入向量库;
  3. 会话注入:把文件 ID 写入当前 conversation 的 metadata;
  4. 检索:用户提问时,先检索该 conversation 关联的文件;
  5. UI:上传时显示进度,处理中显示 loading,处理完显示文件卡片。

注意:

  • 大文件分片上传(避免超时);
  • 异步处理(不阻塞对话);
  • 处理失败时给清晰错误(PDF 加密 / 编码异常等);
  • 单用户的存储配额必须控制。

# 207. Markdown 渲染中的 XSS 安全?

LLM 输出会被渲染成 Markdown / HTML,潜在 XSS 风险:

  • 用户问"输出 <script> 标签" → 模型照写 → 直接渲染就执行了;
  • 第三方 RAG 文档里夹带恶意脚本。

防御:

  • DOMPurify 等库过滤 HTML;
  • Markdown 渲染器关闭 raw HTML(markedsanitizereact-markdown 默认安全);
  • 代码块单独渲染(用 <pre><code> 包裹,不解析);
  • iframe 嵌入要警惕;
  • 用户输入也要消毒,不能让用户在自己问题里塞攻击。

# 208. 移动端 AI 应用有什么特殊问题?

不是把 Web 缩小那么简单:

  • 键盘弹起:消息列表要重新计算 viewport 高度;
  • 流式更新滚动:要避免每个 token 都触发滚动;
  • 后台切换:iOS / Android 切到后台后流式可能断,要做重连;
  • 网络抖动:弱网下 SSE 易断,要支持断点续传 / 重试;
  • 输入法预测:避免误触发发送;
  • 语音输入:移动端用户期望更高;
  • 流量提示:长文 / 图片传输前提示用户;
  • 省电:长时间流式 + 不间断渲染会发热掉电。

# 209. 怎么实现"AI 自动补全代码"(Copilot 同款)?

前端流程:

  1. 监听 cursor 位置 + 上下文(前后 200 行);
  2. debounce 300-500ms 后请求后端;
  3. 后端用 FIM(Fill-in-the-Middle)prompt 调模型;
  4. 流式返回,前端 ghost text 渲染;
  5. Tab 接受 / Esc 拒绝 / 编辑中放弃。

关键点:

  • FIM-friendly 的模型才合用(DeepSeek-Coder、Qwen-Coder、StarCoder);
  • AbortController 让新一次输入立刻取消上一次;
  • 接受率 / 拒绝率打点持续优化;
  • 长函数分阶段补,让用户分阶段确认。

# 210. 怎么把 AI 集成到富文本编辑器(TipTap / Lexical / Slate)?

主流交互模式:

  1. 斜杠菜单(/):输入 /ai 弹出操作面板(总结 / 改写 / 翻译 / 续写);
  2. 选中改写:选一段文字 → 右键 / 浮动按钮 → "用 AI 改写";
  3. 行内补全:cursor 后显示 ghost text,Tab 接受;
  4. 侧边栏 AI 助手:独立面板,可与文档双向同步。

工程要点:

  • AI 改写要走事务:原文 → 模型流式输出 → 替换;用户能撤销;
  • 多人协作时要走 CRDT,AI 写入算特殊作者;
  • 长文档别全量喂模型,只喂选中片段 + 必要上下文

# 十、AI 提效篇(怎么用 AI 反过来帮你干活)

这一节是 2026 年面试新增的高频区。所有公司都在问"你日常用什么 AI 工具",能讲出真实工作流 + 踩过的坑,比"我用 ChatGPT 写代码"具体一百倍。

# 211. 你日常用哪些 AI 工具?典型的工作流是什么?

参考答案要素:

  • 写代码主战场:Cursor / Claude Code / Codex / Copilot 选 1-2 个;
  • 写文档 / 写脚本 / 调研:ChatGPT / Claude / 通义;
  • 画图 / 生图:Figma AI / Midjourney / 国内即梦;
  • 会议 / 笔记:飞书妙记 / Notion AI / 通义听悟。

工作流示例(可参考改写):

我用 Claude Code 做主力编码:早上接到需求 → 让 Claude Code 先读相关文件给出初步实现思路 → 我确认方案 → 让它写出来 + 跑测试 → 我 review + 局部修 → commit。一些零散的研究 / 文档我用 ChatGPT。每周复盘的时候让模型帮我总结这周的 commit。

讲得越具体越能加分。

# 212. Cursor / Claude Code / Copilot 这些 AI 编程工具的本质区别?

Copilot Cursor Claude Code
主战场 编辑器补全 IDE 整合 命令行 / Agent
单次粒度 单行 / 单函数 多文件编辑 跨任务 Agent
主力模型 OpenAI Codex / GPT-4 多家可选 Claude 系列
上下文 当前文件 Workspace 全局 工作目录 + 工具调用
强项 行内补全 改造代码 完成完整任务
适合 加速打字 改造重构 端到端开发

工程上常组合:Copilot 行内补全 + Cursor / Claude Code 端到端任务

# 213. AI 写代码最容易翻车的几种情况?

实战踩坑:

  1. 依赖虚构 API:模型编不存在的库函数 / 方法名;
  2. 版本不匹配:写的是旧版 API,你用的是新版(或反过来);
  3. 静默改了无关代码:让它改 A,它顺手"优化"了 B、C、D;
  4. 删测试 / 删错误处理凑通过:测试跑不过它就改测试;
  5. 不读现有约定:项目里用 antd 它写 element-ui;
  6. 改完不验证:声称"已修复"但其实没跑。

面试讲出来这些细节就能加分。

# 214. 怎么写一个高质量的 AI 编程指令?

不要扔一句"帮我写个登录页"。结构化指令:

背景:项目用 React 18 + Vite + antd 6 + zustand。
任务:实现一个用户列表页,要求支持搜索、分页、删除。
接口:GET /api/users?q=&page=&size= ,返回 { list, total }。
约束:
- 只改 src/pages/UserList/,别动其他文件。
- 用 antd ProTable,不要重新造轮子。
- 删除要二次确认。
- 我已经有 useAuth、useApi hook,直接复用。
完成标准:
- 列表能渲染。
- 搜索和分页能联动。
- 删除有 message 反馈。
- 写一个最小的 vitest 测试。

要点:背景 + 任务 + 边界 + 约束 + 完成标准,模型不会跑偏。

# 215. AI 写完代码你怎么 review?

一定要 review,不要直接 commit。最少这几步:

  1. 读 diff:每一行都过一遍,看有没有"惊喜改动";
  2. 跑测试 / 跑应用:能在本地跑通 + 关键路径过一遍;
  3. typecheck + lint
  4. 看依赖:有没有新增包,是不是必要;
  5. 看 commit message 是否准确:别让 AI 写 "fix everything"。

AI 写的代码 ≠ 你不用读。它写得快,但你署名

# 216. AI 帮调 bug 应该怎么用?

无效用法:把报错堆栈丢过去问"怎么修"。

更有效的用法:

  1. 先描述上下文:项目结构、当前任务、最近改了什么;
  2. 完整堆栈 + 最小复现:错误信息 + 触发步骤;
  3. 告诉它你试过什么、排除了什么
  4. 让它先给出几个假设,而不是直接给修复方案;
  5. 挨个验证假设,找到根因再修。

不要让 AI 替你思考根因,让它辅助你思考

# 217. AI 写单元测试该怎么用?

容易踩的坑:

  • AI 写的测试只覆盖 happy path,没覆盖边界;
  • 测试和实现耦合太紧,重构就挂;
  • mock 写错,测试根本没在测;
  • 看起来通过,实际没 assert 关键逻辑。

更好的用法:

  1. 先告诉 AI 输入输出契约,让它写"测试用例描述";
  2. 你 review 测试用例够不够,再让它生成代码;
  3. 故意改坏实现,跑测试看能不能测出来(mutation testing 思路);
  4. 测试要简单到一眼看懂,复杂测试反而藏 bug。

# 218. AI 帮 code review 怎么用?

让 AI 做"第一道筛"是合理的:

  • 自动跑 lint / type check 看不到的问题;
  • 命名 / 复杂度 / 副作用之类的"软指标";
  • 安全 / 性能的一般性建议。

不能替代人 review

  • AI 看不到业务上下文;
  • AI 容易给出"安全的废话"建议(什么都建议加 try/catch);
  • 关键决策(API 设计、架构)还是要人拍。

# 219. AI 帮写文档 / commit message / PR 描述?

完全可以,但有讲究:

  • commit message:让 AI 看 diff 写一句话总结,你最后审一眼。我用过 aicommit 类工具,命中率 80% 但还是要改;
  • PR 描述:让 AI 看所有 commit 写 changelog 草稿,然后你补"为什么这么做";
  • API 文档 / TSDoc:让 AI 看代码生成初稿,你必须 review 准确性
  • README:自己写比让 AI 写更靠谱,README 是给人看的,要有"人味"。

# 220. AI 帮设计 API / 数据结构靠谱吗?

不靠谱当主笔,靠谱当评审。

  • 让 AI 给 3 个方案比让它给 1 个方案有用;
  • 让 AI 找出某个方案的潜在问题;
  • 让 AI 模拟"如果未来要加 X 字段,这个设计能不能扛"。

API 设计最关键的是业务理解,AI 不知道你的业务,所以决策权永远在你。

# 221. AI 改造遗留代码(legacy code)的正确姿势?

遗留代码最危险,常见错误:让 AI 一次性"重构这个文件"。

更安全的方式:

  1. 先让 AI 解释这段代码做了什么(让它先理解);
  2. 写测试覆盖现有行为(用 AI 写测试);
  3. 小步重构:一次只改一个函数 / 一个职责;
  4. 每次重构后跑测试
  5. 保留原 commit,新建分支 / PR 做对比

不要把"重构一万行代码"当成一个 prompt。

# 222. AI 帮选技术栈 / 框架对比靠谱吗?

部分靠谱:

  • 客观对比(性能、生态、上手成本)AI 给的信息 80% 准确;
  • 结合业务的推荐不可信,因为它不了解你的业务;
  • 最新信息(半年内的新框架、新版本)容易过时,必须查官网。

最佳用法:让 AI 列对比维度,然后你按维度自己拉数据。

# 223. 怎么避免对 AI 过度依赖?

实战感受:

  • 重要决策不让 AI 拍(架构、API 设计、技术栈选型);
  • 手感不能丢:定期写一段不用 AI 的代码,保持思维;
  • review 不外包:AI 写的也是你的代码,你要懂;
  • 不要"我让 AI 写过了所以肯定对":AI 错误率高于直觉;
  • 写 prompt 比写代码更难:能说清需求才能让 AI 帮你,逻辑思考还是要练。

# 224. AI 帮做需求分析 / PRD 解析?

实战用法:

  1. 把 PRD 丢给 AI,让它抽取需求点(功能、约束、验收标准);
  2. 让它指出含糊的地方(这里没说限制条件、这里和前面冲突);
  3. 让它列出实现要点(要建几张表、要改几个接口、要考虑哪些边界);
  4. 你拿着这份草稿去和产品对齐。

把 AI 当一个"会做笔记的实习生",它善于结构化整理。

# 225. 怎么让 AI 帮你"读代码 / 接手老项目"?

接手陌生项目时最高效用法:

  1. 让 AI 读项目根目录 + package.json + README → 总结技术栈;
  2. 让 AI 看 src 目录结构 → 推断架构分层;
  3. 让 AI 挑一条核心链路(比如"用户登录")走读 → 解释主流程;
  4. 你拿着这份"地图"去看代码,事半功倍。

Claude Code / Cursor / Codex 类工具特别擅长这件事。

# 226. AI 写脚本(一次性 ops 脚本)的正确姿势?

很多时候不值得自己写:迁移数据、清洗 log、跑 cron 任务。

实战经验:

  • 明确输入输出:数据格式、文件路径、预期效果;
  • 跑前先 dry-run:让 AI 加 --dry-run 模式打印不执行;
  • 加日志 + 进度条:长时间脚本要能看进度;
  • 可中断 + 可重入:跑一半挂了能从中间继续;
  • 小数据集先跑一遍:再跑全量。

# 227. 让 AI 帮"写英文 / 改邮件 / 翻译" 的注意点?

  • 写英文邮件:明确风格(正式 / 友好 / 简短),明确收件人;
  • 翻译:来回翻译看是否丢信息;
  • 技术翻译:术语先 review,AI 容易把专业术语翻成日常词;
  • 多语言文档:让 AI 翻一遍 + 找一个母语同事过一眼。

# 228. AI 帮"画架构图 / 时序图" 怎么用?

实战流程:

  1. 让 AI 输出 Mermaid 代码:graph LR / sequenceDiagram / classDiagram
  2. 在 VSCode / Typora / Mermaid Live 里渲染看效果;
  3. 不满意继续让 AI 改 mermaid;
  4. 满意后导出 SVG / PNG 用到 PR / 文档里。

不要让 AI 直接画图(多模态生成图片可控性差),让它写代码。

# 229. AI 帮"查文档 / 学新框架" 怎么用?

  • 官方文档先用 AI 摘要:但要 verify 关键代码,AI 容易把版本搞混;
  • 新框架快速 onboarding:让 AI 给"5 个最常用的 API 示例";
  • 不要全信:新版 API 是 AI 训练后才出的,比如 React 19 / Next 16 的新特性 AI 容易写错;
  • 代码示例必须自己跑:别信"我刚刚帮你写好"。

# 230. AI 帮"看性能 profile / 看 source map" 靠谱吗?

部分靠谱:

  • 看 profile:让 AI 看 Chrome Performance / Lighthouse 报告总结瓶颈,靠谱;
  • 看 minified 代码:AI 能读 source map 反映射后的代码,定位 bug;
  • 优化建议:AI 给的是"通用建议",你的项目特定优化它不懂。

更好的用法:你自己定位到瓶颈点 → 把那段代码喂给 AI 让它给优化方案。

# 231. AI 工具的 cost 怎么控制?

公司给的 AI 工具有预算,超了要被关怀。控制思路:

  • 选小模型:日常 80% 任务用 Haiku / GPT-4o-mini / DeepSeek 这种便宜模型;
  • 大模型只在难任务上用:架构设计、复杂 debug;
  • 避免重复对话:复杂任务一次问清楚,不要来回试探;
  • 缓存常用 prompt:开发模板存起来;
  • 关掉自动续传 / Background Agent:跑着不知道,就是烧钱。

# 232. AI 工具的"安全 / 数据合规"风险?

工作中要警惕:

  • 不能把公司源代码 / 客户数据传给个人 ChatGPT 账户
  • 走公司统一网关 / 企业版(数据不进训练集);
  • 敏感字段(密钥、客户信息)脱敏后再问
  • 生成的代码也是代码,要走 code review,不要直接合

面试里被问"你怎么保证用 AI 不泄密",答出这几点就稳了。

# 233. AI 工具帮做技术调研 / 写技术分享的工作流?

  • 第一步:明确要分享的主题 + 受众(前端组 / 全公司);
  • 第二步:让 AI 列大纲(10 - 15 个点);
  • 第三步:每个点让 AI 写 200 字初稿;
  • 第四步:你补自己的例子 / 项目截图 / 失败经验——这部分 AI 写不出来;
  • 第五步:让 AI 生成 PPT 用 Mermaid / Marp 大纲;
  • 第六步:本地 review 修改,配图。

AI 帮你处理体力活,判断力和真实经验你自己出

# 234. 怎么用 AI 帮你"晋升 / 写自评"?

不开玩笑,很多人这么用。但要小心:

  • AI 不知道你做了什么:你得先列出来;
  • AI 容易写得"假大空":让它优化"具体到指标 / 影响范围 / 协作角色";
  • 避免明显 AI 味:成段排比、抽象动词(赋能、闭环、抓手)多半要改;
  • 最后自己读一遍:能不能复述出来。如果不能,说明写虚了。

# 235. 长期看,AI 对前端工程师意味着什么?

实诚答法(面试这种题不要装高调):

  • 门槛上升:以前写组件、调样式就能干活,现在这部分 AI 半秒做完;
  • 架构 / 业务 / 系统设计 的权重上升:决策能力比写代码更值钱;
  • 学习曲线变陡:跟不上 AI 工具的人会落后;
  • 不是替代,是升级:会用 AI 的前端 > 不会用 AI 的前端;
  • 健康的心态:把 AI 当协作伙伴,不当奴隶也不当神。

# 236. 怎么用 AI 复盘一周 / 一月的 commit?

实用工作流:

  1. git log --since="1 week ago" --pretty=format:"%h %s%n%b" --no-merges 拿到所有 commit;
  2. 把列表喂给 AI,让它按主题分类(feature / bugfix / refactor / chore);
  3. 让它写两份:对内技术周报(细节) + 对外业务周报(成果);
  4. 你补"为什么这么做" + "踩过什么坑"。

提示词模板:

帮我整理这一周的工作,按"完成的功能 / 解决的 bug / 重构 / 文档"四个分类。
每项写 1 句话,强调对业务的影响和量化指标。
风格简洁、可读、面向非技术 leader。

# 237. AI 帮处理 Excel / CSV / JSON 数据怎么用?

实战路径:

  • 结构化整理:把"乱格式"的数据用 AI 转成规范 schema;
  • 批量改写:让 AI 写 Python / Node 脚本,跑 dry-run 看输出再批量;
  • 数据清洗:让 AI 列出"可能的脏数据模式",再写规则过滤;
  • Excel 公式:让 AI 写复杂公式(VLOOKUP 嵌套、数组公式),可读性差但能跑;
  • 直接 ChatGPT Data Analysis:上传文件让它跑代码(适合一次性分析,不要长期依赖)。

提示词模板:

我有一份 CSV,字段是 [...],目标是 [...]。
请写一个 Node.js 脚本,要求:
1. 支持 --dry-run 模式
2. 异常数据写到 error.log
3. 输出每一步进度

# 238. AI 帮做产品 / 设计 brainstorm?

不是让 AI 拍板,是让 AI 当反弹墙

  • 让它列当前方案的潜在问题(10 个);
  • 让它扮演典型用户 / 竞品给你提反馈;
  • 让它给3 个不同的解决方向让你选;
  • 让它模拟 5 年后这个产品会被怎么颠覆。

不要问"你觉得 XX 怎么样"(它一定说"很好"),要问"找 5 个理由说为什么不该做 XX"。

# 239. AI 帮写周报 / 月报 / 述职报告?

提示词技巧:

  • 先输入事实:列出"做了什么、改了什么文件、解了什么 bug";
  • 指定风格:简洁 / 详细 / 数据驱动 / 故事化;
  • 限制字数
  • 指定结构:成果 / 难点 / 协作 / 改进;
  • 要求量化:每点尽量带数字(前后对比、用户量、性能提升)。

最后一定自己读一遍:能不能口头复述出来?不能的话就是写虚了。

# 240. AI 提效的"反模式"有哪些?

工作中容易踩的坑:

  1. 凡事先问 AI:简单事情靠 AI 反而慢;
  2. AI 给的答案不验证:当成事实直接用;
  3. 代码 review 外包给 AI:自己不读就 commit;
  4. AI 写的注释 / 文档不改:充满"如上所述、综上所述";
  5. 越聊越长不止:来回十几轮还没解决,直接看文档 / 看源码更快;
  6. 过度依赖单一工具:AI 不可用时啥都不会做;
  7. 不积累自己的方法论:每次都重新问 AI,没有沉淀。

健康的工作流:先想 → 上 AI 加速 → review → 沉淀到 own playbook。

# 241. AI 帮你"学新框架 / 新工具"的最快路径?

参考流程:

  1. 让 AI 给你一份 30 分钟入门路径(核心概念 + 最小 demo);
  2. 让它对比你已会的框架("React 开发者怎么理解 Svelte");
  3. 跟着写一个最小可运行项目
  4. 让 AI 帮你列 5 个最常见踩坑 + 解决方案
  5. 实际项目尝试 → 出问题再回头问;
  6. 一周后写一份自己的小结(强迫输出加深记忆)。

关键:别只看,要写。AI 让"看懂"变得容易,但只有"写出来"才真懂。

# 242. AI 帮你做技术博客 / 知识沉淀?

实战做法:

  1. 大纲:让 AI 从你的笔记 / commits / 问答记录里抽取"值得写的话题";
  2. 初稿:你列要点,AI 扩展段落;
  3. 改写:AI 给的初稿"AI 味"重,用"删形容词、加例子、加自己的话"三招过一遍;
  4. 配图:让 AI 生成 Mermaid 流程图 / 表格;
  5. 校对:让 AI 当 reviewer,从读者角度提"哪里不清楚"。

写完后:自己讲一遍能不能讲明白,是检验质量的硬指标。

# 243. AI 帮你做 OKR / 目标拆解?

公司层级 OKR 落到个人时,让 AI 帮你:

  • 模糊目标翻译成可衡量动作
  • 让它列出潜在阻塞 / 依赖
  • 让它模拟季度末复盘,提前看到"哪些指标会卡住";
  • 给一份周维度的拆分计划

记住:AI 给的是模板,真正的目标取舍只能你自己拍板

# 244. 怎么用 AI 提升英文 / 跨国协作?

  • 写英文邮件 / 文档:先中文起草,让 AI 翻译 + 优化语气;
  • 接收英文长邮件 / PR review:让 AI 总结要点 + 列出"必须回应的问题";
  • 会议:飞书妙记 + Notion AI 自动转录 + 摘要;
  • 跨时区沟通:让 AI 帮你写"非阻塞式回复"模板(明确说清楚下一步、避免无谓 ping)。

提示:英文表达从"语法对"到"地道"中间还有一大段,让 AI 多给几个候选自己挑。

# 245. 用 AI 学竞品 / 做技术调研的工作流?

参考流程:

  1. 收集竞品的公开资料(官网、文档、博客、PR);
  2. 让 AI 抽取"它解决了什么问题、用了什么技术、有什么独特性";
  3. 让 AI 对比"我们家做法 vs 竞品做法";
  4. 让 AI 帮你列问竞品的好问题(如果以后能聊到他们工程师);
  5. 自己亲测竞品,形成第一手感受——这个 AI 替代不了。

# 246. Claude Code 的架构是什么样的?

理解 Claude Code 别只把它当成"命令行版 Cursor"。它本质是 Agent Loop + 多层治理

  • 核心 Loop:标准 Agent Loop(思考 → 工具调用 → 观察 → 再思考),但循环里能调几十种内置工具;
  • 工具层(Tools):Read / Write / Edit / Bash / Grep / WebFetch / Agent / TodoWrite 等几十个,每个都有完整 schema;
  • MCP 层:通过 MCP 协议把外部能力(数据库 / Figma / 浏览器 / 自研工具)接进来;
  • Skills 层:可复用的"能力包",包含 prompt + 工具组合 + 触发条件(如 dev-guide / brainstorming);
  • Memory 层CLAUDE.md(项目级)+ ~/.claude/CLAUDE.md(全局)+ memory/ 目录(结构化记忆);
  • Hooks 层:用户可配置的脚本,能在工具调用前后插入校验 / 自动化动作;
  • Permissions 层:哪些工具自动允许、哪些每次问、哪些禁止。

记一句话:Claude Code 真正强的不是模型,是治理(governance)——这套分层让 AI 编程从"放飞"变成"可控"。

# 247. Claude Code 的"治理"具体怎么做?

四件套从粗到细:

  1. CLAUDE.md:项目级指令文件,约定技术栈、命令、不要做的事、不要碰的文件。每次会话自动加载;
  2. Skills:把"对这个项目怎么干活"封装成可调用的能力。比如 dev-guide skill 列出本仓库所有命令 + 部署流程,模型按需读;
  3. Hooks:在 pre-committool-call-before/after 这些事件点跑用户脚本,能做格式化、敏感词过滤、危险命令拦截;
  4. Permissionssettings.json 里精确控制哪些工具 / 哪些参数模式可以自动跑,哪些必须用户点确认。

实战收益:

  • 团队新人接手项目,AI 自动遵守约定(避免反复教);
  • 危险操作(rm -rfforce-push)必须人工二次确认;
  • 跨项目复用 Skills,省掉重复教模型。

# 248. 什么是 Spec-Driven Development(SDD)?为什么 AI 时代需要它?

SDD = 先写规范再写代码,本身不是新概念,但 AI 编程让它复活。

为什么 AI 时代必须:

  1. AI 理解需求不靠谱:你说"加个登录",它可能给你 Session 也可能 JWT,结果跑偏;
  2. AI 写的代码缺决策上下文:关掉聊天窗口决策就没了,后来人看不懂为啥这么做;
  3. AI 生成速度太快,review 跟不上:缺一层"先达成共识再让 AI 写"的过滤。

SDD 的核心动作:在让 AI 写代码前,先用文档把**「为什么 / 做什么 / 怎么做」**写清楚,模型按文档执行,结果可追溯、可对齐、可审计。

# 249. OpenSpec 是什么?解决了什么问题?

OpenSpec 是把 SDD 工程化的工具,主要解决 AI 编程的三个痛点:

痛点 OpenSpec 解法
需求偏差(AI 不懂你真要什么) proposal.md 把"为什么 / 不做会怎样"写下来
设计漂移(AI 一会儿用方案 A 一会儿用方案 B) design.md 锁定架构决策、接口、数据流
实施失控(AI 顺手改一堆无关代码) tasks.md 列出可验证的具体任务
决策遗失(下次会话又重头讨论) changes/ 目录归档每次变更的完整提案

工程上 OpenSpec 把"和 AI 聊天"变成"和 AI 共同维护一份蓝图"。

# 250. OpenSpec 的核心三件套:proposal / design / tasks 各写什么?

  • proposal.md为什么要做。背景、业务痛点、不做的代价、成功标准。一两屏长度,不写技术;
  • design.md技术怎么实现。架构决策、接口定义、数据流、依赖、风险点、备选方案对比。这是 AI 写代码时的事实来源
  • tasks.md具体要做哪些动作。可执行清单,每项粒度小到能被一次 executing-plans 跑完。

附加:

  • specs/<capability>/spec.md:当前系统的稳定能力规范(事实记录,不是变更);
  • changes/<change-id>/:每次变更的完整目录;
  • changes/archive/<date>-<id>/:完成后归档。

# 251. OpenSpec 的双文件夹模型(specs vs changes)是什么意思?

OpenSpec 区分两类内容:

  • specs/:当前系统已稳定的事实规范。"系统现在长这样";
  • changes/:每次变更的完整提案。"这次要把系统改成怎样"。

工作流:

1. /opsx:propose → 在 changes/<id>/ 下生成 proposal + design + tasks
2. 人工 review design.md
3. 执行 tasks.md(交给 Superpowers / Claude Code)
4. 完工后 /opsx:archive → 改动反向更新 specs/,change 归档到 changes/archive/

精髓:变更和事实分离。下一次会话来,看 specs/ 知道系统现状,看 changes/archive/ 知道历史决策。AI 不会重头讨论已经决定过的事。

# 252. Superpowers 是什么?提供了哪些核心能力?

Superpowers 是把"工程纪律"封装成 Skills 包。核心能力:

Skill 干什么
brainstorming 创造性工作前先发散,避免 AI 跑偏
writing-plans 把目标拆成可执行的实施计划(带文件、命令、验证步骤)
executing-plans 严格按计划执行,跑完一步勾一步
test-driven-development 强制先写测试再写实现("会删掉测试之前写的代码"——硬约束)
systematic-debugging 调 bug 的系统方法:复现、隔离、根因、修复、验证
code-reviewer 独立 review pass,不和实现混在一起
verification-before-completion 完成前必须跑过验证(测试 / 构建 / 真访问)
worktrees git worktree 隔离开发,避免污染主分支

简单说:OpenSpec 管"要做什么",Superpowers 管"怎么做得专业"

# 253. Claude Code + OpenSpec + Superpowers 三件套是过度工程吗?

被面试官追问最容易翻车的题,记住一个观点:按项目规模分档,不是非黑即白。

项目规模 / 类型 推荐配置
30 分钟脚本 / 一次性任务 只用 Claude Code,跑完丢
< 2h 探索性原型 Claude Code + 必要时 brainstorming
2-8h 个人项目 / 小功能 Claude Code + Superpowers(保质量)
4-16h 团队项目 / 跨人协作 全套(OpenSpec 留决策痕迹 + Superpowers 守纪律)
长期维护 / ToB 交付 全套 + 严格 archive 流程

不分场景上全套 = 过度工程;不分场景拒绝全套 = 野路子。务实地按场景挑。

面试答法:

我会按"任务可逆性 + 跨人协作度 + 长期维护可能性"三个维度判断。一次性脚本直接 Claude Code,团队级功能必上 OpenSpec 留决策痕迹。

# 254. OpenSpec 的常见踩坑有哪些?

实际用过的人会踩到这些:

  1. 完成后忘了 archive:下一次会话以为是新需求,重复实现已有功能;
  2. 把 spec 写成伪代码:太具体反而限制 AI 实现空间,应该停留在"接口 / 数据流 / 决策"层;
  3. 跳过 brainstorming 直接 propose:技术选型偏差,AI 写到一半才发现方向不对;
  4. proposal 和 design 混写:proposal 只讲"为什么",design 才讲"怎么做";
  5. tasks 颗粒度太大:一项 tasks 跑两小时,AI 中途跑飞;
  6. OpenSpec 和 Superpowers 没有串联:用了 propose 但执行时没走 TDD / review,等于半套。

避免方式:在 CLAUDE.md 明确写"propose 之后 tasks 必须走 Superpowers 的 TDD + verification + code-review 链路"。

# 255. "你日常怎么用 AI 提效"被问到,怎么答得让人记住?

把流程讲具体、有例子、有反思。参考模板:

我们团队最近上 AI First 工作流,分三层:

1. **决策层**:用 OpenSpec 先写 proposal + design 锁定方向。
   解决的痛是:以前一句话需求让 AI 干,常常跑偏 + 决策没留痕。

2. **执行层**:Claude Code 跑 Agent + Superpowers 守纪律。
   关键约束:跑功能必须先写测试(TDD skill 强制),完成前必须 verify。
   实战收益:上线后回归率明显下降,且改完代码自带 review pass。

3. **沉淀层**:每个变更跑完 archive 到 changes/archive/,
   下次有人接手能直接读历史决策,省掉一遍口头同步。

踩过的坑:
- 早期 OpenSpec 写得太详细,反而限制实现 → 后来 design 只写决策不写代码;
- Superpowers 全开太重 → 现在按任务规模分档,一次性脚本不用全套。

我自己最大的体感:AI 写代码的速度上限不是模型决定的,是"治理"决定的。
有治理 = AI 是高级实习生;没治理 = AI 是熊孩子。

要点:有架构、有指标、有反思,是讲故事不是背概念。


# 十一、综合追问 & 场景题

这一节是把前面所有知识揉到具体场景,面试官最爱问。能讲出真实方案就赢。

# 256. 场景题:公司想做一个"内部知识库问答机器人",让你设计技术方案。

参考答案(30 秒能讲完的版本):

  1. 数据层:把 Confluence / 内部 Wiki / 飞书 / Git 文档汇总,做 ETL 进入统一存储;
  2. 切片 + Embedding:递归切分(500/50 overlap),用 bge-m3 入 Milvus / pgvector;
  3. 检索:Hybrid Search(ES BM25 + 向量),用 bge-reranker 重排 top 5;
  4. 生成:Claude / Qwen,prompt 强制带引用 + 拒答;
  5. 接入层:Next.js BFF + SSE 流式,Slack / 飞书机器人 + 网页 UI 双入口;
  6. 可观测:Langfuse 自部署,监控 TTFT / 召回 / 满意度;
  7. 合规:私有化部署 / 数据不出网 / 审计日志;
  8. 运营闭环:用户点踩的样本进入"待整理"队列,由文档负责人补充 / 更新。

面试官追问:

  • "为什么不直接用 ChatGPT?" → 数据合规 + 内部知识;
  • "为什么 Hybrid 不只向量?" → 产品编号 / 错误码 / 专有名词;
  • "怎么评估效果?" → 准备 100 条 ground truth + RAGAS 跑回归。

# 257. 场景题:让你做一个"代码评审 Agent",怎么设计?

最小可行:

  1. 触发:GitHub Actions / GitLab Webhook,PR 创建时拉 diff;
  2. 预处理:识别变更文件类型、过滤 vendor / lock / generated;
  3. Tool 集合:read_file、search_code、run_linter、run_tests;
  4. Agent 流程
    • 读 diff → 理解改了什么;
    • 看 related files 拿上下文;
    • 跑 lint / type check 看明显问题;
    • 用 LLM 评审 → 输出结构化建议;
  5. 输出:行级 comment + 总体评分 + 必须修 / 建议修两档;
  6. HIL:高严重度自动 request changes,其他只提建议;
  7. 反馈闭环:开发者标记"无效建议",反过来调 Agent。

要点:让 Agent 跑工具拿事实,不要让它凭"读 diff"瞎评。

# 258. 场景题:公司 ToB 客户要私有化 LLM,从硬件到部署你怎么选?

阶段化:

  • POC:单卡 A10/A100,跑 Qwen-14B AWQ 量化版,Ollama / vLLM 起来快;
  • 试运行:2-4 卡 H800 / 4090 部署,跑 32B / 70B AWQ,vLLM + nginx 反代;
  • 生产:8 卡 H100 集群 + K8s + vLLM serverless 模式 + Prometheus + Grafana;
  • 监控:tokens/s、并发、显存、温度、错误率;
  • 备份模型:主模型挂时自动切到备模型。

要点:别一上来上 70B,先证明小模型 + RAG 业务跑得通,再扩。

# 259. 场景题:让你优化一个"AI 回答平均要 30 秒"的产品,怎么排查?

按"用户感知"维度拆:

维度 排查 优化
TTFT streaming 是否开 / 网关是否缓冲 上 SSE / 关闭 buffer
首跳网络 是否走 CDN / 边缘 Edge Runtime / CDN
Prompt 长度 system + 历史是否过长 压缩 + Prompt Caching
工具调用 串行 vs 并行 改并行
RAG 检索 单次召回耗时 加索引 / Reranker 异步
模型 是否用了 o1 / DeepSeek-R1 这种慢模型 切到 Haiku / GPT-4o-mini
后端处理 是否在 LLM 调用前同步等了一堆数据 提前并行加载

不要只看一个数字,画成瀑布图才知道时间花在哪。

# 260. 场景题:让你做一个"AI 客服",怎么保证不乱说话?

防护多层:

  1. 意图分类:先用小模型分类用户意图,只有白名单内意图才走 AI 回答
  2. 强 system prompt:明确回答范围 + 拒答规则;
  3. RAG 限定知识源:只用公司知识库,不让模型用通用知识;
  4. 关键事实校验:金额、订单状态、政策类回答用代码二次确认;
  5. 敏感词过滤:输出前过一层;
  6. HIL 兜底:遇到投诉 / 复杂诉求 → 转人工;
  7. 审计 + 回溯:所有对话保存,方便事后排查;
  8. 持续学习:用户点踩样本 → 改 prompt / 加 FAQ。

宁可"我不知道"也不能"瞎说"。

# 261. 场景题:把 ChatGPT 类的对话产品迁移到你们的国产替代方案,应该注意什么?

不只是改 SDK:

  • Tokenizer 不同:上下文 token 估算要重新校准;
  • system / user / assistant 行为差异:有些国产模型对 system 不那么"听话",要在 user 里补强;
  • 工具调用格式:每家略有差异,封一层适配器;
  • 流式协议:不一定都标准 SSE,写 fallback;
  • 速率限制 / 重试:不同家限流策略不一样;
  • 多模态接口:图片 base64 / URL 支持度不同;
  • 价格 / token 模式:算成本要重新做。

测试一定要跑端到端真实场景而不是单元测试。

# 262. 场景题:用户对 AI 输出不满意怎么办?

产品 / 工程都要联动:

  • 用户视角:点踩 / 重试 / 编辑 / 切模型;
  • 数据视角:点踩样本进入标注队列,每周一次回顾改进 prompt / 知识库;
  • 指标视角:监控点赞率 / 点踩率 / 重试率 / 满意度;
  • 闭环视角:改进上线后 A/B 看指标是否上升。

不要只在用户体验上做"满意度评分",要落到可改进的样本

# 263. 场景题:模型出现"复读机"现象怎么处理?

复读 = 同一句话不断重复,原因可能:

  • temperature 太低 + presence_penalty 太低;
  • 模型陷入局部最优;
  • 部分量化模型常出。

处理:

  • 适度提高 temperature(0.5-0.7);
  • 设置 presence_penalty / frequency_penalty;
  • 用更大的模型;
  • streaming 时前端检测连续 N 个 token 重复 → 中断;
  • 后端检测连续 N 句重复 → 中止并重试。

# 264. 场景题:怎么做"AI 应用的灾备 / 降级"?

模型挂了你的产品不能挂:

  • 多模型互备:主模型超时 → 自动切到备模型;
  • 降级回答:模型完全不可用时返回 FAQ / 文档链接;
  • 缓存兜底:常见问题预生成答案,挂了也能答;
  • 熔断:错误率高于阈值时自动熔断,不要持续重试拖垮系统;
  • 状态保留:用户的会话别因为模型挂了就丢,能继续接着用。

# 265. 自我介绍:怎么把"我做过 AI 项目"讲得让面试官眼前一亮?

模板:

我在 [项目名] 里做了一个 [一句话功能],
解决的核心问题是 [业务痛点]。
技术上用了 [前端栈] + [LLM + 工具] + [RAG / Agent / 工作流],
关键决策点是 [选型 + 为什么]。
上线后 [一两个指标] 提升了 [X%],
我自己负责 [模块 / 端到端],
踩过的最深的坑是 [真实事故],最后用 [方案] 解决。

要点:有数字 + 有决策 + 有踩坑,三件套缺一不可。

# 266. 场景题:让你设计一个 Cursor 同款 AI 编辑器,怎么做?

参考方案:

  1. 编辑器内核:Monaco / CodeMirror 起步,复用社区基础;
  2. AI 集成方式
    • 行内补全(ghost text + FIM);
    • 选中改写(command palette / 浮动菜单);
    • 侧边栏对话(项目级问答);
    • 端到端任务(Agent 跑工具改文件);
  3. 上下文管理:当前文件 + workspace 索引(用向量库);
  4. 工具集:read_file / write_file / edit_file / run_command / search_code;
  5. Agent 模式:plan + execute + diff 三阶段;
  6. diff 预览:AI 改动以 diff 形式预览,用户 Accept/Reject;
  7. 历史回滚:每次 AI 改动一个 commit;
  8. 多模型支持:用户可切 Claude / GPT / 本地模型;
  9. 隐私模式:可选不把代码上传给云模型。

被追问要点:

  • 为什么 Cursor 比 Copilot 好?→ workspace 级上下文 + 多文件编辑;
  • diff 预览为什么必须?→ 用户对 AI 改动可控;
  • 本地模型有什么用?→ 合规 / 离线 / 省钱。

# 267. 场景题:AI 监控告警归并系统怎么做?

业务背景:监控系统一天发几千条告警,人工看不过来。

方案:

  1. 采集:从 Prometheus / Grafana / Sentry / 日志系统 webhook 接告警;
  2. 归一化:把不同来源的告警转成统一 schema(service / severity / message / time);
  3. 聚类:用 embedding 做向量聚类,相似告警归一组;
  4. AI 总结:每组让 LLM 生成"根因猜测 + 影响范围 + 建议动作";
  5. 优先级:用 LLM 评分 P0-P3,根据评分推不同通道(电话 / IM / 邮件);
  6. 关联历史:检索过去类似告警的解决记录,附在新告警旁边;
  7. HIL:高严重度自动推 + 人工确认才能 ack;
  8. 闭环:值班人员标"误报 / 已解决"反向训练系统。

收益:值班人从看 1000 条到看 20 组,注意力聚焦。

# 268. 场景题:智能客服路由(什么时候转人工)?

不能让 AI 永远兜底。分流策略:

场景 处理
简单查询 / FAQ AI 直接答
涉及金额 / 退款 / 投诉 直接转人工
用户连续点踩 N 次 转人工
AI 检索后置信度低(无相关文档) 转人工
用户明确说"转人工" 立即转
涉及合规 / 法务 转人工
情绪检测:用户情绪激动 转人工
关键词触发("投诉 12315") 转人工 + 飞书报警

转人工时带上对话摘要,人工不用从头看。

# 269. 场景题:让 AI 把设计稿自动转代码?

务实方案(注意:完全自动不可行,辅助才靠谱):

  1. 输入:Figma URL 或截图;
  2. 解析:调 Figma API 拿出结构化设计描述(不是裸图);
  3. 组件匹配:和项目已有组件库(antd / shadcn)做 mapping;
  4. 代码生成:让 AI 输出用项目组件实现的代码,不是从零写;
  5. 样式提取:颜色、字号、间距从 design token 取;
  6. 响应式:要求 AI 输出多个 breakpoint;
  7. 人工 review:开发者 review + 微调,不能 100% 替代。

避免误区:让 AI"看图写代码"会得到一堆 inline 样式的烂代码,结合设计系统的代码生成才有产品价值。

# 270. 场景题:AI 应用的 SLA 怎么保证?

外部模型不可控,SLA 必须做兜底:

  • 多模型互备:主模型挂自动切;
  • 本地小模型兜底:基本能答简单问题;
  • 熔断 + 降级:错误率高于阈值就熔断,UI 降级为"暂不可用";
  • 缓存预热:常见问题预生成答案;
  • 告警:错误率 / 延迟 / token 用量异常立刻报警;
  • SLA 透明化:状态页 + 月度报告;
  • 限流 + 公平队列:避免少数用户拖垮所有人。

ToB 客户要看 SLA 数字,说不准就别承诺

# 271. 场景题:多端 AI 助手(Web + iOS + Android + 桌面)怎么统一?

架构:

  • 核心 API 后端:唯一事实来源,所有端都调它;
  • 会话存储:服务端为主,端侧只缓存;
  • 流式协议:SSE 或 WebSocket,端侧统一适配;
  • 同步:端侧 push 新消息到服务端 + 拉取其他端的更新(WebSocket 推送);
  • 离线:端侧支持只读历史 + 草稿;
  • 能力差异:端侧能力不一致(如桌面端能跑本地模型、移动端只能调云),后端按 capability 协商;
  • 共享 prompt / 配置:通过 globalConfig 接口下发。

不要每端各写一套核心逻辑,重 BFF 或 SDK

# 272. 场景题:AI 应用全链路可观测性怎么做?

至少四层:

工具 看什么
前端 Sentry / Web Vitals 客户端错误、TTFB、流式卡顿
接入层 Nginx / API Gateway 请求量、错误码、限流
LLM 调用层 LangSmith / Langfuse 每次调用的 prompt、token、cost、耗时
Agent / RAG 自定义 trace 每步 plan / tool / retrieval / output

聚合:

  • 全链路 trace_id 串起来;
  • 每个请求能从前端点击 → 后端 → LLM → 工具调用 → 回包,一条线追完;
  • 关键指标进 Grafana 看实时;
  • 错误归类 + alerting。

没有可观测 = 没法调优 = 没法上线。

# 273. 场景题:AI 应用合规风险有哪些?怎么处理?

不只是技术问题,是法务问题:

  • 数据出境:海外模型涉及,国内业务要走合规审批;
  • PII 保护:身份证 / 手机号 / 地址不能明文进 prompt;
  • 未成年人保护:可能触发实名 + 内容过滤;
  • 大模型生成内容备案(国内):明确告知用户"内容由 AI 生成";
  • 版权:生成内容的归属、训练数据的合法性;
  • 审计:所有对话保留 N 天,监管要求随时调取;
  • 拒答场景:政治、暴力、医疗 / 法律建议要做明显约束。

合规上线前一定有法务过一遍。

# 274. 场景题:把团队"AI First"推进开发流程,怎么做?

不是发几个 ChatGPT 账号就行:

  1. 统一工具链:选一两个核心工具(Claude Code / Cursor / Copilot),统一付费 / 培训;
  2. 统一 prompt 库:把团队验证过的高质量 prompt 共享出来;
  3. 统一 MCP / Skills:把内部工具封装成可复用能力;
  4. 代码规范同步给 AI:CLAUDE.md / .cursorrules 写好;
  5. 培训 + 分享:每周一次 AI 用法分享,沉淀 best practices;
  6. 指标驱动:跟踪 AI 工具使用率 / commit 中 AI 参与比例 / 节省工时;
  7. 底线规则:什么不能让 AI 做(提交不读、改生产、写测试不审);
  8. 合规护栏:源代码 / 客户数据不进个人账号。

记住:工具好不好用,看团队;不是发完账号就万事大吉。

# 275. 终极开放题:如果让你三年内深耕一个 AI 方向,你会选哪个?

参考思路(不要背,要按自己情况答):

  • AI Agent 工程:架构 + 工具 + 落地,需求量最大;
  • Context Engineering / Prompt Engineering:基础设施型岗位;
  • RAG / 知识工程:ToB 长青;
  • AI 基础设施:网关 / 推理 / 评估,技术门槛高;
  • 多模态 / 端侧:手机 / 车机 / 机器人,硬件结合;
  • AI 安全 / 对齐:研究偏多,国内还没大规模商业化;
  • AI 产品:把模型能力翻译成用户价值,需求量上升。

要点:

  • 自己有兴趣 + 公司有资源的方向;
  • 不要追最热(红海早进的人吃肉,晚进的人吃灰);
  • 每个方向都需要工程能力 + 业务理解,纯算法岗在缩。

# 附录:常用速查表(背版)

# AI 名词速查(面试官最爱当快问快答)

名词 一句话
Prompt 给大模型的输入指令,控制行为 / 风格 / 思路
LLM Large Language Model,大语言模型
Token 模型实际处理的最小单元,影响计费和上下文
Context Window 一次能看到的最大 token 数
Embedding 把文本压成高维向量,反映语义相似度
RAG 检索增强生成,给模型外挂知识库
Fine-tuning 用领域数据在预训练模型上继续训练
PEFT / LoRA / QLoRA 轻量微调,省显存的代表方案
Agent LLM + 工具 + 记忆 + 规划,能自主完成任务
Tool Agent 能调用的外部功能(接口、文件、命令)
Function Calling 模型按 schema 输出 JSON 决定调哪个函数
MCP Model Context Protocol,跨语言跨进程工具协议
CoT Chain of Thought,让模型先想再答
ReAct Reason + Act,Agent 的基础范式
Memory 模型的"记忆",分短期 / 长期 / 工作记忆
Hallucination 模型幻觉,听起来合理但事实错误
Prompt Injection 用户输入夹带恶意指令攻击 system prompt
Jailbreak 突破模型自身安全限制
Streaming 一边生成一边推到客户端
TTFT First Token Time,首 token 出现时间
Prompt Caching 复用 KV Cache 给重复 prompt 打折计费

# 主流模型(2026 年)

厂商 主力 特点 适合
Anthropic Claude Opus 4.7 / Sonnet 4.6 / Haiku 4.5 Agent、长文本、代码 复杂 Agent / 编程
OpenAI GPT-4.1 / GPT-5 / GPT-4o / o1 通用、工具生态 通用业务、多模态
Google Gemini 2 Pro / Flash 多模态、超长上下文 长文档、视频
Meta LLaMA 系列 开源标杆、微调研究事实底座 学术研究 / 私有定制
DeepSeek V3 / R1 开源、推理 / 代码 / 数学强 私有化、降本、推理任务
阿里 Qwen Max / Plus / Qwen-VL 中文、私有化生态 ToB / 多模态
Moonshot Kimi K1 长文本、中文阅读 长文档问答
智谱 GLM-4 国内私有化好 国企 / 政企
字节 豆包 / Doubao 抖音生态打通 字节渠道
Mistral / Phi / Gemma 1B - 14B 轻量模型 边缘部署、端侧推理 IoT / 浏览器 / 端侧 Agent

# 主流框架 / SDK

类别 推荐
前端 SDK Vercel AI SDK
后端 Agent LangChain / LangGraph
多 Agent CrewAI / AutoGen / LangGraph
RAG LlamaIndex / LangChain
向量库 pgvector / Milvus / Qdrant / Chroma
评估 RAGAS / DeepEval / TruLens
可观测 LangSmith / Langfuse / Helicone
私有化推理 vLLM / Ollama / SGLang

# Prompt 万能骨架

# 角色
# 任务
# 输入
# 步骤(复杂任务必加)
# 输出格式
# 约束
# 示例(复杂任务必加)

# Agent 公式

Agent = LLM + 工具 + 记忆 + 规划
用户输入
  ↓
规划(拆任务)
  ↓
循环:思考 → 工具调用 → 观察 → 再思考
  ↓
输出 + 写记忆

# RAG 公式

切片 → embedding → 入库
查询 → 改写 → 向量召回 + BM25 召回 → 重排 → top-k
材料 + 问题 → LLM → 回答(带引用)

# MCP 公式

LLM ↔ Function Calling ↔ Client ↔ MCP Protocol ↔ Server ↔ Real Tools

# Memory 公式

全量 messages → 滑动窗口 → 滑动窗口 + 摘要 → 向量长期记忆 → 图谱 / 结构化记忆

第一版整理到这里。每年都会补 30-50 道新题,建议只看问题不看答案先自己讲一遍,能讲清的跳过、卡壳的再看答案。

真正能拉差距的不是题目多寡,而是有没有真的写过 Agent、调过 RAG、踩过 Memory 的坑。面试前找一个你正在用的产品想想能怎么加 AI,自己做一个最小 demo 上线让真实用户用一周,胜过刷十遍题。

阅读全文
webapp
公众号
开发者导航
切换夜间模式
折叠侧边栏
收起全部