Agent/AI工程 面试题


1. RAG 核心流程与关键优化

题目: 请描述一个完整 RAG(检索增强生成)系统的核心流程,以及在每个环节上有哪些关键的优化点?

追问1:RAG 的”检索”和”生成”两个环节是如何衔接的?为什么说检索质量决定了 RAG 的上限? 追问2:在多轮对话场景下,RAG 的检索查询应该如何构造?直接拿用户最后一句话去检索有什么问题?

💡 答案:

主问题: RAG 系统的核心流程分为离线阶段和在线阶段。离线阶段处理文档:首先是文档解析和分块(Chunking),将文档按段落或语义边界切分,块的粒度直接影响检索效果——太大检索不准、太小语义不完整。然后是向量化(Embedding),用 Embedding 模型将文本块转为向量存入向量数据库。在线阶段处理用户请求:用户提问先做 Query 处理(可能包括改写、扩展、多轮上下文拼接),然后向量化后在向量库中检索 Top-K 相似文档块,最后将检索到的文档块作为上下文拼接进 Prompt 发给大模型生成回答。

各环节的优化点:文档处理阶段,分块策略可以按固定大小分、按语义段落分,也可以用专门的分块模型比如根据句子间相似度的断点来判断”该不该在这里切”。向量化阶段,可以微调 Embedding 模型让它更好理解领域术语——通用模型对垂直领域的专业名词向量化效果往往不好。检索阶段,除了单纯的向量相似度检索,可以结合关键词检索(BM25)做混合检索,弥补向量检索对精确关键词召回能力偏弱的缺陷。生成阶段,可以在 Prompt 中要求模型严格基于检索结果回答,对于检索结果无法覆盖的问题明确说不清楚而不是”编造”。

追问1: 检索和生成通过 Prompt 上下文衔接。检索召回的相关文档块被拼接到 Prompt 的”上下文”区域,模型在生成时基于这些上下文给出回答。检索质量决定 RAG 上限的原因是:大模型只能基于你喂给它的上下文来生成答案,如果检索阶段漏掉了关键文档块(召回率低)或者召回了大量不相关内容(精准度低),上下文里就没有正确的信息,大模型再强大也只能”无中生有”地编造答案。这就是 RAG 领域常说的”Garbage In, Garbage Out”。实践中很多 RAG 效果不好的问题,根源不在生成端而在检索端——Embedding 模型不够好、分块粒度不合理、检索策略单一等等。

追问2: 多轮对话场景下直接用最后一句话检索几乎是必然失败的。用户的日常对话包含大量省略和指代——第一轮问”Spring 的循环依赖怎么解决?“,第二轮问”那它有什么局限性?“,这里的”它”指的是什么?如果没有上下文,向量检索会匹配到完全无关的内容。正确的做法是对多轮 Query 做上下文补全,通常用一个小模型或直接让大模型基于对话历史将”那它有什么局限性?“重写为”Spring 循环依赖解决方案有什么局限性?“,然后再用补全后的 Query 去检索。这就是 Query Rewriting(查询改写),是多轮 RAG 不可或缺的一环。更高级的做法还包括 Query Decomposition(将一个复杂问题拆分为多个子问题分别检索再合并结果)、Step-Back Prompting(先问更宏观的问题再逐步聚焦)。

📌 易错点 / 加分项:

  • 能区分”语义检索”和”关键词检索”各自擅长的场景:语义检索擅长理解意图但可能漏掉精确术语,关键词检索精确但召回窄
  • 提到 Re-ranking(用 Cross-Encoder 对检索结果重新排序)是提升 RAG 效果的高性价比优化点
  • 了解 GraphRAG(知识图谱 + RAG)在回答全局性问题时优于传统 RAG

2. LangChain 核心架构与 Chain 机制

题目: LangChain 的核心设计理念是什么?Chain 和 Agent 在 LangChain 中的定位有什么本质区别?

追问1:LangChain Expression Language(LCEL)解决了什么问题?没有 LCEL 之前 LangChain 的 Chain 有什么痛点? 追问2:LangChain 的 Memory 模块在 Web 服务中如何处理多用户?如果需要把 Memory 持久化到 Redis 怎么做?

