AI KOL Wiki — Schema¶
本仓库按 Karpathy 的 LLM Wiki 模式 运作: 把中美 AI KOL 的长视频转录稿作为不可变原始资料,由 LLM 增量维护一个结构化、互相链接的 Markdown 知识库。
三层结构¶
| 层 | 位置 | 谁负责 |
|---|---|---|
| Raw Sources | sources/ |
脚本抓取,只增不改 |
| Wiki | wiki/ |
LLM 完全拥有,随新资料更新 |
| Schema | 本文件 + watchlist.yaml |
人来定规范和关注名单 |
目录结构¶
watchlist.yaml # 关注的 KOL / 频道名单(人来维护)
sources/
seen.txt # 已 fetch 的视频 ID,一行一个(fetch.py 自动追加)
skipped.txt # 已评估、主动决定不收录的视频 ID + 理由
<kol-slug>/
<YYYYMMDD>-<video-id>/
transcript.md # 带 frontmatter 的转录稿,含 [HH:MM:SS] 时间戳锚点
speakers.md # (可选)说话人分离 sidecar:说话占比 + 轮次表,匿名 SPEAKER_XX
wiki/
index.md # 内容目录(按人物 / 主题 / 视频组织)
log.md # 追加式操作日志
people/<name>.md # 人物页:背景、立场、观点汇总
topics/<topic>.md # 主题页:跨 KOL 观点综合,标注共识与分歧
videos/<YYYYMMDD>-<kol>-<slug>.md # 单视频页:概要 + 核心观点
scripts/
fetch.py # 摄取单个视频:uv run scripts/fetch.py <url> --kol <slug>
discover.py # 扫描 watchlist 里各频道的新视频:uv run scripts/discover.py
backfill_diarization.py # 给已摄取的转录稿补做说话人分离,写 speakers.md sidecar
工作流¶
Discover(发现新视频)¶
uv run scripts/discover.py— 列出 watchlist 各频道中未摄取、时长达标的新视频。- 对每个值得收录的视频执行 Ingest。判断标准:实质性访谈/演讲/教程,跳过预告片、shorts、纯营销。
- 判定不收录的,写进
sources/skipped.txt(<video-id> # 理由),这样以后 discover 不再重复列出。 否则同一批老候选每天都会占满输出。discover 会报出被跳过的数量,不会悄悄隐藏。
seen.txt vs skipped.txt:seen.txt = 已 fetch(转录稿已存档,fetch.py 自动写);
skipped.txt = 看过后主动放弃。两者分开,是因为 fetch ≠ 已摄取:
若 fetch 之后才判定不收录,转录稿会留档但没有 wiki 页——这种情况必须显式写进
skipped.txt,否则 lint.py 会一直把它报成「已摄取但没写 wiki 页」。
Ingest(摄取一个视频)¶
uv run scripts/fetch.py <url> --kol <slug>— 抓元数据和字幕,生成sources/.../transcript.md。- 若有字幕:自动下载 VTT → 纯文本(带 [HH:MM:SS] 时间戳锚点)。
- 若无字幕但有英文配音版:用
--lang zh-Hans从配音版取中文字幕(张小珺频道常用)。 - 若完全无字幕:用
--transcribe一键下载音频 + faster-whisper 本地转录。模型体积大不进内联依赖,按需注入:uv run --with faster-whisper scripts/fetch.py <url> --kol <slug> --transcribe(首次会拉模型约 1.5GB;faster-whisper 基于 CTranslate2,不依赖 torch,比原版快约 4 倍,默认模型 large-v3-turbo)。- GPU 转录(本机有 RTX 5090,明显更快):再注入两个 CUDA 运行库 wheel 即可,脚本会自动配好 LD_LIBRARY_PATH:
uv run --with faster-whisper --with nvidia-cublas-cu12 --with nvidia-cudnn-cu12 scripts/fetch.py <url> --kol <slug> --transcribe。缺这两个 wheel 或无 GPU 时自动回退 CPU;也可用--device cpu强制。 - 访谈类建议再加
--diarize做说话人分离(多注入--with pyannote.audio):在转录稿里插入SPEAKER_00:/SPEAKER_01:标签,让"谁说的"有机械依据,而不是靠读内容猜。首次需用同一 HF 账号接受pyannote/speaker-diarization-community-1的条款(默认模型;条款按账号生效,换 token 不带过去),再export HF_TOKEN=<token>;无 GPU 或未配 token 时自动跳过,仍产出无标签转录稿。
- GPU 转录(本机有 RTX 5090,明显更快):再注入两个 CUDA 运行库 wheel 即可,脚本会自动配好 LD_LIBRARY_PATH:
- 旧方式
--audio仍可用,仅下载音频不转录。 - 完整阅读转录稿,提取:核心论点、事实性断言、预测、与他人观点的呼应或冲突。
- 转录稿带
SPEAKER_XX标签时,结合视频标题/简介/频道判断每个标签对应谁,在视频页开头记一次映射(如SPEAKER_00 = 张小珺(主持)、SPEAKER_01 = 姚顺宇)。匿名标签留在sources/不改——认人是编辑判断,属于 wiki 层,符合"原始资料只增不改、勘误在 wiki 层处理"。 - 分离结果并非完美(抢话、串场会错配)。标签是证据不是判决:与内容明显矛盾时以内容为准,并在视频页注明存疑。
- 同目录若有
speakers.md(补做分离的 sidecar),把它和转录稿对照着读:轮次表给出各时间段的说话人,说话占比低的通常是主持人。 - 创建
wiki/videos/页;更新或创建相关wiki/people/和wiki/topics/页。 - 维护交叉链接(相对路径 Markdown 链接);更新
wiki/index.md。 - 在
wiki/log.md追加一行操作记录。
Backfill(给旧转录稿补分离)¶
uv run --with pyannote.audio scripts/backfill_diarization.py --dry-run 先看范围,去掉 --dry-run 执行。
只新增 speakers.md(pyannote 的说话占比 + 轮次表),transcript.md 逐字节不动
(脚本用 sha256 前后比对做硬保证)。
脚本本身不跑 whisper,只做分离:要把 SPEAKER_XX 标签嵌回转录稿正文才需要
重跑 whisper 取片段级时间轴,而重跑会让切分漂移,使 wiki 里已有的 [HH:MM:SS]
引用失准。所以这里只出 sidecar——只增不改,旧引用全部继续有效。
sidecar 怎么和转录稿对照着读,见上面 Ingest 第 2 步。
音频缺失会自动重下(.gitignore 已排除音频,不进仓库),默认用完即删。
Query(查询)¶
从 wiki/index.md 出发定位相关页面,综合回答并引用来源(视频页 + 时间戳)。
有价值的新综合结论可以回填为新的 topic 页。
Lint(巡检,每积累 ~10 个视频做一次)¶
- 检查主题页之间的矛盾、过时断言(KOL 改口了要标注时间线,不要删旧观点)
- 找出没有入链的孤儿页、该建未建的交叉链接
- 确认 index.md 覆盖所有页面
- 确认引用时间戳都是信源转录稿里逐字存在的锚点(
lint.py自动查,规则见下方「写作约定」)
写作约定¶
- 观点必须可溯源:wiki 中每条实质性观点后面标
([视频页](../videos/xxx.md) HH:MM:SS)。 - 信源要写成链接,不能只写在标题文字里:一个小节的引用若只写时间戳、不逐条带视频链接,就在小节标题下紧跟一行
来源:[频道 / 主体](../videos/xxx.md)(多个视频用顿号并列)。 - 「来源:」行管到下一条「来源:」行为止,
###子小节不声明就沿用上层;所以换了视频的小节必须重新声明,否则会继承上一节的信源。 - 标题里的"(Decagon,2026-07)"、括号里的
[No Priors 00:06:12]都不算声明——读者点不过去,巡检也认不出。曾有 93 条真锚点因此被判成"对不上信源"。 - 同一行引用别的视频时(交叉引用、对照),把链接放进时间戳所在的括号里:
([视频页](../videos/yyy.md) HH:MM:SS);链接在括号外的,时间戳会被算到本节声明的信源上。 - 一个小节混用多个视频、且逐条都能带行内链接时,可以不写「来源:」行。
- 整页只链接一个视频的页面不必写(默认就是它);视频页默认是自己的转录稿。
uv run scripts/lint.py按这套规则逐处核验:时间戳不是信源转录稿里的锚点报 🟠,找不到信源报 🟡。- 时间戳必须照抄转录稿锚点,写成
([HH:MM:SS])或区间([HH:MM:SS]–[HH:MM:SS]): - 只能用
transcript.md里真实存在的[HH:MM:SS]行首锚点,逐字复制。不要自己心算、取整或插值——写(00:05)这类值在转录稿里搜不到,读者无法定位。 - 一律写满
HH:MM:SS,不写HH:MM,更不写MM:SS。这两种缩写彼此无法区分:05:00既可读成 5 分 0 秒也可读成 5 小时,曾导致一整页 42 处引用被误算、全部指向同一时间点。 - ⚠️ 锚点不代表秒级精度:锚点间隔 60–68 秒,一个锚点标注的是一整块约一分钟的文本。写满秒数是为了能 grep 定位,不是说这条观点精确出现在那一秒。
- 若某处内容超出转录稿结尾(转录稿比视频短),保留粗略写法并注明,不要硬套到最近的锚点上——宁可粗,也不要假精确。
- 区分转述与断言:KOL 的观点写成"X 认为…",不要写成客观事实。
- 中美对照是本库的核心价值:topic 页里尽量并列中美 KOL 对同一问题的看法。
- 人物页/主题页用中文写作;专有名词、术语保留英文原文。
- 时间一律写绝对日期(如 2026-07),不写"最近""上个月"。
sources/下的文件一旦写入不再修改;勘误在 wiki 层处理。