前言
最近和几个做 AI 产品的朋友聊天,发现大家对"怎么用好大模型"这件事,认知差距非常大。
有人还停留在"多加几个词就能让 GPT 听话"的阶段;有人开始系统地管理上下文窗口、设计信息流;还有人已经在构建整套测试框架,把 AI 调用当成工程系统来对待。
这三种状态,其实对应着目前 AI 工程领域正在发生的三次认知跃迁:
- Prompt Engineering:怎么说话
- Context Engineering:怎么喂信息
- Harness Engineering:怎么造框架
本文想认真捋一下这三层的本质区别,以及它们在实际工程中的意义。如果你正在用大模型做产品或工具,这篇文章应该对你有帮助。
一、Prompt Engineering:与模型对话的艺术
1.1 它到底是什么
Prompt Engineering(提示词工程)是目前最广为人知的概念。简单说,就是通过精心设计输入文本,引导语言模型输出你想要的结果。
但很多人对它的理解是错的------以为只是"换几个词"或者"加一句 you are an expert in..."。
实际上,成熟的 Prompt Engineering 包含以下几个核心维度:
角色设定(Persona)
csharp
You are a senior backend engineer with 10 years of experience in distributed systems.
Your responses should be concise, technical, and assume the reader is familiar with CS fundamentals.
任务拆解(Task Decomposition)
把复杂任务拆成子任务,让模型一步步完成,而不是期待它一次到位。
vbnet
Step 1: Analyze the requirements
Step 2: Identify potential edge cases
Step 3: Propose a solution
Step 4: Write the implementation
少样本示例(Few-shot Examples)
给模型看几个"正确答案长什么样",比说一百遍"请输出 JSON 格式"都管用。
vbnet
Input: "用户无法登录"
Output: {"category": "auth", "priority": "high", "assignee": "backend-team"}
Input: "首页加载很慢"
Output: {"category": "performance", "priority": "medium", "assignee": "frontend-team"}
Input: "{{user_issue}}"
Output:
思维链(Chain of Thought)
在提示词里加上 Let's think step by step,或者显式要求模型在回答前先推理。
这不是玄学,而是有实验支撑的:CoT 能显著提升模型在推理、数学、逻辑类任务上的准确率。
1.2 Prompt Engineering 的局限
Prompt Engineering 的核心假设是:模型是固定的,我们通过调整输入来控制输出。
这个假设在简单场景下没问题。但当你的应用变复杂之后,你会遇到几个绕不过去的墙:
- 上下文窗口是有限的:你不可能把所有相关信息都塞进一个 prompt
- 状态无法持久化:每次调用都是无状态的,模型不记得你上次说了什么
- 提示词难以复用:写死在代码里的 prompt 既难维护,也难测试
- 输出质量难以稳定:换个模型版本,你的精心调教可能全部失效
这就引出了下一层:Context Engineering。
二、Context Engineering:信息架构的重新设计
2.1 从"写提示词"到"管上下文"
如果说 Prompt Engineering 关注的是"怎么说话",那么 Context Engineering 关注的是**"在对话里放什么信息,以什么结构放,放多少"**。
一个现代 LLM 应用的上下文窗口,远不止是 system prompt + user message,它可能包含:
sql
┌─────────────────────────────────────┐
│ Context Window │
├──────────────┬──────────────────────┤
│ System │ 角色定义、行为约束 │
│ Prompt │ 输出格式要求 │
├──────────────┼──────────────────────┤
│ Retrieved │ RAG 检索到的相关文档 │
│ Documents │ 数据库查询结果 │
├──────────────┼──────────────────────┤
│ Tool Results │ 已执行工具的返回结果 │
│ │ API 调用输出 │
├──────────────┼──────────────────────┤
│ Memory │ 用户历史偏好 │
│ │ 上一轮关键信息摘要 │
├──────────────┼──────────────────────┤
│ Conversation │ 多轮对话历史 │
│ History │ (经过筛选和压缩的) │
├──────────────┼──────────────────────┤
│ Current │ 用户当前输入 │
│ Input │ 附件、截图等 │
└──────────────┴──────────────────────┘
你要做的不只是写提示词,而是精心设计这整个信息架构。
2.2 Context Engineering 的核心挑战
挑战一:相关性过滤
不是所有信息都该进上下文。把无关内容塞进去不仅浪费 token,还可能干扰模型的注意力(这不是比喻,Attention 机制就是字面意义上的"注意力")。
好的 Context Engineering 需要回答:这条信息,现在,对当前任务,有没有用?
挑战二:信息密度优化
有时候你需要在有限的 token 预算里塞进尽可能多的信息。这就涉及到:
- 对话历史的滚动压缩(Sliding Window + Summarization)
- 文档的分块策略(Chunking)和检索排序
- 结构化数据的紧凑表示(用 YAML 而不是 JSON,有时能省 30% token)
挑战三:信息时效性管理
模型对上下文里靠前和靠后的内容记得更清楚(这是 Lost in the Middle 现象),所以重要信息的位置也是工程变量。
挑战四:跨轮次状态管理
多轮对话中,如何在不超出 context 限制的同时,保持对话的连贯性和"记忆"?
一个经典的解法:
python
def compress_history(messages: list[dict], max_tokens: int) -> list[dict]:
"""
保留最近 N 轮完整对话,
对更早的对话进行摘要压缩,
始终保留 system prompt。
"""
system = [m for m in messages if m["role"] == "system"]
history = [m for m in messages if m["role"] != "system"]
recent = history[-6:] # 保留最近 3 轮
older = history[:-6]
if older:
summary = summarize_with_llm(older) # 摘要压缩
summary_msg = {"role": "assistant", "content": f"[Earlier context summary]: {summary}"}
return system + [summary_msg] + recent
return system + recent
2.3 Context Engineering 的本质
Context Engineering 的本质是一个信息检索与筛选问题:在正确的时机,把正确的信息,以正确的格式,放到模型能看到的位置。
它要求工程师不只懂 LLM,还要懂信息架构、检索系统、数据结构。
这是比 Prompt Engineering 深一层的能力。
三、Harness Engineering:把 AI 当软件系统来对待
3.1 什么是 Harness
"Harness" 这个词来自测试工程领域,原指测试框架 或测试脚手架。
在 AI 工程语境下,Harness Engineering 指的是:围绕 LLM 调用构建完整的工程基础设施,包括评估、测试、可观测性、版本管理等。
如果说前两层关注的是"怎么让模型表现好",Harness Engineering 关注的是:我怎么知道它表现好?我怎么保证它持续表现好?
3.2 核心组成部分
组件一:Evaluation Framework(评估框架)
LLM 的输出是自然语言,不像传统软件可以直接 assert output == expected。你需要专门的评估机制:
python
class LLMEvaluator:
def evaluate(self,
prompt: str,
output: str,
ground_truth: str | None = None) -> EvalResult:
scores = {}
# 1. 基于规则的评估(快速、确定性)
scores["format_valid"] = self.check_format(output)
scores["no_hallucination_markers"] = self.check_safe_phrases(output)
# 2. 基于模型的评估(慢、但能评估语义质量)
scores["relevance"] = self.llm_judge(
f"Rate the relevance of this response to the query: {prompt}\nResponse: {output}"
)
# 3. 基于 ground truth 的评估(最准确,但需要标注数据)
if ground_truth:
scores["accuracy"] = self.semantic_similarity(output, ground_truth)
return EvalResult(scores=scores, passed=all(s > 0.7 for s in scores.values()))
组件二:Prompt 版本管理
提示词不应该硬编码在业务逻辑里。你需要:
- 把 prompt 存到配置系统或数据库
- 支持 A/B 测试不同版本的 prompt
- 记录每次修改的原因和效果
makefile
# prompts/ticket_classifier/v2.yaml
version: "2.0"
author: "zhangsan"
created_at: "2025-03-15"
changelog: "增加了对中文工单的支持,优化了 priority 判断逻辑"
system: |
You are a customer support ticket classifier...
few_shot_examples:
- input: "用户无法登录"
output: '{"category": "auth", "priority": "high"}'
eval_metrics:
- name: "format_valid"
threshold: 1.0
- name: "accuracy"
threshold: 0.85
组件三:可观测性(Observability)
LLM 调用是黑盒,但你的系统不应该是黑盒。你需要追踪:
- 每次调用的输入输出(用于回溯问题)
- Latency 和 token 消耗(用于成本控制)
- 输出质量分数的趋势(用于发现退化)
- 用户反馈信号(用于持续改进)
less
@trace_llm_call # 装饰器自动记录输入输出、耗时、token 数
async def classify_ticket(ticket: str) -> dict:
prompt = prompt_registry.get("ticket_classifier", version="latest")
response = await llm.complete(prompt.render(input=ticket))
result = parse_json(response)
metrics.record("ticket_classifier.confidence", result.get("confidence", 0))
return result
组件四:回归测试套件
每次修改 prompt 或升级模型版本,都需要跑一遍测试,确保没有引入退化:
bash
测试套件结构:
├── golden_set/ # 核心用例,必须 100% 通过
│ ├── auth_cases.json
│ ├── billing_cases.json
│ └── edge_cases.json
├── regression_set/ # 历史 bug 的复现用例
│ └── reported_issues.json
└── stress_set/ # 边界条件和压力测试
└── adversarial.json
3.3 为什么需要 Harness Engineering
有一个现象我在很多团队里都见过:AI 功能上线时效果不错,但几个月后慢慢变差,大家都不知道为什么,也不知道从哪里查起。
原因可能是:
- 模型供应商悄悄更新了模型
- 数据分布发生了变化
- 某次"优化"prompt 时引入了退化
- 依赖的 RAG 数据库内容变了
没有 Harness,你对这些变化是盲目的。有了 Harness,你才有能力持续、可信地迭代 AI 功能。
这是把 AI 功能从"玩具"做成"产品"的关键一跃。
四、三层工程的对比与协作
| 维度 | Prompt Engineering | Context Engineering | Harness Engineering |
|---|---|---|---|
| 关注点 | 如何表达任务 | 如何组织信息 | 如何保证质量 |
| 核心技能 | 语言理解、认知心理学 | 信息检索、数据工程 | 测试、可观测性 |
| 主要产物 | 提示词模板 | 上下文管道 | 评估框架与测试套件 |
| 衡量指标 | 人工感知质量 | Token 效率、召回率 | 准确率趋势、回归率 |
| 迭代周期 | 快(分钟级) | 中(天级) | 慢(周级) |
| 适用阶段 | MVP 探索期 | 产品成长期 | 规模化运营期 |
这三层不是互相替代的关系,而是递进且相互依赖的:
- 没有好的 Prompt,Context 再丰富也是乱码
- 没有好的 Context,Prompt 再精妙也是巧妇难为无米之炊
- 没有 Harness,前两层的努力都是在沙滩上建城堡
五、一个实际场景串联三层
假设你在做一个代码审查 AI 助手,让我们看看三层工程分别在做什么:
Prompt Engineering 层
设计 system prompt,明确角色是"资深工程师",输出格式要求 Markdown,审查维度包括安全性、性能、可读性;用 few-shot 给出标准审查意见的样例。
Context Engineering 层
在用户提交代码时,动态检索:
- 项目的编码规范文档(来自 RAG)
- 该文件的历史审查意见(来自数据库)
- 相关的内部 SDK 文档(来自知识库)
- 当前 PR 的其他改动(来自 Git API)
把这些信息精心组装进上下文,确保 token 不超限,且最相关的信息排在最前面。
Harness Engineering 层
维护一个包含 200+ 历史 PR 的评估集,其中有人工标注的"好审查"和"差审查";每次修改 prompt 后自动跑评估,报告质量分数;监控线上调用的 latency 和用户满意度打分;发现哪类代码审查质量在下降时自动告警。
总结
大模型应用工程正在快速成熟,三层工程代表着三种能力层次,也代表着 AI 工程师的三个成长台阶:
- Prompt Engineering:入门门槛低,但精通需要对模型行为有深刻理解
- Context Engineering:需要跨域知识,是大多数复杂 AI 产品的核心竞争力所在
- Harness Engineering:最接近传统软件工程,是 AI 系统走向可靠、可维护的必由之路
你现在站在哪一层?又打算往哪里走?
欢迎在评论区聊聊你的实践和踩坑经历。
如果文章对你有帮助,点个免费的赞鼓励一下吧!关注公众号:加瓦点灯, 每天推送干货知识!