refactor(kb-workflow): 改用Prompt-based模式
- SKILL.md: 重写为详细workflow指导,主代理直接读取执行 - kb_workflow.py: 简化为辅助工具函数库 - skill_main.py: 简化为触发检测入口 - SkillBug.md: 记录架构变更 主代理读取SKILL.md后,按照指导调用sessions_spawn,无需配置allowlist
This commit is contained in:
+222
-208
@@ -1,244 +1,258 @@
|
||||
---
|
||||
name: kb-workflow
|
||||
description: 知识库工作流编排技能,提供收件箱扫描、内容处理、归档、订阅检测、Git版本管理和自动清理功能。
|
||||
description: 知识库工作流编排技能。接收"添加到知识库 + 链接"消息,编排各子代理完成完整处理流程。
|
||||
metadata:
|
||||
short-description: 知识库工作流编排
|
||||
---
|
||||
|
||||
# KB Workflow
|
||||
|
||||
## Description
|
||||
## 触发条件
|
||||
|
||||
KB Workflow 是一个完整的知识库管理系统,包含:
|
||||
|
||||
**核心功能**:
|
||||
- 📥 **收件箱扫描** - 扫描四个子目录 (pending, metadata, content, analyzed)
|
||||
- 🔄 **内容处理** - 调用子agent处理各阶段
|
||||
- 📦 **Git版本管理** - 归档后自动提交并推送
|
||||
- 🔔 **订阅管理** - 跟踪订阅源更新
|
||||
- 🧹 **自动清理** - 定期清理临时文件
|
||||
- 📊 **汇报生成** - 生成处理统计
|
||||
|
||||
## 触发方式
|
||||
|
||||
### 自然语言触发
|
||||
|
||||
当用户发送包含以下模式的消息时,技能会自动触发:
|
||||
当用户发送包含以下模式的消息时,此技能自动触发:
|
||||
|
||||
| 触发词 | 行为 | 示例 |
|
||||
|--------|------|------|
|
||||
| `添加到知识库` + 链接 | 添加到收件箱并处理 | "添加到知识库 https://www.bilibili.com/video/BVxxx" |
|
||||
| `保存到知识库` + 链接 | 添加到收件箱并处理 | "保存到知识库 https://www.bilibili.com/video/BVxxx" |
|
||||
| `添加到知识库` + 链接 | 添加到知识库并处理 | "添加到知识库 https://www.bilibili.com/video/BVxxx" |
|
||||
| `保存到知识库` + 链接 | 同上 | "保存到知识库 https://www.bilibili.com/video/BVxxx" |
|
||||
|
||||
### 支持的平台
|
||||
## Workflow 步骤
|
||||
|
||||
| 平台 | 子技能 |
|
||||
|------|--------|
|
||||
| Bilibili | kb-bilibili-metadata, kb-bilibili-content |
|
||||
| 知乎 | kb-zhihu-metadata |
|
||||
当触发后,按照以下步骤执行:
|
||||
|
||||
## 架构设计
|
||||
### 步骤 1: 查重
|
||||
|
||||
```
|
||||
用户: "添加到知识库 https://www.bilibili.com/video/BV1ci4y1V7tb"
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ kb-workflow (主代理) │
|
||||
│ │
|
||||
│ 职责: │
|
||||
│ 1. 接收用户消息,识别触发词和链接 │
|
||||
│ 2. 查重(根据URL/文件名) │
|
||||
│ 3. 调用子agent处理各阶段 │
|
||||
│ 4. 文件流转(mv) │
|
||||
│ 5. Git版本管理 │
|
||||
│ 6. 归档和清理 │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
│ │ │ │
|
||||
▼ ▼ ▼ ▼
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ kb-link-parser│ │kb-bilibili- │ │kb-bilibili- │ │ kb-deep- │
|
||||
│ (子agent) │ │ metadata │ │ content │ │ analyzer │
|
||||
│ │ │ (子agent) │ │ (子agent) │ │ (子agent) │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
|
||||
**操作:** 检查知识库是否已存在此内容。
|
||||
|
||||
1. 根据 URL 中的 ID(如 `BVxxx`)扫描 `knowledge-base/metadata/` 和 `knowledge-base/archive/` 目录
|
||||
2. 如果存在:
|
||||
- 汇报用户内容已存在及其状态
|
||||
- 询问用户是要更新还是跳过
|
||||
- 等待用户指示
|
||||
3. 如果不存在:继续步骤 2
|
||||
|
||||
### 步骤 2: 调用 kb-link-parser
|
||||
|
||||
**操作:** 解析 URL,获取平台和内容 ID。
|
||||
|
||||
```python
|
||||
# 调用方式
|
||||
result = sessions_spawn(
|
||||
agentId="kb-link-parser",
|
||||
task="""解析以下URL,将结果保存到指定目录:
|
||||
|
||||
URL: [用户的URL]
|
||||
|
||||
输出目录: ~/work/knowledge-base/pending
|
||||
输出文件名格式: {platform}_{id}.link.json
|
||||
|
||||
请解析URL中的平台和内容ID,将解析结果保存为JSON文件。
|
||||
返回结果时告诉我输出文件的完整路径。""",
|
||||
timeoutSeconds=60
|
||||
)
|
||||
```
|
||||
|
||||
## 处理流程
|
||||
**预期输出:** `pending/{platform}_{id}.link.json`
|
||||
|
||||
### 完整流程(6个阶段)
|
||||
### 步骤 3: 提取平台并调用对应元数据技能
|
||||
|
||||
**操作:** 从文件名提取平台(如 `bilibili`),调用对应平台的元数据技能。
|
||||
|
||||
```python
|
||||
# 从返回结果中提取 output_file
|
||||
output_file = result.get("output_file")
|
||||
platform = output_file.split("/")[-1].split("_")[0] # 从文件名提取平台
|
||||
content_id = output_file.split("/")[-1].split("_")[1].split(".")[0]
|
||||
```
|
||||
用户发送"添加到知识库 + 链接"
|
||||
│
|
||||
▼
|
||||
kb-workflow:
|
||||
1. 查重(根据URL/文件名)
|
||||
2. 确认目录存在
|
||||
3. 调用 kb-link-parser (sessions_spawn)
|
||||
│
|
||||
▼
|
||||
kb-link-parser (子agent):
|
||||
解析URL
|
||||
输出: pending/bilibili_BV1ci4y1V7tb.link.json
|
||||
返回: {"success": true/false, "output_file": "pending/..."}
|
||||
│
|
||||
▼
|
||||
kb-workflow:
|
||||
从文件名提取平台 "bilibili" → 调用 kb-bilibili-metadata
|
||||
│
|
||||
▼
|
||||
kb-bilibili-metadata (子agent):
|
||||
获取元数据
|
||||
输出: metadata/bilibili_BV1ci4y1V7tb.meta.json
|
||||
返回: {"success": true/false, "output_file": "metadata/..."}
|
||||
│
|
||||
▼
|
||||
kb-workflow:
|
||||
调用 kb-bilibili-content
|
||||
│
|
||||
▼
|
||||
kb-bilibili-content (子agent):
|
||||
下载视频+字幕
|
||||
输出: content/downloads/*.mp4, *.srt
|
||||
返回: {"success": true/false, "output_file": "...", "subtitles": "..."}
|
||||
│
|
||||
▼
|
||||
kb-workflow:
|
||||
拿到字幕文件 → 调用 kb-ocr-processor
|
||||
│
|
||||
▼
|
||||
kb-ocr-processor (子agent):
|
||||
OCR处理
|
||||
输出: content/bilibili_BV1ci4y1V7tb.txt
|
||||
返回: {"success": true/false, "output_file": "content/..."}
|
||||
│
|
||||
▼
|
||||
kb-workflow:
|
||||
拿到txt文件 → 调用 kb-deep-analyzer
|
||||
│
|
||||
▼
|
||||
kb-deep-analyzer (子agent):
|
||||
深度分析
|
||||
输出: analyzed/bilibili_BV1ci4y1V7tb.md
|
||||
返回: {"success": true/false, "output_file": "analyzed/..."}
|
||||
│
|
||||
▼
|
||||
kb-workflow:
|
||||
mv → archive/YYYY-MM-DD/
|
||||
git add → commit → push
|
||||
汇报完成
|
||||
|
||||
**调用元数据技能:**
|
||||
|
||||
```python
|
||||
if platform == "bilibili":
|
||||
agent = "kb-bilibili-metadata"
|
||||
elif platform == "zhihu":
|
||||
agent = "kb-zhihu-metadata"
|
||||
|
||||
result = sessions_spawn(
|
||||
agentId=agent,
|
||||
task="""获取链接的元数据:
|
||||
|
||||
链接文件: [上一步的output_file]
|
||||
输出目录: ~/work/knowledge-base/metadata
|
||||
|
||||
请读取链接文件,提取URL,然后获取该链接的元数据(标题、作者、播放量等)。
|
||||
将元数据保存为JSON文件,文件名格式: {platform}_{id}.meta.json
|
||||
|
||||
返回结果时告诉我输出文件的完整路径。""",
|
||||
timeoutSeconds=120
|
||||
)
|
||||
```
|
||||
|
||||
**预期输出:** `metadata/{platform}_{id}.meta.json`
|
||||
|
||||
### 步骤 4: 调用内容下载技能
|
||||
|
||||
**操作:** 根据平台调用内容下载技能。
|
||||
|
||||
```python
|
||||
if platform == "bilibili":
|
||||
agent = "kb-bilibili-content"
|
||||
|
||||
result = sessions_spawn(
|
||||
agentId=agent,
|
||||
task="""下载视频内容:
|
||||
|
||||
元数据文件: [上一步的output_file]
|
||||
下载目录: ~/work/knowledge-base/content
|
||||
|
||||
请读取元数据文件,获取视频信息,然后下载视频和字幕。
|
||||
视频保存到: content/downloads/
|
||||
字幕保存到: content/subtitles/
|
||||
|
||||
文件名格式: {platform}_{id}.mp4 和 {platform}_{id}.srt
|
||||
|
||||
返回结果时告诉我下载的视频文件和字幕文件的完整路径。""",
|
||||
timeoutSeconds=600
|
||||
)
|
||||
```
|
||||
|
||||
**预期输出:**
|
||||
- `content/downloads/{platform}_{id}.mp4`
|
||||
- `content/subtitles/{platform}_{id}.srt`(可能没有)
|
||||
|
||||
### 步骤 5: OCR 处理
|
||||
|
||||
**操作:** 对视频或字幕进行 OCR 提取文字。
|
||||
|
||||
```python
|
||||
subtitle_file = result.get("subtitle") or result.get("subtitles")
|
||||
video_file = result.get("output_file")
|
||||
|
||||
# 如果有字幕用字幕,没有就用视频
|
||||
ocr_source = subtitle_file or video_file
|
||||
|
||||
result = sessions_spawn(
|
||||
agentId="kb-ocr-processor",
|
||||
task="""处理文件,提取文字内容:
|
||||
|
||||
源文件: [ocr_source]
|
||||
输出目录: ~/work/knowledge-base/content
|
||||
|
||||
请读取文件,提取文字内容。
|
||||
输出文件名格式: {platform}_{id}.txt
|
||||
|
||||
返回结果时告诉我输出文件的完整路径。""",
|
||||
timeoutSeconds=1800 # 30分钟
|
||||
)
|
||||
```
|
||||
|
||||
**预期输出:** `content/{platform}_{id}.txt`
|
||||
|
||||
### 步骤 6: 深度分析
|
||||
|
||||
**操作:** 调用深度分析生成最终报告。
|
||||
|
||||
```python
|
||||
result = sessions_spawn(
|
||||
agentId="kb-deep-analyzer",
|
||||
task="""深度分析内容:
|
||||
|
||||
元数据文件: [步骤3的output_file]
|
||||
文字内容文件: [步骤5的output_file](如果存在,否则用元数据文件)
|
||||
输出目录: ~/work/knowledge-base/analyzed
|
||||
|
||||
请读取元数据和文字内容,进行深度分析。
|
||||
生成分析报告,保存为Markdown文件。
|
||||
文件名格式: {platform}_{id}.md
|
||||
|
||||
分析报告应包含:
|
||||
- 一句话总结
|
||||
- 核心要点
|
||||
- 时间轴(如适用)
|
||||
- 推荐标签
|
||||
|
||||
返回结果时告诉我输出文件的完整路径。""",
|
||||
timeoutSeconds=180
|
||||
)
|
||||
```
|
||||
|
||||
**预期输出:** `analyzed/{platform}_{id}.md`
|
||||
|
||||
### 步骤 7: 归档和 Git
|
||||
|
||||
**操作:** 移动文件到归档目录,提交 Git。
|
||||
|
||||
```python
|
||||
# 1. 创建归档目录
|
||||
date_dir = Path.home() / "work/knowledge-base/archive" / datetime.now().strftime('%Y-%m-%d')
|
||||
date_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# 2. 移动分析报告
|
||||
analyzed_file = Path(result.get("output_file"))
|
||||
archive_file = date_dir / analyzed_file.name
|
||||
shutil.copy(analyzed_file, archive_file)
|
||||
|
||||
# 3. 复制元数据
|
||||
meta_file = Path.home() / "work/knowledge-base/metadata" / f"{analyzed_file.stem}.meta.json"
|
||||
if meta_file.exists():
|
||||
shutil.copy(meta_file, date_dir / meta_file.name)
|
||||
|
||||
# 4. Git commit(如果已初始化)
|
||||
git_root = Path.home() / "work/knowledge-base/archive"
|
||||
subprocess.run(['git', 'add', '.'], cwd=str(git_root))
|
||||
subprocess.run(['git', 'commit', '-m', f"Archive: {analyzed_file.name}"], cwd=str(git_root))
|
||||
```
|
||||
|
||||
### 步骤 8: 汇报完成
|
||||
|
||||
**操作:** 向用户汇报处理结果。
|
||||
|
||||
```python
|
||||
汇报内容:
|
||||
- 视频标题
|
||||
- 处理阶段完成情况
|
||||
- 最终文件路径
|
||||
- Git commit 信息
|
||||
```
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
知识库根目录 KB_BASE_PATH/
|
||||
├── archive/ # Git归档目录
|
||||
│ ├── YYYY-MM-DD/ # 按日期归档
|
||||
│ └── subscriptions/ # 订阅数据
|
||||
├── pending/ # 链接解析结果 (*.link.json)
|
||||
├── metadata/ # 元数据 (*.meta.json)
|
||||
~/work/knowledge-base/
|
||||
├── archive/
|
||||
│ └── YYYY-MM-DD/
|
||||
│ └── {platform}_{id}.md # 分析报告
|
||||
│ └── {platform}_{id}.meta.json # 元数据
|
||||
├── pending/
|
||||
│ └── {platform}_{id}.link.json # 链接解析结果
|
||||
├── metadata/
|
||||
│ └── {platform}_{id}.meta.json # 元数据
|
||||
├── content/
|
||||
│ ├── downloads/ # 视频文件 (*.mp4) - 7天后清理
|
||||
│ └── subtitles/ # 字幕文件 (*.srt) - 7天后清理
|
||||
├── frames/ # 视频截帧 (*.jpg) - 7天后清理
|
||||
└── analyzed/ # 分析报告 (*.md)
|
||||
│ ├── downloads/
|
||||
│ │ └── {platform}_{id}.mp4 # 视频文件
|
||||
│ ├── subtitles/
|
||||
│ │ └── {platform}_{id}.srt # 字幕文件
|
||||
│ └── {platform}_{id}.txt # OCR结果
|
||||
└── analyzed/
|
||||
└── {platform}_{id}.md # 分析报告
|
||||
```
|
||||
|
||||
## 设计原则
|
||||
|
||||
### workflow 职责
|
||||
|
||||
| 操作 | 说明 |
|
||||
|------|------|
|
||||
| 查重 | 根据URL/文件名查重 |
|
||||
| 创建目录 | 确保 base_path 下目录存在 |
|
||||
| 调用子agent | 使用 sessions_spawn 调用子技能 |
|
||||
| 提取文件名 | 从子agent返回的output_file提取 |
|
||||
| 提取平台 | 从文件名第一个下划线之前提取(不读内容) |
|
||||
| 传递信息 | 给子agent提示词 + 需要的路径 |
|
||||
| 文件流转 | 最后归档 |
|
||||
| Git | commit + push |
|
||||
|
||||
### workflow 不管
|
||||
|
||||
- 不读文件内容
|
||||
- 不关心子技能内部格式
|
||||
- 子技能自己定义输入输出规范
|
||||
|
||||
### 子agent 调用方式
|
||||
|
||||
```python
|
||||
# kb-workflow 调用子agent
|
||||
result = sessions_spawn(
|
||||
agentId="子技能名称",
|
||||
task="提示词 + 需要的路径信息",
|
||||
timeoutSeconds=120
|
||||
)
|
||||
```
|
||||
|
||||
### 子技能返回格式
|
||||
|
||||
所有子技能应返回JSON:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"output_file": "完整文件路径",
|
||||
"subtitles": "字幕文件路径(可选)"
|
||||
}
|
||||
```
|
||||
|
||||
## 环境变量
|
||||
## 环境变量(可选)
|
||||
|
||||
```bash
|
||||
export KB_BASE_PATH="/path/to/knowledge-base" # 知识库根目录
|
||||
export KB_GIT_ROOT="/path/to/archive" # Git仓库目录
|
||||
export KB_GIT_REMOTE="git@github.com:user/repo.git" # 远程仓库
|
||||
export KB_GIT_USER="Username" # 用户名
|
||||
export KB_GIT_EMAIL="user@example.com" # 邮箱
|
||||
export KB_BASE_PATH="~/work/knowledge-base" # 知识库根目录
|
||||
```
|
||||
|
||||
## Usage
|
||||
## 支持的平台
|
||||
|
||||
### 作为 OpenClaw 技能
|
||||
| 平台 | 元数据技能 | 内容技能 |
|
||||
|------|-----------|---------|
|
||||
| Bilibili | kb-bilibili-metadata | kb-bilibili-content |
|
||||
| 知乎 | kb-zhihu-metadata | - |
|
||||
|
||||
当用户发送消息时自动触发:
|
||||
```
|
||||
用户: "添加到知识库 https://www.bilibili.com/video/BVxxx"
|
||||
```
|
||||
## 注意事项
|
||||
|
||||
### 作为子代理
|
||||
|
||||
```python
|
||||
# 从其他技能调用
|
||||
result = sessions_spawn(
|
||||
agentId="kb-workflow",
|
||||
task="添加到知识库 https://www.bilibili.com/video/BVxxx"
|
||||
)
|
||||
```
|
||||
|
||||
### 命令行
|
||||
|
||||
```bash
|
||||
# 处理单个URL
|
||||
python kb_workflow.py --url "https://www.bilibili.com/video/BVxxx"
|
||||
```
|
||||
|
||||
## 子技能集成
|
||||
|
||||
| 阶段 | 子技能 | 输出文件 |
|
||||
|------|--------|----------|
|
||||
| 链接解析 | kb-link-parser | pending/{platform}_{id}.link.json |
|
||||
| 元数据 | kb-bilibili-metadata | metadata/{platform}_{id}.meta.json |
|
||||
| 内容 | kb-bilibili-content | content/downloads/{platform}_{id}.mp4, content/subtitles/{platform}_{id}.srt |
|
||||
| OCR | kb-ocr-processor | content/{platform}_{id}.txt |
|
||||
| 分析 | kb-deep-analyzer | analyzed/{platform}_{id}.md |
|
||||
|
||||
## Related Skills
|
||||
|
||||
- **kb-link-parser** - 链接解析
|
||||
- **kb-bilibili-metadata** - B站元数据
|
||||
- **kb-bilibili-content** - B站内容获取
|
||||
- **kb-deep-analyzer** - 深度分析
|
||||
- **kb-ocr-processor** - OCR处理
|
||||
1. **文件名提取平台:** 从文件名第一个下划线之前提取(如 `bilibili_BVxxx.link.json` → `bilibili`)
|
||||
2. **不读文件内容:** workflow 只根据文件名判断,不读取文件内部
|
||||
3. **超时设置:** OCR 步骤较长,建议 30 分钟超时
|
||||
4. **子代理权限:** 确保子代理已在 allowlist 中配置
|
||||
|
||||
Reference in New Issue
Block a user