Auto-sync: 2026-04-16 20:05
This commit is contained in:
273
Hermes/xingzhi/wiki-sync-setup-2026-04-16.md
Normal file
273
Hermes/xingzhi/wiki-sync-setup-2026-04-16.md
Normal file
@@ -0,0 +1,273 @@
|
||||
# Wiki Sync 系统搭建完整记录
|
||||
|
||||
> 日期:2026-04-16
|
||||
> 作者:Hermes Agent
|
||||
> 用途:记录 llm-wiki-agent 自动化同步系统的完整搭建过程
|
||||
|
||||
---
|
||||
|
||||
## 背景
|
||||
|
||||
用户希望将 Obsidian vault 中的 markdown 文件批量摄入到 LLM Wiki(Karpathy's LLM Wiki)中。原有方案是手动逐篇执行,效率低下。本次目标:搭建自动化系统,实现定时自动摄入。
|
||||
|
||||
---
|
||||
|
||||
## 系统架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Hermes Agent (我) │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
||||
│ │ Cron Job │ → │ TMUX Session │ → │ Claude Code Agent │ │
|
||||
│ │ 每15分钟 │ │ wiki-ingest │ │ /wiki-ingest │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
|
||||
│ ↓ ↓ │
|
||||
│ manifest.json ←───────────────────────────────── 实际生成文件 │
|
||||
│ 更新 wiki/ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 核心组件
|
||||
|
||||
| 组件 | 位置 | 职责 |
|
||||
|------|------|------|
|
||||
| **llm-wiki-sync skill** | `~/.hermes/skills/research/llm-wiki-sync/SKILL.md` | 执行模板和工作流定义 |
|
||||
| **sync.py** | `/Users/weishen/Git/llm-wiki-agent/tools/sync.py` | manifest 管理、CLI 工具 |
|
||||
| **manifest.json** | `/Users/weishen/Git/llm-wiki-agent/tools/manifest.json` | 文件状态追踪(181篇) |
|
||||
| **Hermes Cron Job** | 内部调度器 | 每 15 分钟触发一次摄入 |
|
||||
|
||||
|
||||
## 一、初始探索(手动执行阶段)
|
||||
|
||||
### 1.1 发现 raw 文件
|
||||
|
||||
- 路径:`/Users/weishen/Workspace/nexus/raw/`(Obsidian vault)
|
||||
- 通过 symlink 挂载到:`/Users/weishen/Git/llm-wiki-agent/raw/`
|
||||
- 文件数:182 个 markdown 文件
|
||||
|
||||
### 1.2 创建 manifest.json
|
||||
|
||||
手动扫描 raw 目录,生成初始 manifest:
|
||||
|
||||
```
|
||||
# 扫描 raw 目录,提取 frontmatter
|
||||
for md in Path("raw").glob("**/*.md"):
|
||||
# 提取 title, ingested, slug 等字段
|
||||
manifest.append({...})
|
||||
```
|
||||
|
||||
### 1.3 测试 /wiki-ingest
|
||||
|
||||
Claude Code 的 `/wiki-ingest` 命令执行 9 步流程:
|
||||
读取 source 文档
|
||||
读取 wiki/index.md 和 overview.md
|
||||
生成 wiki/sources/<slug>.md
|
||||
更新 wiki/index.md
|
||||
更新 wiki/overview.md
|
||||
创建/更新 Entity 页面
|
||||
创建/更新 Concept 页面
|
||||
检测并记录冲突
|
||||
追加 wiki/log.md
|
||||
|
||||
## 二、遇到的问题和解决方案
|
||||
|
||||
### 问题 1:stdin 交互问题
|
||||
|
||||
**现象**:`claude --print` 模式在非交互环境下无法正常工作,stdin 被占用导致命令卡住。
|
||||
|
||||
**解决方案**:使用 TMUX 交互模式启动 Claude Code:
|
||||
|
||||
```bash
|
||||
# 启动 TMUX session
|
||||
tmux new-session -d -s wiki-ingest "cd /Users/weishen/Git/llm-wiki-agent && claude --permission-mode bypassPermissions"
|
||||
|
||||
# 等待启动完成
|
||||
sleep 8 && tmux send-keys -t wiki-ingest Enter
|
||||
|
||||
# 发送任务
|
||||
tmux send-keys -t wiki-ingest "请执行任务..."
|
||||
```
|
||||
|
||||
### 问题 2:manifest slug 与实际文件不匹配
|
||||
|
||||
**现象**:manifest 中记录的 slug 和 source_path 与 LLM 实际生成的文件名不一致。
|
||||
|
||||
**原因**:LLM 根据内容自动生成 slug,而不是简单从文件名转换。
|
||||
|
||||
**解决方案**:要求 LLM 在任务完成后输出 `SLUG: xxx`,然后 Hermes 解析并更新 manifest:
|
||||
|
||||
```python
|
||||
def parse_slug_from_output(output: str) -> str:
|
||||
"""从 LLM 输出中解析实际使用的 slug"""
|
||||
match = re.search(r'SLUG:\s*([^\s]+)', output)
|
||||
return match.group(1) if match else None
|
||||
```
|
||||
|
||||
### 问题 3:170 条 ingest 错误记录
|
||||
|
||||
**现象**:manifest 中有 170 条记录标记为 `ingested=true` 但实际未成功。
|
||||
|
||||
**原因**:早期测试时使用 `--print` 模式失败但仍标记为成功。
|
||||
|
||||
**解决方案**:使用 `sync.py --reset-failed` 清理错误状态。
|
||||
|
||||
---
|
||||
|
||||
## 三、自建组件
|
||||
|
||||
### 3.1 sync.py CLI 工具
|
||||
|
||||
**位置**:`/Users/weishen/Git/llm-wiki-agent/tools/sync.py`
|
||||
|
||||
**功能**:
|
||||
- `--pending`:列出待摄取文件
|
||||
- `--check`:预览变化
|
||||
- `--reset-failed`:重置失败记录
|
||||
- `--bootstrap`:从现有 wiki sources 重建 manifest
|
||||
|
||||
**核心函数**:
|
||||
```python
|
||||
def get_pending_files() -> list:
|
||||
"""返回所有未摄入的文件"""
|
||||
|
||||
def mark_ingested(file_path: str, slug: str):
|
||||
"""标记文件为已摄入"""
|
||||
|
||||
def reset_failed():
|
||||
"""重置所有失败状态"""
|
||||
|
||||
def parse_slug_from_output(output: str) -> str:
|
||||
"""从 LLM 输出解析 SLUG"""
|
||||
```
|
||||
|
||||
### 3.2 llm-wiki-sync skill
|
||||
|
||||
**位置**:`~/.hermes/skills/research/llm-wiki-sync/SKILL.md`
|
||||
|
||||
**版本**:1.4.0
|
||||
|
||||
**核心内容**:
|
||||
- **角色分工**:Hermes 编排流程 → Claude Code 执行 ingest
|
||||
- **关键设计**:TMUX 交互模式、顺序执行、SLUG 输出要求
|
||||
- **TMUX 执行流程**:完整的启动、发送任务、监控、清理流程
|
||||
- **Ingest Workflow 9 步**:标准化执行步骤
|
||||
- **Cron Job 自动化**:使用 Hermes 原生 cron job
|
||||
|
||||
### 3.3 Hermes Cron Job
|
||||
|
||||
**创建命令**:
|
||||
```bash
|
||||
cronjob create \
|
||||
--name wiki-sync-15min \
|
||||
--skill llm-wiki-sync \
|
||||
--schedule "*/15 * * * *" \
|
||||
--repeat 999999 \
|
||||
--deliver "telegram:5038825565" \
|
||||
--prompt "使用 llm-wiki-sync 技能执行一次 wiki 文章摄入..."
|
||||
```
|
||||
|
||||
**配置**:
|
||||
- Job ID:`98265b6998c5`
|
||||
- Schedule:`*/15 * * * *`(每 15 分钟)
|
||||
- 交付方式:Telegram(ID: 5038825565)
|
||||
- 技能:llm-wiki-sync
|
||||
|
||||
---
|
||||
|
||||
## 四、执行流程(自动化阶段)
|
||||
|
||||
### 4.1 Cron Job 触发
|
||||
|
||||
1. 每 15 分钟(00, 15, 30, 45 分)触发
|
||||
2. 加载 llm-wiki-sync skill
|
||||
3. 执行 skill 中的 prompt
|
||||
|
||||
### 4.2 实际执行步骤
|
||||
|
||||
```
|
||||
1. 加载 llm-wiki-sync 技能
|
||||
2. 检查 manifest(python tools/sync.py --pending)
|
||||
3. 启动 TMUX session
|
||||
4. 启动 Claude Code(bypassPermissions)
|
||||
5. 发送任务指令(含 SLUG 输出要求)
|
||||
6. 监控任务完成(tmux capture-pane)
|
||||
7. 解析 SLUG 并更新 manifest.json
|
||||
8. 清理 TMUX session
|
||||
9. 输出结果(自动发往 Telegram)
|
||||
```
|
||||
|
||||
### 4.3 示例输出
|
||||
|
||||
```
|
||||
## Wiki Sync 完成
|
||||
|
||||
| 项目 | 结果 |
|
||||
|------|------|
|
||||
| 摄入文件 | raw/Home Office/用Docker中安装Navidrome.md |
|
||||
| Slug | 用docker中安装navidrome |
|
||||
| 状态 | ✅ 已完成 |
|
||||
|
||||
新增页面:
|
||||
- wiki/sources/用docker中安装navidrome.md
|
||||
- wiki/entities/Navidrome.md
|
||||
- wiki/concepts/Docker-Compose.md
|
||||
|
||||
manifest 已更新:ingested: true
|
||||
剩余待摄入:165 篇
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、当前状态
|
||||
|
||||
| 指标 | 值 |
|
||||
|------|-----|
|
||||
| 总文件数 | 181 篇 |
|
||||
| 已摄入 | 16 篇 |
|
||||
| 待摄入 | 165 篇 |
|
||||
| Cron Job 状态 | 运行中 |
|
||||
| 下次运行 | 18:15:00 |
|
||||
|
||||
---
|
||||
|
||||
## 六、关键命令速查
|
||||
|
||||
```bash
|
||||
# 检查待摄取文件
|
||||
cd /Users/weishen/Git/llm-wiki-agent && python tools/sync.py --pending
|
||||
|
||||
# 预览变化
|
||||
python tools/sync.py --check
|
||||
|
||||
# 重置失败记录
|
||||
python tools/sync.py --reset-failed
|
||||
|
||||
# 查看 cron job 状态
|
||||
cronjob --list
|
||||
|
||||
# 手动触发 cron job
|
||||
cronjob --run <job_id>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、注意事项
|
||||
|
||||
1. **必须使用 TMUX**:不能用 subprocess 或 --print 模式
|
||||
2. **必须顺序执行**:并发会触发 529 rate limit
|
||||
3. **必须解析 SLUG**:LLM 输出的实际 slug 用于更新 manifest
|
||||
4. **交付方式**:使用 `telegram:5038825565` 发给用户
|
||||
5. **保留 orphan**:不删除任何原始数据
|
||||
|
||||
---
|
||||
|
||||
## 八、扩展方向
|
||||
|
||||
- [ ] 添加错误重试机制(529 时等待后重试)
|
||||
- [ ] 支持批量摄入(改为每次 3-5 篇)
|
||||
- [ ] 添加 webhook 通知(不只是 Telegram)
|
||||
- [ ] 统计摄入速率和成功率
|
||||
|
||||
---
|
||||
|
||||
*End of Note*
|
||||
Reference in New Issue
Block a user