Skip to content

AI智能体应用开发面试题 ​

生成时间:2026-06-15 21:35
题目数量:10道
知识范围:1-3年岗位要求,聚焦全新考点(避免与历史题库重复)


【面试题】1. MCP(Model Context Protocol)是什么?你在实际项目中是怎么用它来连接智能体和外部工具的? ​

【标准答案】 MCP是Anthropic推出的开放协议,核心思路是把"工具调用"标准化——就像USB-C统一了外设接口一样,MCP统一了智能体与外部工具、数据源的连接方式。

MCP的核心架构:

  • MCP Server:工具提供方,实现一个标准接口暴露工具和数据资源
  • MCP Client:智能体侧,通过协议自动发现Server的能力
  • 传输层:支持stdio(本地进程间通信)和SSE(远程服务)

我的实战经验: 在一个内部数据分析Agent项目中,我把五个数据源(MySQL、ClickHouse、Elasticsearch、公司API网关、文件系统)各封装成一个MCP Server。Agent启动时自动发现所有可用工具,无需硬编码工具列表。

收益:

  • 新增数据源只需加一个MCP Server,Agent zero-code接入
  • 工具描述统一管理,工具文档自动同步到模型侧
  • 安全性提升:MCP Server可以独立做鉴权,不会把内部API Key暴露给Agent

相比传统Function Calling的优势: 传统方式要在代码里显式定义每个工具的JSON Schema,MCP让工具发现变成运行时动态的——Agent问Server"你支持什么"就行了。这对工具数量超过20个的场景特别有用。


【面试题】2. 智能体在工作流执行过程中意外中断了(如服务重启、API超时),你如何设计"中断恢复"机制来保证不丢失进度? ​

【标准答案】 这是生产环境必须解决的问题。我设计的方案叫"检查点+补偿事务"模式:

核心思路:把Agent的每次决策和中间结果都持久化,中断后从最近的检查点恢复。

第一层:状态持久化 每次Agent执行完一个步骤(Thought/Action/Observation),都把完整状态写入数据库:

json
{
  "session_id": "xxx",
  "step_index": 5,
  "status": "done",
  "state": {
    "已完成工具调用": ["搜索竞品列表", "分析竞品A"],
    "当前任务": "分析竞品B",
    "pending_tools": ["分析竞品C", "汇总报告"],
    "accumulated_context": "已分析竞品A和B..."
  },
  "created_at": "2026-06-15 21:00:00"
}

用LangGraph的StateGraph天然支持这个模式——它的State对象可以配置为持久化到PostgreSQL或Redis。

第二层:幂等性设计 工具调用必须是幂等的——调用一次和调用多次效果一样。比如"发送邮件"就不幂等,实现方式是先存草稿(幂等),再触发发送(带唯一ID去重)。

第三层:恢复策略 中断后恢复时:

  1. 读取最新检查点,加载state
  2. 检查pending_tools,跳过已完成步骤
  3. 重新执行未完成的工具调用
  4. 用事务ID去重,避免重复执行副作用

实战案例: 我们做数据报告Agent,一次任务可能要跑30分钟。加了检查点后,半夜API超时中断,第二天重启后自动从第7步继续跑,用户完全没感知。

框架支持:

  • LangGraph的Checkpointer + SqliteSaver/PostgresSaver
  • CrewAI的KickoffTask支持异步+重入

【面试题】3. GraphRAG和传统RAG有什么区别?你什么时候会选择用GraphRAG? ​

【标准答案】 传统RAG是把文档切块后向量化存向量库,检索时找语义相似的块。适合"答案在一个文档块里"的场景。

GraphRAG是在文档之上建知识图谱:提取实体(人、事、物)和关系(实体之间的连接),检索时既做语义搜索也做图谱遍历。适合"答案需要跨文档推理"或"需要发现实体间关系"的场景。

核心区别:

