AI智能体应用开发面试题(2026-06-12 02:35)
【面试题】1. 你在做多智能体协作项目时,怎么避免"羊群效应"——多个Agent抢同一个工具或输出重复?
【标准答案】 核心思路是"角色分工+冲突仲裁"。
分工层面:每个Agent有明确的职责边界,比如专门负责搜索的只管搜索,负责写作的只管写作,物理上隔离工具调用权限,避免职责重叠。
协调层面:我一般会设计一个Orchestrator(编排器)Agent作为中枢,它负责拆解任务后,把子任务分发给专用Agent,最后汇总结果,而不是让Agent之间直接对等通信——对等通信在大模型里很容易变成"吵架"。
具体机制:任务分发时带上"独占锁"的语义,比如"你负责这个搜索任务,直到完成,其他人不能动";汇总阶段用去重逻辑,根据输出内容或语义指纹做相似度检测,把重复结果合并。
羊群效应的本质是缺乏中心调度,所以设计思路就是"让合适的人做合适的事,而不是所有人抢同一件事"。
【面试题】2. Dify的工作流编排里,如果某个节点失败了,怎么设计自动降级策略?
【标准答案】 Dify的工作流本身支持节点级别的错误处理,我一般分三层设计降级:
第一层:节点内重试。对不稳定节点(调用外部API、模型推理),配置3次指数退避重试,间隔10s/30s/90s,避免瞬时失败。
第二层:失败分支兜底。每个关键节点并联一个"降级节点",比如大模型生成失败时,自动切换到预设模板填充;搜索API超时时,切换到缓存结果或者返回"暂不可用"。
第三层:全局兜底。工作流最末端设置一个"默认回复"节点,无论前面哪步出错,最终用户拿到的是一个友好回复,而不是直接暴露错误。
设计原则是:降级不是隐藏问题,而是让系统在部分能力缺失时仍然可用,同时记录错误供后续排查。
【面试题】3. 1-3年经验的候选人在RAG系统里,怎么平衡"召回率"和"精确率"?
【标准答案】 核心矛盾是:召回低了漏答案,精确率低了噪音多。实操中我一般这么处理:
召回端:用混合检索——语义向量检索+关键词BM25同时跑,取并集或用RRF融合打分。向量化时选一个偏稠密的模型(哪怕牺牲一点精确率),比如text-embedding-3-small配合768维,比稀疏向量召回更全。
精确端:召回后加"重排序"(ReRanker),用Cohere或者LLM做二轮排序,把真正相关的Top-K提到最前面。提示词里明确要求"基于检索内容回答,不要依赖外部知识",减少模型幻觉带来的精确率下降。
一个经验:先保证召回够用(能答出来),再优化精确(答得准),因为漏答比噪音更致命。
【面试题】4. 面试官问"如果让你从0设计一个客服Agent,你的第一步是什么?"
【标准答案】 第一步是画清楚人机边界,不是直接写代码。
具体说,我先想清楚三件事:
- 哪些是规则性任务(查订单、退款政策、FAQ)——这些用工作流+知识库解决,不需要LLM参与,稳定可控。
- 哪些是真需要LLM理解的任务(复杂投诉、多轮对话意图判断)——这些才上Agent。
- 边界在哪——用户说什么话的时候,Agent应该转人工。
产出物是一张表:左边是用户问题类型,右边是处理方式(规则/Agent/转人工)。这张表定好了,后面搭框架才不会返工。
很多人一上来就搭LangChain链,结果搭完发现大部分问题其实用if-else就够了,这是经验不足最常见的问题。
【面试题】5. LangChain的LCEL链式调用里,RunnablePassthrough和RunnableParallel在什么场景用?怎么配合?
【标准答案】
RunnablePassthrough:透传输入,不做任何转换。用于把上游输入原封不动地传给下游,或者在链中间"插入"一个什么都不做的节点来保持数据流完整。
chain = prompt | model | output_parser
# 实际调用时,输入是 {"question": "xxx"}
# 如果想让输入透传到prompt,就用 RunnablePassthrough()RunnableParallel:并行执行多个任务,接收一个字典,返回一个字典。常用于"同时查知识库+查数据库+查配置"这种可以并行跑的步骤,然后再把结果合并给LLM。
combined = RunnableParallel(
context=retriever,
config=config_retriever,
history=memory
)
chain = combined | prompt | model配合场景:比如先RunnableParallel同时拿多个数据源,再用RunnablePassthrough把结果透传给下一步的prompt,这是LCEL里最常见的组合之一。
【面试题】6. 多模态Agent在处理"图文混排"文档时,最大的坑是什么?怎么解决?
【标准答案】 最大的坑是布局信息丢失。
大多数多模态模型把图片整体喂进去,但图文混排文档(PPT、网页、PDF报表)有很强的空间结构——文字在左、图片在右,表格跨两栏。如果直接OCR或者整体描述,会丢失"哪里说的是什么"这个关键信息。
解决方案:
- 版面分析在前:用专门的版面分析模型(或者PP-Structure这类工具)先把文档切分成阅读顺序,识别标题段落在哪、图片标题在哪。
- 区域裁剪:按照版面分析结果,把文档切成小块,每块单独做OCR或描述,保持局部上下文。
- 结构化输出:最终输出不是纯文本,而是一张结构化JSON,标注每个内容块的位置和类型,后续RAG检索时按位置权重排序。
一句话总结:多模态不是把图片直接扔给VLM就完了,前处理和版面理解才是决定效果的关键。
【面试题】7. 智能体的"记忆系统"怎么设计,才能让对话有连贯性又不会超出上下文限制?
【标准答案】 我一般用三层记忆架构,按时间由近及远:
第一层:工作记忆(Conversation Summary)。最近的3-5轮对话,用LLM摘要压缩成一段话,不是原文拼接。这样5轮对话从500字压到80字,上下文开销小。
第二层:会话记忆(Session Memory)。当前会话的完整记录,但做滑动窗口,比如保留最近20轮,超出的部分同样摘要压缩。
第三层:长期记忆(Long-term Memory)。持久化存储用户偏好、历史任务、关键结论。用向量数据库按语义检索,只在需要时召回,不需要全量塞进上下文。
关键原则:不是记忆越多越好,而是"按需召回"。每次对话开始前,用语义检索从长期记忆里捞出相关的几条,作为system prompt的一部分注入进去。
【面试题】8. 用CrewAI做多Agent项目时,如果任务A依赖任务B的结果,怎么用Task Dependencies正确配置?
【标准答案】 CrewAI的任务依赖配置很直接,用context参数指定依赖:
task_b = Task(
description="分析竞品数据",
agent=analyst,
expected_output="竞品对比表格"
)
task_a = Task(
description="撰写推广方案",
agent=writer,
expected_output="完整方案文档",
context=[task_b] # 关键:这里声明依赖task_b
)CrewAI的Crew在run的时候会自动等待task_b完成后,把它的输出作为context注入到task_a的prompt里,不需要手动传参。
常见踩坑点:很多人忘记在expected_output里写清楚输出格式,导致下游Agent拿到的是一堆废话没法用。所以expected_output要写得具体,比如"输出一张包含竞品名称、月活、价格三列的对比表格"。
【面试题】9. 你怎么理解"智能体的规划能力"?ReAct和Plan-and-Execute两种范式各适合什么场景?
【标准答案】
规划能力的本质:让模型不只是"见招拆招",而是能预判多步路径再执行。
ReAct范式:Think→Act→Observe循环,边做边想。适合任务路径不明确、环境反馈重要的场景,比如聊天机器人、动态搜索、工具组合探索。优点是灵活,缺点是步数不可控,容易在循环里打转。
Plan-and-Execute范式:先完整规划所有步骤,再按顺序执行。适合任务路径相对固定、步骤可预期的场景,比如数据清洗流水线、报告生成、批量处理任务。优点是可控可审计,缺点是规划错误会导致整条链失效。
我的选择习惯:ToB产品(客服、审批)用Plan-and-Execute,因为需要可解释可审计;ToC或者探索性场景用ReAct,灵活优先。
【面试题】10. 如果线上Agent响应变慢了,你怎么快速定位瓶颈是出在模型推理还是工具调用?
【标准答案】 快速定位的方法是打时间戳日志,每个环节单独计时:
Step1 [LLM推理] → 2.3s ✅ 正常
Step2 [工具选择] → 0.1s ✅ 正常
Step3 [知识库检索] → 8.7s ❌ 超时!
Step4 [结果生成] → 省略常见规律:
- 如果是LLM推理慢 → 看模型响应时间曲线,是否模型限速了,考虑换更快的模型或加缓存
- 如果是工具调用慢 → 优先检查网络延迟、API限速;如果工具是本地检索,看索引大小和硬件资源
- 如果是生成内容长但慢 → 检查是否向向量库塞了太多无关内容,导致检索+生成都变慢
最实用的做法:在代码里用time.time()对每个环节打日志,配合日志的trace_id串联请求,线上跑一天就能画出性能瓶颈的热力图,定位准确率很高。