💡 答案:

主问题: LangChain 的核心设计理念是”将 LLM 应用视为多个可组合的模块串联”——把大模型的能力与外部数据、工具、记忆等组件连接起来,形成完整的 AI 应用。其架构分为五大模块:Model I/O(模型交互)、Retrieval(检索增强)、Chains(组件编排)、Agents(智能决策)、Memory(对话记忆)。Chain 和 Agent 的本质区别在于”控制流的决定者不同”。Chain 是确定性的执行流程——开发者预先定义好”先调 A、再调 B、最后调 C”的执行顺序,适合已知业务逻辑的场景,比如”读取文档 → 切片 → Embedding → 向量检索 → 拼接上下文 → 调 LLM 生成答案”,每一步是固定的。Agent 是自主决策的——开发者定义一组 Tool,Agent 自己根据用户的请求和当前状态决定”该调用哪个 Tool”、“什么时候该停止”,循环决策直到问题解决。Agent 本质上是一个”LLM 驱动决策循环”,在每一步由 LLM 决定 nextAction,而 Chain 是静态 DAG 图。

追问1: LCEL 是 LangChain 在 0.1.x 版本引入的表达语言,核心解决的问题是在没有它之前 Chain 的”组合方式不透明”。旧版 Chain 通过 SequentialChainLLMChain 等类来串联,但组合内部的 prompt 传递、callback 流、异步支持、流式输出等行为都是由 Chain 内部实现的黑盒——组合出不透明的”洋葱皮”,调试困难。LCEL 通过 | 管道操作符和 Runnable 协议,将一个复杂 Chain 表达为 prompt | model | output_parser 这样的声明式管道。优点:一是内部行为透明——每一步的 input/output 可以轻易 trace;二是自动支持流式输出——每个 Runnable 节点决定是否要 stream,LCEL 自动串联整个流的传递;三是统一的 callback 和 observability——所有节点共享同一套 Callback 系统。这就相当于从”面向黑盒组件”到”面向协议组合”的转变。

追问2: Memory 模块在 Web 服务的多用户场景下需要”按用户隔离”——每个用户的对话历史(session)都应该是独立的,不能串在一起。LangChain 的 Memory 默认是进程内存储——所有聊天记录放在一个 Python dict 里,这在 Web 服务中会产生严重问题:不同用户的对话历史混在一起(只要 memory 实例是单例);服务重启后所有对话历史丢失。解决方式是:为每个请求传入 sessionId,Memory 的 load_memory_variables 方法接收 sessionId 参数,底层从外部存储(如 Redis)按 sessionId 读写对话历史。持久化到 Redis 的方案:使用 RedisChatMessageHistory 类——配置 Redis 连接后,每次对话结束调用 save_context 把用户消息和 AI 回复追加到 Redis 的 list 中(key 为 session:<sessionId>:history),重启不会丢失。同时需要设定消息上限和过期时间防止 Redis 被吃满。

📌 易错点 / 加分项:

  • Agent 不是免费的——每一步决策都是 LLM 调用,成本远高于 Chain,能用 Chain 的不要用 Agent
  • LCEL 的 | 操作符底层是 RunnableSequence,不是简单的管道,里面包含错误传播和 schema 适配
  • Memory 在 multi-turn RAG 中常用于自动生成包含上下文的 Query Rewriting

3. MCP 协议的设计目标与工作模式

题目: 什么是 MCP(Model Context Protocol)?它解决了 AI 应用中什么核心问题?

追问1:MCP 和 Tool Calling(Function Calling)是什么关系?它不是和 Tool Calling 重复了吗? 追问2:MCP 的资源(Resource)、工具(Tool)、提示(Prompt)三个原语的设计动机分别是什么?

💡 答案:

主问题: MCP 是 Anthropic 提出的一个开放协议标准,核心目标是解决 AI 应用与外部工具和数据源之间的连接标准化问题。在没有 MCP 之前,每接入一个外部系统(数据库、文件系统、GitHub API、Slack 等),都需要为每个 AI 平台(Claude、ChatGPT、Copilot 等)单独编写一套连接代码和适配层——N 个平台 × M 个工具的矩阵集成成本非常高。MCP 定义了一套标准的 Client-Server 协议:MCP Server 负责暴露数据源和工具能力,MCP Client 负责将 Server 暴露的能力注册到 AI 应用中。通过这套协议,只需要为每个工具编写一个 MCP Server,所有支持 MCP 的 AI 客户端都可以直接调用,实现了”编写一次,到处运行”的集成模式。MCP 采用 JSON-RPC 2.0 作为传输协议,支持 stdio 和 SSE/HTTP 两种方式。

追问1: MCP 和 Tool Calling 不是重复关系,而是解决不同层面的问题。Tool Calling 是”AI 模型如何调用一个函数”的问题——它定义了函数声明(JSON Schema 描述函数签名)和调用约定(模型输出一个 function call,执行后把结果返回给模型)。但 Tool Calling 没有定义”这个函数的实现怎么注册进来”、“这个工具需要什么连接信息”、“工具的生命周期怎么管理”——这些都是模型不知道的工程细节。MCP 解决的是”工具如何被发现、如何被管理和暴露给 AI 应用”的问题。具体来说:一个 MCP Server 注册进来后,MCP Client 通过 tools/list 获取它暴露的所有工具定义(name、description、inputSchema),然后将这些工具定义上报给 AI 模型,AI 模型通过 Tool Calling 决定调用哪个工具,MCP Client 再将调用请求通过 MCP 协议发给 Server 执行。所以 MCP 是 Tool Calling 的下游基础设施——它让 Tool Calling 用的工具可以来自不同供应商、不同环境,而不需要硬编码在应用中。

追问2: 三个原语的划分对应 AI 与外部世界交互的三个维度。Tool(工具)代表”AI 可以执行的操作”——如发送邮件、查询数据库、创建 issue。它需要 AI 模型理解输入参数、推理调用时机,是 Agent 最核心的能力载体。Resource(资源)代表”AI 可以读取的上下文”——如文件内容、数据库 schema 描述、用户文档。与 Tool 的区别在于 Resource 不要求 AI 决定”什么时候该调用”——它是 passively consumed 的上下文,客户端通常提前拉取并注入到系统提示词中。Prompt(提示模板)代表”可复用的交互模式”——如标准化的代码审查模板、commit message 生成模板。它为常见任务预先定义好 prompt 结构,减少用户重复输入。三者合在一起覆盖了 AI 应用的完整交互场景:给 AI 提供上下文(Resource),让 AI 使用能力(Tool),以及标准化交互方式(Prompt)。

📌 易错点 / 加分项:

  • MCP Server 的 stdio 和 HTTP 传输选择——stdio 适合本地工具(如操作文件系统),HTTP 适合远程服务(如访问公司内网 API)
  • MCP 的安全性:Server 的权限范围由 Client 的沙箱控制,Server 本身不知道最终用户是谁
  • MCP 与 LangChain/AutoGen 不是竞争关系——它是底层协议,可以被这些框架集成

4. RAG 评估与检索质量优化

题目: 你会如何评估一个 RAG 系统的效果?有哪些关键指标?

追问1:向量检索中 HNSW 算法为什么比暴力搜索快?它的分层结构带来什么优势? 追问2:RAG 的 Chunking 策略对检索效果影响很大——你会尝试哪几种分块方式?语义分块比固定大小分块有什么优势?

💡 答案:

主问题: RAG 评估分为检索评估和生成评估两个层面。检索评估的核心指标:召回率(所有相关文档中多少被检索回来了?丢失一个关键文档可能导致模型无法回答)、精准率(检索回来的文档中多少是真正相关的?无关文档占用上下文窗口、浪费 token 且可能误导模型)、MRR(Mean Reciprocal Rank——正确答案第一次出现在结果中的排名越靠前越好)、nDCG(归一化折扣累积增益——不仅看相关文档是否在结果中,还看它们的排序位置)。生成评估的核心指标:忠实度(生成的答案是否严格基于检索结果,而不是模型”编造”——可以用另一个 LLM 评测或人工抽样)、答案相关性(答案是否真正回答了用户的问题)、上下文利用率(模型是否充分利用了检索到的上下文)。