维度传统RAGGraphRAG
数据结构文档块向量实体+关系+社区摘要
检索方式向量相似度向量检索 + 图遍历 + 社区查询
适合问题"苹果的毛利率是多少?""苹果和微软的供应链有什么共同点?"
推理能力弱(需要模型自己关联)强(图结构天然展示关系)
构建成本低高(提取+建图+社区检测)
维护成本低高(图谱更新复杂)

选型判断:

  • 问题多数是直接查询型("XX公司的XX指标")→ 传统RAG够用
  • 问题需要多跳推理("哪些公司同时与A和B有合作关系")→ GraphRAG
  • 数据量大且关系密集(如论文评审、法律案例、医疗诊断)→ GraphRAG值

我的实战: 做一个企业内网知识库时,一开始用传统RAG效果尚可,但用户问"这个部门和那个部门有什么协作历史"这类跨文档问题时,传统RAG就抓瞎了。改用Microsoft的GraphRAG方案后,提取出部门、项目、人员的关系图谱,这类问题准确率从55%提升到82%。

部署姿势:不需要所有数据都走GraphRAG,可以分层——简单问答走传统RAG(快且便宜),复杂推理走GraphRAG(慢但准),用"问题复杂度分类器"做路由。


【面试题】4. 你在智能体开发中怎么用结构化输出(Structured Output)?遇到过什么坑? ​

【标准答案】 结构化输出是让Agent从"写文章"变成"填表格"的能力,对构建可靠Agent至关重要。

我的用法:

  1. 工具调用参数:用response_format={"type": "json_schema", "json_schema": {...}}强制模型输出合法JSON,而不是靠Prompt约束
  2. Agent的决策输出:要求Agent输出固定Schema,比如{"thought": "...", "next_action": "call_tool", "tool_name": "search", "parameters": {...}}
  3. RAG答案格式:要求答案包含{"answer": "...", "confidence": 0.9, "sources": ["doc1", "doc2"]},方便下游做置信度判断和引用溯源

踩过的坑:

坑1:复杂嵌套Schema模型经常漏字段 用gpt-4o-mini输出深层嵌套的JSON Schema,经常漏掉optional字段或给出不合法的枚举值。 解决:Schema尽量扁平化,嵌套不超过2层;用Pydantic做后置校验,校验失败重试一次(在Prompt里附上错误信息让模型修正)。

坑2:结构化输出和Function Calling冲突 同时用response_format和tools参数,某些API版本不支持。 解决:如果既要用工具又需要结构化输出,我统一走Function Calling路径(把所有输出需求定义成一个叫final_answer的工具)。

坑3:Schema版本管理 换了Schema结构,旧Session存的数据和新Schema不兼容。 解决:Schema文件用Semantic Version,在metadata里记录版本号,下游做兼容转换。

实战技巧:

python
from openai import OpenAI
from pydantic import BaseModel

class AgentOutput(BaseModel):
    thought: str
    action: str  # "call_tool" | "final_answer" | "ask_clarification"
    tool_name: str | None = None
    tool_params: dict | None = None
    final_answer: str | None = None

# 强制结构化输出
response = client.beta.chat.completions.parse(
    model="gpt-4o",
    messages=[...],
    response_format=AgentOutput,
)

注:response_format传Pydantic模型是OpenAI SDK的parse模式,会自动校验Schema

核心建议:结构化输出不应该只靠"告诉模型",要用API的原生能力(response_format、tools、strict=true)来做强制约束。


【面试题】5. 智能体系统的可观测性你是怎么做的?说一套从日志到追踪再到分析的完整方案。 ​

【标准答案】 Agent系统的可观测性比传统后端Web服务复杂得多——因为有"推理链路"在里面,每一步都是LLM调用,不能只靠"状态码200"来判断。

我的三层可观测性架构:

第一层:结构化日志(Logging) 不只是记"调用了LLM",而是记:

