侧边栏壁纸
  • 累计撰写 56 篇文章
  • 累计创建 5 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

LLM_应用开发面试题与参考答案

温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

LLM 应用开发面试题 & 参考答案

面试官:严察
日期:2026-06-02
面试阶段:基础知识 → 工程实战 → 开放场景


目录


阶段一:基础知识与核心概念

问题一:System Prompt 要素与指令遵循优化

题目: 一个好的 System Prompt 应该具备哪些要素?如果模型不按照你的指令执行,你会从哪些方向去排查和优化?

参考回答

优质 System Prompt 的六大要素

要素 说明
角色定位 明确身份、领域与职责
任务目标 写明核心工作与使用场景
约束边界 划定能做 / 禁止事项
输出规范 限定格式、语种、篇幅
示例参考 内置少量样例(Few-shot)
异常处理 信息缺失 / 超范围时的应答规则

模型不遵指令的排查优化方向

  1. 提示词本身: 关键规则前置、细化量化、精简长度、补充样例
  2. 上下文污染: 清空历史、防范用户输入覆盖系统指令(最容易被忽视)
  3. 推理参数: 降低 temperature、合理设置 top_p / max_tokens
  4. 模型选型: 能力不足则换大模型或领域微调模型
  5. 工程拆分: 复杂任务分多轮调用,降低单次指令的认知负荷

深挖点 Q&A

Q:Role Prompt 为什么有效?

本质上是为模型预设了输出的概率分布先验,压缩了解空间。当模型被赋予一个具体角色时,它在高维空间中的输出路径会被约束在与该角色相关的语义区域,减少了随机漂移。

Q:Few-shot 放 System Prompt 与放 User Message 有何不同?

放在 System Prompt 中权重更高,占据上下文头部位置(attention bias 偏好开头),但也占用宝贵的系统指令预算。放在 User Message 中更灵活,适合动态切换示例,但在长上下文中容易被中间内容淹没(Lost in the Middle)。


问题二:Embedding 模型选型与 Top-K 噪声处理

题目: 为知识库问答系统选择 Embedding 模型,你会考虑哪些关键指标?如果检索回的 Top-K 中混入大量不相关内容,怎么处理?

参考回答

Embedding 模型选型指标

  1. 向量维度: 高维度(1536/3072)表达力强但成本高;低维度(384/768)速度快,适合实时场景
  2. 评估指标: MTEB / BEIR 等公开 benchmark 得分
  3. 成本: API 调用费用 vs 本地部署成本
  4. 支持的 token 长度: 长文档需要大窗口模型
  5. 领域适配性: 通用模型 vs 领域微调模型
  6. 语言支持: 是否覆盖目标语种

Top-K 噪声处理方案

  • Reranker(重排序): 对检索结果做二次精排,大幅提升精度,是最直接有效的手段
  • Hybrid Search(混合检索): 关键词(BM25)+ 向量检索互补,覆盖语义和字面匹配的盲区
  • Chunk 调优: 根据文档类型实验最优切分粒度(大块噪声多,小块语义断)
  • Query 重写(Rewrite): 用户短查询表达模糊,先让 LLM 扩展 / 改写后再检索

深挖点 Q&A

Q:维度与召回率的关系是什么?

高维度(1536/3072)能捕获更细粒度的语义差异,精度理论上更高,但带来了更高的存储和计算成本,且在数据量不足时容易过拟合。低维度(384/768)适合对延迟敏感、数据量大的场景。选型需在精度、成本、延迟之间做 trade-off。

Q:Hybrid Search 中 BM25 和向量检索的权重如何配比?

没有通用最优值。实践中通常从 RRF(Reciprocal Rank Fusion)的默认 k=60 开始,或者用 0.5:0.5 等权,然后通过线上 A/B 测试或离线评测调整。推荐用 Auto-weight 方式:在检索结果上训练一个轻量级权重模型,让数据决定配比。


问题三:RAG 幻觉的检索侧与生成侧缓解策略

题目: RAG 系统中产生幻觉的主要原因有哪些?在检索侧和生成侧分别如何缓解?

参考回答

幻觉本质: 检索内容与模型生成之间的对齐失败。

检索侧缓解方案

方案 说明
混合检索 BM25 + 向量检索,互补盲区
重排序 Reranker 二次精排 Top-K
阈值过滤 设置相似度阈值,低于阈值的宁可不要
Chunk 调优 合适的粒度 + 重叠切片

生成侧缓解方案

