Skip to content

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 示例选择原则

  1. 代表性: 覆盖常见场景
  2. 边界情况: 包含极端或特殊情况
  3. 反例: 展示"不要这样做"

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
实现一个包含标题、描述和操作按钮的卡片组件,垂直间距 16px

5. 角色设定 (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 API

6. 约束与边界 (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. 关键要点

  1. 结构化 > 随意: 使用固定模板组织 Prompt
  2. 明确 > 隐含: 显式说明所有要求
  3. 示例 > 描述: 一个好示例胜过百字描述
  4. 约束 > 自由: 明确边界减少意外输出
  5. 迭代 > 一次性: 通过反馈持续改进 Prompt

前端面试知识库