Skip to content

Part 4: 正确使用 AI 编程 (25-30 min)

核心思路:从「怎么做」出发,通过现场演示展示 Best Practice

4.1 Context Engineering 实操要点

Part 2 讲了 Context Engineering 是什么,这里讲怎么做

text
┌─────────────────────────────────────────────────────────────────────┐
│  Context Engineering 的核心思维                                       │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│    ❌ 错误思维:「我要把所有信息都告诉 AI」                            │
│                                                                     │
│    ┌──────────────────────────────────────────────────────────┐    │
│    │  项目文档 + 所有代码 + 历史对话 + 各种规范 + ...            │    │
│    │                         │                                 │    │
│    │                         ▼                                 │    │
│    │                   Context 爆炸                            │    │
│    │                         │                                 │    │
│    │                         ▼                                 │    │
│    │              准确率下降 (Context Rot)                      │    │
│    └──────────────────────────────────────────────────────────┘    │
│                                                                     │
│    ✅ 正确思维:「最小化高信号 Token」                                │
│                                                                     │
│    ┌──────────────────────────────────────────────────────────┐    │
│    │  只给当前任务需要的信息                                     │    │
│    │                         │                                 │    │
│    │                         ▼                                 │    │
│    │            ┌─────────────────────┐                       │    │
│    │            │  System Prompt      │ ← CLAUDE.md (精简)     │    │
│    │            │  + 相关文件         │ ← 按需读取              │    │
│    │            │  + 当前任务描述     │ ← 具体、明确            │    │
│    │            └─────────────────────┘                       │    │
│    │                         │                                 │    │
│    │                         ▼                                 │    │
│    │                   高质量输出                               │    │
│    └──────────────────────────────────────────────────────────┘    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

三条核心原则(来自 Anthropic 官方指南):

原则说明实操建议
Context 是有限资源准确率随 token 数增加而下降定期 /clear,不要让对话无限累积
工具集要精简每个工具占用 Context,功能重叠会让 AI 困惑MCP 不要装太多,保持功能不重叠
具体胜过模糊「写测试」不如「为 foo.py 的登出边界情况写测试,不要用 mock」花时间写好 prompt,比反复纠正划算

4.1.1 好 Context vs 坏 Context

这是同一个需求的两种写法,效果天差地别:

