核心公式
P(接受更差的解) = exp(−ΔE / T)
ΔE = 新prompt得分 − 当前prompt得分 (负数 = 更差)
T = 当前温度 (从1.0降到接近0)
T 高 → P 大 → 接受差解的概率高 → 大幅跳跃
T 低 → P 小 → 几乎只接受更好的解 → 精细微调
关键直觉:允许"走错路"才能跳出局部最优。纯贪心 = 永远卡在第一个山顶。
Claude Code 场景
真实场景
你在调优 社媒内容 agent 的 system prompt,当前输出质量 7.5/10,微调措辞已经一周没有提升。你陷入了局部最优。
识别信号 — 什么时候用这个模式
| 你观察到 | 诊断 | 应对 |
| 微调措辞 → 无变化 |
局部最优 |
进入高温阶段,换结构 |
| 加 example → 变好 → 再加 → 更差 |
过拟合到 example |
降温,只调 example 数量 |
| 换 role/persona → 质量波动很大 |
温度仍然高,探索空间大 |
继续高温,记录最高分结构 |
代码模式 — CLAUDE.md 中的调优协议
// 模拟退火 Prompt 调优器
// 在 Claude Code 中运行:cc run optimize
interface PromptCandidate {
content: string;
score: number;
}
async function simulatedAnnealingOptimize(
initialPrompt: string,
evaluate: (p: string) => Promise<number>,
iterations = 100
) {
let current: PromptCandidate = {
content: initialPrompt,
score: await evaluate(initialPrompt)
};
let best = { ...current };
let T = 1.0; // 初始温度
for (let i = 0; i < iterations; i++) {
T *= 0.97; // 降温速率
// 高温:大变动;低温:小变动
const candidate = T > 0.5
? await mutateStructure(current.content) // 换段落/结构/persona
: await mutatePhrasing(current.content); // 只换措辞/词语
const newScore = await evaluate(candidate);
const delta = newScore - current.score;
// 接受条件:更好 OR 概率性接受更差的
if (delta > 0 || Math.random() < Math.exp(delta / T)) {
current = { content: candidate, score: newScore };
}
if (current.score > best.score) best = { ...current };
console.log(`T=${T.toFixed(2)} score=${newScore.toFixed(1)} best=${best.score.toFixed(1)}`);
}
return best;
}
⚠ 反模式
只看当前得分微调措辞,没有"高温阶段"。这是纯贪心,必然卡在局部最优。如果你的 prompt 调了两天得分没超过 7/10,这就是信号——需要退火,不是微调。
实操记忆法
- 高温期(T > 0.5):换 persona、换结构、加删整段 example,接受暂时变差
- 低温期(T < 0.3):只改单词、语气、标点,不接受退步
- 判断标准:同一类型的变动已经连续 3 次没有提升 → 升温,换变动类型
拿走就能用 — 粘贴进你的 CLAUDE.md
## Prompt 调优协议(模拟退火模式)
### 当前处于哪个阶段?
- 高温期:新任务、新场景、效果还差。此时大改,不计较单次变差。
- 低温期:效果已经 7+/10,微调收敛。此时小改,不接受退步。
### 升温触发条件(任意一条)
- 同类改法连续 3 次无效
- 被同一个问题卡超过 2 天
- 输出得分长期在 6-7 震荡,无法突破
### 高温期允许的动作
- 完全换掉 persona / role 设定
- 增删整个 example 段落
- 改变输出格式(JSON vs Markdown vs 纯文本)
- 换 task framing(从"生成"改成"检查")
### 低温期禁止的动作
- 同时改超过 2 处
- 接受比上一版得分低的版本
核心直觉
任意复杂信号 = Σ 简单正弦波
任意复杂任务 = Σ 正交子任务
正交的数学定义:∫ f(x)·g(x)dx = 0
工程含义:改变 f 的参数,不影响 g 的处理逻辑
关键词是"正交"。正交子任务之间没有依赖 → 可以完全并行。
正交测试 — 如何判断任务是否可并行
正交判断题
修改任务 A 的输入或实现,任务 B 的逻辑需要改变吗?如果需要 → 不正交,必须串行。如果不需要 → 正交,可以并行。
Claude Code 场景 — 内容生成 Agent
真实场景
生成"推文 + 配图 + 发布策略"。错误做法是串行;正确做法是识别三个维度是否正交,然后决定并行度。
// ❌ 错误:伪装成并行的串行
const [text, image, timing] = await Promise.all([
generateText(topic),
generateImage(topic), // 实际上需要 text 来做风格对齐
getBestTiming(topic), // 实际上需要 text 来判断内容类型
]);
// → text/image/timing 之间有隐性依赖,并行会导致不一致
// ✅ 正确:先做正交测试,再决定并发结构
async function orchestrateContent(topic: string) {
// Step 1:识别正交维度
// 视觉风格模板 ⊥ 发布时间分析 ⊥ 历史数据提取 → 三者正交
// 文案 → 依赖 topic(但不依赖其他 agent)→ 可独立
const [styleTemplates, timingData, historicalPerf] = await Promise.all([
fetchVisualStyles(), // 不依赖文案
analyzeBestPostTimes(), // 不依赖文案
fetchHistoricalPerformance(), // 不依赖文案
]);
// Step 2:用上面的数据生成文案(现在可以做好风格对齐)
const texts = await generateTexts(topic, {
styleHints: styleTemplates,
performanceSignals: historicalPerf,
});
// Step 3:文案确定后,图+排期可以再次并行
const [images, schedule] = await Promise.all([
generateImages(texts, styleTemplates),
buildSchedule(texts, timingData),
]);
return { texts, images, schedule };
}
⚠ 反模式
用 Promise.all 包所有 agent 就叫"并行"。实际上 agents 之间有隐性依赖(一个 agent 的质量影响另一个),结果是并行执行、串行失败。
拆解步骤
- 列出所有子任务,对每对画一条"依赖线"
- 没有依赖线的任务 → 正交 → 放入第一批并行
- 有单向依赖的任务 → 拓扑排序,分批执行
- 有双向依赖 → 这不是两个任务,而是一个任务,合并
拿走就能用 — 粘贴进你的 CLAUDE.md
## Multi-agent 任务拆解(傅里叶正交原则)
### 并行前必须通过正交测试
- 修改任务 A 的输入或实现,任务 B 的逻辑需要改变吗?
- 需要 → 不正交 → 必须串行
- 不需要 → 正交 → 可以并行
### 三类依赖关系
- 无依赖 → 第一批并行执行
- 单向依赖 → 拓扑排序,分批执行
- 双向依赖 → 不是两个任务,合并为一个
### 禁止
- 用 Promise.all 包所有 agent 就叫"并行"
- 忽视 agent 之间的隐性数据依赖(一个输出影响另一个质量)
核心直觉
水在 99°C → 100°C 发生质变,不是量变
Agent 系统在某个临界点发生质变,不是线性退化
关键:找到你系统的相变点,在它之前设置硬限制
永远不要做线性外推("再多加一点应该没问题")
Claude Code 中的三类相变点
| 变量 | 相变表现 | 典型临界点 | 处理方式 |
| Context 长度 |
质量从 8/10 突然跌到 3/10 |
~60-80% 窗口上限 |
硬截断 + 摘要压缩 |
| Prompt 复杂度 |
模型开始幻觉、跳过指令 |
约 15+ 条规则 |
分层 prompt + 子 agent |
| 并发 Agent 数量 |
协调延迟 > 并行收益 |
通信复杂度 O(n²) 拐点 |
分组 + 层级编排 |
| Retry 次数 |
质量不再提升,开始循环 |
3-5 次 |
切换策略,不增加次数 |
代码模式 — 主动探测相变点
// 主动探测 Context 相变点
async function findPhaseTransition(
basePrompt: string,
targetTask: string,
) {
const results: { tokens: number; quality: number }[] = [];
const tokenLevels = [1000, 2000, 4000, 8000, 16000, 32000];
for (const tokens of tokenLevels) {
const paddedPrompt = padToTokens(basePrompt, tokens);
const quality = await evaluateQuality(paddedPrompt, targetTask);
results.push({ tokens, quality });
// 检测相变:质量突然下降超过 30%
if (results.length > 1) {
const prev = results[results.length - 2];
const drop = (prev.quality - quality) / prev.quality;
if (drop > 0.3) {
console.log(`⚡ 相变点发现: ${tokens} tokens`);
console.log(` 质量从 ${prev.quality.toFixed(1)} 跌至 ${quality.toFixed(1)}`);
console.log(` 建议硬限制: ${prev.tokens} tokens`);
break;
}
}
}
return results;
}
// 在系统中设置硬限制(不是软限制)
const CONTEXT_HARD_LIMIT = 6000; // 实测相变点 × 0.75
function safeContext(messages: Message[]): Message[] {
const totalTokens = countTokens(messages);
if (totalTokens <= CONTEXT_HARD_LIMIT) return messages;
// 不是线性截断,是结构化压缩
return [
messages[0], // system prompt 保留
...summarizeMiddle(messages.slice(1, -4)), // 中间压缩
...messages.slice(-4), // 最近 4 条保留
];
}
⚠ 反模式
发现 10 个 agent 开始变慢,加到 12 个试试。这是线性外推思维。相变之后增加更多只会加剧问题,因为协调成本是 O(n²) 的。
拿走就能用 — 粘贴进你的 CLAUDE.md
## System 临界点管理(相变原则)
### 已知的 Claude Code 相变点(设为硬限制)
- Context 长度:超过 60% 窗口上限开始压缩,到 80% 必须截断
- Prompt 规则数:不超过 15 条,超出则拆分为子 agent
- Retry 次数:最多 3 次,超出换策略而不是继续重试
- 并发 Agent 数:超过 5 个必须分组,不能扁平并发
### 设置方式:硬限制,不是软警告
- 不是"快到了提示一下",是"到了就截断/拒绝/换策略"
- 限制值 = 实测相变点 × 0.75(留安全边际)
### 禁止线性外推
- "再加几个 agent 应该没问题" → 协调成本是 O(n²)
- "context 再长一点应该还好" → 相变是突然发生的,不是线性的
核心公式
u(t) = Kp·e(t) + Ki·∫e(t)dt + Kd·de/dt
e(t) = 误差 = 目标分数 − 实际分数
Kp·e = P 项:当前这次差多少 → 立即修正
Ki·∫e = I 项:历史误差积累 → 系统性修正
Kd·de = D 项:误差变化速度 → 预判式修正
三项的工程映射
| PID 项 | 信号 | Claude Code 中的动作 |
| P(当前误差) |
这次输出得 4/10 |
立刻修改这次的 prompt 措辞/结构 |
| I(历史积累) |
最近 10 次平均 5.5/10 |
重写 system prompt,修改 CLAUDE.md 的 agent 规则 |
| D(变化趋势) |
得分从 7→6→5,趋势在恶化 |
预判性重构,不等质量崩溃再改 |
代码模式 — Agent 质量反馈系统
class AgentQualityPID {
private history: number[] = [];
private kp = 0.5, ki = 0.1, kd = 0.3;
private target = 8.5;
record(score: number): CorrectiveAction {
this.history.push(score);
const e = this.target - score; // 当前误差
const recentHistory = this.history.slice(-10);
const I = recentHistory.reduce((s, v) => s + (this.target - v), 0);
const D = this.history.length > 1
? score - this.history[this.history.length - 2] // 正数=改善,负数=恶化
: 0;
const signal = this.kp * e + this.ki * I - this.kd * D;
// 决策逻辑
if (Math.abs(e) > 3) return {
type: 'immediate',
action: 'rewrite_user_prompt', // P 大:立即修这次
reason: `Score ${score} vs target ${this.target}`
};
if (I > 8) return {
type: 'systemic',
action: 'update_system_prompt', // I 大:系统性问题
reason: `Accumulated error: ${I.toFixed(1)}`
};
if (D < -1) return {
type: 'preemptive',
action: 'restructure_agent_pipeline', // D 负:趋势恶化
reason: `Quality trending down: ${D.toFixed(2)}/call`
};
return { type: 'none', action: 'continue' };
}
}
// 用法:在 agent 每次执行后记录
const pid = new AgentQualityPID();
const result = await agent.run(task);
const action = pid.record(await evaluate(result));
if (action.type !== 'none') handleCorrection(action);
⚠ 反模式(只看 P)
每次输出差了就改措辞,从不看历史趋势。结果是过度修正——像没有 D 项的控制器,会在目标附近震荡,无法稳定收敛。
调参直觉
- Kp 太高:修正过猛,质量在目标附近上下震荡
- Ki 太高:对历史误差太敏感,频繁触发"系统性重写"
- Kd 太高:对趋势过于敏感,还没到问题就开始重构
- 推荐起点:Kp=0.5, Ki=0.1, Kd=0.3,根据实际震荡情况调整
拿走就能用 — 粘贴进你的 CLAUDE.md
## Agent 输出质量反馈(PID 模式)
### P 项(当前误差)— 立即修正
- 单次输出明显偏差时:在下一条消息里直接指出,让 Claude 重做这一步
- 不要积累问题,当场纠正
### I 项(历史积累)— 系统性修正
- 如果同类问题出现 3 次以上:更新本文件的相关规则
- 触发信号:反复提醒同一件事 → 说明 system prompt 有结构性漏洞
### D 项(变化趋势)— 预判式修正
- 输出质量在变差但还没崩溃时:主动重新描述任务背景和约束
- 不要等到质量已经很差再修正,提前干预成本最低
核心直觉
混沌系统轨迹:不可预测单次路径,但永远在有界区域内
LLM 输出:不可完全控制单次输出,但可以定义"不可能区域"
好的 system prompt ≠ 控制每次输出
好的 system prompt = 定义输出的可能空间(吸引域)
原则:约束"什么绝对不出现" > 规定"必须出现什么"
Claude Code 场景 — 设计 内容 Agent 的边界
❌ 错误:试图控制每次输出(脆弱,过拟合)
你是一个社媒文案 agent。
每次输出必须:
- 第一句以数字或问题开头
- 第二句解释背景
- 第三句给出行动号召
- 结尾用 3 个 emoji
- 字数在 180-220 字之间
...(30条规则)
→ 对某类 topic 完全失控,规则相互冲突
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ 正确:定义吸引域边界(鲁棒,泛化性强)
## 引力中心(目标区域)
你生成的内容在语气上贴近真实用户,不像 AI,
在信息上聚焦有价值的洞察,不是空泛的感叹。
## 排斥边界(绝对不出现)
- 不使用"赋能/赋权/生态"等营销黑话
- 不使用 5 个以上 emoji(视觉噪音)
- 不承诺具体数字收益(合规风险)
- 不提及竞争产品名称
- 不超过 280 字
## 自由区间(故意不规定)
- 开头方式:自由,根据内容选择最自然的
- 句子数量:自由,够清晰就行
- 话题角度:自由,选最有趣的切入点
代码模式 — 用程序化方式定义吸引域
// 吸引域验证器:检查输出是否在边界内
interface AttractorBoundary {
hardRules: { // 排斥边界:违反 = 重新生成
maxLength: number;
forbiddenPatterns: RegExp[];
requiredElements?: string[];
};
softGuidelines: string[]; // 引力中心:写在 prompt 里,不做硬检查
}
const xerpaAgentBoundary: AttractorBoundary = {
hardRules: {
maxLength: 280,
forbiddenPatterns: [
/赋能|赋权|生态/g,
/保证.*%收益|承诺.*倍/g,
/(competitor1|competitor2)/gi,
/[^\S\r\n]{2,}/g, // 多余空格
],
},
softGuidelines: [
'语气真实,不像营销文案',
'优先用具体数据替代形容词',
],
};
async function generateWithBoundary(
prompt: string,
boundary: AttractorBoundary,
maxRetries = 3
): Promise<string> {
for (let i = 0; i < maxRetries; i++) {
const output = await callClaude(prompt);
const violation = checkBoundary(output, boundary.hardRules);
if (!violation) return output; // 在吸引域内
// 把违规信息加回 prompt,让模型自我修正
prompt += `\n\n[修正提示] 上次违规: ${violation},请重新生成`;
}
throw new Error('无法在边界内生成合格内容');
}
✓ 核心洞见
你无法复现某次完美输出,但你可以让"差的输出"无处出现。设计吸引域比复现单次输出更实用。
拿走就能用 — 粘贴进你的 CLAUDE.md
## System Prompt 结构(吸引域三层模板)
### 第一层:引力中心(写在 prompt 里,不做硬检查)
- 目标语气/风格方向
- 好的输出"看起来像什么"
### 第二层:排斥边界(硬约束,程序化检查 or 明确列出)
- 禁止词汇:[根据业务填写,如"赋能/生态/赋权"]
- 禁止格式:超过 N 个 emoji,超过 X 字
- 禁止内容:具体数字承诺、竞品名称
### 第三层:自由区间(故意留白,不规定)
- 开头方式:自由
- 句子数量:够清晰就行
- 角度选择:选最有趣的
### 禁止
- 超过 15 条规则的 system prompt(触发相变)
- "必须出现什么"比"绝对不出现什么"更多
核心公式
H = −Σ p(x) · log₂p(x)
熵高 → 输出分布扁平 → prompt 有歧义
熵低 → 输出分布尖峰 → prompt 很明确
实操:同一个 prompt 跑 5-10 次,观察输出分散程度
不需要算公式,只需要看输出多样性
四级熵诊断
| 症状(跑 5 次后) | 熵级别 | 根因 | 修复 |
| 结构都不一样,甚至有的用中文有的用英文 |
极高熵 |
prompt 完全歧义 |
重写,加格式约束 |
| 结构相同,内容切角差异很大 |
高熵 |
任务范围模糊 |
加 few-shot examples |
| 结构内容相似,但细节不同 |
中熵 |
正常的创造性变化 |
如果这就是目标,可以接受 |
| 几乎完全相同(95%+) |
低熵 |
prompt 过于确定 |
如果需要多样性,放松约束 |
代码模式 — Prompt 熵诊断工具
// 用于在 Claude Code 中快速诊断 prompt 质量
// 运行:cc run check-entropy --prompt="your prompt"
import { Claude } from '@anthropic-ai/sdk';
async function diagnosePromptEntropy(
prompt: string,
n = 5
): Promise<EntropDiagnosis> {
const client = new Claude();
// 并行跑 n 次
const outputs = await Promise.all(
Array.from({ length: n }, () =>
client.messages.create({
model: 'claude-opus-4-5',
max_tokens: 500,
messages: [{ role: 'user', content: prompt }],
temperature: 1.0, // 使用默认温度,不要降温
})
)
);
const texts = outputs.map(o => o.content[0].text);
// 简单结构相似度:比较段落数、总字数、关键词
const structures = texts.map(t => ({
paragraphs: t.split('\n\n').length,
wordCount: t.split(' ').length,
hasCode: t.includes('```'),
hasNumberedList: /^\d+\./m.test(t),
}));
// 计算结构一致性(越接近 1 = 低熵)
const structuralConsistency = calcConsistency(structures);
return {
sampleOutputs: texts,
structuralConsistency, // 0-1,越高越一致
entropyLevel: structuralConsistency > 0.8 ? 'low'
: structuralConsistency > 0.5 ? 'medium'
: 'high',
diagnosis: diagnose(structures, texts),
};
}
// 在 Claude Code 工作流中:
// cc run diagnose-entropy → 识别问题 → cc run fix-prompt → 再诊断
✓ 最快用法
不需要代码。对任何 prompt,脑内运行 3 次,想象输出的结构差异有多大。差异大 → 高熵 → 需要加约束。这个直觉训练 2-3 次就会内化。
降熵工具箱(按效果排序)
- 指定输出格式(JSON/Markdown结构/固定段落数)
- 加 2-3 个 few-shot examples(最有效)
- 指定输出长度范围(字数或 token 数)
- 指定视角/角色("你是...的专家")
- 加负面示例("不要像这样...")
拿走就能用 — 粘贴进你的 CLAUDE.md
## Prompt 质量诊断(香农熵方法)
### 诊断信号(不需要代码,脑内判断)
- 同一 prompt 跑 3 次,结构都不一样 → 极高熵,需要重写
- 结构相同但内容切角差异大 → 高熵,加 few-shot examples
- 细节略有不同,结构一致 → 正常,可接受
- 几乎完全相同 → 低熵,如需多样性则放松约束
### 降熵工具(按效果排序)
1. 指定输出格式(JSON / 固定段落结构)
2. 加 2-3 个 few-shot examples(最有效)
3. 指定输出长度范围(字数上限)
4. 指定视角/角色
### 触发降熵操作的条件
- 同一 prompt 连续 3 次输出质量差异超过 30%
- 输出语言不稳定(时中时英)
- 每次结构都需要人工调整
核心直觉
在多目标优化中,不存在一个解在所有维度都最优
改善任何一个维度,必然牺牲另一个 — 这是数学必然
实践含义:
1. 先明确你的约束优先级
2. 找到帕累托前沿上对应的点
3. 不要在"前沿内部"浪费时间(存在同时更好的解)
Claude Code 场景 — Agent 配置选型
真实场景
为 AI 内容 agent 选择:模型、并发数、重试策略。速度/质量/成本三者不能同时最优,必须先明确优先级再选配置。
// 三条产品线的帕累托配置
const paretoConfigs = {
// 支付确认:速度 > 质量 > 成本
'payment-confirm': {
model: 'claude-haiku-4-5',
concurrency: 10,
maxRetries: 1, // 宁可失败,不能超时
timeoutMs: 2000,
streaming: true,
tradeoff: 'speed=10, quality=6, cost=9',
},
// 内容生成:质量 > 成本 > 速度
'xerpa-content': {
model: 'claude-sonnet-4-6',
concurrency: 3,
maxRetries: 3, // 允许重试,追求质量
timeoutMs: 30000,
streaming: false,
tradeoff: 'speed=4, quality=9, cost=5',
},
// 数据分析:成本 > 质量 > 速度
'data-analytics': {
model: 'claude-haiku-4-5',
concurrency: 1, // 串行,省 token
maxRetries: 2,
timeoutMs: 60000, // 允许慢
cacheEnabled: true, // 激进缓存
tradeoff: 'speed=2, quality=7, cost=10',
},
};
// 关键:每条业务线明确自己在哪个前沿点,不混用
function getAgentConfig(productLine: string) {
const config = paretoConfigs[productLine];
if (!config) throw new Error(
`Unknown product line: ${productLine}. Must explicitly define tradeoffs first.`
);
return config;
}
帕累托支配检查 — 找出"绝对差"的配置
// 帕累托支配:如果 A 在所有维度都 >= B,则 B 被支配(B 是次优的)
function isDominated(
candidate: Config,
others: Config[],
objectives: (keyof Config)[]
): boolean {
return others.some(other =>
objectives.every(o => other[o] >= candidate[o]) &&
objectives.some(o => other[o] > candidate[o])
);
}
// 使用:淘汰被支配的配置
const paretoFront = configs.filter(c =>
!isDominated(c, configs, ['speed', 'quality', 'cost'])
);
// 剩下的才值得讨论,它们才是真正的 tradeoff 选择
⚠ 反模式
给同一个 agent 设置"又快又好又便宜"的目标,然后不停调参试图同时提升三个维度。这违反了帕累托定理。正确做法是先决定"什么最重要",再接受另外两个维度的牺牲。
拿走就能用 — 粘贴进你的 CLAUDE.md
## 架构决策原则(帕累托约束)
### 本项目的优先级(按顺序)
1. 正确性 > 速度 > 成本
- 宁可慢,不要错
- 宁可贵,不要用户不信任
### 禁止"同时优化三个维度"
- 每次架构讨论必须明确:这次牺牲哪个
- 如果有方案声称"全都能优化",必须质疑
### agent 配置时的 tradeoff 模板
- 高质量场景(对外输出):quality first,允许慢 3x、贵 5x
- 高频内部场景(数据处理):speed first,允许质量 -20%
- 实验/原型阶段:cost first,允许不稳定
核心公式
P(H|E) = P(E|H) · P(H) / P(E)
H = 假设(Claude 能/不能做某件事)
E = 证据(实际观测到的输出)
先验 P(H):做这件事之前,你对 Claude 能力的估计
似然 P(E|H):如果假设成立,观测到这个证据的概率
后验 P(H|E):看到证据后,更新的能力判断
关键直觉:不要用单次失败/成功来彻底改变判断。要积累证据,逐步更新。
Claude Code 场景 — 能力边界探测
| 先验(你的预期) | 证据(观测结果) | 后验(更新后的判断) |
| Claude 能处理这类任务(70%) |
成功了 3/3 次 |
提升到 ~92%,可以信任 |
| Claude 能处理这类任务(70%) |
失败了 1 次 |
降到 ~55%,再测 2-3 次再决策 |
| Claude 能处理这类任务(70%) |
失败了 3/3 次 |
降到 ~28%,考虑换方案 |
| 不确定(50%) |
成功 1 次,失败 1 次 |
仍然 ~50%,需要更多证据 |
代码模式 — Capability Probe
// 贝叶斯能力探测:用小样本测试更新对 Claude 的能力判断
class CapabilityBayes {
private prior: number; // 初始估计 0-1
private successes = 0;
private trials = 0;
constructor(prior = 0.5) {
this.prior = prior;
}
update(success: boolean): void {
this.trials++;
if (success) this.successes++;
}
posterior(): number {
const alpha = this.prior * 10 + this.successes;
const beta = (1 - this.prior) * 10 + (this.trials - this.successes);
return alpha / (alpha + beta);
}
decision(): 'trust' | 'uncertain' | 'fallback' {
const p = this.posterior();
if (p > 0.8) return 'trust';
if (p > 0.4) return 'uncertain';
return 'fallback';
}
}
const probe = new CapabilityBayes(0.6); // 先验 60%
for (const testCase of testCases) {
const result = await claudeAgent.run(testCase);
probe.update(evaluate(result, testCase.expected));
console.log(`后验: ${(probe.posterior() * 100).toFixed(0)}% | 决策: ${probe.decision()}`);
if (probe.decision() !== 'uncertain') break;
}
⚠ 反模式
用单次测试结论化判断 Claude 的能力。"试了一次,不行,Claude 做不到这个。" 这是点估计,不是概率估计。单次失败只是一个数据点,会把 70% 的先验更新到 55%,不是 0%。
判断需要多少次测试
- 先验强(90%+):失败 3 次才触发重新评估
- 先验中(50-70%):5 次混合结果就能给出明确方向
- 先验弱(<30%):成功 2-3 次即可提升信心
- 规则:后验超过 80% 或低于 20%,才算有足够证据做决策
拿走就能用 — 粘贴进你的 CLAUDE.md
## Claude 能力评估规则(贝叶斯原则)
### 禁止单次定论
- 1 次失败 ≠ "Claude 做不到"
- 1 次成功 ≠ "Claude 可以可靠依赖"
- 需要 3-5 次测试,再决策
### 评估触发条件
- 新类型任务:先跑 3 个样本测试,再集成到主流程
- 质量波动大:增加测试次数,确认是偶然还是系统性
### 决策阈值
- >80% 成功率(3+ 次测试)→ 可以依赖
- 40-80%:继续测,或加 retry 逻辑
- <40% → 换策略:改 prompt、换模型、或人工介入
核心公式
x̂ₙ = x̂ₙ₋₁ + K · (zₙ − x̂ₙ₋₁)
x̂ₙ = 当前估计的"真实质量"
zₙ = 本次实际观测值(单次评分)
K = 卡尔曼增益 = 信任观测 vs 信任预测的权重
K 高(接近 1)→ 更信任新观测,估计变化快
K 低(接近 0)→ 更信任历史,估计变化慢
关键直觉:单次评分不等于真实质量。真实质量 = 历史估计 × (1-K) + 当前观测 × K
区分噪声 vs 真实退化
| 观测序列 | 原始判断 | 卡尔曼估计(K=0.3) |
| 8, 8, 8, 4, 8, 8 |
看到 4 → 系统崩了 |
x̂ = 7.9 → 4 是噪声,系统正常 |
| 8, 7, 6, 5, 4, 3 |
最新是 3,还好 |
x̂ = 5.8 → 趋势恶化,需干预 |
| 4, 5, 4, 5, 4, 5 |
震荡,不知道咋办 |
x̂ ≈ 4.5 → 系统性问题 |
代码模式 — Agent 质量状态跟踪
class KalmanQualityTracker {
private estimate: number;
private uncertainty: number;
private processNoise: number;
private observationNoise: number;
constructor(initialEstimate = 7) {
this.estimate = initialEstimate;
this.uncertainty = 1;
this.processNoise = 0.1;
this.observationNoise = 2;
}
update(observed: number) {
const predictedUncertainty = this.uncertainty + this.processNoise;
const K = predictedUncertainty / (predictedUncertainty + this.observationNoise);
const prevEstimate = this.estimate;
this.estimate = this.estimate + K * (observed - this.estimate);
this.uncertainty = (1 - K) * predictedUncertainty;
const deviation = Math.abs(observed - prevEstimate);
const trend = this.estimate - prevEstimate;
return {
estimate: Math.round(this.estimate * 10) / 10,
kalmanGain: Math.round(K * 100) / 100,
status: deviation > 3 && Math.abs(trend) < 0.5 ? 'noise'
: trend < -0.3 ? 'degrading'
: 'normal',
};
}
}
⚠ 反模式
直接用原始评分驱动决策。agent 输出 3/10 → 立刻触发告警 → 重写 system prompt。但这可能只是一次难度特别高的任务带来的噪声,真实质量仍然是 7.8/10。过度响应噪声会导致系统不稳定。
拿走就能用 — 粘贴进你的 CLAUDE.md
## Agent 质量跟踪规则(卡尔曼滤波原则)
### 用移动平均代替单次评分
- 不用单次分数触发告警
- 用最近 5 次的加权平均(近期权重更高)判断趋势
### 区分噪声和真实退化
- 单次分数偏离历史均值 >3 → 大概率是噪声,观察下一次
- 连续 3 次低于历史均值 >1 → 真实退化,触发 I 项修正
### 响应阈值(防止过度响应)
- 不要因为一次差的输出修改 system prompt
- 要因为"移动平均持续下降超过 1 分"才修改
- 更新 system prompt 前,先判断是任务难度问题还是系统问题
核心概念
纳什均衡:在给定其他参与者策略的情况下,
没有任何参与者能通过单方面改变策略来改善自身结果。
多 Agent 系统中:
- 每个 agent 都有自己的"最优策略"
- 均衡 = 所有 agent 的策略互相一致、互相强化
- 非均衡 = 某个 agent 总想"偏离"→ 系统不稳定
关键直觉:不是让每个 agent "最优",而是让系统的均衡点恰好在你想要的地方。
为什么多 Agent 系统会失衡
典型场景:囚徒困境
Writer agent 想通过审核 → 倾向于写"安全"内容。Reviewer agent 想找到问题 → 倾向于挑剔。结果:writer 越来越保守,reviewer 越来越严苛,最终输出质量反而下降。这是"军备竞赛"均衡,不是你想要的均衡。
| 系统设计 | 均衡类型 | 结果 |
| Reviewer 只评分不解释 |
对抗均衡 |
Writer 猜测标准 → 质量随机 |
| Reviewer 给出改进方向 |
合作均衡 |
Writer 有明确目标 → 质量上升 |
| 共享评分标准 rubric |
协调均衡 |
双方对齐 → 系统最优 |
代码模式 — 协调均衡设计
// 错误:各 agent 独立定义"成功"标准 → 对抗均衡
const writerPrompt = `写一篇高质量文章,要通过审核`
const reviewerPrompt = `严格审核文章,找出所有问题`
// 结果:writer 写防御性内容,reviewer 挑越来越细的毛病
// 正确:共享 rubric,建立协调均衡
const SHARED_RUBRIC = {
clarity: { weight: 0.3, desc: '逻辑清晰,论点有层次' },
accuracy: { weight: 0.3, desc: '事实准确,代码可运行' },
actionable: { weight: 0.2, desc: '读者可以立即采取行动' },
conciseness: { weight: 0.2, desc: '没有多余的话' },
}
const writerPrompt = `
写一篇满足以下标准的文章:
${JSON.stringify(SHARED_RUBRIC)}
每个维度目标分:≥7/10
`
const reviewerPrompt = `
按以下标准评分,给出每个维度的分数和具体改进建议:
${JSON.stringify(SHARED_RUBRIC)}
目标:帮助 writer 达到每项 ≥7/10,不是找茬
`
async function coordinatedGeneration(topic: string) {
let draft = await writer.generate(topic, writerPrompt)
for (let i = 0; i < 3; i++) {
const review = await reviewer.evaluate(draft, reviewerPrompt)
if (review.scores.every(s => s.score >= 7)) break
draft = await writer.revise(draft, review.feedback)
}
return draft
}
⚠ 反模式
给 critic agent 设置"找到至少 5 个问题才算完成任务"。这会把系统推向对抗均衡——即使内容质量很高,critic 也会捏造问题来完成任务。永远不要用"问题数量"作为 critic 的成功指标。
✓ 最佳实践
用"共享 rubric + 收敛判断"代替"writer vs reviewer"对抗结构。让系统的自然均衡点与你的目标对齐,而不是靠强制约束压制对抗行为。
拿走就能用 — 粘贴进你的 CLAUDE.md
## 多 Agent 系统设计规则(纳什均衡原则)
### 共享评分标准
- 所有参与同一任务的 agent 必须使用相同的 rubric
- rubric 在系统提示开头声明,所有 agent 都能看到
### 禁止对抗性指标
- 不允许用"找到问题数量"衡量 critic agent 的效果
- 不允许用"通过审核率"衡量 writer agent 的效果
- 只用"最终输出质量"作为整体系统指标
### 收敛条件
- 每个迭代循环必须有明确的终止条件(分数阈值或最大轮次)
- 若达到最大轮次仍未收敛,升级为人工介入,不要静默降级
核心概念
李雅普诺夫稳定:系统从任意接近均衡点的初始状态出发,
都能保持在均衡点附近(不发散)。
渐近稳定:不仅不发散,还能最终收敛回均衡点。
不稳定:微小扰动会导致系统状态无界发散。
关键直觉:不要只针对"正常输入"测试你的 agent,要针对"边界扰动"测试。真正的鲁棒性 = 遇到扰动后能回到正轨,而不是一路偏离。
Agent 流水线的稳定性问题
典型失稳场景
你的摘要 agent 在正常输入下输出很好。但当输入文章包含大量代码块时,它开始输出格式混乱;当输入是非常短的文本时,它又开始"编造"内容。这是一个不稳定的系统——小扰动导致系统发散到你不想要的状态。
| 系统行为 | 稳定性类型 | 对应动作 |
| 异常输入 → 仍然输出合理结果 |
李雅普诺夫稳定 |
继续,可以上线 |
| 异常输入 → 短暂偏离后自动回正 |
渐近稳定 |
最佳状态,继续 |
| 异常输入 → 输出越来越奇怪 |
不稳定 |
加边界检查,截断异常路径 |
| 正常输入偶尔触发完全错误的路径 |
临界稳定 |
找到触发条件,加断路器 |
代码模式 — 稳定性测试框架
const stabilityTests = [
{
name: '短文本扰动',
perturbations: ['ok', '.', ''],
isStable: (out: string) => out.length < 200,
},
{
name: '超长输入扰动',
perturbations: ['x'.repeat(50000)],
isStable: (out: string) => !out.includes('error'),
},
]
for (const test of stabilityTests) {
for (const p of test.perturbations) {
const out = await agent.run(p)
if (!test.isStable(out))
console.warn(`⚠ 不稳定:${test.name}`)
}
}
⚠ 反模式
只用"正常用例"测试 agent 性能,然后在生产环境遇到边界输入时崩溃。真实用户输入的分布远比你预期的宽——空字符串、超长文本、特殊字符都会出现。
拿走就能用 — 粘贴进你的 CLAUDE.md
## Agent 鲁棒性规则(李雅普诺夫原则)
### 必须处理的边界输入
- 空输入:返回明确错误,不要静默失败
- 超长输入(>预期 5 倍):截断 + 告知,不要崩溃
- 非预期语言:检测后明确告知,不要乱猜
### 稳定域定义
- 每个 agent 的 system prompt 开头必须声明"本 agent 处理什么类型的输入"
- 超出稳定域的输入应触发 fallback,不是随机输出
### 发散预防
- 不允许 agent 在单次对话中无限追加内容(设置最大 token 限制)
- 不允许 agent 自我引用上一轮输出作为新输入(防止雪球效应)
核心概念
阻抗匹配:信号源阻抗 = 负载阻抗时,功率传输效率最高。
LLM 类比:
- 信号源 = 你的意图(Prompt)
- 负载 = 模型的"接收方式"
- 匹配良好 → 模型准确执行意图,最小幻觉
- 匹配不良 → 模型误解,过度脑补,反复错方向
关键直觉:模型的"阻抗"是固定的。问题不是模型不够聪明,而是你的 Prompt 和它的接收方式不匹配。
常见阻抗不匹配模式
| 不匹配类型 | 症状 | 匹配方案 |
| 意图太模糊 |
模型过度脑补,答案方向偏 |
写明"你不需要做什么" |
| 约束没有层次 |
模型平等对待所有要求,优先级混乱 |
用 1/2/3 明确优先级顺序 |
| 输出格式未指定 |
模型猜测格式,每次不同 |
给出示例格式(few-shot) |
| 一次请求太多 |
模型完成了大部分,遗漏了少数 |
拆分为顺序的子任务 |
代码模式 — 阻抗匹配改造
// 低匹配(常见写法)
"帮我优化这段代码"
// 高匹配(对齐模型接收方式)
`目标:减少数据库查询次数(不是重构代码结构)
约束:不改函数签名,不引入新依赖
输出:① 问题诊断 ② 具体改动 ③ 改后代码
不需要:测试代码,基础知识解释`
// 现在模型知道:做什么、不做什么、输出什么格式
⚠ 反模式
认为"Prompt 越长越好"。超过一定长度后,每增加一条规则都可能降低效果——模型在众多约束之间权衡,阻抗反而增大。真正的匹配是精简 Prompt + 明确优先级。
拿走就能用 — 粘贴进你的 CLAUDE.md
## Prompt 设计规则(阻抗匹配原则)
### 必须包含的元素
- 任务目标:一句话说清楚要做什么
- 排除项:明确说"不需要做什么"(减少过度脑补)
- 输出格式:提供一个示例
### 禁止的模式
- 不用"帮我优化/改进/完善"等模糊动词
- 不在单次请求中混合多个不同类型的任务
- 不用"尽量/最好/如果可以"(会降低执行优先级)
核心公式
P(Xₙ₊₁ = s | X₁, X₂, ..., Xₙ) = P(Xₙ₊₁ = s | Xₙ)
下一个状态只取决于当前状态,与历史无关。
对 LLM 的含义
Transformer 理论上能看到所有历史(全局 attention),但实践中:远处的 token attention 权重更低,早期指令会被稀释。Context window 是硬截断。这意味着你的对话历史越长,早期的约束越容易被"遗忘"。
识别信号
| 现象 | 马尔可夫解释 |
| 长对话后 Claude 忽略早期指令 | 状态漂移——远处状态影响力衰减 |
| 多步 Agent 任务偏离原始目标 | 每步只看当前状态,无法回溯 |
| CLAUDE.md 里的规则被遗忘 | context 被新内容稀释 |
代码模式 — Agent 状态机
# 显式状态转换,不依赖对话历史
class AgentStateMachine:
states = ["IDLE", "PLANNING", "EXECUTING", "VERIFYING", "DONE"]
def transition(self, current_state, event):
transitions = {
("IDLE", "task_received"): "PLANNING",
("PLANNING", "plan_approved"): "EXECUTING",
("EXECUTING", "task_done"): "VERIFYING",
("EXECUTING", "error"): "PLANNING", # 重新规划
("VERIFYING", "passed"): "DONE",
}
return transitions.get((current_state, event), current_state)
错误用法
在 session 开头设置约束,然后进行大量对话,期望约束始终生效。状态漂移会让早期约束失去影响力。
修复:把核心约束放在 CLAUDE.md(每次都重新加载),或在长对话中定期用 /compact 保留关键约束。
核心概念
系统整体表现出其组成部分所没有的性质。蚁群无中央指挥却能建造复杂巢穴;神经元不会"思考"但大脑会。LLM 超过某规模阈值后,能力出现非线性跳跃。
识别信号
| 现象 | 涌现解释 |
| 同一 prompt 在 Haiku 和 Sonnet 效果差异极大 | 某能力在小模型上未涌现 |
| Multi-Agent 系统比单 Agent 更能发现问题 | 协作涌现出角色制衡效果 |
| Claude 偶尔能做出你没预期的推理 | 涌现能力——可遇不可求 |
代码模式 — 利用多 Agent 涌现
# 单 Agent 三重角色——互相干扰
result = agent.plan_and_execute_and_verify(task)
# 分离角色——涌现出制衡效果
plan = planning_agent.run(task)
execution = execution_agent.run(plan)
verdict = verification_agent.run(task, execution) # 独立视角
错误用法
把涌现能力当成稳定的生产保障。"Claude 上次能做这个"不代表每次都能。涌现能力上下文敏感、不可精确复现。
原则:把涌现当惊喜,把显式设计当基础。关键任务用明确约束,不靠能力涌现。
| 你遇到的问题 | 对应模式 | 关键动作 |
| Prompt 调了很久,质量卡在某个分数上不去 |
模拟退火 |
升温,换结构,接受暂时退步 |
| Multi-agent 并行了,但结果不一致/互相冲突 |
傅里叶分解 |
做正交测试,找隐性依赖 |
| 多加了一些东西(agent/context/rules),系统突然变差 |
相变 |
你越过临界点了,退回找相变点 |
| Agent 质量时好时坏,不知道如何系统性改善 |
PID 控制 |
区分 P/I/D,对症下药 |
| System prompt 很长但模型经常"跑偏" |
奇异吸引子 |
改成"绝对不做什么"的边界设计 |
| 同一个 prompt 跑出来差异很大,不稳定 |
香农熵 |
高熵 = prompt 有歧义,加约束/examples |
| 团队讨论 agent 配置,争论"又快又好又便宜" |
帕累托前沿 |
先定优先级,不存在全部最优 |
| 试了一次失败,觉得 Claude 做不到这件事 |
贝叶斯更新 |
单次失败只更新先验 -15%,再测 3 次 |
| 单次低分不知道是偶发还是系统质量下降 |
卡尔曼滤波 |
看移动平均趋势,而不是单次评分 |
| 多 agent 互相掣肘,质量越迭代越差 |
纳什均衡 |
检查 agent 目标是否对抗,统一 rubric |
| 正常输入没问题,边界输入输出乱飞 |
李雅普诺夫稳定性 |
做扰动测试,加边界检查和 fallback |
| Prompt 写了很多,但模型经常"理解偏了" |
阻抗匹配 |
加"不需要做什么",给出输出示例 |
| 常见错误思路 | 背后的误区 | 正确模式 |
| "再加几条规则 prompt 就会好" |
忽视相变临界点 |
测临界点,超过后拆 sub-agent |
| "这次输出好,把它硬编码成模板" |
混淆单次输出与吸引域 |
设计边界,不复现单次 |
| "Promise.all 包起来就是并行" |
没做正交检查 |
先画依赖图,再决定并发结构 |
| "每次输出差了就改措辞" |
只看 P 项,忽视 I 和 D |
区分本次误差/历史积累/趋势 |
| "输出不稳定,降低 temperature" |
把熵问题当温度问题 |
先诊断 prompt 是否有歧义 |
| "我们要最快最好最省钱的方案" |
无视帕累托约束 |
先定优先级,再找前沿上的点 |
| "调了两天,这个 prompt 已经最优了" |
局部最优,没有退火 |
换结构探索,接受暂时退步 |
| "Claude 失败了一次,这个任务它做不到" |
点估计,单次定论 |
贝叶斯更新,3-5 次测试再决策 |
| "这次输出 3/10,立刻重写 system prompt" |
把噪声当趋势,过度响应 |
卡尔曼滤波,看移动平均而非单次分数 |
| "让 reviewer 找出更多问题,质量就会提升" |
制造对抗均衡,系统自我破坏 |
共享 rubric,让 writer 和 reviewer 目标一致 |
| "测试通过了,应该没问题"(只测正常路径) |
没有做扰动测试,稳定性未知 |
针对空输入、超长输入、特殊字符做专项测试 |
| "把所有要求都写进一个 Prompt 应该最全" |
Prompt 过长,阻抗增大,执行率下降 |
精简 Prompt,加优先级和排除项,而不是堆积规则 |