🏆 AI Agent & RAG 综合面试题库:21 道大厂高频真题速查与通关解析

随着大模型应用落地,AI Agent 和 RAG 已经成为算法工程师和后端开发面试的“必考核心”。

这篇博客为你汇总了 21 道最高频、最核心的面试真题,涵盖了从 RAG 基础、进阶检索、Agent 框架到底层工程优化的方方面面。为了对入门者友好,每道题都配有标准答案大白话解析,最后还附带了一段大厂面试极爱考的综合架构白板代码

建议直接收藏,面试前一天反复背诵!


📚 第一部分:RAG 基础与架构篇 (Q1 - Q6)

Q1:什么是 RAG?请用一句话解释。

标准答案:RAG(检索增强生成)是指在让大语言模型生成答案前,先从外部知识库检索相关证据,并将证据作为上下文一并输入给模型,从而约束输出依据、减少幻觉的范式。
💡 大白话:给大模型一场“开卷考试”,遇到不会的先去翻书找证据,再根据证据作答。

Q2:RAG 和 微调(Fine-tuning)在业务落地上该怎么选?

标准答案:需要注入“实时变化的外部事实知识”时选 RAG(成本低、更新快);需要改变模型的“说话语气、输出格式、特定指令遵循”时选微调。在真实工业界,通常是“RAG 提供事实 + 微调规范格式”两者结合。

Q3:现在大模型都支持 100万 Token 的长上下文了,RAG 还会被淘汰吗?

标准答案:不会。长上下文模型存在三大硬伤:1. 成本极高(每次提问都要为几百页文档的 Token 付费);2. 延迟极大(TTFT首字响应时间可能长达几十秒);3. 注意力迷失(中间遗忘现象,Lost in the middle)。RAG 在成本控制、低延迟和精准度上仍是不可替代的。

Q4:为什么文档分块(Chunking)不能切得太大,也不能切得太碎?

标准答案:切得太碎(如 50 个字),会导致语义断裂,检索到的片段缺少主语或前置条件;切得太大(如 3000 个字),会混入大量无关噪声,模糊向量特征,且浪费大模型 Token。

Q5:业界常用的父子文档分块(Parent-Child Chunking)是为了解决什么问题?

标准答案:解决“检索精度”与“生成上下文完整性”的矛盾。用小块(子文档)去做向量化和检索,命中后,顺藤摸瓜提取出包含它的大块(父文档)喂给大模型。

Q6:向量数据库和传统关系型数据库(如 MySQL)的本质区别是什么?

标准答案:传统数据库基于“字面的精确匹配(B+树索引等)”;向量数据库基于“高维向量空间的相似度计算(ANN 近似最近邻算法)”,专门用于模糊查询和语义匹配。


🔍 第二部分:RAG 进阶与检索策略篇 (Q7 - Q11)

Q7:纯向量检索有什么致命缺点?怎么解决?

标准答案:纯向量检索擅长“懂意思”,但不擅长“精确匹配”,对专有名词、型号、商品编号极容易漏召回。
解决方案:引入 BM25 算法进行关键词匹配,采用混合检索(Hybrid Search)

Q8:在多路召回(混合检索)中,RRF(倒数排名融合)有什么优势?

标准答案:向量打分(如余弦相似度 0.8)和 BM25 打分(如 35.5)量纲完全不同,无法直接相加。RRF 只看排名不看分数,通过倒数公式把各路排名融合,鲁棒性极高且无需繁琐调参。

Q9:什么是 HyDE(假设文档嵌入)策略?

标准答案:面对用户口语化的简短提问,先让大模型“裸考”生成一个假想答案。虽然假想答案可能有事实错误,但它的句式和词汇更接近真实文档。拿着假想答案去向量库检索,能极大拉近语义距离。

Q10:在 RAG 流程中,为什么一定要加重排序(Reranking)?

标准答案:基础的双塔向量检索(Bi-Encoder)速度快但精度低(Query 和 Doc 没做特征交互)。重排序使用交叉编码器(Cross-Encoder),将 Query 和 Doc 拼接在一起深度打分,能将召回的粗糙候选集精准排序,大幅提升最终 Top-3 的准确度。