评估数据集需要构造三个维度:query(用户问题)、相关文档(ground truth——哪些文档应该被检索到)、参考答案(ground truth——理想答案应该是什么)。可以用人工标注,也可以用小模型生成初步的标注数据集再人工修正。

追问1: HNSW 算法的核心思想是”构建多层图结构”。最底层是完整的图(包含所有节点),向上每层的节点量指数减少(类似跳表)。检索时从顶层(节点最少)开始,做贪心搜索找到最近节点,然后逐层向下、到更密集的层中做更精细的搜索。这样每一层只搜索少量节点,避免全图搜索。到达最底层后,再在完整的图中做精细搜索。这种设计的本质是”用图的跳表结构代替全图搜索”,搜索复杂度从 O(n) 暴力搜索降到 O(log n)。另一个优势是 HNSW 支持动态插入新节点(不需要重建索引),这对于频繁更新的知识库很重要。代价是内存占用高——需要存储多层图结构,这个占用比暴力搜索大得多。

追问2: 分块策略至少有五种。固定大小分块:按 token 数均匀切分(如 256 token 一块),通常会设一定的 overlap(如 20 token)防止语义被切成两半。句子分块:按句号、换行等自然分隔符切分,保证每个 chunk 是一个完整句子。段落分块:以段落为边界。语义分块:用一个小模型计算相邻句子之间的 embedding 相似度,通过相似度的”断崖下降”来找出语义的自然分界点。层级分块:把文档按标题层级拆成树形结构,检索时可以定位到更精确的章节。

语义分块相比固定大小分块的最大优势:一个 chunk 内的文本是语义相关的,不会出现”前半段讲 Spring 依赖注入、后半段讲 JVM 类加载”这种割裂。当用户提问时,检索到的 chunk 语义完整、回答质量更高。而且语义分块更接近人类阅读的”自然段落”,上下文也更容易被模型理解。代价是需要额外的分块模型调用,但这可以离线完成一次写入。

📌 易错点 / 加分项:

  • RAGAS 框架是目前评估 RAG 的主流工具——面试时提到说明关注了行业实践
  • HNSW 的 M 参数(每层连接的邻居数)直接影响搜索精度和内存占用的 trade-off
  • 混合检索(BM25 + Dense Vector)在很多 benchmark 上比单纯向量检索有显著效果提升

5. Agent 的 Function Calling 机制

题目: Agent 的 Function Calling 是如何工作的?从模型如何定义工具到实际调用执行,完整描述这个流程。

追问1:当 Agent 同时有 20 个工具可用时,如何保证模型选择正确的工具?工具描述有什么最佳实践? 追问2:Agent 执行一个工具后,返回的结果很大(比如数据库查询返回 1 万条记录),如何处理?

💡 答案:

主问题: Function Calling 的完整流程分四步。第一步是工具定义:开发者在调用模型时,在请求中附带一个 tools 参数,用 JSON Schema 描述每个函数——包括名称、自然语言描述、参数类型和描述(必填/选填、枚举值、默认值等)。第二步是模型推理:模型结合用户输入和工具描述,决定是否需要调用工具、调用哪个工具、传什么参数。如果决定调用,模型输出 tool_calls 数组——包含 function.namefunction.arguments(JSON 字符串)。第三步是由开发者执行实际调用:应用程序解析模型的 tool_calls,根据 name 和 arguments 执行对应函数(如查询数据库、调用第三方 API),获取返回值。第四步是结果回传:将函数返回值以 tool role 消息的形式追加到对话历史中,再次调用模型,模型根据返回结果生成最终回答。注意这里模型只做决策不做执行——真正的函数调用是发生在 ChatGPT/Claude 服务器之外的,由你的应用代码执行。

