复习比倍速更重要。这篇把 Markdown 笔记里的
##小节与「术语:释义」转成 Q/A 闪卡 JSON,方便自测。
先看清成品
- 样例笔记生成多张卡片。
- 2 项 pytest 通过。
合规提醒:OpenAI Academy 课程与徽章侧重产品使用学习,不是职业资格认证;评估通过线以 Help Center / 课程页为准(常见表述为评分 ≥80%)。学习账号遵守 OpenAI 使用政策;勿把课程作业变成未授权自动化刷分。课程目录会更新,本教程附带的 JSON 是离线快照,上线前请回官网核对。
运行说明:Academy 无公开「课程列表 REST API」。三篇均本地:A 用 curated catalog 生成周计划;B 笔记转闪卡;C 本地 ledger 追踪及格阈值。未登录 academy.openai.com。2026-10-23(Asia/Shanghai)pytest 通过。
做完之后你会得到什么?
| 成果 | 说明 |
|---|---|
notes_to_cards.py |
闪卡生成 |
sample_notes.md |
样例笔记 |
test_103b.py |
测试 |
需要准备哪些环境?
| 项目 | 说明 |
|---|---|
| Python | 3.10+ |
关键事实
| 事实 | 来源 |
|---|---|
| 闪卡来自你自己的笔记,不调用 OpenAI API | 本篇范围 |
| 答题仍建议对照官方课程材料 | 学习建议 |
| 不要把未公开内部政策写进可分享闪卡 | 合规 |
文件结构
103-openai-academy-B-src/
├── notes_to_cards.py
├── sample_notes.md
└── test_103b.py
第 1 步:转换脚本
#!/usr/bin/env python3
"""Turn Markdown study notes into simple Q/A flashcards (local; for Academy review)."""
from __future__ import annotations
import argparse
import json
import re
from pathlib import Path
def cards_from_md(text: str) -> list[dict]:
cards = []
# ## Heading + following paragraph
parts = re.split(r"(?m)^##\s+", text)
for part in parts[1:]:
lines = part.strip().splitlines()
if not lines:
continue
q = lines[0].strip()
body = "\n".join(lines[1:]).strip()
if body:
cards.append({"q": q, "a": body[:500]})
# definition style: Term — meaning
for m in re.finditer(r"(?m)^[-*]\s*\*\*(.+?)\*\*\s*[::—-]\s*(.+)$", text):
cards.append({"q": f"什么是 {m.group(1).strip()}?", "a": m.group(2).strip()})
# dedupe
seen = set()
out = []
for c in cards:
if c["q"] in seen:
continue
seen.add(c["q"])
out.append(c)
return out
def main(argv=None) -> int:
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument("notes_md")
ap.add_argument("-o", "--out", default="cards.json")
args = ap.parse_args(argv)
cards = cards_from_md(Path(args.notes_md).read_text(encoding="utf-8"))
Path(args.out).write_text(json.dumps(cards, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
print(f"cards={len(cards)} -> {args.out}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
第 2 步:测试
from pathlib import Path
import json, subprocess, sys
from notes_to_cards import cards_from_md
HERE = Path(__file__).resolve().parent
def test_cards():
cards = cards_from_md((HERE/"sample_notes.md").read_text())
assert len(cards) >= 3
def test_cli(tmp_path):
out = tmp_path / "c.json"
r = subprocess.run([sys.executable, str(HERE/"notes_to_cards.py"), str(HERE/"sample_notes.md"), "-o", str(out)], capture_output=True, text=True, check=True)
assert "cards=" in r.stdout
assert json.loads(out.read_text())
第 3 步:运行
$ python notes_to_cards.py sample_notes.md
cards=4 -> /tmp/cards103.json
[
{
"q": "什么是提示词",
"a": "提示词是你给模型的指令与上下文,应包含目标、约束和输出格式。"
},
{
"q": "为何要人工复核",
"a": "模型可能幻觉;关键事实与决策需人确认。\n\n- **温度**:控制随机性,越高越发散。\n- **上下文窗口**:模型一次能看到的最大 token 范围。"
},
{
"q": "什么是 温度?",
"a": "控制随机性,越高越发散。"
},
{
"q": "什么是 上下文窗口?",
"a": "模型一次能看到的最大 token 范围。"
}
]
$ pytest -q
.. [100%]
2 passed in 0.03s
怎么检查结果?
- cards≥3。
- JSON 含 q/a 字段。
调试示例
只有一级标题没有正文。 规则需要 ## 后有段落,或列表里的加粗术语。先补两句再转。
常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 要 Anki | 可再写导入 | 本篇输出 JSON |
| 中英混合 | 支持 | 按你的笔记 |
| 卡片太长 | 截断 500 字 | 自行精炼答案 |
模板规则
- 闪卡不替代官方评估。
- 勿泄露雇主机密。
- 定期对照课程更新。
项目资源
| 用途 | 地址 |
|---|---|
| OpenAI Academy | https://academy.openai.com/ |
| Academy Home | https://academy.openai.com/home |
| OpenAI Status | https://status.openai.com/ |
笔记进闪卡,被动阅读变主动回忆。