Prompt Engineering:LLM 时代的"调参"
如果说传统机器学习的调参是需要考虑特征权重与统计边界的寻优,而深度学习时代的调参是摸索网络架构与梯度下降的动力学,那么 LLM 时代的'调参'就是 Prompt Engineering------通过自然语言的上下文来激活知识与对齐意图。
Prompt Engineering 解决的核心问题是:面对一个具体任务,如何用一段精心设计的自然语言输入(包括指令、示例、格式约束、推理引导等),让模型在一次调用中就给出准确、符合预期的输出?
具体包含几个子问题:
- 怎么把任务讲清楚:指令的措辞、结构、强调方式,让模型准确理解你的意图,而不是字面解读后跑偏
- 要不要给示例:用 few-shot examples 展示期望的输入输出模式,借助模型的 in-context learning 能力让它快速习得任务规律
- 要不要引导推理:通过 Chain-of-Thought 等技巧让模型显式生成中间推理步骤,在数学、常识、符号推理等任务上提升准确率
- 怎么约束输出:格式(JSON / Markdown / XML)、风格、范围限制,让结果可解析、可复用、可被下游系统消费
这里也包含两部分考虑:
- 让结果更准:通过措辞、结构、示例、推理引导,把模型"一次做对"的概率拉到最高
- 让结果更稳定:通过温度控制、Schema 约束、Self-Consistency 等,降低输出的随机性,让相同输入产生可复现的结果
在模型还比较弱的时代(2022-2024),prompt 的好坏极大程度地影响了生成质量。当时 agent 的概念还没有兴起,人们更多关注的就是这个"单次调用如何更好出结果"的问题。
那个时期积累了大量"调参"技巧:
| # | 技巧 | 背后的原理 / 实证 |
|---|---|---|
| 1 | 重要信息放开头和结尾 | Transformer 注意力在长上下文中呈 U 型衰减,中间位置容易被忽略(Lost in the Middle)。2025 年先进模型依然存在:GPT-4o 在 32K 上下文时准确率从 99.3% 掉到 69.7% |
| 2 | 输出结构化数据时优先用类型/Schema 描述,而非自然语言描述 | 模型在预训练中见过大量代码与类型定义语料,对 TypeScript interface / JSON Schema / Pydantic 这类结构化描述的识别与遵守度显著优于自然语言描述 |
| 3 | 关键约束用强调标记并复述 1-2 次 | 重复关键指令能强化注意力权重,已被实证列入可测量提升 LLM 准确率的 prompt 原则之一 |
| 4 | 对推理类任务加上 CoT 引导 | 让模型显式生成中间推理步骤(Chain-of-Thought),在数学、常识、符号推理任务上大幅提升表现。最简单形式:prompt 末尾加 "Let's think step by step" |
| 5 | 对有客观正确解的任务使用 Self-Consistency | 在较高温度下采样多条推理链、对最终答案做多数投票,能显著提升准确率 |
| 6 | 给 2-5 个高质量示例(Few-shot) | 大模型具备 in-context learning 能力,无需梯度更新就能从示例中习得任务模式 |
| 7 | 要稳定/可重复的输出时把温度调到 0 | 低温使 softmax 趋近 argmax,输出趋向贪心解码、随机性显著下降。即使温度=0 仍存在一定隐藏随机性,但已经足够稳定 |
| 8 | 长上下文末尾完整重复一次核心提示词 | 打破因果语言模型"从左到右单向阅读"的注意力物理局限,使模型处理第二遍时能全局回溯。Google Research 2025 年研究证实这种 "prompt 复述" 在非 reasoning 模式下普遍提升性能 |
但很多技巧在模型强大并引入推理能力之后,变得没那么重要了。现在的 prompt 变得更简单更直观:讲清楚你想要做的事情。
当然,如果想要达到更极致的效果,或者使用一些本地模型、小模型,这些技巧仍然有价值。
但很快大家发现,单纯调 prompt 远远不够。即使 prompt 构建得再好,如果没有把必要的知识(领域知识、上下文信息)放进上下文里,最终效果还是会很差,LLM 的幻觉会很严重。
这就引出了 Context Engineering。
二、Context Engineering:给模型看什么
Context Engineering 解决的核心问题是:我有一堆信息和上下文,应该给模型看什么,以及怎么给?
具体包含两个子问题:
- 选什么内容放到 LLM 的上下文中:从海量数据中检索相关信息
- 已经选好了上下文后怎么给到模型:内容的排序、格式化
这里包含了两部分考虑:
- 让结果更准:放的内容和格式会影响 LLM 的输出质量
- 让成本更低:context window 是稀缺资源,要高效利用;还要从推理效率上考虑成本
Context Engineering 不是 Prompt Engineering
Context Engineering 和 Prompt Engineering 的区别在于:Prompt 关心"怎么说",Context 关心"给什么信息"。你的 prompt 可以写得很完美,但如果缺少必要的领域知识、业务上下文、关键信息,模型一样会产生幻觉。
这个视角的转变,在 2025 年中已经成为行业共识的关键节点。Shopify CEO Tobi Lütke 在 2025 年 6 月公开表态:
"I really like the term 'context engineering' over prompt engineering. It describes the core skill better: the art of providing all the context for the task to be plausibly solvable by the LLM." (我更喜欢 'context engineering' 这个词,而不是 'prompt engineering'。它更准确地描述了这项核心技能:为任务提供所有相关上下文,让 LLM 有可能解决这个任务的艺术。)
紧接着,Andrej Karpathy 公开背书,并给出了更工程化的定义:
"+1 for 'context engineering' over 'prompt engineering'. People associate prompts with short task descriptions you'd give an LLM in your day-to-day use. When in every industrial-strength LLM app, context engineering is the delicate art and science of filling the context window with just the right information for the next step." (+1,赞成用 'context engineering' 替代 'prompt engineering'。人们会把 prompt 联想到日常使用 LLM 时给的一小段任务描述。但在每一个工业强度的 LLM 应用里,context engineering 是一门精细的艺术与科学:为下一步把恰到好处的信息填进 context window。)
"prompt" 这个词容易让人联想到"写一句措辞精巧的指令",但真正决定模型表现的,是把哪些信息、以什么形式、按什么顺序塞进 context window------这是一个系统工程问题,而不是文学问题。Karpathy 强调:人们把 "prompt" 联想成"短小、措辞巧妙的指令",但真正的技能要宽得多------它涵盖信息检索、工具结果、对话历史、示例选择的整套组装工作。
Context Engineering 的关键维度
Context Engineering 涉及多个维度的优化,先把 6 个维度并列出来一览:
| # | 维度 | 核心关注点 |
|---|---|---|
| 1 | 外部知识的检索与组织 | 从外部知识库找内容、决定排序方式 |
| 2 | 工具定义与 Schema 设计 | 向模型描述"有哪些能力可用" |
| 3 | 对话历史与记忆管理 | 保留什么、丢弃什么、怎么跨 session 检索 |
| 4 | 格式与结构化 | 用什么格式(纯文本 / Markdown / XML / JSON)让模型认知负荷最低 |
| 5 | Token Budget 管理 | 何时压缩、何时 offload、何时读回 |
| 6 | Context Caching | 把稳定不变的内容标记为缓存前缀,命中即 0.1× 价格 |
下面逐项展开。
1. 外部知识的检索与组织
这是最典型的场景,包括:
- RAG(检索增强生成):从外部知识库检索相关内容
- 语义检索:使用向量嵌入进行相似度匹配
- Reranking:对检索结果进行二次排序
关键:
- 原文顺序 vs 相关度顺序:传统 RAG 按相似度降序排列检索结果,但这会破坏文本的逻辑流、时序进展、指代关系。保持原文顺序(OP-RAG)能用更少的 token 实现更好的效果
2. 工具定义与 Schema 设计
Context Engineering 也包含如何向模型描述可用的工具:
- Tool schema 的结构化:JSON Schema、TypeScript interface、Function signature
- Tool description 的清晰度:决定模型能否正确选择和调用工具
- 参数说明的精确性:影响工具调用的参数准确率
这部分看似是"工具定义",但本质上是在构建模型的上下文------告诉模型"有哪些能力可用"。
3. 对话历史与记忆管理
- 对话历史的压缩与过滤:保留关键信息,丢弃冗余内容
- 长期记忆的检索:从历史对话中提取相关上下文
- 工作记忆的维护:当前任务的临时状态
4. 格式与结构化
不同的格式对模型的认知负荷差异巨大:
| 格式 | 适合场景 | 注意点 |
|---|---|---|
| 纯文本 | 向量嵌入构建 | Token 利用率最高 |
| Markdown | 文档/对话 | 模型"原生认知结构",预训练语料大量存在,理解力可提升 |
| XML 标签 | 多文档边界控制 | 严格边界,防止多文档语义污染 |
| JSON / YAML | 数据交换 | 高认知负荷,容易产生"语法正确但内容幻觉"的输出 |
5. Token Budget 管理
在有限的上下文窗口内:
- 什么时候触发 compaction(压缩)
- 哪些内容 offload 到磁盘
- 如何按需读回之前的内容
6. Context Caching(上下文缓存)
在 agent 的实际运行中,绝大多数 token 是被反复重发的:system prompt、tool schemas、few-shot 示例、规则说明、长文档背景------这些内容每次工具调用都会原封不动地塞回 context window。Context caching 就是针对这一现象的工程优化:把稳定不变的内容标记为"缓存前缀",只为第一次付比较昂贵的cache write的费用,之后命中缓存,基本只需要1/10的cache read的价格。
以 Anthropic prompt caching 为例,量级差异是显著的:
| 维度 | 数值 | 备注 |
|---|---|---|
| 写入(cache write) | 1.25× base input price | 只付一次 |
| 读取(cache hit) | 0.1× base input price | 比正常 input 便宜 90% |
| 首 token 延迟(TTFT) | 下降约 85% | --- |
| TTL | 默认 5 分钟,可延长至 1 小时 | --- |
对一个典型的 coding agent 而言,system prompt + tool definitions 动辄上万 token,每一轮工具调用都重复发一次。如果不做 caching,这一块就是持续不断的成本黑洞;做了 caching 之后,它从"每轮都要付的过路费"变成了"一次性投入 + 极低的复用成本"。
要让缓存真正命中,工程上有几条原则:
| 原则 | 做什么 | 反面教材 |
|---|---|---|
| Stable prefix | 把不变的内容放在 context 最前面,动态内容(用户消息、工具结果、时间戳)放后面 | 任何前缀位置的字符变动都会让后面的缓存失效 |
| 避免无谓的破坏 | 检查前缀里不要混入会变的内容 | 日期、随机 ID、自增计数器这类"看似无害"的字段如果放在前缀里,会让整个缓存秒级失效------这种坑在生产中非常常见 |
Context Engineering 的局限
Context Engineering 解决的是**"已经选好内容后怎么组织"**的问题。它假设你需要的信息是可获取的、有边界的------但真实场景下,单靠组织上下文是远远不够的:
- Agent 怎么主动去找信息?(工具调用、检索流程)
- Agent 如何安全地运行?(沙箱、权限)
- Agent 如何跨多个 session 持续工作?(状态持久化、调度)
- 什么时候应该把上下文压缩、卸载、读回?(生命周期管理)
这些是 Context Engineering 本身回答不了的------它们关心的不是"模型这一步看什么",而是"整套系统怎么运转"。要回答这些问题,需要把视角从"单次调用的上下文"抬升到"整个 agent 系统的工程框架",这就是下一节要展开的主题。
三、Harness Engineering:Agent = Model + Harness
到了 Harness Engineering 这一层,视角发生了根本性的转变。如果说 Prompt 和 Context Engineering 关注的是"怎么跟模型说话"和"给模型看什么",那么 Harness Engineering 关注的是:如何把模型变成一个可以信赖的、能自主完成任务的 Agent。
Harness的定义简洁,却带来了混乱
按照 LangChain 的定义:Agent = Model + Harness,也就是说,模型之外的所有东西都是 Harness。这个定义很简洁,但在实践中会导致混乱:
- 你说"Harness",可能指的是 Claude Code 这个产品
- 我说"Harness",可能指的是 Initializer + Coding Agent 这种设计模式
- 他说"Harness",可能指的是他项目里的 AGENT.md 配置文件
三个人用同一个词,说的完全不是同一个东西。这就像说"软件工程"------你可能在说设计模式,也可能在说编程语言,也可能在说某个具体的代码库。
问题的根源在于:Harness 的范围太广了。
如果不对 Harness 进行分层,我们就无法精确讨论问题。
解决手段就是,将Harness再拆一拆,拆成多个可以用来讨论的概念.
Harness 的分层结构
为了解决"Harness 范围太广"的问题,我结合了 Anup Jadhav、Anthropic、学术界的研究,提出了一个从底层到上层的分层结构:
| 层 | 名称 | 性质 | 回答的问题 | 典型内容 |
|---|---|---|---|---|
| 第 5 层 | Design Instance(实际场景) | 具体 Policy | "为了某个目标,怎么组合?" | Claude Code、Stripe Minions、CI/CD Auto-Fix |
| 第 4 层 | Pattern(可复用模式) | 可复用 Policy | "一组能力该怎么组合?" | Plan-Act-Verify、Initializer + Coding Agent、Loop |
| 第 3 层 | Design Components(Design Axes) | 上层 Mechanism | "有哪些可选项?" | 10 个 Design Axes(topology / coordination / memory ...) |
| 第 2 层 | Framework(mechanism / runtime) | 底层 Mechanism | "能做什么?" | Tool dispatch、Sandbox、MCP、Skill、Trigger ... |
| 第 1 层 | Cross-cutting Concerns(横切基础) | 横切所有层 | "贯穿全程的基础能力?" | Prompt Engineering、Context Engineering |