方案 说明
强制引用 要求模型逐句标注来源 Chunk ID
自检 生成内容后模型自我验证
低置信拒绝 置信度低于阈值时拒答
LLM-as-Judge 引入评判器做二次验证

核心原则: 宁可承认不知道,也不输出未经检索支撑的"合理编造"。

强制引用的落地方式: 在 Prompt 中要求模型逐句标注来源 chunk ID,后处理脚本检查引用对应关系。若某句无引用或引用并非来自检索内容,直接截断或打回重写。

深挖点 Q&A

Q:怎么用代码实现"强制引用"的后处理?

大致流程:解析 LLM 输出中 [来源: chunk-xxx] 格式的标注 → 提取所有 chunk ID → 与本轮检索返回的 chunk ID 集合取交集 → 未匹配到的句子打标删除,或在返回给用户前触发重新生成。

Q:LLM-as-Judge 的 prompt 怎么写才不偏?

关键原则:评判器需使用与生成器不同的 Prompt 模板,且评判标准要量化(打分制 + 具体扣分项),避免模糊的"是否符合事实"。实践中可以让评判器只看检索片段和生成的对应句子,不看完整对话,减少位置偏差。


阶段二:工程实战与架构设计

问题四:多轮对话 Agent 架构拆解

题目: 设计一个能自主调用外部工具的 Agent,核心模块有哪些?各模块的职责是什么?

参考回答

核心模块 职责
模型适配器 对接不同 LLM 提供商,统一调用接口,处理 token 限流和重试
推理 / 规划模块 决策引擎 — 选择 ReAct、Plan-and-Execute 或混合策略
上下文管理 维护对话窗口,管理截断策略,防止上下文溢出
记忆管理 短期(对话窗口)vs 长期(持久化存储),筛选关键信息写回
工具管理与执行 工具注册、参数注入、结果解析、异常处理
感知层 解析用户意图,识别关键实体和约束条件

深挖点 Q&A

Q:长期记忆怎么写回?写哪些?

筛选标准:涉及用户偏好、已完成的跨轮任务状态、明确的决策结果。实现常用方案是每次对话结束时让 LLM 对当前对话做摘要,提取该记住的信息,然后写入向量库或 KV 存储。核心原则是不要全盘存,只存摘要和关键事实

Q:上下文窗口满了怎么办?

常见策略:

  • 滑动窗口: 保留最近的 N 轮对话
  • 摘要压缩: 将历史对话压缩为摘要,放回窗口顶部
  • 分层检索: 窗口内仅保留当前轮强相关的历史消息,其余放入外部记忆

问题五:ReAct vs Plan-and-Execute 策略选择

题目: 面对复杂任务,ReAct(边想边做)和 Plan-and-Execute(先计划再执行)如何选择?

参考回答

对比维度 ReAct Plan-and-Execute
流程 循环:思考→行动→观察→再思考 先规划出 DAG,再依次/并行执行
灵活性 高,每步都能根据环境反馈临时转向 低,计划一旦定下来不易中途切换
LLM 调用量 多(每步都要调) 少(规划一次,后续按图执行)
适合场景 开放探索型、信息不确定的任务 流程固定、依赖明确的管道式任务
容错/可恢复 天然支持:观察报错→调整策略 需额外编排重试/回滚逻辑
举例 「帮我规划周末杭州两日游」 「查 Q1 数据→画图→发邮件」

决策原则:

  • 任务结构已知 → Plan-and-Execute
  • 结果不确定、需要探索 → ReAct
  • 两者不互斥 → 外层 Plan 搭骨架,内层每个子任务用 ReAct

生产最佳实践(混搭策略): 先用 Plan 编排 DAG,每个子节点内部用 ReAct 做局部决策。这样既有全局的确定性,又有局部的灵活性。

深挖点 Q&A

Q:混搭策略中,Plan 的执行器怎么感知子任务的中间状态?

常见方案是维护一个全局上下文对象(Shared Context / Blackboard),每个子节点执行后将中间结果写入,后续节点按需读取。Plan 编排器负责 DAG 的状态流转(待执行 → 执行中 → 成功 / 失败),失败时可触发重试或重新规划。


问题六:LangChain vs LlamaIndex 框架选型

题目: 从开发效率、可调试性、Agent 支持、生产维护成本出发,LangChain 和 LlamaIndex 怎么选?

参考回答