json
{
  "trace_id": "xxx",
  "session_id": "xxx",
  "step_type": "llm_call",
  "model": "gpt-4o",
  "prompt_tokens": 2500,
  "completion_tokens": 350,
  "latency_ms": 1200,
  "temperature": 0.3,
  "tools_called": ["search", "analyze"],
  "success": true,
  "user_input_hash": "xxx"
}

每条日志挂上trace_id,串联整条Agent推理链路。

第二层:链路追踪(Tracing) 用OpenTelemetry + LangSmith/LangFuse做分布式追踪:

关键追踪指标:

  • 端到端响应时间(P50/P95/P99)
  • 每步的LLM调用耗时和token消耗
  • 工具调用成功率、耗时
  • 重试次数和原因
  • Agent最终是否成功完成任务

LangSmith的用法:给LangChain的Runnable配置callbacks=[LangSmithCallbackHandler()],所有链路的输入输出、token消耗、耗时全自动追踪。

第三层:质量评估(Evaluation) 日志和追踪只是"发生了什么",质量评估回答"做得好不好":

自动化评估:

  • 用LLM-as-Judge:用一个强模型(GPT-4o/Claude)给Agent的回答打分(准确性、完整性、安全性)
  • 用RAGAS评估RAG链路:Faithfulness、Answer Relevancy、Context Precision
  • Tool调用成功率、平均重试次数
  • 用户显式反馈(👍👎)收集率

我的监控看板(Grafana): 放四个核心图:

  1. 端到端成功率趋势图(过去24h/7d)
  2. Token消耗按用户/功能拆分的柱状图
  3. 工具调用成功率热力图(按工具×时间)
  4. 用户满意度趋势(👍率/👎率)

实战案例: 接入LangSmith后,我发现某个工具调用成功但平均耗时5秒,排查发现是网络问题,切换到内网API后降到200ms。没有tracing根本抓不到这个问题。

工具推荐:

  • 快速起步:LangSmith(和LangChain天然集成)
  • 自托管/数据合规:LangFuse(开源,支持自部署)
  • 大规模生产:OpenTelemetry + 自建收束

【面试题】6. 大模型的长上下文窗口(128K+ tokens)越来越普及,你怎么利用它?又有哪些实际坑? ​

【标准答案】 长上下文既是礼物也是陷阱,我的观点是"用但别滥用"。

我利用长上下文的方式:

1. 替代RAG的简单场景 当数据量小(<200页文档)且不需要频繁更新时,直接把全文塞进System Prompt,省掉RAG的复杂链路。比如给Agent一份完整的用户手册,而不是切块检索。

2. 多轮对话不丢上下文 用128K窗口可以存下10-20轮完整对话(含历史工具的调用结果),不需要做"记忆摘要压缩"。这让Agent在多轮交互中保持"完整记忆"。

3. 批量处理 一次传入50条待处理的记录,让模型批量生成结果,用结构化输出分离,减少API调用次数。

踩过的坑:

坑1:注意力衰减(Lost in the Middle) 模型对"中间部分"的记忆最差,开头和结尾记得最牢。把100页文档放中间,50-70页的内容经常被忽略。 解决:

  • 把最重要的信息放开头和结尾
  • 或者分段处理:先让模型扫描全文摘要,再对关键章节深入分析
  • 用Anthropic的Prompt Caching把文档缓存,减少注意力衰减

坑2:Token成本并不便宜 128K token输入的成本=纯文本的30-50倍。如果每天处理1000次请求,用长上下文的费用是RAG方案的5-10倍。 解决:只对需要全局上下文的请求用长上下文(如"总结全文"),简单的单点查询走RAG。

坑3:延迟大幅增加 输入50K tokens时,首Token延迟可能从500ms飙到5-10秒。 解决:用Prompt Caching(Anthropic)或KV Cache优化,把重复的文档内容缓存起来,首Token延迟能降70%。

我的选型策略:

数据量 < 100页 + 不需要频繁更新 → 直接长上下文(省去RAG)
数据量 > 100页 + 需要实时更新 → RAG(成本可控)
数据量 > 500页 + 需要全局推理 → GraphRAG + 长上下文做最后汇总

