Skip to content

12.6 面试场景题精选

前面五节我们从智能客服讲到代码生成、数据分析,从多 Agent 协作讲到稳定性设计。这些知识怎么在面试中用出来?面试场景题考的不仅是"知不知道",更是"能不能用 SCALE 框架拆解问题、能不能清晰表达设计思路和权衡"。

本节精选四道最高频的 Agent 面试场景题——智能客服 Agent 设计、输出一致性保障、RAG 检索质量优化、工具调用失败处理——每道题都给出完整的分析框架和代码实现。下一章我们将进入实战项目,把前面所有章节的知识融合到一个完整的 Agent 项目中。

生活类比:急诊科医生的思维

想象你是医院急诊科的值班医生。患者被送进来时,你不会一上来就开药,而是先快速判断病情(场景分析),再决定要做哪些检查(组件拆解),然后设计诊疗方案(架构设计),同时考虑药物副作用和替代方案(限制与权衡),最后从急救到康复分阶段治疗(演进路径)。

面试场景题就是这种"急诊思维"的考验。面试官给你一个模糊的业务需求,你要在 15-20 分钟内把它拆解成清晰的系统设计。推荐使用 SCALE 框架

S - Scenario(场景分析):明确需求、用户量、约束条件
C - Component(组件拆解):拆解为可独立设计的模块
A - Architecture(架构设计):设计模块间交互和数据流
L - Limitations(限制与权衡):指出方案的局限性和取舍
E - Evolution(演进路径):从MVP到生产级的演进计划

一、场景题1:设计智能客服 Agent

题目:设计一个电商平台的智能客服 Agent,支持售前咨询、售后处理、订单查询,日活 100 万用户。

S - 场景分析

  • 功能需求:售前咨询(产品推荐、比价)、售后处理(退换货、投诉)、订单查询(物流、状态)
  • 非功能需求:日活 100 万,峰值 QPS 约 5000,P99 延迟 < 3 秒
  • 约束:不能给出错误承诺(如退货金额),敏感操作需人工确认

C - 组件拆解

python
# 核心组件架构
class CustomerServiceSystem:                       # 智能客服系统
    """
    组件清单:
    1. 意图分类器 - 将用户消息分为:咨询/售后/订单/闲聊/投诉
    2. 对话管理器 - 维护多轮对话状态和上下文
    3. 知识检索器 - 从FAQ、产品库、历史工单中检索
    4. 业务执行器 - 查询订单、创建工单等
    5. 情绪分析器 - 实时分析用户情绪
    6. 人工转接器 - 在必要时转人工
    7. 安全审核器 - 防止不当回复
    """
    pass

A - 架构设计

用户请求 -> API Gateway -> 意图分类 -> 路由分发
                                    ├── 咨询:RAG检索 -> LLM生成 -> 安全审核 -> 回复
                                    ├── 售后:情绪分析 -> 工单查询 -> 策略决策 -> 回复
                                    ├── 订单:身份验证 -> 订单查询 -> 格式化回复
                                    └── 投诉:情绪分析 -> 自动升级 -> 转人工

关键设计决策

  1. 缓存策略:热点问题(如"如何退货")缓存到 Redis,减少 LLM 调用
  2. 异步处理:非紧急操作(如创建工单)异步处理,快速返回 ACK
  3. 分级响应:简单问题走规则引擎,复杂问题走 LLM+RAG

L - 限制与权衡

  • LLM 可能产生幻觉,需要事实核查层
  • 100 万 DAU 的成本控制:缓存+规则引擎覆盖 80% 场景
  • 安全性:敏感操作(退款)必须人工确认

E - 演进路径

  • V1:规则引擎+FAQ 匹配(1 周上线)
  • V2:加入 LLM+RAG(1 个月)
  • V3:多 Agent 协作+自动学习(3 个月)

这个演进路径的设计思路是"先解决 80% 的问题,再逐步优化"。V1 用规则引擎覆盖高频标准问题(如退货流程、物流查询),这类问题占客服总量的 70-80%,用规则引擎 1 周就能上线,立即降低人工压力。V2 引入 LLM+RAG 处理需要语义理解的复杂问题。V3 做多 Agent 协作和自动学习——系统自动从历史对话中学习新的问答模式,持续提升覆盖率。