追问1: 工具量增多后面临的核心问题是模型的注意力被稀释——20 个工具的 JSON Schema 描述会占用大量上下文窗口,而且模型可能在相似功能的工具间犯错。最佳实践几个关键点:一是工具描述和参数描述要像写产品需求一样写——不能写”订单 id”要写”数据库 orders 表的主键,格式为 ord_YYYYMMDD_xxxxx”;二要避免工具间的语义重叠——一个工具修改订单、一个工具更新订单、一个工具编辑订单会让模型困惑;三是用”服务边界”组织工具——不相关的业务工具分批注册而不是一次性全量;四是参数用枚举限制可选值——参数 action: string 不如 action: "create" | "delete" | "update" 好。工程上也可以用 RAG 的思想——先根据用户意图从工具库中检索最相关的一批工具再注册进去。

追问2: 大结果的核心问题是上下文窗口和成本——1 万条记录塞进下一轮请求不仅 token 爆炸,模型在这么多噪音中也很难提取有效信息。处理方案:一是做结果过滤和截断——只保留前 N 条或按某些条件过滤,如果数据量还是太大,进行统计聚合(如 COUNT、SUM、DISTINCT 分布等)再返回概要。二是降级策略——如果返回行数超过阈值,不直接返回原始数据而是返回”查询结果有 10023 行,以下为前 10 行预览 ⋯ 你可以要求更精准的过滤条件”。三是多步交互——让 Agent 先总结查询结果,判断是否需要进一步缩小范围,再进行第二次查询。四是如果确实需要处理海量数据,让工具处理后把结果存储为临时文件(如生成 CSV 上传到临时存储),给模型返回下载链接。

📌 易错点 / 加分项:

  • Tool Calling 不等于”模型变聪明了”——它只是在提示词后面加了 tool 的定义,模型”可能”决定调用
  • 工具定义的 JSON Schema 写不好,效果会很差——参数描述必须具体、枚举值必须全面
  • OpenAI 的 parallel tool calling 允许多工具并发调用(无依赖时),Claude 的调用较保守

6. LangGraph 的状态图编排

题目: LangGraph 和传统的 Chain(如 LangChain 的 SequentialChain)在设计哲学上有什么根本不同?

追问1:LangGraph 的 Checkpointing 机制是什么?它在 Agent 的”中断与恢复”场景中起什么作用? 追问2:LangGraph 的 StateGraph 中,条件边(Conditional Edge)如何实现 Agent 的循环决策?

💡 答案:

主问题: LangGraph 的设计哲学是”把 Agent 表达为状态图而非线性链”。传统 Chain 是一个 DAG(有向无环图)——执行路径从输入到输出是确定性的、无回路的,适合”预定义流程”,比如 “RAG 的检索 → 生成” 就是直链。但 Agent 的行为是循环的——Agent 根据 LLM 的推理决策”调用某个工具 → 收到工具结果 → 再次推理 → 决定调用另一个工具或返回最终结果”,这是一个循环的过程,不是直线。LangGraph 通过 StateGraph(状态图)来建模这种循环——节点代表操作(LLM 推理、工具执行、最终返回),边代表状态转移(可以有条件分支和回环)。图的”当前状态”是可变的 State 对象,每个节点可以读写这个 State,节点之间的流转由图的 edge 决定。这种设计天然适合实现 Agent 的循环决策、Human-in-the-loop(人工审核)等复杂编排。

追问1: Checkpointing 是 LangGraph 最强大的机制之一——它能在图的每次”超步”(super-step,即经过一个节点)之后自动保存整个 State 的快照。这意味着一个 Agent 图可以在任何节点执行后被”冻结”和”恢复”。对于 Human-in-the-loop 场景:Agent 调用了一个敏感工具(如 transfer_money),图执行到这个节点时 Checkpointing 自动保存状态并暂停——等人工审核批准后,再从 Checkpoint 恢复继续执行。对于长时间运行的 Agent:如果网络中断或程序重启,可以从最近的 Checkpoint 恢复,而不必从头开始。Checkpointing 的存储可以选内存、SQLite 或 Postgres,生产环境用 Postgres 做持久化。