Q11:遇到表格和图片,RAG 该怎么处理?

标准答案

  • 表格:尽量保留为 Markdown/HTML 格式防止行列关系碎裂;或者把表格单独存入结构化数据库(Text-to-SQL)。
  • 图片:使用多模态大模型(VLM)进行看图说话,生成图像描述(Caption)后再存入向量库。

🤖 第三部分:AI Agent 核心框架篇 (Q12 - Q16)

Q12:Agent 和传统的代码脚本有什么区别?

标准答案:传统脚本是由人类写好 if-else 的静态控制流;而 Agent 的核心控制流(下一步该调用什么工具、怎么处理结果)是交由大模型实时推理决策的

Q13:请简述 ReAct 框架的核心执行流。

标准答案Thought (思考) →\rightarrow Action (行动) →\rightarrow Observation (观察)。模型先分析当前状况,决定调用外部工具,工具返回真实结果,模型基于真实结果再进行下一轮思考,直到得出最终答案。

Q14:LangChain 的 AgentExecutor 为什么要设置最大迭代次数(max_iterations)?

标准答案:大模型有时会陷入“死胡同”,不断地使用错误的参数重复调用同一个工具,导致无限死循环。设置最大迭代次数是防止 API Token 费用爆表和系统宕机的最后一道物理防线。

Q15:Plan-and-Execute 框架比 ReAct 好在哪里?

标准答案:ReAct 是“走一步看一步”的贪心策略,遇到复杂长链条任务容易中途迷失。Plan-and-Execute 强制要求模型先画出全局多步任务蓝图,再挨个执行,适合耗时较长的复杂工作流(如撰写深度研报)。

Q16:在配置 Agent 工具时,为什么说“工具的描述(Description)就是接口”?

标准答案:因为大模型完全是通过阅读这段自然语言描述,来判断“我该不该用这个工具”以及“这个参数该传什么”的。描述写得越清晰、包含的 Few-shot 示例越多,Agent 调用的成功率就越高。


🛠️ 第四部分:生产环境与工程优化篇 (Q17 - Q21)

Q17:真实业务中 RAG 的延迟(首字响应时间)太高,怎么优化?

标准答案

  1. 开启 Streaming 流式输出,先返回参考文献安抚用户。
  2. 引入 语义缓存(Semantic Cache),极度相似的历史问题直接返回,耗时降至毫秒级。
  3. 精简传给大模型的 Prompt 长度,删减冗余的上下文块。

Q18:如何评估你的 RAG 系统准不准?(如何做无参考评估)

标准答案:使用 LLM-as-a-Judge(大模型作为裁判),围绕 RAG 三元组 打分:

  1. 检索相关性(捞出来的资料对不对)。
  2. 忠实度(大模型有没有脱离资料胡编乱造,防幻觉)。
  3. 回答相关性(最终答案有没有切中用户的核心诉求)。

Q19:业务知识库每天都在变,如何保证 RAG 数据的实时性?

标准答案:放弃全量更新,走事件驱动的异步流。业务端一有修改,立刻触发 Webhook,只对那篇被修改的文档进行重新解析和切块,并利用 doc_id 对向量数据库执行 UPSERT(更新插入)或软删除。

Q20:LangGraph 相比于 LangChain 解决的业务痛点是什么?

标准答案:LangChain 的 Agent 控制流是相对黑盒的循环。LangGraph 引入了**状态机(State Machine)**和图编排的概念,让我们可以显式地定义节点、条件路由(Conditional Edge)、加入人工审核(Human-in-the-loop)以及设计复杂的失败重试环路,更适合企业级复杂 SOP 流水线。

Q21:多 Agent 系统(Multi-Agent,如 AutoGen/CrewAI)一定会比单 Agent 好吗?

标准答案不一定。多 Agent 会带来极高的 Token 交互成本和对话协调时间。只有当任务极度复杂、需要清晰的角色分工(如:一个负责写代码,一个独立负责检查挑错)时,多 Agent 的“对抗互补”机制才有明显收益。如果是直来直去的任务,加了强工具的单 Agent 反而更高效。