面试时如果面试官追问"100 万 DAU 的成本怎么控",关键回答是:缓存+规则引擎覆盖 80% 流量,只有 20% 复杂问题走 LLM+RAG,这样 LLM 调用量控制在可控范围内。同时通过异步批处理非紧急请求,削峰填谷降低峰值 QPS 压力。

二、场景题2:确保输出一致性

题目:如何确保 Agent 在相同输入下产生一致的输出?特别是涉及金额、日期等关键信息时。

LLM 本质上是概率模型——同一输入可能产生不同输出。这在创意场景是优点,但在涉及金额、日期、订单号等关键信息时是致命的。解决方案是四重保障:结构化输出约束、确定性后处理、事实核查、温度参数控制。

python
class OutputConsistency:                            # 输出一致性保障
    """输出一致性保障"""                             #   四重保障确保关键信息准确

    # 策略1:结构化输出约束
    STRUCTURED_OUTPUT_PROMPT = """请严格按照以下JSON格式回复,不要添加任何额外内容。

## 输出格式
```json
{
    "answer": "回答内容",
    "confidence": 0.0-1.0,
    "sources": ["来源1", "来源2"],
    "requires_human_review": true/false
}

严格规则

  1. 金额字段只使用数字,不要添加货币符号

  2. 日期使用YYYY-MM-DD格式

  3. 如果信息不确定,confidence设为0,并标记requires_human_review=true """

    策略2:确定性后处理

    @staticmethod def normalize_output(response: str) -> str: """标准化输出""" # 用正则统一格式 import re # 正则模块 date_patterns = [ # 日期格式统一 (r'(\d{4})年(\d{1,2})月(\d{1,2})日', r'\1-\2-\3'), # 2024年1月1日->2024-1-1 (r'(\d{1,2})/(\d{1,2})/(\d{4})', r'\3-\1-\2'), # 01/15/2024->2024-01-15 ] for pattern, replacement in date_patterns: # 遍历日期模式 response = re.sub(pattern, replacement, response) # 替换 response = re.sub(r'[¥¥]', 'CNY', response) # 统一货币符号 return response # 返回标准化结果

    策略3:事实核查

    @staticmethod async def fact_check(response: str, knowledge_base) -> Dict: """对比知识库验证事实""" # 提取声明并逐条验证 claims = OutputConsistency._extract_claims(response) # 提取声明性语句 verified = [] # 验证结果列表 for claim in claims: # 逐条验证 kb_result = await knowledge_base.search(claim) # 查知识库 verified.append({ # 记录验证结果 "claim": claim, # 声明内容 "verified": len(kb_result) > 0, # 是否验证通过 "evidence": kb_result[0] if kb_result else None # 证据 }) return { # 返回验证汇总 "all_verified": all(v["verified"] for v in verified), # 是否全部通过 "details": verified # 详细结果 }

    策略4:温度参数控制

    @staticmethod def get_consistency_config(task_type: str) -> Dict: """根据任务类型返回一致性配置""" # 不同任务不同温度 configs = { "factual_qa": {"temperature": 0.0, "top_p": 1.0}, # 事实问答:最确定 "explanation": {"temperature": 0.3, "top_p": 0.9}, # 解释说明:较确定 "creative": {"temperature": 0.7, "top_p": 0.9}, # 创意写作:一般 "brainstorm": {"temperature": 1.0, "top_p": 0.95}, # 头脑风暴:最随机 } return configs.get(task_type, configs["factual_qa"]) # 默认用最确定


**面试回答要点**:
1. 区分"需要一致性"和"需要多样性"的场景——事实问答要确定性,创意写作要多样性
2. 技术手段:结构化输出、验证层、低温度参数、多次采样投票
3. 关键信息(金额、日期)必须经过后处理验证,不能完全信任 LLM
4. 不确定时明确告知用户,而非给出看似确定的错误答案

**面试加分技巧**:如果面试官追问"多次采样投票怎么实现",可以这样回答——对同一问题用 temperature=0.3 生成 3 次回答,取多数一致的部分作为最终输出。如果 3 次答案各不相同,说明模型对这个问题不确定,应该标记 `requires_human_review=true` 转人工。这种"投票+置信度"的组合策略,在金融、医疗等高精度场景尤其重要。