追问2: 条件边是 LangGraph 实现 Agent 决策的核心。在 Agent 图中,LLM 节点输出一个包含 next 字段的结果——这个结果可能有三个值:"tools"(LLM 决定需要调用工具)、"continue"(LLM 认为已经有足够信息,可以继续到下一阶段)、"end"(LLM 认为应直接返回最终答案)。条件边的路由函数接收状态作为输入,读取 LLM 的 next 判断值,然后返回要跳转到的下一个节点名。如果返回到工具执行节点,工具执行后将结果写回 State 再回到 LLM 节点——这就构成了”推理 → 调工具 → 获结果 → 再推理”的循环。循环终止条件是 LLM 返回 "end" 或达到最大循环次数,防止无限循环和 token 浪费。

📌 易错点 / 加分项:

  • LangGraph 不等于 LangChain——前者是图编排框架,后者是组件框架,两者独立发布
  • State 的不可变性是 LangGraph 的核心约束——每个节点返回一个新的 State 快照而非修改旧 State
  • 对复杂 Agent 来说,图比链的好处在于可测试性——每个节点可以独立测试且端到端可 trace

7. 向量数据库选型与对比

题目: 目前主流的向量数据库有哪些?你会如何根据业务场景选型?

追问1:Milvus、Pinecone、Weaviate、Qdrant 各自的核心差异是什么?如果数据量级在十亿级向量,选哪个? 追问2:向量数据库的核心性能瓶颈是什么?HNSW 索引参数如何调优?

💡 答案:

主问题: 目前主流的向量数据库可分为三类。第一类是专用向量数据库:Milvus(开源、云原生架构、支持十亿级向量、分布式部署)、Pinecone(全托管商业服务、零运维、对中小企业友好)、Weaviate(开源、支持 GraphQL 原生集成、内建向量化和混合搜索)、Qdrant(Rust 编写、极致性能、轻量但仍然可以分布式)。第二类是传统数据库的向量扩展:Pgvector(PostgreSQL 扩展)、Redis Stack(RediSearch 模块)、Elasticsearch(8.x 开始支持向量)。第三类是向量检索库(非数据库):FAISS(Meta,极致搜索性能但不提供数据库能力)、Annoy(Spotify)、hnswlib。选型维度主要包括:数据规模(百万、亿、十亿级)、部署方式(自建 vs 云托管)、召回率要求、过滤查询复杂度、运维成本、生态兼容性(与现有框架的集成)。

追问1: Milvus 面向的是十亿甚至百亿级的向量搜索——它采用了存算分离架构,计算节点和存储节点独立扩展,存储基于对象存储做持久化,索引用 GPU/CPU 并行构建。适合大型企业级 RAG 应用。Pinecone 是”云优先”的——零运维部署和扩展,但无法私有化部署,适合中小团队。Weaviate 的差异化在于模块化——内建多种 vectorizer(OpenAI、Cohere、HuggingFace 等)、支持 BM25 + 向量混合搜索,适合需要多种检索策略的场景。Qdrant 的优势在于单个节点的事务吞吐量极高(Rust 性能优势明显),对资源要求较低,适合资源受限但仍然需要高性能的场景。十亿级向量通常建议 Milvus 或 Pinecone,因为它们为大规模做了 depth 设计——分片(Sharding)、索引分区、增量插入优化等。Pgvector 和 Redis Stack 适合百万级向量、可以把向量数据和其他业务数据一起管理。

追问2: 向量数据库的核心性能瓶颈在三个维度:索引构建速度(写)、搜索延迟(读)、内存占用(空间成本)。HNSW 的调优关键是四对参数的关系:M(每层节点连接的最大邻居数)——值越大召回率越高但内存占用量增加;efConstruction(构建时搜索的宽度)——值越大构建出的图越连通、搜索质量越高,但构建速度显著降低;efSearch(查询时搜索的宽度)——值越大召回率越高但搜索延迟增加;向量维度和数量——维度越高、数量越大,所有上述参数对性能的影响更明显。调优策略:先固定 M(16-64 之间)和 efConstruction(200-500),然后通过调节 efSearch(从 64 开始逐渐提高)观察召回率-延迟曲线,找到满足业务 SLA 的最优参数。另外选择量化方案(如 SCANN、IVF_PQ)可以在十亿级场景下大幅降低内存占用,代价是召回率略微下降。

