diff --git a/kb-workflow/SKILL.md b/kb-workflow/SKILL.md index e88bb8a..a4c8573 100644 --- a/kb-workflow/SKILL.md +++ b/kb-workflow/SKILL.md @@ -38,510 +38,167 @@ export AI_BASE_URL="https://open.bigmodel.cn/api/coding/paas/v4" | `KB_GIT_EMAIL` | Git提交邮箱 | `your@email.com` | | `KB_ARCHIVE_PATH` | 归档目录路径 | `~/work/zq/30.资源/AI分析` | | `KB_GIT_ROOT` | Git仓库根目录 | `~/work/zq` | +| `HF_TOKEN` | HuggingFace Token(说话者分离) | `hf_xxx` | ### 检查命令 ```bash -# 检查必须的环境变量 -echo "AI_API_KEY: ${AI_API_KEY:0:10}..." -echo "AI_PROVIDER: $AI_PROVIDER" -echo "AI_MODEL: $AI_MODEL" -echo "AI_BASE_URL: $AI_BASE_URL" - -# 验证方式1: 检查变量是否存在 -if [ -z "$AI_API_KEY" ]; then - echo "❌ AI_API_KEY 未设置" - exit 1 -fi - -# 验证方式2: 执行测试调用 -python3 -c " -import os -if not os.environ.get('AI_API_KEY'): - raise RuntimeError('AI_API_KEY 未设置') -print('✅ 环境变量检查通过') -" -``` - - -## Workflow 执行方式 - -主代理直接执行以下步骤,无需启动 kb-workflow 子代理: - -1. 主代理启动子代理调用 kb-link-parser -2. 主代理启动子代理调用 kb-平台-metadata -3. 主代理启动子代理调用 kb-平台-content -4. 主代理启动子代理调用 kb-ocr-processor(如需要) -5. 主代理启动子代理调用 kb-deep-analyzer -6. 主代理执行 `kb_workflow.py --archive-file` 归档 - - -## Workflow 执行步骤 - -当触发后,按照以下步骤执行: - -### 步骤 1: 环境变量检查 - -**❌ 禁止跳过此步骤!必须先检查环境变量。** - -```bash -# 0. 从 ~/.kb_env 加载环境变量(专门的知识库配置文件,不受 bashrc 交互式检查影响) +# 从 ~/.kb_env 加载环境变量 if [ -f ~/.kb_env ]; then source ~/.kb_env fi -# 1. 检查必须的环境变量是否存在 +# 检查必须的环境变量 if [ -z "$AI_API_KEY" ] || [ -z "$AI_PROVIDER" ] || [ -z "$AI_MODEL" ] || [ -z "$AI_BASE_URL" ]; then echo "❌ 错误:必须的环境变量未设置" - echo "请配置以下环境变量:" - echo " - AI_API_KEY" - echo " - AI_PROVIDER (zhipu/openai/minimax)" - echo " - AI_MODEL" - echo " - AI_BASE_URL" + echo "请配置 ~/.kb_env 文件" exit 1 fi echo "✅ 环境变量检查通过" -echo " AI_PROVIDER: $AI_PROVIDER" -echo " AI_MODEL: $AI_MODEL" ``` -**如果检查不通过,必须**: -1. 报错提示用户 -2. 退出,不执行后续步骤 -3. 等待用户配置好环境变量后重新执行 +## Workflow 执行方式 + +### 方式一:一键处理(推荐) + +使用管道 CLI 一键完成所有步骤: + +```bash +python3 kb-workflow/kb_workflow.py process "https://www.bilibili.com/video/BVxxx" +``` + +**该命令自动执行:** +1. URL 解析 → 识别平台和内容 ID +2. 元数据提取 → 获取标题、作者等信息 +3. 内容下载 → 字幕/视频/文章内容 +4. 语音识别 → Whisper/FunASR(如需要) +5. 深度分析 → AI 生成分析报告 +6. 归档 → 移动到归档目录 + +**命令参数:** +```bash +# 指定输出目录 +python3 kb-workflow/kb_workflow.py process "https://..." -o /path/to/output + +# 强制重新执行(忽略已完成状态) +python3 kb-workflow/kb_workflow.py process "https://..." --no-skip +``` + +### 方式二:手动分步执行(高级) + +如需更细粒度控制,可手动调用各子技能: + +```bash +# 1. 查重 +python3 kb-workflow/kb_workflow.py --check --url "https://..." + +# 2. 一键处理 +python3 kb-workflow/kb_workflow.py process "https://..." + +# 3. 归档 +python3 kb-workflow/kb_workflow.py --archive-file "/path/to/report.md" +``` + +## 支持的平台和内容类型 + +| 平台 | 内容类型 | URL 示例 | +|------|----------|----------| +| B站 | 视频 | `bilibili.com/video/BVxxx` | +| B站 | 专栏 | `bilibili.com/read/cvxxx` | +| 知乎 | 问答 | `zhihu.com/question/xxx` | +| 知乎 | 专栏 | `zhuanlan.zhihu.com/p/xxx` | +| 知乎 | 视频 | `zhihu.com/zvideo/xxx` | + +## 处理流程 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ kb-workflow process │ +├─────────────────────────────────────────────────────────────┤ +│ 1. Parse → LinkParser 解析 URL │ +│ 2. Download → 平台适配器获取元数据和内容 │ +│ 3. ASR → 语音识别(视频无字幕时) │ +│ 4. Analyze → DeepAnalyzer 生成分析报告 │ +│ 5. Archive → 归档到 KB_ARCHIVE_PATH │ +└─────────────────────────────────────────────────────────────┘ +``` + +## 目录结构 + +**工作目录(默认 ~/work/knowledge-base/):** +``` +~/work/knowledge-base/ +├── pending/ # 待处理链接 +├── metadata/ # 元数据 JSON +├── content/ # 内容文件 +│ └── downloads/ # 下载的视频/字幕 +└── analyzed/ # 分析报告 +``` + +**归档目录(默认 ~/work/zq/30.资源/AI分析/):** +``` +~/work/zq/30.资源/AI分析/ +└── YYYY-MM-DD/ + └── {platform}_{id}.md # 深度分析报告 +``` ## ⚠️ 严格失败处理原则 > **深度分析步骤必须成功,否则整个流程失败** -在执行工作流时,必须遵守以下原则: -1. **深度分析不可跳过**:kb-deep-analyzer 是必须成功执行的步骤 -2. **失败即终止**:如果深度分析返回 `success: false`,必须立即停止并汇报失败 +1. **深度分析不可跳过**:AI 分析是必须成功执行的步骤 +2. **失败即终止**:如果分析返回失败,必须立即停止并汇报 3. **禁止降级处理**:不能使用预设模板或简单摘要来"假装成功" 4. **每次执行都要使用 AI**:必须有真实的 AI API 调用记录 -### 步骤 2: 链接解析 - -1. 获取目录路径: -```bash -python3 kb_workflow.py --pending -``` - -2. 启动子代理调用 kb-link-parser: -```bash -python3 /path/to/link-parser.py --url "[URL]" -``` - -3. 解析输出 JSON,提取 filename 和 platform - -### 步骤 3: 元数据提取 - -1. 获取元数据目录路径: -```bash -python3 kb_workflow.py --metadata -# 返回: {"path": "/home/admin/work/knowledge-base/metadata"} -``` - -2. 构建输出文件路径:`${metadata_dir}/${platform}_${id}.meta.json` - -3. 启动子代理调用对应平台的 metadata 技能(传入 `--output`): -```bash -# Bilibili -python3 /path/to/bilibili_metadata.py --id "[ID]" --type video --output "${metadata_dir}/bilibili_[ID].meta.json" - -# Zhihu -python3 /path/to/zhihu_metadata.py --id "[ID]" --type question --output "${metadata_dir}/zhihu_[ID].meta.json" -``` - -4. 解析输出 JSON,提取 filename - -### 步骤 4: 内容下载 - -> ⚠️ **根据内容类型选择处理方式**: -> - **视频 (video)**:下载字幕/视频(B站视频) -> - **知乎视频 (zvideo)**:下载视频 -> - **专栏文章 (article)**:提取文字内容(跳过步骤5) -> - **知乎问答/专栏**:提取文字内容(跳过步骤5) - -#### 4.1 视频内容处理(B站视频 type=video) - -1. 获取目录路径: -```bash -python3 kb_workflow.py --content_downloads -python3 kb_workflow.py --content -``` - -2. 启动子代理调用对应平台的 content 技能: -```bash -# Bilibili 字幕下载(自动检测是否有官方字幕) -python3 /path/to/bilibili_content.py --id "[ID]" --type subtitle-download --output [content_dir] - -# 返回 JSON 包含 has_subtitle 字段 -``` - -3. 解析输出 JSON: -- **has_subtitle = true**: 有官方字幕,直接进入步骤 6 -- **has_subtitle = false**: 没有官方字幕,继续步骤 5 - -> ⚠️ **重要提示**:没有找到官方字幕是**正常的**!很多视频没有自动生成的字幕。不要因为没有字幕就停止工作流,继续执行 Whisper 步骤即可。 - -#### 4.1.2 知乎视频处理(type=zvideo) - -1. 获取目录路径: -```bash -python3 kb_workflow.py --content_downloads -python3 kb_workflow.py --content -``` - -2. 启动子代理调用知乎 content 技能: -```bash -# 知乎视频下载 -python3 /path/to/zhihu_content.py --id "[ID]" --type video --output [content_dir] -``` - -3. 知乎视频没有官方字幕,直接进入步骤 5(Whisper 语音识别) - -#### 4.2 专栏文章处理(type=article/zhuanlan/question) - -1. 获取目录路径: -```bash -python3 kb_workflow.py --content -``` - -2. 启动子代理调用对应平台的 content 技能提取文字: - -**B站专栏 (article)**: -```bash -# 提取专栏文字内容 -python3 /path/to/bilibili_content.py --id "cv[ID]" --type article --output [content_dir] - -# 示例:cv43780186 → id 填 43780186 -python3 /path/to/bilibili_content.py --id "43780186" --type article --output [content_dir] -``` - -**知乎文章/问答**: -```bash -# 知乎专栏文章(推荐方式:自动爬取) -python3 /path/to/zhihu_content.py --id "2013919514258072086" --type zhuanlan --output [content_dir] -# 或使用完整 URL -python3 /path/to/zhihu_content.py --id "https://zhuanlan.zhihu.com/p/2013919514258072086" --type zhuanlan --output [content_dir] - -# 如果已有 MediaCrawler 数据,可直接读取 -python3 /path/to/zhihu_content.py --type article-from-media --input [json文件路径] --output [content_dir] -``` - -3. 解析输出 JSON,提取文字内容用于深度分析 - -> ⚠️ **重要**:专栏文章不需要 Whisper 步骤,提取完文字后直接进入步骤 6(深度分析) - -### 步骤 5: 语音识别转文字(仅当没有官方字幕时执行) - -> ⚠️ **重要**:此步骤仅在**没有官方字幕**时执行。如果有官方字幕,**跳过此步骤**。 - -此步骤使用 Whisper 进行语音识别: -- **严禁跳过**:必须等待识别完成 -- **定时汇报**:每2-3分钟向用户汇报进度 -- **超时时间**:30分钟 -- **耐心等待**:不要中途启动其他步骤,必须串行执行 - -1. 获取目录路径: -```bash -python3 kb_workflow.py --content -``` - -2. **选择识别方式**: - -**方式 A: 普通识别(不区分说话者)** -```bash -python3 /path/to/whisper.py --input [video_path] --model base --output [content_dir] -``` - -**方式 B: 带说话者分离(推荐用于访谈、对话类视频)** -```bash -# 先检查 HF_TOKEN 环境变量 -if [ -z "$HF_TOKEN" ]; then - echo "⚠️ HF_TOKEN 未设置,将使用普通识别(不区分说话者)" - python3 /path/to/whisper.py --input [video_path] --model base --output [content_dir] -else - echo "✅ 使用说话者分离模式" - python3 /path/to/whisper_diarization.py --input [video_path] --model base --diarize --output [content_dir] -fi -``` - -**方式 C: kb-funasr(备用方案,Whisper 效果不佳时使用)** -```bash -# 当 Whisper 识别效果不好时,可尝试使用 FunAudioLLM 的 SenseVoice 模型 -# 支持中文、英文、粤语、日语、韩语等 -python3 /path/to/funasr_runner.py --input [video_path] --model sensevoice --output [content_dir] - -# 或使用 Paraformer 模型(更精准但稍慢) -python3 /path/to/funasr_runner.py --input [video_path] --model paraformer --output [content_dir] -``` - -**方式 D: OCR 识别(当语音识别困难时的替代方案)** -> ⚠️ **适用场景**:音频质量差、有背景音乐干扰、多种语言混合等情况,语音识别效果不佳时使用 OCR 作为补充或替代。 - -```bash -# 使用 kb-ocr-processor 进行视频 OCR 识别 -# 会截取视频帧并进行文字识别 -python3 /path/to/ocr_processor.py --input [video_path] --output [content_dir] -``` - -> 📌 **识别方式选择建议**: -> - **首选 Whisper**(通用性强) -> - **Whisper 效果不佳时**尝试 kb-funasr(中文支持更好) -> - **音频质量极差或多种语言混合**时考虑 OCR -> - **访谈/对话类视频**推荐使用带说话者分离的 Whisper - -3. 等待 Whisper 完成(定时汇报进度) - -4. 解析输出 JSON: -- 普通识别:生成 `xxx.json`, `xxx.txt`, `xxx.srt` -- 说话者分离:生成 `xxx_diarized.json`, `xxx_diarized.txt`, `xxx_diarized.srt` - -#### 说话者分离环境变量 - -| 变量名 | 用途 | 获取方式 | -|--------|------|----------| -| `HF_TOKEN` | HuggingFace Token | 见下方说明 | - -**获取 HuggingFace Token:** -1. 注册 HuggingFace 账号:https://huggingface.co/join -2. 申请 pyannote 模型访问权限: - - https://huggingface.co/pyannote/speaker-diarization (点击 "Access") - - https://huggingface.co/pyannote/segmentation (点击 "Access") -3. 创建 Token:https://huggingface.co/settings/tokens → New token → Read -4. 设置环境变量: - ```bash - # 添加到 ~/.kb_env - echo 'export HF_TOKEN="hf_xxxxxxxxxxxxxxxxxxxxxx"' >> ~/.kb_env - source ~/.kb_env - ``` - -### 步骤 6: 深度分析 - -1. 获取目录路径: -```bash -python3 kb_workflow.py --analyzed -``` - -2. 准备 content JSON 文件(包含 subtitle/description) - -3. 如果有官方字幕,使用官方字幕的 SRT 文件 -4. 如果没有官方字幕,使用 Whisper 识别的结果 - -5. 启动子代理调用 kb-deep-analyzer(使用 g5 模型): - -**根据内容类型选择 --type 参数:** -- 视频(video/zvideo):`--type video` -- 文章(article/zhuanlan/question):`--type article` - -```bash -# 视频 -python3 /path/to/deep_analyzer.py --metadata [meta_path] --content [content_path] --output [analyzed_dir]/[filename].md --type video --provider zhipu --model glm-5 - -# 文章 -python3 /path/to/deep_analyzer.py --metadata [meta_path] --content [content_path] --output [analyzed_dir]/[filename].md --type article --provider zhipu --model glm-5 -``` - -**文章类型输出格式:** -- 300 字以内的摘要(核心观点) -- 主要主题 -- 完整原文 - -**环境变量设置**(在子代理中设置): -- `AI_PROVIDER=zhipu` -- `AI_MODEL=glm-5` - -6. 解析输出 JSON,检查 `success` 字段: - -> ⚠️ **深度分析失败 = 整个流程失败** -> - 如果 `success = true`:继续步骤 7(归档) -> - 如果 `success = false`:**立即终止流程**,向用户汇报失败原因 -> - **严禁**继续执行后续步骤或使用降级内容"假装成功" - -### 步骤 7: 归档 - -运行归档命令: -```bash -python3 kb_workflow.py --archive-file "[分析报告文件路径]" -``` - -### 步骤 8: 汇报完成 - -向用户汇报: -- 视频标题 -- 处理阶段完成情况 -- 最终文件路径 -- Git commit 信息 - - -## 子技能清单 - -| 步骤 | 子技能 | 命令示例 | 输出 | 备注 | -|------|--------|----------|------|------| -| 2 | kb-link-parser | `--url "BVxxx"` | `{p}_{id}.link.json` | | -| 3 | kb-bilibili-metadata | `--id "BVxxx" --type video` | `{p}_{id}.meta.json` | | -| 3 | kb-bilibili-metadata | `--id "cvxxx" --type article` | `{p}_{id}.meta.json` | 专栏元数据 | -| 3 | kb-zhihu-metadata | `--id "xxx" --type question` | `{p}_{id}.meta.json` | 知乎问答 | -| 3 | kb-zhihu-metadata | `--id "xxx" --type answer` | `{p}_{id}.meta.json` | 知乎回答 | -| 3 | kb-zhihu-metadata | `--id "xxx" --type zvideo` | `{p}_{id}.meta.json` | 知乎视频 | -| 4 | kb-bilibili-content | `--id "BVxxx" --type subtitle-download` | `{p}_{id}.srt` | 如果没有字幕是正常的 | -| 4 | kb-bilibili-content | `--id "BVxxx" --type video` | `{p}_{id}.mp4` | 如果需要下载视频 | -| 4 | kb-bilibili-content | `--id "cvxxx" --type article` | `{p}_{id}.txt` | **专栏文章提取文字** | -| 4 | kb-zhihu-content | `--id "xxx" --type video` | `{p}_{id}.mp4` | **知乎视频下载** | -| 5 | kb-whisper | `--input xxx.mp4 --model base` | `{p}_{id}.json`, `{p}_{id}.txt` | 仅当没有官方字幕时执行 | -| 5 | kb-whisper-diarization | `--input xxx.mp4 --model base --diarize` | `{p}_{id}_diarized.json` | 带说话者分离(需 HF_TOKEN) | -| 5 | kb-funasr | `--input xxx.mp4 --model sensevoice` | `{p}_{id}.json`, `{p}_{id}.txt` | **推荐用于中文视频** | -| 5 | kb-ocr-processor | `--input xxx.mp4` | `{p}_{id}_ocr.json` | 语音识别困难时的替代方案 | -| 6 | kb-deep-analyzer | `--metadata x.meta.json --content x.json --output x.md --type video --provider zhipu --model glm-5` | `{p}_{id}.md` | **视频分析,使用 g5 模型** | -| 6 | kb-deep-analyzer | `--metadata x.meta.json --content x.json --output x.md --type article --provider zhipu --model glm-5` | `{p}_{id}.md` | **文章分析,300字摘要+原文** | - -## 条件分支逻辑 - -### 内容类型判断 - -链接解析后,根据 `type` 字段判断内容类型: - -| type 值 | 内容类型 | 处理方式 | -|---------|---------|---------| -| `video` | B站视频 | 下载视频/字幕,可能需要 Whisper | -| `zvideo` | 知乎视频 | 下载视频,需要 Whisper 语音识别 | -| `article` | B站专栏 | 直接提取文字内容 | -| `zhuanlan` | 知乎专栏 | 直接提取文字内容 | -| `question` / `answer` | 知乎问答 | 直接提取文字内容 | -| `note` | 小红书 | 下载图片 | - -### 视频处理流程(type=video/zvideo) - -``` -步骤3: 获取元数据 - ↓ -步骤4: 下载字幕 (--type subtitle-download) - ↓ -┌─────────────────────────────────────┐ -│ has_subtitle = true? │ -├─────────────────────────────────────┤ -│ 是 → 直接进入步骤6(深度分析) │ -│ 否 → 进入步骤5(Whisper语音识别) │ -└─────────────────────────────────────┘ - ↓ -步骤6: 深度分析 - ↓ -┌─────────────────────────────────────┐ -│ kb-deep-analyzer 执行结果 │ -├─────────────────────────────────────┤ -│ success = true → 步骤7(归档) │ -│ success = false → ❌ 整个流程失败 │ -└─────────────────────────────────────┘ -``` - -### 专栏文章处理流程(type=article/zhuanlan/question) - -``` -步骤3: 获取元数据 - ↓ -步骤4: 提取专栏/文章文字内容 - │ 命令: python3 bilibili_content.py --id "cvxxx" --type article - ↓ -步骤6: 深度分析(使用 --type article) - │ 命令: python3 deep_analyzer.py --type article - │ 输出: 300字摘要 + 原文 - ↓ -步骤6: 深度分析(直接使用提取的文字) - ↓ -┌─────────────────────────────────────┐ -│ kb-deep-analyzer 执行结果 │ -├─────────────────────────────────────┤ -│ success = true → 步骤7(归档) │ -│ success = false → ❌ 整个流程失败 │ -└─────────────────────────────────────┘ -``` - -> ⚠️ **重要:深度分析失败则整个流程失败** -> - 深度分析必须使用正确的 AI 模型(glm-5)完整分析字幕内容 -> - 如果 `kb-deep-analyzer` 返回 `success: false`,**必须汇报失败**,不能继续执行后续步骤 -> - 不能使用预设模板或降级内容来"假装成功" -> - 失败时必须向用户报告具体的错误原因 - -> ⚠️ **重要**:没有找到官方字幕是**正常的**!很多视频没有自动生成的字幕。 -> - 如果 `has_subtitle = false`,继续执行 Whisper 步骤 -> - 如果 `has_subtitle = true`,跳过 Whisper 步骤,直接使用官方字幕 - -## 目录结构 - -**工作目录(~/work/knowledge-base/):** -``` -~/work/knowledge-base/ -├── pending/ -│ └── {platform}_{id}.link.json -├── metadata/ -│ └── {platform}_{id}.meta.json -├── content/ -│ ├── downloads/ -│ │ └── {platform}_{id}.mp4 -│ ├── {platform}_{id}.txt # Whisper 识别的文本 -│ └── {platform}_{id}.json # Whisper 完整结果 -└── analyzed/ - └── {platform}_{id}.md -``` - -**归档目录(~/work/zq/30.资源/AI分析/):** -``` -~/work/zq/30.资源/AI分析/ -└── YYYY-MM-DD/ - ├── {platform}_{id}.md # 深度分析报告 - └── {platform}_{id}.meta.json # 元数据(可选) -``` - -> 📌 **注意**:归档目录通过 `KB_ARCHIVE_PATH` 环境变量配置,默认为 `~/work/zq/30.资源/AI分析` - ## 辅助命令 ```bash -# ------------------- 查重与归档 ------------------- - # 查重 -python3 kb_workflow.py --check --url "[URL]" +python3 kb-workflow/kb_workflow.py --check --url "https://..." + +# 获取目录路径 +python3 kb-workflow/kb_workflow.py --base-path +python3 kb-workflow/kb_workflow.py --metadata +python3 kb-workflow/kb_workflow.py --content +python3 kb-workflow/kb_workflow.py --analyzed # 归档分析报告 -python3 kb_workflow.py --archive-file "[分析报告路径]" - - -# ------------------- 目录路径查询 ------------------- - -# 获取知识库根目录(默认 ~/work/knowledge-base) -python3 kb_workflow.py --base-path "~/custom/path" - -# 获取待处理目录(pending) -python3 kb_workflow.py --pending - -# 获取元数据目录 -python3 kb_workflow.py --metadata - -# 获取内容目录 -python3 kb_workflow.py --content - -# 获取内容下载目录 -python3 kb_workflow.py --content_downloads - -# 获取字幕目录 -python3 kb_workflow.py --content_subtitles - -# 获取深度分析目录 -python3 kb_workflow.py --analyzed - -# 获取归档目录 -python3 kb_workflow.py --archive - -# 获取订阅信息目录 -python3 kb_workflow.py --archive_subscriptions - - -# ------------------- 工具函数 ------------------- - -# 从文件名提取平台名称 -python3 kb_workflow.py --extract_platform "bilibili_BVxxx.mp4" +python3 kb-workflow/kb_workflow.py --archive-file "/path/to/report.md" ``` +## 示例 + +``` +用户: 添加到知识库 https://www.bilibili.com/video/BV1xx + +Claude: +✅ 环境变量检查通过 + +◆ 处理中... + → 解析 URL: bilibili 视频 BV1xx + → 获取元数据... + → 下载字幕... + → 深度分析... + +✅ 完成! + +标题: 【教程】如何使用 Python 进行数据分析 +处理阶段: 全部完成 +最终文件: ~/work/zq/30.资源/AI分析/2026-03-15/bilibili_BV1xx.md +``` + +## 技术架构 + +``` +kb-workflow/kb_workflow.py (CLI) + └── kb_pipeline/ (核心管道包) + ├── pipeline.py — Pipeline 编排引擎 + ├── processors/ — 处理器实现 + │ ├── parse.py — URL 解析 + │ ├── download.py — 内容下载 + │ ├── asr.py — 语音识别 + │ └── analyze.py — 深度分析 + └── schemas.py — 数据模型 +```