【面试题】7. 你做过代码生成Agent吗?怎么保证生成的代码是正确且安全的? ​

【标准答案】 做过一个"自动修复Bug"的Agent,嵌入到CI/CD流水线里。

架构设计(四阶段):

阶段1:代码理解 把代码仓库上下文(文件结构、相关代码块、Git diff)注入到Agent的上下文中。关键是用"仓库地图"——只传相关文件,不传整个仓库(用embedding检索相关代码)。

阶段2:代码生成 Agent用few-shot示例+结构化输出生成代码变更:

json
{
  "changed_files": ["src/api/handler.py"],
  "changes": [
    {
      "file": "src/api/handler.py", 
      "operation": "modify",  // "create" | "modify" | "delete"
      "start_line": 42,
      "end_line": 55,
      "new_content": "def handle_request(...):\n    ..."
    }
  ]
}

阶段3:安全执行沙箱 生成的代码绝不能直接执行。我的做法:

  • 隔离沙箱:用Docker容器执行,限制文件系统只读、网络断连、CPU/内存配额
  • 静态分析:自动跑pylint/mypy/bandit做代码质量审查
  • 单元测试:自动生成测试用例并执行,通过率<90%的代码变更自动标记为"不可用"

阶段4:人工审核入口 Agent生成的代码以PR形式提交,加上AI Review Comment,必须有真人 approve 才能合并到主分支。

实战中遇到的关键问题:

问题1:Agent容易生成"看似正确但实际有逻辑漏洞"的代码解决:要求Agent输出"变更的测试用例"和"变更理由",Reviewer Agent用这些信息做交叉验证。

问题2:Agent会保留旧代码中的安全隐患(如硬编码密码)解决:在代码分析阶段,加一道安全扫描工具(如Semgrep),自动标记安全风险点,Agent生成时必须处理这些标记。

问题3:Agent生成代码依赖一个第三方库不存在解决:沙箱执行时自动检测导入失败,把错误信息反馈给Agent让其修正。

安全原则:代码生成Agent的核心原则是 "generate but not execute without human approval"——不要相信模型生成的代码直接能跑,更不要相信它没安全漏洞。


【面试题】8. 语义缓存(Semantic Caching)怎么做?对降本有多大帮助? ​

【标准答案】 语义缓存不是"相同问题直接命中缓存"(那是传统KV缓存),而是"语义相似的问题复用答案"——用户问"退款要多久"和"退款时间多长"得到同样的答案。

实现方案:

用户问题 → Embedding → 向量检索缓存库 → 命中(相似度>阈值) → 直接返回缓存答案
                                 → 未命中 → 调用LLM → 存缓存 → 返回

核心参数:

  • 相似度阈值:0.85-0.95(默认0.90),太高命中少,太低会返回不相关答案
  • 缓存TTL:根据场景设定,事实性问题设长(24h),时效性问题设短(5min)
  • 缓存大小:常见FAQ场景存最近1000条就够了

技术实现(Redis + Embedding):

python
import numpy as np
from redis import Redis

class SemanticCache:
    def __init__(self, threshold=0.90):
        self.redis = Redis()
        self.threshold = threshold
    
    def get(self, query: str) -> str | None:
        q_vec = embed(query)  # 用户问题转向量
        # 检索缓存的query向量,计算相似度
        for cached_query, cached_answer, vec_blob in self.redis.hscan_iter("semantic_cache"):
            cached_vec = np.frombuffer(vec_blob, dtype=np.float32)
            sim = cosine_similarity(q_vec, cached_vec)
            if sim > self.threshold:
                return cached_answer
        return None
    
    def set(self, query: str, answer: str):
        vec = embed(query).tobytes()
        self.redis.hset("semantic_cache", query, answer)
        self.redis.hset("semantic_vecs", query, vec)
        self.redis.expire("semantic_cache", 86400)  # 24h TTL