在这里插入图片描述

💻 终极加分项:手写“路由 + 缓存 + RAG”综合架构代码

面试官最爱考白板设计!下面这段伪代码融合了语义路由、语义缓存、混合检索三大生产级优化点,你能写出这段骨架,面试官直接发 Offer:

import numpy as np

# ==========================================
# 模拟核心组件:大模型、缓存、检索器
# ==========================================
class MockLLM:
    def encode(self, text):
        # 模拟 Embedding 向量化
        return np.random.rand(512) 
        
    def generate(self, prompt):
        return "模拟生成的大模型答案"

class MockVectorDB:
    def search(self, query_vec):
        return ["向量检索文档 A", "向量检索文档 B"]

class MockBM25:
    def search(self, query_text):
        return ["关键词检索文档 B", "关键词检索文档 C"]

# ==========================================
# 生产级 RAG 问答管线 (Pipeline)
# ==========================================
class EnterpriseQA_Pipeline:
    def __init__(self):
        self.llm = MockLLM()
        self.v_db = MockVectorDB()
        self.bm25 = MockBM25()
        self.semantic_cache = {} # 模拟缓存 {query_text: answer}

    def _cosine_similarity(self, v1, v2):
        # 计算余弦相似度
        return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2) + 1e-8)

    def ask(self, user_query: str) -> str:
        print(f"\n[请求到达] -> {user_query}")
        
        # -------------------------------------------
        # 1. 拦截层:语义缓存 (Semantic Cache)
        # -------------------------------------------
        query_vec = self.llm.encode(user_query)
        for cached_query, cached_data in self.semantic_cache.items():
            sim = self._cosine_similarity(query_vec, cached_data['vec'])
            if sim > 0.95:  # 相似度极高,视为同一个问题
                print("✅ 命中语义缓存!0ms 极速返回!")
                return cached_data['answer']

        # -------------------------------------------
        # 2. 路由层:意图分发 (Query Routing)
        # -------------------------------------------
        # 真实场景中可用小模型或基于规则进行分类
        if "天气" in user_query or "时间" in user_query:
            print("🔀 路由命中:这是一个实时问题,调用【联网搜索 Agent】")
            answer = "调用外部天气 API 获得结果..."
            self._save_to_cache(user_query, query_vec, answer)
            return answer

        # -------------------------------------------
        # 3. 检索层:混合检索 (Hybrid Search + RRF 融合)
        # -------------------------------------------
        print("🔀 路由命中:需要查阅内部知识库,进入 RAG 流程...")
        vec_docs = self.v_db.search(query_vec)
        bm25_docs = self.bm25.search(user_query)
        
        # 模拟 RRF 或简单的去重融合
        fused_docs = list(set(vec_docs + bm25_docs))
        print(f"🔍 混合检索完毕,召回上下文:{fused_docs}")

        # -------------------------------------------
        # 4. 生成层:防幻觉 Prompt 构建
        # -------------------------------------------
        prompt = f"""
        请严格根据以下上下文回答问题。如果上下文中没有答案,请明确回答"我不知道"。
        上下文:{fused_docs}
        用户提问:{user_query}
        """
        answer = self.llm.generate(prompt)
        print("🧠 大模型生成完毕。")

        # 5. 写入缓存,造福下一次请求
        self._save_to_cache(user_query, query_vec, answer)
        return answer

    def _save_to_cache(self, query, vec, answer):
        self.semantic_cache[query] = {'vec': vec, 'answer': answer}

# ==========================================
# 测试运行
# ==========================================
if __name__ == "__main__":
    pipeline = EnterpriseQA_Pipeline()
    
    # 第一次提问:走完整的 RAG 流程
    pipeline.ask("公司年假怎么休?")
    
    # 第二次提问:意思极度相似,会直接命中缓存
    pipeline.ask("年假如何申请?")
    
    # 第三次提问:路由分发到外部 API
    pipeline.ask("北京今天天气怎么样?")
Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