对比维度 LangChain LlamaIndex
强项 Agent / Chain / 工具编排 RAG / 数据索引 / 检索
生态丰富度 高,集成最多 中,聚焦检索场景
开发效率 初期上手慢(抽象层多),熟悉后强大 初期上手快,开箱即用
可调试性 LCEL 回调机制完善,但问题定位需要经验 链路清晰,调试相对简单
Agent 支持 ✅ 最强,Tool/Function Calling 原生支持 🔶 支持但不如 LangChain 成熟
生产维护 版本迭代快,API 变动频繁,需锁版本 版本稳定,维护量小
选型建议 系统复杂、Agent 多、需深度定制 以 RAG 为核心、检索链路重的场景

一句话原则: 做 Agent 选 LangChain,做 RAG 选 LlamaIndex,两者也可以混用。

深挖点 Q&A

Q:LangChain 版本迭代快导致生产维护难,具体怎么应对?

  • 锁大版本:poetrypip freeze 锁定到具体小版本,不随意升级
  • 封装抽象层: 对 LangChain 的调用做一层薄封装(如 LLMServiceToolExecutor),业务代码不直接依赖 LangChain 内部类
  • 跟踪 Deprecation 通知: 关注官方 changelog,有计划地批量升级
  • 关键模块自己实现: 如回调链路、记忆管理等对稳定性要求高的模块,可以考虑自己写

阶段三:开放场景题与故障排查

问题七:RAG 客服系统答案不一致排查

题目: RAG 客服问答系统上线一周后,用户满意度下降 15%,发现同一问题答案不一致、有时对有时错。排查路径和修复方案?

参考回答

Step 1 — 快速止血(P0)

动作 说明
黄金答案缓存 将该高频问题的标准答案通过缓存/规则直接返回,绕过 RAG 流程
临时人工兜底 关键业务问题暂时转人工

Step 2 — 链路排查

① 检索层:召回结果是否稳定?

  • 取该 query 连续调用检索接口 20-30 次
  • 记录每次返回的 Top-K 文档 ID 和排序
  • 计算 Jaccard 相似度,若波动 > 10%,检索层是主因
可能根因 修复方案
向量索引正在重建或实时更新,分片数据不一致 确保全量重建时新旧索引切换是原子的
多副本间数据未完全同步 对检索层做 sticky session 绑定,或统一数据版本
Embedding 模型版本不一致(新旧混用) 统一模型版本
检索策略含随机性 去掉随机采样,固定随机种子
短期内对该高频问题做查询结果缓存

② 知识库层:是否存在矛盾或过时内容?

  • 拉出多次召回的文档集合,人工审查
  • 检查是否有相互矛盾的文档共存
可能根因 修复方案
旧文档未下架或未标记失效 建立文档生效/失效时间标记,检索时过滤过期内容
切片更新遗漏 切片与源文档建立强关联,文档更新时原子性重切
多数据源信息冲突 增加知识审核流程,冲突内容告警

③ Prompt 拼接层:上下文是否一致?

  • 记录线上完整 Prompt,对比同一问题的多次请求
  • 检查是否有随机元素 / 时间戳 / 动态系统指令
可能根因 修复方案
Prompt 中注入了当前时间、轮次等动态变量 该高频问题使用固定 Prompt 模板,去除动态变量
历史截断策略不稳定 统一上下文窗口截断逻辑
Prompt A/B 测试 该问题不参与实验

④ LLM 生成层:模型本身是否稳定?

  • 用相同 Prompt 调用模型 10 次,观察输出
  • 检查 temperaturetop_p 设置
可能根因 修复方案
temperature > 0.3 导致随机性强 对该请求设 temperature=0
模型灰度升级,新旧并存 确保同一场景打到同一模型版本
不同 endpoint 行为差异 统一 endpoint

Step 3 — 系统性修复(防复发)

措施 说明
FAQ 黄金答案 高频问题走意图识别直接返回标准答案
全链路缓存 Query 归一化后查缓存,知识库更新时主动失效
一致性监控 定期对标杆 Query 做探测,检测答案分布的熵值,异常告警
知识库治理 文档标注生效时间、来源;更新走灰度→全量流程,切原子化

排查优先级矩阵

优先级 排查层 核心问题 动作
P0 止血 用户体验持续受损 缓存标准答案 / 转人工
P1 检索层 召回结果波动 对比多次召回结果
P1 LLM 层 temperature/模型版本 检查生成参数
P2 知识库 矛盾内容共存 审查召回文档集
P2 Prompt 动态变量干扰 检查拼接后完整 Prompt

深挖点 Q&A