更成熟的方案:用向量数据库代替Redis做缓存检索,适合大规模场景。

  • Redisearch(Redis的向量搜索模块)
  • Qdrant/Pinecone做缓存库(和RAG复用一套基础设施)

对降本的实际效果:

我们一个知识问答Agent,上线后前两周数据:

  • 总查询量:50,000次
  • 语义缓存命中率:~30%(常见多的是"退款"/"登录"/"如何"这类高频问题)
  • 节省的LLM调用:15,000次
  • 按GPT-4o mini计费,每月节省约$600

命中率优化技巧:

  1. 双阈值策略:高阈值(0.95)直接返回,中阈值(0.85-0.95)返回时标注"可能不完全匹配,仅供参考"
  2. Query归一化:统一语言(英文→中文)、去掉停用词、同义词替换,提升命中率
  3. 缓存预热:上线前把历史FAQ扔进去预缓存,启动即有命中

注意事项:

  • 时效性敏感场景(如"今天天气")不要走语义缓存,设category标记
  • 个人化问题(如"我的订单")不要走语义缓存,涉及隐私
  • 定期清理冷数据,防止缓存膨胀

语义缓存是成本控制中最被低估的手段——实现简单、收益显著,建议所有RAG/Agent项目都加上。


【面试题】9. 你怎么系统化地评估一个智能体的效果?用哪些指标?用什么工具? ​

【标准答案】 智能体评估比传统软件复杂——不只测"功不功能正常",还要测"回答质量"和"用户体验"。我的评估框架分三层:

第一层:功能正确性(Functional Correctness)指标:

  • Tool调用成功率:Agent是否正确选择了工具并传了正确参数
  • 任务完成率:Agent是否完成了用户的目标(如"查询订单"最后确实返回了订单信息)
  • 意图识别准确率:Agent是否准确理解了用户意图
  • Schema合规率:Agent输出是否符合要求的结构化格式

测试方法:准备50-100条标注好的测试用例(输入+预期输出),跑回归测试。用pytest写自动化用例,断言Agent的输出是否符合预期。

第二层:答案质量(Answer Quality)

LLM-as-Judge(自动化评分): 用更强的模型(GPT-4o/Claude)对Agent的回答做多维评分:

  • 准确性(Accuracy):回答是否基于事实,1-5分
  • 完整性(Completeness):是否回答了用户所有子问题
  • 安全性(Safety):是否包含有风险或不当内容
  • 引用正确性(Citation):RAG答案的引用是否真实命中
python
from ragas import SingleTurnSample
from ragas.llms import LangchainLLM

sample = SingleTurnSample(
    user_input="退款多久到账?",
    response="通常3-5个工作日,政策见...",
    retrieved_contexts=["退款政策文档片段"],  # RAG上下文
    reference="3-5个工作日"  # 期望答案
)

scorer = Faithfulness(llm=LangchainLLM(ChatOpenAI(model="gpt-4o")))
score = scorer.single_turn_score(sample)

第三层:用户体验(User Experience)

  • 用户满意度:对话后的👍👎点击率,目标>85%
  • 首次解决率:Agent是否在首次交互中解决了用户问题(没发重问或转人工)
  • 平均对话轮数:轮数越少效果越好(说明一次就懂了)
  • 转人工率:越转人工说明Agent效果越差,目标<20%

评估工具推荐:

  • RAGAS:RAG链路质量评估,最成熟的方案
  • LangSmith / LangFuse:自带评估模块,支持在线评估+人工标注
  • DeepEval:支持多种Agent和LLM的评估指标,CI集成方便
  • 自建评估平台:大规模团队建议自建,把测试用例管理+自动评估+人工标注+趋势报表放一起

我的评估流程(每周跑一次):

  1. 从生产环境随机抽取100条对话(去隐私后)
  2. 自动跑LLM-as-Judge评分
  3. 人工标注Top-10高分和低分对话(用来校准自动评分)
  4. 对比上周数据,看趋势
  5. 发现某个指标下降,追查到具体问题类型,进入优化流程

