Files
val-blog/karpathy-wiki-compiler-design.md
T

674 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Karpathy风格 Wiki 自动编译器设计文档
> 基于LLM的个人知识库自动构建系统
## 一、核心架构
```
┌─────────────────────────────────────────────────────────────────┐
│ 腾讯云 2核2G (编译服务器) │
│ │
│ /data/knowledge-base/ │
│ ├── 00-inbox/ ← 原始资料入口(手动/Web Clipper放入) │
│ ├── 01-raw/ ← 已整理的原始资料(PDF/网页/图片) │
│ ├── 02-compiler/ ← 编译器工作目录 │
│ │ ├── scripts/ ← 编译脚本 │
│ │ ├── queue/ ← 待处理队列 │
│ │ └── logs/ ← 处理日志 │
│ ├── 03-wiki/ ← 生成的WikiObsidian主目录) │
│ │ ├── Concepts/ ← 概念文章(LLM生成) │
│ │ ├── Summaries/ ← 资料摘要 │
│ │ ├── MOCs/ ← 内容地图 │
│ │ └── Index.md ← 主索引 │
│ ├── 04-outputs/ ← 查询输出(问答/可视化) │
│ └── 05-archive/ ← 归档 │
│ │
│ 编译服务: │
│ ├── File Watcher (inotify) ← 监控inbox新文件 │
│ ├── Compiler Pipeline ← 调用LLM处理 │
│ └── WebDAV Server ← 供Obsidian同步 │
└─────────────────────────────────────────────────────────────────┘
WebDAV / HTTPS
┌─────────────────────┼─────────────────────┐
│ │ │
MacBook 手机/iPad (其他设备)
(Obsidian IDE) (Obsidian App)
(也可本地编译)
```
## 二、编译流程设计
### 2.1 阶段一:数据摄取(Ingest)
**输入**:任意格式的原始资料
- 网页文章(通过Obsidian Web Clipper
- PDF论文
- 图片/截图
- GitHub仓库
- 数据集说明
**处理**
```bash
# 1. 文件放入 00-inbox/
# 2. File Watcher检测到新文件
# 3. 预处理:
# - 网页 → Markdownreadability-lxml
# - PDF → Markdownpymupdf4llm
# - 图片 → OCR提取文字(可选)
# 4. 移动到 01-raw/,记录元数据
```
**元数据记录**JSON sidecar):
```json
{
"source": "https://example.com/article",
"title": "原始标题",
"author": "作者",
"date_ingested": "2025-04-15",
"file_type": "web_article",
"word_count": 3500,
"hash": "sha256:xxx",
"status": "pending_compilation"
}
```
### 2.2 阶段二:编译(Compile
**核心编译管道**(每次处理一个文档):
```python
# compiler.py 伪代码
def compile_document(raw_file):
# 1. 读取原始内容
content = read_raw(raw_file)
metadata = read_sidecar(raw_file)
# 2. LLM生成摘要(500字以内)
summary = llm_call(
model="claude-3-5-sonnet",
prompt=f"""
请为以下文章生成结构化摘要:
- 一句话核心观点
- 3-5个关键要点
- 重要数据/事实
- 与其他概念的潜在联系
原文:{content[:8000]} # 前8K字符
"""
)
# 3. LLM提取概念
concepts = llm_call(
prompt=f"""
从以下文章中提取关键概念(实体、理论、方法、工具等)。
对每个概念给出:名称、定义、重要性(1-5)、相关概念
格式:YAML列表
"""
)
# 4. 生成或更新概念文章
for concept in concepts:
concept_file = f"03-wiki/Concepts/{concept.name}.md"
if exists(concept_file):
# 更新现有概念(添加新信息)
update_concept(concept_file, concept, raw_file)
else:
# 创建新概念文章
create_concept(concept_file, concept, raw_file)
# 5. 生成资料摘要卡片
summary_file = f"03-wiki/Summaries/{raw_file.basename}.md"
create_summary_card(summary_file, summary, concepts, metadata)
# 6. 更新主索引
update_index()
# 7. 生成反向链接
create_backlinks(raw_file, concepts)
return {
"status": "compiled",
"summary": summary_file,
"concepts": [c.name for c in concepts],
"links_created": len(concepts)
}
```
**概念文章模板**LLM生成):
```markdown
---
concept: "概念名称"
aliases: ["别名1", "别名2"]
importance: 4
created: 2025-04-15
last_updated: 2025-04-15
sources:
- "[[Summaries/原始文章1]]"
- "[[Summaries/原始文章2]]"
related:
- "[[概念A]]"
- "[[概念B]]"
---
# 概念名称
## 定义
(LLM生成的简洁定义,50-100字)
## 核心要点
- 要点1
- 要点2
- 要点3
## 在资料中的出现
(自动聚合所有提到此概念的原始资料)
### [[Summaries/原始文章1]]
> 引用段落...
> 引用段落...
### [[Summaries/原始文章2]]
> 引用段落...
## 相关概念
- [[概念A]]:关系说明...
- [[概念B]]:关系说明...
## 待探索问题
LLM自动生成,供后续查询)
- 这个概念与X有什么区别?
- 在Y场景下如何应用?
```
### 2.3 阶段三:MOC生成(Map of Content
**自动生成内容地图**
```python
def generate_mocs():
# 1. 分析所有概念的关系
concepts = load_all_concepts()
graph = build_concept_graph(concepts)
# 2. LLM识别主题集群
clusters = llm_call(
prompt=f"""
以下是我知识库中的所有概念(共{len(concepts)}个)。
请将它们组织成5-10个主题集群(MOC),每个集群包含:
- 主题名称
- 核心概念列表
- 集群间的联系
概念列表:{concepts}
关系图:{graph}
"""
)
# 3. 为每个集群生成MOC文件
for cluster in clusters:
moc_file = f"03-wiki/MOCs/{cluster.name}.md"
create_moc(moc_file, cluster)
# 4. 更新主索引
update_master_index(clusters)
```
**MOC文件模板**
```markdown
---
moc: true
title: "人工智能研究"
description: "关于AI核心概念、方法论的集合"
concepts_count: 42
last_updated: 2025-04-15
---
# 🗺️ 人工智能研究
## 核心概念
Dataview查询自动生成)
```dataview
LIST
FROM "Concepts"
WHERE contains(mocs, "人工智能研究")
SORT importance DESC
```
## 重要资料
```dataview
LIST
FROM "Summaries"
WHERE contains(topics, "AI")
SORT file.mtime DESC
LIMIT 10
```
## 最新探索
(手动或自动记录的研究问题)
- [ ] 大模型微调的最佳实践?
- [ ] RAG vs 长上下文,何时用哪个?
## 关联MOC
- [[机器学习基础]]
- [[自然语言处理]]
```
### 2.4 阶段四:问答与输出(Q&A)
**基于Wiki的问答机制**
```python
def query_wiki(question):
# 1. 确定相关概念
relevant_concepts = llm_call(
prompt=f"""
用户问题:{question}
请从以下概念列表中,找出最相关的5-10个概念:
{all_concepts}
返回概念名称列表。
"""
)
# 2. 读取相关概念文章
context = ""
for concept in relevant_concepts:
context += read_concept_file(concept)
# 3. 可选:读取原始资料(如果需要更多细节)
if need_more_detail(question):
raw_sources = find_raw_sources(relevant_concepts)
context += extract_relevant_parts(raw_sources, question)
# 4. LLM生成回答
answer = llm_call(
prompt=f"""
基于以下Wiki内容,回答用户问题。
如果信息不足,请明确说明。
上下文:{context[:12000]} # 限制长度
问题:{question}
要求:
- 使用中文回答
- 引用来源概念(如[[概念名称]])
- 如果涉及多个方面,分点说明
"""
)
# 5. (可选)生成输出文档
if user_wants_output:
output_file = f"04-outputs/QnA-{timestamp}.md"
create_qna_doc(output_file, question, answer, relevant_concepts)
return answer
```
**可视化输出**(可选):
```python
def generate_visualization(query_type):
if query_type == "concept_graph":
# 生成概念关系图(Mermaid或D3)
pass
elif query_type == "timeline":
# 生成时间线
pass
elif query_type == "slides":
# 生成Marp幻灯片
pass
```
### 2.5 阶段五:健康检查与增强(Linting)
**定期检查任务**(每日/每周):
```python
def health_check():
# 1. 查找孤立概念(无链接的概念)
orphans = find_orphan_concepts()
# 2. 查找矛盾信息
contradictions = llm_call(
prompt="扫描所有概念文章,标记矛盾或过时的信息"
)
# 3. 建议新文章
gaps = llm_call(
prompt="基于现有概念,建议缺失的链接文章或MOC"
)
# 4. 生成健康报告
report = generate_report(orphans, contradictions, gaps)
save_to("04-outputs/health-reports/weekly.md")
```
## 三、技术实现细节
### 3.1 文件监控与触发
**使用inotifyLinux**
```python
# file_watcher.py
import inotify.adapters
def watch_inbox():
i = inotify.adapters.Inotify()
i.add_watch('/data/knowledge-base/00-inbox')
for event in i.event_gen(yield_nones=False):
(_, type_names, path, filename) = event
if 'IN_CLOSE_WRITE' in type_names:
# 新文件写入完成,触发编译
queue_for_compilation(os.path.join(path, filename))
```
**备选:定时扫描**
```bash
# cron任务,每分钟检查
* * * * * /usr/bin/python3 /data/knowledge-base/compiler/scan_inbox.py
```
### 3.2 队列管理
**使用Redis或简单文件队列**
```python
# queue.py - 简化版文件队列
import json
import os
from datetime import datetime
QUEUE_DIR = "/data/knowledge-base/02-compiler/queue"
def enqueue(file_path, priority=5):
task = {
"id": generate_id(),
"file": file_path,
"priority": priority, # 1-10, 10最优先
"status": "pending",
"created": datetime.now().isoformat(),
"attempts": 0
}
queue_file = os.path.join(QUEUE_DIR, f"{task['id']}.json")
with open(queue_file, 'w') as f:
json.dump(task, f)
def dequeue():
"""按优先级取出任务"""
tasks = []
for f in os.listdir(QUEUE_DIR):
if f.endswith('.json'):
with open(os.path.join(QUEUE_DIR, f)) as fp:
task = json.load(fp)
if task['status'] == 'pending':
tasks.append(task)
# 按优先级排序
tasks.sort(key=lambda x: x['priority'], reverse=True)
return tasks[0] if tasks else None
```
### 3.3 LLM调用封装
**统一接口,支持多后端**
```python
# llm_client.py
import os
from typing import Literal
Backend = Literal["claude", "openai", "kimi", "local"]
class LLMClient:
def __init__(self, default_backend: Backend = "claude"):
self.default = default_backend
self.api_keys = {
"claude": os.getenv("ANTHROPIC_API_KEY"),
"openai": os.getenv("OPENAI_API_KEY"),
"kimi": os.getenv("MOONSHOT_API_KEY"),
"local": "http://localhost:11434" # Ollama
}
def call(self, prompt: str, backend: Backend = None, **kwargs):
backend = backend or self.default
if backend == "claude":
return self._call_claude(prompt, **kwargs)
elif backend == "openai":
return self._call_openai(prompt, **kwargs)
elif backend == "kimi":
return self._call_kimi(prompt, **kwargs)
elif backend == "local":
return self._call_ollama(prompt, **kwargs)
def _call_claude(self, prompt, model="claude-3-5-sonnet-20241022", max_tokens=4000):
import anthropic
client = anthropic.Anthropic(api_key=self.api_keys["claude"])
message = client.messages.create(
model=model,
max_tokens=max_tokens,
messages=[{"role": "user", "content": prompt}]
)
return message.content[0].text
# ... 其他后端的实现
```
### 3.4 WebDAV配置
**使用WsgiDAV**
```bash
# 安装
pip install wsgidav cheroot
# 配置 /etc/wsgidav.yaml
host: 0.0.0.0
port: 5232
root: /data/knowledge-base/03-wiki
auth:
type: htpasswd
htpasswd_filename: /etc/wsgidav/users.htpasswd
# SSL(通过Nginx反向代理)
```
**Nginx反向代理配置**
```nginx
server {
listen 443 ssl http2;
server_name knowledge.yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# WebDAV
location / {
proxy_pass http://localhost:5232;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# WebDAV方法
dav_methods PUT DELETE MKCOL COPY MOVE;
dav_ext_methods PROPFIND OPTIONS;
}
# API网关(编译器API
location /api/ {
proxy_pass http://localhost:8000;
proxy_set_header Authorization $http_authorization;
}
}
```
## 四、Obsidian配置
### 4.1 必需插件
1. **Remotely Save** - WebDAV同步
2. **Dataview** - 查询和索引
3. **Templater** - 模板自动化
4. **QuickAdd** - 快速捕获
5. **Obsidian Web Clipper**(浏览器扩展)- 剪藏网页
### 4.2 快捷键配置
```json
{
"快速捕获到inbox": "Ctrl+Shift+I",
"触发编译当前文件": "Ctrl+Shift+C",
"打开概念图谱": "Ctrl+Shift+G",
"查询Wiki": "Ctrl+Shift+Q"
}
```
### 4.3 模板示例
**新资料模板**(放入00-inbox时自动添加):
```markdown
---
ingest_date: {{date}}
source: {{source_url}}
status: pending
priority: 5
tags: [raw]
---
# {{title}}
[原始链接]({{source_url}})
## 内容
{{content}}
## 待处理
- [ ] 编译成摘要
- [ ] 提取概念
- [ ] 链接到相关MOC
```
## 五、部署清单
### 5.1 腾讯云初始化
```bash
# 1. 系统更新
sudo apt update && sudo apt upgrade -y
# 2. 安装依赖
sudo apt install -y python3 python3-pip nodejs npm redis-server nginx
# 3. 安装Python包
pip3 install anthropic openai pymupdf4llm readability-lxml markdown pyyaml watchdog
# 4. 创建目录结构
sudo mkdir -p /data/knowledge-base/{00-inbox,01-raw,02-compiler,03-wiki,04-outputs,05-archive}
sudo chown -R $USER:$USER /data/knowledge-base
# 5. 配置环境变量
export ANTHROPIC_API_KEY="your-key"
export OPENAI_API_KEY="your-key"
export MOONSHOT_API_KEY="your-key"
# 6. 启动服务
# - WebDAV
# - File Watcher
# - Compiler Worker
```
### 5.2 服务脚本
**systemd服务:编译器工作器**
```ini
# /etc/systemd/system/wiki-compiler.service
[Unit]
Description=Wiki Compiler Worker
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/data/knowledge-base
ExecStart=/usr/bin/python3 /data/knowledge-base/compiler/worker.py
Restart=always
RestartSec=10
Environment="ANTHROPIC_API_KEY=xxx"
Environment="OPENAI_API_KEY=xxx"
[Install]
WantedBy=multi-user.target
```
## 六、使用工作流
### 日常流程
```
1. 发现资料
2. Web Clipper剪藏 → 自动放入00-inbox/
3. File Watcher检测 → 触发编译队列
4. Compiler Worker处理:
- 预处理 → 01-raw/
- LLM生成摘要 → 03-wiki/Summaries/
- LLM提取概念 → 03-wiki/Concepts/
- 更新MOC → 03-wiki/MOCs/
- 建立反向链接
5. Obsidian自动同步(通过WebDAV
6. 在Obsidian中查看生成的Wiki
```
### 查询流程
```
1. 在Obsidian中打开查询面板(或命令行)
2. 输入问题
3. 系统:
- 识别相关概念
- 读取Concepts/和Summaries/
- 组装上下文
- 调用LLM生成回答
4. 输出:
- 直接回答(聊天形式)
- 或生成文档 → 04-outputs/
- 或生成可视化(图表/幻灯片)
```
## 七、扩展思路
### 7.1 未来增强
1. **语义搜索**:用向量数据库存储embedding,支持模糊查询
2. **多模态**:处理图片、音频、视频内容
3. **协作**:多人共享Wiki,权限管理
4. **版本控制**Git集成,追踪概念演变
5. **AI Agent**:让LLM主动提出问题、建议研究方向
### 7.2 与OpenClaw集成
可以设计一个OpenClaw Skill
- `/wiki ingest <url>` - 让Val帮你剪藏和编译
- `/wiki query <question>` - 查询你的知识库
- `/wiki stats` - 查看知识库统计
Val可以直接调用腾讯云的编译API,帮你管理个人知识库。
---
> **核心原则**:LLM维护Wiki,人负责提出问题和判断价值。
这是一个活的系统,随着使用它会越来越懂你的知识结构和兴趣方向。