📌 易错点 / 加分项:

  • 向量数据库不替代关系数据库——它适合相似搜索不是精准查询,两者的查询模式完全不同
  • 对”混合搜索”的理解——metadata filter + vector search 同时进行是向量数据库的核心竞争力
  • 不要以为 PAISS 就是”向量数据库”——它是”向量检索库”,缺少持久化、分片、高可用等数据库能力

8. Prompt Engineering 与系统提示词设计

题目: Prompt Engineering 的核心理念是什么?系统提示词(System Prompt)和用户提示词(User Prompt)在定位上有什么分工?

追问1:Few-shot 提示和 Chain-of-Thought 提示分别是解决什么问题的?什么时候该用哪种? 追问2:如果在生产环境中发现 Agent 回答质量不稳定,你如何系统化地迭代优化 Prompt?

💡 答案:

主问题: Prompt Engineering 的核心理念是”通过结构化、精确的语言描述来引导大模型产生期望的输出”,本质上是”编程自然语言”——用清晰的结构、示例、约束条件去定义模型的输出空间。系统提示词(System Prompt)和用户提示词(User Prompt)有明确的分工:System Prompt 用于定义”模型是什么角色、有哪些能力边界、行为约束、输出格式要求”,它是稳定的、很少随请求变化——比如”你是一个资深 Java 工程师面试官,答案要求口述风格、不能只列关键词”。User Prompt 用于描述”当前用户的具体请求”——比如”出一道 HashMap 的面试题”。这个分工设计的好处在于:System Prompt 的 token 可被缓存(prompt caching),大幅降低重复调用的成本。

追问1: Few-shot 提示是通过在 Prompt 中加入几个问-答示例(示例中展示了期望的输出格式和推理方式)来引导模型理解任务模式。它解决的是”模型不理解任务格式”的问题——如果期望输出是特定的 JSON Schema 或表格结构,给 2-3 个示例比用文字描述一百遍更有效。Chain-of-Thought 提示是通过在 Prompt 中要求模型”逐步思考”(Let’s think step by step)或者在示例中展示推理步骤来解决”模型无法正确推理复杂问题”的问题。CoT 在数学推理、多步决策、代码分析等需要推理的场合适用。Few-shot 和 CoT 通常组合使用——示例中不仅展示输入输出还展示中间推理步骤。如果任务是简单的格式转换就用 Few-shot 不用 CoT(节省 token),如果是需要多步推理就用 CoT(即使 token 多)。

追问2: 系统化迭代 Prompt 的流程分五步。第一是建立评估集——收集 50-100 个有代表性的测试 query,对每个 query 定义预期行为。第二是建立自动化评估——每次改 Prompt 后在评估集上跑一遍,统计成功率、分析失败 pattern。第三步是定位失败原因——是模型”缺乏上下文信息”?(需要补更多 RAG 召回)还是”指令不够清晰”?(Prompt 中行为约束需要更精确的描述)还是”模型能力边界”?(这个任务超出了模型的能力范围需要换策略)。第四步是单变量改动——每次只改 Prompt 中的一个元素(比如只改系统提示词的角色定义),然后重新评估,确认改动有效再合入。第五步是版本管理和回滚——Prompt 应该和代码一起走 Git,每次改动有 PR 和 review,万一新 Prompt 效果变差可以立刻回滚。

📌 易错点 / 加分项:

  • System Prompt 和 User Prompt 的缓存策略不同——Claude 对 System Prompt 做 automatic caching
  • Few-shot 的”高质量示例”比”多示例”更重要——一个精心编写的示例胜过 10 个草率的示例
  • Prompt 的 token 优化很重要——同样的逻辑用 200 token vs 50 token,在前端调用时差异显著