18 KiB
18 KiB
Karpathy风格 Wiki 自动编译器设计文档
基于LLM的个人知识库自动构建系统
一、核心架构
┌─────────────────────────────────────────────────────────────────┐
│ 腾讯云 2核2G (编译服务器) │
│ │
│ /data/knowledge-base/ │
│ ├── 00-inbox/ ← 原始资料入口(手动/Web Clipper放入) │
│ ├── 01-raw/ ← 已整理的原始资料(PDF/网页/图片) │
│ ├── 02-compiler/ ← 编译器工作目录 │
│ │ ├── scripts/ ← 编译脚本 │
│ │ ├── queue/ ← 待处理队列 │
│ │ └── logs/ ← 处理日志 │
│ ├── 03-wiki/ ← 生成的Wiki(Obsidian主目录) │
│ │ ├── 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仓库
- 数据集说明
处理:
# 1. 文件放入 00-inbox/
# 2. File Watcher检测到新文件
# 3. 预处理:
# - 网页 → Markdown(readability-lxml)
# - PDF → Markdown(pymupdf4llm)
# - 图片 → OCR提取文字(可选)
# 4. 移动到 01-raw/,记录元数据
元数据记录(JSON sidecar):
{
"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)
核心编译管道(每次处理一个文档):
# 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生成):
---
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)
自动生成内容地图:
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文件模板:
---
moc: true
title: "人工智能研究"
description: "关于AI核心概念、方法论的集合"
concepts_count: 42
last_updated: 2025-04-15
---
# 🗺️ 人工智能研究
## 核心概念
(Dataview查询自动生成)
```dataview
LIST
FROM "Concepts"
WHERE contains(mocs, "人工智能研究")
SORT importance DESC
重要资料
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
可视化输出(可选):
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)
定期检查任务(每日/每周):
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 文件监控与触发
使用inotify(Linux):
# 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))
备选:定时扫描:
# cron任务,每分钟检查
* * * * * /usr/bin/python3 /data/knowledge-base/compiler/scan_inbox.py
3.2 队列管理
使用Redis或简单文件队列:
# 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调用封装
统一接口,支持多后端:
# 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:
# 安装
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反向代理配置:
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 必需插件
- Remotely Save - WebDAV同步
- Dataview - 查询和索引
- Templater - 模板自动化
- QuickAdd - 快速捕获
- Obsidian Web Clipper(浏览器扩展)- 剪藏网页
4.2 快捷键配置
{
"快速捕获到inbox": "Ctrl+Shift+I",
"触发编译当前文件": "Ctrl+Shift+C",
"打开概念图谱": "Ctrl+Shift+G",
"查询Wiki": "Ctrl+Shift+Q"
}
4.3 模板示例
新资料模板(放入00-inbox时自动添加):
---
ingest_date: {{date}}
source: {{source_url}}
status: pending
priority: 5
tags: [raw]
---
# {{title}}
[原始链接]({{source_url}})
## 内容
{{content}}
## 待处理
- [ ] 编译成摘要
- [ ] 提取概念
- [ ] 链接到相关MOC
五、部署清单
5.1 腾讯云初始化
# 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服务:编译器工作器
# /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 未来增强
- 语义搜索:用向量数据库存储embedding,支持模糊查询
- 多模态:处理图片、音频、视频内容
- 协作:多人共享Wiki,权限管理
- 版本控制:Git集成,追踪概念演变
- AI Agent:让LLM主动提出问题、建议研究方向
7.2 与OpenClaw集成
可以设计一个OpenClaw Skill:
/wiki ingest <url>- 让Val帮你剪藏和编译/wiki query <question>- 查询你的知识库/wiki stats- 查看知识库统计
Val可以直接调用腾讯云的编译API,帮你管理个人知识库。
核心原则:LLM维护Wiki,人负责提出问题和判断价值。
这是一个活的系统,随着使用它会越来越懂你的知识结构和兴趣方向。