📖 AI Agent与RAG面试专题¶
⚠️ 时效性说明:本章涉及前沿模型/价格/榜单等信息,可能随版本快速变化;请以论文原文、官方发布页和 API 文档为准。
重要性:⭐⭐⭐⭐⭐(2025-2028 AI岗位面试最热门方向) 难度:⭐⭐⭐⭐ 学习时间:2-3天 前置知识:LLM基础、Prompt工程、向量数据库
📚 目录¶
Part A:AI Agent面试题¶
Q1:什么是AI Agent?它与传统Chatbot的本质区别是什么?¶
参考答案:
AI Agent是具备感知-规划-行动-反思闭环能力的智能系统,核心区别:
| 维度 | Chatbot | AI Agent |
|---|---|---|
| 交互模式 | 单轮/多轮对话 | 自主规划+多步执行 |
| 工具使用 | 无 | 可调用API/数据库/代码执行器 |
| 记忆 | 上下文窗口内 | 短期+长期记忆系统 |
| 决策 | 被动响应 | 主动分解任务、自主决策 |
| 反思 | 无 | 可自我评估、纠错、迭代 |
Agent核心组件:
追问:Agent的"幻觉"和Chatbot的"幻觉"有什么不同? → Agent幻觉更危险:会导致错误的工具调用、错误的代码执行等实际行为后果
Q2:解释ReAct框架的工作原理及其优势¶
参考答案:
ReAct = Reasoning + Acting,交替进行推理和行动:
循环:
1. Thought(推理): 分析当前状态,决定下一步
2. Action(行动): 调用工具/API执行操作
3. Observation(观察): 获取工具返回结果
4. 重复直到完成任务
# ReAct伪代码
def react_agent(query, tools, llm):
history = []
for step in range(max_steps):
# Thought: LLM推理
thought = llm.generate(f"Query: {query}\nHistory: {history}\nThought:")
# Action: 选择并执行工具
action = llm.generate(f"...Action:")
tool_name, tool_input = parse_action(action)
# Observation: 获取结果
observation = tools[tool_name].run(tool_input)
history.append((thought, action, observation))
if is_final_answer(thought):
return extract_answer(thought)
优势: - 可解释性:每步推理可见 - 纠错能力:观察结果后可调整策略 - 通用性:适用于各种工具组合
追问:ReAct的缺点是什么?如何改进? → 缺点:推理链过长、token消耗大、容易陷入循环。改进:Reflexion(加反思)、LATS(树搜索)、Plan-and-Execute(先规划再执行)
Q3:如何设计Agent的工具调用(Tool Use)系统?¶
参考答案:
工具调用系统设计要点:
1. 工具描述标准化:
{
"name": "search_database",
"description": "搜索产品数据库,返回匹配的产品列表",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "搜索关键词"},
"category": {"type": "string", "enum": ["电子", "服装", "食品"]},
"max_results": {"type": "integer", "default": 10}
},
"required": ["query"]
}
}
2. 工具选择策略: - 静态选择:预定义工具集 - 动态选择:根据query检索相关工具(工具多时必须) - 分层选择:先选类别再选具体工具
3. 安全机制: - 权限控制(只读/读写/管理员) - 参数验证(防注入) - 调用频率限制 - 人工确认高风险操作
4. 错误处理:
def safe_tool_call(tool, params, max_retries=3):
for attempt in range(max_retries):
try: # try/except捕获异常
result = tool.execute(params)
if validate_result(result):
return result
# 结果无效,让LLM修正参数
params = llm_fix_params(tool, params, result)
except ToolError as e:
if attempt == max_retries - 1:
return f"工具调用失败: {e}"
params = llm_handle_error(tool, params, e)
追问:MCP协议如何解决工具互操作性问题? → MCP定义标准化的Tool/Resource/Prompt接口,让不同Agent框架都能使用同一套工具,类似USB的通用连接标准
Q4:LangGraph与CrewAI的设计哲学差异?¶
参考答案:
| 维度 | LangGraph | CrewAI |
|---|---|---|
| 核心抽象 | 图(Graph) — 状态机 | 角色(Crew) — 团队协作 |
| 流程控制 | 显式定义Node/Edge/条件路由 | 声明式Task→Agent映射 |
| 状态管理 | 强 — 内置State + Checkpoint | 弱 — 依赖上下文传递 |
| 适用场景 | 复杂工作流/需持久化/需人工审批 | 快速搭建多角色协作 |
| 灵活性 | 极高(可定义任意图拓扑) | 中等(线性/层级流程) |
| 学习曲线 | 陡峭 | 平缓 |
| 生产就绪 | 高(LangSmith集成/断点恢复) | 中等 |
选型建议: - LangGraph:需要复杂分支/循环/人机交互/持久化的生产系统 - CrewAI:快速原型/多角色模拟/简单任务编排 - AutoGen:学术研究/对话式多Agent
追问:如果让你选一个框架做生产系统,选什么?为什么?
Q5:MCP协议的设计理念和架构是什么?¶
参考答案:
MCP (Model Context Protocol) 由Anthropic提出,是AI模型与外部工具/数据的标准通信协议。
核心设计理念:将工具集成从N×M问题简化为N+M问题 - 之前:N个Agent框架 × M个工具 = N×M种集成 - 之后:N个Client + M个Server = N+M种实现
架构:
┌─────────────┐ ┌─────────────┐
│ MCP Client │ │ MCP Server │
│ (Agent/IDE) │←───→│ (Tool/Data) │
│ │JSON │ │
│ - Claude │RPC │ - GitHub │
│ - Cursor │ │ - DB │
│ - Custom │ │ - API │
└─────────────┘ └─────────────┘
三大能力: 1. Tools: Server暴露可调用的函数(如search/create/delete) 2. Resources: Server暴露可读取的数据(如文件/数据库记录) 3. Prompts: Server提供预设的Prompt模板
传输层:stdio(本地)/ SSE(远程)/ HTTP
追问:MCP与Function Calling有什么区别? → Function Calling是LLM API级别的工具调用格式;MCP是应用级别的工具互操作协议。MCP建立在Function Calling之上,解决的是工具标准化和跨框架复用问题。
Q6:如何处理Agent的幻觉和错误循环?¶
参考答案:
幻觉类型: 1. 工具幻觉:调用不存在的工具/参数 2. 结果幻觉:编造工具返回结果 3. 推理幻觉:错误的逻辑推理链 4. 循环幻觉:重复相同操作不收敛
解决策略:
class AgentGuardrails:
def __init__(self, max_steps=15, max_retries=3):
self.max_steps = max_steps
self.max_retries = max_retries
self.action_history = []
def check_loop(self, action):
"""检测重复动作循环"""
recent = self.action_history[-5:]
if recent.count(action) >= 3:
return True # 循环检测
return False
def validate_tool_call(self, tool_name, params, available_tools):
"""验证工具调用合法性"""
if tool_name not in available_tools:
return False, f"工具{tool_name}不存在,可用: {list(available_tools.keys())}"
schema = available_tools[tool_name].schema
return validate_params(params, schema)
def force_reflection(self, agent, history):
"""强制反思(每N步或出错时)"""
prompt = f"回顾执行历史,评估进展:\n{history}\n\n你是否在正确的方向上?是否需要改变策略?"
return agent.llm.generate(prompt)
最佳实践: 1. 限制最大步数(防止无限循环) 2. 工具白名单+参数校验(防止幻觉调用) 3. 周期性强制反思(每3-5步) 4. 观察值验证(工具结果后置检查) 5. 人类兜底(关键决策人工确认)
Q7:多Agent系统的通信和协调策略有哪些?¶
参考答案:
通信模式: 1. 中心化:Orchestrator统一调度,各Agent只与中心通信 2. 去中心化:Agent之间直接P2P通信 3. 广播式:消息发送到共享空间,所有Agent可见 4. 层级式:Manager → Team Lead → Worker 分层管理
协调策略: | 策略 | 描述 | 适用场景 | |------|------|----------| | 顺序传递 | A→B→C,链式处理 | 流水线任务 | | 分派聚合 | Master分派子任务→Worker并行→汇总 | 大规模数据处理 | | 辩论共识 | 多Agent讨论→投票/共识 | 需要多视角决策 | | 竞争选优 | 多Agent独立完成→选最优结果 | 创意生成 | | 反馈循环 | Writer→Reviewer→Writer迭代 | 内容生产 |
追问:A2A协议和MCP的关系? → MCP解决Agent↔Tool通信;A2A (Agent-to-Agent) 解决Agent↔Agent通信,两者互补
Q8:Agent的安全性如何保证?¶
参考答案:
安全威胁矩阵: | 威胁 | 描述 | 防御 | |------|------|------| | Prompt注入 | 用户输入覆盖系统指令 | 输入清洗/指令隔离 | | 工具滥用 | Agent被诱导执行危险操作 | 权限最小化/审批流程 | | 数据泄露 | Agent暴露敏感信息 | 输出过滤/数据脱敏 | | 供应链攻击 | 恶意MCP Server | Server认证/沙箱隔离 | | 资源耗尽 | 无限循环消耗Token/API | 预算限制/超时机制 |
核心安全架构:
关键实践:权限最小化、沙箱执行、操作审计日志、敏感操作人工确认
Q9:如何评估Agent的性能?¶
参考答案:
评估维度: | 维度 | 指标 | 测量方式 | |------|------|----------| | 任务完成率 | 成功完成/总尝试 | 自动化测试集 | | 步骤效率 | 平均步数/成功步数比 | 日志分析 | | 工具使用准确率 | 正确调用/总调用 | 日志分析 | | 推理质量 | 推理链逻辑正确 | 人工评估/LLM-as-Judge | | 端到端延迟 | 从输入到最终输出 | 时间戳 | | 成本效率 | Token消耗/成功任务 | 计费API | | 鲁棒性 | 对抗样本表现 | 红队测试 |
常用评估基准: - SWE-Bench:代码Agent,在真实GitHub Issue上测试 - WebArena:Web操作Agent - AgentBench:综合Agent评测 - HumanEval+:代码生成+执行Agent - GAIA:通用AI助手评测
追问:LLM-as-Judge评估Agent有什么局限? → 评判LLM自身能力上限、成本高、对长推理链评估不可靠、需要结合rule-based指标
Q10:设计一个企业级AI Agent系统(系统设计题)¶
设计要求:为一家电商公司设计智能客服Agent系统,日均10万询问。
参考答案(简要框架):
┌─────────────┐
│ API Gateway│
│ (限流/认证) │
└──────┬──────┘
│
┌──────▼──────┐
│ Router Agent│
│ (意图识别) │
└──────┬──────┘
┌────────────┼────────────┐
┌─────▼─────┐ ┌───▼────┐ ┌─────▼─────┐
│ FAQ Agent │ │Order │ │Complaint │
│(RAG检索) │ │Agent │ │Agent │
└───────────┘ │(API调用)│ │(工单系统) │
└────────┘ └───────────┘
关键设计点: 1. 分层路由:先意图分类,再分发到专业Agent 2. RAG知识库:商品/政策FAQ + 历史工单 → 混合检索 3. 工具集成:订单系统/物流API/退款API/工单系统 4. 人工兜底:置信度<0.7 或 敏感操作自动转人工 5. 缓存策略:高频问题LRU缓存 + 语义缓存(Embedding相似度) 6. 监控告警:满意度/解决率/转人工率/成本 实时Dashboard 7. A/B测试:不同Agent策略灰度对比
Part B:RAG系统面试题¶
Q1:RAG系统的完整架构和各组件作用?¶
参考答案:
文档 → [加载器] → [分割器] → [Embedding] → [向量库]
↓
用户Query → [Query改写] → [检索器] → [重排序] → [上下文]
↓
[Prompt模板] + [LLM] → 回答
| 组件 | 作用 | 常用工具 |
|---|---|---|
| 文档加载 | 解析PDF/Word/HTML等 | Unstructured/PyMuPDF |
| 文本分割 | Chunk策略 | RecursiveCharacterSplitter/语义分割 |
| Embedding | 文本→向量 | BGE-M3/text-embedding-3/Jina |
| 向量数据库 | 存储+检索 | Milvus/Qdrant/Chroma/Pinecone |
| 检索器 | 查询匹配 | 向量检索/BM25/混合检索 |
| 重排序 | 精排 | BGE-Reranker/Cohere Rerank |
| LLM生成 | 基于上下文回答 | GPT-4o/Claude/Qwen |
Q2:如何选择Embedding模型和向量数据库?¶
参考答案:
Embedding选型: | 模型 | 维度 | 中文 | 多语言 | 推荐场景 | |------|------|------|--------|----------| | BGE-M3 | 1024 | ✅ | ✅ | 中文企业RAG首选 | | text-embedding-3-large | 3072 | ✅ | ✅ | OpenAI生态 | | Jina-embeddings-v3 | 1024 | ✅ | ✅ | 长文档/代码 | | GTE-Qwen2 | 1024 | ✅ | ✅ | 开源最强之一 |
向量库选型: | 数据库 | 规模 | 特点 | 推荐场景 | |--------|------|------|----------| | Chroma | <100万 | 轻量/嵌入式 | 原型/小项目 | | Qdrant | 百万级 | Rust实现/高性能 | 中型生产 | | Milvus | 十亿级 | 分布式/GPU加速 | 大规模企业 | | Pinecone | 任意 | 全托管/零运维 | SaaS优先 |
选型决策:数据规模 → 是否自托管 → 性能要求 → 预算
Q3:Chunk策略如何选择?¶
参考答案:
| 策略 | 原理 | 优点 | 缺点 | 适用 |
|---|---|---|---|---|
| 固定长度 | 按字符数切分 | 简单快速 | 可能切断语义 | 结构化文档不多时 |
| 递归分割 | 按段落→句子→字符递归 | 保持语义完整 | 参数调优 | 通用场景首选 |
| 语义分割 | 按Embedding相似度聚类 | 语义最优 | 计算量大 | 长文档/混合内容 |
| 按标题分割 | 按Markdown/HTML标题 | 保持文档结构 | 需结构化文档 | 文档/Wiki |
| 滑动窗口 | 重叠分割 | 减少信息丢失 | 存储增加 | 需要高召回 |
# 推荐实践:递归分割 + 滑动窗口
from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=512, # 512-1024 token适合大多数场景
chunk_overlap=50, # 10%重叠
separators=["\n\n", "\n", "。", ".", " "],
length_function=len
)
追问:小Chunk vs 大Chunk如何选? → 小Chunk(256-512)检索精度高但可能缺语境;大Chunk(1024-2048)语境完整但可能引入噪声。可以用Parent-Document策略:小Chunk检索,返回对应的大Chunk。
Q4:混合检索的实现原理?¶
参考答案:
def hybrid_search(query, k=10, alpha=0.7):
"""
混合检索 = 向量检索 + 关键词检索 + 重排序
alpha: 向量检索权重
"""
# 1. 向量检索(语义相似)
vector_results = vector_db.search(
embedding=embed(query), top_k=k*2
)
# 2. 关键词检索(精确匹配)
bm25_results = bm25_index.search(query, top_k=k*2)
# 3. 分数融合(RRF - Reciprocal Rank Fusion)
fused = reciprocal_rank_fusion(
[vector_results, bm25_results],
weights=[alpha, 1-alpha]
)
# 4. 重排序
reranked = reranker.rerank(query, fused[:k*2]) # 切片操作:[start:end:step]提取子序列
return reranked[:k]
def reciprocal_rank_fusion(results_lists, weights, k=60):
"""RRF融合公式:score = Σ weight / (k + rank)"""
scores = {}
for results, weight in zip(results_lists, weights): # zip并行遍历多个可迭代对象
for rank, doc in enumerate(results): # enumerate同时获取索引和值
scores[doc.id] = scores.get(doc.id, 0) + weight / (k + rank + 1)
return sorted(scores.items(), key=lambda x: -x[1]) # lambda匿名函数:简洁的单行函数
为什么需要混合: - 向量检索擅长语义匹配但可能遗漏关键词精确匹配 - BM25擅长关键词匹配但不理解语义 - 混合后互补,召回率显著提升(通常+10-20%)
Q5:GraphRAG的原理和优势?¶
参考答案:
GraphRAG = 知识图谱 + RAG,由Microsoft Research提出。
核心流程: 1. 文档→知识图谱:LLM提取实体和关系,构建图 2. 社区检测:Leiden算法对图聚类 3. 社区摘要:为每个社区生成高层摘要 4. 查询时: - Local Search:从实体出发,遍历邻居子图 - Global Search:利用社区摘要回答全局问题
优势: | 维度 | 普通RAG | GraphRAG | |------|---------|----------| | 全局问题 | ❌ 差(只能检索局部片段) | ✅ 强(社区摘要覆盖全局) | | 实体关系 | 隐含在文本中 | 显式建模 | | 多跳推理 | ❌ 弱 | ✅ 强(图遍历) | | 构建成本 | 低 | 高(需LLM提取知识图谱) | | 维护成本 | 低 | 中(图更新) |
追问:什么时候用普通RAG就够了,什么时候需要GraphRAG? → FAQ/单文档问答用普通RAG;需要跨文档关联推理、回答"总结所有..."类全局问题时用GraphRAG
Q6:RAGAS评估框架的核心指标?¶
参考答案:
| 指标 | 含义 | 评估什么 | 是否需Ground Truth |
|---|---|---|---|
| Faithfulness | 回答是否基于检索的上下文 | 幻觉程度 | 否 |
| Answer Relevancy | 回答与问题的相关性 | 答案质量 | 否 |
| Context Precision | 检索结果中相关文档的排位 | 检索精度 | 是 |
| Context Recall | Ground Truth是否被检索到 | 检索召回 | 是 |
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_precision, context_recall
result = evaluate(
dataset=eval_dataset, # questions + contexts + answers + ground_truths
metrics=[faithfulness, answer_relevancy, context_precision, context_recall]
)
print(result) # {'faithfulness': 0.85, 'answer_relevancy': 0.92, ...}
其他常用指标: - MRR (Mean Reciprocal Rank):第一个正确结果的排名倒数 - NDCG:考虑排名位置的相关性 - Hit Rate:top-k中是否包含正确答案 - 端到端准确率:人工标注正确/错误
Q7:如何处理RAG中的幻觉问题?¶
参考答案:
幻觉来源与对策:
| 来源 | 原因 | 对策 |
|---|---|---|
| 检索失败 | 相关文档未被检索到 | 混合检索/Query扩展/HyDE |
| 上下文噪声 | 检索到不相关内容 | 重排序/上下文压缩/过滤 |
| LLM臆造 | 模型倾向于"编造"答案 | 提示词约束/后处理验证 |
| 信息冲突 | 多个源信息矛盾 | 时间戳排序/置信度加权 |
关键技术:
# Prompt约束模板
SYSTEM_PROMPT = """
基于以下上下文回答问题。规则:
1. 只使用上下文中的信息
2. 如果上下文不包含答案,明确说"根据现有资料无法回答"
3. 引用来源:[来源: 文档名]
4. 不要推测或补充上下文中没有的信息
上下文:
{context}
"""
# 后处理:NLI验证
def verify_faithfulness(answer, context, nli_model):
"""用NLI模型验证回答是否被上下文支持"""
claims = extract_claims(answer) # 拆分为原子声明
for claim in claims:
result = nli_model.predict(premise=context, hypothesis=claim)
if result == "contradiction":
return False, claim # 发现幻觉
return True, None
Q8:多模态RAG如何设计?¶
参考答案:
文档(含图片/表格/公式)
↓
[多模态解析器]
├── 文本 → Text Embedding
├── 图片 → Vision Embedding (CLIP/SigLIP)
├── 表格 → 结构化解析 → Text Embedding
└── 公式 → LaTeX转文本 → Text Embedding
↓
[统一向量库] ← 带元数据(类型/页码/位置)
↓
检索 → [多模态LLM] (GPT-4o/Claude) → 回答
关键挑战: 1. 对齐:文本和图像的Embedding空间对齐 2. 解析:图表/流程图的准确提取 3. 推理:需要同时理解文本和视觉信息 4. 存储:多模态数据的高效索引
Q9:RAG vs 微调,什么场景选什么?¶
参考答案:
| 维度 | RAG | 微调 |
|---|---|---|
| 知识更新 | 实时(换文档即可) | 需重新训练 |
| 成本 | 检索+推理成本 | 训练成本(一次性) |
| 幻觉 | 较少(有源可查) | 较多(知识嵌入模型) |
| 适用 | 事实性QA/知识库/客服 | 风格适配/领域术语/格式控制 |
| 数据量 | 任意(作为检索库) | 需要高质量标注数据 |
| 可溯源 | ✅ 可引用来源 | ❌ 不可溯源 |
最佳方案:RAG + 微调结合 - 微调:让模型学会领域术语、输出格式、推理风格 - RAG:提供最新知识、可溯源的事实
Q10:设计一个支持10万文档的企业RAG系统¶
参考架构:
┌──────────────────────────────────────────┐
│ 数据摄入Pipeline │
│ 文档上传 → 解析 → 分割 → Embedding → 存储│
│ (Celery异步 + 增量更新 + 版本管理) │
└─────────────────┬────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 存储层 │
│ Milvus(向量) + ES(全文) + PostgreSQL(元)│
│ Redis(缓存) + S3(原始文档) │
└─────────────────┬───────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 检索层 │
│ Query改写 → 混合检索 → 重排序 → 过滤 │
│ (支持多租户/权限隔离/部门级别) │
└─────────────────┬───────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 生成层 │
│ Prompt构建 → LLM调用 → 后处理 → 引用标注│
│ (流式响应/多模型路由/cost控制) │
└─────────────────────────────────────────┘
关键设计点: 1. 分区索引:按部门/项目分Collection,减少检索范围 2. 增量更新:CDC监听文档变更,实时更新向量 3. 缓存策略:语义缓存(Embedding余弦相似>0.95直接返回) 4. 多租户:RBAC权限控制,确保数据隔离 5. 监控:检索延迟/命中率/用户满意度/幻觉率实时告警 6. 容量规划:10万文档 × 平均20 chunks = 200万向量,Milvus单机可承载
Part C:综合系统设计题¶
C1:设计一个AI代码审查系统¶
要求:自动审查PR,检测Bug/安全漏洞/代码风格,生成Review意见。
参考思路: 1. GitHub Webhook触发 → 获取PR diff 2. 代码分析Pipeline:AST解析 + LLM审查 + 规则引擎 3. Agent工具:运行测试/检查类型/查看上下文文件 4. 输出:逐行评论 + 总结 + 严重度分级 5. 人工反馈循环:采纳/驳回 → 训练数据
C2:设计一个智能文档搜索引擎¶
要求:支持100万篇技术文档,自然语言搜索+精确检索,日均100万查询。
参考思路: 1. 离线Pipeline:文档解析 → 多粒度索引(段落/章节/全文) 2. 在线检索:Query理解 → 混合检索(向量+ES) → 重排序 → 答案抽取 3. 扩展:Query自动补全/相关推荐/个性化排序 4. 基础设施:分布式Milvus + ES集群 + CDN缓存
C3:设计一个多模态AI助手¶
要求:理解文本/图片/语音输入,生成多模态输出,支持工具调用。
参考思路: 1. 输入层:ASR(语音→文本) + OCR(图片文字) + CLIP(图片理解) 2. Agent层:多模态LLM + 工具调用(搜索/代码/绘图/TTS) 3. 输出层:文本回复 + 图片生成(DALL-E) + 语音合成(TTS) 4. 记忆:多模态对话历史 + 用户偏好Profile
✅ 学习检查清单¶
- 能完整描述Agent架构(LLM+Tools+Memory+Planning)
- 理解ReAct/Reflexion/Plan-and-Execute等Agent范式
- 能比较LangGraph/CrewAI/AutoGen的差异
- 了解MCP协议的设计和三大能力
- 掌握RAG完整架构和各组件选型
- 理解Chunk策略/混合检索/重排序的原理和代码
- 了解GraphRAG的原理和适用场景
- 能用RAGAS评估RAG系统
- 能设计生产级Agent/RAG系统架构
- 完成Part C的3道系统设计题练习