Prompt 设计模式:从玄学到工程 ✨
"好的 Prompt 是设计出来的,不是试出来的。"
1. System Prompt 设计原则
1.1 结构化 System Prompt 模板
markdown
# Role & Identity
你是 [角色描述],专注于 [领域]。
# Core Capabilities
你擅长:
- 能力 1
- 能力 2
# Rules & Constraints (重要!)
## MUST (必须做)
- 规则 1
- 规则 2
## MUST NOT (禁止)
- 禁止行为 1
- 禁止行为 2
# Output Format
[指定输出格式]
# Examples (可选)
[提供示例]1.2 实战示例:代码审查助手
markdown
# Role
你是一名资深前端代码审查专家,有 10 年 React/TypeScript 经验。
# Core Focus
- 性能问题 (不必要的渲染、内存泄漏)
- 类型安全 (any 滥用、类型断言)
- 可维护性 (代码重复、命名不清)
- 安全漏洞 (XSS、敏感信息暴露)
# Rules
## MUST
- 对每个问题给出具体行号
- 提供修复后的代码示例
- 按严重程度排序: Critical > Major > Minor
## MUST NOT
- 不要提及代码风格问题 (由 ESLint 处理)
- 不要建议不必要的重构
# Output Format
## [严重程度] 问题标题
**位置**: 第 X 行
**问题**: 描述
**修复**:
```code
修复后的代码
```2. 结构化输出 (Structured Output)
2.1 JSON 输出
让模型返回可解析的结构化数据:
markdown
分析以下用户反馈,提取结构化信息:
反馈: "登录页面太慢了,而且手机上按钮太小点不到,希望能加个记住密码功能"
请以 JSON 格式输出:
{
"issues": [
{
"category": "performance|ux|feature_request|bug",
"description": "问题描述",
"severity": "high|medium|low"
}
],
"suggested_priority": "p0|p1|p2"
}2.2 使用 JSON Schema 强制格式
javascript
// OpenAI 的 Structured Outputs
const response = await openai.chat.completions.create({
model: "gpt-4o",
messages: [...],
response_format: {
type: "json_schema",
json_schema: {
name: "feedback_analysis",
strict: true,
schema: {
type: "object",
properties: {
issues: {
type: "array",
items: {
type: "object",
properties: {
category: {
type: "string",
enum: ["performance", "ux", "feature_request", "bug"]
},
description: { type: "string" },
severity: {
type: "string",
enum: ["high", "medium", "low"]
}
},
required: ["category", "description", "severity"]
}
}
},
required: ["issues"]
}
}
}
});2.3 Anthropic Tool Use 实现结构化输出
javascript
// 使用 Tool 定义强制结构化输出
const response = await anthropic.messages.create({
model: "claude-sonnet-4-20250514",
tools: [{
name: "output_analysis",
description: "Output the structured analysis",
input_schema: {
type: "object",
properties: {
issues: {
type: "array",
items: {
type: "object",
properties: {
category: { type: "string" },
description: { type: "string" },
severity: { type: "string" }
}
}
}
},
required: ["issues"]
}
}],
tool_choice: { type: "tool", name: "output_analysis" }, // 强制使用此 tool
messages: [...]
});3. Chain-of-Thought (思维链)
3.1 基础 CoT
简单地要求模型"思考":
markdown
# 基础版本
请一步步思考,然后回答这个问题...
# 更有效的版本
请按以下步骤分析这个问题:
1. 首先,识别问题的关键信息
2. 然后,列出可能的原因
3. 接着,逐一验证每个原因
4. 最后,给出结论和解决方案3.2 结构化 CoT: 代码 Debug
markdown
# Context
下面的 React 组件在用户快速输入时崩溃了:
[代码]
# Task
找出并修复这个 Bug。
# Required Analysis Steps
## Step 1: 复现路径
描述用户操作路径和预期 vs 实际行为
## Step 2: 依赖追踪
列出组件的所有 useEffect 依赖,画出触发关系图
## Step 3: 状态变化
模拟快速输入时的状态变化序列
## Step 4: 根因定位
指出导致问题的具体代码行和原因
## Step 5: 修复方案
提供修复代码并解释为什么这能解决问题3.3 Zero-shot CoT vs Few-shot CoT
markdown
# Zero-shot CoT (无示例)
让我们一步步思考这个性能问题...
# Few-shot CoT (带示例) - 更可靠
下面是分析 React 性能问题的方法:
## 示例 1
问题: 列表滚动卡顿
分析:
1. 检查列表项数量 → 1000+ 项
2. 检查是否虚拟化 → 否
3. 检查重渲染 → 每个 item 都重渲染
结论: 需要实现虚拟列表 + memo 优化
## 示例 2
问题: 页面初始加载慢
分析:
1. 检查 bundle 大小 → 2MB
2. 检查代码分割 → 未使用
3. 检查首屏依赖 → 加载了未使用的图表库
结论: 实现路由级代码分割
## 你的问题
[描述问题]
请按照上述分析方法进行分析:4. Few-shot Learning (少样本学习)
4.1 示例选择原则
- 代表性: 覆盖常见场景
- 边界情况: 包含极端或特殊情况
- 反例: 展示"不要这样做"
4.2 实战:代码转换
markdown
将 Class 组件转换为 Function 组件 + Hooks
## Example 1: 简单状态
Input:
class Counter extends React.Component {
state = { count: 0 };
increment = () => this.setState({ count: this.state.count + 1 });
render() {
return <button onClick={this.increment}>{this.state.count}</button>;
}
}
Output:
function Counter() {
const [count, setCount] = useState(0);
const increment = () => setCount(c => c + 1);
return <button onClick={increment}>{count}</button>;
}
## Example 2: 生命周期
Input:
class DataFetcher extends React.Component {
state = { data: null };
componentDidMount() {
fetch(this.props.url).then(r => r.json()).then(data => this.setState({ data }));
}
componentDidUpdate(prevProps) {
if (prevProps.url !== this.props.url) {
fetch(this.props.url).then(r => r.json()).then(data => this.setState({ data }));
}
}
render() { return <div>{JSON.stringify(this.state.data)}</div>; }
}
Output:
function DataFetcher({ url }) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url).then(r => r.json()).then(setData);
}, [url]); // 依赖项处理了 componentDidMount 和 componentDidUpdate
return <div>{JSON.stringify(data)}</div>;
}
## Your Task
[粘贴需要转换的 Class 组件]4.3 负面示例 (Negative Examples)
markdown
实现组件间距,遵循 "Gap-First" 布局规范:
## ❌ Wrong (不要这样做)
<Button>Submit</Button>
<Button style={{ marginTop: 16 }}>Cancel</Button>
## ✅ Correct (这样做)
<div className="flex flex-col gap-4">
<Button>Submit</Button>
<Button>Cancel</Button>
</div>
## ❌ Wrong
<Header />
<div style={{ marginTop: 24 }}>
<Content />
</div>
## ✅ Correct
<div className="space-y-6">
<Header />
<Content />
</div>
## Your Task
实现一个包含标题、描述和操作按钮的卡片组件,垂直间距 16px5. 角色设定 (Role Prompting)
5.1 有效的角色描述
markdown
# 弱角色描述
你是一个 React 专家。
# 强角色描述
你是 React 核心团队成员,主要贡献了 Concurrent Mode 和 Suspense 特性。
你的代码风格特点:
- 极度重视性能,会主动考虑渲染优化
- 喜欢使用 TypeScript 泛型实现类型安全
- 倾向于组合而非继承
- 会考虑 Edge Case 和错误处理
当被问及代码问题时,你会:
1. 先确认理解了问题
2. 解释你的思考过程
3. 给出代码示例
4. 指出潜在的坑和最佳实践5.2 专家 Persona 模板
markdown
# Expert Persona: Senior Frontend Architect
## Background
- 15 年前端开发经验
- 主导过 5+ 大型 SPA 项目重构
- 熟悉 React、Vue、Svelte 内部原理
## Thinking Style
- 从架构层面思考问题,不急于写代码
- 会考虑团队协作和代码可维护性
- 对性能有洁癖,但不会过度优化
## Communication Style
- 先问清楚需求背景
- 给出多个方案让人选择
- 解释 trade-offs
## Knowledge Areas
- 状态管理: Redux, Zustand, Jotai, Valtio
- 构建工具: Webpack, Vite, esbuild
- 测试: Jest, Vitest, Playwright
- 性能: Core Web Vitals, Performance API6. 约束与边界 (Constraints)
6.1 硬性约束
markdown
# HARD CONSTRAINTS (违反则无效)
- 只使用 TypeScript,禁止 any
- 只使用 React 18+ 特性
- 所有组件必须是函数组件
- 必须包含完整的类型定义
# SOFT CONSTRAINTS (优先但可协商)
- 优先使用 Tailwind CSS
- 优先使用 Zustand 状态管理
- 单个文件不超过 200 行6.2 输出约束
markdown
# Output Constraints
- 最多返回 3 个方案
- 每个代码块不超过 50 行
- 必须包含使用示例
- 不要解释基础概念 (假设读者是高级开发者)6.3 安全约束
markdown
# Security Constraints
- 不要在代码中硬编码任何 API Key 或密码
- 所有用户输入必须进行验证和转义
- 不要使用 dangerouslySetInnerHTML 除非明确说明
- 不要使用 eval() 或 Function() 构造函数7. Prompt 组合技巧
7.1 Prompt Chaining (提示链)
将复杂任务拆分为多个步骤:
javascript
// Step 1: 分析需求
const analysis = await callLLM(`
分析以下用户故事,提取技术需求:
${userStory}
输出 JSON: { components: [], apis: [], states: [] }
`);
// Step 2: 设计接口
const interfaces = await callLLM(`
根据以下技术需求,设计 TypeScript 接口:
${analysis}
只输出接口定义,不要实现
`);
// Step 3: 实现代码
const implementation = await callLLM(`
实现以下接口:
${interfaces}
技术栈: React + Zustand
`);7.2 Self-Consistency (自洽性验证)
多次生成并取一致结果:
javascript
async function generateWithConsistency(prompt, n = 3) {
const responses = await Promise.all(
Array(n).fill(null).map(() =>
callLLM(prompt, { temperature: 0.7 })
)
);
// 让 LLM 分析结果一致性
const consensus = await callLLM(`
以下是 ${n} 个不同的回答,找出它们的共识:
${responses.map((r, i) => `## 回答 ${i+1}\n${r}`).join('\n\n')}
输出最可靠的综合答案
`);
return consensus;
}7.3 Reflexion (反思)
让模型自我检查和改进:
markdown
# Initial Task
[生成代码]
# Self-Review
现在请审查你刚才生成的代码:
1. 是否有类型安全问题?
2. 是否处理了边界情况?
3. 是否有性能问题?
4. 代码是否可测试?
如果发现问题,请输出改进后的版本。8. 企业级 Prompt 管理
8.1 Prompt 版本控制
yaml
# prompts/code-review-v2.1.yaml
metadata:
name: code-review
version: 2.1.0
author: team-ai
updated: 2024-01-15
changelog: "添加了 TypeScript 特定规则"
prompt:
system: |
你是代码审查专家...
template: |
请审查以下代码:
```{{language}}
{{code}}
```
tests:
- input:
language: typescript
code: "const x: any = 1;"
expected:
contains: ["避免使用 any", "类型安全"]8.2 Prompt 复用
javascript
// prompts/base.js
export const BASE_RULES = `
## Universal Rules
- 使用 TypeScript
- 添加 JSDoc 注释
- 处理错误情况
`;
// prompts/react.js
import { BASE_RULES } from './base.js';
export const REACT_PROMPT = `
${BASE_RULES}
## React Specific
- 使用函数组件
- 正确处理 useEffect 依赖
- 使用 memo 优化重渲染
`;9. 常见反模式
9.1 ❌ 反模式列表
| 反模式 | 问题 | 改进 |
|---|---|---|
| 过度角色扮演 | "你是宇宙最强程序员" | 具体描述专业能力 |
| 模糊指令 | "写好一点" | "遵循 SOLID 原则" |
| 规则冲突 | "要简洁" + "要详细解释" | 明确优先级 |
| 过多规则 | 20+ 条规则 | 精简到 5-7 条核心规则 |
| 没有示例 | 期望特定格式但不给例子 | 提供 2-3 个示例 |
9.2 调试 Prompt 的方法
markdown
# 当输出不符合预期时:
1. 检查是否提供了足够的上下文
2. 检查规则是否有歧义或冲突
3. 添加明确的格式示例
4. 使用更低的 temperature
5. 拆分为多个简单任务
6. 添加 "如果不确定,请询问" 的规则10. 关键要点
- 结构化 > 随意: 使用固定模板组织 Prompt
- 明确 > 隐含: 显式说明所有要求
- 示例 > 描述: 一个好示例胜过百字描述
- 约束 > 自由: 明确边界减少意外输出
- 迭代 > 一次性: 通过反馈持续改进 Prompt