#### 三、场景题3:RAG 检索质量优化

**题目**:RAG 系统检索到的文档不相关,导致回答质量差。如何诊断和优化?

RAG 是 Agent 的核心能力之一,但"检索到不相关文档"是 RAG 系统最常见的痛点。面试时不能只说"换个 embedding 模型"——要先诊断再优化,分层处理。

诊断的思路是逐一排查可能的故障点:查询是否被正确理解、文档分块是否合理、向量相似度分布是否正常、有没有重复文档。`RAGDiagnostics` 把这套诊断逻辑编码成了代码:

```python
class RAGDiagnostics:                               # RAG系统诊断工具
    """RAG系统诊断工具"""                            #   逐一排查检索质量问题

    def __init__(self):                             # 初始化
        self.metrics = {}                           #   诊断指标

    def diagnose(self, query: str, retrieved_docs: List[str],
                 expected_docs: List[str] = None) -> Dict:
        """诊断RAG检索质量"""                       #   返回问题列表和建议
        issues = []                                  #   发现的问题

        # 检查1:Query是否被正确理解
        if len(query.split()) < 3:                  #   查询太短
            issues.append("查询过短,可能缺少上下文")

        # 检查2:文档分块是否合理
        avg_chunk_size = sum(len(d) for d in retrieved_docs) / max(len(retrieved_docs), 1)  # 平均分块大小
        if avg_chunk_size < 100:                    #   分块太小
            issues.append("文档分块过小,缺少上下文")
        elif avg_chunk_size > 2000:                 #   分块太大
            issues.append("文档分块过大,噪声过多")

        # 检查3:向量相似度分布(召回率)
        if expected_docs:                            #   有标注的期望结果
            recall = len(set(expected_docs) & set(retrieved_docs)) / len(expected_docs)  # 计算召回率
            if recall < 0.5:                        #   召回率太低
                issues.append(f"召回率过低:{recall:.2f}")

        # 检查4:重复文档
        unique_docs = set(retrieved_docs)            #   去重后的文档集
        if len(unique_docs) < len(retrieved_docs):  #   有重复
            issues.append(f"存在重复文档:{len(retrieved_docs) - len(unique_docs)}个重复")

        return {                                    #   返回诊断报告
            "issues": issues,                       #     问题列表
            "severity": "high" if len(issues) > 2 else "medium" if issues else "low",
            "recommendations": self._generate_recommendations(issues)  # 优化建议
        }

    def _generate_recommendations(self, issues: List[str]) -> List[str]:
        """生成优化建议"""                           #   根据问题给建议
        recommendations = []                        #   建议列表
        for issue in issues:                         #   遍历每个问题
            if "分块过小" in issue:                  #   分块太小
                recommendations.append("增大chunk_size到500-800,增加overlap到100")
            elif "分块过大" in issue:                 #   分块太大
                recommendations.append("减小chunk_size到300-500")
            elif "召回率过低" in issue:              #   召回率低
                recommendations.append("尝试混合检索(BM25+向量),或使用重排序模型")
            elif "重复" in issue:                   #   有重复
                recommendations.append("添加去重逻辑,或使用MMR算法增加多样性")
            elif "查询过短" in issue:                #   查询太短
                recommendations.append("使用Query Rewriting或HyDE技术扩充查询")
        return recommendations                       #   返回建议列表

诊断后要分层优化。RAGOptimizer 总结了八种主流优化策略:

python
class RAGOptimizer:                                  # RAG优化策略集
    """RAG优化策略集"""                              #   八种策略覆盖全链路

    STRATEGIES = {
        "query_rewriting": "使用LLM改写用户查询,增加关键词和上下文",  # Query层优化
        "hyde": "先生成假设性答案,再用答案检索相关文档",               # 假设性答案
        "hybrid_search": "BM25(关键词)+ 向量(语义)混合检索",        # 检索层优化
        "reranking": "使用Cross-Encoder重排序检索结果",                # 后处理优化
        "chunk_optimization": "优化文档分块策略(大小、重叠、语义分块)",  # 分块优化
        "metadata_filtering": "利用元数据过滤(时间、类别、来源)",     # 元数据过滤
        "multi_query": "生成多个查询变体,合并检索结果",                # 多查询
        "self_query": "LLM自动提取查询中的过滤条件",                    # 自动过滤
    }

面试回答要点

  1. 先诊断再优化:分块策略 -> Embedding 质量 -> 检索算法 -> 重排序,逐一排查
  2. 分层优化:Query 层(改写)-> 检索层(混合检索)-> 后处理层(重排序)
  3. 评估指标:Recall@K、MRR、NDCG,用数据说话而非凭感觉
  4. 权衡:提高召回率可能降低精确率,需根据场景选择

四、场景题4:工具调用失败处理

题目:Agent 调用工具时可能失败(超时、权限不足、结果异常),如何设计健壮的错误处理?

工具调用是 Agent 执行动作的核心途径,但外部工具不可能 100% 可靠。面试时不能只说"加个 try-catch"——要区分错误类型,对不同错误用不同策略。

核心思路是错误分类 -> 匹配策略 -> 降级兜底:可重试错误(超时、限流)用指数退避重试;不可重试错误(权限不足)直接降级;结果异常要验证后再决定是否重试。

python
class ToolCallErrorHandler:                          # 工具调用错误处理器
    """工具调用错误处理器"""                         #   分类错误+匹配策略+降级

    # 错误分类与处理策略
    ERROR_STRATEGIES = {
        "timeout": {                                #   超时:可重试
            "retry": True,
            "max_retries": 3,
            "backoff": "exponential",
            "fallback": "use_cached_result"
        },
        "permission_denied": {                      #   权限不足:不可重试
            "retry": False,
            "fallback": "request_user_permission",
            "user_message": "需要您的授权才能执行此操作"
        },
        "rate_limited": {                            #   限流:可重试但等更久
            "retry": True,
            "max_retries": 5,
            "backoff": "exponential",
            "fallback": "queue_and_retry_later"
        },
        "invalid_input": {                          #   输入无效:让LLM修复
            "retry": True,
            "strategy": "fix_input_with_llm",
            "max_retries": 2,
            "fallback": "ask_user_for_clarification"
        },
        "service_unavailable": {                     #   服务不可用:线性退避
            "retry": True,
            "max_retries": 3,
            "backoff": "linear",
            "fallback": "use_alternative_tool"
        },
        "unexpected_result": {                      #   结果异常:验证后重试
            "retry": True,
            "strategy": "validate_and_retry",
            "max_retries": 2,
            "fallback": "report_to_user"
        }
    }

    def __init__(self):                             # 初始化
        self.circuit_breakers = {}                  #   熔断器集合
        self.tool_alternatives = {}                 #   替代工具表

    def register_alternative(self, tool_name: str, alternative: callable):
        """注册替代工具"""                           #   主工具挂了用备胎
        self.tool_alternatives[tool_name] = alternative

    async def execute_with_recovery(self, tool_name: str, tool_func: callable,
                                     *args, **kwargs) -> Dict:
        """带恢复策略的工具执行"""                    #   主入口:执行+重试+降级
        strategy = self.ERROR_STRATEGIES.get("service_unavailable")  # 默认策略
        last_error = None                            #   记录最后一次错误
        for attempt in range(strategy.get("max_retries", 3) + 1):  # 最多重试N次
            try:
                result = await tool_func(*args, **kwargs)  # 执行工具
                if self._is_valid_result(result):   #   验证结果
                    return {"success": True, "data": result, "attempts": attempt + 1}
                else:                                #   结果无效
                    last_error = ToolResultError("结果验证失败")
            except asyncio.TimeoutError:             #   超时
                last_error = ToolTimeoutError(f"{tool_name} 超时")
                strategy = self.ERROR_STRATEGIES["timeout"]  # 切换到超时策略
            except PermissionError:                  #   权限不足
                return await self._handle_permission_error(tool_name)  # 直接处理
            except Exception as e:                   #   其他异常
                last_error = e
            if attempt < strategy.get("max_retries", 3):  # 还能重试
                delay = self._calculate_backoff(attempt, strategy.get("backoff", "linear"))
                await asyncio.sleep(delay)          #   等待退避时间
        return await self._fallback(tool_name, last_error)  # 所有重试失败,走降级

    async def _fallback(self, tool_name: str, error: Exception) -> Dict:
        """执行降级策略"""                           #   替代工具->告知用户
        if tool_name in self.tool_alternatives:     #   有替代工具
            try:
                result = await self.tool_alternatives[tool_name]()  # 用备胎
                return {
                    "success": True, "data": result, "degraded": True,
                    "message": f"使用了替代工具,原工具错误:{str(error)}"
                }
            except Exception:                       #   备胎也挂了
                pass
        return {                                    #   最终降级:告知用户
            "success": False,
            "error": str(error),
            "user_message": f"抱歉,{tool_name} 功能暂时不可用,请稍后重试或联系人工客服。"
        }

    def _calculate_backoff(self, attempt: int, strategy: str) -> float:
        """计算退避时间"""                           #   指数或线性
        if strategy == "exponential":               #   指数退避
            return min(2 ** attempt, 30)            #     最大30秒
        return attempt * 2                           #   线性退避:2,4,6...

    def _is_valid_result(self, result: Any) -> bool:
        """验证结果有效性"""                         #   空值和错误都算无效
        if result is None:                          #   返回空
            return False
        if isinstance(result, dict) and result.get("error"):  # 返回错误
            return False
        return True                                 #   有效

class ToolTimeoutError(Exception): pass              # 超时异常
class ToolPermissionError(Exception): pass           # 权限异常
class ToolResultError(Exception): pass               # 结果异常

面试回答要点

  1. 错误分类:区分可重试错误(超时、限流)和不可重试错误(权限、参数错误)
  2. 退避策略:指数退避避免雪崩,添加随机抖动
  3. 降级方案:替代工具 -> 缓存结果 -> 告知用户,三级降级
  4. 熔断保护:连续失败 n 次后暂时跳过该工具(见 12.5 节的 CircuitBreaker

五、常见误区

  1. 误区一:面试时直接跳到实现细节。很多人拿到题目就开始写代码,但面试官想看的是你的思考过程。应该先用 SCALE 框架做场景分析、组件拆解,再讲架构设计,最后才到代码。

  2. 误区二:方案没有权衡。好的设计不是"完美方案",而是"在约束条件下的最优选择"。面试官追问"为什么不用 X 方案"时,要能说出 X 方案的缺点和当前方案的取舍。

  3. 误区三:RAG 优化只谈 embedding。很多人一提到 RAG 质量差就说"换更好的 embedding 模型",但实际上分块策略、查询改写、重排序的影响往往比 embedding 更大。

  4. 误区四:错误处理只做重试。有人对所有错误都无脑重试,但权限错误重试 100 次还是权限错误。必须区分可重试和不可重试错误,不可重试的直接走降级。

  5. 误区五:演进路径缺失。面试官常问"如果给你 3 个月怎么做到生产级"。如果你只讲 V1 方案不讲演进路径,面试官会认为你缺乏工程思维。V1 用规则引擎快速上线,V2 加 LLM+RAG,V3 做多 Agent 协作+自动学习。

六、本节小结

场景题核心考点关键思路
客服 Agent 设计系统设计、多轮对话、RAG意图分流 -> 知识检索 -> 安全审核 -> 人工兜底
输出一致性LLM 可控性、后处理结构化输出 + 验证层 + 低温度 + 事实核查
RAG 检索质量信息检索、向量搜索Query 改写 -> 混合检索 -> 重排序 -> 评估指标
工具调用失败错误处理、容错设计错误分类 -> 退避重试 -> 降级 -> 熔断 -> 告知用户

面试场景题是本章所有知识的"综合考"。客服 Agent 考的是 12.1 的架构设计,输出一致性考的是 12.5 的不确定性管理,RAG 优化考的是 12.3 的数据分析能力,工具调用失败考的是 12.5 的熔断降级。掌握了 SCALE 框架和这四道题的分析思路,你就能在面试中从容应对大多数 Agent 系统设计题。下一章我们将进入实战项目,把全书的知识融合到一个完整的 Agent 项目中,从设计到实现到部署,走一遍完整流程。