Karpathy 的 LLM Wiki 到底是什么?完整拆解+实操路径及OKF
4 月 3 日,Andrej Karpathy 在 X 上发了一条长帖,标题就三个词:LLM Knowledge Bases。
这条帖子的数据有点夸张——1500 万浏览,4.8 万转发,8.8 万收藏。两天后他又追加了一篇完整的方法论文档,放在 GitHub Gist 上,评论区也炸了。
我花了一天时间把原帖、Gist 文档、社区讨论全部读了一遍。这不是一个新工具推荐,是一套”用 LLM 管理知识”的方法论。读完之后我有点被刷新——原来 LLM 最该干的事,可能不是帮你写代码,而是帮你”编知识”。
下面把这套东西拆开看看。
一句话说清楚:LLM Wiki 是什么
说白了就是:你把各种原始资料(文章、论文、笔记、图片)丢给 LLM,LLM 帮你把这些资料”编译”成一个结构化的 Markdown wiki——带分类、带摘要、带交叉链接、带索引。
跟 RAG 的区别在哪?RAG 是每次提问都从原始文档里临时检索拼凑答案,知识不会积累。LLM Wiki 是提前把知识”编译”好,存成持久化的 wiki 文件,每次新增资料都会更新已有的页面。知识是会”长”的。
用 Karpathy 自己的类比:Obsidian 是 IDE,LLM 是程序员,wiki 是代码库。你几乎不直接编辑 wiki,那是 LLM 的领地。
三层架构:Raw → Wiki → Schema
Karpathy 在 Gist 文档里把整个系统拆成了三层,每层职责分明:
第一层:Raw Sources(原始资料)
你的资料库。文章、论文、图片、数据文件,什么都往里丢。这一层是不可变的——LLM 只读不写,这是你的信息源头。
实操上,Karpathy 用 Obsidian Web Clipper 浏览器插件把网页文章一键转成 Markdown,再用快捷键把文章里的图片全部下载到本地。这样 LLM 就能直接读图,不用依赖可能失效的外链。
第二层:Wiki(知识库)
LLM 生成和维护的 Markdown 文件集合。包括:摘要页、实体页、概念页、对比分析、综述文章、索引文件。所有页面之间有交叉链接。
关键点:这一层完全由 LLM 拥有。你读,它写。每次新增一个原始资料,LLM 不只是写一篇摘要,它会更新所有相关的实体页、概念页,标注新旧数据的矛盾,维护交叉引用。一个新资料可能触发 10-15 个页面的更新。
第三层:Schema(规则文件)
一个配置文档(比如 Claude Code 的 CLAUDE.md),告诉 LLM wiki 的结构规范、命名约定、工作流程。这是让 LLM 从”通用聊天机器人”变成”专业 wiki 维护员”的关键。你和 LLM 一起迭代这个文件,越用越精确。
三大核心操作:Ingest、Query、Lint
架构搭好之后,日常使用就围绕三个动作展开。
Ingest(摄入)
往 raw 目录丢一个新资料,让 LLM 处理它。LLM 会读原文,写摘要页,更新索引,然后扫一遍 wiki 里所有相关页面做增量更新。
Karpathy 说他更喜欢一次处理一个资料,全程参与——读 LLM 写的摘要,检查更新,引导 LLM 该强调什么。当然你也可以批量丢一堆资料让 LLM 自己处理,看你的风格。
Query(查询)
对着 wiki 提问。LLM 先读索引文件找到相关页面,再深入阅读,最后综合回答。答案可以是 Markdown 文档、对比表格、Marp 幻灯片、matplotlib 图表——取决于你问什么。
这里有个我觉得很聪明的地方:好的回答可以反哺 wiki。你做了一个对比分析,觉得有价值?存回 wiki 变成新页面。你的每次提问都在给知识库”加料”,不会消失在聊天记录里。
Lint(健康检查)
定期让 LLM 给 wiki 做体检:找矛盾的数据、过时的结论、没有入链的孤立页面、被提到但还没有独立页面的概念、可以用网络搜索补充的数据缺口。
Karpathy 说 LLM 很擅长”建议你接下来该研究什么”。想想看,这就是自动化的知识图谱扩展。
索引的秘密:为什么不需要 RAG
很多人第一反应是:wiki 大了之后,LLM 怎么找到相关内容?不需要向量数据库和 RAG 吗?
Karpathy 的回答出乎意料:不需要。至少在他的规模下(约 100 篇文章,40 万字)不需要。
秘密在两个文件:
- index.md:内容索引。每个 wiki 页面一行,包含链接、一句话摘要、分类标签。LLM 回答问题时先读这个文件,就知道该去看哪些页面。
- log.md:操作日志。按时间记录每次摄入、查询、检查的操作。格式统一(比如
## [2026-04-02] ingest | 文章标题),用 grep 就能快速回溯。
这个方案妙在哪?LLM 自己维护索引,索引质量随着 wiki 成长自动提升。不需要额外基础设施,一个目录的 Markdown 文件就够了。
当然,wiki 再大一些可能就需要搜索工具了。Karpathy 推荐了 qmd——一个本地 Markdown 搜索引擎,支持 BM25 和向量混合搜索,有 CLI 和 MCP server 两种接入方式。
真实案例:Farzapedia——2500 条日记变成 400 篇文章
光看方法论可能还是抽象。说个真实的例子。
4 月 4 日,一个叫 Farza(@FarzaTV)的开发者发了一条推文,标题是”This is Farzapedia”。他把 2500 条日记、Apple Notes 笔记和部分 iMessage 对话喂给 LLM,生成了一个关于自己的个人 Wikipedia——400 篇详细文章,覆盖朋友、创业项目、研究方向,甚至他喜欢的动漫对他的影响。所有文章之间都有反向链接。
有意思的是,Farza 说这个 wiki 不是给自己看的——是给他的 AI agent 用的。
他举了一个例子:设计新产品的落地页时,他问 agent:”去看看最近启发我的图片和电影,给我一些文案和视觉方向的建议。”Agent 从 wiki 里翻出了他关于吉卜力纪录片的笔记、他截图过的 YC 公司落地页、还有他几年前保存的 1970 年代 Beatles 周边设计。然后给出了一个融合这些灵感的方案。
Farza 之前用 RAG 做过类似的系统,他的原话是”it was ass”(烂透了)。文件系统结构的 wiki 让 agent 能真正理解和导航知识,比向量检索靠谱得多。
这条推文也火了:123 万浏览,3825 点赞,4710 收藏。
社区实战经验:6 条生产环境教训
Karpathy 的 Gist 评论区也很精彩。一个叫 bluewater8008 的用户分享了他们团队在生产环境跑了几周 LLM Wiki 后的经验,我觉得比原文还实用:
1. 先分类再提取。 不要把所有文档一视同仁。50 页的报告和 2 页的信件需要不同的处理策略。先按类型分类,再用类型专属的提取流程。这能省大量 token,结果也更好。
2. 给索引设 token 预算。 他们用了四级渐进式披露:L0(约 200 token,项目上下文,每次会话都加载)、L1(1-2K,索引文件,会话开始时加载)、L2(2-5K,搜索结果)、L3(5-20K,完整文章)。关键纪律:不读完索引就不读全文。
3. 每种实体类型一个模板。 人物页、事件页、文档摘要页需要不同的字段结构。他们定义了 7 种实体类型,每种有专属的必填字段。LLM 会严格遵守,wiki 的结构一致性就有了保障。
4. 每个任务产出两个输出。 这条最关键。用户问了一个分析问题,LLM 给出答案——这是输出一。输出二是把相关发现更新回 wiki 对应的文章。如果不在 schema 里明确要求这一点,LLM 做完分析就把知识丢在聊天记录里了。
5. 从第一天就设计跨域标签。 如果你的知识可能跨多个项目、客户或研究领域,在 frontmatter 里加 domain 标签。出现在多个领域的共享实体(人物、组织、概念)会成为知识图谱里最有价值的节点。后期补这个很痛苦。
6. 人类负责验证。 LLM 可以在不引用来源的情况下做综合,你不仔细看根本发现不了。在 schema 里强制要求来源引用,定期抽查 wiki 内容——不只是查最终交付物。LLM 是作者,你是主编。
一个有意思的彩蛋:idea file
Karpathy 在追加推文里提到了一个概念,值得单独说一下。
他说这条推文火了之后,他没有选择开源一个具体的代码仓库,而是写了一个”idea file”——就是那个 Gist 文档。他的理由是:在 LLM agent 时代,分享想法比分享代码更有意义。你把 idea file 丢给你的 agent,agent 会根据你的具体需求定制和构建整个系统。
这条追加推文本身也获得了 2709 转发和 4 万收藏。
想想看,这是一种新的知识传播方式:不是给你一个成品让你 fork,而是给你一个想法让你的 AI 帮你从零构建。每个人得到的实现都不一样,核心模式是一致的。
历史回响:80 年前就有人想到了
Karpathy 在 Gist 文档的最后提到了 Vannevar Bush 1945 年发表的文章”As We May Think”和他提出的 Memex 概念。
Bush 当年设想了一种个人知识设备:用户可以存储所有书籍和记录,在任意两个条目之间建立永久链接,形成”思维路径”(trails)。这些路径可以分享给别人,别人可以在自己的 Memex 里继续扩展。
听起来是不是很像 LLM Wiki?关联索引、个人知识库、可分享的知识路径。Bush 在 80 年前就想清楚了。他没解决的问题是:谁来做维护?
LLM 补上了这最后一环。
想试试?快速上手路径
如果你想自己搭一个 LLM Wiki,这是最小可用路径:
- 准备工具:安装 Obsidian + Obsidian Web Clipper 浏览器插件。在 Obsidian 设置里把附件目录指定到
raw/assets/,绑一个快捷键用来下载文章图片。 - 创建目录结构:
raw/— 放原始资料(用 Web Clipper 剪藏的文章、手动放入的 PDF 和图片)wiki/— LLM 生成和维护的知识页面wiki/index.md— 内容索引wiki/log.md— 操作日志CLAUDE.md(或对应的 agent 配置文件)— schema 规则
- 写 Schema:把 Karpathy 的 Gist 文档(链接见文末)直接丢给你的 LLM agent,让它帮你生成一份适合你领域的 schema。告诉它你的研究方向、你想要的页面类型、你偏好的工作流程。
- 开始摄入:丢第一篇资料进
raw/,让 LLM 处理。检查生成的 wiki 页面,调整 schema,再丢第二篇。前 5-10 篇资料是调校期,之后就顺了。 - 日常使用:在 Obsidian 里浏览 wiki,在 LLM agent 里提问和摄入新资料。定期跑一次 Lint。
不需要向量数据库,不需要 RAG 框架,不需要部署服务。一个目录的 Markdown 文件加一个 LLM agent,就这样。
反思
读完 Karpathy 的方法论,我一直在想一个问题:这套模式放到企业里会怎样?
现在大多数公司的知识库都是”写了没人维护”的状态。Confluence 里躺着三年前的文档,Notion 里的项目记录半年没更新,新人入职翻半天找不到想要的东西。问题不是没人想维护,是维护成本太高——谁愿意每次开完会还要花半小时更新五个相关文档的交叉引用?
LLM Wiki 模式可能真的能解决这个问题。想象一下:会议纪要、Slack 讨论、客户反馈、项目文档全部作为 raw source 喂进去,LLM 自动维护一个结构化的内部 wiki。新人入职直接对着 wiki 提问,LLM 从索引里找到相关页面综合回答。每次有新的会议纪要进来,相关的项目页、人物页、决策记录都自动更新。
当然,企业场景比个人场景复杂得多。数据安全、权限控制、多人协作的冲突处理,这些 Karpathy 的方案都没涉及。但方向是对的:让 LLM 承担知识库的”记账”工作,人只负责输入和决策。
说几个具体的问题:
- 规模上限不明确。 Karpathy 自己的 wiki 大概 100 篇文章、40 万字。再大一个量级会怎样?索引文件还够用吗?LLM 的上下文窗口能不能覆盖?他没说。
- 对 LLM 能力有要求。 这套方法论默认你用的是顶级模型(Claude、GPT-4 级别)。小模型跑 Ingest 和 Lint 效果可能打折扣。
- 冷启动需要耐心。 前 5-10 篇资料的摄入过程需要你深度参与,调校 schema 和 wiki 结构。不是”丢进去就能用”的东西。
- 验证成本容易被低估。 bluewater8008 的第 6 条经验说得对:LLM 会在不引用来源的情况下做综合。如果你用这个系统做严肃研究或商业决策,抽查验证的时间要算进去。
一句话总结
如果你经常需要在某个领域持续积累和检索知识,Karpathy 的 LLM Wiki 模式值得一试。它不是一个工具,是一种思路——把 LLM 从”问答机器”变成”知识编译器”。
Obsidian + 任意 LLM agent + 一个目录的 Markdown 文件,门槛不高,上限很高。
作者:NikoAI编程
链接:https://juejin.cn/post/7625301482213130291
okf
目录
- OKF 概述
- 核心术语
- Bundle 目录结构规范
- Concept 文档编写规范
- 交叉链接规则
- Index 与 Log 文件
- 引用规范
- 一致性校验
- Reference Agent 自动化生成流程
- 可视化生成流程
- 完整操作流程示例(GA4 实例)
- 三大实例 Bundle 结构对比
- 周边工具链
- 最佳实践与注意事项
1. OKF 概述
Open Knowledge Format (OKF) 是一种开放的、厂商中立的格式,用于将知识——即围绕数据和系统的元数据、上下文和精选洞察——表示为带 YAML frontmatter 的纯 Markdown 文件。
设计理念
| 特性 | 说明 |
|---|---|
| 人类与 Agent 可读 | 无需 SDK 或查询语言,工程师可 cat 概念文档,LLM 可直接将其载入上下文 |
| 版本可控 | Bundle 存放在 Git 中,PR、diff、blame、review 工作流开箱即用 |
| 便携无锁定 | Bundle 是一个目录,可打包为 tarball、托管在任何仓库、从任何文件系统挂载 |
| 结构化与非结构化混合 | frontmatter 提供可查询字段,markdown body 提供人类和 LLM 实际阅读的叙述 |
| 最小化约束 | 仅标准化少量必填字段,允许生产者自由扩展 |
| 渐进式披露 | 自动生成的 index.md 让 Agent 或人类逐层导航层级结构 |
| 图状而非树状 | 概念间通过 markdown 链接相互引用,表达比目录父子更丰富的关系 |
目标
- 定义一个通用格式,富化 Agent (Enrichment Agent) 可以写入
- 指导消费 Agent (Consumption Agent) 如何读取和遍历
- 促进跨系统和组织的知识交换
- 标准化少量必填字段
非目标
- 不定义固定的概念类型分类法
- 不规定存储、服务或查询基础设施
- 不替代领域特定 schema (Avro, Protobuf, OpenAPI 等) — OKF *引用*它们,不取代
2. 核心术语
| 术语 | 定义 |
|---|---|
| Knowledge Bundle | 自包含的、分层级的知识文档集合,是分发的单位 |
| Concept | Bundle 中的一个知识单元,表示为一个 markdown 文档。可描述有形资产(表、API)或抽象概念(指标、流程) |
| Concept ID | 概念文件在 Bundle 中的路径,去掉 .md 后缀。例如 tables/users.md 的 ID 为 tables/users |
| Frontmatter | 文件顶部由 — 分隔的 YAML 元数据块 |
| Body | frontmatter 之后的所有内容 |
| Link | 从一个概念到另一个概念的标准 markdown 链接 |
| Citation | 从概念到外部来源的链接,支持 body 中的声明 |
3. Bundle 目录结构规范
3.1 基本结构
path/to/bundle/
├── index.md # 可选。目录列表,用于渐进式披露
├── log.md # 可选。更新历史
├── <concept>.md # Bundle 根目录下的概念
└── <subdirectory>/ # 子目录将概念分组
├── index.md
├── <concept>.md
└── <subdirectory>/
└── …
3.2 保留文件名
| 文件名 | 用途 | 规则 |
|---|---|---|
| index.md | 目录列表(见 §6) | MUST NOT 用作概念文档 |
| log.md | 更新历史(见 §7) | MUST NOT 用作概念文档 |
所有其他 .md 文件都是概念文档。
3.3 分发形式
- Git 仓库(推荐 — 提供历史、归属、diff)
- tarball 或 zip 归档
- 更大仓库中的一个子目录
3.4 实际实例结构
以 GA4 Bundle 为例,实际产出的目录结构为:
bundles/ga4/
├── index.md ← 根索引
├── datasets/
│ ├── index.md ← 数据集目录索引
│ └── ga4_obfuscated_sample_ecommerce.md ← 数据集概念文档
├── tables/
│ ├── index.md ← 表目录索引
│ └── events_.md ← 表概念文档(含完整 schema)
├── references/
│ ├── index.md ← 引用目录索引
│ ├── joins/
│ │ ├── index.md
│ │ └── events___ads_clickstats.md ← Join 引用文档
│ └── metrics/
│ ├── index.md
│ ├── event_count.md ← 指标引用文档
│ ├── user_count.md
│ ├── day_count.md
│ ├── new_user_count.md
│ ├── avg_pageviews.md
│ ├── avg_transactions_per_purchaser.md
│ ├── avg_spend_per_purchase_session_by_user.md
│ └── overall_avg_spend_per_purchase_session.md
└── viz.html ← 可视化 HTML(可选)
4. Concept 文档编写规范
每个概念是一个 UTF-8 Markdown 文件,由两部分组成:
- YAML frontmatter 块 — 以
---开头和结尾 - Markdown body — 自由格式内容
4.1 Frontmatter 字段
---
type: <Type name> # 必填 (REQUIRED)
title: <Optional display name> # 推荐
description: <Optional one-line summary> # 推荐
resource: <Optional canonical URI> # 推荐
tags: [<tag>, <tag>, …] # 可选
timestamp: <ISO 8601 datetime> # 可选,最后修改时间
# … 其他生产者自定义键值对
---
必填字段
| 字段 | 说明 | 示例值 |
|---|---|---|
| type | 标识概念类型的短字符串,消费者用于路由、过滤和展示 | BigQuery Table, BigQuery Dataset, Reference, Metric, Playbook |
Type 值不在中心注册。生产者应选择描述性、自解释的值;消费者必须优雅地容忍未知类型。
推荐字段(按优先级排序)
| 优先级 | 字段 | 说明 |
|---|---|---|
| 1 | title | 人类可读显示名。省略时消费者可从文件名推导 |
| 2 | description | 单句概括概念。用于 index.md 生成器、搜索摘要和预览 |
| 3 | resource | 唯一标识概念所描述底层资产的 URI。描述抽象概念时省略 |
| 4 | tags | YAML 列表,用于交叉分类 |
| 5 | timestamp | ISO 8601 最后修改时间 |
扩展字段
生产者可包含任何额外键。消费者应保留未知键,不应拒绝包含未识别字段的文档。
注意:Reference Agent 实现中 (
document.py),必填键为type,title,description,timestamp四项。frontmatter 键的推荐顺序为:type→resource→title→description→tags→timestamp。
4.2 Body 规范
Body 是标准 Markdown。生产者应优先使用结构化 Markdown — 标题、列表、表格、围栏代码块 — 而非自由散文,因为结构有助于人类阅读和 Agent 检索。
约定章节标题
| 标题 | 用途 |
|---|---|
| # Schema | 资产列/字段的结构化描述 |
| # Examples | 具体使用示例,通常为围栏代码块 |
| # Citations | 支持 body 中声明的外部来源(见 §7) |
Reference Agent 生成表文档时遵循以下 body 顺序:
- 短散文描述(1-3 段)— 描述概念是什么、代表什么、通常如何使用
# Schema— 扁平化、可读的字段摘要。对嵌套 RECORD 字段,缩进或表格格式化其子字段# Common query patterns— 1-3 个短 SQL 片段,用 `__CODE_BLOCK_4__yaml --- type: BigQuery Table resource: https://bigquery.googleapis.com/v2/projects/bigquery-public-data/datasets/ga4_obfuscated_sample_ecommerce/tables/events_* title: Events table (Google Analytics BigQuery Export) description: Contains Google Analytics event export data from thega4_obfuscated_sample_ecommerce` dataset. tags:
- events
- Google Analytics
- BigQuery
- ecommerce
- schema
- basic queries
- advanced queries timestamp: ‘2026-05-28T22:53:05+00:00’ —
Body 包含 `# Overview`、`# Metrics`(链接到指标引用)、`# Schema`(详细字段描述,包括 `event`、`user`、`device`、`geo`、`items` 等 RECORD)、`# Joins`(链接到 join 引用)、`# Citations`。
### 4.4 实例:未绑定资源的概念
以指标引用 `references/metrics/user_count.md` 为例:
```yaml
---
type: Reference
resource: https://developers.google.com/analytics/bigquery/web-ecommerce-demo-dataset
title: User Count
description: Total number of unique users.
tags:
- metric
timestamp: '2026-05-28T22:50:09+00:00'
---
Total number of unique users.
```sql
COUNT(DISTINCT user_pseudo_id)
Citations
### 4.5 实例:Join 引用概念
以 `references/joins/events___ads_clickstats.md` 为例:
```yaml
---
type: Reference
resource: https://developers.google.com/analytics/bigquery/basic-queries
title: Join Google Analytics Events to Google Ads Clicks
description: Join Google Analytics event data with Google Ads click data.
tags:
- join
- Google Ads
timestamp: '2026-05-28T22:51:46+00:00'
---
Join Google Analytics event data with Google Ads click data.
__CODE_BLOCK_8__
# Citations
- https://developers.google.com/analytics/bigquery/basic-queries
5. 交叉链接规则
概念间可使用标准 markdown 链接相互引用。支持两种形式:
5.1 绝对链接(Bundle 相对)
以 / 开头,相对于 Bundle 根目录解释。
See the [customers table](/tables/customers.md) for the join key.
__CODE_BLOCK_10__markdown
See the [neighboring concept](./other.md).
从 tables/events_.md 链接到其他概念的示例:
| 链接目标类型 | 示例路径 |
|---|---|
| 同级表 | [users](users.md) |
| 父数据集 | [dataset](../datasets/ga4_obfuscated_sample_ecommerce.md) |
| 引用文档 | [Event Count](../references/metrics/event_count.md) |
5.3 链接语义
- 从概念 A 到概念 B 的链接断言一种关系。具体关系类型由周围散文传达,而非链接本身
- 构建图视图的消费者通常将所有链接视为无类型关系的有向边
- 消费者必须容忍断链 — 目标不存在的链接不是格式错误,可能表示尚未编写的知识
5.4 Reference Agent 链接规则
- 仅使用文件相对路径。绝不以
/开头(在 GitHub 渲染中会失效) - 仅链接到
list_concepts()返回的 ID。不得发明链接目标 - 每个章节每个概念提及一个链接足够。不要过度链接
- 不要从标题、围栏代码块或 schema 字段名列表中链接
- 不要将当前文档链接到自身
6. Index 与 Log 文件
6.1 Index 文件 (index.md)
index.md 可出现在任何目录(包括 Bundle 根)。它枚举目录内容以支持渐进式披露。
格式规范
- 不含 frontmatter(唯一例外:Bundle 根
index.md可包含okf_version字段) - Body 使用一个或多个章节,每个章节在标题下分组概念:
# Section / Group Heading
* [Title 1](relative-url-1) - short description of item 1
* [Title 2](relative-url-2) - short description of item 2
# Another Section
* [Subdirectory](subdir/) - short description of the subdirectory
自动生成
Reference Agent 的 regenerate_indexes() 函数自动生成 index.md:
- 遍历 Bundle 中所有
.md文件,收集需要索引的目录 - 按层级深度从深到浅处理(先处理子目录,再处理父目录)
- 对每个目录,按
type分组概念,按title字母排序 - 条目包含从 frontmatter 提取的
description - 对子目录,使用 LLM 合成一句话描述(当子目录有多个条目时)
实例
GA4 Bundle 根 index.md:
# Subdirectories
* [datasets](datasets/index.md) - A sample of obfuscated Google Analytics BigQuery event export data...
* [references](references/index.md) - This directory contains specifications for data joins...
* [tables](tables/index.md) - Contains Google Analytics event export data...
__CODE_BLOCK_13__markdown
# BigQuery Table
* [Events table (Google Analytics BigQuery Export)](events_.md) - Contains Google Analytics event export data...
__CODE_BLOCK_14__markdown
# Directory Update Log
## 2026-05-22
* **Update**: Added new BigQuery table reference for [Customer Metrics](/tables/customer-metrics.md).
* **Creation**: Established the [Dataplex Playbook](/playbooks/dataplex.md).
## 2026-05-15
* **Initialization**: Created foundational directory structure.
- 日期标题必须使用 ISO 8601
YYYY-MM-DD格式 - 日志条目为散文;加粗的前导词(
**Update**,**Creation**,**Deprecation**等)是约定,非要求
7. 引用规范
当概念 body 中的声明来源于外部材料时,这些来源应在文档底部的 # Citations 标题下列出,编号排列:
# Citations
[1] [BigQuery public dataset announcement](https://cloud.google.com/blog/products/data-analytics/...)
[2] [Internal data quality runbook](https://wiki.acme.internal/data/quality)
__CODE_BLOCK_16__markdown
# Citations
- https://developers.google.com/analytics/bigquery/web-ecommerce-demo-dataset
- https://support.google.com/analytics/answer/7029846
- https://developers.google.com/analytics/bigquery/basic-queries
- https://developers.google.com/analytics/bigquery/advanced-queries
注意:Reference Agent 使用无编号的
-列表格式而非[1]编号格式,这是生产者的选择变体。
8. 一致性校验
一个 Bundle 符合 OKF v0.1 当且仅当:
- ✅ 树中每个非保留
.md文件包含可解析的 YAML frontmatter 块 - ✅ 每个 frontmatter 块包含非空
type字段 - ✅ 每个保留文件名(
index.md,log.md)在存在时遵循 §6 和 §7 的结构
消费者容忍规则
消费者应将所有其他约束视为软指导。特别是,消费者不得因以下原因拒绝 Bundle:
- ❌ 缺少可选 frontmatter 字段
- ❌ 未知
type值 - ❌ 未知额外 frontmatter 键
- ❌ 断链
- ❌ 缺少
index.md文件
Reference Agent 校验实现
document.py 中的 OKFDocument.validate() 方法检查必填键:
REQUIRED_FRONTMATTER_KEYS = ("type", "title", "description", "timestamp")
def validate(self) -> None:
missing = [k for k in REQUIRED_FRONTMATTER_KEYS if not self.frontmatter.get(k)]
if missing:
raise OKFDocumentError(f"Missing required frontmatter keys: {', '.join(missing)}")
write_concept_doc 工具在写入前调用 validate(),拒绝无效 frontmatter 的写入。同时在 web pass 中实施增强守卫:拒绝会缩减现有 BigQuery Table 文档 # Schema 字段集或 # Citations 条目数的写入。
9. Reference Agent 自动化生成流程
Reference Agent 是 OKF 的概念验证生产者,基于 Google ADK 构建。它通过两个阶段 (pass) 自动从数据源和 Web 文档生成 OKF Bundle。
9.1 架构概览
┌─────────────────────────────────────────────────────────────────┐
│ Reference Agent │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │ BQ Agent │ │ Web Agent │ │ Visualize │ │
│ │ (Pass 1) │ │ (Pass 2) │ │ (Subcommand) │ │
│ └──────┬──────┘ └──────┬───────┘ └─────────┬──────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │ Source Tools │ │ Web Tools │ │ Viewer Generator │ │
│ │ - list │ │ - fetch_url │ │ - Cytoscape.js │ │
│ │ - read_raw │ │ - 爬虫预算 │ │ - marked.js │ │
│ │ - sample │ │ - 深度限制 │ │ - 自包含 HTML │ │
│ └──────┬──────┘ └──────┬───────┘ └────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │ Bundle Tools │ │ Bundle Tools │ │ Bundle 目录 │ │
│ │ - read_doc │ │ - read_doc │ │ → viz.html │ │
│ │ - write_doc │ │ - write_doc │ │ │ │
│ └─────────────┘ └──────────────┘ └────────────────────┘ │
│ │ │ │ │
│ └────────┬─────────┘ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ regenerate_ │ │ generate_ │ │
│ │ indexes() │ │ visualization│ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
__CODE_BLOCK_19__
┌──────────────────────────────────────────────────────────────┐
│ BQ Agent 单概念富化工作流 │
│ │
│ 1. read_existing_doc(concept_id) │
│ → 检查是否已有文档,有则在此基础上改进而非重写 │
│ │
│ 2. read_concept_raw(concept_id) │
│ → 获取结构化元数据(schema、分区、聚类、行数、时间戳) │
│ │
│ 3. sample_rows(concept_id, n=3) [可选] │
│ → 元数据稀疏时拉取少量数据样本辅助描述 │
│ │
│ 4. list_concepts() │
│ → 了解 Bundle 中存在哪些其他概念,用于编织交叉链接 │
│ │
│ 5. write_concept_doc(concept_id, frontmatter, body) │
│ → 组合并写入 OKF 文档(仅调用一次) │
└──────────────────────────────────────────────────────────────┘
__CODE_BLOCK_20__
┌──────────────────────────────────────────────────────────────┐
│ Web Agent 爬虫工作流 │
│ │
│ 1. list_concepts() │
│ → 了解 Bundle 已有哪些概念 │
│ │
│ 2. 对每个种子 URL 调用 fetch_url(url) │
│ → 返回页面 markdown 内容 + 出站链接列表 │
│ │
│ 3. 从出站链接中选取少量看起来像权威文档的链接 │
│ → 跳过导航、页脚、登录页、关于我们、营销页等 │
│ → 对选中链接递归调用 fetch_url │
│ │
│ 4. 对每个抓取的页面,决定以下之一: │
│ a) 增强现有概念 — read_existing_doc → write_concept_doc │
│ b) 创建新引用概念 — 仅当同时满足四个条件(见下文) │
│ c) 跳过 │
│ │
│ 5. 停止条件: │
│ - fetch_url 返回 "max_pages reached"(预算耗尽) │
│ - 已覆盖种子站点相关材料,继续抓取收益递减 │
└──────────────────────────────────────────────────────────────┘
创建新引用概念的四个条件(必须全部满足):
- 主题形状:定义了可被现有概念文档按名称引用的内容(业务实体、指标、枚举/状态码、字段/参数词汇表、定价说明、单位/时区/标识符约定)
- 非 Bundle 级元信息:不是概述、介绍、快速入门、教程、发布说明、变更日志、路线图、FAQ 或产品落地页
- 引用测试:能在现有概念文档中合理写出
See the [X reference](/references/x.md) for ...的句子 - 复用测试:至少两个现有概念会受益于引用它,或一个概念需要它作为其自身文档放不下的承重背景
安全限制(在 fetch_url 工具中强制执行):
| 限制 | 说明 | 默认值 |
|---|---|---|
| max_pages | 硬性抓取页面上限 | 100 |
| allowed_hosts | 仅允许种子 URL 的主机名(可额外添加) | 种子主机名 |
| max_depth | 距种子 URL 的跳数上限 | 2 |
| allowed_path_prefixes | URL 路径前缀白名单 | 无限制 |
| denied_path_substrings | URL 路径子串黑名单 | 无 |
增强守卫:Web Pass 不允许缩减已有 BQ Pass 生成的 BigQuery Table 文档的 # Schema 字段集或 # Citations 条目数。如果新文档缺失字段,写入将被拒绝。
9.4 CLI 命令
enrich 子命令
.venv/bin/python -m reference_agent enrich \
--source bq \
--dataset <project>.<dataset> \
--web-seed-file <path/to/seeds.txt> \
--out ./bundles/<name>
__CODE_BLOCK_22__bash
.venv/bin/python -m reference_agent visualize --bundle ./bundles/<name>
| 参数 | 默认值 | 说明 |
|---|---|---|
| –bundle | (必填) | Bundle 根目录 |
| –out | <bundle>/viz.html | 输出 HTML 路径 |
| –name | Bundle 目录名 | 查看器头部显示名 |
10.2 生成逻辑 (generator.py)
1. _walk_concepts(bundle_root)
→ 遍历所有 .md 文件(跳过 index.md)
→ 解析 frontmatter 和 body
→ 用 _extract_links() 提取 body 中的相对链接
→ 构建 Concept 对象列表
2. _build_graph(concepts)
→ 节点:每个概念一个节点(id, label, type, color, size)
→ 边:从 body 链接提取的有向边(去重、去自环、仅保留存在的目标)
→ 颜色映射:BigQuery Dataset=#8b5cf6, BigQuery Table=#3b82f6, Reference=#10b981
3. generate_visualization()
→ 加载 HTML 模板 (viz.html)
→ 将 Bundle 序列化为 JSON 嵌入 HTML
→ 使用 Cytoscape.js (图) + marked.js (Markdown 渲染)
→ 写入单个自包含 HTML 文件
10.3 可视化特性
- 力导向图:Bundle 中所有概念为节点,按类型着色,有向边由 markdown 交叉链接绘制
- 详情面板:选中概念显示其 frontmatter(description、resource、tags)和渲染的 markdown body,内部链接重写为查看器内导航
- “被引用”反向链接列表:从链接图的反向计算
- 搜索框(匹配标题、概念 ID 和标签)、类型过滤器、可切换图布局(cose / concentric / breadth-first / circle / grid)
11. 完整操作流程示例(GA4 实例)
以 GA4 Google Merchandise Store 数据集为例,完整展示从安装到产出的端到端流程。
Step 1: 环境安装
# 从仓库根目录
python3.13 -m venv .venv
.venv/bin/pip install --index-url https://pypi.org/simple/ -e .[dev]
__CODE_BLOCK_25__bash
# BigQuery 访问
gcloud auth application-default login
gcloud config set project <your-billing-project>
# Gemini 凭据(二选一)
# 方式 A: AI Studio API Key
export GEMINI_API_KEY=<key>
# 方式 B: Vertex AI
export GOOGLE_GENAI_USE_VERTEXAI=true
export GOOGLE_CLOUD_PROJECT=<id>
export GOOGLE_CLOUD_LOCATION=<region>
__CODE_BLOCK_26__
# Seed URLs for the GA4 Google Merchandise Store anchor dataset
# 每行一个 URL,# 开头为注释
# GA4 BigQuery Export — top-level overview and index
https://support.google.com/analytics/answer/7029846
# GA4 BigQuery Export — schema reference (events, items, params)
https://support.google.com/analytics/answer/7029846?hl=en
# GA4 BigQuery cookbook (example queries by use case)
...
__CODE_BLOCK_27__bash
.venv/bin/python -m reference_agent enrich \
--source bq \
--dataset bigquery-public-data.ga4_obfuscated_sample_ecommerce \
--web-seed-file samples/ga4_merch_store/seeds.txt \
--out ./bundles/ga4
Step 5: Agent 内部执行流程
┌─────────────────────────────────────────────────────────────────────┐
│ 阶段 1: BQ Pass │
│ │
│ ① BigQuerySource.list_concepts() │
│ → 发现概念: │
│ - datasets/ga4_obfuscated_sample_ecommerce (BigQuery Dataset)│
│ - tables/events_ (BigQuery Table, 分片表, wildcard=True) │
│ │
│ ② 对每个概念运行 BQ Agent: │
│ datasets/ga4_obfuscated_sample_ecommerce: │
│ → read_concept_raw → 获取 dataset 元数据 │
│ → list_concepts → 了解有 tables/events_ 可链接 │
│ → write_concept_doc → 写入 datasets/ga4_obfuscated_sample_ │
│ ecommerce.md (含 Overview, Sample Query, Citations) │
│ │
│ tables/events_: │
│ → read_concept_raw → 获取表 schema (含嵌套 RECORD) │
│ → sample_rows(n=3) → 拉取样本行 │
│ → list_concepts → 了解有 datasets/ 和可链接的概念 │
│ → write_concept_doc → 写入 tables/events_.md │
│ (含 Overview, Metrics 链接, Schema, Joins 链接, Citations) │
│ │
│ ③ regenerate_indexes() → 自动生成各层 index.md │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ 阶段 2: Web Pass │
│ │
│ ① list_concepts() → 了解已有 datasets/ 和 tables/ 概念 │
│ │
│ ② 抓取种子 URL (developers.google.com / support.google.com): │
│ → fetch_url → 获取页面 markdown + 出站链接 │
│ │
│ ③ 跟踪权威文档链接 (max_depth=2): │
│ → schema reference 页 → 增强 tables/events_.md 的 Schema 部分 │
│ → cookbook 页 → 为指标定义创建引用文档: │
│ references/metrics/event_count.md │
│ references/metrics/user_count.md │
│ references/metrics/day_count.md │
│ references/metrics/new_user_count.md │
│ references/metrics/avg_pageviews.md │
│ references/metrics/avg_transactions_per_purchaser.md │
│ references/metrics/avg_spend_per_purchase_session_by_user.md │
│ references/metrics/overall_avg_spend_per_purchase_session.md │
│ → basic-queries 页 → 创建 join 引用文档: │
│ references/joins/events___ads_clickstats.md │
│ → 在 tables/events_.md 中添加到引用的交叉链接 │
│ │
│ ④ regenerate_indexes() → 更新所有 index.md │
└─────────────────────────────────────────────────────────────────────┘
Step 6: 生成可视化
.venv/bin/python -m reference_agent visualize --bundle ./bundles/ga4
# → 产出 bundles/ga4/viz.html
Step 7: 最终产出
bundles/ga4/
├── index.md ← 根索引 (自动生成)
├── viz.html ← 交互式可视化 (自动生成)
├── datasets/
│ ├── index.md
│ └── ga4_obfuscated_sample_ecommerce.md ← BQ Pass 产出
├── tables/
│ ├── index.md
│ └── events_.md ← BQ Pass 产出 + Web Pass 增强
└── references/ ← Web Pass 产出
├── index.md
├── joins/
│ ├── index.md
│ └── events___ads_clickstats.md
└── metrics/
├── index.md
├── event_count.md
├── user_count.md
├── day_count.md
├── new_user_count.md
├── avg_pageviews.md
├── avg_transactions_per_purchaser.md
├── avg_spend_per_purchase_session_by_user.md
└── overall_avg_spend_per_purchase_session.md
Step 8: 迭代与验证
# 仅迭代单个概念
.venv/bin/python -m reference_agent enrich \
--source bq \
--dataset bigquery-public-data.ga4_obfuscated_sample_ecommerce \
--concept tables/events_ \
--no-web \
--out ./bundles/ga4
# 运行测试
.venv/bin/pytest
12. 三大实例 Bundle 结构对比
| 维度 | GA4 | Stack Overflow | Bitcoin (crypto_bitcoin) |
|---|---|---|---|
| 数据源 | bigquery-public-data.ga4_obfuscated_sample_ecommerce | bigquery-public-data.stackoverflow | bigquery-public-data.crypto_bitcoin |
| 表数量 | 1 (分片表 events_*) | 16 (独立表) | 4 (blocks, transactions, inputs, outputs) |
| 表特征 | 单一宽表,大量嵌套 RECORD | 多个独立实体表 | 紧密关联的事实表,外键关系 |
| 引用文档 | 8 metrics + 1 join | 28 个引用(枚举、类型、状态码等) | 无引用文档 |
| 种子 URL | GA4 BigQuery Export 官方文档 | Stack Exchange Data Dump schema 文档 | bitcoin-etl GitHub + Google Cloud 博客 |
| Web Pass 行为 | 单概念增强 + 指标/join 创建 | 多概念增强(单页面描述多个表) | 跨表外键关系在 prose 中体现 |
| 数据量级 | 中等 | 大(stackoverflow 表数百 GB) | 大(transactions 数百 GB) |
| 引用类型 | Metric, Join | 枚举类型、状态码、审核类型等 | — |
| 适用场景 | 展示单一宽表的完整 schema 文档化 | 展示多表交叉增强 | 展示紧密关联表的跨表关系 |
13. 周边工具链
13.1 Metadata as Code (toolbox/mdcode/)
提供源代码工件式的元数据管理能力:
- YAML + Markdown 表示元数据,与资源层级镜像的目录结构
- 双向同步:本地工作区 ↔ Knowledge Catalog 服务
- 分发形式:TypeScript/Python 库、CLI 工具 (
kcmd)、MCP 服务器 - 支持 BigQuery Dataset、EntryGroup 等资源类型
目录布局
path/to/root/
├── catalog.yaml # 清单和配置指令
└── catalog/ # 元数据快照
└── <dir1>/
└── <entry-id1>.yaml # Entry
└── <dir2>/
├── <entry-id2>.yaml # 带 sidecar markdown 的 Entry
└── <entry-id2>.aspect.md # sidecar 文件
__CODE_BLOCK_33__
输入文本
│
├─ 第一行是否为 "---"? ──否──→ 返回空 frontmatter + 全文为 body
│
是
│
├─ 查找闭合 "---" ──未找到──→ 抛出 OKFDocumentError("未终止的 YAML frontmatter")
│
找到
│
├─ yaml.safe_load(frontmatter 文本)
│ └─ 解析失败 → 抛出 OKFDocumentError("无效 YAML")
│ └─ 非 dict → 抛出 OKFDocumentError("frontmatter 必须是 YAML 映射")
│
└─ 返回 OKFDocument(frontmatter=解析结果, body=闭合之后的文本)
序列化流程 (OKFDocument.serialize())
OKFDocument 对象
│
├─ yaml.safe_dump(frontmatter, sort_keys=False, allow_unicode=True)
│
├─ 确保 body 以 "\n" 结尾
│
└─ 输出: "---\n{fm_text}\n---\n\n{body}"
附录 B: 概念 ID 路径映射
概念 ID 与文件系统路径之间的双向映射 (paths.py):
| 操作 | 示例 |
|---|---|
| Concept ID → 文件路径 | tables/events_ → bundle_root/tables/events_.md |
| 文件路径 → Concept ID | bundle_root/tables/events_.md → (“tables”, “events_”) |
| 字符串 → Concept ID | “tables/events_” → (“tables”, “events_”) |
路径段验证正则:[A-Za-z0-9_][A-Za-z0-9_.\-]*(字母数字开头,允许下划线、点、连字符)
附录 C: 完整依赖清单
# pyproject.toml
google-adk>=2.0 # Google ADK 框架
google-cloud-bigquery>=3.20 # BigQuery 客户端
pyyaml>=6.0 # YAML 解析
pydantic>=2.0 # 数据验证
markdownify>=0.11 # HTML → Markdown 转换(Web 抓取)
pytest>=7.0 # 测试(dev)
__CODE_BLOCK_36__
# 运行时凭据
GEMINI_API_KEY # AI Studio 方式
# 或
GOOGLE_GENAI_USE_VERTEXAI=true
GOOGLE_CLOUD_PROJECT=<id>
GOOGLE_CLOUD_LOCATION=<region>
# 以及
gcloud auth application-default login # BigQuery ADC