ai自学笔记 (2.prompt 踩坑与优化)

用 Claude API 做结构化 JSON 输出(10 个 hook) 记录问题原因、修复,和复用的 prompt 模板。


踩坑记录

坑 1:模型不输出纯 JSON,而是包裹中文前言

现象 :即使设置了 output_config.format (json_schema),Claude 仍然返回:

复制代码
好的,姐妹!以下是为您生成的 10 个 hook...
{"hooks": [...]}

原因

  • Claude 4.7 在中文场景下倾向于"礼貌回复",即使有结构化输出约束也会附上前言
  • output_config.format 是约束而非强制------不能 100% 依赖它
  • 中文 system prompt + 中文 user message 时,模型更容易"聊天化"

修复(双层防护)

第一层------Prompt 加强,在 system prompt 末尾加:

复制代码
## 输出格式(极其重要)

你必须只输出一个合法的 JSON 对象,不要加任何前缀说明、后缀总结、markdown 代码块标记。
正确示例:{"hooks":[{"text":"...","style":"悬念式","score":8,"reason":"..."}]}
错误示例:好的,以下是为您生成的...\`\`\`json...\`\`\`
不要输出 "以下是"、"好的"、"为您生成" 这类废话,直接输出 JSON。
  • 用"正确示例"和"错误示例"对比,比单纯说"不要"有效得多
  • 明确列出常见废话("以下是"、"好的"、"为您生成")
  • 放在 prompt 末尾(模型的 recency bias 会让它更重视末尾指令)

第二层------代码容错,在 JSON.parse 前加提取逻辑:

typescript 复制代码
let rawText = textBlock.text.trim();

// 1. 如果被包裹在 markdown 代码块中,提取出来
const codeBlockMatch = rawText.match(/\`\`\`(?:json)?\s*([\s\S]*?)\`\`\`/);
if (codeBlockMatch) {
  rawText = codeBlockMatch[1].trim();
}

// 2. 尝试找到 JSON 对象的起始位置
const jsonStart = rawText.indexOf('{"hooks"');
if (jsonStart > 0) {
  rawText = rawText.slice(jsonStart);
}

// 3. 解析
const data = JSON.parse(rawText);

三层防护(markdown 代码块 → 文本中挖 JSON → 报错)保证健壮。

坑 2:prompt 过长导致模型"浏览"而非"精读"

现象:10 种风格 + 5 个平台规则 + 评分标准,prompt 接近 2000 字,模型可能跳读某些约束。

建议

  • 关键约束放末尾(recency bias)
  • 用明确的分隔线和层级标题帮助模型定位
  • 不要用"请"、"如果可以的话"这类弱化词------用"必须"、"只能"

坑 3:结构化输出 ≠ 100% 保证

经验output_config.format (json_schema) 是概率性约束,不是硬保证。永远要:

  1. Prompt 层面强调格式
  2. 代码层面做 JSON 提取容错
  3. 两个路由(generate + regenerate)都要加同样的容错

可复用的 Prompt 模板

结构化 JSON 输出的通用 System Prompt 模板

复制代码
你是一个[角色描述]。

## 你的任务
[任务描述]

## 规则
[业务规则 1-N]

## 输出格式(最重要)

你必须只输出一个合法的 JSON 对象。
- 不要加任何前缀说明或后缀总结
- 不要用 markdown 代码块包裹
- 不要输出"好的"、"以下是"、"为您生成"等人机对话用语

正确格式示例:
{"key": "value"}

错误格式示例(禁止):
好的,以下是结果... {"key": "value"}
```json
{"key": "value"}


### 关键原则

1. **末尾强调**:格式约束放 prompt 最后一段
2. **正反示例**:同时给出正确和错误的输出示例
3. **明确禁止词**:列出"以下是"、"好的"、"为您生成"、"当然"等常见废话
4. **简短有力**:用"必须"、"禁止"、"只能",不要用"请"、"如果可以的话"
5. **代码兜底**:永远在 `JSON.parse` 前加提取/容错逻辑

---

## 生成类 Prompt 的通用 Checklist

- [ ] 角色定位是否清晰?(一句话,不要多)
- [ ] 输出数量是否明确?("恰好 10 个",不是"10 个左右")
- [ ] 格式约束是否在末尾且醒目?
- [ ] 是否有正反示例对比?
- [ ] 评分/评价标准是否量化?("好奇心缺口 30% + 情感冲击 30%",不是"综合判断")
- [ ] 是否避免了弱化词("请"、"尽量"、"如果可以")?
- [ ] 代码端是否做了 JSON 解析容错?

---

## 编码侧的通用 JSON 提取函数

```typescript
function extractJson<T>(text: string): T {
  let raw = text.trim();

  // 去掉 markdown 代码块
  const codeMatch = raw.match(/```(?:json)?\s*([\s\S]*?)```/);
  if (codeMatch) raw = codeMatch[1].trim();

  // 找到 JSON 起始
  const start = raw.indexOf("{");
  const end = raw.lastIndexOf("}");
  if (start > -1 && end > start) {
    raw = raw.slice(start, end + 1);
  }

  return JSON.parse(raw) as T;
}

这个函数可以复用到任何需要从 AI 响应中提取 JSON 的项目。

相关推荐
Json_1 小时前
Claude Code 使用指南:高频命令、快捷键、核心功能与实战技巧详解
agent·ai编程·claude
pluviophile_s1 小时前
数据结构:第1讲:算法分析
数据结构·笔记
belldeep2 小时前
CSR座席模块 如何结合AI 大模型应用?
人工智能·ai·大模型·csr坐席
05候补工程师2 小时前
【硬核干货】用“算法”思维袭英语新题型:集合逆清晰除与降维打击解题法
经验分享·笔记·考研·算法·学习方法
许长安2 小时前
Redis 跳表实现详解
数据库·c++·经验分享·redis·笔记·缓存
东风微鸣2 小时前
AI 时代,闲暇为何比忙碌更重要
ai
June bug2 小时前
【雅思学习笔记】Part2话题词汇及表达
笔记·学习
Hehuyi_In3 小时前
postgres-howto 学习笔记
笔记·学习·postgresql·脚本·how to
蜗牛^^O^3 小时前
Agent学习笔记
笔记·学习