


为课程网站撰写先讲原因、后给公式的章节
在由文件生成的课程网站上编写或修改教学章节时使用。规定文件放在哪里、发布前要跑哪些检查、如何制作图,以及如何用耐心的讲课口吻写作,先举例再给公式。
要使用这个AI规则
## 确定课程页面和翻译页面的存放位置
本项目是一个由仓库中的源文件构建而成的静态文档站点。要让目录树保持可预测,使贡献者能够猜到任何东西所在的位置:
- `docs/` —— 会成为已发布页面的课程内容。
- 内容树内部的站点配置目录 —— 静态站点生成器的配置与主题覆盖。
- `docs/public/` —— 原样复制到最终站点中的静态资源。
- 内容树内部每种额外语言各占一个目录 —— 结构与主语言相互镜像的翻译树。在翻译树中,占位用的存根页面是可以接受的。
- `code/` —— 与正文逐章对应、可实际运行的实验代码。
- `scripts/` —— 仓库维护脚本,例如站点地图生成、验证和资源优化。
- CI 工作流目录 —— 构建并部署站点的流水线。
新材料放到内容目录之下。导航与侧边栏条目在站点配置文件中声明,绝不仅凭文件的存放位置来推断。
## 用项目自带的命令在本地预览并检查网站
要通过项目自身的脚本入口来工作,而不是直接调用底层工具,这样每个人跑的都是同一条流水线。这种形态的文档站点会暴露出一小组固定的入口:
- `npm install` —— 安装依赖。
- `npm run dev` —— 带资源优化的开发服务器。
- `npm run dev:fast` —— 跳过资源优化的开发服务器,启动速度快得多。
- `npm run build` —— 产出可发布的输出。
- `npm run preview` —— 完全按照将要发布的样子来提供构建输出。
- `npm run verify` —— 仓库范围的一致性检查。
- `npm run assets:optimize` —— 压缩并转换图片。
编辑正文时使用快速开发变体,因为图片优化不会改变你正在看的任何东西。当你需要完全按照将要发布的样子查看输出时,先用 `build` 再用 `preview`。`verify` 是下一部分所描述的关卡,而 `assets:optimize` 在添加图片之后运行,以确保体积很大的原图永远不会进入已发布的站点。
## 新增页面时更新所有语言的菜单,发布前先检查
- 让每一次变更都限定在手头的任务范围内。不要在顺带经过时改写与之无关的文档或配置。
- 优先在内容目录下新增课程材料,而不是重构已经存在的材料。
- 添加新页面时,要把它们注册到导航与侧边栏配置中。
- 当某个页面被添加、移动或重命名时,要更新与之镜像的每一棵语言树的侧边栏,而不只是主语言那一棵。被落下的翻译树会产生失效条目或缺失页面。
- 只要动过配置、主题或构建脚本,就要在推送之前运行验证命令。推送会发布站点,因此未经验证的构建会在公开环境中把站点弄坏。
## 用 LaTeX 写含公式的图,再转换成 SVG
带有真正数学排版的学术风格插图是以源码方式撰写的,而不是手工绘制的:
1. 用一种矢量图语言把图写成一个独立文档 —— 例如使用 TikZ 风格宏包的 LaTeX standalone 文档。要照搬仓库中已有插图的样式,而不是发明一种新样式。
2. 用支持你所用字体的 LaTeX 引擎编译源码,然后用 PDF 转 SVG 的转换器把生成的 PDF 转成 SVG。这两步都是命令行工具,因此任何插图都可以随时从其源码重新构建。
3. 把源文件和生成的 SVG 都放在同一个 `images/` 目录中,紧挨着使用它们的章节,这样插图才能保持可复现。
4. 在 markdown 页面中通过相对路径引用生成的 SVG。
要在所有插图之间保持同一种视觉风格:圆角方框配以非常浅的填充色和深灰色描边、单一的箭头样式、与正文相匹配的正文字体,以及用于符号的行内数学定界符。
## 用耐心的讲课口吻写作,不要闲聊式语气
- 把章节当作教程与讲义材料来写,而不是当作简略的参考笔记。
- 保持一种引导式讲课的语气:对话感强、有耐心、以问题为驱动。那些把下一步动作交到读者手上的说法 —— “让我们从直觉开始”“换个角度来看”“这一步的含义是……”“真正的问题在于……” —— 是受欢迎的,同时语气仍要保持严肃而精确。
- 不要滑向闲聊式的、助手腔的或随意的网络化措辞。目标语域是一章打磨过的教科书内容。
- 要控制段落的节奏,使它们能够被朗读出来或被独自琢磨透。如果某个段落无法以阅读的速度被跟上,就把它拆开。
## 讲清完整的推理,不写空洞的铺垫句
深度与简省是并存的:要把整条推理链解释清楚,同时不在这条链之外的任何东西上花费一个字。
- 要循序渐进地解释 —— 先给直觉,然后给形式化定义,再给代码或实践。
- 要给出背景以及某一步为何必要的理由。不要把一章压缩成一份光秃秃的结论清单。
- 要删掉起引导作用的废话。凡是宣告将要解释、却并不真的给出解释的句子(“举个例子会让这一点更直观”)都要删除,并直接把例子或公式呈现出来。
- 每件事只说一次。不要用不同的措辞把同一个观点再讲一遍。
- 要把含糊的限定词替换成精确的因果陈述。比喻式的替代说法(“这大致相当于……”)和模棱两可的连接词只应出现在初稿里。
- 要避免那种把某种机制压缩成一句朗朗上口的字符串的口号式总结说法。要改为陈述具体的机制。
- 要避免机器腔的、把平行错误罗列出来的清单(“查询太宽泛、没有做价格比较、库存水平不对、参数不对”)。要描述整个过程,并展示一个早期的错误状态如何传播到后续的动作中。
- 要避免“不是 A,而是 B”的对比句式;它读起来很迂回。要陈述正面的主张,然后解释它为何成立。
## 按顺序排列思路,每个新步骤都先说明原因
- 要沿着因果线索推进。不要通过总结、复述、再对比的方式围着同一个点打转。要按照想法实际发生变化的顺序来写:一种新能力或新设定出现,它改变了训练对象或问题对象,而这使得一种新的表述成为可能或不可避免。
- 在引出一个新概念时,优先采用“既然 X 已经存在,系统就会做 Y,因此 Z 变得可能(或必要)”这样的结构。
- 开启一节时,先与读者已经知道的内容建立连接,然后点明本节所要解决的新问题。
- 不要回指前面的章节,除非这个回指对于紧接着的下一句话是必需的。
- 要给每一个概念推进的步骤都配上过渡。绝不要从一个定义直接跳到公式、术语、算法或结论;在引入下一个想法之前,先说明为什么需要它。
- 不要写那种只罗列定义的百科式页面。定义要在它的动机之后出现,并且其后要跟上一段解读。
- 要让段落从问题走向答案。一节构建得当的内容通常遵循这样的节奏:熟悉的例子 → 张力或困惑 → 形式化工具 → 演算过的例子 → 要点归纳。
## 先举熟悉的例子再给公式,并逐个解释符号
- 在引入一个公式或一个算法之前,先陈述它所解决的问题;只有在那之后才展示记号。
- 要让公式与它的含义紧挨着:解释每一个重要符号,然后用平实的语言把整个公式重新表述一遍。
- 在抽象之前先抓住一个具体的场景。小而熟悉的设定 —— 一项平衡杆的控制任务、一个多臂老虎机、文本生成、一个游戏任务、一个日常选择 —— 应当在一个概念被命名之前就让人感到它是必要的。
- 要包含小的推导过程,而不是直接断言结论,并且要让整篇正文始终面向学习者。
- 只要存在已确立的对应说法,就要用正文的主语言来书写技术术语,而不是把借来的英文词原样不译地留在那里。只有当某个英文术语是标准缩写,或者章节标题需要它时,才保留英文术语,并在首次使用时加以解释。
- 在整门课程中,每个概念固定使用一个词。一个在各章之间来回漂移的同义词,在学习者读来就是第二个概念。
## 用短小的带标题小节,提交信息加上 feat: 等标记
- 使用带明确标题的短小章节,而不是长而不分段的大段文字。
- 克制地使用粗体,用来标记概念上的转折点 —— 绝不把它当作装饰。
- 内容目录下的路径使用 kebab-case。
- 优先采用基于目录、内部放一个 `index.md` 的路由方式,这样一个主题可以扩展成好几个页面而不必改变它的 URL。
- 每一次变更都使用 Conventional Commits:`feat:`、`fix:`、`docs:`、`chore:` 等等。