Q:怎么在线上拿到每次请求的召回文档 ID 和完整 Prompt?没有日志怎么办?

这是考察可观测性建设。如果线上没有日志,排查难度极大。标准做法:

  • OpenTelemetry 做全链路 tracing,每个请求带一个 trace_id,贯穿 query→检索→rerank→生成→输出
  • Agent 框架层暴露中间结果回调(LangChain 的 CallbackHandler 或 LlamaIndex 的 EventHandler
  • 如果没有 tracing 设施,现场加日志重新上线是唯一选择。这也说明了一个关键教训:可观测性是 RAG 系统的第一基础设施,不是可选功能

Q:temperature=0 仍不一致,还能是什么原因?

这是一个进阶追问。可能原因:

  • GPU 计算精度: float16 vs float32、不同 GPU 架构的微小差异
  • vLLM prefix caching: 缓存命中状态不同导致推理路径不同
  • 批次内 padding: batch 内其他请求的 padding 长度影响计算图
  • 模型提供商的负载均衡: 不同后端节点的模型权重微小差异

问题八:第三方 API 不稳定下的容错与降级策略

题目: Agent 调用第三方天气 API 经常超时或 5xx,不能换提供商。设计 Function Calling 的容错与降级策略。

参考回答

1. 超时策略(双层异步超时)

层级 配置 说明
IO 层(Socket) 连接超时 3s,读取超时 5s 防止 socket 挂起
Agent 调度层 工具调用整体超时 8s 独立上下文,超时后主线程快速失败,不被阻塞

关键点:超时链路必须对齐。 Agent 框架超时 > HTTP 超时。如果 Agent 超时设 10s 但 HTTP 读超时设 15s,HTTP 永远走不完但 Agent 先超时了,中间线程一直悬空。

2. 重试机制

  • 库选型: Tenacity(Python),带随机抖动的指数退避(1s → 2s),最多 3 次
  • 重试条件: 仅对 5xx、429 及网络级错误(ConnectionError、Timeout)
  • 不重试: 4xx 客户端错误(业务拒绝)
  • 安全阀: 引入重试预算(Retry Budget),每分钟最多 N 次重试,超出后直接降级,防止重试风暴击穿服务
  • 熔断器: 与重试分层 — 先查熔断器状态,已熔断则直接降级;未熔断才进重试

3. 降级方案(多级缓存 + 结构化 Fallback)

第一级降级 — 缓存数据(Redis):
  TTL=5min 的缓存
  返回数据 + header: X-Cache: HIT
  附标注:"数据来自 12:34 缓存,非实时"

第二级降级 — 无缓存可用:
  返回结构化 JSON:
  {
    "status": "fallback",
    "message": "天气服务暂时不可用",
    "recommendation": "请稍后再试或选择其他日期"
  }

核心原则:降级输出的 schema 与正常输出保持一致,下游解析逻辑无需特殊处理。

严禁行为: 不允许 LLM 说"根据最新数据"而实际返回的是缓存。降级时通过 is_fallback: true 标记让 LLM 调整措辞。

4. 用户反馈

策略
前端 定时器在等待期流式展示"查询中 / 响应慢"等状态文案
后端 降级状态作为 ToolMessage 传给 LLM,配合 System Prompt 约束模型输出透明提示
监控 Prometheus 埋点:weather_api_latency_seconds{status="success|timeout|fallback"} 三个标签,分别设置告警阈值

深挖点 Q&A

Q:Redis 缓存失效策略怎么选?如果用户查的城市都不同,缓存命中率低怎么办?

  • 选型: Cache-Aside(旁路缓存),TTL 过期自动失效。热门城市预缓存(手动预热 Top 100 城市)。
  • 低命中率应对: 如果查询分布极度离散,缓存收益有限,应倒过来优化 API 本身的稳定性(如增加 provider 冗余),而不是在缓存上继续加码。

Q:熔断器打开期间有用户一定要查天气,怎么办?

区分场景:

  • 非强实时场景: 返回陈旧缓存 + 告知数据时间
  • 强实时场景(如航班调度): 保留手动刷新入口,后台真正触发请求时绕过熔断器(用单独的 bypass 通道)

Q:怎么保证 LLM 在降级时不自己编数据?有没有翻车经验?

一个典型翻车案例:降级时返回的 JSON 被 LLM 忽略,LLM 自行编造了"25°C,晴"的回答。修复方案:

  • 在 ToolMessage 中加入 "override_user_message": true 标记,System Prompt 中要求如果看到此标记,直接输出 recommendation 字段内容,不自行生成
  • 或者在 Agent 层面做规则拦截:如果输出包含天气数据但工具返回是 fallback,拒绝输出并返回预设文案

问题九:长 System Prompt 的代码质量与重构

题目: 初级工程师在 System Prompt 中硬编码 2000 字业务规则,要求 LLM 严格遵循。有什么问题?怎么重构?

参考回答

三个核心问题

问题 解释
Lost in the Middle LLM 对长文本中间段的注意力最弱。2000 字规则,中间部分几乎等于没写
Token 成本浪费 日均万次调用 × 1500 token × 30 天,仅规则部分烧掉 ~4500 万 token,按常见定价约数百到上千元
改规则 = 改代码 业务更新频繁,每次改规则要走 CI/CD 上线,迭代周期长、风险高

重构方案

Step 1 — 规则分类

类别 内容 存放位置
A 角色身份 + 行为边界 保留在 System Prompt(≤ 200 字)
B 具体业务规则(条目化) 搬进知识库 / 向量库,RAG 按需检索
C 条件判断逻辑(if-else) 搬进 Function Calling / 代码逻辑

Step 2 — System Prompt 精简后的样子

你是一个客服助手。回答时必须依据知识库中的最新规则。
如果规则未覆盖,回答"我暂时没有相关信息"。

Step 3 — 运行效果对比

修改前:
  System Prompt: 2000 字规则 + 角色 + 格式
  每次请求: 2000 token 固定开销
  改规则: 走 CI/CD 上线流程

修改后:
  System Prompt: 150 字(角色 + 约束)
  每次请求: 按需检索注入 ~200-300 token
  改规则: 更新知识库,无需上线

核心理念: Prompt 是胶水,不是数据库。

深挖点 Q&A

Q:RAG 按需注入规则,怎么保证每次能召到对的规则?如果规则有优先级(新政策覆盖旧政策),相似度检索能处理好吗?

相似度检索本身没有优先级概念,它只衡量语义相近程度。要处理规则优先级,需要:

  1. 元数据过滤: 每条规则带 effective_starteffective_endpriority 字段。检索时先过滤生效时间范围内的规则,再按优先级排序
  2. 检索 + 规则引擎: RAG 只做粗筛,具体的优先级冲突由后置规则引擎(如简单的 if-else 链或决策表)解决
  3. 显式版本标记: 在规则内容中标记版本号,Prompt 中要求 LLM 如发现同一问题的多个版本,取版本号最高的

Q:如果规则总长度超过上下文窗口的 60%,怎么处理?

  • 分层检索: 先检索规则摘要(summary index),再根据摘要命中结果检索详细规则
  • 滑窗策略: 一次只注入当前轮任务相关的规则子集,不一次性全放
  • 摘要压缩: 对规则做 LLM 摘要,压缩到关键要点的 bullet list

Q:规则版本管理怎么做?线上两套规则同时生效(灰度实验),RAG 怎么区分?

  • 规则数据带实验标签: 每条规则携带 experiment_group: "control" | "treatment" 字段
  • 用户分桶 ID 传入检索层: 检索时根据用户 ID 的 hash 值决定过滤哪个实验组的规则
  • 版本历史不可变: 规则更新不走修改,走新增 + 标记版本号,旧版本只标记过期不下架,保证可追溯

面试总结

评分矩阵

维度 评价
基础理论 🟢 扎实,Prompt 原理、Embedding 选型、RAG 链路认知清晰
架构设计 🟢 有系统思维,模块拆解、缓存策略、容错降级都落到了具体方案
工程实战 🟢 明显有生产经验,线上排查路径完整,有止血意识
带队能力 🟢 有导师意识,懂得让新人自己发现问题
表达结构 🟢 结构化表达好,擅先用框架再填充细节

可加强的方向

  1. 可观测性落地: 排查时"如何拿到数据"有时比"拿什么数据"更难,建议加强对全链路 Tracing 和日志体系的认知
  2. 成本量化意识: 已有 token 成本感知,可以强化单位换算和 ROI 表达(如"日均万次调用 × 每请求节省 X token = 每月省 Y 元")
  3. 混搭策略的边界判断: ReAct vs Plan-and-Execute 的选型如果能给出量化阈值(如"子任务数 > 5 且依赖明确 → Plan"),会更可信

一句话总结

Senior 级别。有实战深度,有架构视野,有带队经验。

0

评论区