text
┌─────────────────────────────────────────────────────────────────────┐
│  ❌ 坏 Context                                                       │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  「帮我写一个时钟」                                                  │
│                                                                     │
│  问题:                                                              │
│  · 什么样的时钟?数字?模拟?                                        │
│  · 什么技术栈?React?Vue?原生 JS?                                 │
│  · 什么风格?简约?华丽?                                            │
│  · 要什么功能?只显示时间?还是要闹钟?                              │
│                                                                     │
│  结果:AI 自己猜,猜错了再改,浪费 Context                           │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│  ✅ 好 Context                                                       │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  「用原生 HTML/CSS/JS 写一个数字时钟:                               │
│                                                                     │
│   功能要求:                                                         │
│   - 显示当前时间(时:分:秒)                                         │
│   - 每秒自动更新                                                     │
│   - 24 小时制                                                        │
│                                                                     │
│   样式要求:                                                         │
│   - 深色背景 (#1a1a2e)                                               │
│   - 白色数字,使用等宽字体                                           │
│   - 居中显示,字号要大                                               │
│                                                                     │
│   文件结构:单个 index.html 文件,CSS 和 JS 内联」                   │
│                                                                     │
│  结果:AI 一次性给出符合预期的代码                                   │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

写好 Context 的检查清单

  • [ ] 技术栈明确了吗?
  • [ ] 功能边界清晰吗?
  • [ ] 有没有可能被误解的地方?
  • [ ] 输出格式/文件结构说清楚了吗?

4.1.2 提问心智:模拟器而非实体

专家观点 — Andrej Karpathy

背景:前 Tesla AI 总监、OpenAI 联合创始人、斯坦福 CS231n 课程讲师 来源:2025 年 12 月 X 推文 [1]

「不要把 LLM 当作实体(Entity),要当作模拟器(Simulator)。」

这是什么意思?

text
┌─────────────────────────────────────────────────────────────────────┐
│  LLM 是模拟器,不是实体                                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│    ❌ 把 LLM 当「实体」                                              │
│                                                                     │
│    你: 「关于 XXX,你怎么看?」                                       │
│                                                                     │
│    问题:根本不存在「你」。                                          │
│                                                                     │
│    LLM 会怎么做?                                                    │
│    → 采用一个「人格嵌入向量」(personality embedding vector)          │
│    → 这个向量来自微调数据的统计规律                                  │
│    → 模拟一个「大众脸」来回答你                                      │
│                                                                     │
│    结果:你得到的是一个「平均意见」,不是深思熟虑的观点               │
│                                                                     │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│    ✅ 把 LLM 当「模拟器」                                            │
│                                                                     │
│    你: 「如果要探讨 XXX 这个话题,最合适的专家是谁?他们会怎么说?」  │
│                                                                     │
│    LLM 会怎么做?                                                    │
│    → 模拟特定领域专家的视角                                          │
│    → 调用训练数据中该领域的知识                                      │
│    → 给出更专业、更有针对性的回答                                    │
│                                                                     │
│    结果:你得到的是「专家视角的模拟」,质量更高                       │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

专家观点 — Andrej Karpathy [^65]

(2023 年 State of GPT 演讲)

「这些 Transformer 就是 token 模拟器。它们不知道自己不知道什么,只是尽力模拟下一个 token。」

这和 Context Engineering 有什么关系?

其实这也是一种「高信号 Context」—— 告诉模型要模拟谁

提问方式模型行为结果质量
「你觉得这段代码怎么样?」模拟「平均程序员」泛泛而谈
「假设你是 Google 的 Staff Engineer,审查这段代码会关注什么?」模拟「资深工程师」更专业的审查意见
「这个架构设计有什么问题?」模拟「平均意见」可能漏掉关键点
「如果 Martin Fowler 看这个架构,他会怎么评价?」模拟「架构大师视角」更深入的分析

实操建议

  • 问观点性问题时,指定一个「角色」或「专家群体」
  • 不是说「你是 XXX 专家」这种 roleplay,而是问「XXX 领域的专家会怎么看」
  • 这样做的本质是:帮模型选择一个更高质量的「模拟目标」

4.1.3 Course Correct:早期纠偏

AI 走偏是正常的,关键是早发现、早纠正

text
┌─────────────────────────────────────────────────────────────────────┐
│  Course Correct 时机                                                 │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│    ❌ 太晚纠正                                                       │
│                                                                     │
│    你: 写一个时钟                                                    │
│    AI: [写了 500 行 React 代码]                                      │
│    你: 不对,我要原生 JS                                             │
│    AI: [重写 500 行]                                                 │
│                                                                     │
│    → 浪费了大量 Context 和时间                                       │
│                                                                     │
│    ✅ 早期纠正                                                       │
│                                                                     │
│    你: 写一个时钟                                                    │
│    AI: 我打算用 React 来实现,首先...                                │
│    你: 停,用原生 JS,不要框架                                       │
│    AI: 好的,那我用原生 JS...                                        │
│                                                                     │
│    → 在 AI 动手之前就纠正方向                                        │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

纠偏技巧

场景做法
AI 选错技术栈立刻打断:「停,用 XXX 而不是 YYY」
AI 过度设计「简化,不需要 XXX 功能」
AI 理解错需求「不是这个意思,我要的是...」
对话太长开始混乱/clear 清空上下文,重新开始

4.2 CLAUDE.md:项目的 AI 说明书

CLAUDE.md 是 Claude Code 的核心配置文件——AI 每次启动都会自动读取它

text
┌─────────────────────────────────────────────────────────────────────┐
│  CLAUDE.md 的作用                                                    │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│    没有 CLAUDE.md                      有 CLAUDE.md                  │
│    ┌─────────────────┐                ┌─────────────────┐           │
│    │ Claude Code     │                │ Claude Code     │           │
│    │                 │                │                 │           │
│    │ 「这是什么项目? │                │ 「我知道:       │           │
│    │  用什么语言?   │                │  - 这是 Python 项目│          │
│    │  怎么跑测试?   │                │  - 用 pytest 测试 │           │
│    │  有什么规范?」 │                │  - 代码风格是... │           │
│    │                 │                │  - 提交规范是...」│           │
│    └─────────────────┘                └─────────────────┘           │
│           │                                  │                      │
│           ▼                                  ▼                      │
│    每次都要重新解释               直接开始工作,风格一致              │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

4.2.1 CLAUDE.md 写什么?

遵循 WHAT / WHY / HOW 结构(来自 HumanLayer 指南):

部分内容示例
WHAT项目是什么、技术栈「这是一个 Python 3.11 的 Home Assistant 集成」
WHY项目目标、各模块作用「用于接入公司物联网网关」
HOW开发流程、测试方法、提交规范「用 pytest 跑测试,commit 遵循 Conventional Commits」

关键原则

原则说明
保持精简研究表明 LLM 可靠遵循 150-200 条指令,Claude Code 自带 ~50 条,留给你的不多
控制长度300 行以内,理想情况 60 行以内
只写通用规则不要写「某个具体功能怎么实现」,那是任务描述不是项目规范
不要当 Linter代码风格用 ESLint/Prettier/Ruff 等工具,不要写在 CLAUDE.md 里
手动编写不要用 /init 自动生成,那个效果很差

4.2.2 我的实践:OpenSpec

作者实践

以下是我个人采用的工作流,不一定适合所有人。供参考。

我现在用的是 OpenSpec——一个 spec-driven 的开发流程。

text
┌─────────────────────────────────────────────────────────────────────┐
│  OpenSpec 目录结构                                                   │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│    project/                                                         │
│    ├── CLAUDE.md              ← 项目入口,引用 OpenSpec              │
│    └── openspec/                                                    │
│        ├── AGENTS.md          ← AI 的详细指南                        │
│        ├── project.md         ← 项目规范                             │
│        ├── specs/             ← 当前状态(已实现的功能)              │
│        │   └── [capability]/                                        │
│        │       └── spec.md                                          │
│        └── changes/           ← 变更提案(待实现的功能)              │
│            └── [change-name]/                                       │
│                ├── proposal.md                                      │
│                ├── tasks.md                                         │
│                └── specs/                                           │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

OpenSpec 的核心思想

「Specs 是真相(已构建),Changes 是提案(待构建),保持它们同步。」

三阶段工作流

阶段触发条件产出
1. 创建提案新功能、Breaking Change、架构变更proposal.md + tasks.md + spec deltas
2. 实现提案提案被批准代码实现,按 tasks.md 逐项完成
3. 归档提案部署完成移动到 archive/,更新 specs/

这样做的好处是:AI 在写代码之前,先帮你把需求和方案理清楚。避免了 Vibe Coding 那种「边写边想」的混乱。


4.3 现场演示:从零到部署

演示任务:用 Claude Code 从零开始,创建并部署一个时钟应用到 GitHub Pages

阶段一:好 Context vs 坏 Context

第一步:展示「坏 Context」的效果

text
┌─────────────────────────────────────────────────────────────────────┐
│  演示 Prompt 1(坏 Context)                                         │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  你: 帮我写一个时钟                                                  │
│                                                                     │
│  [等待 AI 响应,观察它会怎么理解这个模糊需求]                         │
│                                                                     │
│  预期问题:                                                          │
│  - AI 可能选择你不想要的技术栈                                       │
│  - AI 可能添加你不需要的功能                                         │
│  - AI 可能问一堆澄清问题(浪费时间)                                  │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

第二步:展示「好 Context」的效果

text
┌─────────────────────────────────────────────────────────────────────┐
│  演示 Prompt 2(好 Context)                                         │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  你: 用原生 HTML/CSS/JS 写一个数字时钟。                             │
│                                                                     │
│      功能:                                                          │
│      - 显示当前时间(时:分:秒),24 小时制                           │
│      - 每秒自动更新                                                  │
│                                                                     │
│      样式:                                                          │
│      - 深色背景,白色等宽字体                                        │
│      - 数字要大,居中显示                                            │
│                                                                     │
│      输出:单个 index.html 文件,CSS/JS 内联                         │
│                                                                     │
│  [观察 AI 直接给出符合预期的代码]                                    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

第三步:迭代添加功能

text
┌─────────────────────────────────────────────────────────────────────┐
│  演示 Prompt 3(增量开发)                                           │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  你: 在数字时钟下方加一个模拟时钟(圆形表盘 + 时针分针秒针)。        │
│      保持同样的配色风格。                                            │
│                                                                     │
│  [观察 AI 如何在现有代码基础上增量修改]                              │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│  演示 Prompt 4(主题切换)                                           │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  你: 加一个主题切换按钮,可以在深色/浅色主题之间切换。               │
│      记住用户的选择(用 localStorage)。                             │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

阶段二:Course Correct 演示

text
┌─────────────────────────────────────────────────────────────────────┐
│  演示 Prompt 5(故意制造纠偏场景)                                   │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  你: 加一个闹钟功能                                                  │
│                                                                     │
│  AI: 好的,我来添加闹钟功能。我打算:                                │
│       1. 添加一个设置闹钟时间的输入框                                │
│       2. 添加多个闹钟的支持...                                       │
│       3. 添加重复闹钟(每天/每周)...                                │
│                                                                     │
│  你: 停。简化一下,只要:                                            │
│      - 一个闹钟就够                                                  │
│      - 用 prompt() 输入时间                                          │
│      - 到时间 alert 一下就行                                         │
│                                                                     │
│  [展示早期纠偏如何节省 Context]                                      │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

阶段三:部署上线

text
┌─────────────────────────────────────────────────────────────────────┐
│  演示 Prompt 6(GitHub 部署)                                        │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  你: 帮我把这个时钟部署到 GitHub Pages:                             │
│                                                                     │
│      1. 用 gh 命令创建一个新的 public 仓库,名字叫 clock-demo        │
│      2. 初始化 git 并推送代码                                        │
│      3. 配置 GitHub Actions 自动部署到 GitHub Pages                  │
│      4. 告诉我最终的访问地址                                         │
│                                                                     │
│  [观察 AI 如何:                                                     │
│   - 调用 gh repo create                                             │
│   - 创建 .github/workflows/deploy.yml                               │
│   - 执行 git 命令                                                   │
│   - 一次性完成整个部署流程]                                          │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

阶段四:Skill 实战

text
┌─────────────────────────────────────────────────────────────────────┐
│  演示 Prompt 7(使用 Git Workflow Skill)                            │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  [先对时钟做一个小修改,比如改个颜色]                                │
│                                                                     │
│  你: /git-workflow 帮我提交这个修改                                  │
│                                                                     │
│  [Skill 自动加载,按照预定义的流程:                                 │
│   - 检查 git status / git diff                                      │
│   - 生成符合 Conventional Commits 格式的 message                    │
│     格式: type(scope): concise summary                              │
│     类型: feat / fix / refactor / docs / test / chore               │
│   - 不带 AI 生成标记(无 🤖 签名)                                   │
│   - 执行 commit 和 push]                                            │
│                                                                     │
│  示例输出:                                                          │
│  ┌────────────────────────────────────────────────────────────┐    │
│  │  feat(ui): add theme toggle button                          │    │
│  │                                                             │    │
│  │  - Support dark/light theme switching                       │    │
│  │  - Persist user preference in localStorage                  │    │
│  └────────────────────────────────────────────────────────────┘    │
│                                                                     │
│  对比:没有 Skill 时,你需要每次都告诉 AI:                          │
│  「帮我 commit,用 Conventional Commits 格式,不要加 AI 签名...」   │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Git Workflow Skill 的三个工作流(可独立或组合使用):

工作流触发方式作用
Commit/git-workflow 帮我提交生成规范的 commit message
Pull Request/git-workflow 帮我创建 PR创建分支 → commit → 开 PR
Release/git-workflow 帮我发布更新版本号 → 改 CHANGELOG → 打 tag → 发布

演示要点总结

阶段展示的概念对应 Part 2 的知识点
阶段一Context 质量决定输出质量Context Engineering
阶段二早期纠偏节省 ContextAgent 的 ReAct 循环
阶段三AI 直接操作外部工具Function Call / Tool Use
阶段四Skill 封装重复工作流Skills 渐进式加载

[!TODO] 演示准备

  • [ ] 准备干净的演示环境(新文件夹、gh CLI 已登录)
  • [ ] 测试完整流程(确保 GitHub Pages 能正常部署)
  • [ ] 准备 Git Workflow Skill
  • [ ] 录制备用视频(防止现场网络问题)
  • [ ] 准备「坏 Context」的反面例子

4.4 什么时候 AI 帮助最大?

不是所有任务都适合用 AI。引用 软件工程的「纯」与「不纯」

text
┌─────────────────────────────────────────────────────────────────────┐
│  纯粹工程 vs 不纯粹工程                                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│    纯粹工程                           不纯粹工程                     │
│    (Pure Engineering)                 (Impure Engineering)          │
│                                                                     │
│    ┌─────────────────────┐           ┌─────────────────────┐       │
│    │ · 你非常了解的问题   │           │ · 你只有粗浅理解     │       │
│    │ · 社区不熟知        │           │ · 问题不新颖        │       │
│    │   (值得研究)      │           │   只是对你新        │       │
│    │ · 在专长极限边缘    │           │ · 很少处理透彻      │       │
│    │ · 有无限时间        │           │   理解的问题        │       │
│    │                     │           │ · 紧迫的截止日期    │       │
│    └──────────┬──────────┘           └──────────┬──────────┘       │
│               │                                  │                  │
│               ▼                                  ▼                  │
│    ┌─────────────────────┐           ┌─────────────────────┐       │
│    │   AI 帮不上忙        │           │  AI 可能比你更聪明   │       │
│    │   (需要深度思考)   │           │  (快速出活)        │       │
│    └─────────────────────┘           └─────────────────────┘       │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

物联网开发的例子

场景类型AI 的作用
写 Home Assistant 集成的样板代码不纯粹很有帮助,快速生成
调试特定硬件的通信协议问题纯粹帮助有限,需要你深入理解
把现有代码移植到新平台不纯粹很有帮助,机械性工作
设计系统架构纯粹可以讨论,但决策得你做
写单元测试不纯粹很有帮助,重复性工作
排查生产环境的诡异 bug纯粹帮助有限,需要经验判断

作者观点

AI 最擅长的是「不纯粹工程」——那些你知道怎么做、但做起来很繁琐的事情。而「纯粹工程」——需要深度思考和创造性的部分——还是得靠你自己。


4.5 工具链总结

text
┌─────────────────────────────────────────────────────────────────────┐
│  Claude Code 工具链全景                                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│    ┌─────────────────────────────────────────────────────────────┐  │
│    │                     CLAUDE.md                               │  │
│    │                  (项目入口配置)                              │  │
│    │                                                             │  │
│    │  · WHAT: 项目是什么、技术栈                                 │  │
│    │  · WHY: 项目目标                                            │  │
│    │  · HOW: 开发流程、测试方法                                  │  │
│    └──────────────────────────┬──────────────────────────────────┘  │
│                               │                                      │
│         ┌─────────────────────┼─────────────────────┐               │
│         │                     │                     │               │
│         ▼                     ▼                     ▼               │
│    ┌──────────┐         ┌──────────┐         ┌──────────┐          │
│    │  Skills  │         │   MCP    │         │  Slash   │          │
│    │          │         │ Servers  │         │ Commands │          │
│    │ 可复用   │         │          │         │          │          │
│    │ 能力包   │         │ 连接外部 │         │ 快捷命令 │          │
│    │          │         │ 服务     │         │          │          │
│    └────┬─────┘         └────┬─────┘         └────┬─────┘          │
│         │                    │                    │                 │
│         ▼                    ▼                    ▼                 │
│    ┌──────────┐         ┌──────────┐         ┌──────────┐          │
│    │writing-  │         │ GitHub   │         │/openspec │          │
│    │assistant │         │ Slack    │         │:proposal │          │
│    │git-      │         │ Database │         │/git-     │          │
│    │workflow  │         │ ...      │         │workflow  │          │
│    └──────────┘         └──────────┘         └──────────┘          │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘
工具作用我的使用场景
CLAUDE.md项目配置入口每个项目都有,定义基本规范
OpenSpecSpec-driven 开发流程大功能开发前先写 proposal
Skills可复用的能力模块writing-assistant 写文章、git-workflow 提交代码
MCP连接外部服务GitHub、文件系统
Slash Commands快捷命令/openspec:proposal 创建提案

实际例子:这篇分享稿就是这样写出来的:

  1. 起手 /writing-assistant 启动写作 Skill
  2. Skill 引导我按启发问题逐步写
  3. 写完后用审校模式检查结构、语言
  4. 最后用 /git-workflow 提交

注意事项

  • MCP 不能装太多——每个 MCP Server 的工具定义都占用 Context
  • Skills 按需加载——只有用到的时候才会消耗 Token
  • 定期 /clear——不要让对话历史无限累积

[!TODO] 素材准备

  • [ ] 展示你的 MCP 配置
  • [ ] 展示 writing-assistant Skill 的效果
  • [ ] 展示 OpenSpec 的工作流程


参考资料


  1. 💬 L4 | Don't think of LLMs as entities but as simulators | Andrej Karpathy - 2025 年 12 月 7 日推文,提出「LLM 是模拟器而非实体」的心智模型,解释 personality embedding vector 概念。 ↩︎

基于 VitePress 构建