依赖方向:第 5 层实例化自第 4 层,第 4 层组合自第 3 层,第 3 层实现于第 2 层;所有层都依赖第 1 层(Cross-cutting Concerns)。
这个分层可以借经典的软件工程原则 Mechanism vs Policy(机制与策略分离)来理解:
| 层 | Mechanism / Policy | 角色 |
|---|---|---|
| Cross-cutting Concerns | 横切基础 | 贯穿所有层的基础能力 |
| Framework | 底层 Mechanism | 让能力真实可执行 |
| Design Components | 上层 Mechanism | 提供可组合的能力组件和设计坐标 |
| Pattern | 可复用 Policy | 决定一组能力如何组合 |
| Design Instance | 具体 Policy | 真实跑起来的系统配置与运行方式 |
也就是说,下面三层回答的是"系统能提供哪些能力、有哪些可选项",上面两层回答的是"为了某个目标,应该怎么组合这些能力"。
让我们从底层开始逐层展开。
第 1 层:Cross-cutting Concerns(横切基础)
这一层是所有其他层都依赖的基础。
Anup Jadhav 明确指出:"Harness engineering subsumes both prompt engineering and context engineering." (Harness engineering 同时涵盖 prompt engineering 和 context engineering。)
| 横切能力 | 关注的核心问题 | 典型内容 |
|---|---|---|
| Context Engineering | 每步给模型什么内容 | RAG、retrieval、tool schema、compaction 触发时机、offload 策略 |
| Prompt Engineering | 单次输入的措辞 | CoT、few-shot、强调标记 |
为什么说它们是"横切"的?
因为无论你在哪一层(Framework、Pattern、还是 Instance),都需要考虑:
| 在哪一层 | 都要回答 |
|---|---|
| Framework | "Tool schema 怎么写?"(Prompt Engineering) |
| Pattern | "Planner 给 Evaluator 什么提示?"(Prompt + Context) |
| Instance | "AGENT.md 里要包含哪些上下文?"(Context Engineering) |
它们不是独立的层级,而是贯穿所有层的基础能力。
第 2 层:Framework(mechanism / runtime)
Framework 层是 Harness 分层的基础,它提供底层的能力。
这一层回答的是:"能做什么" ,而不是 "怎么做" 。
典型的 Framework 产品:
- Claude Code
- Codex SDK
- OpenAI Agents SDK
- LangGraph
- Deep Agents
Framework 提供的核心机制:
| Mechanism | 核心能力 / 关键说明 |
|---|---|
| Tool dispatch | Tool registry(注册可用工具) Schema 注入(把工具签名注入 context) JSON tool-call 协议(标准化的调用格式) |
| Sandbox runtime | 隔离执行环境 文件系统沙箱 Shell 环境管理 |
| MCP client | 外部 tool/data 的标准接入 MCP server lifecycle 管理 Tool description 注入(⚠️ 信任边界,需要审计) |
| Skill registry | Skill 发现机制 Progressive disclosure 触发 Skill 文件格式规范 |
| Subagent spawn | Context isolation:每个 subagent 独立的 context window Event-driven wait:父 agent 不轮询,等 subagent 完成后被通知 → 避免父 agent 上下文膨胀 |
| Hook lifecycle | Before/after tool call、on session start、on error Deterministic enforcement:"success is silent, failures are verbose" (成功时保持安静,失败时输出详细信息) 把"我跟 agent 说要做 X"变成"系统强制 X" |
| Permission gate | Destructive action 拦截(git reset --hard、rm -rf) Human approval 流程 细粒度权限配置 |
| Trigger 系统 | Cron / event / webhook → 启动新 session 可用于自动化调度场景 trigger 系统本身是 framework 能力 |
| Observability | Trace、logging、event bus Cost tracking、latency monitoring 调试工具(inspector、replay) |
Mechanism vs Policy 的边界:
这是最容易混淆的地方。举个例子:
-
Mechanism 提供:Trigger 系统(能够定时启动 session 的能力)
-
Policy 决定:什么时候触发、触发后执行什么agent。
-
Mechanism 提供:Skill registry(能够注册和触发 skill 的能力)
-
Policy 决定:有多少个 skill、每个 skill 的内容是什么、触发条件是什么
-
Mechanism 提供:Subagent spawn(能够启动子 agent 的能力)
-
Policy 决定:拆分成几个 subagent、职责是什么、用什么模型
这就是 Mechanism vs Policy 的分离:Framework 和 Design Components 暴露能力,Pattern 和 Design Instance 决定如何组合、何时使用、做到什么程度。
第 3 层:Design Components(Design Axes)
这一层我称之为 Design Components 。它由一组 Design Axes 构成------这些 axes 描述了设计 Harness 时的"选择空间"。它们仍然偏 Mechanism,因为只告诉你"有哪些选项",并不直接替你决定"该怎么用"。
这一层回答一个问题:设计 Harness 时,有哪些维度需要决策?