核心原则:指标不是为了"好看",而是为了"发现问题"。如果一个指标连续两周不变化,说明它没在驱动优化,该换指标了。


【面试题】10. 你遇到过的AI Agent端到端响应慢的问题,从用户提问到收到回复,你排查过哪些瓶颈?怎么优化到1秒以内? ​

【标准答案】 端到端延迟优化是Agent工程化的必答题。我按"定位→优化"两步走。

第一步:链路拆解,找到瓶颈

一个典型Agent请求从发出到回复的完整链路:

用户请求 → 网络传输 → 意图识别(LLM) → 检索RAG(向量库) 
→ 重排序(Cross Encoder) → 组装Prompt → LLM生成(首Token)
→ Streaming响应 → 网络传输 → 用户看到

在生产中实际测到的各环节耗时占比(200次采样均值):

环节耗时占比
意图识别LLM200-400ms15%
向量检索20-50ms2%
Rerank50-150ms5%
LLM生成(首Token)500-2000ms50-60%
Streaming传输200-500ms15%
网络+序列化100-200ms8%

瓶颈很明确:LLM的首Token延迟是所有环节中最慢的。

第二步:针对性优化(从收益最高到最低)

优化1:LLM首Token加速(收益最大)

  • Prompt Caching:用Anthropic的Prompt Caching或OpenAI的Project,把System Prompt和知识库上下文提前缓存,首Token延迟从2s降到300ms
  • 模型选型:相同能力下选首Token更快的模型,如Claude Haiku比Sonite快,Gemini Flash比Pro快
  • 降低Prompt长度:System Prompt不要超过2000 tokens,长文档走RAG而不是全文塞入

优化2:流式输出(Streaming)

  • 用SSE(Server-Sent Events)边生成边输出,用户不需要等全部生成完
  • 实测"读完前100字"的时间:非流式5s → 流式1.2s(TTP=Time To First Token + 100字生成时间)

优化3:并行化非依赖步骤

  • 意图识别和向量检索可以并行,因为两者无依赖关系
  • 用asyncio.gather并行调用,节省串行等待时间
python
async def handle_request(query):
    # 并行执行意图识别和向量检索
    intent_task = detect_intent(query)   # LLM调用
    rag_task = retrieve_knowledge(query) # 向量检索
    intent, docs = await asyncio.gather(intent_task, rag_task)
    # 然后再合成回答

优化4:缓存策略

  • 语义缓存:语义相似的问题直接返回缓存答案,跳过LLM调用(命中时延迟从2s降到20ms)
  • KV Cache共享:相同用户的相似请求复用模型内部的KV Cache

优化5:轻量级预判(前置过滤)

  • 简单问题(如"你好"、"你是谁")直接用规则引擎回复,不走大模型
  • 实现:用一个分类模型(可以是小模型BERT或setFit)做0-shot/1-shot判断,100ms以内

优化6:基础设施优化

  • 向量数据库加连接池,避免每次建连接(Qdrant的gRPC默认有连接池)
  • 模型实例保持warm状态(Serverless冷启动可以提前预热)
  • CDN加速静态资源(前端文件、图标等)

我的优化前后数据对比:

指标优化前优化后
P50延迟3.2s0.8s
P95延迟8.5s2.1s
P99延迟15s4.5s
首Token出现时间2.5s0.8s
日处理请求数50005000(成本下降60%)

最立竿见影的三个优化(按收益排序):

  1. Prompt Caching → 首Token延迟降60%
  2. 语义缓存 → 命中请求从3s降到20ms
  3. 并行化意图识别+RAG检索 → 串行变并行省500ms

一句话总结:不要一上来就折腾代码,先用量化手段找到瓶颈,LLM的首Token延迟永远是最大的优化空间,Prompt Caching + Streaming是默认必加的最小套餐。


本题库由AI智能体应用开发面试题生成器自动生成,聚焦1-3年经验岗位核心考点。本批次全部为全新考点,与历史题库无重复。