闪卡牌组
将一个主题转化为问答卡片牌组,这些卡片首先传授通用概念,打印清晰,并可转换为 YouTube 视频。卡片用单个 Python 文件 (deck.py) 编写,包含小型辅助函数,配套脚本可从中渲染所有内容,因此对一张卡片的修改只需编辑一处并重新构建。
工作分为四个阶段。在每个会消耗用户时间或发布任何内容的阶段之前都要先询问,因为只有覆盖了用户所需内容的牌组才有用,而视频编码需要几分钟时间。
- 访谈:询问要构建什么。
- 计划:提出主题和卡片问题;获得用户同意。
- 卡片:编写
deck.py,渲染,检查每张卡片,修复不合适的内容。 - 额外内容(仅在需要时):视频、缩略图、发布。
1. 访谈
先提问,而不是直接构建。使用 AskUserQuestion 工具,以便用户可以点击答案。在单次调用中询问所有问题(最多 4 个),并跳过用户消息或打开的项目中已包含的任何问题。首先提供一个推荐选项,并标记为“(推荐)”。
询问以下内容。该工具最多接受 4 个问题,因此当来源是用户已有资料且需要第五个问题时,在第二次调用中询问最后一个问题。
- 来源:卡片覆盖的内容。选项包括:用户已有的材料(文件或文件夹:PDF、幻灯片、Word 或 Markdown 笔记、课程、仓库或现有闪卡)、本仓库、您自己知识中的主题,或用户即将粘贴的笔记。如果请求中已指明来源,则跳过此项。
- 遵循程度(仅当来源是用户材料时):仅遵循材料所述内容(推荐)、材料内容加上缺少的基础知识(标记为新增)、或将材料作为起点。
- 受众和深度:初级(每张卡片一个概念,用词简单)、中级(概念加上简短代码示例)或高级(权衡、边缘情况)。
- 最大卡片数:最多 10 张(快速套)、最多 20 张(推荐)、最多 40 张(完整课程)或无限(尽可能满足材料需要)。用户可以输入任何其他数字。将其记录为
deck(..., max_cards=N):如果牌组卡片数超过此限制,构建将停止,因此后续拆分卡片不会悄悄突破限制。更多卡片意味着更多主题,而非更长的卡片。 - 输出:仅卡片图片和 PDF(推荐)、或加上视频、或加上视频和缩略图。无论哪种情况,视频都在卡片获得批准后生成。
然后,如果仍然未知,以纯文本形式询问(无需工具):每张卡片上显示的牌组标题(例如“FastAPI”或“Kubernetes”)、输出保存位置(建议当前项目中的 flashcards/ 文件夹,或新建文件夹),以及代码示例是否可以引用源项目名称还是应保持通用。对于用户自己的材料,还要询问每张卡片是否应显示其来源(例如“第 3 章,第 42 页”)。
2. 计划
首先阅读源材料。如果源材料是用户已有的材料,现在请阅读 references/existing-material.md:它涵盖了阅读 PDF、幻灯片、Word 文件、文件夹和现有闪卡的方法,映射所有材料以免遗漏任何内容,忠实于原文,并将每张卡片指向其来源页面。对于来自您自己知识的主题,决定处于所选水平的学习者需要什么。然后将牌组以简短列表的形式提出:按学习顺序排列的主题,每个主题下,每张卡片一行,包含其问题。按概念分组(HTTP 基础、验证、认证),而不是按文件。每个主题的目标是 3 到 9 张卡片。小于约 12 张卡片的小牌组可以分成 2 或 3 个主题,每个主题 2 到 4 张卡片。
保持计划在最大卡片数限制内,并为拆分留出一些空间。如果材料需要的卡片数超过最大限制,先覆盖核心思想,然后列出缺少的主题或章节,并提供提高限制的选项。
展示计划并在编写卡片前询问用户是否同意、需要更改或进行删减。为错误主题编写 40 张卡片最浪费时间,因此这一步检查值得进行一次往返。
3. 卡片
编写 deck.py,先处理第一个主题
将 references/deck_template.py 复制到输出位置旁边。编写第一个主题的卡片,仅渲染该主题(--topic 1),向用户展示其中的两到三张,并询问样式和深度是否合适。然后编写其余卡片。在第 3 张卡片发现用户想要更短的卡片代价很小,在第 40 张卡片发现则代价高昂。在编写第一张卡片之前,阅读 references/components.md:它展示了每个构建块(引导句、框、步骤、表格、代码示例、标注、图表)以及要使用的 HTML。
如何写好一张卡片,以及为什么:
- **概念优先。**问题和开头句子(
lead)陈述适用于任何地方的通用思想。特定于项目的代码放在标有“示例:...”的example(...)框中,以便读者首先学习规则,然后看到一个案例。如果示例项目与常见实践不同,在示例的注释中说明。 - **每张卡片一个概念。**连接两个独立思想的问题(“什么是 X,以及如何部署它?”)需要两张卡片。对比(“X 与 Y 有何不同?”)或只有在一起才有意义的配对则是一个概念。
- **先引导,再结构,后示例。**一个一两句的回答,然后是两个或三个框、步骤或一个小表格来分解,最后是一个可选的标注和代码示例。读者应仅从引导句就获得答案。
- 页脚是要记住的一句话,少于 15 个单词。标签是用一两个单词命名该概念。
- **简洁、精确的措辞。**短句子。命名真实的状态码、函数名和命令;不要暗示它们。
- 仅在图表能增加价值时使用:流程、带有失败路径的决策、或 URL 或消息的组成部分。不要在表格已显示结构的卡片上使用。
- 交叉引用需指明位置:“应用结构中的第 4 张卡片显示了服务器端。”
渲染并检查
python3 <skill-dir>/scripts/build_deck.py deck.py --out OUT_DIR # 所有卡片、PDF、README
python3 <skill-dir>/scripts/build_deck.py deck.py --out OUT_DIR --topic 1 # 一个主题,快速检查
<skill-dir> 是此 SKILL.md 所在的文件夹。使用 python3,或使用 python(前提是它指向 Python 3)。脚本需要安装了 playwright 和 Pillow 的 Python(使用 pip install playwright pillow),以及 Google Chrome 或通过 playwright install chromium 安装的浏览器。它将每张卡片渲染为 2400 x 1698 像素的 A4 横向 PNG,检查每张卡片的内容是否适合(高度和宽度),并停止处理任何不适合的卡片。然后,它为每个主题生成一个 PDF、一个 print/all-cards.pdf 和一个 README.md。
- 重复内容:适合检查测量的是尺寸,而不是含义。查找重复步骤或引导句的框并将其删除。
- 超出最大限制:如果牌组的卡片数超过
max_cards,构建会停止。合并或删除最不重要的卡片,或要求用户提高限制。不要自行提高。 - 卡片不适合:缩短文本、删除一个框,或将其拆分为两张卡片(例如“9a”和“9b”,或两个问题)。切勿缩小字体以强行塞入内容;卡片必须保证打印时清晰可读。
- 渲染后检查每张卡片,通过打开 PNG 文件。适合检查能捕捉到溢出问题,但无法捕捉到令人困惑的卡片、误导性的图表或拼写错误。修复后重新渲染;
--topic N可快速重新渲染一个主题。 - **空白空间是正常的。**构建会以 CSS 像素为单位报告 1200 x 849 像素卡片上的空白空间(PNG 是其两倍大)。一张简单的卡片通常会有 150 到 350 像素的空白,这对于阅读和打印来说是正常的。不要为了填满卡片而填充内容。如果一张卡片留有超过约 400 像素的空白且感觉内容单薄,可能需要添加图表或示例,或者更适合合并到相邻卡片中。
4. 额外内容:视频、缩略图、发布
仅在用户需要且批准卡片后才执行。询问用户想要的视频样式,并大致说明编码所需时间(笔记本电脑上每张卡片约需 15 秒编码时间)。
python3 <skill-dir>/scripts/build_videos.py deck.py --cards OUT_DIR --out VIDEO_DIR [--mode both|questions|cards]
python3 <skill-dir>/scripts/build_thumbnails.py deck.py --cards OUT_DIR --out VIDEO_DIR/thumbnails [--mode both|questions|cards]
--mode both(默认):每个问题先显示答案隐藏并带有一个时间条(6 秒),然后显示完整卡片(12 秒)。--mode questions:测验,每个问题显示 10 秒,无答案。--mode cards:复习,每张完整卡片显示 15 秒。- 每种模式都会为每个主题生成一个视频,以及一个包含所有卡片的视频,视频名称中包含模式标识(
-questions、-cards),这样不同样式永远不会互相覆盖。将相同的--mode参数传递给build_thumbnails.py,以确保其名称匹配。 - 每个视频都有介绍和主题标题画面,以及一个
.txt描述文件,YouTube 会将其章节转换为可点击的章节。章节至少 10 秒,这是 YouTube 的要求。 - 视频需要
ffmpeg。将VIDEO_DIR放在任何 git 仓库之外,因为视频文件很大。 - 缩略图是 1280 x 720 的 JPEG 文件,命名与每个视频匹配。
topic(..., hook="A · B · C")设置每个主题标题下方的简短说明。 - 构建完成后,提供可直接粘贴的 YouTube 标题和描述:标题不超过 70 个字符,包含主题和要点;描述包含开场白、每个主题的一行要点、任何链接以及来自
.txt文件的章节。
在推送、发布或上传任何内容之前要询问用户;因为这些操作会影响其他人。如果牌组的代码示例来自其他人的课程或仓库,请在公开之前提及这一点,并提供致谢行(deck(..., credit="...") 会在 README 中添加一行致谢)。
后续修改牌组
编辑 deck.py 并再次运行 build_deck.py;它会重新构建每张卡片、PDF 和 README,并删除已删除卡片的图片。仅当用户希望更新视频时才重新构建视频,而 --descriptions-only 仅重写视频描述。
此技能中的文件
scripts/build_deck.py:卡片、适合检查、PDF、README。scripts/build_videos.py、scripts/build_thumbnails.py:额外内容。scripts/flashcards/:deck.py导入的辅助函数(__init__.py)、渲染器(engine.py)和卡片样式表(card.css:适合打印、白色背景配彩色轮廓、固定 A4 横向)。references/components.md:每个卡片构建块及其示例。在编写卡片前阅读。references/deck_template.py:一个可供复制的小型工作牌组。references/existing-material.md:从用户自己的笔记、PDF、幻灯片、仓库或闪卡构建牌组。当来源是这些材料时阅读。