20 KiB
20 KiB
name, description
| name | description |
|---|---|
| kb-workflow | 当收到"添加到知识库 + 链接" 或"保存到知识库 + 链接"时使用 |
KB Workflow
触发条件
| 触发词 | 行为 | 示例 |
|---|---|---|
添加到知识库 + 链接 |
添加到知识库并处理 | "添加到知识库 https://www.bilibili.com/video/BVxxx" |
保存到知识库 + 链接 |
同上 | "保存到知识库 https://www.bilibili.com/video/BVxxx" |
状态机定义
工作流是一个严格的状态机,每个状态有明确的前置条件和后置条件:
| 状态 | 前置条件 | 执行动作 | 成功后进入 | 失败处理 |
|---|---|---|---|---|
init |
用户触发 + URL 有效 | 创建 state.json,检查环境变量 | link_parse |
报错退出 |
link_parse |
state.json 存在 | 解析链接,提取平台和ID | metadata |
记录错误,最多重试1次 |
metadata |
platform, content_id 已知 | 提取元数据 | content |
记录错误,最多重试1次 |
content |
元数据文件存在 | 下载内容/字幕 | analyze 或 whisper |
根据错误类型处理 |
whisper |
视频已下载,无官方字幕 | 语音识别转文字 | analyze |
尝试 OCR 降级 |
analyze |
有文本内容(字幕/识别结果/文章) | AI 深度分析 | archive |
流程失败,报错退出 |
archive |
分析报告存在 | 归档 + Git 提交 | done |
记录错误,可手动处理 |
done |
- | 汇报完成 | - | - |
状态判断流程图
用户发送链接
↓
┌─────────────────────────────────────┐
│ Step 0: 环境变量检查 │
│ 缺少必需变量 → 报错退出 │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ Step 1: 链接解析 (link_parse) │
│ 输出: platform, content_type, id │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ Step 2: 元数据提取 (metadata) │
│ 输出: title, author, etc. │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ content_type 判断 │
├─────────────────────────────────────┤
│ video/zvideo → Step 3a (视频处理) │
│ article/zhuanlan/question → Step 3b │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ Step 3a: 视频处理 │
│ 有官方字幕? → 是 → Step 5 │
│ → 否 → Step 4 (Whisper) │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ Step 3b: 文章处理 │
│ 提取文字 → 直接进入 Step 5 │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ Step 4: Whisper 语音识别 (可选) │
│ 无字幕时执行,生成 text/json/srt │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ Step 5: 深度分析 (analyze) │
│ ⚠️ 必须成功,否则流程失败 │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ Step 6: 归档 (archive) │
│ 复制到归档目录 + Git 提交 │
└─────────────────────────────────────┘
↓
完成
环境变量清单
必需变量(缺失则报错退出)
| 变量名 | 用途 | 示例 |
|---|---|---|
AI_API_KEY |
AI API 密钥 | your-api-key |
AI_PROVIDER |
AI 提供商 | zhipu / openai / minimax |
AI_MODEL |
模型名称 | glm-5 / gpt-4 |
AI_BASE_URL |
API 端点 | https://open.bigmodel.cn/api/coding/paas/v4 |
可选变量
| 变量名 | 用途 | 用途说明 |
|---|---|---|
BILIBILI_COOKIE |
B站登录态 | 下载会员视频 |
ZHIHU_COOKIE |
知乎登录态 | 访问专栏等 |
HF_TOKEN |
HuggingFace Token | 说话者分离功能 |
KB_ARCHIVE_PATH |
归档目录 | 默认 ~/work/zq/30.资源/AI分析 |
KB_GIT_ROOT |
Git 仓库根目录 | 默认 ~/work/zq |
KB_GIT_USER |
Git 提交用户名 | 归档时使用 |
KB_GIT_EMAIL |
Git 提交邮箱 | 归档时使用 |
配置方法
# 创建专用配置文件
cat > ~/.kb_env << 'EOF'
export AI_API_KEY="your-api-key"
export AI_PROVIDER="zhipu"
export AI_MODEL="glm-5"
export AI_BASE_URL="https://open.bigmodel.cn/api/coding/paas/v4"
export BILIBILI_COOKIE="SESSDATA=xxx; bili_jct=xxx"
export KB_ARCHIVE_PATH="$HOME/work/zq/30.资源/AI分析"
export KB_GIT_ROOT="$HOME/work/zq"
EOF
# 在 ~/.bashrc 中添加
[ -f ~/.kb_env ] && source ~/.kb_env
步骤详解
Step 0: 环境变量检查
前置条件: 无
执行命令:
# 加载环境变量
if [ -f ~/.kb_env ]; then source ~/.kb_env; fi
# 检查必需变量
for var in AI_API_KEY AI_PROVIDER AI_MODEL AI_BASE_URL; do
if [ -z "${!var}" ]; then
echo "❌ 错误:$var 未设置"
exit 1
fi
done
echo "✅ 环境变量检查通过"
成功标准:
- 所有必需变量已设置
- 输出 "✅ 环境变量检查通过"
失败处理:
- 缺少任何必需变量 → 报错退出,提示用户配置
输出示例:
✅ 环境变量检查通过
AI_PROVIDER: zhipu
AI_MODEL: glm-5
错误示例:
❌ 错误:AI_API_KEY 未设置
请配置以下环境变量:
- AI_API_KEY
- AI_PROVIDER
- AI_MODEL
- AI_BASE_URL
Step 1: 链接解析
前置条件:
- 环境变量检查通过
- URL 格式有效
执行命令:
# 获取目录路径
python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --pending
# 解析链接
python3 ~/.openclaw/skills/kb-link-parser/link-parser.py --url "[URL]"
成功标准:
- 返回 JSON 包含
success: true - 包含字段:
platform,content_type,content_id - 生成文件:
pending/{platform}_{id}.link.json
失败处理:
- 不支持的平台 → 报错退出,告知用户支持的平台
- URL 无效 → 报错退出,请用户提供正确链接
输出示例:
{
"success": true,
"platform": "bilibili",
"content_type": "video",
"content_id": "BV1xx411c7mD",
"output_file": "pending/bilibili_BV1xx411c7mD.link.json"
}
错误示例:
{
"success": false,
"error": "不支持的平台: example.com",
"supported_platforms": ["bilibili.com", "zhihu.com", "youtube.com"]
}
Step 2: 元数据提取
前置条件:
- Step 1 完成
platform,content_type,content_id已知
执行命令:
# 获取目录路径
python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --metadata
# 根据平台选择命令
# B站视频
python3 ~/.openclaw/skills/kb-bilibili-metadata/bilibili_metadata.py \
--id "[BV号]" --type video \
--output "metadata/bilibili_[BV号].meta.json"
# B站专栏
python3 ~/.openclaw/skills/kb-bilibili-metadata/bilibili_metadata.py \
--id "[cv号]" --type article \
--output "metadata/bilibili_cv[cv号].meta.json"
# 知乎问答
python3 ~/.openclaw/skills/kb-zhihu-metadata/zhihu_metadata.py \
--id "[问题ID]" --type question \
--output "metadata/zhihu_[ID].meta.json"
# 知乎视频
python3 ~/.openclaw/skills/kb-zhihu-metadata/zhihu_metadata.py \
--id "[视频ID]" --type zvideo \
--output "metadata/zhihu_[ID].meta.json"
成功标准:
- 返回 JSON 包含
success: true - 包含字段:
platform,content_id,title - 生成文件:
metadata/{platform}_{id}.meta.json
失败处理:
- 网络错误 → 重试1次
- 内容不存在 → 报错退出
- 需要登录 → 提示配置 Cookie
输出示例:
{
"success": true,
"platform": "bilibili",
"content_id": "BV1xx411c7mD",
"content_type": "video",
"title": "视频标题",
"author": "UP主名字",
"duration": "10:30",
"output_file": "metadata/bilibili_BV1xx411c7mD.meta.json"
}
错误示例:
{
"success": false,
"error": "视频不存在或已被删除",
"content_id": "BV1xx411c7mD"
}
Step 3a: 视频内容下载
前置条件:
- Step 2 完成
content_type为video或zvideo
执行命令:
# 获取目录路径
python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --content_downloads
# B站视频 - 优先尝试字幕
python3 ~/.openclaw/skills/kb-bilibili-content/bilibili_content.py \
--id "[BV号]" --type subtitle-download \
--output "content/downloads/"
# 检查是否有官方字幕
# 如果 has_subtitle=true → 进入 Step 5
# 如果 has_subtitle=false → 下载视频,进入 Step 4
成功标准:
- 返回 JSON 包含
success: true has_subtitle=true: 有字幕文件has_subtitle=false: 视频文件下载成功
失败处理:
- 403 禁止访问 → 检查 BILIBILI_COOKIE 配置
- 网络超时 → 重试1次
- 会员视频 → 提示需要配置 Cookie
输出示例(有字幕):
{
"success": true,
"type": "subtitle",
"has_subtitle": true,
"subtitle_file": "content/downloads/bilibili_BV1xx411c7mD.srt",
"message": "官方字幕下载成功"
}
输出示例(无字幕):
{
"success": true,
"type": "subtitle",
"has_subtitle": false,
"message": "无官方字幕,需要下载视频进行语音识别"
}
错误示例:
{
"success": false,
"error": "403 Forbidden - 可能需要会员权限",
"suggestion": "请配置 BILIBILI_COOKIE 环境变量"
}
Step 3b: 文章内容提取
前置条件:
- Step 2 完成
content_type为article、zhuanlan或question
执行命令:
# B站专栏
python3 ~/.openclaw/skills/kb-bilibili-content/bilibili_content.py \
--id "[cv号]" --type article \
--output "content/"
# 知乎专栏
python3 ~/.openclaw/skills/kb-zhihu-content/zhihu_content.py \
--type article-from-media \
--output "content/"
成功标准:
- 返回 JSON 包含
success: true - 包含字段:
filepath,content_length - 跳过 Step 4,直接进入 Step 5
输出示例:
{
"success": true,
"type": "article",
"filepath": "content/bilibili_cv43780186.txt",
"content_length": 5234,
"message": "文章内容提取成功"
}
Step 4: Whisper 语音识别
前置条件:
- Step 3a 完成
has_subtitle=false- 视频文件已下载
执行命令:
# 获取目录路径
python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --content
# 普通识别
python3 ~/.openclaw/skills/kb-whisper/whisper.py \
--input "content/downloads/bilibili_BV1xx411c7mD.mp4" \
--model base \
--output "content/"
# 带说话者分离(需要 HF_TOKEN)
if [ -n "$HF_TOKEN" ]; then
python3 ~/.openclaw/skills/kb-whisper-diarization/whisper_diarization.py \
--input "content/downloads/bilibili_BV1xx411c7mD.mp4" \
--model base --diarize \
--output "content/"
fi
成功标准:
- 返回 JSON 包含
success: true - 生成文件:
.json,.txt,.srt
失败处理:
- 模型未下载 → 提示下载模型
- 内存不足 → 尝试更小的模型
- Whisper 失败 → 尝试 OCR 降级
输出示例:
{
"success": true,
"input_file": "content/downloads/bilibili_BV1xx411c7mD.mp4",
"model": "base",
"output_files": {
"json": "content/bilibili_BV1xx411c7mD.json",
"txt": "content/bilibili_BV1xx411c7mD.txt",
"srt": "content/bilibili_BV1xx411c7mD.srt"
},
"duration_seconds": 630
}
Step 5: 深度分析
前置条件:
- 有文本内容(字幕/识别结果/文章)
- 元数据文件存在
执行命令:
# 获取目录路径
python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --analyzed
# 分析视频
AI_API_KEY="$AI_API_KEY" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \
python3 -u ~/.openclaw/skills/kb-deep-analyzer/deep_analyzer.py \
--metadata "metadata/bilibili_BV1xx411c7mD.meta.json" \
--content "content/bilibili_BV1xx411c7mD.json" \
--output "analyzed/bilibili_BV1xx411c7mD.md" \
--type video \
--provider zhipu --model glm-5
# 分析文章
AI_API_KEY="$AI_API_KEY" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \
python3 -u ~/.openclaw/skills/kb-deep-analyzer/deep_analyzer.py \
--metadata "metadata/xxx.meta.json" \
--content "content/xxx.txt" \
--output "analyzed/xxx.md" \
--type article \
--provider zhipu --model glm-5
成功标准:
- 返回 JSON 包含
success: true - 生成分析报告文件
失败处理:
- ⚠️ 深度分析失败 = 整个流程失败
- API 调用失败 → 记录错误,终止流程
- 禁止使用预设模板或降级内容
输出示例:
{
"success": true,
"output_file": "analyzed/bilibili_BV1xx411c7mD.md",
"model": "glm-5",
"provider": "zhipu"
}
错误示例:
{
"success": false,
"error": "AI API 调用失败: rate limit exceeded",
"message": "深度分析失败,整个流程终止"
}
Step 6: 归档
前置条件:
- Step 5 完成
- 分析报告文件存在
执行命令:
# 归档
python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py \
--archive-file "analyzed/bilibili_BV1xx411c7mD.md"
# 如果配置了 Git,会自动提交
成功标准:
- 文件复制到归档目录
- Git 提交成功(如果配置)
失败处理:
- 归档失败 → 记录错误,文件仍可用
- Git 失败 → 不影响主流程
输出示例:
{
"success": true,
"archive_path": "~/work/zq/30.资源/AI分析/2026-03-13/bilibili_BV1xx411c7mD.md",
"git_commit": "abc1234"
}
目录结构
~/work/knowledge-base/ # 知识库根目录
├── pending/ # 待处理链接
│ └── {platform}_{id}.link.json
├── metadata/ # 元数据
│ └── {platform}_{id}.meta.json
├── content/ # 内容
│ ├── downloads/ # 视频下载
│ │ └── {platform}_{id}.mp4
│ ├── {platform}_{id}.txt # 文本内容
│ └── {platform}_{id}.json # Whisper 结果
└── analyzed/ # 深度分析报告
└── {platform}_{id}.md
~/work/zq/30.资源/AI分析/ # 归档目录
└── YYYY-MM-DD/
└── {platform}_{id}.md
子技能清单
| 步骤 | 子技能 | 命令 |
|---|---|---|
| 1 | kb-link-parser | --url "[URL]" |
| 2 | kb-bilibili-metadata | --id "[ID]" --type video --output "[PATH]" |
| 2 | kb-zhihu-metadata | --id "[ID]" --type question --output "[PATH]" |
| 3a | kb-bilibili-content | --id "[ID]" --type subtitle-download --output "[PATH]" |
| 3a | kb-bilibili-content | --id "[ID]" --type video --output "[PATH]" |
| 3b | kb-bilibili-content | --id "[ID]" --type article --output "[PATH]" |
| 3b | kb-zhihu-content | --type article-from-media --output "[PATH]" |
| 4 | kb-whisper | --input "[VIDEO]" --model base --output "[PATH]" |
| 4 | kb-whisper-diarization | --input "[VIDEO]" --model base --diarize --output "[PATH]" |
| 5 | kb-deep-analyzer | --metadata "[META]" --content "[CONTENT]" --output "[OUT]" --type video |
端到端示例
示例 1: B站视频(有官方字幕)
输入: 添加到知识库 https://www.bilibili.com/video/BV1xx411c7mD
Step 0: ✅ 环境变量检查通过
Step 1: ✅ 链接解析 → bilibili, video, BV1xx411c7mD
Step 2: ✅ 元数据提取 → 标题: "xxx", 作者: "xxx"
Step 3a: ✅ 字幕下载 → has_subtitle=true, bilibili_BV1xx411c7mD.srt
Step 4: ⏭️ 跳过(有官方字幕)
Step 5: ✅ 深度分析 → bilibili_BV1xx411c7mD.md
Step 6: ✅ 归档 → ~/work/zq/30.资源/AI分析/2026-03-13/
示例 2: B站视频(无官方字幕)
输入: 添加到知识库 https://www.bilibili.com/video/BV1yy411c7mE
Step 0: ✅ 环境变量检查通过
Step 1: ✅ 链接解析 → bilibili, video, BV1yy411c7mE
Step 2: ✅ 元数据提取 → 标题: "xxx", 时长: "15:30"
Step 3a: ⚠️ 无官方字幕 → 下载视频
Step 3a: ✅ 视频下载 → bilibili_BV1yy411c7mE.mp4
Step 4: ✅ Whisper 识别 → bilibili_BV1yy411c7mE.json/txt/srt
Step 5: ✅ 深度分析 → bilibili_BV1yy411c7mE.md
Step 6: ✅ 归档
示例 3: 403 下载失败
输入: 添加到知识库 https://www.bilibili.com/video/BV1zz411c7mF
Step 0: ✅ 环境变量检查通过
Step 1: ✅ 链接解析
Step 2: ✅ 元数据提取
Step 3a: ❌ 403 Forbidden
→ 可能需要会员权限
→ 请配置 BILIBILI_COOKIE 环境变量
→ 流程暂停,等待用户处理
常见错误处理
错误 1: 环境变量未设置
症状: ❌ 错误:AI_API_KEY 未设置
解决:
echo 'export AI_API_KEY="your-key"' >> ~/.kb_env
source ~/.kb_env
错误 2: 403 下载失败
症状: B站视频下载返回 403
解决:
- 获取 B站 Cookie(F12 → Network → Copy Cookie)
- 配置环境变量:
echo 'export BILIBILI_COOKIE="SESSDATA=xxx; bili_jct=xxx"' >> ~/.kb_env
source ~/.kb_env
错误 3: 深度分析失败
症状: success: false from kb-deep-analyzer
处理:
- 整个流程终止
- 检查 AI_API_KEY 是否有效
- 检查 AI_BASE_URL 是否正确
- 检查模型配额是否用尽
错误 4: Whisper 模型未下载
症状: Model file not found
解决:
cd ~/whisper.cpp
./models/download-ggml-model.sh base
状态管理(断点续传)
⚠️ 此功能需要完成 P3 实现
# 初始化状态
python3 kb_workflow.py --init-state "[URL]"
# 查询当前状态
python3 kb_workflow.py --get-state "[URL]"
# 推进到下一步
python3 kb_workflow.py --advance-step "[URL]" "metadata"
# 记录错误
python3 kb_workflow.py --record-error "[URL]" "403 Forbidden"
# 获取恢复指令
python3 kb_workflow.py --resume "[URL]"
⚠️ 严格失败处理原则
- 深度分析不可跳过:kb-deep-analyzer 是必须成功的步骤
- 失败即终止:如果深度分析返回
success: false,必须立即停止 - 禁止降级处理:不能使用预设模板或简单摘要"假装成功"
- 每次执行都要使用 AI:必须有真实的 AI API 调用