AI 大模型面试核心八股:从模型本质、微调、RAG 到 Agent 工程落地
这篇文章整理的是大模型应用工程里很常见的一组面试问题。它不只是为了背概念,而是想把这些概念放到真实工程里看:大模型到底是什么,为什么要微调,RAG 怎么提升准确率,MCP 和 Agent 各自解决什么问题,Agent 调用工具报错怎么办,长任务记忆爆了又该怎么处理。
如果只用一句话概括整篇文章,我觉得可以这么说:
大模型应用不是简单调一个 LLM API,而是围绕模型、数据、知识库、工具、任务编排、评估和闭环迭代搭起来的一套工程系统。
一、大模型的本质是什么?
很多面试官会先问一个看起来很基础的问题:大模型的本质到底是什么?
这个问题不能只回答"大模型很智能""大模型能理解语言"。更准确的说法是:现在主流的大语言模型,本质上是基于 Transformer 架构训练出来的高维条件概率分布模型。它最底层的训练目标,是不断做 Next-Token Prediction,也就是根据当前上下文预测下一个 Token。
换句话说,模型每次生成内容,其实都是在计算:
text
P(下一个 Token | 当前上下文)
所以,从微观层面看,大模型是在做条件概率预测;从中观层面看,它把语言规律、知识模式和大量世界信息压缩进了参数权重里;从宏观层面看,当数据规模、参数规模和算力规模足够大时,它就会表现出推理、代码生成、多轮对话、泛化迁移等能力,也就是我们经常说的"涌现能力"。
但是这里一定要注意:大模型不是数据库。
它虽然能回答很多知识性问题,但它不能保证参数里的知识永远最新,也不能保证每句话都有事实依据。尤其是企业内部文档、实时数据、业务系统状态,这些都不是模型参数天然知道的。所以在工程里,通常还要配合 RAG、工具调用、Prompt Engineering、微调、评估体系和安全防护来提升可靠性。
如果面试时被问到"大模型的本质是什么",可以这样回答:
从技术底层看,大模型本质上是基于 Transformer 的条件概率分布模型,它通过 Next-Token Prediction 来预测下一个 Token。在预训练阶段,模型会从海量语料中学习语言结构、知识模式和推理规律,并把这些信息压缩到参数权重中。当数据规模、参数规模和算力达到一定程度后,模型会出现一定的涌现能力,比如推理、代码生成、多轮对话和泛化能力。但它本质上仍然不是数据库,也不是绝对可靠的知识系统,所以工程上通常会结合 RAG、Prompt Engineering、微调和评估体系来提升可靠性。
二、优质的大模型参数是怎么来的?
大模型参数不是人工一条条写进去的,而是训练出来的。一个比较好记的表达是:
text
优质海量数据 + 稳定暴力算力 + 精细偏好对齐 = 高质量模型参数
也可以说,优质参数的形成,本质上是一场数据、算力、算法和工程稳定性的组合工程。
一般来说,大模型训练会经历几个重要阶段。
第一个阶段是 数据淬炼。数据阶段决定模型能力上限。这里要处理乱码、重复数据、低质量内容、敏感内容、评测集污染等问题,还要控制通用文本、代码数据、数学数据、专业语料之间的比例。很多模型看起来榜单分数高,但真实使用效果差,很可能就是训练数据和评测数据发生了污染,模型只是"背到了题",而不是真的具备泛化能力。
第二个阶段是 规模预训练。这一阶段的核心目标是通过 Next-Token Prediction 注入通用语言能力和世界知识。这里会涉及 Scaling Laws、优化器、并行训练、学习率调度、数值稳定性等问题。如果训练过程中出现 Loss 突然发散、梯度爆炸、NaN,可能会导致几个月训练直接报废。因此,工程上通常会使用 RMSNorm、梯度裁剪、高频 Checkpoint、自动恢复机制等手段来保证训练稳定。
第三个阶段是 指令微调 SFT。预训练模型会续写文本,但不一定会听懂人类指令。SFT 的作用就是通过高质量的问答对、任务指令、格式样例,让模型学会"用户让我做什么,我就按要求完成什么"。比如从"续写一段合同文本"变成"提取这段合同里的风险点"。
第四个阶段是 偏好对齐。模型能回答问题不代表回答得安全、礼貌、可靠。偏好对齐的目标,是让模型更符合人类偏好,尽量做到 Helpful、Honest、Harmless,也就是有用、诚实、无害。常见方法包括 RLHF 和 DPO。其中 RLHF 流程更复杂,需要奖励模型和强化学习;DPO 工程上更简单,直接利用偏好数据优化模型,因此现在很多项目会优先考虑 DPO。
面试时可以这样总结:
优质参数不是直接写进去的,而是数据、算力和训练目标共同作用的结果。一般流程包括数据淬炼、规模预训练、指令微调和偏好对齐。数据阶段要保证高质量、去重、去污染,并控制通用数据、代码数据、数学数据等比例;预训练阶段通过 Next-Token Prediction 注入通用知识和语言能力;SFT 阶段让模型学会遵循指令和按格式回答;最后通过 RLHF 或 DPO 做人类偏好对齐,让模型更安全、更有用、更符合真实业务需求。
三、怎么判断一个大模型是否学得好?
判断模型好不好,不能只盯着 Loss,也不能只盯着某一个榜单分数。Loss 下降只能说明模型在训练或验证数据上的预测更稳定,但它不一定代表模型真的会推理,也不一定代表业务场景里好用。
比较完整的评估体系,至少要分成四层。
第一层是 训练统计指标。比如 Loss 曲线、PPL 困惑度、梯度范数、验证集表现、学习率变化等。这一层主要用来判断训练过程是否健康,有没有发散、过拟合或数值异常。
第二层是 客观 Benchmark。比如通识与学科知识、数学推理、代码生成、多语言能力、长上下文能力、工具调用能力等。这一层可以看出模型能力的广度和深度。比如代码模型不只是看能不能生成代码,还要看能不能通过单元测试、能不能修复错误、能不能解释代码逻辑。
第三层是 主观对齐和人类偏好。一个模型不仅要会回答,还要回答得像一个可靠助手。这里常用 LLM-as-a-Judge、HHH 安全准则、Elo Rating、人工评估等方式,看模型是否有用、诚实、无害,是否能合理拒答,是否能抵御越狱攻击。
第四层是 真实业务 ROI。最终模型好不好,要看它在线上是否真的创造价值。比如 A/B 测试、采纳率、用户留存、问题解决率、首轮解决率、推理速度、并发吞吐、内存占用和 Token 成本等。很多模型离线评测不错,但一上线就发现成本太高、延迟太大、用户不买账,这就说明评估体系不完整。
面试时可以这样回答:
不能只看训练 Loss。一般要从四个层面判断:第一,看训练统计指标,比如 Loss、PPL、梯度范数,判断训练是否稳定;第二,看 Benchmark,比如通识、数学、代码、推理能力;第三,看人类偏好和安全对齐,比如 LLM-as-a-Judge、HHH、Elo Rating;第四,看真实业务指标,比如 A/B 测试、用户采纳率、留存、推理成本和响应速度。所以模型好不好,最终要看它在真实业务场景里是否稳定、可控、低成本并且有实际价值。
四、什么是微调 Fine-tuning?
微调就是在一个已经预训练好的大模型基础上,用特定领域、特定任务、特定风格的数据继续训练,让模型从"通用能力强"变成"更适合某个具体场景"。
可以用一个类比理解:
text
预训练模型 = 大学毕业生
微调后模型 = 某个岗位上的专业员工
预训练模型已经具备大量通用知识,但它不一定懂你的业务,不一定按你的格式回答,也不一定符合你的安全要求。微调的作用,就是让模型更懂特定领域知识、特定任务流程、特定输出格式、特定风格语气和特定安全边界。
比如医疗问答场景,希望模型更懂医学术语、病历结构和诊疗逻辑;法律合同场景,希望模型更懂条款解释、风险识别和合规表达;代码助手场景,希望模型更擅长代码生成、修复、解释和测试;企业客服场景,希望模型更符合企业话术、业务规则和服务流程。
但是需要注意,微调不是让模型从零学习知识,也不是万能知识注入器。更准确地说,微调是在已有大模型能力基础上,让它更适配具体任务和业务场景。
可以把预训练、微调和对齐的关系理解为:
text
预训练:让模型拥有通用知识
微调:让模型适配具体任务
对齐:让模型更符合人类期望
在生命周期上,大致是:
text
基础预训练
↓
监督微调 SFT
↓
偏好对齐 DPO / RLHF
↓
业务专用模型
五、为什么需要进行微调?
通用大模型虽然能力很强,但默认只是一个通用助手。真正落到企业、行业、产品场景里,经常会遇到几个问题:它不一定严格遵循指令,不一定懂垂直领域规范,不一定符合人类偏好,也不一定满足成本和延迟要求。
所以微调的核心价值,是让一个通用大模型从"什么都懂一点",变成"在某个具体业务场景里稳定、可控、低成本地完成任务"。
第一类动因是 激发指令遵循能力。基础模型本质上更像一个"词语接龙器",它擅长续写文本,但不一定擅长按照人类指令完成任务。比如用户说"请把下面这段内容整理成 JSON",没有经过指令微调的模型可能只是继续补全文本;经过 SFT 之后,它更容易理解这是一个任务,需要按照指定格式输出,不能随便发挥。
第二类动因是 注入领域规范。通用模型可能知道医疗、法律、金融、代码等领域的一些常识,但不一定懂具体行业里的表达方式、业务流程和专业规范。比如法律场景要求严谨措辞,医疗场景要求风险提示,客服场景要求统一话术,这些都可以通过微调强化。
第三类动因是 人类偏好对齐。模型原始生成能力强,但不代表回答一定安全、礼貌、可靠。它可能胡编,也可能该拒绝时不拒绝,还可能输出不符合安全规范的内容。通过 RLHF、DPO、拒答数据、安全数据训练,可以让模型更接近 Helpful、Honest、Harmless。
第四类动因是 降本增效。很多业务场景不需要每次都调用最强的大模型。如果任务边界明确,比如客服分类、信息抽取、固定格式生成、合同风险初筛、文档标签判断,可以通过微调一个较小模型,让它在特定任务上接近大模型效果,从而降低推理成本,提高响应速度,也更适合私有化部署。
不过,微调不是所有问题的最佳答案。适合微调的场景一般是:需要固定输出格式、统一客服话术、强化某类任务能力、学会拒答边界、有大量高质量标注数据、希望小模型承担固定任务。
如果是知识经常更新、需要引用企业内部文档、需要查数据库或 API、只是临时改变输出风格,通常不应该优先微调。更合理的判断是:
text
Prompt 解决表达问题
RAG 解决外部知识问题
Tool 解决实时操作问题
Fine-tuning 解决行为模式和任务适配问题
面试中可以这样回答:
我理解微调的核心目的,是让通用大模型更好地适配具体业务场景。预训练模型具备通用语言能力和知识,但它不一定能稳定遵循业务指令,也不一定懂垂直领域规范,更不一定符合企业的输出格式、安全边界和成本要求。所以微调主要解决四类问题:第一,让模型通过 SFT 学会指令遵循;第二,通过领域数据注入行业表达和任务模式;第三,通过 DPO 或 RLHF 进行人类偏好和安全对齐;第四,在明确任务上用小模型达到接近大模型的效果,从而降低推理成本和提升响应速度。但微调不是万能的。如果是知识更新、企业文档问答或事实检索,我会优先考虑 RAG;如果是调用系统或实时数据,我会考虑 Tool Calling。微调更适合解决行为模式、输出规范和任务适配问题。
六、微调的标准流程是什么?
大模型微调不是"拿一批数据直接开训"这么简单。一个相对完整的流程可以分成六步:
text
明确目标与场景
↓
数据处理与构造
↓
模型选择与微调策略
↓
环境配置与工程训练
↓
模型多维评估
↓
部署上线与持续迭代
第一步是 明确目标与场景。训练之前要先搞清楚模型到底要解决什么问题,是增强领域知识,还是增强任务能力,还是控制输出格式和安全边界。比如是医疗问答、法律合同、代码生成,还是客服话术。目标不清楚,后面的数据和评估都会跑偏。
第二步是 数据处理与构造。这一步通常最耗时,也是成败关键。核心原则是"数据质量大于数据数量"。要做去重、去乱码、去低质量内容、去敏感内容、去逻辑不通的数据,还要构造 Instruction-Input-Output 格式的数据。比如:
text
Instruction:请提取下面文本中的合同风险点
Input:这里是合同内容
Output:风险点一......风险点二......
这里有一个非常常见的坑:数据模板必须和基座模型的 Chat Template 对齐,否则模型可能出现输出错乱、不停生成、结束符异常等问题。
第三步是 模型选择与微调策略。这一阶段要决定选哪个基座模型,用全参数微调还是 LoRA,是否需要 QLoRA,是否做 SFT,是否做 DPO。资源充足并追求效果上限,可以考虑 Full SFT;大多数企业场景更常用 LoRA;显存有限时可以考虑 QLoRA;如果需要提升偏好和安全性,可以加入 DPO;如果既需要领域行为又需要事实可靠,通常会结合 RAG。
第四步是 环境配置与工程训练。这一步主要解决训练能不能跑起来、跑得稳不稳。常见问题有 OOM、训练中断、Loss 不收敛、梯度爆炸、模型复读、训练太慢等。解决手段包括 QLoRA、减小 batch size、梯度累积、Gradient Checkpointing、ZeRO、BF16、梯度裁剪、Early Stopping、Weight Decay、Dropout 等。Gradient Checkpointing 可以理解为用更多计算时间换更少显存占用。
第五步是 模型多维评估。微调后不能只看 Loss 下降,因为 Loss 下降不等于模型真的好用。评估要看 Benchmark、LLM-as-a-Judge、人工评估、业务指标、安全评估,还要关注幻觉率、拒答能力、格式稳定性、任务完成率、成本、延迟、用户采纳率等。尤其要记住,微调后仍然可能存在严重幻觉,所以不能完全指望微调记忆知识,很多事实类场景仍然要结合 RAG。
第六步是 部署上线与持续迭代。微调不是训练完就结束。上线之前可能要做 LoRA 权重合并、推理加速、灰度发布、A/B 测试。上线之后要收集 Bad Case,比如答非所问、格式错误、事实编造、拒答不合理、安全边界失效,然后清洗后加入下一轮训练数据,形成数据飞轮。
面试时可以这样回答:
我理解的大模型微调流程一般分为六步。第一步是明确目标和场景,确定模型到底要增强领域知识、任务能力,还是输出格式和安全边界。第二步是数据处理,包括清洗、去重、脱敏、去污染,以及构造 Instruction-Input-Output 格式的数据。第三步是选择基座模型和微调策略,例如 Full SFT、LoRA、QLoRA、DPO 等。第四步是工程训练,包括显存优化、梯度检查点、混合精度、batch size、学习率和 checkpoint 管理。第五步是多维评估,不能只看 Loss,还要看 Benchmark、人工评估、LLM-as-a-Judge、幻觉率和业务指标。第六步是部署上线与迭代,包括权重合并、推理加速、灰度发布、Bad Case 收集和数据飞轮优化。
七、主流微调方案:Full Fine-tuning、LoRA、QLoRA、RLHF 和 DPO
全参数微调,也就是 Full Fine-tuning,指的是更新模型里的所有参数。它的优点是效果上限高,模型整体适配程度强;缺点也很明显:显存消耗巨大、训练成本很高、容易 OOM、容易灾难性遗忘,工程代价很大。一般只有资源非常充足的大厂或实验室会经常使用。
LoRA 是更常见的参数高效微调方法。它的核心思想是:冻结原始大模型参数,只额外训练一小部分低秩矩阵。可以理解为原模型不动,在旁边加一个小插件,只训练这个插件。它的公式可以写成:
text
ΔW = A × B
意思是模型权重变化量不直接训练完整大矩阵,而是用两个更小的低秩矩阵 A 和 B 来近似。LoRA 的好处是显存占用低、训练成本低、效果不错、容易部署,适合多数业务微调场景。
面试里可以说:
LoRA 的核心思想是冻结基座模型参数,通过训练旁路的低秩矩阵来近似权重更新,从而大幅降低可训练参数量和显存消耗。
QLoRA 可以理解为量化版 LoRA。它在 LoRA 基础上,把基础模型进行低比特量化,比如 4-bit,从而进一步降低显存占用。优点是显存更低,普通消费级显卡也可能跑较大模型;缺点是训练稳定性要求更高,量化可能带来精度损失,工程配置也更复杂。
RLHF 和 DPO 都属于偏好对齐方法。RLHF 是基于人类反馈的强化学习,需要奖励模型和强化学习流程,整体链路比较复杂。DPO 是直接偏好优化,直接利用偏好数据优化模型,工程上更简单、稳定、容易落地,所以很多实际项目更愿意先尝试 DPO。
八、微调中常见的坑和解决方案
微调最常见的第一个坑是 灾难性遗忘。表现是模型学了垂直领域后,原本优秀的通用能力下降,甚至变成只会做某个特定任务的复读机。解决方式包括混入 10%-20% 通用 SFT 数据、使用 LoRA 等 PEFT 方法、降低学习率、减少 Epoch、保留基础能力评估集。
第二个坑是 数据质量黑洞。如果标注数据存在幻觉、格式不统一、答案质量参差不齐,模型输出就很容易语无伦次,甚至出现复读现象。解决方式是精益清洗数据、去除低质量样本、统一数据模板、用强模型辅助改写和质检,并保证 Prompt 和 Answer 格式一致。这里最重要的原则是:微调不是数据越多越好,而是数据越干净、越一致、越贴近目标任务越好。
第三个坑是 显存和算力瓶颈。训练显存开销巨大、单卡跑不动、容易 OOM,是微调里非常常见的问题。解决方式包括 QLoRA 4-bit 量化微调、开启 Gradient Checkpointing、减小 Batch Size、使用梯度累积、使用 DeepSpeed ZeRO 做显存分片。可以简单理解为:LoRA 是少训练参数,QLoRA 是进一步压缩显存,ZeRO 是把显存压力拆到多张卡上。
第四个坑是 模型过拟合。表现是训练集 Loss 很低,但测试集效果很差,模型只会机械背诵,泛化能力差。解决方式包括 Early Stopping、Weight Decay、增加 LoRA Dropout、增强数据多样性、控制训练 Epoch。
第五个坑是 微调后仍然严重幻觉。模型可能一本正经胡说八道,尤其是开放式问题或外部事实更新后。解决方式包括加入拒答数据,让模型学会说"不知道",结合 RAG 检索真实上下文,对回答做 Faithfulness 评估,并用人工评估和强模型裁判辅助判断。这里的核心是:不能指望微调解决所有知识记忆问题,事实类需求应该结合 RAG。
如果面试官问"微调中最容易踩的坑是什么",可以回答:
我认为主要有四类坑。第一是数据质量问题,垃圾进垃圾出,数据质量比数据数量更重要。第二是灾难性遗忘,模型学了垂直领域后可能损失原有通用能力,所以需要混入一定比例的通用数据,并控制学习率和 Epoch。第三是显存和训练稳定性问题,需要用 LoRA、QLoRA、Gradient Checkpointing、梯度累积、BF16 等工程手段优化。第四是评估误区,Loss 下降不代表模型真的好用,最终还要结合 Benchmark、人工评估、业务 A/B 测试和线上 Bad Case 来判断。
九、RAG 准确率怎么从 60% 提到 85%?
这是一道非常典型的 RAG 工程面试题。它不是问你"调哪个参数",而是在考察你是否理解 RAG 的完整链路。
一个 RAG 系统的准确率,通常不是由某一个点决定的,而是由文档切分、问题理解、召回策略、重排策略、上下文过滤、生成约束和评估闭环共同决定的。
所以回答这个问题时,不要只说"调大 Top-K"或者"换 embedding 模型"。更好的回答是:
我会从离线数据处理、在线查询改写、混合检索与重排、闭环评估四个环节系统优化,而不是简单调一个参数。
第一步是 优化文档切分。很多 RAG 准确率低,不是模型问题,而是知识库切分一开始就错了。传统做法可能按 500 Token 暴力截断,但这样容易造成句子被截断、段落语义丢失、标题和正文分离、表格结构错乱、PDF 扫描件格式混乱。更好的方式是基于句子边界、Markdown 标题、段落结构、PDF 页面结构、表格结构做动态切分,并保留标题层级。为了避免关键信息刚好被切断,还可以设置 100-200 Token 的 overlap。
第二步是 优化在线查询处理。用户问题经常很短、很口语,比如"怎么退款?"直接检索可能召回质量很差,所以需要 Query Rewrite,把它改写成"用户购买课程后如何申请退款?退款流程、条件和到账时间是什么?"但是改写也可能改歪,比如把"怎么退款"改成"怎么赚钱"。所以工程上要做语义校验,用 embedding 相似度比较原问题和改写问题,如果相似度过低,比如小于 0.8,就回退到原始问题。
第三步是 混合检索与重排。RAG 不能只依赖向量检索。向量检索擅长抓语义,但可能抓不到精确关键词;BM25 擅长关键词匹配,但不懂语义;FAQ、手册、结构化规则又适合补充业务规则。因此工业级 RAG 通常会做多路召回:向量检索抓语义相似,BM25 抓关键词、人名、术语、编号,FAQ/手册补充标准答案,结构化数据补充数据库或 API 结果。
这里还要注意,向量分数和 BM25 分数不能简单相加,因为它们不在一个量纲上。向量分数通常是 0-1,BM25 分数可能是 0 到几十。更合理的方法是做归一化、排序融合,或者引入 LambdaMART 这类 Learning to Rank 方法统一排序。对于简单问题,可以直接取 Top3;复杂问题可以先召回 Top30,再用 Reranker 重排到 Top3。
第四步是 建立闭环评估。不能只看最终回答正确率,因为答案错可能来自很多地方:问题没理解对、Query Rewrite 改歪、召回没召到、召回到了但排序靠后、上下文太多导致模型没用对、生成阶段发生幻觉。应该拆成 Context Recall、Context Precision、Faithfulness、Answer Correctness、首轮解决率、幻觉率、延迟和成本等指标。
尤其是这三个指标很重要:
text
Context Recall:答案在不在召回里?
Faithfulness:回答有没有胡编?
首轮解决率:用户一问是否解决?
面试时可以这样回答:
如果要把 RAG 准确率从 60% 提到 85%,我不会只调 Top-K 或者换 embedding 模型,而是会从 RAG 全链路排查。第一是离线数据处理,固定 Token 硬切分容易破坏语义边界,所以我会按标题、段落、句子、表格结构做动态切分,并加入 overlap,保证 chunk 语义完整。第二是在线查询处理,对短问题和口语问题做 Query Rewrite,但改写后要用 embedding 相似度和原问题做语义校验,防止改写偏题。第三是检索策略,采用向量检索、BM25、FAQ 或结构化数据的多路召回,再用 Reranker 或 Learning to Rank 做重排;简单问题直接 Top3,复杂问题先 Top30 再重排到 Top3。第四是评估闭环,不只看最终准确率,而是拆成 Context Recall、Context Precision、Faithfulness、Answer Correctness、首轮解决率和幻觉率。这样才能知道问题到底出在切分、召回、排序还是生成阶段。所以 RAG 准确率提升,本质是从暴力切分走向语义闭环,从单路召回走向混合检索和可观测评估。
十、RAG 系统里为什么要做 Query 改写?
Query 改写的核心目的,是把用户"不规范、不完整、不适合检索"的问题,转换成更适合知识库召回的检索表达,从而提升 Recall,降低语义偏差,并改善最终回答质量。
RAG 不是用户怎么问系统就怎么搜。真实用户的问题往往很口语、很短、上下文省略严重,比如"这个怎么弄?""怎么退款?""它为什么报错?"这些问题对人来说可能能理解,但对检索系统来说信息太少。文档里可能写的是"账户异常冻结处理流程",用户问的是"账号被封了怎么办",两者意思接近,但字面表达不同,直接检索可能召回不到。
常见 Query 改写策略主要有五类:Query Rewrite、Multi-Query、Decomposition、HyDE 和 Step-Back。
Query Rewrite 是最基础的单问题改写。它把用户原始问题改写成更规范、更清晰、更适合检索的问题。比如把"怎么退款?"改成"用户购买课程后如何申请退款?退款条件、退款流程和到账时间分别是什么?"它适合问题太短、口语化、缺少关键词、检索意图不清晰的情况。工程上要注意语义一致性校验,避免改写偏题。
Multi-Query 是从多个角度生成多个检索 Query。比如用户问"RAG 为什么召回效果不好?",可以扩展成"RAG 召回率低的原因""向量检索召回不到相关文档怎么办""RAG chunk 切分对召回效果的影响""RAG query rewrite 和 rerank 优化方法"。它的好处是提高 Recall,减少单一 Query 表达造成的漏召回;缺点是召回数量增加,噪声和成本也会上升,所以要配合 Rerank。
Decomposition 是把复杂问题拆成多个子问题,分别检索后再汇总回答。比如"企业版用户购买超过 30 天还能不能退款?退款流程是什么?多久能到账?"可以拆成企业版退款条件、超过 30 天是否退款、退款流程、到账时间等子问题。它适合多跳推理、复杂条件判断、对比类问题。
HyDE 是 Hypothetical Document Embeddings。它的思路是先让 LLM 根据用户问题生成一个"假想答案"或"假想文档",再用这个假想答案做向量检索。因为文档片段通常更像答案文本,而不是问题文本,所以用假想答案检索可能更接近真实文档。但 HyDE 有幻觉风险,因此生成的假想答案只能作为检索辅助,不能直接作为最终答案。
Step-Back 是先把具体问题抽象成更高层的原则问题,再检索背景知识,最后回到原问题推理。比如用户问"我这个订单买了 35 天,还能不能退款?"可以先改写成"平台退款政策中,关于退款期限和特殊情况的通用规则是什么?"先查规则,再结合具体条件判断。它适合法律、政策、医疗、金融、技术原理等需要背景规则的问题。
这五种策略可以这样对比:
| 策略 | 解决什么问题 | 适合场景 | 风险 |
|---|---|---|---|
| Query Rewrite | 原问题表达不规范 | 口语化、模糊问题 | 改写偏题 |
| Multi-Query | 单一表达召回不足 | 问题较泛、文档表达多样 | 噪声变多 |
| Decomposition | 问题太复杂 | 多跳推理、条件判断 | 子问题拆错 |
| HyDE | Query 和 Doc 语义不匹配 | 文档像答案,问题较抽象 | 假想答案幻觉 |
| Step-Back | 具体问题缺少背景规则 | 原理、政策、法律类问题 | 抽象过度 |
工程落地时,不应该所有问题都套一遍全流程,否则成本和延迟会很高。比较合理的方式是先做 Query Classification,根据问题类型选择策略:
text
短问题 / 口语问题 → Query Rewrite
泛问题 / 召回不足 → Multi-Query
复杂问题 / 多条件问题 → Decomposition
语义不匹配问题 → HyDE
需要背景规则的问题 → Step-Back
改写后还必须配合 Rerank、去重、上下文过滤和置信度判断。否则召回了一堆内容,真正有用的片段被淹没,LLM 反而会被无关上下文干扰。
评估 Query 改写时,也不能只看"改写得像不像人话"。重点要看 Recall、Context Recall、Context Precision、Faithfulness、Answer Correctness、Latency 和 Cost。最好通过 A/B Testing 验证。
面试时可以这样回答:
RAG 中做 Query 改写,核心是为了解决用户问题和知识库文档之间的语义鸿沟。用户的提问往往口语化、短、不完整,甚至带有上下文省略,而知识库文档通常是规范化、正式化的表达。直接拿原始 Query 去检索,可能导致召回不足或召回偏差。常见策略有五类:第一是 Query Rewrite,把口语化问题改写成规范检索语句;第二是 Multi-Query,从多个角度生成多个查询,提升召回覆盖率;第三是 Decomposition,把复杂问题拆成多个子问题分别检索;第四是 HyDE,先生成假想答案,再用假想答案做向量检索,缓解 Query 和 Doc 语义空间不匹配;第五是 Step-Back,把具体问题抽象成更高层的原则问题,先检索背景规则,再回到原问题推理。工程上不会对所有问题都套用同一策略,而是先做 Query Classification,根据问题类型选择改写方式。并且改写后要做相似度校验,防止改写偏题;多路召回后还要配合 Rerank 和去重,避免噪声增加。最终要通过 Recall、Context Recall、Faithfulness、Answer Correctness、延迟和成本做综合评估。
十一、Agent 调用 Python 代码解释器报错了怎么办?
这是一道典型的 Agent 工程题。它不是在问你会不会看 Python 报错,而是在考察你是否理解 Agent 调用工具后的异常处理机制:错误信息如何回传给 LLM,LLM 如何基于错误反思和修正,系统如何防止死循环、幻觉修复和上下文爆炸。
一个比较清晰的链路是:
text
Agent / LLM
↓
Code Executor
↓
Error Handler
↓
Observation 回传给 Agent
↓
Agent 反思并修正
Agent 负责思考、生成代码、决定下一步;Code Executor 在 Python 沙箱环境中执行代码;Error Handler 捕获异常、截断日志、封装 Observation;Observation 把执行结果或错误信息反馈给 Agent;Agent 再根据反馈进行 Reflection 和修复。
这里第一个常见问题是 上下文爆炸。代码执行失败后,可能产生几百行 Traceback。如果直接把完整报错塞回大模型,会占满上下文、浪费 Token、干扰模型判断,甚至覆盖原始任务目标。所以 Error Handler 应该只提取关键部分,比如 Exception Type、Error Message、出错文件名、出错行号、Traceback 最后 3-5 行和相关代码片段。必要时可以先用小模型对错误做摘要。
例如原始错误是:
text
Traceback ...
File "main.py", line 12, in <module>
NameError: name 'pd' is not defined
可以结构化成:
json
{
"status": "error",
"error_type": "NameError",
"message": "name 'pd' is not defined",
"file": "main.py",
"line": 12,
"hint": "可能缺少 import pandas as pd"
}
第二个问题是 死循环陷阱。Agent 可能一直重复提交同一段错误代码。比如第一次是 NameError,第二次还是 NameError,第三次还是 NameError。如果没有控制机制,任务会卡死,成本不断增加。所以需要设置 Max Retries,比如最多 3 次,并记录每次失败原因。如果连续两次错误类型和出错行相同,说明模型没有真正修复,就要触发熔断,切换修复 Prompt 或进入 fallback。
第三个问题是 幻觉修复 。模型为了修 Bug,可能编造不存在的库、函数或 API,比如 import magic_data_cleaner 或 df.auto_fix_all_errors()。解决方式是加入 RAG 增强和 Linter 检查。如果错误来自 pandas、numpy、torch、sklearn、transformers、langchain 等真实库,可以自动检索官方文档或本地知识库,把真实 API 用法返回给 Agent。执行前也可以使用 ruff、pylint、mypy、flake8、AST parser 做语法检查、未定义变量检查、import 检查、简单类型检查和危险操作检查。
一个完整的 Error Handler 可以这样设计:
text
Code Executor 执行失败
↓
Error Handler 捕获异常
↓
错误清洗、截断、结构化
↓
判断是否可重试
↓
必要时补充文档/RAG/Linter 结果
↓
生成 Observation
↓
返回给 Agent
Observation 不应该是一大坨报错,而应该是结构化信息:
json
{
"status": "error",
"error_type": "ImportError",
"message": "No module named 'xgboost'",
"traceback_tail": "...",
"retry_count": 1,
"is_same_error_as_last_time": false,
"suggested_action": "检查依赖是否可用,或改用 sklearn 替代方案"
}
工程上还要加一些防护,比如限制文件访问、网络访问、执行时间、内存占用,禁止危险命令;记录错误历史;把所有错误和修复结果进入 Bad Case 日志,后续优化 Prompt、工具描述、测试用例和知识库。
面试时可以这样回答:
我会把它当成一个 Agent 工具调用失败后的闭环修复问题,而不是简单让模型继续猜。首先,Code Executor 执行失败后,Error Handler 会捕获异常,把完整 Traceback 做截断和结构化,只保留错误类型、错误信息、出错行号和最后几行关键栈信息,避免上下文爆炸。第二,我会把这些信息封装成 Observation 返回给 Agent,让模型基于明确的错误反馈进行 Reflection 和代码修正。第三,我会设置最大重试次数,比如 3 次,并记录每次错误。如果连续出现相同错误,就触发熔断,切换修复 Prompt 或 fallback,避免死循环。第四,为了防止幻觉修复,我会在执行前加入 Linter 或静态检查;如果是库 API 使用错误,则通过 RAG 检索官方文档或项目内部文档,把真实 API 用法补充给 Agent。最后,所有错误和修复结果都要进入 Bad Case 日志,后续用于优化 Prompt、工具描述、测试用例和知识库。所以核心不是"报错了再问一次模型",而是构建 Code Executor、Error Handler、Observation、Reflection、Retry 和 RAG/Linter 组成的闭环。
十二、RAG、MCP 和 Agent 分别解决什么问题?
这道题不是单独问概念,而是在看你能不能把 RAG、MCP 和 Agent 放到一个完整的大模型工程架构里理解。
最简单的分工是:
text
RAG:补知识
MCP:接工具
Agent:做决策和执行
RAG,也就是 Retrieval-Augmented Generation,解决的是知识问题。大模型参数里的知识可能过时,也不知道企业内部文档,还容易凭记忆胡编。RAG 的作用是让模型回答前先检索外部知识库,把相关文档片段作为上下文交给模型生成答案。因此,RAG 不是让模型"记住知识",而是让模型"临时查资料后再回答"。
MCP,也就是 Model Context Protocol,解决的是连接问题。它用一套标准协议,把外部工具、数据源、文件系统、数据库、API 等能力暴露给模型或 Agent 使用。如果没有 MCP,每个模型和每个工具都要单独适配,就会出现 N 个模型 × M 个工具的适配复杂度。MCP 通过 Resources、Tools、Prompts、Auth 等机制,把外部能力标准化。可以把它类比成大模型时代的 USB-C 接口,或者类似 JDBC/HTTP Client 的标准层。
Agent 解决的是复杂任务执行问题。它以 LLM 为核心大脑,能够理解目标、拆解任务、选择工具、调用工具、观察结果、反思修正,并持续执行直到完成任务。RAG 只是查知识,MCP 只是提供工具接口,但 Agent 负责决定怎么干。
三者的区别可以这样看:
| 模块 | 核心问题 | 类比 | 典型能力 |
|---|---|---|---|
| RAG | 知识不够怎么办 | 外挂资料库 | 检索文档、补充上下文、减少幻觉 |
| MCP | 工具怎么接入 | 标准接口/插座 | 连接数据库、API、文件、搜索、代码工具 |
| Agent | 复杂任务怎么执行 | 大脑/指挥官 | 任务规划、工具调用、状态管理、反思修正 |
在完整架构里,它们通常是这样协同的:
text
用户需求
↓
Agent 负责理解任务、规划流程
↓
通过 MCP 调用标准化工具
↓
需要知识时调用 RAG 检索知识库
↓
需要操作时调用外部工具/API/代码执行器
↓
Agent 汇总结果、反思修正、输出答案
比如企业知识库助手里,用户让系统分析某个客户的合同风险。Agent 先判断这是合同分析任务,然后通过 MCP 读取合同文件,通过 RAG 检索公司法务知识库和历史案例,再调用合同条款解析工具和风险评分 API,最后汇总风险点生成结构化报告。如果置信度低,还可以触发人工复核。
工程落地时也要注意风险。Agent 太自由,容易死循环、上下文膨胀、错误级联或执行高风险操作,所以需要状态机、工作流、最大步数、最大重试次数、Human-in-the-loop 和执行日志。MCP 把工具暴露出来后,会带来权限和安全风险,所以要做 RBAC、最小权限、工具白名单、参数校验、调用审计、远程调用降级。RAG 则要解决查不准、排不准、答不准的问题,需要语义分块、Query Rewrite、混合检索、Rerank、知识图谱增强、Faithfulness 和 Context Recall 评估。
面试时可以这样回答:
我理解这三者在大模型工程里分别解决不同层的问题。RAG 主要解决知识问题,也就是模型不知道、知识过时或企业私有知识无法直接内化到参数里的问题。它通过检索外部知识库,把相关上下文提供给模型,降低幻觉并增强事实依据。MCP 主要解决连接问题,也就是模型和外部工具、数据源、API、文件系统之间如何标准化通信的问题。它把 Resources、Tools、Prompts 和权限控制封装成统一协议,降低多模型、多工具之间的适配成本。Agent 主要解决复杂任务执行问题。它以 LLM 为大脑,负责任务拆解、流程编排、工具选择、状态管理、错误恢复和人机协同。在完整架构里,Agent 负责规划和调度,MCP 负责把工具和数据源标准化暴露出来,RAG 通常作为一种知识检索能力被 Agent 调用。比如企业知识库助手中,Agent 先理解用户任务,再通过 MCP 调用搜索、数据库、文件系统等工具,需要事实依据时调用 RAG 检索知识库,最后综合结果生成答案。所以三者不是互相替代关系,而是协作关系:RAG 补知识,MCP 接工具,Agent 做决策和执行。
十三、Agent 运行久了,记忆撑爆了怎么办?
Agent 长任务记忆管理,本质上是在解决一个问题:Context Window 是有限资源,不能把所有历史都塞进去。
Agent 和普通对话不同,它会不断执行 Thought、Action、Observation、Reflection。如果每一步都完整保留,Token 很快就会爆炸,成本升高,模型注意力被旧信息稀释,早期错误结论还可能污染后续判断,最终导致任务漂移。
比较成熟的做法是使用混合记忆架构:
text
滑动窗口 + 摘要压缩 + 向量检索 + 知识图谱
第一层是 滑动窗口,也就是短期记忆。它只保留最近 N 轮对话、最近几次工具调用结果、当前任务状态和当前错误信息。旧内容不直接丢弃,而是进入摘要或长期记忆。这样可以保证模型关注最近发生的事情,同时避免 Token 溢出。
第二层是 递归摘要,也就是中期记忆。当任务步骤太长时,不能无限保留原文,就把旧上下文压缩成摘要。比如原始历史有 1000 字,可以压缩成"已定位性能问题集中在 UserRepository 与 CacheManager 的缓存失效逻辑,下一步检查缓存更新条件"。摘要保留关键结论、决策和下一步计划,但也可能丢失细节,所以最好把摘要和原始记录一起存入长期记忆,需要时再检索回原文。
第三层是 向量数据库,也就是长期记忆。长期历史、项目文档、工具调用记录、用户偏好、历史 Bad Case、代码分析结论、任务执行日志,都不应该长期塞在上下文里,而应该存起来。当用户提出新问题时,用 embedding 检索和当前任务最相关的片段,再动态放回 Prompt。
第四层是 知识图谱或结构化状态。向量检索适合找语义相近的文本,但不擅长处理实体关系和任务状态。比如用户偏好、项目状态、模块依赖、Bug 关联文件、任务下一步,这些更适合用结构化状态或知识图谱保存。示例:
json
{
"memory": "问题可能在 CacheManager",
"source": "agent_inference",
"confidence": 0.6,
"verified": false,
"status": "hypothesis"
}
这里还有一个关键点:不要把假设当事实。Agent 早期可能产生错误判断,如果错误判断被长期保存,后面就会一直被误导。所以每条记忆最好记录来源、置信度、是否验证、是否被推翻、是否仍然有效。
真正推理前,Agent 的上下文应该动态拼装,而不是固定堆历史。优先级可以是:
text
1. System Prompt:固定规则和安全边界
2. 当前用户输入:当前任务
3. 当前任务状态:目标、进度、下一步
4. 最近 N 轮对话:滑动窗口
5. 上阶段摘要:压缩后的中期记忆
6. 向量库检索结果:相关长期记忆
7. 知识图谱结果:实体关系和任务状态
8. 工具返回结果:必要 Observation
可以把核心策略记成三个词:
text
Fresh:最近信息保鲜
Precise:长期记忆精准检索
Compress:历史信息压缩摘要
此外,任务状态要单独维护。长任务最容易丢的不是所有历史细节,而是"当前做到哪了"。所以要记录任务目标、已完成步骤、当前阻塞点、关键发现、下一步计划、已调用工具、失败原因。这部分比完整对话历史更重要。
面试时可以这样回答:
我会用混合记忆架构来解决,而不是把所有历史都塞进 Context Window。首先,短期记忆用滑动窗口,只保留最近 N 轮对话、关键工具调用结果和当前任务状态,保证上下文鲜活。第二,中期记忆用递归摘要,把已经完成的阶段性过程压缩成摘要,保留关键结论、决策和下一步计划,减少 Token 占用。第三,长期记忆放到向量数据库里,通过 embedding 检索按需取回相关历史,而不是全量加载。第四,对于用户画像、任务状态、实体关系和项目依赖这类结构化信息,可以放到知识图谱或结构化状态存储里。最后,在每次调用大模型前动态组装上下文:System Prompt、当前问题、任务状态、最近窗口、阶段摘要、向量检索结果和必要工具 Observation。这样既能防止上下文爆炸,又能保证 Agent 长任务不断片。
十四、把这些内容放到一个完整大模型工程体系里
如果把上面内容串起来,可以得到一个完整的大模型应用工程视角。
大模型底层是 Transformer + Next-Token Prediction,是一个高维条件概率分布模型。它通过预训练学习通用能力,但不是数据库,也不是可靠执行器。
如果需要让模型适配某个业务场景,可以做微调。SFT 让模型学会听指令,RLHF / DPO 让模型符合人类偏好,LoRA / QLoRA 降低训练成本和显存压力。但微调主要解决行为模式、输出规范和任务适配,不应该把所有事实知识都硬塞进参数里。
如果需要外部事实、企业文档、实时知识,就要用 RAG。RAG 的重点不只是"向量库 + Embedding + 大模型",而是包括文档切分、Query 改写、混合检索、Rerank、上下文过滤、Faithfulness 评估和业务闭环。
如果需要连接外部工具、文件、数据库和 API,就需要 MCP 或类似协议来做标准化接入。MCP 的价值是降低多模型、多工具之间的适配成本,但同时要关注权限、安全、审计和延迟。
如果要完成复杂任务,就需要 Agent。Agent 是大脑和指挥官,负责任务拆解、工具选择、状态管理、错误恢复、人机协同和持续执行。但 Agent 不能完全放任自治,需要工作流、状态机、最大步数、重试机制、Human-in-the-loop、错误处理和记忆管理。
最终,一个成熟的大模型应用不是单点能力,而是一个系统:
text
用户需求
↓
Agent 理解目标并拆解任务
↓
通过 MCP 接入工具、数据库、文件和 API
↓
通过 RAG 检索外部知识
↓
调用工具执行动作
↓
Error Handler 处理失败
↓
Memory 管理长任务上下文
↓
Evaluation 评估回答质量和业务效果
↓
Bad Case 反哺 Prompt、RAG、微调和工具描述
最终可以用一句话收束:
大模型工程的关键,不是让模型"自己什么都会",而是把模型放进一个由数据、知识库、工具协议、任务编排、记忆系统、评估闭环组成的工程体系里,让它在边界清晰、反馈明确、结果可控的环境中发挥能力。