fix: 完成 doco src layout 重构,文件移至 src/doco/ 子目录
This commit is contained in:
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,11 @@
|
|||||||
|
**本文件是制片人刘通与 Claude(Opus 4.7 高级技术顾问)的协作原则,与项目宪法(.clinerules / project_plan.md / dev_plan.md / docs/git_workflow.md)并列。新对话接手时,请连同宪法一并阅读本文件。**
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
**Claude 与我交流、沟通、协作时需要注意的原则**
|
||||||
|
|
||||||
|
1. 全程使用简体中文。
|
||||||
|
2. 我不懂代码编程,给我的解释说明和理由要尽量简明扼要。不要堆叠大量技术语言,说人话。
|
||||||
|
3. 请参阅宪法文件中你(Claude)的定位:写具体 Plan 是 Cline 的事,不要架空 Cline 的 Plan 模式。除非特别必要(Cline 反复修改都过不去的坎)可以上手,以及制片人明确指定你可以操刀的具体工作。
|
||||||
|
4. 给 Cline 的指令要用代码块封装起来,方便复制。
|
||||||
|
5. 给我的回复要简明扼要,不要解释太多的中间过程和理由和分析,有不懂的我会问你。
|
||||||
@@ -14,6 +14,10 @@
|
|||||||
有沉淀、有权限、可检索的系统。核心价值 = 经验从"靠人"变"靠系统"。
|
有沉淀、有权限、可检索的系统。核心价值 = 经验从"靠人"变"靠系统"。
|
||||||
- 现有克制选择(不用 TS / 不用 Alembic / pgvector 不用独立向量库 /
|
- 现有克制选择(不用 TS / 不用 Alembic / pgvector 不用独立向量库 /
|
||||||
Session 不用 JWT)方向正确,保持。
|
Session 不用 JWT)方向正确,保持。
|
||||||
|
- ⚠️ 更新(2026-06-12):看板分析升级相关待办(原 F1-F8)已整体迁移到
|
||||||
|
**TPS 看板分析升级子项目**。主 project 这边不再维护这部分待办。
|
||||||
|
子项目状态见 `寄存条_看板升级已外迁.md`。
|
||||||
|
- doco 相关条目已外迁
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,364 @@
|
|||||||
|
# 主 project 答复 — 分钟收视回放子板块
|
||||||
|
|
||||||
|
> 版本:v1
|
||||||
|
> 日期:2026-06-11
|
||||||
|
> 作者:TPS 主 project 顾问 (Claude Opus 4.7) + 制片人 刘通
|
||||||
|
> 状态:已采纳,待秒级 chat 接收并按本文件推进实现
|
||||||
|
> 上一版:无
|
||||||
|
> 对应文档:秒级收视 project《军事科技_分钟收视回放_子板块需求规格.md》v1(2026-06-10)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、本文件用途
|
||||||
|
|
||||||
|
回复秒级 chat 那份 PRD 第八节的 6 个对接问题,并把主 project 这边的**红线、修订建议、交付物期待**全部白纸黑字写下来。本文件是子板块继续推进的**最终输入**,秒级 chat 这边可基于此开干。
|
||||||
|
|
||||||
|
子板块结束前,要按本文件第九节的清单产出**五份交付物**给主 project。主 project 这边的 Cline 拿着五份交付物落代码,完成最终整合。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、对 6 个对接问题的最终答复
|
||||||
|
|
||||||
|
### 1. TPS 工作台有没有"每期节目详情页"?
|
||||||
|
|
||||||
|
**没有。子板块需要附带把详情页骨架建起来。**
|
||||||
|
|
||||||
|
现状:仪表盘 (Dashboard) 是聚合视角,责编录入页 (EditorDesk) 是表单 + 列表,**没有"看单期 + 该期所有维度"的页面**。分钟收视回放需要这个容器,整个工作台早晚也需要这个页面,借这次一起做掉。
|
||||||
|
|
||||||
|
入口规划:
|
||||||
|
- 仪表盘柱图每根柱子点进去 → 详情页
|
||||||
|
- EditorDesk 列表行点进去 → 详情页
|
||||||
|
- 路由建议:`/episodes/:id`,`:id` 用 `episodes.id`(SERIAL 主键)
|
||||||
|
|
||||||
|
详情页骨架要预留位置承载未来其他维度(审片意见、文稿、外拍信息等),分钟收视回放是其中**第一个模块**。
|
||||||
|
|
||||||
|
### 2. 数据库技术栈
|
||||||
|
|
||||||
|
**PostgreSQL 16 + pgvector(1536 维)**,ORM 是 **SQLModel(同步,非 async)**。
|
||||||
|
|
||||||
|
手写 SQL 走 `backend/sql/00X_*.sql`,不用 Alembic。
|
||||||
|
|
||||||
|
第五节那两张表的接入方式见第四节"数据模型修改建议"——简短版:**别新建"节目期次表",复用现有 `episodes` 表**;分钟数据表新建,命名 `episode_minute_ratings`,外键挂到 `episodes.id`。
|
||||||
|
|
||||||
|
### 3. 视频和截图存储方案
|
||||||
|
|
||||||
|
**最终决策:视频不入工作台。**
|
||||||
|
|
||||||
|
- 视频本体由制片人在本地/百度网盘/极空间多渠道自存
|
||||||
|
- 工作台只接收**截图**(27 张 jpg)
|
||||||
|
- 不再讨论服务端 ffmpeg、视频压缩、转码删源片等服务端方案
|
||||||
|
|
||||||
|
截图处理走**本地切图工具**(子板块产出,详见第五节):
|
||||||
|
|
||||||
|
- 责编本地双击工具 → 拖入源片 → 自动切 27 张 480p 截图 + 命名好
|
||||||
|
- 责编打开工作台 → 一键多文件上传截图(~5 MB 一次传完)
|
||||||
|
|
||||||
|
截图存储:服务器文件系统 `/screenshots/{episode_id}/{分钟序号_两位数}.jpg`,数据库只存 URL。
|
||||||
|
|
||||||
|
### 4. 前端技术栈
|
||||||
|
|
||||||
|
**React 18 + Vite + Ant Design 5 + Zustand**,JavaScript(不用 TS),项目宪法锁定。
|
||||||
|
|
||||||
|
图表库选型:
|
||||||
|
|
||||||
|
- **优先 @ant-design/charts**:与现有 AntD 5 视觉血缘最近,配色和圆角自然贴合
|
||||||
|
- **次选 ECharts**:自定义 tooltip 模板灵活成熟
|
||||||
|
- **已用过 Recharts**:仪表盘柱图已采用
|
||||||
|
|
||||||
|
**不要再引第三方图表库**。三选一即可,最终选哪个由 Cline 在 Plan 阶段定。
|
||||||
|
|
||||||
|
### 5. 后台异步任务怎么跑
|
||||||
|
|
||||||
|
**在"视频不入工作台 + 本地切图工具"决策下,服务端没有重型异步任务。**
|
||||||
|
|
||||||
|
工作台后端只接收截图入库 + 跑数据校验(见第四节建议 E),都是毫秒级同步操作,**FastAPI BackgroundTasks 都用不上**。
|
||||||
|
|
||||||
|
如果未来某个新场景确实需要异步任务,再启用 FastAPI BackgroundTasks。**不引 Celery、不引 Redis 队列**——8 人栏目用这些是过度工程。
|
||||||
|
|
||||||
|
### 6. 录入身份/权限
|
||||||
|
|
||||||
|
**有完整用户系统**:Session + Cookie 认证,三角色拼音枚举锁定(`zhipianren` / `zebian` / `biandao`)。
|
||||||
|
|
||||||
|
写权限规则参照 `yearly_targets` 既有口径平移:
|
||||||
|
|
||||||
|
- **POST/PATCH/DELETE 录入分钟数据 + 上传截图**:`zhipianren` + `zebian` 可写,`biandao` 返回 403
|
||||||
|
- **GET 查看分钟回放**:三角色均可读
|
||||||
|
|
||||||
|
**实现细节**:FastAPI 后端直接从 session 拿 user_id 写入 `created_by` 字段,**前端不要把"录入人"作为字段提交**。
|
||||||
|
|
||||||
|
字段命名用 `created_by INTEGER REFERENCES users(id)`,**不要用 string 类型的"录入人姓名"**——主 project backlog 里有一条 "操作留痕 schema"(待办池 B2),分钟收视这张新表作为落地先例。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、视频/截图最终方案(决策落地)
|
||||||
|
|
||||||
|
### 责编一周一期的标准流程(最终版)
|
||||||
|
|
||||||
|
```
|
||||||
|
周二 21:20-21:47 节目播出
|
||||||
|
↓
|
||||||
|
周二 22:00 后 责编到总编室账号抄 27 个份额数字(保留原方案)
|
||||||
|
↓
|
||||||
|
次日 责编打开本地切图工具
|
||||||
|
↓
|
||||||
|
拖入当期源片 mp4 → 工具自动切 27 张 480p jpg
|
||||||
|
+ 自动命名为 01.jpg ~ 27.jpg
|
||||||
|
↓
|
||||||
|
责编登录工作台 → 进入"节目期次"管理
|
||||||
|
→ 选择当期 episode(基于已录入的 episodes 记录)
|
||||||
|
→ 进入分钟收视模块
|
||||||
|
↓
|
||||||
|
上传 27 张截图(多文件选择 / 拖拽)
|
||||||
|
→ 服务器存到 /screenshots/{episode_id}/
|
||||||
|
→ 数据库写入 27 条 episode_minute_ratings 记录
|
||||||
|
↓
|
||||||
|
录入 27 个份额数字
|
||||||
|
(推荐:"批量粘贴一列数字"输入框,
|
||||||
|
从 Excel 复制 27 个数字粘贴后系统按行切分)
|
||||||
|
→ 系统软校验(数据齐全?范围合理?均值与已录全期均值吻合?)
|
||||||
|
→ 保存
|
||||||
|
↓
|
||||||
|
该期详情页里"分钟收视回放"模块即刻可看
|
||||||
|
```
|
||||||
|
|
||||||
|
### 主 project 这边不做的事
|
||||||
|
|
||||||
|
- 服务端 ffmpeg(不需要)
|
||||||
|
- 视频上传接口(不需要)
|
||||||
|
- 视频压缩转码(不需要)
|
||||||
|
- 异步任务队列(不需要)
|
||||||
|
- 视频删除/清理脚本(不需要)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、数据模型修改建议(主 project 在此明确给出)
|
||||||
|
|
||||||
|
> 任何 schema 改动**必须经主 project 顾问 (Opus) 审、配回补方案,Cline 不得自行动手**。这是项目红线。下面是建议方案,最终落地前还会过一遍审查。
|
||||||
|
|
||||||
|
### 建议 A:复用现有 `episodes` 表,**不新建"节目期次表"**
|
||||||
|
|
||||||
|
现有 episodes 表已涵盖你需要的全部"节目期次"信息:
|
||||||
|
|
||||||
|
| 你的字段 | 对应现有 episodes 字段 |
|
||||||
|
|---|---|
|
||||||
|
| 期次主键 | `id`(SERIAL) |
|
||||||
|
| 期数显示 | 前端从 `air_date` + `episode_number` 拼,不入库 |
|
||||||
|
| 节目名称 | `program_name` |
|
||||||
|
| 播出日期 | `air_date` |
|
||||||
|
| 播出时段 | 不入库,前端常量 "21:20-21:47" |
|
||||||
|
| 备注 | `notes` |
|
||||||
|
|
||||||
|
理由:新建一张冗余表会割裂 episodes 与其他模块(收视成绩、外拍、未来选题、审片意见)的关联,破坏单一事实源。
|
||||||
|
|
||||||
|
### 建议 B:用 `episodes.id`(INTEGER)做外键,**不用"播出日期 string"做主键**
|
||||||
|
|
||||||
|
秒级 chat v1 文档建议"期次主键用 `2026-06-09` 字符串"。这与 `episodes.id SERIAL` 体系冲突。
|
||||||
|
|
||||||
|
最终方案:分钟数据表用 `episode_id INTEGER REFERENCES episodes(id)` 外键,所有展示字符串("2026 年第 23 期 · 2026-06-09")由前端从 episodes 数据拼出,不入库。
|
||||||
|
|
||||||
|
### 建议 C:`收视份额` 用 `NUMERIC(6,4)`,**不用 float**
|
||||||
|
|
||||||
|
与现有 `episodes.audience_share NUMERIC(6,4)` 类型对齐,避免浮点比较的怪事。
|
||||||
|
|
||||||
|
### 建议 D:新表 `episode_minute_ratings` 建议 schema
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE IF NOT EXISTS episode_minute_ratings (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
episode_id INTEGER NOT NULL REFERENCES episodes(id) ON DELETE CASCADE,
|
||||||
|
minute_index INTEGER NOT NULL CHECK (minute_index BETWEEN 1 AND 27),
|
||||||
|
audience_share NUMERIC(6,4) NOT NULL,
|
||||||
|
screenshot_url VARCHAR(500),
|
||||||
|
created_by INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
UNIQUE(episode_id, minute_index)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_minute_ratings_episode ON episode_minute_ratings (episode_id);
|
||||||
|
```
|
||||||
|
|
||||||
|
P1+ 扩展(多期对比、批注/标签):1.0 不建表,到 P1 触发时再说。当前 UNIQUE 复合键和外键设计已留好扩展空间。
|
||||||
|
|
||||||
|
### 建议 E:工作流补一个"软校验"环节
|
||||||
|
|
||||||
|
录入 27 个分钟份额时,系统应做**非阻塞**的合理性提示:
|
||||||
|
|
||||||
|
- 27 个数字是否齐?
|
||||||
|
- 最大值/最小值是否在合理区间(如 0-3)?
|
||||||
|
- 27 个数字的平均值是否与已录的 `episodes.audience_share`(该期全期均值)大致吻合?误差 > 30% 给"数据可能录错"提示
|
||||||
|
|
||||||
|
不阻塞保存,只是温柔提醒。理由:分钟数据是栏目考核依据,权重最高,录错一个小数点不发现就一直错。
|
||||||
|
|
||||||
|
### 建议 F:批量导入接口复用现有 ExcelService
|
||||||
|
|
||||||
|
23 期历史数据一次性导入:复用主 project 已有的 ExcelService 框架(Phase 2 Task 2 跑通),但单开一个 endpoint:
|
||||||
|
|
||||||
|
- 上传一份"期次 × 27 列分钟份额"的 Excel
|
||||||
|
- 按行展开成 23 × 27 = 621 条 `episode_minute_ratings` 入库
|
||||||
|
- 截图 URL 字段第一次导入时留空,后续走本地工具补传
|
||||||
|
|
||||||
|
### 建议 G:episodes 表是否要加视频 URL 字段?
|
||||||
|
|
||||||
|
**不加。**
|
||||||
|
|
||||||
|
因为视频不入工作台。如果未来某天想记录"这一期视频存在哪个网盘 / 哪个本地路径",可以走 `episodes.notes` 字段写自由文本,不需要专门字段。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、本地切图工具规格(子板块产出物之一)
|
||||||
|
|
||||||
|
子板块的 Claude 负责设计与实现这个工具。
|
||||||
|
|
||||||
|
### 5.1 形态
|
||||||
|
|
||||||
|
- 一个 Windows 上能跑的可执行文件(py 源码 + pyinstaller 打包成 exe)
|
||||||
|
- 双击即用,无安装步骤
|
||||||
|
- 不依赖网络,不依赖工作台,完全离线
|
||||||
|
- 不需要责编装 Python 环境
|
||||||
|
|
||||||
|
### 5.2 用户界面
|
||||||
|
|
||||||
|
简洁到极致:
|
||||||
|
|
||||||
|
- 一个窗口,拖文件进去即可(或"选择文件"按钮)
|
||||||
|
- 接收 mp4 / mov / mkv 等常见格式
|
||||||
|
- 进度条显示切图进度
|
||||||
|
- 完成后弹"已生成 27 张截图于 [输出文件夹]"
|
||||||
|
- 自动打开输出文件夹
|
||||||
|
|
||||||
|
### 5.3 切图规则(与秒级 chat v1 文档保持一致)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 27 张截图,每分钟第 30 秒位置,480p (854 × 480)
|
||||||
|
for i in $(seq 0 26); do
|
||||||
|
sec=$((i*60+30)) # 0:30, 1:30, 2:30, ..., 26:30
|
||||||
|
ffmpeg -i 源片.mp4 -ss $sec -vframes 1 -vf scale=854:480 \
|
||||||
|
"$(printf "%02d" $((i+1))).jpg" -y
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
输出文件名规则:**`01.jpg` ~ `27.jpg`**(两位数,零填充,便于排序)。
|
||||||
|
|
||||||
|
### 5.4 输出文件夹组织
|
||||||
|
|
||||||
|
工具自动新建一个文件夹,命名建议:`截图_{源片文件名去后缀}_{日期}/`,里面 27 张 jpg。
|
||||||
|
|
||||||
|
### 5.5 ffmpeg 依赖
|
||||||
|
|
||||||
|
打包时把 ffmpeg.exe 一并塞进 exe,或者用 `imageio-ffmpeg` 包自动下载。**绝对不要让责编手动装 ffmpeg**。
|
||||||
|
|
||||||
|
### 5.6 错误处理
|
||||||
|
|
||||||
|
- 源片读不到 → 弹窗"文件无法读取,请检查格式"
|
||||||
|
- 源片时长 < 26 分 30 秒 → 弹窗"视频时长不足 27 分钟,是否继续?"(允许跳过缺失分钟)
|
||||||
|
- 输出文件夹已存在 → 自动加时间戳后缀
|
||||||
|
|
||||||
|
### 5.7 给责编的使用说明
|
||||||
|
|
||||||
|
子板块产出一份 `使用说明.md`,傻瓜级,要有截图。预期长度 200-400 字 + 3-5 张截图。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、主 project 红线(不可越)
|
||||||
|
|
||||||
|
子板块设计与实现过程中,下面这几条是**主 project 宪法**,任何方案不得违反:
|
||||||
|
|
||||||
|
1. **改 schema 须主 project 顾问 (Opus) 审**:包括新建表、改字段、加字段。Cline / 子板块 Claude 不得自行动手。
|
||||||
|
2. **角色枚举锁定拼音值**:`zhipianren` / `zebian` / `biandao`,不许新增枚举,不许用英文别名。
|
||||||
|
3. **AI 给方向不给答案**:分钟收视回放的 P1+ 功能(多期对比找规律、批注 AI 建议等)若涉及 AI,必须保持"建议草稿 + 制片人审核"的三档置信度,不得 AI 直接拍板。
|
||||||
|
4. **编导关联用"软引用 + 快照"**:本子板块如需展示编导信息,沿用 `episodes.editor_id` + `episodes.editor_name_snapshot` 双字段,不许新增编导关联字段。
|
||||||
|
5. **收视颜色判定**:红=优秀(>摸高目标)/ 蓝=达标 / 绿=待提升(<基础目标)。反直觉规约,分钟收视回放折线图如果上色,按此规则。
|
||||||
|
6. **AI 输出必须有"忽略 / 我来改写"否决权**:任何 AI 建议(如本子板块 P1+ 的 AI 找规律功能)必须给编导否决入口。
|
||||||
|
7. **不引新依赖**:图表库三选一(@ant-design/charts / ECharts / Recharts),不引第四个;后端不引 Celery / Redis 队列。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、子板块产出物清单(最终交付包)
|
||||||
|
|
||||||
|
子板块结束前,请凝结成以下**五份交付物**,作为整体交付给主 project:
|
||||||
|
|
||||||
|
### 产物 1:决策摘要 md
|
||||||
|
|
||||||
|
记录子板块全程的关键决策。每条决策三句话:
|
||||||
|
|
||||||
|
```
|
||||||
|
决策 X:[一句话决策内容]
|
||||||
|
- 背景:为什么需要这个决策
|
||||||
|
- 拍板理由:选这条不选那条的理由
|
||||||
|
- 拍板人:[制片人 / 主 project 顾问 / 子 project Claude 建议+制片人采纳]
|
||||||
|
```
|
||||||
|
|
||||||
|
10-20 条决策足以讲清整个子板块"为什么这么做"。
|
||||||
|
|
||||||
|
### 产物 2:接口约定 md(最技术、最精确)
|
||||||
|
|
||||||
|
把子板块与主 project 接驳的所有"接口"白纸黑字写出来:
|
||||||
|
|
||||||
|
- **数据接口**:新建表 / 字段 / 类型 / 约束(细化到 SQL DDL 级别)
|
||||||
|
- **API 接口**:新增 endpoint URL / 方法 / 请求体 / 响应体 / 错误码
|
||||||
|
- **UI 接口**:在主 project 哪个页面挂载、入口、路由
|
||||||
|
- **权限接口**:哪些角色可以做什么操作
|
||||||
|
- **存储接口**:截图存到哪个目录、命名规则、URL 拼接规则
|
||||||
|
|
||||||
|
要具体到"主 project 的 Cline 拿着这份就能写代码"的程度。**这是子 project 给主 project 的"合同"**。
|
||||||
|
|
||||||
|
### 产物 3:本地切图工具完整包
|
||||||
|
|
||||||
|
- `screenshot_tool.py`:源码,注释齐全
|
||||||
|
- `screenshot_tool.exe`:打包好的可执行文件,责编双击即用
|
||||||
|
- `使用说明.md`:傻瓜级文档 + 截图
|
||||||
|
|
||||||
|
工具规格见本文件第五节。
|
||||||
|
|
||||||
|
### 产物 4:未尽事项 backlog
|
||||||
|
|
||||||
|
诚实写出"子板块讨论中提到但没做的事"。每条三行:
|
||||||
|
|
||||||
|
- 是什么
|
||||||
|
- 为什么没做(暂缓 / P1+ / 等条件成熟)
|
||||||
|
- 触发时机(什么时候应该捡起来)
|
||||||
|
|
||||||
|
放进主 project 的 backlog 池子里。
|
||||||
|
|
||||||
|
### 产物 5:给主 project Claude 的"接手提示词"
|
||||||
|
|
||||||
|
一两段话,告诉主 project 顾问"如果你是接手这件事的 Claude,最重要的三件事是 X、Y、Z"。
|
||||||
|
|
||||||
|
这次至少要包含:
|
||||||
|
- 复用 episodes 表,不新建节目期次表
|
||||||
|
- 权限沿用 yearly_targets 口径
|
||||||
|
- 本地切图工具与工作台零耦合,不在工作台 UI 里给它留接口
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、跨 project 协作规矩(子板块这边也要遵守)
|
||||||
|
|
||||||
|
1. **不动主 project 代码**:子板块产出文档 + 独立工具,不写主 project 的实际代码。代码合入由主 project 的 Cline 完成。
|
||||||
|
2. **遇到吃不准的事回主 project 问**:本次 v1 文档第八节就是好榜样,继续保持。
|
||||||
|
3. **每份跨 project 文档顶部带元信息块**:版本、日期、作者、状态、上一版、主要变化(v2 以上必填)。
|
||||||
|
4. **一份文档只谈一件事**:不要在分钟收视回放交付包里夹带其他议题。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、给秒级 chat Claude 的明确动作清单
|
||||||
|
|
||||||
|
收到本文件后,请按下面顺序推进:
|
||||||
|
|
||||||
|
1. **吸收本文件所有决策与红线**,回到秒级 chat 的 PRD v1,把不一致处标注出来(如果有)
|
||||||
|
2. **如有需要修订的地方,出 PRD v2**,顶部元信息块写明跟 v1 的变化点
|
||||||
|
3. **设计本地切图工具**:与制片人讨论用户体验细节,定稿后凭工具规格让秒级 chat 的 Cline 实现(如果有)或制片人自己找 v0/Lovable 等工具生成 demo
|
||||||
|
4. **凝结成最终五份交付物**(第七节清单)
|
||||||
|
5. **交付给制片人**,由制片人带回主 project,主 project 顾问 (Opus) 审一遍,无冲突后主 project 的 Cline 落实施
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、附:版本演进规约
|
||||||
|
|
||||||
|
本文件未来如修订(v2+),顶部元信息块"主要变化"必须写清楚改了什么。
|
||||||
|
|
||||||
|
历史版本不覆盖,旧文件保留在 `docs/cross_project/` 目录(主 project 这边)以便回看决策史。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*本文件由主 project 顾问 (Claude Opus 4.7) 于 2026-06-11 基于与制片人刘通的两轮对话整理生成,供秒级收视项目接收使用。*
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
# 子项目立项备忘 — 分钟收视回放
|
||||||
|
|
||||||
|
> 文档类型:子项目立项备忘
|
||||||
|
> 子项目名称:分钟收视回放
|
||||||
|
> 立项日期:2026-06-11
|
||||||
|
> 子项目所在:秒级收视 project(Claude.ai 网页版的另一个 project)
|
||||||
|
> 当前状态:**推进中**(设计已收敛,进入子板块内部实现阶段)
|
||||||
|
> 主 project 联系人:制片人刘通 + Claude Opus 4.7 顾问
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、文档用途
|
||||||
|
|
||||||
|
未来主 project 这边新开 chat 时(必然会发生 Claude 失忆),新 Claude 通过此文件快速恢复"分钟收视回放子项目"的上下文。**它不重复 v1 答复 md 里的细节,只留指针 + 关键决策摘要**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、立项缘由
|
||||||
|
|
||||||
|
制片人在另一个 project(秒级收视)里讨论分钟收视数据怎么进工作台、怎么呈现。那边 Claude 写了一份 PRD(需求规格 v1, 2026-06-10),向主 project 这边提了 6 个对接问题。
|
||||||
|
|
||||||
|
主 project 这边讨论两轮后采纳"以子项目模式独立推进",并把答复凝结成正式 md 带回子项目。**这次是项目里第一次完整使用"子项目模式"**——既是分钟收视回放本身的立项,也是这套跨 project 协作工作流的首次实操。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、关键决策摘要(已采纳,不要重复讨论)
|
||||||
|
|
||||||
|
1. **视频不入工作台**:制片人多渠道自存(极空间/百度网盘/本地),工作台只接收截图
|
||||||
|
2. **本地切图工具**:子板块产出,py + exe + 使用说明,与工作台零耦合
|
||||||
|
3. **复用现有 episodes 表**:不新建"节目期次表",分钟数据表 `episode_minute_ratings` 外键挂到 `episodes.id`
|
||||||
|
4. **录入人字段用 `created_by INTEGER REFERENCES users(id)`**:不用 string,顺手落地 backlog B2 操作留痕
|
||||||
|
5. **后端不上 Celery/Redis**:异步任务在视频不入库后基本消失,必要时用 FastAPI BackgroundTasks
|
||||||
|
6. **图表库三选一**:@ant-design/charts / ECharts / Recharts,不引第四个,最终由 Cline Plan 阶段定
|
||||||
|
7. **详情页 `/episodes/:id` 骨架由本子板块附带建起来**:早晚要做,借这次一起
|
||||||
|
8. **权限沿用 yearly_targets 口径**:zhipianren + zebian 可写,biandao 只读
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、子板块要交付什么(五份产物)
|
||||||
|
|
||||||
|
子项目结束时,那边凝结以下交付包带回主 project:
|
||||||
|
|
||||||
|
1. 决策摘要 md
|
||||||
|
2. 接口约定 md(含 SQL DDL、API endpoint、UI 接入点、权限规则、存储路径规则)
|
||||||
|
3. 本地切图工具完整包(py 源码 + exe + 使用说明)
|
||||||
|
4. 未尽事项 backlog
|
||||||
|
5. 给主 project Claude 顾问的"接手提示词"
|
||||||
|
|
||||||
|
详见《分钟收视回放_主project答复_v1.md》第七节。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、主 project 要做的事
|
||||||
|
|
||||||
|
**现在(推进期)**:不做事,不接收过程文档,等收交付包。
|
||||||
|
|
||||||
|
**收到交付包后**:
|
||||||
|
|
||||||
|
1. 主 project 顾问 (Opus) 审一遍,看跟主项目红线有没有冲突
|
||||||
|
2. 无冲突 → 主 project workspace 里让 Cline 落代码
|
||||||
|
3. 有冲突 → 标出冲突点,回子项目修,循环
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、相关文档(指针)
|
||||||
|
|
||||||
|
**外部输入**(子项目发来的):
|
||||||
|
|
||||||
|
- 秒级 chat 的 PRD v1:《军事科技_分钟收视回放_子板块需求规格.md》(2026-06-10)
|
||||||
|
- 已在主 project files 中(制片人 2026-06-11 上传)
|
||||||
|
|
||||||
|
**主 project 输出**(咱们这边给子项目的):
|
||||||
|
|
||||||
|
- 《分钟收视回放_主project答复_v1.md》(2026-06-11)
|
||||||
|
- 建议归档位置:`docs/cross_project/分钟收视回放/分钟收视回放_主project答复_v1.md`
|
||||||
|
|
||||||
|
**配套文档**:
|
||||||
|
|
||||||
|
- 《跨project协作提示单_v1.md》(2026-06-11,制片人随身保存)
|
||||||
|
- 不在主 project 仓库内,是制片人个人工作流手册
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、预计回归时间
|
||||||
|
|
||||||
|
未明确锁定。子项目那边的 Claude 表示"没有什么不清楚的了",已在内部推进。
|
||||||
|
|
||||||
|
**触发主 project 这边介入的信号**:
|
||||||
|
|
||||||
|
- 子项目带交付包过来(正常路径)
|
||||||
|
- 子项目过程中遇到吃不准的事 → 单点咨询主 project 顾问(不要整份过程稿上传)
|
||||||
|
- 超过 4 周还没收敛 → 主动 ping 一下,看是不是要重新切分
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、给未来失忆接手 Claude 的提示
|
||||||
|
|
||||||
|
如果你是几周后接手主 project 的 Claude,看到这份备忘,请记住:
|
||||||
|
|
||||||
|
1. **分钟收视回放是一个独立推进的子项目**,主 project 不掺合其内部讨论
|
||||||
|
2. **复用 episodes 表,不要新建节目期次表**——这是已经定死的决策,不重新讨论
|
||||||
|
3. **改 schema 必须经 Opus 顾问审**,子项目交付包带 schema 修改建议时严守这条
|
||||||
|
4. **本地切图工具与工作台零耦合**,工作台 UI 里不要给它留接口
|
||||||
|
5. **视频不入工作台**——任何提议加视频上传接口的方案都已被否决
|
||||||
|
6. **审查交付包是必经环节**,发现子项目设计违反主项目红线(如角色枚举、收视颜色判定)时直接打回
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、版本演进
|
||||||
|
|
||||||
|
本文件未来如需更新(v2+):
|
||||||
|
|
||||||
|
- 子项目交付包接收后:更新"当前状态"为"已交付,整合中"
|
||||||
|
- Cline 实施完成后:更新"当前状态"为"已完成",加一节"实施回顾"
|
||||||
|
- 实施过程中如有重大决策变更:v2 顶部"主要变化"写明
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*本立项备忘由主 project 顾问 (Claude Opus 4.7) 于 2026-06-11 制片人立项动作后随手生成。轻量、精简,未来失忆接手时由此恢复上下文。*
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# 寄存条:看板升级已外迁
|
||||||
|
|
||||||
|
> 留在主 project,让未来的 Claude 一眼知道:看板分析升级已经拉出去单独立项了。
|
||||||
|
> 外迁时间:2026-06-12
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 外迁了什么
|
||||||
|
|
||||||
|
**TPS 看板分析升级**整体作为子项目,搬到独立 Claude project。
|
||||||
|
|
||||||
|
子项目聚焦:三层信息架构、双引擎象限图、AI 打标流水线、编导能力地图、本期诊断小结、看板 UI 设计。
|
||||||
|
|
||||||
|
子项目持有的核心资产:主项目签发的 Brief + 三份续接快照 + ground-truth 基准集 + 23 期文稿等。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 主 project 不再讨论的话题
|
||||||
|
|
||||||
|
聊到下面这些词,**先问一句"这是子项目的事还是主 project 的事?"**——是子项目的事,提醒制片人切到子项目 chat。
|
||||||
|
|
||||||
|
关键词:看板升级 / 双引擎象限图 / 题材热度 / 叙事结构(作为字段)/ AI 打标 / Prompt 1/2/3 / ground-truth / episodes 加字段 / 23 期回填 / 能力地图 / 置信度三档 / 本期诊断小结
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 主 project 仍在管什么
|
||||||
|
|
||||||
|
- Phase 0-3 已落地的主干代码(episodes、editors、收视诊断基础)
|
||||||
|
- backend 全部 schema、API、迁移脚本
|
||||||
|
- 前端全部 React 代码实施
|
||||||
|
- 主干 Bug、性能优化、新需求(看板升级以外的)
|
||||||
|
- Cline 的全部 Plan + Act 操作
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 接收子项目交付物的接口
|
||||||
|
|
||||||
|
子项目交付物的具体接口约定,见**子项目主 Brief §六**(交付什么)。简要回顾:
|
||||||
|
|
||||||
|
- **Schema 变更**:子项目出字段定义文档 → 主 project Cline 切 Plan + Opus 审 + 制片人批准 Act → `pg_dump` 备份 → 跑迁移
|
||||||
|
- **前端实施**:子项目出设计 token + HTML mock + 视觉规范 → 主 project Cline 落 React
|
||||||
|
- **AI 打标**:沙盒 `ai-labeling/` 由子项目自治,主 project 不碰
|
||||||
|
- **回填**:子项目出脚本设计 → 主 project 跑 + 制片人审 staging
|
||||||
|
|
||||||
|
**纪律**:
|
||||||
|
- 只接稳定版,草稿不实施
|
||||||
|
- 实施前 `pg_dump` 备份
|
||||||
|
- 实施完成后回访子项目登记状态
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 开局口径
|
||||||
|
|
||||||
|
进主 project 新 chat:
|
||||||
|
> "续接 TPS 主项目。读 `寄存条_看板升级已外迁.md`。当前要做 [具体任务]。"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 万一子项目记录丢了
|
||||||
|
|
||||||
|
降级方案:
|
||||||
|
1. 主 project 这边还保留资产副本(xlsx + 11 份 docx + 部分 UI 参考图)
|
||||||
|
2. 决策史在 Gitea 有 git 历史(关键 commit `38f3728` 等)
|
||||||
|
3. 制片人本地应有副本
|
||||||
|
4. **主 project 这边不要凭记忆重建子项目内容**——找制片人或重建子项目
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# 看板升级子项目 — 入口
|
||||||
|
|
||||||
|
> 这是 TPS 主 project 拆出来的子项目,聚焦"看板分析升级"。
|
||||||
|
> 立项时间:2026-06-12
|
||||||
|
> 顾问:Claude Opus 4.7 | 制片人:刘通
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 开局必读(顺序)
|
||||||
|
|
||||||
|
1. `看板升级子项目_Brief.md` — 主项目签发的"交接宪法"(红线、技术栈、出入口接口)。**不在子项目内修改。**
|
||||||
|
2. `续接快照_看板分析升级_设计讨论_v4.md` — 最新决策史(往前可回溯 v3 / v1)
|
||||||
|
3. 上面两份读完,就有完整上下文了
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 已有资产
|
||||||
|
|
||||||
|
**决策史**:
|
||||||
|
- 续接快照 v1 / v3 / v4 — 整个看板升级讨论的完整记录
|
||||||
|
|
||||||
|
**数据基础**:
|
||||||
|
- `军事科技栏目收视诊断分析_v2.xlsx` — 双引擎模型源数据(主项目也留一份)
|
||||||
|
- 11 份节目文稿 `.docx` — AI 打标基准集源稿(主项目也留一份)
|
||||||
|
|
||||||
|
**UI 参考**:
|
||||||
|
- `dashiboard首页原版.jpg` — 首屏改造起点(主项目也留一份)
|
||||||
|
- `dashiboard首页_拷贝.jpg` — 制片人批注稿
|
||||||
|
- `色调字体倒角.webp` — 整体视觉资产(主项目也留一份)
|
||||||
|
- `简洁风_清晰.jpg` — DataEase 风格参考
|
||||||
|
|
||||||
|
**协作纪律**:
|
||||||
|
- `Claude协作原则.md` — 与主项目同源,沿用
|
||||||
|
|
||||||
|
**沙盒**:
|
||||||
|
- `ai-labeling/` 工作区(物理上仍在 `E:\tps-dashboard\ai-labeling\`)
|
||||||
|
- Prompt 2 v0.2 已锁,MiniMax M3 选定,ground-truth v0.2.1 锁定
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 子项目自由度
|
||||||
|
|
||||||
|
读完 Brief 你会注意到 §八"未决项"——那是子项目可自由发挥的部分。
|
||||||
|
Brief 里没明确禁止、没在续接快照里拍板的事,都是讨论空间。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 新 chat 开局第一句
|
||||||
|
|
||||||
|
> "续接 TPS 看板分析升级子项目。先读主 Brief 和续接快照 v4。本 project 是设计+PRD 产出,不动主 project 的 backend 代码。当前推进到 [具体任务]。"
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
# 看板升级子项目 Brief
|
||||||
|
|
||||||
|
> 主项目 → 子项目的"交接宪法":红线、技术栈、出入口接口
|
||||||
|
> 起草日期:2026-06-12
|
||||||
|
> 状态:子项目立项时由主项目顾问(Opus)签发,子项目内部不修改
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、为什么做
|
||||||
|
|
||||||
|
**痛点**:制片人和编导团队拿到的"收视成绩单"只能看到结果(均值、走势、单期高低),
|
||||||
|
看不到结构性原因。每次复盘要靠人工拼诊断(21 期那次花了若干周),无法持续。
|
||||||
|
|
||||||
|
**升级目标**:把仪表盘从"看成绩"升级为"能分析"——
|
||||||
|
让"双引擎模型(题材热度 × 叙事结构)"这个一次性人工产出的分析框架,
|
||||||
|
变成一台**持续运转的诊断仪**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、做什么(功能边界,只列名)
|
||||||
|
|
||||||
|
| 模块 | 简述 |
|
||||||
|
|---|---|
|
||||||
|
| 三层信息架构 | 纯算 / 打标后 / AI 起草,分层呈现 |
|
||||||
|
| 双引擎象限图 | 招牌视觉,题材热度 × 叙事结构 |
|
||||||
|
| AI 打标流水线 | Prompt 1/2/3 + MiniMax M3 + ground-truth |
|
||||||
|
| 编导能力地图 | 反排名,正反馈 |
|
||||||
|
| 本期诊断小结 | AI 起草 + 制片人审改后发布 |
|
||||||
|
| 时间选择器 | 实时脉搏 vs 周期复盘,边界永远可调 |
|
||||||
|
|
||||||
|
**具体怎么做,子项目内部讨论,本 Brief 不预设方案。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、怎么用(目标流程)
|
||||||
|
|
||||||
|
- **每周**:制片人看"实时脉搏"——核心指标卡 + 近 9 期走势
|
||||||
|
- **每月**:制片人看"题材分析"——题材汇总,关注异动
|
||||||
|
- **每季**:制片人看"双引擎象限图 + 本期诊断小结"——周期复盘
|
||||||
|
- **新节目入库**:AI 打标草稿 → staging 表 → 制片人审 → 落库
|
||||||
|
- **编导维度**:制片人查能力地图,把强项做成全组可复用模板
|
||||||
|
- **离职编导**:历史保留,面向当下视图可筛掉
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、不做什么(红线)
|
||||||
|
|
||||||
|
子项目设计任何方案,**绝不**触碰以下:
|
||||||
|
|
||||||
|
- ❌ **不做深色大屏**(留给 2.0 数据大屏蓝本)
|
||||||
|
- ❌ **不做编导排名**(团队视角走能力地图)
|
||||||
|
- ❌ **AI 不自动盖章下结论**(永远是"AI 出草稿,人拍板")
|
||||||
|
- ❌ **不引入新图表库**(继续 ECharts / @ant-design/charts)
|
||||||
|
- ❌ **不引入主 project 没有的技术栈**
|
||||||
|
- ❌ **不动主 project 已有的 schema**(改字段必须走 §六交付协议)
|
||||||
|
- ❌ **不做"未审字段直接上看板"**(置信度三档必须可辨)
|
||||||
|
- ❌ **不写 / 不改 AI 打标 Prompt 由 Cline 完成**(Cline 是执行者不是作者)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、技术栈约束(继承主 project)
|
||||||
|
|
||||||
|
子项目所有设计必须能落在以下栈上,不引入新依赖:
|
||||||
|
|
||||||
|
- **前端**:React 18 + Vite + AntD 5 + Zustand + ECharts / @ant-design/charts
|
||||||
|
- **后端**:FastAPI + SQLModel + PG 16 + pgvector
|
||||||
|
- **配色**:米色底 `#fbf9f1` + 深绿主色 `#6b8e6b`
|
||||||
|
- **三色色板**:红 `#c0584f` / 蓝 `#5b8db8` / 绿 `#7aa874`
|
||||||
|
- **基准线**:基础线 0.6448 / 摸高线 0.8989(2026)
|
||||||
|
- **AI 打标**:沙盒 `ai-labeling/`,生产模型 MiniMax M3,openai==1.55.0 锁版本
|
||||||
|
- **部署**:腾讯云 4 核 8G(性能上限,凡是吃不动的方案直接否决)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、交付什么(出口接口)
|
||||||
|
|
||||||
|
子项目产出最终要回到主 project 实施,**交付物必须满足以下接口**:
|
||||||
|
|
||||||
|
### 6.1 Schema 变更类
|
||||||
|
- 子项目出:**字段定义文档**(命名 / 类型 / 枚举 / nullable / 约束 / 回滚方案)
|
||||||
|
- 主 project 实施:**Cline 切 Plan → Opus 审 → 制片人批准 Act → `pg_dump` 备份 → 跑迁移**
|
||||||
|
- 不接受:子项目自己改主 project schema 或 `backend/` 任何代码
|
||||||
|
|
||||||
|
### 6.2 前端实施类
|
||||||
|
- 子项目出:**设计 token JSON + HTML mock + 视觉规范文档**
|
||||||
|
- 主 project 实施:**Cline 按设计稿落 React 组件**
|
||||||
|
- 不接受:子项目自己写主 project 的 React 代码
|
||||||
|
|
||||||
|
### 6.3 AI 打标类
|
||||||
|
- 子项目在 `ai-labeling/` 沙盒自治,**沙盒内 Cline 可直接 Act**
|
||||||
|
- 子项目出:**Prompt 文件 + ground-truth.json + 模型选型结论**
|
||||||
|
- 主 project 实施:**episodes_staging 表 schema 落库 + 审稿 UI 落地**
|
||||||
|
|
||||||
|
### 6.4 回填类
|
||||||
|
- 子项目出:**回填脚本设计文档 + 23 期回填策略**
|
||||||
|
- 主 project 实施:**Cline 跑脚本 + 制片人审 staging**
|
||||||
|
|
||||||
|
### 6.5 通用约束
|
||||||
|
- 子项目**不主动 push** 文件到主 project,**所有交付物由制片人决定时机**
|
||||||
|
- 主 project 只接**稳定版**,子项目内部草稿不交付
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、入口接口(子项目要知道的主 project 现状)
|
||||||
|
|
||||||
|
- **Phase 0-3 已落地**:episodes / editors / 收视诊断基础数据,23 期 2026 年数据已入库
|
||||||
|
- **现有视觉语言**:米色 + 深绿,卡片圆角 12px,AntD 5 默认行高
|
||||||
|
- **现有 backlog**:主 project 这边的 backlog 已标注"看板升级条目已外迁"
|
||||||
|
- **现有沙盒**:`ai-labeling/` 工作区已搭建,Prompt 2 v0.2 已锁,MiniMax M3 已选定
|
||||||
|
- **现有 git**:Gitea 落库,关键 commit `38f3728`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、未决项(归子项目自己拍板)
|
||||||
|
|
||||||
|
以下不在本 Brief 内预设,**由子项目和制片人讨论决定**:
|
||||||
|
|
||||||
|
- 横轴量化方法的具体公式
|
||||||
|
- AI 打标 Prompt 1 / Prompt 3 的具体写法
|
||||||
|
- 看板各屏幕的具体布局和交互
|
||||||
|
- 双引擎象限图的具体视觉细节
|
||||||
|
- 能力地图的具体可视化方案
|
||||||
|
- episodes 新字段的最终命名 / 类型 / 是否多对多关联表
|
||||||
|
- 置信度是单字段还是分字段
|
||||||
|
- 时间窗口取多大 / 小样本怎么兜底等具体口径
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、决策史指向(不重复内容)
|
||||||
|
|
||||||
|
子项目讨论前应该读的:
|
||||||
|
- `续接快照_看板分析升级_设计讨论.md`(v1,2026-06-09)
|
||||||
|
- `续接快照_看板分析升级_设计讨论_v3.md`(v3,2026-06-11 上午)
|
||||||
|
- `续接快照_看板分析升级_设计讨论_v4.md`(v4,2026-06-11 晚)
|
||||||
|
- `军事科技栏目收视诊断分析_v2.xlsx`(双引擎模型源数据)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、本 Brief 自身的修订规则
|
||||||
|
|
||||||
|
- 本 Brief 不在子项目内修改
|
||||||
|
- 红线 / 技术栈如有变更,**主 project 这边发新版**,通过寄存条同步
|
||||||
|
- 子项目可在自己的 chat 里讨论"建议主 project 调整某条红线",但调整动作只能在主 project 发生
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
# 迁移清单 — 主 project 操作指南
|
||||||
|
|
||||||
|
> 用途:看板升级子项目立项时,主 project 这边的文件操作清单
|
||||||
|
> 操作完即可丢弃
|
||||||
|
> 制定时间:2026-06-12
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 资产分两类处理
|
||||||
|
|
||||||
|
### 🔵 子项目独有(主 project 这边删)
|
||||||
|
|
||||||
|
纯决策记录性质,主 project 不再需要:
|
||||||
|
|
||||||
|
1. `续接快照_看板分析升级_设计讨论.md`(v1)
|
||||||
|
2. `续接快照_看板分析升级_设计讨论_v3.md`
|
||||||
|
3. `续接快照_看板分析升级_设计讨论_v4.md`
|
||||||
|
4. `dashiboard首页_拷贝.jpg`(批注稿)
|
||||||
|
5. `简洁风_清晰.jpg`(参考图)
|
||||||
|
|
||||||
|
### 🟢 两边都留(各保留一份)
|
||||||
|
|
||||||
|
资产类性质,主 project 将来也可能用得到:
|
||||||
|
|
||||||
|
1. `军事科技栏目收视诊断分析_v2.xlsx` — 数据基础
|
||||||
|
2. 11 份节目文稿 `.docx`(硅基大脑、潜艇仿生 等) — 节目原始资料
|
||||||
|
3. `dashiboard首页原版.jpg` — 主 project 实施 React 时要看
|
||||||
|
4. `色调字体倒角.webp` — 整体视觉资产
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 主 project 这边的其他动作
|
||||||
|
|
||||||
|
### 新增
|
||||||
|
|
||||||
|
- 上传 `寄存条_看板升级已外迁.md`
|
||||||
|
|
||||||
|
### 更新
|
||||||
|
|
||||||
|
- `backlog_md_TPS_工作台待办池_不丢视野_非排期_.md` 顶部加一段:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
> ⚠️ 更新(2026-06-12):看板分析升级相关待办(原 F1-F8)已整体迁移到
|
||||||
|
> **TPS 看板分析升级子项目**。主 project 这边不再维护这部分待办。
|
||||||
|
> 子项目状态见 `寄存条_看板升级已外迁.md`。
|
||||||
|
```
|
||||||
|
|
||||||
|
### 保留(不动)
|
||||||
|
|
||||||
|
主干文档(README、Claude协作原则、phase 日志、doco 系列、git_workflow、_clinerules、_gitignore、001_init.sql、dev_plan、project_plan、Phase 3 续接快照系列)全部保留。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 操作步骤
|
||||||
|
|
||||||
|
**Step 1 ─ 建子项目**
|
||||||
|
1. 新建 Claude project,名为 `TPS看板分析升级`
|
||||||
|
2. 上传 4 份新文件:`INDEX.md` + `看板升级子项目_Brief.md` + 拷贝一份 `Claude协作原则.md`
|
||||||
|
3. 上传 🔵 5 份子项目独有的文件
|
||||||
|
4. 上传 🟢 14 份资产文件(主 project 也保留同名副本)
|
||||||
|
|
||||||
|
**Step 2 ─ 清主 project + 寄存**
|
||||||
|
5. 删除 🔵 5 份文件
|
||||||
|
6. 上传 `寄存条_看板升级已外迁.md`
|
||||||
|
7. 更新 `backlog` 顶部标注
|
||||||
|
|
||||||
|
**Step 3 ─ 验证**
|
||||||
|
8. 进主 project 新 chat:"读寄存条" → 看 Claude 是否懂"这部分外迁了,不在我这里讨论"
|
||||||
|
9. 进子项目新 chat:按 INDEX 开局口径 → 看 Claude 是否能正确进入顾问角色
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 操作后的拓扑
|
||||||
|
|
||||||
|
```
|
||||||
|
TPS 主 project TPS 看板升级子项目
|
||||||
|
───────────────────── ─────────────────────
|
||||||
|
├─ 主干文档(README/协作原则/phase 等) ├─ INDEX.md ★
|
||||||
|
├─ doco/migration/git/init/dev/plan ├─ 看板升级子项目_Brief.md ★
|
||||||
|
├─ Phase 3 续接快照系列 ├─ Claude协作原则.md(拷贝)
|
||||||
|
├─ backlog(顶部加标注) ├─ 续接快照 v1/v3/v4
|
||||||
|
├─ 寄存条_看板升级已外迁.md ★ ├─ xlsx + 11 份 docx(副本)
|
||||||
|
├─ xlsx + 11 份 docx(副本) ├─ dashboard 首页原版(副本)
|
||||||
|
├─ dashboard 首页原版(副本) ├─ 色调字体倒角(副本)
|
||||||
|
└─ 色调字体倒角(副本) ├─ dashboard 首页_拷贝.jpg
|
||||||
|
└─ 简洁风_清晰.jpg
|
||||||
|
```
|
||||||
|
|
||||||
|
★ = 新增
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 拿不准的就先不动
|
||||||
|
|
||||||
|
任何一份文件去留拿不准的,**先保留**。文件保留比误删容易处理。
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
# F3 横轴量化方法 PRD v1.0
|
||||||
|
|
||||||
|
> 子项目交付物 · 看板分析升级
|
||||||
|
> 状态:**v1.0 已锁**(2026-06-12 通哥审过 §2/§3/§4 决策)
|
||||||
|
> 起草时间:2026-06-12
|
||||||
|
> 顾问:Claude Opus 4.7 | 制片人:刘通
|
||||||
|
> 类型:薄 PRD(只解 v2 之后留下的开放点,已锁部分仅引用)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §1 引用已锁结论(不重述)
|
||||||
|
|
||||||
|
本 PRD 是对已有结论的**补丁/收敛**,不替换。已锁部分直接参见以下来源:
|
||||||
|
|
||||||
|
| 来源 | 已锁内容 |
|
||||||
|
|---|---|
|
||||||
|
| 续接快照 v2 §3 | 横轴公式 `X = 该题材在分析窗口内的均值份额 − 栏目均值份额`,零点 = 栏目均值,单位 = 收视份额绝对差 |
|
||||||
|
| 续接快照 v2 §4 | 双引擎象限图视觉规格:气泡大小 = 收视份额、气泡颜色 = 收视判定三色、气泡边框 = 开篇钩子三档、重叠用 jitter 解 |
|
||||||
|
| 主 project Claude 示意图(2026-06-10) | 23 期实际数据 + 模拟纵轴/钩子已可视化,制片人认可"不挤、不堆叠" |
|
||||||
|
| 续接快照 v3 §1.1 / v4 §3 | 纵轴从 3 档收为 2 档(主线演进 / 并列结构),Prompt 2 v0.2 + ground-truth v0.2.1 M3 100% 锁定 |
|
||||||
|
| 续接快照 v2 §2 字段二 | `equipment_domain` 多选 9 类:陆战装备 / 海军舰船 / 航空航天 / 导弹与反导 / 信息化 / 后勤保障 / 轻武器 / 跨域 / 其他 |
|
||||||
|
|
||||||
|
本 PRD 解决 v2 之后留下的三个开放点:**多标签横轴取值规则、小样本兜底、视觉规格刷新到 2 档纵轴**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §2 决策一:多标签 → 横轴单点取值规则(Path A 全额法)
|
||||||
|
|
||||||
|
`equipment_domain` 字段为多选(至少 1 项),但横轴一期只能落一个点。
|
||||||
|
|
||||||
|
### 2.1 规则
|
||||||
|
|
||||||
|
**每个 `equipment_domain` 标签独立维护自己的累计均值;一期节目标了 N 个标签,就把该期完整 share 直接记进**每一个**沾上的标签的均值池(全额、不瓜分、不加权)。**
|
||||||
|
|
||||||
|
### 2.2 数学定义
|
||||||
|
|
||||||
|
```
|
||||||
|
对每个 equipment_domain 标签 i:
|
||||||
|
base_i = 所有沾标签 i 的节目的 share 的算术平均
|
||||||
|
= Σ(share_j, ∀ j 沾标签 i) / count(j 沾标签 i)
|
||||||
|
|
||||||
|
栏目均值:
|
||||||
|
base_全栏目 = 所有节目的 share 的算术平均(单期单算)
|
||||||
|
|
||||||
|
每期 ep 的横轴位置:
|
||||||
|
X(ep) = mean(base_i, ∀ i ∈ ep.equipment_domain) − base_全栏目
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 示例
|
||||||
|
|
||||||
|
设当前 `海军舰船` 桶均值 = 0.69,`跨域` 桶均值 = 0.79,栏目均值 = 0.72。
|
||||||
|
|
||||||
|
- 一期标 `海军舰船 + 跨域`,share = 0.71
|
||||||
|
- 该期 X 位置 = (0.69 + 0.79) / 2 − 0.72 = **+0.02**(略偏热)
|
||||||
|
- 这期 share = 0.71 同时记入 `海军舰船` 均值池(下次 base 重算用)和 `跨域` 均值池
|
||||||
|
|
||||||
|
**两点说明**:
|
||||||
|
|
||||||
|
1. **均值更新方向自洽**:0.71 < 0.72(栏目均值),也低于"跨域 0.79"。记入两个桶后,两个桶的均值都会被这期略往下拉,符合"低于均值的样本拉低均值"的直觉。
|
||||||
|
2. **不存在 ×N 放大**:之前讨论过的"按基值加权 × 标签数"方案因方向 bug(低于均值的样本可能反向拉高均值)被否决,详见 2026-06-12 续接讨论。
|
||||||
|
|
||||||
|
### 2.4 适用范围
|
||||||
|
|
||||||
|
本规则**仅用于横轴 X 值计算**。其他统计(能力地图、编导对比、scene_tags 分布等)的多标签处理另议。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §3 决策二:小样本兜底规则
|
||||||
|
|
||||||
|
某 `equipment_domain` 桶若在当前分析窗口内样本量 n 较小,均值统计意义弱。视觉上需可辨。
|
||||||
|
|
||||||
|
### 3.1 兜底分档
|
||||||
|
|
||||||
|
| 桶样本量 | 视觉处理 |
|
||||||
|
|---|---|
|
||||||
|
| **n ≥ 3** | 正常显示,base 值直接入横轴坐标 |
|
||||||
|
| **n = 1 或 2** | 桶名右侧显示 `(n=X)` 灰色小字;桶内气泡描边改为虚线浅灰;tooltip 警示"样本不足,横轴位置参考价值有限" |
|
||||||
|
| **n = 0** | 桶不出现在横轴坐标系上(如 `陆战装备` 在 21 期场景下属此类,预留枚举值但暂不画) |
|
||||||
|
|
||||||
|
### 3.2 阈值出处
|
||||||
|
|
||||||
|
n = 3 阈值的取法:统计上方差估计起码需 2 自由度,记录方便取 3。**这是初值,后续看实际分布可调**。
|
||||||
|
|
||||||
|
### 3.3 当前 21 期场景的小样本桶预测
|
||||||
|
|
||||||
|
按 v2 §2 九类 + 我对 21 期的初步映射(见配套回填提案表):
|
||||||
|
|
||||||
|
- `导弹与反导` n=1(ep15 一期),**小样本桶**
|
||||||
|
- `信息化` n=1 或 2(取决于 ep03 是否归这里 vs 跨域),**可能小样本**
|
||||||
|
- `陆战装备` n=0,**不出现在坐标系**
|
||||||
|
- `后勤保障` n=0,**不出现在坐标系**
|
||||||
|
- `其他` n=0,**不出现在坐标系**
|
||||||
|
|
||||||
|
其余 4 个桶(`海军舰船` / `航空航天` / `轻武器` / `跨域`)预计 n ≥ 3,正常显示。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §4 决策三:视觉规格刷新(纵轴 3 档 → 2 档)
|
||||||
|
|
||||||
|
v2 §4 视觉规格除以下差异外,**全部沿用**:
|
||||||
|
|
||||||
|
| 元素 | v2 §4(3 档,旧) | 本版(2 档,新) |
|
||||||
|
|---|---|---|
|
||||||
|
| 纵轴档位 | 强主线悬念 / 主线演进 / 并列结构 | **主线演进 / 并列结构**(v3 §1.1 收为 2 档) |
|
||||||
|
| 纵轴坐标 | 三个水平基线 | 两个水平基线 |
|
||||||
|
| 同档内 jitter | ±0.3 | ±0.4(档少了,jitter 可适当加大避免聚拢) |
|
||||||
|
| 中线视觉 | 两条次级分隔 | **一条主分隔线显著加粗**,强调"主线 vs 并列"对照 |
|
||||||
|
| 上下区视觉重点 | 三层等权 | **两区中性等权**——纵轴不暗示偏好方向,呈现客观对照(2026-06-12 通哥拍板) |
|
||||||
|
|
||||||
|
横轴部分全部沿用 v2 §4,无变化。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §5 配套交付清单(子项目本轮其余产出)
|
||||||
|
|
||||||
|
- [✅ 本文件] `F3_横轴量化方法_PRD_v1.0草稿.md`
|
||||||
|
- [⏳ 下批] `双引擎象限图_HTML_mock_v1.0.html`——基于本 PRD 的纵轴 2 档版可视化,可浏览器直开看交互
|
||||||
|
- [⏳ 下批] `F3_算法验证脚本.py`——在子项目沙盒里跑通完整计算流程,输入 23 期 equipment_domain 多选 + share,输出各桶 base + 23 期 X 值表 + 数据校验报告
|
||||||
|
- [⏳ 下批] `equipment_domain_字段定义文档.md`——按 Brief §6.1 格式,主 project Cline 拿去做 schema 迁移
|
||||||
|
- [⏳ 下批] `23期_equipment_domain_回填提案表.md`——给制片人审,或转 Prompt 1a 的 ground-truth 输入
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §6 落地依赖(主 project Cline 工作清单)
|
||||||
|
|
||||||
|
子项目这边的 5 份交付物全部锁定后,主 project Cline 可接手以下工作(均需切 Plan + Opus 审):
|
||||||
|
|
||||||
|
1. **Schema 迁移**:`backend/sql/00X_add_equipment_domain.sql`(基于字段定义文档)
|
||||||
|
2. **23 期回填**:Prompt 1a 跑批结果落库 + 制片人审过的 8 期标题推断低置信度样本
|
||||||
|
3. **后端 API endpoint**:横轴聚合数据接口 `GET /api/v1/episodes/quadrant-data`(或类似)
|
||||||
|
4. **前端 React/ECharts 组件**:基于本 PRD 的 HTML mock 1:1 翻译
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §7 后续可能调整项(本版不解,留入 backlog)
|
||||||
|
|
||||||
|
- **时间窗口选择**:滚动窗口 vs 全部历史 vs 季度,默认设"全部历史",后续 UI 加切换器
|
||||||
|
- **n ≥ 3 阈值的实际验证**:用 23 期 + 新片陆续入库 6 个月后看分布,必要时调阈值
|
||||||
|
- **多标签规则是否升级**:本版用全额路 A,运行半年若发现不妥(如某桶均值长期被高频跨域期数刷高)再议升级到带权或 1/N 守恒版
|
||||||
|
- **n=1/2 视觉表达细节**:虚线浅灰 vs 描边淡化 vs 加图例,等 HTML mock 出来后定
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §8 修订规则
|
||||||
|
|
||||||
|
本 PRD 锁定 v1.0 后:
|
||||||
|
|
||||||
|
- v1.x 微调(视觉细节、阈值小动)在本子项目内修改
|
||||||
|
- v2.0 重大变更(规则换路 B、取消纵轴 2 档等)需主 project 同步审,通过新一版续接快照固化
|
||||||
|
|
||||||
|
修订必留 changelog,谁、何时、改了什么、为什么改。
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
# F3 横轴量化方法 PRD v1.0(草稿)
|
||||||
|
|
||||||
|
> 子项目交付物 · 看板分析升级
|
||||||
|
> 状态:**草稿**,等制片人审 + 锁定后转正式 v1.0
|
||||||
|
> 起草时间:2026-06-12
|
||||||
|
> 顾问:Claude Opus 4.7 | 制片人:刘通
|
||||||
|
> 类型:薄 PRD(只解 v2 之后留下的开放点,已锁部分仅引用)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §1 引用已锁结论(不重述)
|
||||||
|
|
||||||
|
本 PRD 是对已有结论的**补丁/收敛**,不替换。已锁部分直接参见以下来源:
|
||||||
|
|
||||||
|
| 来源 | 已锁内容 |
|
||||||
|
|---|---|
|
||||||
|
| 续接快照 v2 §3 | 横轴公式 `X = 该题材在分析窗口内的均值份额 − 栏目均值份额`,零点 = 栏目均值,单位 = 收视份额绝对差 |
|
||||||
|
| 续接快照 v2 §4 | 双引擎象限图视觉规格:气泡大小 = 收视份额、气泡颜色 = 收视判定三色、气泡边框 = 开篇钩子三档、重叠用 jitter 解 |
|
||||||
|
| 主 project Claude 示意图(2026-06-10) | 23 期实际数据 + 模拟纵轴/钩子已可视化,制片人认可"不挤、不堆叠" |
|
||||||
|
| 续接快照 v3 §1.1 / v4 §3 | 纵轴从 3 档收为 2 档(主线演进 / 并列结构),Prompt 2 v0.2 + ground-truth v0.2.1 M3 100% 锁定 |
|
||||||
|
| 续接快照 v2 §2 字段二 | `equipment_domain` 多选 9 类:陆战装备 / 海军舰船 / 航空航天 / 导弹与反导 / 信息化 / 后勤保障 / 轻武器 / 跨域 / 其他 |
|
||||||
|
|
||||||
|
本 PRD 解决 v2 之后留下的三个开放点:**多标签横轴取值规则、小样本兜底、视觉规格刷新到 2 档纵轴**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §2 决策一:多标签 → 横轴单点取值规则(Path A 全额法)
|
||||||
|
|
||||||
|
`equipment_domain` 字段为多选(至少 1 项),但横轴一期只能落一个点。
|
||||||
|
|
||||||
|
### 2.1 规则
|
||||||
|
|
||||||
|
**每个 `equipment_domain` 标签独立维护自己的累计均值;一期节目标了 N 个标签,就把该期完整 share 直接记进**每一个**沾上的标签的均值池(全额、不瓜分、不加权)。**
|
||||||
|
|
||||||
|
### 2.2 数学定义
|
||||||
|
|
||||||
|
```
|
||||||
|
对每个 equipment_domain 标签 i:
|
||||||
|
base_i = 所有沾标签 i 的节目的 share 的算术平均
|
||||||
|
= Σ(share_j, ∀ j 沾标签 i) / count(j 沾标签 i)
|
||||||
|
|
||||||
|
栏目均值:
|
||||||
|
base_全栏目 = 所有节目的 share 的算术平均(单期单算)
|
||||||
|
|
||||||
|
每期 ep 的横轴位置:
|
||||||
|
X(ep) = mean(base_i, ∀ i ∈ ep.equipment_domain) − base_全栏目
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 示例
|
||||||
|
|
||||||
|
设当前 `海军舰船` 桶均值 = 0.69,`跨域` 桶均值 = 0.79,栏目均值 = 0.72。
|
||||||
|
|
||||||
|
- 一期标 `海军舰船 + 跨域`,share = 0.71
|
||||||
|
- 该期 X 位置 = (0.69 + 0.79) / 2 − 0.72 = **+0.02**(略偏热)
|
||||||
|
- 这期 share = 0.71 同时记入 `海军舰船` 均值池(下次 base 重算用)和 `跨域` 均值池
|
||||||
|
|
||||||
|
**两点说明**:
|
||||||
|
|
||||||
|
1. **均值更新方向自洽**:0.71 < 0.72(栏目均值),也低于"跨域 0.79"。记入两个桶后,两个桶的均值都会被这期略往下拉,符合"低于均值的样本拉低均值"的直觉。
|
||||||
|
2. **不存在 ×N 放大**:之前讨论过的"按基值加权 × 标签数"方案因方向 bug(低于均值的样本可能反向拉高均值)被否决,详见 2026-06-12 续接讨论。
|
||||||
|
|
||||||
|
### 2.4 适用范围
|
||||||
|
|
||||||
|
本规则**仅用于横轴 X 值计算**。其他统计(能力地图、编导对比、scene_tags 分布等)的多标签处理另议。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §3 决策二:小样本兜底规则
|
||||||
|
|
||||||
|
某 `equipment_domain` 桶若在当前分析窗口内样本量 n 较小,均值统计意义弱。视觉上需可辨。
|
||||||
|
|
||||||
|
### 3.1 兜底分档
|
||||||
|
|
||||||
|
| 桶样本量 | 视觉处理 |
|
||||||
|
|---|---|
|
||||||
|
| **n ≥ 3** | 正常显示,base 值直接入横轴坐标 |
|
||||||
|
| **n = 1 或 2** | 桶名右侧显示 `(n=X)` 灰色小字;桶内气泡描边改为虚线浅灰;tooltip 警示"样本不足,横轴位置参考价值有限" |
|
||||||
|
| **n = 0** | 桶不出现在横轴坐标系上(如 `陆战装备` 在 21 期场景下属此类,预留枚举值但暂不画) |
|
||||||
|
|
||||||
|
### 3.2 阈值出处
|
||||||
|
|
||||||
|
n = 3 阈值的取法:统计上方差估计起码需 2 自由度,记录方便取 3。**这是初值,后续看实际分布可调**。
|
||||||
|
|
||||||
|
### 3.3 当前 21 期场景的小样本桶预测
|
||||||
|
|
||||||
|
按 v2 §2 九类 + 我对 21 期的初步映射(见配套回填提案表):
|
||||||
|
|
||||||
|
- `导弹与反导` n=1(ep15 一期),**小样本桶**
|
||||||
|
- `信息化` n=1 或 2(取决于 ep03 是否归这里 vs 跨域),**可能小样本**
|
||||||
|
- `陆战装备` n=0,**不出现在坐标系**
|
||||||
|
- `后勤保障` n=0,**不出现在坐标系**
|
||||||
|
- `其他` n=0,**不出现在坐标系**
|
||||||
|
|
||||||
|
其余 4 个桶(`海军舰船` / `航空航天` / `轻武器` / `跨域`)预计 n ≥ 3,正常显示。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §4 决策三:视觉规格刷新(纵轴 3 档 → 2 档)
|
||||||
|
|
||||||
|
v2 §4 视觉规格除以下差异外,**全部沿用**:
|
||||||
|
|
||||||
|
| 元素 | v2 §4(3 档,旧) | 本版(2 档,新) |
|
||||||
|
|---|---|---|
|
||||||
|
| 纵轴档位 | 强主线悬念 / 主线演进 / 并列结构 | **主线演进 / 并列结构**(v3 §1.1 收为 2 档) |
|
||||||
|
| 纵轴坐标 | 三个水平基线 | 两个水平基线 |
|
||||||
|
| 同档内 jitter | ±0.3 | ±0.4(档少了,jitter 可适当加大避免聚拢) |
|
||||||
|
| 中线视觉 | 两条次级分隔 | **一条主分隔线显著加粗**,强调"主线 vs 并列"对照 |
|
||||||
|
| 上下区视觉重点 | 三层等权 | 上区(主线演进)略亮、下区(并列结构)略灰,**视觉上暗示偏好方向**(可选,等通哥决) |
|
||||||
|
|
||||||
|
横轴部分全部沿用 v2 §4,无变化。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §5 配套交付清单(子项目本轮其余产出)
|
||||||
|
|
||||||
|
- [✅ 本文件] `F3_横轴量化方法_PRD_v1.0草稿.md`
|
||||||
|
- [⏳ 下批] `双引擎象限图_HTML_mock_v1.0.html`——基于本 PRD 的纵轴 2 档版可视化,可浏览器直开看交互
|
||||||
|
- [⏳ 下批] `F3_算法验证脚本.py`——在子项目沙盒里跑通完整计算流程,输入 23 期 equipment_domain 多选 + share,输出各桶 base + 23 期 X 值表 + 数据校验报告
|
||||||
|
- [⏳ 下批] `equipment_domain_字段定义文档.md`——按 Brief §6.1 格式,主 project Cline 拿去做 schema 迁移
|
||||||
|
- [⏳ 下批] `23期_equipment_domain_回填提案表.md`——给制片人审,或转 Prompt 1a 的 ground-truth 输入
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §6 落地依赖(主 project Cline 工作清单)
|
||||||
|
|
||||||
|
子项目这边的 5 份交付物全部锁定后,主 project Cline 可接手以下工作(均需切 Plan + Opus 审):
|
||||||
|
|
||||||
|
1. **Schema 迁移**:`backend/sql/00X_add_equipment_domain.sql`(基于字段定义文档)
|
||||||
|
2. **23 期回填**:Prompt 1a 跑批结果落库 + 制片人审过的 8 期标题推断低置信度样本
|
||||||
|
3. **后端 API endpoint**:横轴聚合数据接口 `GET /api/v1/episodes/quadrant-data`(或类似)
|
||||||
|
4. **前端 React/ECharts 组件**:基于本 PRD 的 HTML mock 1:1 翻译
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §7 后续可能调整项(本版不解,留入 backlog)
|
||||||
|
|
||||||
|
- **时间窗口选择**:滚动窗口 vs 全部历史 vs 季度,默认设"全部历史",后续 UI 加切换器
|
||||||
|
- **n ≥ 3 阈值的实际验证**:用 23 期 + 新片陆续入库 6 个月后看分布,必要时调阈值
|
||||||
|
- **多标签规则是否升级**:本版用全额路 A,运行半年若发现不妥(如某桶均值长期被高频跨域期数刷高)再议升级到带权或 1/N 守恒版
|
||||||
|
- **n=1/2 视觉表达细节**:虚线浅灰 vs 描边淡化 vs 加图例,等 HTML mock 出来后定
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §8 修订规则
|
||||||
|
|
||||||
|
本 PRD 锁定 v1.0 后:
|
||||||
|
|
||||||
|
- v1.x 微调(视觉细节、阈值小动)在本子项目内修改
|
||||||
|
- v2.0 重大变更(规则换路 B、取消纵轴 2 档等)需主 project 同步审,通过新一版续接快照固化
|
||||||
|
|
||||||
|
修订必留 changelog,谁、何时、改了什么、为什么改。
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
# 跨 project 协作 — 制片人随身提示单
|
||||||
|
|
||||||
|
> 用途:每次想在主项目之外单开子 project 讨论某个模块时,照此提示单走一遍,避免漏环节、避免版本错位、避免子项目设计违反主项目宪法。
|
||||||
|
> 适用:刘通在 Claude 网页版多 project 工作流下的所有"主项目 + 子项目"场景。
|
||||||
|
> 维护人:刘通 + 主 project 顾问 (Claude Opus 4.7)
|
||||||
|
> 首版日期:2026-06-11
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 〇、什么是 PRD?
|
||||||
|
|
||||||
|
**PRD = Product Requirements Document,产品需求文档**。
|
||||||
|
|
||||||
|
把"我想要个东西"翻译成"工程师可以照着做的具体规格"。一份合格的 PRD 回答:
|
||||||
|
|
||||||
|
- 为什么做:解决谁的什么痛点
|
||||||
|
- 做什么:功能边界、必做/不做
|
||||||
|
- 怎么用:用户走完流程的样子
|
||||||
|
- 数据形态:输入什么、输出什么、字段怎样
|
||||||
|
- 不做什么:明确划红线,防止范围蔓延
|
||||||
|
|
||||||
|
子项目立项时,请那边的 Claude 写一份 PRD 跟主项目对接——这就是工程界的标准操作。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、先判断:这事适不适合分子 project?
|
||||||
|
|
||||||
|
分之前先想三个问题。三条都满足才适合分:
|
||||||
|
|
||||||
|
1. **这个模块与主项目耦合深不深?** 耦合深的(改用户体系、改权限)就别分,分了沟通成本比省下的还高。
|
||||||
|
2. **这个模块边界清不清?** 输入输出明确的(如分钟收视回放)分得开;边界模糊的(如"优化整体视觉风格")分不开。
|
||||||
|
3. **工作量够不够大?** 特别小的事(改个字段名)直接在主项目谈完即可。三五次对话讨论不完的,才值得分。
|
||||||
|
|
||||||
|
**反例**:未来想做"AI 自动生成报题单"——这件事跟主项目的 TPS 模块、知识库、收视数据、编导画像全打通,**强耦合**,分子 project 反而割裂上下文。这种就在主项目里推进。
|
||||||
|
|
||||||
|
**正例**:分钟收视回放、本地切图工具、外拍资源管理子模块——边界清晰,可独立设计。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、流程(四步)
|
||||||
|
|
||||||
|
### 步骤 1:在主项目立"项"——先打招呼
|
||||||
|
|
||||||
|
子项目开干**之前**,先在主项目 chat 里跟 Claude 顾问说一声:
|
||||||
|
|
||||||
|
> "我要开一个子 project 讨论 X 模块,目标是 Y。"
|
||||||
|
|
||||||
|
主项目 Claude 会做两件事:
|
||||||
|
|
||||||
|
- 检查 X 是否真的适合分出去(参照第一节三问)
|
||||||
|
- 把主项目跟 X 相关的红线、技术栈、宪法摘出来给你
|
||||||
|
|
||||||
|
**实操**:把这些"开局材料"打包好,作为子项目的 files 上传过去(至少包括 `.clinerules`、`project_plan.md`、`dev_plan.md`,必要时加相关的 phase log)。子项目 Claude 能读到这些,就能少犯错。
|
||||||
|
|
||||||
|
**这一步不能省**。子项目 Claude 看不到主项目宪法时,会本能地按自己的最佳实践设计——很可能违反主项目某条红线。
|
||||||
|
|
||||||
|
### 步骤 2:在子项目讨论、迭代、收敛
|
||||||
|
|
||||||
|
要点:
|
||||||
|
|
||||||
|
- 子项目**不写主项目的代码**,只输出文档、demo、独立小工具
|
||||||
|
- 子项目**不改主项目的 schema**,所有涉及主项目数据库结构的提议,回主项目让 Claude 顾问审
|
||||||
|
- 子项目**遇到吃不准的事,回主项目问**——以提问列表的形式(参考秒级 chat 那份 PRD 第八节的 6 问)
|
||||||
|
|
||||||
|
### 步骤 3:子项目凝结成"交付包"
|
||||||
|
|
||||||
|
讨论完不能就这么散了。要凝结成可以跨 chat、跨 project、被未来任何人接手的产物。**详见下面第四节五份交付物**。
|
||||||
|
|
||||||
|
**关键认知**:Claude 的 chat 越长,判断力越下降(上下文太满);而且新 chat 一开就丢了。**md 文档才是真正的产物,chat 只是过程**。讨论一收敛,赶紧让子项目 Claude 凝结成 md。
|
||||||
|
|
||||||
|
### 步骤 4:回主项目整合
|
||||||
|
|
||||||
|
带着交付包回主项目:
|
||||||
|
|
||||||
|
- 主项目 Claude 顾问审一遍交付包,看跟主项目红线有没有冲突
|
||||||
|
- 没冲突 → 在主项目 workspace 里让 Cline 落代码
|
||||||
|
- 有冲突 → 标出冲突点,回子项目修,循环
|
||||||
|
|
||||||
|
**主项目顾问对子项目交付物有否决权**。听起来霸道,但必要——子项目 Claude 不知道主项目全部红线。这一步省不掉。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、规范:跨 project 文档怎么写
|
||||||
|
|
||||||
|
做对四件事,文档传递不会乱。
|
||||||
|
|
||||||
|
### 规范 1:文件名带版本号
|
||||||
|
|
||||||
|
❌ `分钟收视需求规格.md`
|
||||||
|
✅ `分钟收视需求规格_v1.md`
|
||||||
|
|
||||||
|
下次改了就 v2。**绝对不要原地覆盖**——历史版本要留着,方便回看"我们当时为什么这么定"。
|
||||||
|
|
||||||
|
### 规范 2:文档顶部固定"元信息块"
|
||||||
|
|
||||||
|
每份跨 project 文档第一段必须有:
|
||||||
|
|
||||||
|
```
|
||||||
|
> 版本:v1
|
||||||
|
> 日期:2026-06-11
|
||||||
|
> 作者:[谁写的]
|
||||||
|
> 状态:[草稿 / 待主项目审 / 已采纳 / 已作废]
|
||||||
|
> 上一版:[v0 或"无"]
|
||||||
|
> 主要变化:[v2 才需要写]
|
||||||
|
```
|
||||||
|
|
||||||
|
这块 6 行,写起来不累,但是救命。**没有这个块的跨 project 文档,主项目这边可以拒收**。
|
||||||
|
|
||||||
|
### 规范 3:一份文档只谈一件事
|
||||||
|
|
||||||
|
不要在"分钟收视需求规格"里顺带讨论"用户管理优化"。串了就乱。
|
||||||
|
|
||||||
|
### 规范 4:主项目这边定期回收
|
||||||
|
|
||||||
|
子项目讨论完、文档传过来、整合完成后,把最终采纳的那份 md 放到主项目的 `docs/cross_project/` 目录里。这是主项目的"对外接口档案库"。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、最终交付物:子项目结束时该产出什么(五份)
|
||||||
|
|
||||||
|
子项目结束时,告诉那边的 Claude:
|
||||||
|
|
||||||
|
> "请把所有讨论凝结成最终交付包,包含以下五份产物。"
|
||||||
|
|
||||||
|
### 产物 1:决策摘要 md
|
||||||
|
|
||||||
|
记录子项目全程的关键决策。每条三句话:
|
||||||
|
|
||||||
|
```
|
||||||
|
决策 X:[一句话决策内容]
|
||||||
|
- 背景:为什么需要这个决策
|
||||||
|
- 拍板理由:选这条不选那条的理由
|
||||||
|
- 拍板人:[制片人 / 主项目顾问 / 子项目 Claude 建议+制片人采纳]
|
||||||
|
```
|
||||||
|
|
||||||
|
不需要"我们讨论了 47 轮"的过程,只要最终结论。10-20 条就把整个子项目的"为什么这么做"讲清。
|
||||||
|
|
||||||
|
### 产物 2:接口约定 md(最技术、最精确)
|
||||||
|
|
||||||
|
把子板块与主项目接驳的所有"接口"白纸黑字写出来。"接口"是广义的,包括:
|
||||||
|
|
||||||
|
- **数据接口**:要新建哪些表、哪些字段、字段类型、约束
|
||||||
|
- **API 接口**:要新增哪些后端 endpoint、URL、方法、请求体、响应体、错误码
|
||||||
|
- **UI 接口**:要在主项目哪个页面挂载这个模块、入口在哪、路由怎么走
|
||||||
|
- **权限接口**:哪些角色可以做什么操作
|
||||||
|
- **存储接口**:文件存到哪个目录、命名规则、URL 怎么拼
|
||||||
|
|
||||||
|
每一条都要具体到"主项目的 Cline 拿着这份就能写代码"的程度。**这份是子项目给主项目的"合同"**。
|
||||||
|
|
||||||
|
### 产物 3:实物交付(独立工具、demo、设计稿)
|
||||||
|
|
||||||
|
子项目特有的产物。视模块性质不同:
|
||||||
|
|
||||||
|
- 分钟收视回放子项目 → 本地切图工具 (py + exe + 使用说明)
|
||||||
|
- 视觉重设计子项目 → 设计稿(Figma / HTML demo)
|
||||||
|
- 数据分析子项目 → 离线分析脚本 + 示例输出
|
||||||
|
|
||||||
|
这些东西**与主项目零耦合**,自己能独立运行。
|
||||||
|
|
||||||
|
### 产物 4:未尽事项 backlog
|
||||||
|
|
||||||
|
诚实写出"子项目讨论中提到但没做的事"。每条三行:
|
||||||
|
|
||||||
|
- 是什么
|
||||||
|
- 为什么没做(暂缓 / P1+ / 等条件成熟)
|
||||||
|
- 触发时机
|
||||||
|
|
||||||
|
放进主项目的 backlog 池子里,未来某个 Phase 收尾时回看,决定哪条捞进下个 Phase。
|
||||||
|
|
||||||
|
### 产物 5:给主项目 Claude 顾问的"接手提示词"
|
||||||
|
|
||||||
|
一两段话,告诉主项目顾问"如果你是接手这件事的 Claude,最重要的三件事是 X、Y、Z"。
|
||||||
|
|
||||||
|
这段相当于一份"防止主项目这边犯傻"的备忘,往往是最有价值的一份。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、操作过程中的实操注意点
|
||||||
|
|
||||||
|
### 注意 1:永远以 md 为准,不要口头转述
|
||||||
|
|
||||||
|
❌ "那边 Claude 说 XX",然后跟那边说"主项目这边说 YY"
|
||||||
|
✅ 所有跨项目沟通**以 md 文档为准**
|
||||||
|
|
||||||
|
口头转述会丢细节、会失真,连续转两次就跟最初的意思差很远。
|
||||||
|
|
||||||
|
### 注意 2:chat 是过程,md 是产物
|
||||||
|
|
||||||
|
子项目 chat 长了之后,Claude 自己的判断力会下降(上下文太满),换新 chat 就丢了。**讨论一收敛,赶紧让子项目 Claude 凝结成 md。chat 可以扔,md 不能扔**。
|
||||||
|
|
||||||
|
### 注意 3:主项目顾问的"审查"环节不能省
|
||||||
|
|
||||||
|
子项目 Claude 不知道主项目的全部红线,可能输出违规方案。**拿到子项目交付包后,先来主项目让顾问审一遍,再让 Cline 落实施**。这一步省不掉。
|
||||||
|
|
||||||
|
### 注意 4:每个子项目最长不要超过 3-4 周
|
||||||
|
|
||||||
|
时间越长,跟主项目脱节越严重(主项目可能在这期间已经迭代)。如果一个子项目超过 4 周还没收敛,应该停下来重新评估:是不是分得太大?要不要切成更小的子子项目?
|
||||||
|
|
||||||
|
### 注意 5:交付包归档到主项目仓库
|
||||||
|
|
||||||
|
交付完成后,五份交付物放到主项目的 `docs/cross_project/{子项目名}/` 目录里。**版本号文件全部保留**,未来回看决策史时会用到。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、一句话总结
|
||||||
|
|
||||||
|
> **子项目专心做事不出主项目;主项目负责审查与整合,不掺合子项目讨论;md 文档是跨项目通信的唯一介质;版本号 + 元信息块永远不省。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、复盘提示(每次子项目结束后回看一次)
|
||||||
|
|
||||||
|
子项目结束,回过头来问自己:
|
||||||
|
|
||||||
|
1. 这次分子项目是不是真的提高了效率?还是反而增加了沟通成本?
|
||||||
|
2. 主项目顾问审查时发现了多少个违规设计?说明子项目立项时给的"开局材料"够不够?
|
||||||
|
3. 五份交付物齐了吗?哪份最有用?哪份没人看?
|
||||||
|
4. 这次的经验,要不要加进本提示单的下一版?
|
||||||
|
|
||||||
|
**本提示单本身也按版本管理**。每次复盘有沉淀就出 v2。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*v1 由主 project 顾问 (Claude Opus 4.7) 协助刘通于 2026-06-11 整理成稿。下次修订时机:第一次完整跑完一个子项目(分钟收视回放)之后。*
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
# Doco 文稿整理子项目 Brief
|
||||||
|
|
||||||
|
> 主项目 → 子项目的"交接宪法":红线、技术栈、出入口接口
|
||||||
|
> 起草日期:2026-06-12
|
||||||
|
> 状态:主项目签发,子项目内部不修改
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、为什么做
|
||||||
|
|
||||||
|
**痛点**:《军事科技》每期节目播出后,产出一份贴近实际播出的终版文稿,过去靠人工对照 A 稿(编导定稿)+ 录音转写 + OCR 字幕反复核对,**单期 4-6 小时**,且容易遗漏错字、整段重写、编导笔误。
|
||||||
|
|
||||||
|
**升级目标**:把"三方文本 → 终版文稿 + 差异报告"做成可自动化的流水线模块。
|
||||||
|
|
||||||
|
**现状起点**:demo 已用《现代防空反导大对决》一期跑通,效果达标。栏目组改变了素材输出方式——直接产出"黑底白字+干净人声"的特殊视频——使物理输入从 3 路(A 稿+B 稿+ASR)收敛到 2 路(A 稿+视频),但**逻辑上仍然三方融合**(A 稿+B 路视频字幕 OCR+音轨 ASR)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、做什么(功能边界,只列名)
|
||||||
|
|
||||||
|
| 模块 | 简述 |
|
||||||
|
|---|---|
|
||||||
|
| 视频双路拆分 | ffmpeg 抽帧+字幕变化检测+OCR → B 稿;ffmpeg 抽音轨 → 16k WAV |
|
||||||
|
| 讯飞 ASR 适配层 | 复用 demo 跑通的 `xfyun_asr_standard.py`,替换凭证 |
|
||||||
|
| 三方融合引擎 | 规则层(Python)+ AI 层(Claude Sonnet 4.6),demo 已锁 |
|
||||||
|
| 单期处理接口 | CLI + Python API,契约见主项目回复 §Q3 |
|
||||||
|
| Golden test | 用 demo 那期视频做零回归验证 |
|
||||||
|
| 23 期批量调度入口 | 单期接口的批量调用方式,具体编排不在本子项目 |
|
||||||
|
|
||||||
|
**具体怎么做,子项目内部讨论,本 Brief 不预设方案。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、怎么用(目标流程)
|
||||||
|
|
||||||
|
**单期处理**:
|
||||||
|
1. 责编/编排层在 episodes 表落库该期,拿到 INT 主键
|
||||||
|
2. 拼出 episode_id:`ep{NNN}_{YYYYMMDD}_{slug}`
|
||||||
|
3. 把视频和 A 稿放进 `programs/{episode_id}/source/`
|
||||||
|
4. 调 doco:`doco.process_episode(episode_id, video_path, a_draft_path, output_dir)`
|
||||||
|
5. 产物落 `programs/{episode_id}/output/`:终版 docx + 差异报告 + needs_review JSON
|
||||||
|
6. 编导/制片人审 needs_review 队列,决定接受 / 拒绝 / 编辑
|
||||||
|
|
||||||
|
**23 期批量**:用同一接口循环调用 23 次,失败重试 + 进度跟踪由调用方负责。
|
||||||
|
|
||||||
|
**降级回退**:若某期视频不符合"黑底白字+干净人声"条件,通过 feature flag 切换到旧流程(独立 mp3 + 上游 OCR)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、不做什么(红线)
|
||||||
|
|
||||||
|
子项目设计任何方案,**绝不**触碰以下:
|
||||||
|
|
||||||
|
- ❌ **不动 demo 已锁的算法层**(三方融合优先级 / 时间戳容忍 ±5s / 口语清理三档 / 改动确信度阈值 0.85/0.6 三段)
|
||||||
|
- ❌ **不引入 `ffmpeg-python` 等 wrapper**(用 subprocess 调系统 ffmpeg)
|
||||||
|
- ❌ **不替换 AI 融合层模型**(Claude Sonnet 4.6 已锁,不临时换 DeepSeek 等)
|
||||||
|
- ❌ **不复用主 project 那把 DeepSeek key**(Cline 工具用的 key 跟生产业务分开)
|
||||||
|
- ❌ **不把凭证写进主 project 的 `backend/.env`**(子模块自治,各自 .env)
|
||||||
|
- ❌ **不假设 episode_id 命名规则**(由调用方给定,doco 只当字符串用)
|
||||||
|
- ❌ **不引入主 project 没有的技术栈**(继续 Python 3.x + Claude API + 讯飞 API)
|
||||||
|
- ❌ **不自己实现批量调度**(失败重试 / 并发控制 / 进度跟踪属于编排层职责)
|
||||||
|
- ❌ **不在子项目里写中台密钥服务**(那不属于 doco 范围)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、技术栈约束(继承主 project)
|
||||||
|
|
||||||
|
- **运行环境**:Python 3.x(版本对齐 backend),Windows / Linux 都可跑
|
||||||
|
- **系统依赖**:ffmpeg ≥ 4.x(子模块文档明确列出)
|
||||||
|
- **AI 融合**:Anthropic Claude API,模型 `claude-sonnet-4-6`
|
||||||
|
- **OCR**:DeepSeek Vision API(主项目已批,Q1)
|
||||||
|
- **ASR**:讯飞开放平台 录音文件转写标准版(**不要用大模型版**——`language` 参数被阉割)
|
||||||
|
- **音频规格**:16kHz / 单声道 / 16bit WAV(讯飞规格)
|
||||||
|
- **数据格式**:句子级时间戳统一 `[Nm Ns] 句子` 格式
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、交付什么(出口接口)
|
||||||
|
|
||||||
|
子项目最终交付物以下面形式回到主 project,**必须满足以下接口**:
|
||||||
|
|
||||||
|
### 6.1 模块交付物
|
||||||
|
- `doco/` Python 包,可被主 project 编排层 import
|
||||||
|
- CLI 入口:`doco process ...`
|
||||||
|
- 单元测试 + golden test(demo 那期零回归)
|
||||||
|
- `README.md`:系统依赖、安装、使用、配置
|
||||||
|
|
||||||
|
### 6.2 配置与凭证
|
||||||
|
- doco 自己的 `.env`(讯飞 + DeepSeek + Claude 三套 key 各自管)
|
||||||
|
- 主项目仓库根目录的 `docs/api_credentials_inventory.md` 登记一行 doco 的凭证元信息(不存真实 key)
|
||||||
|
|
||||||
|
### 6.3 数据资产沉淀(可入 TPS 中台共享)
|
||||||
|
- A 稿术语表(每期处理时从 A 稿提取,可入主 project 数据库的 terms 维度)
|
||||||
|
- OCR 错字映射表(demo 已整理,固定字形混淆对)
|
||||||
|
|
||||||
|
### 6.4 不接受
|
||||||
|
- 子项目自己改主 project 的 backend 代码、schema、迁移
|
||||||
|
- 子项目自己写主 project 的前端 UI(编导确认 UI 属于上层,不在 doco 范围)
|
||||||
|
- 子项目自己定 episode_id 命名规则(由主项目给定)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、入口接口(子项目要知道的主 project 现状)
|
||||||
|
|
||||||
|
- **主项目没有 OCR 子模块**(已确认,Q1)
|
||||||
|
- **主项目没有视频处理服务**(已确认,Q2)
|
||||||
|
- **主项目没有节目素材批量编排层**(已确认,Q3)
|
||||||
|
- **主项目没有中台密钥服务**(已确认,Q4)
|
||||||
|
- **主项目没有节目素材目录规约**(已确认,Q5,本子项目带头定 `programs/{episode_id}/...`)
|
||||||
|
- **主项目有 episodes 表**(INT 自增主键),doco 用 episode_id 时假定调用方已落库
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、未决项(归子项目自己拍板)
|
||||||
|
|
||||||
|
以下不在本 Brief 内预设,**由子项目和制片人讨论决定**:
|
||||||
|
|
||||||
|
- 视频抽帧的具体策略(关键帧检测算法 / 抽帧密度 / 字幕变化阈值)
|
||||||
|
- DeepSeek Vision 调用的具体 prompt 设计
|
||||||
|
- 规则层 OCR 错字映射表的具体扩展机制
|
||||||
|
- AI 融合层的具体提示词迭代
|
||||||
|
- needs_review JSON 的具体字段(在 demo 基础上演化)
|
||||||
|
- 单元测试覆盖率目标
|
||||||
|
- 子项目内部的 git 分支策略 / 版本号约定
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、决策史指向(不重复内容)
|
||||||
|
|
||||||
|
子项目讨论前必读:
|
||||||
|
- `doco_project_design.md / .docx`(三方融合算法层,demo 沉淀,已锁)
|
||||||
|
- `doco_xfyun_integration_notes.md / .docx`(讯飞 ASR 接入 15 个坑)
|
||||||
|
- `doco_handoff_to_opus_chat.md / .docx`(子项目立项前的 opus 接手提示)
|
||||||
|
- `PRD_doco_文稿整理子项目_v2.md`(当前子项目的请求稿)
|
||||||
|
- `主project对Doco_PRDv2的回复.md`(主项目的批复)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、本 Brief 自身的修订规则
|
||||||
|
|
||||||
|
- 本 Brief 不在子项目内修改
|
||||||
|
- 红线 / 技术栈如有变更,**主 project 这边发新版**,通过寄存条同步
|
||||||
|
- 子项目可在自己的 chat 里讨论"建议主 project 调整某条红线",调整动作只能在主 project 发生
|
||||||
|
- 子项目每次出新版 PRD,主项目顾问发新版回复;两者形成 PRD vN ↔ 回复 vN 的对照关系
|
||||||
@@ -0,0 +1,295 @@
|
|||||||
|
# PRD · Doco 文稿整理模块 · 视频源改造方案
|
||||||
|
|
||||||
|
> 版本:v2
|
||||||
|
> 日期:2026-06-12
|
||||||
|
> 作者:子 project Claude(Opus 4.7)
|
||||||
|
> 状态:草稿 / 待主项目审
|
||||||
|
> 上一版:v1(2026-06-12 同日,更早一稿)
|
||||||
|
> 主要变化:
|
||||||
|
> 1. **子模块正式定名为「Doco 文稿整理模块」**(v1 沿用旧称"TPS 三方融合子模块",本版起全部改用 Doco;Q6 已由制片人拍板,不再列为待决问题)
|
||||||
|
> 2. **Q1(OCR 选型)方向更新**:制片人确认"软件离线刚需"已不成立,云端方案可接受。补充查清的关键事实:**讯飞 OCR 与 STT 共享鉴权凭证但套餐/余额各自独立**——按制片人原判据"如果能通用 token 订阅和余额就选讯飞"不成立。**新推荐方案:DeepSeek API**(制片人手上已有),并向主项目确认是否已有 OCR 能力或 LLM 视觉调用基础设施
|
||||||
|
> 3. 其他 Q(Q2/Q3/Q4/Q5)保持不变
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 〇、一段话摘要(给主 project 顾问的最短摘要)
|
||||||
|
|
||||||
|
Doco 文稿整理模块(前称"TPS 三方融合子模块")此前的物理输入是 A 稿 docx + B 稿 OCR txt + ASR txt(mp3→讯飞)。栏目组现在改了素材输出方式:责编一次性输出 23 期"特殊视频"——画面是黑底白字唱词字幕、声音是无 BGM/音效的干净人声(极少同期声杂音)。**B 稿与 ASR 现在同源派生于一个视频文件**,物理输入从 3 个收敛到 2 个(A 稿 + 视频)。
|
||||||
|
|
||||||
|
**核心判断**:下游"三方融合引擎"(规则层 + AI 层)算法**零侵入**——只要新增的"视频双路拆分"模块输出与旧版 B 稿/ASR txt 格式完全一致(`[Nm Ns] 句子`),下游所有逻辑不动。**逻辑上仍然是三方融合**——A 稿术语权威 + B 路视频字幕 OCR + 音轨 ASR,三路独立验证的关系没破。
|
||||||
|
|
||||||
|
子项目这边需要主 project 在开工前对 5 件影响接口/数据形态的事拍板。详见 §4。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、变更前后对照
|
||||||
|
|
||||||
|
### 旧设计(demo 已验证)
|
||||||
|
|
||||||
|
```
|
||||||
|
[A 稿 docx] ──────────────────────┐
|
||||||
|
│
|
||||||
|
[上游既有 OCR 流程] ── B 稿 txt ──┤
|
||||||
|
├─► [三方融合引擎] ─► 终版.docx + 差异报告.docx
|
||||||
|
[节目纯净人声 mp3] │
|
||||||
|
│ │
|
||||||
|
└─► [讯飞 ASR] ── ASR txt ─┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 新设计(本 PRD 提出)
|
||||||
|
|
||||||
|
```
|
||||||
|
[A 稿 docx] ─────────────────────────────────────┐
|
||||||
|
│
|
||||||
|
[节目特殊视频文件] │
|
||||||
|
画面:黑底白字字幕 │
|
||||||
|
声音:干净人声 │
|
||||||
|
│ │
|
||||||
|
├─► [视频双路拆分子模块 · NEW] │
|
||||||
|
│ │ │
|
||||||
|
│ ├─► ffmpeg 抽帧+字幕变化检测 │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ └─► [OCR] ── B 稿 txt ──────┤
|
||||||
|
│ │ (待 Q1 拍板用 DeepSeek) ├─► [三方融合引擎] ─► 终版 + 差异
|
||||||
|
│ └─► ffmpeg 抽音轨 → 16k/mono WAV │ (复用)
|
||||||
|
│ │ │
|
||||||
|
│ └─► [讯飞 ASR · 复用] │
|
||||||
|
│ └────── ASR txt ──────┘
|
||||||
|
│
|
||||||
|
└─ (后续接 23 期批量调度)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 关键变化清单
|
||||||
|
|
||||||
|
| 项 | 旧 | 新 |
|
||||||
|
|---|---|---|
|
||||||
|
| 子模块名称 | TPS 三方融合子模块 | **Doco 文稿整理模块** |
|
||||||
|
| 物理输入 | A 稿 + B 稿 + ASR | A 稿 + 视频 |
|
||||||
|
| 逻辑融合方 | 三方 | **仍然三方**(A / B 路 / ASR 路) |
|
||||||
|
| B 稿来源 | 上游既有 OCR 流程 | 视频抽帧 → OCR |
|
||||||
|
| ASR 来源 | 节目 mp3 | 视频音轨 |
|
||||||
|
| 算法层 | 规则层 + AI 层 | **不变** |
|
||||||
|
| 新增模块 | — | 视频双路拆分(ffmpeg + OCR) |
|
||||||
|
| 处理粒度 | 单期 | 单期接口 + 23 期批量调度 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、子项目这边已经拍板的事(不需要主 project 决策,仅告知)
|
||||||
|
|
||||||
|
### 2.1 制片人已明确的决策
|
||||||
|
|
||||||
|
1. **子模块定名**:**Doco 文稿整理模块**("Doco" 取意"Documentation Consolidation"——文稿整合)。本 PRD 起所有引用旧称("TPS 三方融合子模块"、"三方融合")的地方都用新名替换。
|
||||||
|
2. **离线不再是刚需**:原 v1 推荐 PaddleOCR 本地的核心理由(离线刚需)失效;OCR 选型转向云端。
|
||||||
|
|
||||||
|
### 2.2 demo 已验证或设计文档已定义的事
|
||||||
|
|
||||||
|
不变:
|
||||||
|
|
||||||
|
1. **三方融合优先级**(A 稿术语权威 / ASR 口吻 / B 稿验证)—— 见 project_design.md §5.1
|
||||||
|
2. **时间戳容忍度 ±5 秒** —— project_design.md §5.2
|
||||||
|
3. **口语清理三档**(keep_all / medium / clean)—— project_design.md §5.3
|
||||||
|
4. **改动确信度阈值**(0.85 自动 / 0.6–0.85 黄标 / <0.6 待确认)—— project_design.md §5.4
|
||||||
|
5. **AI 融合层模型**:Claude Sonnet 4.6 起步
|
||||||
|
6. **差异报告格式**:demo 黄金对照已落定
|
||||||
|
7. **A 稿术语表数据结构**:project_design.md §9.1
|
||||||
|
8. **OCR 错字映射表**:复用 demo 整理的字形混淆对
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、子项目这边的开发计划草案(待主 project 审)
|
||||||
|
|
||||||
|
| Phase | 内容 | 产物 | 主依赖 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| P1 | 视频双路拆分预处理(单期)| `video_split.py`:视频 → 抽帧+字幕变化检测+OCR → B稿.txt;视频 → 音轨 → 16k WAV | ffmpeg、OCR(待 Q1 拍板,倾向 DeepSeek API) |
|
||||||
|
| P2 | 讯飞 ASR 适配层 | 复用 `xfyun_asr_standard.py`,替换新凭证、做成可被 P1 流水线调用的模块 | 讯飞开发端密钥(待 Q4 拍板) |
|
||||||
|
| P3 | Doco 融合引擎 | 规则层 Python + AI 层 Claude API;输入 A/B/ASR 三方 txt,输出终版 docx + 差异报告 + needs_review JSON | Claude API |
|
||||||
|
| P4 | 单期端到端 golden test | 用 demo 那期《现代防空反导大对决》的视频跑一遍,与 demo 产物比对,确认零回归 | 上面三 phase |
|
||||||
|
| P5 | 23 期批量 | 单期模块包成可被批量调度调用的接口(CLI / Python API 二选一,待 Q3 拍板) | — |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、需要主项目决策的 5 个问题
|
||||||
|
|
||||||
|
> 每条都给了子项目这边的推荐答案 + 理由。主项目顾问可以照单批,也可以推翻。
|
||||||
|
|
||||||
|
### Q1. OCR 方案选型?
|
||||||
|
|
||||||
|
**问题**:B 路 OCR 用什么?这是新引入的依赖,绕不开。
|
||||||
|
|
||||||
|
#### Q1.A 关键事实(更新自 v1)
|
||||||
|
|
||||||
|
子项目这边查清了几件事,供主项目决策参考:
|
||||||
|
|
||||||
|
1. **讯飞 OCR 与 STT 的共享情况**:
|
||||||
|
- 鉴权凭证(开发者账号、APPID、APIKey、APISecret)**可共享**,一组凭证可同时调用多个服务
|
||||||
|
- 但**套餐/计费/余额各自独立**:STT 是"5 小时免费试用包"独立购买;OCR 是另一套计费体系(参考 SaaS 零售价 4.9 元/10 张、9.9 元/50 张)。**不存在用 STT 的余额跑 OCR 这种事**
|
||||||
|
- **按制片人原判据("如果能通用 token 订阅和余额就选讯飞")此条件不成立**
|
||||||
|
|
||||||
|
2. **制片人手上已有的 API**:
|
||||||
|
- **DeepSeek**:有专门的 `DeepSeek-OCR` 模型(OCR 2.0 方案,对中文文档识别准确率行业领先)+ DeepSeek Vision 识图模式(官方 API endpoint)。**推荐**
|
||||||
|
- **MiniMax**:有 MiniMax-VL 视觉模型,理论上可 OCR,但 OCR 专项优化不如 DeepSeek-OCR
|
||||||
|
- **小米 MiMo**:主推推理模型,未见明确的视觉/OCR 能力
|
||||||
|
|
||||||
|
3. **本场景的 OCR 难度评估**:
|
||||||
|
- 输入图像是**黑底白字纯字幕画面**——OCR 最简单的子集(高对比度、印刷体、无图案干扰、无版面分析)
|
||||||
|
- LLM 视觉模型在此场景几乎不会出错;用 LLM 做 OCR 在这里不是杀鸡用牛刀,因为成本极低且无新增依赖
|
||||||
|
|
||||||
|
4. **成本估算(23 期总量)**:
|
||||||
|
- 单期约 300 条字幕(demo 数据),23 期 ≈ 6900 张图
|
||||||
|
- DeepSeek Vision API 单张成本约几厘到一分,**总成本预估 50–150 元**
|
||||||
|
- 对比讯飞 OCR SaaS 零售价:6900 张 × 0.198 元/张 ≈ 1370 元
|
||||||
|
- 对比 PaddleOCR 本地:0 元但需要维护本地环境(已不是刚需)
|
||||||
|
|
||||||
|
#### Q1.B 选项与推荐
|
||||||
|
|
||||||
|
**选项**:
|
||||||
|
- A. **DeepSeek API(视觉模型)**——制片人已有 API,无新增订阅
|
||||||
|
- B. **讯飞 OCR**——与 STT 同账号但余额独立
|
||||||
|
- C. **PaddleOCR 本地**——零成本但需本地环境
|
||||||
|
- D. **主 project 已有的 OCR 服务**——如果存在
|
||||||
|
|
||||||
|
**子项目推荐**:A(DeepSeek API)
|
||||||
|
|
||||||
|
**理由**:
|
||||||
|
- 满足制片人"用现有 API 资源"的方向
|
||||||
|
- 黑底白字字幕是 LLM 视觉模型的舒适区,识别质量有保障
|
||||||
|
- 与讯飞 STT 解耦,单点故障范围小
|
||||||
|
- 成本最低(除 PaddleOCR)且无本地环境维护成本
|
||||||
|
|
||||||
|
**请主项目确认**:
|
||||||
|
- 主 project 是否已有 OCR 子模块/能力?(制片人初步判断"主 project 应该没有 OCR 配置",请顾问最终确认)
|
||||||
|
- 主 project 的密钥管理体系是否已经接入 DeepSeek?还是需要 Doco 子模块自行管理 DeepSeek 凭证?
|
||||||
|
- 6900 张图调用 DeepSeek 是否会影响主 project 其他模块的 DeepSeek 配额/限流?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Q2. 视频处理依赖(ffmpeg)的入口?
|
||||||
|
|
||||||
|
**问题**:抽帧与抽音轨都依赖 ffmpeg。
|
||||||
|
|
||||||
|
**选项**:
|
||||||
|
- A. Doco 子模块自带 ffmpeg 系统依赖 + Python 封装(`ffmpeg-python` 或 subprocess)
|
||||||
|
- B. 主 project 有统一的视频处理服务/适配层
|
||||||
|
|
||||||
|
**子项目推荐**:A,使用 subprocess 调用系统 ffmpeg
|
||||||
|
|
||||||
|
**理由**:ffmpeg 是标准工具,独立部署足够简单。
|
||||||
|
|
||||||
|
**请主项目确认**:是否已经有视频处理子模块/服务在规划中?如有,应改走中台接口。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Q3. 23 期批量 vs 单期接口?
|
||||||
|
|
||||||
|
**问题**:本次实际场景是 23 期,Doco 子模块的接口应该长什么样?
|
||||||
|
|
||||||
|
**选项**:
|
||||||
|
- A. 子模块只负责单期,输入 = 1 视频 + 1 A 稿;批量调度交给主 project 编排层
|
||||||
|
- B. 子模块内部支持批量,输入 = 视频目录 + A 稿目录
|
||||||
|
- C. 两者都提供
|
||||||
|
|
||||||
|
**子项目推荐**:A(子模块只对单期负责)
|
||||||
|
|
||||||
|
**理由**:
|
||||||
|
- 单一职责原则。批量调度涉及失败重试、进度跟踪、并发控制——属于编排层职责
|
||||||
|
- 单期接口在出错时定位简单(哪期失败、失败在哪个 phase 一目了然)
|
||||||
|
- 主 project 未来可能有节目档案库流水线、报题单流水线等,统一在编排层做并发更合理
|
||||||
|
|
||||||
|
**请主项目确认**:
|
||||||
|
- 主 project 是否计划做"节目素材批量处理编排层"?如有,Doco 的单期接口应满足什么样的契约(CLI?Python API?返回值结构?)
|
||||||
|
- 23 期这次是先单期跑通再批量,还是要求一次性 batch?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Q4. 讯飞密钥更新/续费策略?
|
||||||
|
|
||||||
|
**问题**:demo 凭证可能已过期(制片人提示"讯飞试用可能也过了"),且需要区分**消费端**(讯飞听见 App)与**开发端**(开放平台)。
|
||||||
|
|
||||||
|
**选项**:
|
||||||
|
- A. Doco 子模块各自申请新凭证、各自管理
|
||||||
|
- B. 接入中台统一密钥服务(如果有)
|
||||||
|
- C. 申请新凭证 + 写入"中台密钥资产文档"作为登记
|
||||||
|
|
||||||
|
**子项目推荐**:C
|
||||||
|
|
||||||
|
**理由**:现阶段中台密钥服务可能未完成,但密钥归属、过期日期、所属子模块应该有统一登记入口。
|
||||||
|
|
||||||
|
**请主项目确认**:
|
||||||
|
- 中台是否已有密钥管理子模块?
|
||||||
|
- 新申请的讯飞开发端密钥(包括 APP_ID、SECRET_KEY、5 小时免费试用包激活状态)应该登记在哪里?
|
||||||
|
- 如果 Q1 拍板用 DeepSeek,DeepSeek API key 是否也按同样规则登记?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Q5. 目录结构与命名规约?
|
||||||
|
|
||||||
|
**问题**:23 期素材、抽帧产物、wav、终版 docx 的存储路径需要规约,否则后期归档混乱。
|
||||||
|
|
||||||
|
**子项目草案**:
|
||||||
|
|
||||||
|
```
|
||||||
|
programs/
|
||||||
|
└── {episode_id}/ # 例:20260612_防空反导
|
||||||
|
├── source/
|
||||||
|
│ ├── video.mp4 # 原始特殊视频(黑底白字+干净人声)
|
||||||
|
│ └── a_draft.docx # A 稿(编导定稿)
|
||||||
|
├── work/ # 中间产物(可清理)
|
||||||
|
│ ├── frames/ # 抽出的字幕关键帧
|
||||||
|
│ ├── audio_16k.wav # 抽音轨标准化产物
|
||||||
|
│ ├── b_draft.txt # OCR 产物(带 [Nm Ns] 时间戳)
|
||||||
|
│ ├── asr_result.txt # 讯飞 ASR 产物
|
||||||
|
│ └── asr_result_raw.json # 讯飞原始返回
|
||||||
|
└── output/ # 主产物(入档案库)
|
||||||
|
├── final.docx # 终版文稿
|
||||||
|
├── diff_report.docx # 差异报告
|
||||||
|
└── needs_review.json # 待编导确认队列
|
||||||
|
```
|
||||||
|
|
||||||
|
**请主项目确认**:
|
||||||
|
- TPS 中台是否对节目素材的目录有统一规约?
|
||||||
|
- `episode_id` 命名规则是什么?(日期+栏目+期号?UUID?编导给定?)
|
||||||
|
- `work/` 中间产物保留多久?是否要自动清理?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、不向主项目提问、但需要告知的事
|
||||||
|
|
||||||
|
1. **demo 的 5 份 fixture 仍然有效**:A 稿 / B 稿 / ASR / 终版 / 差异报告 在新流程下都可作为单元测试与集成测试的黄金对照
|
||||||
|
2. **讯飞 ASR 脚本仍然有效**:`xfyun_asr_standard.py` 只需替换凭证、把"音频文件路径"参数从"独立 mp3"改为"视频抽音轨产物 wav"
|
||||||
|
3. **23 期之后的常态化问题**:栏目组以后是否每期都按"黑底白字+干净人声"特殊视频出素材?还是只这一批 23 期是特例?这影响 Doco 子模块要不要保留旧的 mp3+独立 OCR 流程作为回退路径。**建议主项目顾问直接跟栏目组确认**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、给主项目顾问的"接手提示词"
|
||||||
|
|
||||||
|
如果主 project 顾问要审这份 PRD,最重要的三件事:
|
||||||
|
|
||||||
|
1. **算法层零侵入是 demo 验证过的硬保证**。任何改动如果会让 P3(Doco 融合引擎)必须改算法,需要警惕——大概率是输入数据形态没对齐。
|
||||||
|
2. **OCR 选型(Q1)和目录规约(Q5)是会广泛影响其他子模块的事**,主项目顾问视野更大,应该是这两条的最终拍板人。如果主 project 有 OCR 能力或 DeepSeek 集成基础设施,Q1 的子项目推荐随时可被覆盖。
|
||||||
|
3. **23 期是一次性还是常态化(§5 第 3 条)是个产品问题,不是技术问题**,建议主项目顾问直接跟栏目组确认后再批 PRD。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、回复期望
|
||||||
|
|
||||||
|
子项目这边等以下确认才正式开干:
|
||||||
|
- Q1(OCR 选型)—— 必须先答,否则 P1 不能开始
|
||||||
|
- Q4(讯飞密钥)—— 必须先答,否则 P2 不能开始
|
||||||
|
- Q5(目录规约)—— 必须先答,否则 P1 输出无处可放
|
||||||
|
- Q3(接口契约)—— P5 之前必须答
|
||||||
|
- Q2 —— Doco 子模块可以先按推荐方案开干,主项目随后批
|
||||||
|
|
||||||
|
收到主项目 Claude 顾问的回复 md 后,Doco 子项目这边出 PRD v3(含元信息块标注"上一版:v2"),再启动 P1。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、版本变更摘要
|
||||||
|
|
||||||
|
| 版本 | 日期 | 主要变化 |
|
||||||
|
|---|---|---|
|
||||||
|
| v1 | 2026-06-12 | 首版。6 个待决问题(含子模块命名 Q6)。OCR 选型推荐 PaddleOCR 本地 |
|
||||||
|
| **v2** | **2026-06-12** | 子模块定名"Doco 文稿整理模块";Q1 改推荐 DeepSeek API(基于讯飞 OCR/STT 余额独立的事实查清 + 制片人手上已有 API 资源);Q6 已拍板移出待决列表;剩余 5 个待决问题 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*v2 由 Doco 子 project Claude(Opus 4.7)于 2026-06-12 拟稿,遵照《跨 project 协作提示单 v1》§三的规范。*
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
# Handoff to opus_chat · TPS三方融合子模块
|
||||||
|
|
||||||
|
> 这份是发给中台 opus_chat 的最短交接说明。完整设计见 `project_design.md`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 这是什么
|
||||||
|
|
||||||
|
《军事科技》TPS(终版文稿生成中台)下的一个子模块,叫"三方融合"。
|
||||||
|
|
||||||
|
**它做的事**:把三份资料合并成一份贴近实际播出的终版 docx 文稿,并生成一份差异报告。
|
||||||
|
|
||||||
|
三份资料是:
|
||||||
|
1. **A 稿** — 编导手写定稿(docx,有【主持人N】【解说N】【专家N】【动画N】结构标签)
|
||||||
|
2. **B 稿** — OCR 扒词(txt,带 `[Nm Ns]` 时间戳,有 OCR 错字)
|
||||||
|
3. **ASR** — 讯飞录音文件转写结果(txt,带 `[Nm Ns]` 时间戳,有同音误识)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 你需要记住的 5 件事
|
||||||
|
|
||||||
|
### 1. 三方权威优先级(**最重要,不要搞反**)
|
||||||
|
|
||||||
|
| 看什么 | 信谁 |
|
||||||
|
|---|---|
|
||||||
|
| 术语 / 人名 / 装备型号 / 事实 | **A 稿** |
|
||||||
|
| 标点 / 语序 / 口吻 | **ASR** |
|
||||||
|
| OCR 字形错(肘/时、娈/变) | 用 **ASR 或 A 稿** 覆盖 B 稿 |
|
||||||
|
| 整段是否存在 | **B 稿 + ASR 联合**判定 |
|
||||||
|
|
||||||
|
为什么 A 稿术语优先?demo 中 ASR 把"美以两国"识别成了"美伊两国"——句子通顺、语义荒谬。无 A 稿无法发现。
|
||||||
|
|
||||||
|
### 2. 架构是双层(不是单层 AI)
|
||||||
|
|
||||||
|
```
|
||||||
|
规则层(Python) AI 层(Claude API)
|
||||||
|
├ OCR 错字映射 ├ 段落对齐
|
||||||
|
├ A 稿术语字典覆盖 ├ 改动类型判定
|
||||||
|
├ 时间戳对齐 ├ 整段改写边界
|
||||||
|
├ 数字 / 标点规范化 └ 编导笔误识别
|
||||||
|
└ 口语词清理(可配置)
|
||||||
|
```
|
||||||
|
|
||||||
|
确定性的事走规则层,需要语义判断的事走 AI 层。**不要全塞给 AI**。
|
||||||
|
|
||||||
|
### 3. 输入有严格规范
|
||||||
|
|
||||||
|
- **A 稿**:自然段开头 `【…】` 是结构标签;`隔断:【…】` 是章节分隔
|
||||||
|
- **B 稿 / ASR**:每行格式 `[Nm Ns] 句子内容`
|
||||||
|
- **音频**(如果走完整流程从音频开始):必须 **16kHz / 单声道 / 16bit WAV**,否则讯飞拒收
|
||||||
|
|
||||||
|
### 4. 讯飞 ASR 有坑(开发前必读)
|
||||||
|
|
||||||
|
- 用"**录音文件转写(标准版)**",**不要**用"大模型版"(免费包阉割了 `language` 参数)
|
||||||
|
- 领域参数 `pd=mil`(军事节目专用)
|
||||||
|
- 顺滑参数 `eng_smoothproc=true` + `eng_colloqproc=true`
|
||||||
|
- **热词机制**是关键:每期从 A 稿提 200 字以内的专业术语作为 `hotWord`
|
||||||
|
- 讯飞**消费端**(讯飞听见 App)和**开发端**(开放平台)密钥**不通用**
|
||||||
|
- "5 小时免费试用"必须走 0 元购买流程激活
|
||||||
|
- 签名:`signa = base64(HmacSHA1(MD5(appid + ts), secretKey))`
|
||||||
|
|
||||||
|
详见 demo 中的 `xfyun_asr_standard.py`。
|
||||||
|
|
||||||
|
### 5. 输出有两份,不只一份
|
||||||
|
|
||||||
|
- **终版.docx** — 主产物,给档案库
|
||||||
|
- **差异报告.docx** — 副产物,给编导回顾。**差异报告的长期价值可能比终版更高**(能反向分析编导删改偏好)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 我和这个模块的关系
|
||||||
|
|
||||||
|
- **你(opus_chat)**:中台对话入口,可能会被用户问到本模块的边界 / 接口 / 状态
|
||||||
|
- **本模块**:被 TPS 主流程调用,输入三份文本,输出两份 docx + 一份 JSON
|
||||||
|
- **不归我管**:音频转码、OCR 识别本身、档案入库、编导确认 UI
|
||||||
|
|
||||||
|
如果用户问以下内容,**统一口径**:
|
||||||
|
|
||||||
|
| 问题 | 答 |
|
||||||
|
|---|---|
|
||||||
|
| "能不能不用 A 稿?" | 不能。会引入 ASR 的同音事实错误,且术语全乱。 |
|
||||||
|
| "能不能不用 B 稿?" | 可以,但失去独立交叉验证;不推荐。 |
|
||||||
|
| "能不能不用 ASR?" | demo 证明 A+B 也能跑,但效果显著下降;不推荐。 |
|
||||||
|
| "ASR 选讯飞还是别家?" | 当前讯飞。已踩坑、已跑通;阿里云是规划中的备份。 |
|
||||||
|
| "AI 用哪个模型?" | Claude Sonnet 4.6 起步,单期 26 分钟节目约 16k 字上下文。 |
|
||||||
|
| "处理一期要多久?" | 正式版预估 15–30 分钟(含人工确认);demo 实测 2 小时但近一半花在踩讯飞坑上。 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## demo 状态
|
||||||
|
|
||||||
|
- 已完整跑通一期《现代防空反导大对决》(26 分钟)
|
||||||
|
- 关键术语识别率接近 100%(开启 35 条热词后)
|
||||||
|
- 主要修复:OCR 错字 10+ 类、ASR 同音误识 4 类、编导笔误 1 段、整段删除 2 段
|
||||||
|
- 复盘文档:`实测复盘.md`
|
||||||
|
- 设计文档:`project_design.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 不一致时怎么办
|
||||||
|
|
||||||
|
如果你(opus_chat)发现本备忘与 `project_design.md` 不一致,**以 project_design.md 为准**。
|
||||||
|
如果你发现 project_design.md 本身需要更新,请同步刘统制片组。
|
||||||
@@ -0,0 +1,451 @@
|
|||||||
|
# TPS · 三方融合子模块 设计文档(project_design.md)
|
||||||
|
|
||||||
|
> 归属:《军事科技》中台 TPS · 终版文稿生成(Three-source Pipeline Synthesis)
|
||||||
|
> 文档目的:把 demo 阶段的实测结论沉淀为可被中台其他子模块(含 opus_chat)调用的明确接口与约束
|
||||||
|
> 当前状态:demo 已跑通一期完整节目(《现代防空反导大对决》),进入正式开发阶段
|
||||||
|
> 文档版本:v0.1(2026-05-15)
|
||||||
|
> 维护:刘统制片组 / Claude
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. TL;DR(给 opus_chat 的最短摘要)
|
||||||
|
|
||||||
|
- 本子模块的输入是三份资料,输出是一份贴近实际播出的 docx 文稿 + 一份逐段差异报告。
|
||||||
|
- **三份输入:**
|
||||||
|
1. **A 稿**:编导手写定稿(docx,带【主持人N】【解说N】【专家N】【动画N】【隔断:…】结构标签)
|
||||||
|
2. **B 稿**:OCR 扒词文档(txt,带 `[Nm Ns]` 句级时间戳,存在 OCR 错字)
|
||||||
|
3. **ASR 结果**:讯飞录音文件转写(txt,带 `[Nm Ns]` 句级时间戳,存在同音误识)
|
||||||
|
- **核心信念**:三方各有短板,单源不可信;融合后才是"播出真相"。
|
||||||
|
- A 稿 → 术语 / 人名 / 装备型号 / 事实 的**权威**
|
||||||
|
- ASR → 播出语序与口吻的**骨架**
|
||||||
|
- B 稿 → 独立**交叉验证**(同时验证 A 与 ASR)
|
||||||
|
- **架构两层:**
|
||||||
|
- **规则层**(Python):术语字典纠正、OCR 错字映射、时间戳对齐、口语词清理、数字规范化
|
||||||
|
- **AI 层**(Claude API):段落对齐、改动类型判定、整段改写边界、编导笔误识别
|
||||||
|
- **请 opus_chat 注意:** 本模块依赖讯飞 ASR 与 Claude API,**两套密钥**互不复用;调用本模块前应确认 A 稿术语表已入库。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 业务背景与定位
|
||||||
|
|
||||||
|
### 1.1 上游 / 下游
|
||||||
|
|
||||||
|
```
|
||||||
|
[节目编导] ──A稿(docx)──┐
|
||||||
|
│
|
||||||
|
[OCR 服务(旧流程)]──B稿(txt+时间戳)──┐
|
||||||
|
├──► [本模块 三方融合] ──► [终版docx] ──► [节目档案库]
|
||||||
|
│ └► [差异报告docx] ──► [编导回顾 / 训练素材]
|
||||||
|
[节目纯净声音文件]──[讯飞 ASR]──ASR(txt+时间戳)─┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 在 TPS 中台的位置
|
||||||
|
|
||||||
|
本子模块是 TPS(终版文稿生成中台)的**核心算法子模块**,位于上游"素材接收"和下游"档案入库 / 编导确认 UI"之间。
|
||||||
|
|
||||||
|
- 它**不**负责音频转码(由 ASR 适配层处理)
|
||||||
|
- 它**不**负责 OCR 识别(B 稿来自既有 OCR 流程)
|
||||||
|
- 它**不**负责最终入库(由档案子模块负责)
|
||||||
|
- 它**只**负责"三方文本 → 一份贴近播出的终版文稿 + 差异报告"
|
||||||
|
|
||||||
|
### 1.3 为什么不能省略某一方?
|
||||||
|
|
||||||
|
| 缺哪一方 | 后果 | 实例 |
|
||||||
|
|---|---|---|
|
||||||
|
| 缺 A 稿 | 术语 / 人名 / 装备型号易错;ASR 同音错难发现 | "美以两国"被 ASR 识别成"美伊两国"——句子通顺、语义荒谬,无 A 稿无法纠正 |
|
||||||
|
| 缺 ASR | 无法知道实际播出语序与口吻;专家口语词全丢 | A 稿用"观众朋友们,你们好",播出实际是"各位观众你们好" |
|
||||||
|
| 缺 B 稿 | 失去独立交叉验证;ASR/A 稿冲突时无第三方仲裁 | A 稿与 ASR 在某段不一致时,B 稿与谁一致就以谁为准 |
|
||||||
|
|
||||||
|
**结论**:B 稿可以视为弱必需(demo 证明 A+ASR 二方融合也能跑),但建议保留 B 稿做 sanity check。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 输入规范
|
||||||
|
|
||||||
|
### 2.1 A 稿(编导定稿)
|
||||||
|
|
||||||
|
- **格式**:`.docx`(实际为 markdown 风格的纯文本,也兼容真 docx)
|
||||||
|
- **结构标签**(出现在自然段开头,方括号包裹):
|
||||||
|
- `【导视】` `【主持人N】` `【解说N】` `【动画N】` `【专家N】`
|
||||||
|
- `隔断:【…】` 用于章节分隔
|
||||||
|
- **特点**:
|
||||||
|
- 内容偏书面化;可能存在编导笔误(如本期【专家7】【专家8】内容字符完全相同 = 复制粘贴失误)
|
||||||
|
- 术语严格、人名 / 装备型号完整("爱国者-3"、"霍拉姆沙赫尔-4"、"见证者-136")
|
||||||
|
- 标点 / 顿号 / 引号规范
|
||||||
|
|
||||||
|
### 2.2 B 稿(OCR 扒词)
|
||||||
|
|
||||||
|
- **格式**:`.txt`
|
||||||
|
- **行格式**:`[Nm Ns] 句子内容`,每行一句
|
||||||
|
- **特点**:
|
||||||
|
- 句子时间戳精度到秒
|
||||||
|
- **存在 OCR 错字**:字形相近字混淆(肘↔时、娈↔变、夭↔天、井↔并、末↔未、纺↔防、观↔现、忽↔您、岳↔越、改命↔致命)
|
||||||
|
- 标点弱(多为空白分隔,缺逗号 / 句号)
|
||||||
|
- 句子切分较碎(一句话常被切成 2–3 行)
|
||||||
|
|
||||||
|
### 2.3 ASR(讯飞录音文件转写)
|
||||||
|
|
||||||
|
- **格式**:`.txt`
|
||||||
|
- **行格式**:`[Nm Ns] 句子内容`,每行一句(与 B 稿对齐)
|
||||||
|
- **特点**:
|
||||||
|
- 标点合理(讯飞已自动加句号、逗号、问号)
|
||||||
|
- 经 `eng_smoothproc + eng_colloqproc` 处理,已**部分**清理"嗯/呃"
|
||||||
|
- **存在同音误识**:"中端↔中段"、"末端↔末段"、"中诚↔中程"、"美伊↔美以"、"高超声速↔高超音速"
|
||||||
|
- 数字 / 百分比识别准确
|
||||||
|
- 句子级时间戳精确,可与 B 稿做交叉对齐
|
||||||
|
|
||||||
|
### 2.4 三方时间戳的对齐口径
|
||||||
|
|
||||||
|
A 稿无时间戳;B 稿与 ASR 都有 `[Nm Ns]` 但**不严格一致**(B 稿来自 OCR 字幕显示时点,ASR 来自语音波形起点;常相差 1–3 秒)。融合时**容忍 ±5 秒**的时间漂移作为同段判定的辅助条件。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 输出规范
|
||||||
|
|
||||||
|
### 3.1 终版文稿(主产物)
|
||||||
|
|
||||||
|
- **格式**:`.docx`
|
||||||
|
- **结构**:保留 A 稿的段落标签(【导视】【主持人1】…)
|
||||||
|
- **内容来源策略**:
|
||||||
|
- 默认以 ASR 文本为骨架
|
||||||
|
- A 稿术语 / 人名 / 装备型号回填
|
||||||
|
- B 稿 OCR 错字修复(用 ASR / A 稿覆盖)
|
||||||
|
- 标点采用 ASR 的版本(最自然)
|
||||||
|
- 口语词处理强度由"清理档位"参数控制(见 §5.3)
|
||||||
|
|
||||||
|
### 3.2 差异报告(副产物)
|
||||||
|
|
||||||
|
- **格式**:`.docx`
|
||||||
|
- **内容**:
|
||||||
|
1. 改动总览(段落数 / 改动类型分布)
|
||||||
|
2. 逐段对照(A 稿原文 vs 终版,标注改动类型与依据)
|
||||||
|
3. 关键差异专题:整段删除 / 整段改写 / 术语变化 / 编导笔误 / OCR 错字修复 / ASR 错字修复 / 口语词处理
|
||||||
|
4. 依据图例(三方一致 / ASR 为主 / A 稿权威 / …)
|
||||||
|
- **价值**:差异报告本身就是编导工作回顾,长期累积可分析编导删改偏好。
|
||||||
|
|
||||||
|
### 3.3 改动类型枚举
|
||||||
|
|
||||||
|
| 枚举值 | 含义 | 处置 |
|
||||||
|
|---|---|---|
|
||||||
|
| `unchanged` | 三方一致或语义等价 | 直接采用 A 稿 |
|
||||||
|
| `minor_edit` | 标点 / 顿号 / 简称差异 | 自动以 ASR 版本输出 |
|
||||||
|
| `term_normalize` | 术语 / 字形 / 同音修正 | 规则层处理 |
|
||||||
|
| `rewrite_large` | 整段重写(A 稿与播出版差异较大) | AI 层处理 + **建议编导确认** |
|
||||||
|
| `segment_delete` | A 稿有但播出无 | AI 层判定 + **建议编导确认** |
|
||||||
|
| `segment_add` | A 稿无但播出有 | AI 层判定 + **建议编导确认** |
|
||||||
|
| `editor_typo` | A 稿编导笔误(整段重复 / 明显错位) | AI 层提示 + **必须编导确认** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 模块架构
|
||||||
|
|
||||||
|
### 4.1 顶层流程
|
||||||
|
|
||||||
|
```
|
||||||
|
┌───────────────────────────────────────────────────┐
|
||||||
|
│ 三方融合引擎(本子模块) │
|
||||||
|
│ │
|
||||||
|
A 稿 ──────►│ 解析层 ──► 段落对齐层 ──► 规则纠错层 ──► AI 融合 │──► 终版docx
|
||||||
|
B 稿 ──────►│ ↓ │──► 差异报告
|
||||||
|
ASR ──────►│ [Claude API] │
|
||||||
|
└───────────────────────────────────────────────────┘
|
||||||
|
▲
|
||||||
|
│
|
||||||
|
[A 稿术语表 / OCR 错字字典 / 口语词字典]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 各层职责
|
||||||
|
|
||||||
|
#### 解析层(parser)
|
||||||
|
- A 稿:按 `【…】` 切段,识别隔断标签,输出 `[(label, text)]`
|
||||||
|
- B 稿 / ASR:按 `[Nm Ns]` 行切句,输出 `[(start_ms, end_ms, text)]`
|
||||||
|
|
||||||
|
#### 段落对齐层(aligner)
|
||||||
|
- 目标:把 B 稿 / ASR 的句子聚合并归到 A 稿的段落标签下
|
||||||
|
- 算法:
|
||||||
|
- **强信号**:通过 A 稿首末锚点句做语义匹配(demo 用了人工锚点列表,正式版应用 Claude API 做语义匹配)
|
||||||
|
- **弱信号**:时间戳的单调推进
|
||||||
|
- 容错:允许 ±5 秒漂移、允许中间出现专家发言被识别为"解说"
|
||||||
|
|
||||||
|
#### 规则纠错层(rule-based corrector)
|
||||||
|
- **A 稿术语字典**:从 A 稿提取专有名词,扫描 ASR / B 稿,发现字形不同但拼音相同的同音字 → 用 A 稿覆盖
|
||||||
|
- **OCR 错字字典**:维护固定映射表(肘→时、娈→变、夭→天…),扫描 B 稿
|
||||||
|
- **数字规范化**:`百%` → `100%`、`数10` → `数十`、`马赫数10` → `10马赫`
|
||||||
|
- **标点规范化**:去重逗号、补齐句号
|
||||||
|
|
||||||
|
#### AI 融合层(Claude API)
|
||||||
|
- 输入:经规则层处理后的三方对齐结果
|
||||||
|
- 任务:
|
||||||
|
1. 段落对齐的最终校验(解决规则层算不准的边界)
|
||||||
|
2. 改动类型标记(`unchanged` / `minor_edit` / `rewrite_large` / `segment_delete` / `segment_add` / `editor_typo`)
|
||||||
|
3. 高把握改动直接产出终版
|
||||||
|
4. 低把握改动标记原因 + 给编导待确认列表
|
||||||
|
- 提示词要点:见 §6
|
||||||
|
|
||||||
|
### 4.3 双层划分的依据
|
||||||
|
|
||||||
|
| 任务 | 走哪层 | 理由 |
|
||||||
|
|---|---|---|
|
||||||
|
| OCR 错字纠正 | 规则层 | 字形错误是确定性映射 |
|
||||||
|
| 术语统一 | 规则层 | A 稿术语表是封闭集 |
|
||||||
|
| 时间戳对齐 | 规则层 | 数值比较 |
|
||||||
|
| 段落归属 | AI 层 | 需要语义判断("这句专家发言到底归【专家3】还是【解说5】") |
|
||||||
|
| 整段删除判定 | AI 层 | 需要判断"A 稿这一段,是否在 B 稿 + ASR 都找不到对应内容" |
|
||||||
|
| 编导笔误识别 | AI 层 | 需要"【专家7】【专家8】内容相同" + "ASR 第 N 句到第 M 句讲了完全不同的内容"的联合判断 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 关键决策与参数
|
||||||
|
|
||||||
|
### 5.1 三方冲突时的优先级
|
||||||
|
|
||||||
|
| 冲突类型 | 优先采用 | 例 |
|
||||||
|
|---|---|---|
|
||||||
|
| 术语 / 人名 / 装备型号 | **A 稿** | "美以两国"(ASR 错识"美伊") |
|
||||||
|
| 标点 / 句式 / 口吻 | **ASR** | "各位观众你们好"(A 稿"观众朋友们,你们好") |
|
||||||
|
| 字形错字 | **ASR / A 稿** 覆盖 B 稿 | "肘→时""纺空→防空" |
|
||||||
|
| 整段存在性 | **B 稿 + ASR 联合** 优先 | A 稿"雷达被誉为眼睛..."B 稿/ASR 都没有 → 删 |
|
||||||
|
| 数字 / 百分比 | **ASR**(已确认 ASR 100% 准确) | "5%"、"100%" |
|
||||||
|
| 同音 / 字形错 | **A 稿术语字典** | "中端→中段""高超声速→高超音速" |
|
||||||
|
|
||||||
|
### 5.2 时间戳容忍度
|
||||||
|
|
||||||
|
- 同段判定:B 稿 / ASR 时间戳差 ≤ **5 秒** 视为同一播出位置
|
||||||
|
- 锚点匹配:A 稿首句对应的 ASR 时间位置 ± **10 秒** 为搜索窗
|
||||||
|
|
||||||
|
### 5.3 口语词清理档位(可配置)
|
||||||
|
|
||||||
|
| 档位 | 行为 | 适用场景 |
|
||||||
|
|---|---|---|
|
||||||
|
| `keep_all` | 完全保留"那么""呢""啊""这个" | 反映播出真相、用于事后复盘 |
|
||||||
|
| `medium`(**默认**) | 保留专家段口语词,清理解说段 | 平衡可读性与真实性 |
|
||||||
|
| `clean` | 全部清理,按 A 稿书面化 | 用于外部传播 / 文稿出版 |
|
||||||
|
|
||||||
|
### 5.4 改动确信度阈值
|
||||||
|
|
||||||
|
- AI 判定结果带 `confidence ∈ [0,1]`
|
||||||
|
- `confidence ≥ 0.85`:自动应用,记入差异报告
|
||||||
|
- `0.6 ≤ confidence < 0.85`:自动应用 + **黄色标记**,编导可在 UI 中翻看
|
||||||
|
- `confidence < 0.6`:**不自动应用**,进入编导待确认队列
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. AI 融合层提示词设计纲要
|
||||||
|
|
||||||
|
提示词应包含以下要素(正式实现时按需扩展):
|
||||||
|
|
||||||
|
```
|
||||||
|
[系统角色]
|
||||||
|
你是《军事科技》节目终版文稿生成助手。已知:
|
||||||
|
- A 稿是编导手写定稿,术语 / 人名 / 装备型号权威
|
||||||
|
- ASR 是讯飞录音转写,标点与口吻接近播出真相,但存在同音误识
|
||||||
|
- B 稿是 OCR 扒词,存在字形错字,用作交叉验证
|
||||||
|
三方冲突时按"§5.1 三方冲突优先级"裁决。
|
||||||
|
|
||||||
|
[输入]
|
||||||
|
A 稿全文(含 【…】 标签):{a_doc}
|
||||||
|
ASR 结果(带时间戳):{asr_sentences}
|
||||||
|
B 稿 OCR(带时间戳):{b_sentences}
|
||||||
|
A 稿术语表:{terms_dict}
|
||||||
|
OCR 错字字典:{ocr_typos}
|
||||||
|
口语清理档位:{level}
|
||||||
|
|
||||||
|
[任务]
|
||||||
|
1. 把 ASR / B 稿的句子按时间顺序聚合并归到 A 稿的段落标签下
|
||||||
|
2. 对每段标记改动类型(unchanged / minor_edit / rewrite_large / segment_delete / segment_add / editor_typo)
|
||||||
|
3. 对每段给出 confidence ∈ [0,1]
|
||||||
|
4. 对 confidence ≥ 0.85 的段落直接产出终版文本
|
||||||
|
5. 对 confidence < 0.85 的段落产出"建议版本 + 待确认原因"
|
||||||
|
6. 识别 A 稿与 ASR 的术语 / 同音 / 字形差异,自动应用 A 稿权威
|
||||||
|
7. 识别 A 稿的编导笔误(如整段复制粘贴)并标记
|
||||||
|
|
||||||
|
[输出]
|
||||||
|
JSON:
|
||||||
|
{
|
||||||
|
"segments": [
|
||||||
|
{
|
||||||
|
"label": "【主持人1】",
|
||||||
|
"change_type": "rewrite_large",
|
||||||
|
"confidence": 0.92,
|
||||||
|
"final_text": "...",
|
||||||
|
"evidence": {"asr_lines": [...], "b_lines": [...]},
|
||||||
|
"reasons": ["A 稿首句被改写为口语化"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"needs_review": [...]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 外部依赖
|
||||||
|
|
||||||
|
### 7.1 讯飞 ASR(必需)
|
||||||
|
|
||||||
|
- **服务**:讯飞开放平台「**录音文件转写(标准版)**」
|
||||||
|
- **不要用**:讯飞「大模型版」——免费包阉割了 `language` 参数,会报误导性的 `language verify fail`
|
||||||
|
- **认证**:APP_ID + SECRET_KEY;本期 demo 已申请到一组测试凭证(见 `xfyun_asr_standard.py`,正式上线需替换)
|
||||||
|
- **音频规格**:**16kHz / 单声道 / 16bit WAV**;其他规格讯飞会拒收
|
||||||
|
- **领域参数**:`pd=mil`(军事节目专用,提升术语识别率)
|
||||||
|
- **顺滑参数**:`eng_smoothproc=true` + `eng_colloqproc=true`
|
||||||
|
- **热词机制(关键)**:
|
||||||
|
- 每期节目从 A 稿提取专业术语(武器装备 / 技术概念 / 人名 / 军方机构),上限 200 个,每个 2–16 字
|
||||||
|
- 用 `|` 分隔传入 `hotWord` 参数
|
||||||
|
- demo 实测 35 个热词后,关键术语识别率接近 100%
|
||||||
|
- **计费**:0元购买"5 小时免费试用包"(注意:看到额度但未走 0 元购买流程**不会激活**),1 年有效期
|
||||||
|
- **签名算法**:`signa = base64(HmacSHA1(MD5(appid + ts), secretKey))`
|
||||||
|
|
||||||
|
详见 `xfyun_asr_standard.py`(demo 已跑通的本地脚本,可直接作为正式适配层的起点)。
|
||||||
|
|
||||||
|
### 7.2 Claude API(必需)
|
||||||
|
|
||||||
|
- 用于 AI 融合层
|
||||||
|
- 调用模型:建议 `claude-sonnet-4-6` 或更高(涉及长文本理解与语义对齐)
|
||||||
|
- 单期节目(26 分钟)的预估上下文:A 稿 ~6k 字 + ASR ~5k 字 + B 稿 ~5k 字 ≈ 16k 字,远在 Sonnet 上下文窗口内
|
||||||
|
- 调用频次:每期节目 1–3 次(首次全量融合 + 若干次低确信段重判)
|
||||||
|
|
||||||
|
### 7.3 OCR 服务(已有)
|
||||||
|
|
||||||
|
- B 稿来自上游既有 OCR 流程
|
||||||
|
- 本模块只消费 B 稿 txt,不调用 OCR 服务
|
||||||
|
|
||||||
|
### 7.4 密钥管理
|
||||||
|
|
||||||
|
> **opus_chat 注意**:以下是常见混淆点,请勿用错。
|
||||||
|
|
||||||
|
| 密钥 | 用途 | 来源 |
|
||||||
|
|---|---|---|
|
||||||
|
| 讯飞 **消费端** | 讯飞听见 App(人工录音转写) | 讯飞听见 App 内 |
|
||||||
|
| 讯飞 **开发端** | 录音文件转写 API(本模块用) | 讯飞**开放平台** console |
|
||||||
|
| Claude API | AI 融合层 | Anthropic console |
|
||||||
|
|
||||||
|
三套密钥**互不相通**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 编导确认 UI(属于上层 UI 子模块,本模块只提供数据)
|
||||||
|
|
||||||
|
本模块按以下结构输出供 UI 子模块消费的 JSON:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"program_id": "xxx",
|
||||||
|
"segments": [...],
|
||||||
|
"needs_review": [
|
||||||
|
{
|
||||||
|
"segment_label": "【解说6】",
|
||||||
|
"reason": "整段改写边界不确定",
|
||||||
|
"candidates": [
|
||||||
|
{"text": "...", "source": "A稿"},
|
||||||
|
{"text": "...", "source": "ASR"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"diff_report_path": "...",
|
||||||
|
"final_docx_path": "..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
UI 子模块应至少提供(参考 demo 复盘 §3.4):
|
||||||
|
|
||||||
|
- **左中右三栏 diff 视图**:A 稿原文 | 终版 | ASR/B 稿(带时间戳,可点击播放对应音频)
|
||||||
|
- **改动类型颜色编码**:删除红 / 改写黄 / 术语修正蓝 / 无变化白
|
||||||
|
- **逐段确认按钮**:接受 / 拒绝 / 编辑 / 标记疑问
|
||||||
|
- **口语清理强度滑杆**:切换 `keep_all / medium / clean`
|
||||||
|
- **导出按钮**:终版 docx / 差异报告 / 复盘 CSV
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 数据资产
|
||||||
|
|
||||||
|
### 9.1 应入库的"中台共享资产"
|
||||||
|
|
||||||
|
1. **A 稿术语表**(核心资产)
|
||||||
|
- 每期节目处理时从 A 稿提取后入库
|
||||||
|
- 同时作为讯飞热词来源 + 规则层纠错字典
|
||||||
|
- 字段:`term`, `domain`(武器 / 技术 / 人名 / 机构 / 栏目),`first_seen_episode`, `frequency`
|
||||||
|
2. **OCR 错字映射表**
|
||||||
|
- 固定字形混淆对(肘↔时、娈↔变、夭↔天…)
|
||||||
|
- 随版本演进可扩展
|
||||||
|
3. **节目编导风格档案**
|
||||||
|
- 长期累积每位编导的删改偏好(口语词保留度、术语简称习惯…)
|
||||||
|
- 用于参数自适应
|
||||||
|
|
||||||
|
### 9.2 demo 阶段产物的处置建议
|
||||||
|
|
||||||
|
| 文件 | 处置 |
|
||||||
|
|---|---|
|
||||||
|
| `xfyun_asr_standard.py` | 作为 ASR 适配层的起点代码 |
|
||||||
|
| `asr_result_timed.txt` | 单元测试 fixture |
|
||||||
|
| `B稿_..._扒词.txt` | 单元测试 fixture(含典型 OCR 错字) |
|
||||||
|
| `A稿_..._定稿.docx` | 单元测试 fixture |
|
||||||
|
| `现代防空反导大对决_终版.docx` | 集成测试**期望输出**(黄金对照) |
|
||||||
|
| `差异报告.docx` | 集成测试**期望输出**(差异报告格式参考) |
|
||||||
|
| `实测复盘.md` | 设计文档背书 + 长期归档 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 性能与耗时基线(实测)
|
||||||
|
|
||||||
|
来自 demo(26 分钟节目):
|
||||||
|
|
||||||
|
| 阶段 | 耗时 | 占比 |
|
||||||
|
|---|---|---|
|
||||||
|
| 讯飞 ASR 转写 | ~5 分钟 | — |
|
||||||
|
| 三方解析 | ~5 分钟 | — |
|
||||||
|
| 段落对齐 | ~15 分钟(demo 手工) | 正式版预计 ≤2 分钟(AI 调用) |
|
||||||
|
| 术语规范化 + 口语清理 | ~5 分钟 | — |
|
||||||
|
| 终版 docx 生成 | ~5 分钟 | — |
|
||||||
|
| 差异报告生成 | ~15 分钟(demo 手工) | 正式版预计 ≤3 分钟 |
|
||||||
|
| **正式版预估单期** | **~15–30 分钟** | 取决于改动幅度与人工确认次数 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. 已知风险与未决事项
|
||||||
|
|
||||||
|
| 项 | 当前态 | 建议 |
|
||||||
|
|---|---|---|
|
||||||
|
| ASR 第三方依赖 | 讯飞单源 | 接入阿里云 ASR 做备份 / 交叉验证 |
|
||||||
|
| 整段改写的边界 | demo 中默认取 ASR 短版 | 必须接入编导确认 UI,不能全自动 |
|
||||||
|
| 编导风格差异 | 硬编码"中度清理" | 需配置文件或编导画像 |
|
||||||
|
| 隔断标签的处置 | demo 直接保留 A 稿 | 待确认是否需要根据音频静音段重新切分 |
|
||||||
|
| A 稿与 ASR 都缺失的旁白 | 不处理 | 极小概率事件,靠 B 稿兜底;记录用例 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. 给 opus_chat 的提示(重要)
|
||||||
|
|
||||||
|
如果 opus_chat 在其他场景中被问到本模块,请按以下口径回答:
|
||||||
|
|
||||||
|
1. **本模块的边界**:只做"三方文本 → 终版文稿 + 差异报告",不负责音频转码、不负责 OCR、不负责档案入库、不负责编导 UI。
|
||||||
|
2. **依赖与约束**:依赖讯飞 ASR(标准版)和 Claude API;A 稿术语表必须先入库;音频规格必须 16kHz/单声道/16bit WAV。
|
||||||
|
3. **三方权威优先级**:A 稿(术语)> ASR(口吻)> B 稿(验证);任何与此相反的处理都是 bug。
|
||||||
|
4. **未来扩展**:编导风格画像、第二 ASR 供应商、口语清理档位是后续路标。
|
||||||
|
|
||||||
|
如遇到与本文档不一致的描述,**以本文档为准**;如发现本文档需要更新,请同步刘统制片组。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录 A:项目文件清单(demo 阶段)
|
||||||
|
|
||||||
|
```
|
||||||
|
project/
|
||||||
|
├── A稿_现代防空反导大对决_定稿.docx # 输入1:编导定稿
|
||||||
|
├── B稿_现代防空反导大对决_扒词.txt # 输入2:OCR扒词
|
||||||
|
├── asr_result_timed.txt # 输入3:讯飞ASR输出
|
||||||
|
├── xfyun_asr_standard.py # ASR调用脚本
|
||||||
|
├── 现代防空反导大对决_终版.docx # 输出1:终版文稿
|
||||||
|
├── 差异报告.docx # 输出2:差异报告
|
||||||
|
├── 实测复盘.md # demo复盘(设计文档原料)
|
||||||
|
└── project_design.md # 本文档
|
||||||
|
```
|
||||||
|
|
||||||
|
## 附录 B:与"实测复盘.md"的对应关系
|
||||||
|
|
||||||
|
| 复盘章节 | 本文档对应位置 |
|
||||||
|
|---|---|
|
||||||
|
| 一、ASR环节实测数据 | §7.1 讯飞 ASR |
|
||||||
|
| 二、三方融合关键决策点 | §5 关键决策与参数 |
|
||||||
|
| 三、对正式开发的启示 | §4 模块架构 / §6 提示词设计 / §8 UI |
|
||||||
|
| 四、实测耗时分解 | §10 性能基线 |
|
||||||
|
| 五、给制片人的建议 | §9 数据资产 / §11 风险 |
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
# 讯飞 ASR 集成踩坑笔记
|
||||||
|
|
||||||
|
> demo 期间累积的所有讯飞接入坑点。建议入 TPS 知识库,作为未来接入新 ASR 供应商时的对照。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 选型坑
|
||||||
|
|
||||||
|
### 坑 1:不要用"大模型版"
|
||||||
|
|
||||||
|
- 讯飞开放平台有两个录音转写产品:
|
||||||
|
- 「录音文件转写(**标准版**)」← **用这个**
|
||||||
|
- 「录音文件转写(**大模型版**)」← 不要用
|
||||||
|
- **大模型版的免费包阉割了 `language` 参数**,调用时会报 `language verify fail`
|
||||||
|
- 这个错误信息**严重误导**:看上去是语种没设对,实际是免费包没开通该参数权限
|
||||||
|
- 排查耗时:约 30 分钟
|
||||||
|
|
||||||
|
### 坑 2:消费端和开发端密钥不通
|
||||||
|
|
||||||
|
- 「讯飞听见 App」属于**消费端**,给最终用户做人工转写用
|
||||||
|
- 「讯飞开放平台」属于**开发端**,给开发者调 API 用
|
||||||
|
- **两套密钥互不相通**——开发端的 APP_ID 在消费端没用,反之亦然
|
||||||
|
- 如果只在讯飞听见 App 注册了账号,**没有** APP_ID 和 SecretKey,必须再去开放平台注册一次
|
||||||
|
|
||||||
|
### 坑 3:免费额度不会自动激活
|
||||||
|
|
||||||
|
- 开放平台首页显示"5 小时免费试用包",但**只有走 0 元购买流程**才会激活
|
||||||
|
- 看到额度但没下单 → 调用时会报余额不足
|
||||||
|
- 流程:商品页 → 0 元下单 → 支付(实际免费)→ 额度到账
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 音频规格坑
|
||||||
|
|
||||||
|
### 坑 4:必须是 16kHz / 单声道 / 16bit WAV
|
||||||
|
|
||||||
|
- 其他规格讯飞会报错(且错误信息可能误导成"language verify fail"或"audio decode error")
|
||||||
|
- MP3 在标准版**也支持**,但保险起见统一转 WAV
|
||||||
|
- 转码命令(ffmpeg):
|
||||||
|
```bash
|
||||||
|
ffmpeg -i input.mp3 -ac 1 -ar 16000 -sample_fmt s16 output_16k_mono.wav
|
||||||
|
```
|
||||||
|
- `-ac 1` = 单声道
|
||||||
|
- `-ar 16000` = 16kHz 采样率
|
||||||
|
- `-sample_fmt s16` = 16bit 位深
|
||||||
|
|
||||||
|
### 坑 5:时长字段不严格校验但建议传准
|
||||||
|
|
||||||
|
- API 要求传 `duration`(毫秒)
|
||||||
|
- 实测哪怕传 0 也能上传成功,但官方文档建议传准确值
|
||||||
|
- WAV 从文件头读:`n_frames / sample_rate * 1000`
|
||||||
|
- MP3 用 `mutagen.mp3.MP3` 读
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 接口坑
|
||||||
|
|
||||||
|
### 坑 6:签名算法是老式 HmacSHA1,不是常见的 HmacSHA256
|
||||||
|
|
||||||
|
```python
|
||||||
|
# signa = base64(HmacSHA1(MD5(appid + ts), secretKey))
|
||||||
|
md5_str = hashlib.md5((appid + ts).encode("utf-8")).hexdigest() # 32 位小写 hex
|
||||||
|
mac = hmac.new(secret_key.encode("utf-8"), md5_str.encode("utf-8"),
|
||||||
|
digestmod=hashlib.sha1)
|
||||||
|
signa = base64.b64encode(mac.digest()).decode("utf-8")
|
||||||
|
```
|
||||||
|
|
||||||
|
注意:
|
||||||
|
- MD5 输出是**32 位小写 hex 字符串**,不是 16 字节 raw bytes
|
||||||
|
- HMAC 的 key 是 `secretKey`,data 是 MD5 字符串本身(不是其字节)
|
||||||
|
- 最后做 base64 编码
|
||||||
|
|
||||||
|
### 坑 7:参数全部走 URL query,不是 form-data 或 JSON body
|
||||||
|
|
||||||
|
- 上传接口:`POST https://raasr.xfyun.cn/v2/api/upload?appId=...&signa=...&ts=...&...`
|
||||||
|
- `Content-Type: application/json`,但**请求体是音频原始字节流**(不是 JSON)
|
||||||
|
- 所有业务参数(`fileSize` `fileName` `duration` `language` `pd` `hotWord` …)都在 URL query 里
|
||||||
|
- 中文热词必须做 URL encode:`quote(hot_word_str, safe='')`
|
||||||
|
|
||||||
|
### 坑 8:热词用 `|` 分隔,不是逗号
|
||||||
|
|
||||||
|
```python
|
||||||
|
hot_word_str = "|".join(HOT_WORDS) # 萨德|爱国者|标准-6|...
|
||||||
|
params["hotWord"] = hot_word_str
|
||||||
|
```
|
||||||
|
|
||||||
|
限制:
|
||||||
|
- 最多 200 个热词
|
||||||
|
- 每个热词 2–16 字
|
||||||
|
- 整个 hotWord 参数 URL encode 后不能超过某个长度(实测 35 个常规军事术语没问题)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 异步查询坑
|
||||||
|
|
||||||
|
### 坑 9:轮询用 POST 不是 GET
|
||||||
|
|
||||||
|
- 查询结果接口:`POST https://raasr.xfyun.cn/v2/api/getResult?...`
|
||||||
|
- 即便没有 body 也是 POST
|
||||||
|
- 用 GET 会报方法不允许
|
||||||
|
|
||||||
|
### 坑 10:status 状态码语义
|
||||||
|
|
||||||
|
| status | 含义 |
|
||||||
|
|---|---|
|
||||||
|
| 0 | 待处理 |
|
||||||
|
| 1 | 处理中 |
|
||||||
|
| 4 | **完成** |
|
||||||
|
| -1 | 失败 |
|
||||||
|
|
||||||
|
完成是 `4`,不是 `2` 也不是 `200`。
|
||||||
|
|
||||||
|
### 坑 11:轮询间隔与超时
|
||||||
|
|
||||||
|
- 26 分钟音频实测转写耗时约 5 分钟
|
||||||
|
- 推荐轮询间隔 30 秒(taskEstimateTime 返回的预估值仅供参考)
|
||||||
|
- 超时上限设 30 分钟比较保险
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 结果解析坑
|
||||||
|
|
||||||
|
### 坑 12:返回结果是双层嵌套 JSON 字符串
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 外层
|
||||||
|
data = response.json()
|
||||||
|
order_result_str = data["content"]["orderResult"] # 这是 JSON 字符串
|
||||||
|
|
||||||
|
# 中间还有一层反斜杠转义
|
||||||
|
cleaned = re.sub(r"\\\\", r"\\", order_result_str)
|
||||||
|
outer = json.loads(cleaned)
|
||||||
|
|
||||||
|
# 句子在 outer["lattice"] 里
|
||||||
|
for item in outer["lattice"]:
|
||||||
|
inner_str = item["json_1best"] # 又是 JSON 字符串
|
||||||
|
inner = json.loads(inner_str)
|
||||||
|
# 句子时间在 inner["st"]["bg"] / inner["st"]["ed"]
|
||||||
|
# 句子内容在 inner["st"]["rt"][..]["ws"][..]["cw"][..]["w"]
|
||||||
|
```
|
||||||
|
|
||||||
|
每个 `cw` 是一个字 / 词;要拼接所有 `cw["w"]`(跳过 `wp == "g"` 的空白标记)。
|
||||||
|
|
||||||
|
### 坑 13:时间戳单位是毫秒(不是秒、不是百分秒)
|
||||||
|
|
||||||
|
- `bg` `ed` 都是毫秒(int)
|
||||||
|
- 与 B 稿的 `[Nm Ns]` 对齐时记得换算
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 业务参数坑
|
||||||
|
|
||||||
|
### 坑 14:`pd=mil` 对军事术语显著加分
|
||||||
|
|
||||||
|
- 不开 `pd`:默认通用领域,军事术语会被识别成同音常见词
|
||||||
|
- 开 `pd=mil`:军事领域专用模型介入,配合热词效果叠加
|
||||||
|
|
||||||
|
### 坑 15:`eng_smoothproc` + `eng_colloqproc` 让 ASR 接近书面
|
||||||
|
|
||||||
|
- `eng_smoothproc=true`:去掉"嗯""那个""呃"
|
||||||
|
- `eng_colloqproc=true`:口语规整("咱们"→"我们"等)
|
||||||
|
- 两个都开后,输出已经非常接近书面文稿
|
||||||
|
- 但**不会清理"那么""呢""啊""这个"**——这些保留与否需要在融合层决定
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 凭证与配额(demo 阶段使用)
|
||||||
|
|
||||||
|
```
|
||||||
|
APP_ID: 84eff996
|
||||||
|
SECRET_KEY: d37fb0c77e7f4b4f4398e6a8834d1017
|
||||||
|
免费包: 5 小时(已激活),有效期至 2027 年 5 月
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ **正式上线时替换为生产凭证**,并把 SECRET_KEY 从代码移到环境变量 / 密钥管理服务。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一句话总结
|
||||||
|
|
||||||
|
讯飞 ASR 标准版**能用、好用**,但接入文档稀少且错误信息误导性强;以上 15 个坑全部踩完后,单次调用的成功率接近 100%。后续接入新 ASR 供应商时,建议按本笔记的结构(选型 / 音频 / 接口 / 异步 / 解析 / 业务参数 / 凭证)做同样的整理。
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,345 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
讯飞 录音文件转写(标准版)- 本地运行脚本
|
||||||
|
=================================================
|
||||||
|
用途:将节目音频转为带时间戳的文本,用于TPS中台三方融合demo。
|
||||||
|
|
||||||
|
接口:https://raasr.xfyun.cn/v2/api/upload / getResult
|
||||||
|
签名:signa = base64(HmacSHA1(MD5(appid + ts), secretKey))
|
||||||
|
|
||||||
|
特性:
|
||||||
|
- 支持热词列表(hotWord),提升专业术语识别率
|
||||||
|
- 支持军事领域参数(pd=mil)
|
||||||
|
- 支持顺滑+口语规整(输出更接近书面语)
|
||||||
|
- 默认语种 cn(中文普通话),免费包标配,无需 autodialect
|
||||||
|
|
||||||
|
依赖:pip install requests
|
||||||
|
|
||||||
|
输出文件(与脚本同目录):
|
||||||
|
asr_result_raw.json - 讯飞原始返回
|
||||||
|
asr_result_full.txt - 纯文本
|
||||||
|
asr_result_timed.txt - 带时间戳的文本(格式同B稿)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import hmac
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import wave
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# 配置区 —— 填写凭证 + 音频路径
|
||||||
|
# ========================================================================
|
||||||
|
|
||||||
|
# 老版只用 APPID + SecretKey 两个字段
|
||||||
|
APP_ID = "84eff996"
|
||||||
|
SECRET_KEY = "在此填入您的SecretKey"
|
||||||
|
|
||||||
|
# 音频文件——可以用之前转好的WAV,也可以直接用mp3(讯飞标准版mp3也支持)
|
||||||
|
AUDIO_FILE = "现代防空反导大对决音频_16k_mono.wav"
|
||||||
|
|
||||||
|
# 自动去除空白
|
||||||
|
APP_ID = APP_ID.strip()
|
||||||
|
SECRET_KEY = SECRET_KEY.strip()
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# 接口配置
|
||||||
|
# ========================================================================
|
||||||
|
|
||||||
|
HOST = "https://raasr.xfyun.cn/v2/api"
|
||||||
|
UPLOAD_URL = HOST + "/upload"
|
||||||
|
RESULT_URL = HOST + "/getResult"
|
||||||
|
|
||||||
|
# 业务参数
|
||||||
|
LANGUAGE = "cn" # 中文普通话
|
||||||
|
PD = "mil" # 军事领域优化
|
||||||
|
ENG_SMOOTHPROC = "true" # 顺滑(去掉"嗯/那个")
|
||||||
|
ENG_COLLOQPROC = "true" # 口语规整
|
||||||
|
|
||||||
|
# 热词列表——节目里出现的关键专业术语(讯飞限制200个热词,每个2-16字)
|
||||||
|
# 我从A稿提取了下面这批,能显著提升识别准确率
|
||||||
|
HOT_WORDS = [
|
||||||
|
# 武器装备
|
||||||
|
"萨德", "爱国者", "标准-6", "铁穹", "塔米尔",
|
||||||
|
"大卫投石索", "箭式", "箭-2", "箭-3",
|
||||||
|
"霍拉姆沙赫尔-4", "见证者-136", "卡桑", "泥石",
|
||||||
|
"C-17", "飞毛腿", "M270",
|
||||||
|
# 技术概念
|
||||||
|
"高超音速", "弹道导弹", "巡航导弹", "无人机蜂群",
|
||||||
|
"中段反导", "饱和攻击", "动能撞击", "诱饵弹",
|
||||||
|
"相控阵雷达", "电子战", "外大气层",
|
||||||
|
# 事件军方
|
||||||
|
"真实承诺-4", "伊斯兰革命卫队", "本·古里安", "拉斐尔",
|
||||||
|
"黎巴嫩真主党", "波斯湾",
|
||||||
|
# 节目栏目
|
||||||
|
"军事科技",
|
||||||
|
]
|
||||||
|
|
||||||
|
# 轮询配置
|
||||||
|
POLL_INTERVAL_SECONDS = 30
|
||||||
|
MAX_WAIT_MINUTES = 30
|
||||||
|
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# 签名+工具
|
||||||
|
# ========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
def make_signa(app_id, secret_key, ts):
|
||||||
|
"""
|
||||||
|
讯飞老版签名:signa = base64(HmacSHA1(MD5(appid + ts), secretKey))
|
||||||
|
"""
|
||||||
|
base_string = (app_id + ts).encode("utf-8")
|
||||||
|
md5_str = hashlib.md5(base_string).hexdigest() # 32位小写hex
|
||||||
|
mac = hmac.new(
|
||||||
|
secret_key.encode("utf-8"),
|
||||||
|
md5_str.encode("utf-8"),
|
||||||
|
digestmod=hashlib.sha1,
|
||||||
|
)
|
||||||
|
signa = base64.b64encode(mac.digest()).decode("utf-8")
|
||||||
|
return signa
|
||||||
|
|
||||||
|
|
||||||
|
def get_audio_duration_ms(filepath):
|
||||||
|
"""获取音频时长(毫秒)。WAV用内置,MP3用mutagen。"""
|
||||||
|
ext = os.path.splitext(filepath)[1].lower()
|
||||||
|
|
||||||
|
if ext == ".wav":
|
||||||
|
with wave.open(filepath, "rb") as wf:
|
||||||
|
n_frames = wf.getnframes()
|
||||||
|
sample_rate = wf.getframerate()
|
||||||
|
duration_ms = int(round(n_frames / sample_rate * 1000))
|
||||||
|
print(f"[info] WAV规格: {sample_rate}Hz, 声道={wf.getnchannels()}, 位深={wf.getsampwidth()*8}bit")
|
||||||
|
return duration_ms
|
||||||
|
|
||||||
|
if ext == ".mp3":
|
||||||
|
try:
|
||||||
|
from mutagen.mp3 import MP3
|
||||||
|
return int(MP3(filepath).info.length * 1000)
|
||||||
|
except ImportError:
|
||||||
|
print("[warn] mutagen未安装,时长按0传——讯飞文档说该字段不严格校验")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
raise ValueError(f"不支持的音频格式: {ext}")
|
||||||
|
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# 上传
|
||||||
|
# ========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
def upload_audio(filepath):
|
||||||
|
"""上传音频,返回 orderId"""
|
||||||
|
if not os.path.exists(filepath):
|
||||||
|
raise FileNotFoundError(f"音频文件不存在: {filepath}")
|
||||||
|
|
||||||
|
file_size = os.path.getsize(filepath)
|
||||||
|
file_name = os.path.basename(filepath)
|
||||||
|
duration_ms = get_audio_duration_ms(filepath)
|
||||||
|
ts = str(int(time.time()))
|
||||||
|
|
||||||
|
signa = make_signa(APP_ID, SECRET_KEY, ts)
|
||||||
|
print(f"[info] ts={ts}, signa={signa}")
|
||||||
|
print(f"[info] 文件: {file_name}, {file_size/1024/1024:.2f}MB, {duration_ms/1000:.1f}秒")
|
||||||
|
|
||||||
|
# 构建URL参数
|
||||||
|
params = {
|
||||||
|
"appId": APP_ID,
|
||||||
|
"signa": signa,
|
||||||
|
"ts": ts,
|
||||||
|
"fileSize": str(file_size),
|
||||||
|
"fileName": file_name,
|
||||||
|
"duration": str(duration_ms),
|
||||||
|
"language": LANGUAGE,
|
||||||
|
"pd": PD,
|
||||||
|
"eng_smoothproc": ENG_SMOOTHPROC,
|
||||||
|
"eng_colloqproc": ENG_COLLOQPROC,
|
||||||
|
}
|
||||||
|
|
||||||
|
# 热词,用 | 分隔
|
||||||
|
if HOT_WORDS:
|
||||||
|
hot_word_str = "|".join(HOT_WORDS)
|
||||||
|
params["hotWord"] = hot_word_str
|
||||||
|
print(f"[info] 热词数量: {len(HOT_WORDS)} 个")
|
||||||
|
|
||||||
|
url_parts = [f"{quote(k, safe='')}={quote(str(v), safe='')}" for k, v in params.items()]
|
||||||
|
url = f"{UPLOAD_URL}?{'&'.join(url_parts)}"
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
|
||||||
|
with open(filepath, "rb") as f:
|
||||||
|
audio_bytes = f.read()
|
||||||
|
|
||||||
|
print(f"[info] 正在上传... ({file_size/1024/1024:.1f}MB)")
|
||||||
|
resp = requests.post(url, headers=headers, data=audio_bytes, timeout=300)
|
||||||
|
print(f"[info] HTTP状态: {resp.status_code}")
|
||||||
|
|
||||||
|
data = resp.json()
|
||||||
|
print(f"[info] 响应: {json.dumps(data, ensure_ascii=False, indent=2)}")
|
||||||
|
|
||||||
|
if data.get("code") != "000000":
|
||||||
|
raise RuntimeError(f"上传失败: code={data.get('code')}, desc={data.get('descInfo')}")
|
||||||
|
|
||||||
|
order_id = data["content"]["orderId"]
|
||||||
|
estimate_ms = data["content"].get("taskEstimateTime", 0)
|
||||||
|
print(f"\n[ok] orderId = {order_id}")
|
||||||
|
print(f"[ok] 预估完成时间: {estimate_ms/1000:.1f}秒\n")
|
||||||
|
return order_id
|
||||||
|
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# 查询结果
|
||||||
|
# ========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
def query_result(order_id):
|
||||||
|
"""单次查询"""
|
||||||
|
ts = str(int(time.time()))
|
||||||
|
signa = make_signa(APP_ID, SECRET_KEY, ts)
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"appId": APP_ID,
|
||||||
|
"signa": signa,
|
||||||
|
"ts": ts,
|
||||||
|
"orderId": order_id,
|
||||||
|
"resultType": "transfer",
|
||||||
|
}
|
||||||
|
url_parts = [f"{quote(k, safe='')}={quote(str(v), safe='')}" for k, v in params.items()]
|
||||||
|
url = f"{RESULT_URL}?{'&'.join(url_parts)}"
|
||||||
|
|
||||||
|
resp = requests.post(url, timeout=30)
|
||||||
|
return resp.json()
|
||||||
|
|
||||||
|
|
||||||
|
def poll_until_done(order_id):
|
||||||
|
"""轮询直到完成"""
|
||||||
|
print(f"[info] 开始轮询(每 {POLL_INTERVAL_SECONDS} 秒一次)...")
|
||||||
|
start_time = time.time()
|
||||||
|
while True:
|
||||||
|
elapsed = time.time() - start_time
|
||||||
|
if elapsed > MAX_WAIT_MINUTES * 60:
|
||||||
|
raise TimeoutError(f"超过 {MAX_WAIT_MINUTES} 分钟未完成")
|
||||||
|
|
||||||
|
data = query_result(order_id)
|
||||||
|
order_info = data.get("content", {}).get("orderInfo", {})
|
||||||
|
status = order_info.get("status")
|
||||||
|
fail_type = order_info.get("failType", 0)
|
||||||
|
elapsed_min = elapsed / 60
|
||||||
|
print(f"[poll] 已等 {elapsed_min:.1f} 分钟, status={status}, failType={fail_type}")
|
||||||
|
|
||||||
|
if status == 4:
|
||||||
|
print(f"\n[ok] 转写完成!耗时 {elapsed_min:.1f} 分钟")
|
||||||
|
return data
|
||||||
|
if status == -1:
|
||||||
|
raise RuntimeError(f"转写失败: failType={fail_type}, 数据: {data}")
|
||||||
|
|
||||||
|
time.sleep(POLL_INTERVAL_SECONDS)
|
||||||
|
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# 结果解析
|
||||||
|
# ========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
def parse_order_result(order_result_str):
|
||||||
|
"""
|
||||||
|
解析嵌套JSON,返回 [(sentence_start_ms, sentence_end_ms, text), ...]
|
||||||
|
"""
|
||||||
|
if not order_result_str:
|
||||||
|
return []
|
||||||
|
|
||||||
|
cleaned = re.sub(r"\\\\", r"\\", order_result_str)
|
||||||
|
outer = json.loads(cleaned)
|
||||||
|
|
||||||
|
sentences = []
|
||||||
|
for item in outer.get("lattice", []):
|
||||||
|
inner_str = item.get("json_1best", "")
|
||||||
|
if not inner_str:
|
||||||
|
continue
|
||||||
|
inner = json.loads(inner_str)
|
||||||
|
st = inner.get("st", {})
|
||||||
|
bg = int(st.get("bg", 0))
|
||||||
|
ed = int(st.get("ed", 0))
|
||||||
|
|
||||||
|
words = []
|
||||||
|
for rt in st.get("rt", []):
|
||||||
|
for ws in rt.get("ws", []):
|
||||||
|
for cw in ws.get("cw", []):
|
||||||
|
w = cw.get("w", "").strip()
|
||||||
|
wp = cw.get("wp", "n")
|
||||||
|
if w and wp != "g":
|
||||||
|
words.append(w)
|
||||||
|
sentence = "".join(words).strip()
|
||||||
|
if sentence:
|
||||||
|
sentences.append((bg, ed, sentence))
|
||||||
|
|
||||||
|
return sentences
|
||||||
|
|
||||||
|
|
||||||
|
def format_timestamp(ms):
|
||||||
|
total_sec = ms // 1000
|
||||||
|
return f"{total_sec // 60}m{total_sec % 60}s"
|
||||||
|
|
||||||
|
|
||||||
|
def write_outputs(sentences, raw_data):
|
||||||
|
with open("asr_result_raw.json", "w", encoding="utf-8") as f:
|
||||||
|
json.dump(raw_data, f, ensure_ascii=False, indent=2)
|
||||||
|
print(f"[ok] 已写 asr_result_raw.json")
|
||||||
|
|
||||||
|
timed_lines = [f"[{format_timestamp(bg)}] {text}" for bg, _, text in sentences]
|
||||||
|
with open("asr_result_timed.txt", "w", encoding="utf-8") as f:
|
||||||
|
f.write("\n".join(timed_lines))
|
||||||
|
print(f"[ok] 已写 asr_result_timed.txt ({len(timed_lines)} 句)")
|
||||||
|
|
||||||
|
full_text = "".join(t for _, _, t in sentences)
|
||||||
|
with open("asr_result_full.txt", "w", encoding="utf-8") as f:
|
||||||
|
f.write(full_text)
|
||||||
|
print(f"[ok] 已写 asr_result_full.txt ({len(full_text)} 字)")
|
||||||
|
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# 入口
|
||||||
|
# ========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("=" * 60)
|
||||||
|
print("讯飞 录音文件转写(标准版) - 本地脚本")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
if SECRET_KEY.startswith("在此填入"):
|
||||||
|
print("[error] 请先填写 SECRET_KEY")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"[diag] APP_ID = {APP_ID} (长度 {len(APP_ID)})")
|
||||||
|
print(f"[diag] SECRET_KEY 长度 {len(SECRET_KEY)}, 首4位={SECRET_KEY[:4]}, 末4位={SECRET_KEY[-4:]}")
|
||||||
|
print(f"[diag] AUDIO_FILE = {AUDIO_FILE}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# 1. 上传
|
||||||
|
order_id = upload_audio(AUDIO_FILE)
|
||||||
|
|
||||||
|
# 2. 轮询
|
||||||
|
final_data = poll_until_done(order_id)
|
||||||
|
|
||||||
|
# 3. 解析+写文件
|
||||||
|
order_result_str = final_data["content"]["orderResult"]
|
||||||
|
sentences = parse_order_result(order_result_str)
|
||||||
|
write_outputs(sentences, final_data)
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print(f"完成!共识别 {len(sentences)} 句")
|
||||||
|
print(f"请把 asr_result_timed.txt 发给 Claude 进行三方融合")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
# 主 project 对 Doco PRD v2 的回复
|
||||||
|
|
||||||
|
> 来源:TPS 主 project 顾问(Claude Opus 4.7)
|
||||||
|
> 日期:2026-06-12
|
||||||
|
> 针对:`PRD_doco_文稿整理子项目_v2.md` 第四章 5 个问题
|
||||||
|
> 性质:正式批复,Doco 子项目据此出 v3 后启动 P1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 总体意见
|
||||||
|
|
||||||
|
**5 个问题的子项目推荐**,**整体方向 4 个批准、1 个调整**:
|
||||||
|
- Q1 OCR 选型:**批准 DeepSeek API,但有附加条件**(见下)
|
||||||
|
- Q2 ffmpeg 入口:**批准,有补充约束**
|
||||||
|
- Q3 单期 vs 批量接口:**批准,加交付契约**
|
||||||
|
- Q4 密钥管理:**调整方案** — 走"自管 + 中台登记 inventory"
|
||||||
|
- Q5 目录规约:**批准草案,但 episode_id 命名规则需主项目定**
|
||||||
|
|
||||||
|
5.3 §"23 期是否常态化":**这是一个产品问题,我代制片人答不了。子项目可以按"先按 23 期一次性做完、保留兜底回退路径"开干,常态化的事跟栏目组确认后再回头审。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Q1. OCR 方案选型 — 批准 DeepSeek API
|
||||||
|
|
||||||
|
### 主 project 现状
|
||||||
|
- **主 project 没有 OCR 子模块/能力**(已确认)。旧设计里 B 稿来自"上游既有 OCR 流程",指的是栏目组那边人工跑的 OCR,不是 TPS 内部的服务。
|
||||||
|
- 主 project `backend/.env` 里有 `DEEPSEEK_API_KEY`,但**只用作 Cline 工具的 Plan/Act 模型**——没有任何业务代码在调 DeepSeek。所以 doco 调 DeepSeek 视觉模型相当于**新增一条业务调用**,不是"复用现有基础设施"。
|
||||||
|
|
||||||
|
### 批复
|
||||||
|
|
||||||
|
**Doco 子模块新增 DeepSeek Vision 调用,自管 API key。**
|
||||||
|
|
||||||
|
- API key 独立申请,**不复用 Cline 用的那把 key**。理由:Cline 的 key 是开发工具用的,doco 是生产服务,生命周期、配额、监控都该独立。
|
||||||
|
- 6900 张图 × 几厘 / 张 ≈ 50-150 元,在制片人手上的 API 余额范围内,**不存在配额冲突问题**(主 project 业务代码侧没人在花)。
|
||||||
|
- 黑底白字字幕场景对 LLM 视觉模型确实是舒适区,**实施前先在 demo 那期视频上跑 10 帧抽样,验证识别准确率达到目标后再扩到 23 期**。
|
||||||
|
- **降级路径**:如果 DeepSeek Vision 在某些边角 case 上不达标(比如有同期声同步显示双行字幕、字号变化等),回退到 PaddleOCR 本地。**不要回退到讯飞 OCR**(余额独立 + 单期 ~13 元成本太高)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Q2. 视频处理依赖(ffmpeg)入口 — 批准方案 A
|
||||||
|
|
||||||
|
### 主 project 现状
|
||||||
|
- **没有视频处理子模块/服务**(已确认),dev_plan 也没规划。
|
||||||
|
|
||||||
|
### 批复
|
||||||
|
|
||||||
|
**Doco 自带 ffmpeg 系统依赖 + Python subprocess 调用。**
|
||||||
|
|
||||||
|
附加约束:
|
||||||
|
- **不引入 `ffmpeg-python` wrapper**——subprocess 足够,不增加新依赖。
|
||||||
|
- ffmpeg 命令封装在 `doco/video_split.py` 内,**对外只暴露 Python 函数接口**,不让上层调用方直接 shell 调 ffmpeg。
|
||||||
|
- 在 doco 的 `README.md` 明确写"系统依赖:ffmpeg ≥ 4.x"——这是部署的前置条件。
|
||||||
|
- 未来如果主 project 真做了统一的视频处理服务,**doco 的封装方式应该使迁移成本最低**(把 subprocess 调用换成 HTTP 调用即可,业务逻辑不动)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Q3. 23 期批量 vs 单期接口 — 批准方案 A,加契约
|
||||||
|
|
||||||
|
### 主 project 现状
|
||||||
|
- **没有节目素材批量处理编排层**(已确认)。dev_plan 提到的"批量导入工具 v1/v2"是收视数据和报题单的批量,跟视频处理是两回事。
|
||||||
|
|
||||||
|
### 批复
|
||||||
|
|
||||||
|
**Doco 只对单期负责。同时提供 CLI 和 Python API 两套接口。**
|
||||||
|
|
||||||
|
**接口契约(子项目正式实现时按这个出)**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Python API
|
||||||
|
def process_episode(
|
||||||
|
episode_id: str, # 调用方给定,doco 不管命名规则
|
||||||
|
video_path: Path, # 输入视频
|
||||||
|
a_draft_path: Path, # A 稿 docx
|
||||||
|
output_dir: Path, # 产物存放目录
|
||||||
|
cleanup_level: str = "medium", # keep_all / medium / clean
|
||||||
|
) -> ProcessResult
|
||||||
|
|
||||||
|
# ProcessResult 必含字段
|
||||||
|
@dataclass
|
||||||
|
class ProcessResult:
|
||||||
|
episode_id: str
|
||||||
|
status: Literal["success", "partial", "failed"]
|
||||||
|
final_docx_path: Optional[Path]
|
||||||
|
diff_report_path: Optional[Path]
|
||||||
|
needs_review_json_path: Optional[Path]
|
||||||
|
errors: List[str]
|
||||||
|
stage_timings: Dict[str, float] # 哪个 phase 用了多久
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# CLI 等价形式
|
||||||
|
doco process \
|
||||||
|
--episode-id ep023 \
|
||||||
|
--input-video /path/to/video.mp4 \
|
||||||
|
--input-a-draft /path/to/a_draft.docx \
|
||||||
|
--output-dir /path/to/output \
|
||||||
|
--cleanup-level medium
|
||||||
|
```
|
||||||
|
|
||||||
|
**关于 23 期推进**:**先单期跑通再批量**——拿 demo 那期《现代防空反导大对决》视频做 golden test(P4),与 demo 已有产物比对零回归,再扩到 23 期。一次性 batch 23 期风险太大。
|
||||||
|
|
||||||
|
未来主 project 若开节目素材批量处理编排层,**会反过来调 doco 的单期接口**,不会改 doco。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Q4. 讯飞密钥管理 — 调整方案:自管 + Inventory 登记
|
||||||
|
|
||||||
|
### 主 project 现状
|
||||||
|
- **没有中台密钥管理子模块**(已确认),也不在 dev_plan 排期内。
|
||||||
|
- 主 project 凭证都在 `backend/.env`,各模块走环境变量。
|
||||||
|
|
||||||
|
### 批复
|
||||||
|
|
||||||
|
不走子项目推荐的"申请新凭证 + 写入中台密钥资产文档"(因为中台密钥服务不存在,不能凭空捏一个)。改为:
|
||||||
|
|
||||||
|
**1. Doco 自管凭证。** 讯飞、DeepSeek 各自的 API key 放 doco 自己的 `.env`,**不放进主 project 的 `backend/.env`**——保持子模块自治。
|
||||||
|
|
||||||
|
**2. 主 project 仓库根目录新增一份登记文档:`docs/api_credentials_inventory.md`**
|
||||||
|
|
||||||
|
这份文档:
|
||||||
|
- **不存储真实凭证**(那些在各自子模块的 .env 里)
|
||||||
|
- 只存储**元信息**:每个外部 API 用了什么、所属子模块是谁、开通时间、激活状态、到期日、续费责任人
|
||||||
|
- 子模块申请新 key、key 到期更换,都更新这份文档
|
||||||
|
- 这是主 project 帮所有子模块做"凭证清单"的最小落地——比起"中台密钥服务",轻得多,但解决"忘了谁管哪把 key"的问题
|
||||||
|
|
||||||
|
**3. Inventory 文档的字段**(供子项目和未来其他子模块参考):
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
| 子模块 | API 服务 | Key 类型 | 开通日 | 激活状态 | 到期日 | 责任人 | 备注 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| doco | 讯飞开放平台 - 录音文件转写 | APP_ID + SECRET_KEY | 2026-06-12 | 已激活 5h 试用包 | 2027-06-12 | 制片人 | demo 凭证已过期,新申请 |
|
||||||
|
| doco | DeepSeek Vision | API_KEY | 2026-06-12 | 已激活 | — | 制片人 | doco OCR 用 |
|
||||||
|
| (主) | Anthropic Claude API | API_KEY | ... | ... | ... | ... | AI 融合层用 |
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. 制片人现在要做的事**(代答 Q4 里"新申请的讯飞开发端密钥应该登记在哪里"):
|
||||||
|
- 去讯飞开放平台 console 申请新的开发端凭证
|
||||||
|
- 走 0 元购买流程激活 5 小时免费试用包
|
||||||
|
- 把 APP_ID / SECRET_KEY 写到 doco 的 .env 里
|
||||||
|
- 在 `docs/api_credentials_inventory.md` 登记一行
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Q5. 目录结构与命名规约 — 批准草案,episode_id 命名由主项目定
|
||||||
|
|
||||||
|
### 主 project 现状
|
||||||
|
- **没有节目素材目录的统一规约**(已确认)。主 project 处理的是数据维度的 `episodes` 表,episode_id 是 INT 自增主键。
|
||||||
|
- 但是,**素材文件名跟数据库 ID 是两层东西**,不能直接套。
|
||||||
|
|
||||||
|
### 批复
|
||||||
|
|
||||||
|
**子项目提的 `programs/{episode_id}/source|work|output/...` 结构批准。**
|
||||||
|
|
||||||
|
**关于 episode_id 命名规则**——这是主项目要定的规约,定如下:
|
||||||
|
|
||||||
|
**episode_id 格式:`ep{NNN}_{YYYYMMDD}_{slug}`**
|
||||||
|
|
||||||
|
- `ep{NNN}` = episodes 表自增 INT 主键,零填充到 3 位(如 ep023)
|
||||||
|
- `{YYYYMMDD}` = 首播日期
|
||||||
|
- `{slug}` = 节目名称的拼音缩写或简称中文(无空格、无特殊字符)
|
||||||
|
|
||||||
|
举例:
|
||||||
|
- `ep023_20260612_haishang_xianfeng`
|
||||||
|
- `ep007_20260201_马年军事图鉴`
|
||||||
|
|
||||||
|
**理由**:
|
||||||
|
- INT 主键稳定可关联到 episodes 表
|
||||||
|
- 日期方便文件系统按时间排序
|
||||||
|
- slug 让人眼可读
|
||||||
|
|
||||||
|
**约定**:
|
||||||
|
- episode_id **由调用方给定**(主项目编排层 / 责编 / CLI 调用者),doco 不生成
|
||||||
|
- doco 只把它当一个字符串使用
|
||||||
|
- 主项目责编/编排层在调 doco 前**先在 episodes 表落库该期、拿到 INT ID**,再拼出 episode_id
|
||||||
|
|
||||||
|
**work/ 中间产物保留时长**:
|
||||||
|
- 节目入档案库后保留 **30 天**,然后可清理(由编排层负责,doco 不管)
|
||||||
|
- 出问题需要复查时,30 天窗口够定位
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §5 第 3 条:23 期是常态化吗?
|
||||||
|
|
||||||
|
**这是产品问题,不是技术问题。我代制片人答不了。**
|
||||||
|
|
||||||
|
**建议子项目的处理**:
|
||||||
|
- 按"23 期一次性"开干,先把这批做完
|
||||||
|
- 算法层零侵入是硬保证,即使将来变常态化,流水线也能继续跑
|
||||||
|
- **保留旧的 mp3+独立 OCR 流程作为回退路径**(代码不删,加 feature flag 或环境变量切换)。万一某期视频不符合"黑底白字+干净人声"特殊条件,降级到旧流程
|
||||||
|
- 23 期完成 + 制片人跟栏目组确认后,再决定是否清理回退路径
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 子项目可以启动的部分
|
||||||
|
|
||||||
|
按 PRD v2 §七 的回复期望:
|
||||||
|
- ✅ **Q1 已答**(DeepSeek API + 附加条件) → P1 可开始
|
||||||
|
- ✅ **Q2 已答**(subprocess + 不引入 wrapper)→ P1 可开始
|
||||||
|
- ✅ **Q3 已答**(单期 + 契约) → P5 推进时按契约
|
||||||
|
- ✅ **Q4 已答**(自管 + inventory 登记) → 制片人先申请讯飞新凭证 + 建 inventory,P2 可开始
|
||||||
|
- ✅ **Q5 已答**(目录草案批准 + episode_id 规则) → P1 输出有处可放
|
||||||
|
|
||||||
|
**Doco 子项目现在可以出 PRD v3,启动 P1。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 顺便给子项目的两条提醒
|
||||||
|
|
||||||
|
1. **demo 的 5 份 fixture 必须进 git**(transcripts / A 稿 / B 稿 / ASR / 终版 / 差异报告),作为单元测试 + golden test 黄金对照。这件事属于 Doco 内部自治,主项目不管,但提醒一下。
|
||||||
|
2. **AI 融合层模型选 Sonnet 4.6**(PRD v2 §二 已锁),不要在子项目里临时换成别的模型。主项目这边也不会推翻这个选择。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*主 project 顾问(Claude Opus 4.7)签发,2026-06-12*
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
# 《现代防空反导大对决》三方融合demo实测复盘
|
||||||
|
|
||||||
|
> 日期:2026年5月13日 | 报告人:Claude | 节目时长:26分钟 | 实施耗时:约2小时
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、ASR环节实测数据
|
||||||
|
|
||||||
|
### 1.1 服务选型最终结果
|
||||||
|
|
||||||
|
**最终采用:讯飞开放平台「录音文件转写(标准版)」**
|
||||||
|
|
||||||
|
| 维度 | 实测结果 |
|
||||||
|
|---|---|
|
||||||
|
| 转写耗时 | 5分钟左右(26分钟音频) |
|
||||||
|
| 识别句子数 | 307句(含片尾彩蛋) |
|
||||||
|
| 主体节目识别 | 297句对齐节目主体 |
|
||||||
|
| 关键术语识别率 | **接近100%**(开启35条热词后) |
|
||||||
|
| 数字/百分比识别 | 100%准确 |
|
||||||
|
| 文档显示价格 | 5小时免费试用包,1年有效期 |
|
||||||
|
|
||||||
|
### 1.2 ASR亮点
|
||||||
|
|
||||||
|
- 讯飞自动加入了合理的标点(句号、逗号、问号)
|
||||||
|
- 开启 `eng_smoothproc=true` 和 `eng_colloqproc=true` 后,已自动清理了大部分"嗯/那个/呃"等口语词
|
||||||
|
- **热词机制效果显著**:`霍拉姆沙赫尔-4` `见证者-136` `塔米尔` `大卫投石索` `本古里安` `拉斐尔` 等生僻军事术语全部正确识别
|
||||||
|
- 句子级时间戳精准,可直接与B稿做时间对齐
|
||||||
|
|
||||||
|
### 1.3 ASR短板(需要A稿术语表后处理修正)
|
||||||
|
|
||||||
|
| 错误类型 | 实例 | 修复依据 |
|
||||||
|
|---|---|---|
|
||||||
|
| 同音误识 | "中端/末端" → 应为"中段/末段" | A稿术语 |
|
||||||
|
| 同音误识 | "中诚防御" → 应为"中程防御" | A稿术语 |
|
||||||
|
| 事实错误 | "美伊两国" → 应为"美以两国"(最严重) | A稿/语境 |
|
||||||
|
| 表述偏好 | "高超声速" → A稿用"高超音速" | A稿术语统一 |
|
||||||
|
| 百分比表达 | "百%" → 应为"100%" | 后处理规则 |
|
||||||
|
| 数字表达 | "数10" → 应为"数十" | 后处理规则 |
|
||||||
|
| 口语词残留 | 专家发言里仍有"啊呢这个" | 部分保留以反映播出状态 |
|
||||||
|
|
||||||
|
### 1.4 关于'美伊→美以'这类事实错误的反思
|
||||||
|
|
||||||
|
ASR第18行把"美以两国"识别成了"美伊两国"。**这是最危险的一类错误**——拼音相同、字形不同,单独看ASR文本完全像是合法的事实陈述("美国和伊朗两国协同向伊朗发起军事打击"语义虽然荒谬但句子通顺),人工审校如果不熟悉上下文也可能漏过。
|
||||||
|
|
||||||
|
这印证了交接说明里的设计判断:**A稿的术语和事实必须作为权威源参与融合**,不能让ASR单独输出,否则会引入危险的事实错误。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、三方融合环节关键决策点
|
||||||
|
|
||||||
|
### 2.1 把握大的判断(demo中AI判断高确信度)
|
||||||
|
|
||||||
|
1. **整段删除的识别**:A稿【解说2】末尾'雷达被誉为中段反导体系的眼睛...'在B稿和ASR里完全找不到对应内容 → 信号非常明确,删除
|
||||||
|
2. **整段重复笔误**:A稿【专家7】和【专家8】内容字符完全相同 → 编导笔误,按ASR的真实内容(讲效费比)替换【专家8】
|
||||||
|
3. **术语事实错误的修复**:ASR'美伊→美以'类同音错误 → A稿权威覆盖
|
||||||
|
4. **OCR错字的批量修复**:'肘→时''娈→变''夭→天'等字形混淆 → ASR提供正确版本
|
||||||
|
|
||||||
|
### 2.2 把握较小的判断(demo中AI判断中等确信度,未来需要编导确认)
|
||||||
|
|
||||||
|
1. **解说6"整段改写"的边界**:A稿80字版本和ASR/B稿40字版本,**究竟保留哪个细节合并哪个细节**——目前demo直接采用了ASR的40字版本,但A稿那80字版本里有"信任危机""推迟采购方案"等A稿独有的内容,编导可能想保留。**未来应该让编导在UI上看diff后人工确认**
|
||||||
|
2. **专家发言的口语词处理**:'呢''啊'保留多少?太多影响阅读,太少违背播出真相。本次demo保留较多,倾向"播出真相"。**未来可做个可调档位("完全保留口语 / 中度清理 / 完全书面化"三档)**
|
||||||
|
3. **A稿首句被改写的情况**:A稿"观众朋友们,你们好!欢迎来到这一期的《军事科技》节目",播出时改为了"各位观众,你们好!欢迎收看《军事科技》"——句式接近但用词全变。demo靠手工锚点列表匹配上了,未来要让Claude做语义对齐而非字符匹配。
|
||||||
|
|
||||||
|
### 2.3 把握很小的判断(demo中AI暂时不处理,必须人工确认)
|
||||||
|
|
||||||
|
1. **句子级的微小增删**:如A稿"在涉及远、中、近程"和ASR"在涉及远中近程"——只是顿号差异。这种差异融合时按ASR走、还是按A稿格式来?**未来UI应该展示句子级diff让编导决定**
|
||||||
|
2. **专有名词的简写问题**:A稿严格用"爱国者-3",播出时多数说"爱国者"。这是术语统一问题还是口语化问题?**取决于该期节目的风格定位**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、对正式开发TPS子模块的启示
|
||||||
|
|
||||||
|
### 3.1 模块架构建议
|
||||||
|
|
||||||
|
```
|
||||||
|
[音频上传] → [ASR服务(讯飞)] → [OCR处理(B稿)] → [三方融合引擎] → [编导确认UI] → [终版docx]
|
||||||
|
↓
|
||||||
|
[大模型API(Claude)]
|
||||||
|
```
|
||||||
|
|
||||||
|
**核心是"三方融合引擎"应当分两层**:
|
||||||
|
- **规则层**:OCR错字纠正(固定映射表)、术语统一(A稿术语权威)、时间戳对齐 — 走Python代码
|
||||||
|
- **AI层**:段落对齐、整段改写判定、'编导笔误'识别 — 走大模型API
|
||||||
|
|
||||||
|
### 3.2 关于讯飞ASR的具体集成建议
|
||||||
|
|
||||||
|
**应该写进project_design.md【外部依赖】章节的内容**:
|
||||||
|
|
||||||
|
1. 优先使用讯飞「录音文件转写(标准版)」API,**不要**用大模型版(免费包阉割了language参数)
|
||||||
|
2. 音频必须先转码为 **16kHz / 单声道 / 16bit WAV**,否则讯飞会报误导性的`language verify fail`错误
|
||||||
|
3. **热词词库**是关键能力:每期节目从A稿提取专业术语作为热词上传给ASR
|
||||||
|
4. **领域参数** `pd=mil` 对军事节目有显著效果
|
||||||
|
5. 开启 `eng_smoothproc=true` + `eng_colloqproc=true` 让ASR输出更接近书面文稿
|
||||||
|
6. 讯飞密钥分两套:消费端(讯飞听见App)和开发端(讯飞开放平台),**互不相通**
|
||||||
|
7. "免费5小时"需要走0元购买流程才激活,不是看到额度就能用
|
||||||
|
|
||||||
|
### 3.3 关于大模型融合提示词的设计
|
||||||
|
|
||||||
|
未来正式开发时调Claude API做段落对齐,prompt应该包含:
|
||||||
|
|
||||||
|
- **输入1**:A稿全文 + 标签序列
|
||||||
|
- **输入2**:ASR结果(句子+时间戳)
|
||||||
|
- **输入3**:B稿OCR结果(句子+时间戳,作为交叉验证)
|
||||||
|
- **任务1**:把ASR句子按A稿标签序列归类
|
||||||
|
- **任务2**:对每段标记改动类型(无变化/细微改写/整段改写/整段删除/整段新增)
|
||||||
|
- **任务3**:对'高把握'改动直接产出终版;对'低把握'改动标记原因,等编导确认
|
||||||
|
- **任务4**:识别A稿术语和ASR结果的字形/同音差异,用A稿权威修正
|
||||||
|
|
||||||
|
### 3.4 关于编导确认UI的设计
|
||||||
|
|
||||||
|
借鉴本次demo发现的痛点,UI应该至少提供:
|
||||||
|
|
||||||
|
- **左中右三栏diff视图**:A稿原文 | 终版 | ASR/B稿(带时间戳,可点击播放对应音频片段)
|
||||||
|
- **改动类型颜色编码**:删除红色 / 改写黄色 / 术语修正蓝色 / 无变化白色
|
||||||
|
- **逐段确认按钮**:接受 / 拒绝 / 编辑 / 标记疑问
|
||||||
|
- **口语清理强度滑杆**:让编导决定保留多少口语词
|
||||||
|
- **导出按钮**:终版docx / 差异报告 / 复盘CSV
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、实测耗时分解(用于未来效率评估)
|
||||||
|
|
||||||
|
| 阶段 | 实测耗时 | 主要消耗 |
|
||||||
|
|---|---|---|
|
||||||
|
| 讯飞ASR申请+踩坑 | 约45分钟 | 大模型版语种权限问题、音频规格转码 |
|
||||||
|
| 老版讯飞ASR调通 | 约15分钟 | 申请+脚本+调用 |
|
||||||
|
| 三方解析 | 约5分钟 | A稿/B稿/ASR解析为统一结构 |
|
||||||
|
| 段落对齐 | 约15分钟 | 锚点匹配算法+单调推进 |
|
||||||
|
| 术语规范化+口语清理 | 约5分钟 | 字符级规则映射 |
|
||||||
|
| 终版docx生成 | 约5分钟 | python-docx写文档 |
|
||||||
|
| 差异报告+复盘 | 约15分钟 | 这份报告本身 |
|
||||||
|
|
||||||
|
**总耗时约2小时**,其中近一半花在讯飞踩坑上——正式开发后这部分会清零,每期实际处理时间预计15-30分钟(取决于改动幅度)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、给您(刘统制片)的几点直接建议
|
||||||
|
|
||||||
|
1. **TPS正式开发时,不必把ASR作为强依赖**。本次demo证明,即便没有ASR,A稿+B稿做二方融合也能产出接近播出版的终版。ASR的价值在于"独立第三方仲裁"——值得做但不应阻塞主流程。
|
||||||
|
|
||||||
|
2. **A稿术语表应该入库管理**,作为TPS的核心知识资产之一。每期节目处理时都从该表查找"权威术语",自动覆盖ASR的同音错误。本次demo手工列出的35个热词清单是个起点。
|
||||||
|
|
||||||
|
3. **节目编导习惯的差异要预留可配置项**。比如有的编导喜欢保留口语词、有的喜欢全部规整化;有的喜欢保留专家发言的原始措辞、有的喜欢编辑过的书面版本。这些应该在配置文件里,而不是硬编码。
|
||||||
|
|
||||||
|
4. **差异报告的价值可能比终版docx更大**。每期节目处理完,差异报告其实是个"编导工作回顾"——能看到自己当初做了哪些删改、哪些是OCR错字。长期累积下来可以分析编导的删改偏好,作为节目优化的素材。
|
||||||
|
|
||||||
|
5. **本次踩的坑值得专门整理一个"讯飞集成踩坑笔记"文档**入TPS知识库。未来下次开发新供应商接入时(比如阿里云ASR),可以走更顺的路。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*本复盘为demo阶段产物,不代表正式开发的最终决策。所有结论以下次设计文档为准。*
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# 跨子项目协作规则
|
||||||
|
|
||||||
|
> 主项目维护的通用规则,所有外迁子项目都适用。
|
||||||
|
> 起始日期:2026-06-12
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 规则 1:PRD 版本管理(立于 Doco 立项时)
|
||||||
|
|
||||||
|
### 1.1 主 project 这边的规则
|
||||||
|
|
||||||
|
- **只保留最新版 PRD + 对应回复**,旧版本一律删
|
||||||
|
- **PRD 与回复一一配对**:PRD v2 ↔ 回复 v2;PRD v3 ↔ 回复 v3
|
||||||
|
- 任何时点,主 project 不允许同时存在同一子项目的两个 PRD 版本
|
||||||
|
|
||||||
|
### 1.2 子 project 那边的规则
|
||||||
|
|
||||||
|
- **保留所有版本**(包括 PRD v0 / v1 / v2 / v3...)
|
||||||
|
- 旧版本可移到 `archive/` 子目录或加 `_archived` 后缀,但不删
|
||||||
|
- 每份新 PRD 在元信息块标注"上一版:vN"
|
||||||
|
|
||||||
|
### 1.3 版本翻新的操作
|
||||||
|
|
||||||
|
子项目出 PRD vN+1 时:
|
||||||
|
1. 制片人在主 project 这边**先删** PRD vN + 回复 vN
|
||||||
|
2. **再传** PRD vN+1 + 主项目顾问写的回复 vN+1
|
||||||
|
3. 一次性,不允许"先传再删"造成短暂双版本状态
|
||||||
|
|
||||||
|
### 1.4 适用范围
|
||||||
|
|
||||||
|
- 当前所有外迁子项目(看板升级 / Doco 等)
|
||||||
|
- 未来新立项的子项目沿用
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## (未来其他通用规则在这里累加)
|
||||||
|
|
||||||
|
> 后续规则按 `## 规则 2:xxx` `## 规则 3:xxx` 顺序追加。
|
||||||
@@ -0,0 +1,377 @@
|
|||||||
|
# 续接快照 — 看板分析升级 v4(AI 打标流水线落地 + 模型选型完成)
|
||||||
|
|
||||||
|
> 用途:下次新 chat 接力用。承接 2026-06-09 v1 + 2026-06-10 v2 + 2026-06-11 上午 v3,包含 2026-06-11 一整天讨论。
|
||||||
|
> 状态:AI 打标流水线跑通;Prompt 2 v0.2 锁定;ground-truth v0.2.1 锁定;模型选型完成 → **MiniMax M3 + Prompt v0.2 = 100% 命中率**;Git 已推 Gitea 落库。
|
||||||
|
> 更新时间:2026-06-11(晚)
|
||||||
|
> 顾问:Claude Opus 4.7 | 制片人:刘通
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 零、本快照与 v1/v2/v3 的关系
|
||||||
|
|
||||||
|
v1/v2/v3 全部结论仍然有效,**v4 是增量,不替换**。今日新增 6 件大事:
|
||||||
|
|
||||||
|
1. AI 打标流水线从纸面落到能跑(脚本 + 配置 + 文稿入库 + 汇总工具)
|
||||||
|
2. Prompt 2 升级到 v0.2(加"段内承接 ≠ 全片骨架"陷阱教学)
|
||||||
|
3. ground-truth 经两轮复议升级到 v0.2.1(三期改判)
|
||||||
|
4. 三家模型在同一份"试卷"上公平对比完成
|
||||||
|
5. 模型选型拍板:**MiniMax M3**
|
||||||
|
6. Git 双 commit 推送 Gitea 落库(commit `38f3728` 是今天的里程碑)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、今天的时间线(2026-06-11 一日)
|
||||||
|
|
||||||
|
| 阶段 | 关键动作 | 产出 |
|
||||||
|
|---|---|---|
|
||||||
|
| 上午 | 工作区目录搭建 + 10 期文稿导入 + ep04 单跑 | 9/10 自动导入成功,ep05 .doc 制片人手工另存补全 |
|
||||||
|
| 中段 | 发现 reasoning model 的 `<think>` 标签 bug → 修 `extract_json_from_response` | JSON 解析链路稳定 |
|
||||||
|
| Prompt v0.1 全跑 | M3 跑 10 期 | **5/10 = 50%**,全部"高置信" |
|
||||||
|
| 复议 1 | ep05/13/14 维持并列,ep10/15 改主线演进 | ground-truth v0.2 |
|
||||||
|
| Prompt 升级 | 加"段内承接陷阱"+ `chapter_list` + `shuffle_test` 强制思考字段 | Prompt 2 v0.2 |
|
||||||
|
| M3 二跑 | 9/10 = 90%,唯一错 ep12 | 锁定 v0.2 不再调 |
|
||||||
|
| DeepSeek V4 Pro | 70%,错的全是"应主线判并列",偏保守 | — |
|
||||||
|
| MiMo v2.5 Pro | 60%,两向都错 | — |
|
||||||
|
| 复议 2 | ep12 三家独立都判并列 → ground-truth 改 | ground-truth v0.2.1 |
|
||||||
|
| 最终战绩 | **M3 100% / DeepSeek 80% / MiMo 70%** | 选 M3 |
|
||||||
|
| 收尾 | Git 双 commit 推 Gitea | commit 38f3728 + edfb298 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、AI 打标流水线已落地资产
|
||||||
|
|
||||||
|
### 2.1 工作目录(`E:\tps-dashboard\ai-labeling\`)
|
||||||
|
|
||||||
|
```
|
||||||
|
ai-labeling/
|
||||||
|
├── benchmark-set/
|
||||||
|
│ ├── transcripts/ ← 10 期文稿 .md(基准卷子)
|
||||||
|
│ │ ├── ep03_硅基大脑.md
|
||||||
|
│ │ ├── ep04_潜艇仿生.md
|
||||||
|
│ │ ├── ep05_舰证不凡.md
|
||||||
|
│ │ ├── ep07_马年图鉴.md
|
||||||
|
│ │ ├── ep10_射速决定论.md
|
||||||
|
│ │ ├── ep11_空战颠覆者.md
|
||||||
|
│ │ ├── ep12_逆袭战局.md
|
||||||
|
│ │ ├── ep13_长短智慧.md
|
||||||
|
│ │ ├── ep14_X76飞机.md
|
||||||
|
│ │ └── ep15_空中坚盾.md
|
||||||
|
│ └── ground-truth.json ← 基准答案 v0.2.1
|
||||||
|
├── prompts/
|
||||||
|
│ └── prompt2_narrative.md ← 叙事结构判别 v0.2(5 示例,含两个陷阱反例)
|
||||||
|
├── experiments/ ← 跑批结果 .json(.gitignore 拦截,不入 git)
|
||||||
|
├── scripts/
|
||||||
|
│ ├── import_transcripts.py ← docx/doc → md 解析 + 清洗
|
||||||
|
│ ├── run_labeling.py ← 单期或批量调模型 + 写文件
|
||||||
|
│ └── summarize.py ← 扫 experiments/ 汇总命中率
|
||||||
|
├── .env.example ← 入 git 的 Key 占位模板
|
||||||
|
├── .env ← 不入 git,真 Key
|
||||||
|
├── .gitignore ← 拦 .env / experiments / __pycache__
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 三个关键脚本的分工
|
||||||
|
|
||||||
|
| 脚本 | 干什么 | 用法 |
|
||||||
|
|---|---|---|
|
||||||
|
| `import_transcripts.py` | 把源 docx/doc 拷+解析+清洗成 .md,落 transcripts/ | 已跑过一次,10 期都在;新文稿要扩源目录映射表 |
|
||||||
|
| `run_labeling.py` | 调模型,把 result + ground_truth 写进 experiments/ 一个 .json | `python scripts/run_labeling.py --ep N --model m3` |
|
||||||
|
| `summarize.py` | 扫 experiments/ 下指定 model 的最新 json,出 10 行命中表 + 汇总 | `python scripts/summarize.py --model m3` |
|
||||||
|
|
||||||
|
PowerShell 批量套路(模型选型阶段用,以后可作为标准跑法):
|
||||||
|
```powershell
|
||||||
|
cd E:\tps-dashboard\ai-labeling
|
||||||
|
3, 4, 5, 7, 10, 11, 12, 13, 14, 15 | ForEach-Object { python scripts/run_labeling.py --ep $_ --model m3 }
|
||||||
|
python scripts/summarize.py --model m3
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 MODEL_CONFIG 已配置的三家(`scripts/run_labeling.py`)
|
||||||
|
|
||||||
|
```python
|
||||||
|
MODEL_CONFIG = {
|
||||||
|
"m3": {
|
||||||
|
"base_url": "https://api.minimaxi.com/v1",
|
||||||
|
"model_name": "MiniMax-M3",
|
||||||
|
"api_key_env": "MINIMAX_API_KEY",
|
||||||
|
},
|
||||||
|
"deepseek-v4-pro": {
|
||||||
|
"base_url": "https://api.deepseek.com", # 注意:不带 /v1
|
||||||
|
"model_name": "deepseek-v4-pro",
|
||||||
|
"api_key_env": "DEEPSEEK_API_KEY",
|
||||||
|
},
|
||||||
|
"mimo-v2.5-pro": {
|
||||||
|
"base_url": "https://api.xiaomimimo.com/v1",
|
||||||
|
"model_name": "mimo-v2.5-pro",
|
||||||
|
"api_key_env": "MIMO_API_KEY",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
依赖锁定(`scripts/requirements.txt`):
|
||||||
|
```
|
||||||
|
openai==1.55.0 # 不能升级,新版自动转 developer 角色,MiniMax 不支持
|
||||||
|
python-dotenv>=1.0.0
|
||||||
|
python-docx>=1.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、Prompt 2 v0.2 核心设计
|
||||||
|
|
||||||
|
(完整文件见 `ai-labeling/prompts/prompt2_narrative.md`,以下是要点摘录)
|
||||||
|
|
||||||
|
### 3.1 两档定义(收为 2 档,沿用 v3)
|
||||||
|
|
||||||
|
- **主线演进**:全片由"贯穿主线"串起来。主线可以是 a) 内在概念 / b) 时间因果链 / c) 性能阶梯
|
||||||
|
- **并列结构**:章节相互独立、可替换,共性只来自分类共性
|
||||||
|
|
||||||
|
### 3.2 关键边界(共 4 条 + 1 条核心新增)
|
||||||
|
|
||||||
|
1. 命名共性不构成主线
|
||||||
|
2. 装备域共性不构成主线
|
||||||
|
3. 空间方位共性不构成主线
|
||||||
|
4. **【v0.2 新增,最重要】段内承接 ≠ 全片骨架**——文稿里某段出现"递进""演进""阶梯""奠定基础"字样,**往往只是段内微观承接**,不是全片骨架。先识别全片大章节,再做章际打乱测试。
|
||||||
|
|
||||||
|
### 3.3 强制判断流程(v0.2 新增)
|
||||||
|
|
||||||
|
模型必须先输出 `chapter_list`(全片 3-5 个大章节)+ `shuffle_test`(打乱测试结论),才能下判断。避免它一看到"递进"两字就秒判主线演进。
|
||||||
|
|
||||||
|
### 3.4 5 个示例(2 主线 + 3 并列,平衡分布)
|
||||||
|
|
||||||
|
| 示例 | 类型 | 教学重点 |
|
||||||
|
|---|---|---|
|
||||||
|
| 潜艇仿生 | 主线演进-内在概念 | 同一命题贯穿全片 |
|
||||||
|
| 空战颠覆者 | 主线演进-时间线 | 严格按时间序推进 |
|
||||||
|
| 马年军事图鉴 | 并列结构-命名共性 | 高收视不靠结构,靠节点策划 |
|
||||||
|
| **舰证不凡** ⚠️ | **并列结构-警惕段内承接陷阱** | "递进式"字样在段内 ≠ 全片主线 |
|
||||||
|
| **X-76 飞行器** ⚠️ | **并列结构-警惕段内时间线陷阱** | 时间线只在"背景"段里 ≠ 全片骨架 |
|
||||||
|
|
||||||
|
### 3.5 JSON 输出 schema(新增两个强制思考字段)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"narrative_structure": "主线演进 或 并列结构",
|
||||||
|
"chapter_list": ["大章节1", "大章节2", ...], ← v0.2 新增
|
||||||
|
"shuffle_test": "打乱后观众怎样的一句话", ← v0.2 新增
|
||||||
|
"main_thread": "主线演进时点明主线,并列填 null",
|
||||||
|
"reasoning": "判断理由,如果文稿有'递进'等字样必须说明是段内还是全片",
|
||||||
|
"key_evidence": ["证据片段1", "证据片段2"],
|
||||||
|
"confidence": "高 或 中 或 低",
|
||||||
|
"confidence_reason": "为什么这个置信度"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、ground-truth v0.2.1 锁定的 10 期分布
|
||||||
|
|
||||||
|
| ep | 节目 | share | 叙事结构(v0.2.1) | 开篇钩子 | v0.1 → v0.2.1 变迁 |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| 3 | 硅基大脑 | 0.85 | 并列结构 | 中 | 未变 |
|
||||||
|
| 4 | 潜艇仿生 | 0.92 | 主线演进 | 强 | 未变 |
|
||||||
|
| 5 | 舰证不凡 | 0.72 | 并列结构 | 中 | 未变(经讨论后维持) |
|
||||||
|
| 7 | 马年军事图鉴 | 0.95 | 并列结构 | 强 | 未变 |
|
||||||
|
| 10 | 射速决定论 | 0.703 | **主线演进** | 弱 | v0.1 并列 → v0.2 主线(性能阶梯) |
|
||||||
|
| 11 | 空战颠覆者 | 0.859 | 主线演进 | 中 | 未变 |
|
||||||
|
| 12 | 逆袭战局 | 0.85 | **并列结构** | 强 | v0.1 主线 → v0.2.1 并列(三家独立都判并列) |
|
||||||
|
| 13 | 长短智慧 | 0.533 | 并列结构 | 中 | 未变(经讨论后维持) |
|
||||||
|
| 14 | X-76 飞行器 | 0.873 | 并列结构 | 中 | 未变(经讨论后维持) |
|
||||||
|
| 15 | 空中坚盾 | 0.875 | **主线演进** | 强 | v0.1 并列 → v0.2 主线(层级承接) |
|
||||||
|
|
||||||
|
**最终分布:5 主线 / 5 并列,平衡。** 此前 v0.1 是 3 主线 / 7 并列。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、三家模型最终对比(基于 v0.2.1 修订版试卷)
|
||||||
|
|
||||||
|
### 5.1 命中率总表
|
||||||
|
|
||||||
|
| 期次 | 修订后标准 | **M3** | **DeepSeek V4 Pro** | **MiMo v2.5 Pro** |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| ep03 | 并列 | ✓ | ✓ | ✓ |
|
||||||
|
| ep04 | 主线 | ✓ | **✗** | ✓ |
|
||||||
|
| ep05 | 并列 | ✓ | ✓ | **✗** |
|
||||||
|
| ep07 | 并列 | ✓ | ✓ | ✓ |
|
||||||
|
| ep10 | 主线 | ✓ | **✗** | **✗** |
|
||||||
|
| ep11 | 主线 | ✓ | ✓ | ✓ |
|
||||||
|
| ep12 | 并列 | ✓ | ✓ | ✓ |
|
||||||
|
| ep13 | 并列 | ✓ | ✓ | ✓ |
|
||||||
|
| ep14 | 并列 | ✓ | ✓ | ✓ |
|
||||||
|
| ep15 | 主线 | ✓ | ✓ | **✗** |
|
||||||
|
| **命中率** | | **10/10 = 100%** | 8/10 = 80% | 7/10 = 70% |
|
||||||
|
| **错的方向** | | 无 | 全部"应主线判并列",**偏保守** | 两个方向都错 |
|
||||||
|
|
||||||
|
### 5.2 选型结论:MiniMax M3 完胜
|
||||||
|
|
||||||
|
理由不只在命中率,更在质量层:
|
||||||
|
|
||||||
|
| 维度 | M3 | DeepSeek | MiMo |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 命中率 | **100%** | 80% | 70% |
|
||||||
|
| 三种主线识别能力(内在概念/时间线/性能阶梯/层级承接) | **全识别** | 漏识别 ep04(示例 1 直接教过的潜艇仿生都没认出来) | 漏 2 期主线 |
|
||||||
|
| Few-shot 学习力 | 强 | **弱**(连示例 1 同型的 ep04 都漏) | 中 |
|
||||||
|
| reasoning 质量 | chapter_list + shuffle_test + 时序验证完整 | 一般 | 一般 |
|
||||||
|
| 系统偏差 | 无 | **偏保守** | 偏向不稳定 |
|
||||||
|
|
||||||
|
**致命差距**:DeepSeek 连 Prompt 里"示例 1 直接教过的潜艇仿生"都没认出来——这说明它对 few-shot 示例的"听话度"较差,以后加再多反例也可能漏。
|
||||||
|
|
||||||
|
### 5.3 落地选型(冻结)
|
||||||
|
|
||||||
|
- **生产模型**:MiniMax M3
|
||||||
|
- **Prompt**:Prompt 2 v0.2(`ai-labeling/prompts/prompt2_narrative.md`)
|
||||||
|
- **基准卷子**:ground-truth v0.2.1(`ai-labeling/benchmark-set/ground-truth.json`)
|
||||||
|
- **回退方案**:如 M3 服务中断,DeepSeek V4 Pro 备选(虽然命中率较低,但稳定可用)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、关键经验教训(下次接力的我必读)
|
||||||
|
|
||||||
|
### 6.1 reasoning model 的输出格式坑
|
||||||
|
|
||||||
|
MiniMax M3 是 reasoning model,输出格式是:
|
||||||
|
```
|
||||||
|
<think>
|
||||||
|
模型的内部推理过程(英文,几百字)
|
||||||
|
</think>
|
||||||
|
|
||||||
|
{真正的 JSON 输出}
|
||||||
|
```
|
||||||
|
|
||||||
|
直接 `json.loads(content)` 会失败。脚本里 `extract_json_from_response` 用正则剥掉 `<think>...</think>` 后再解析。**未来如果换其他 reasoning model(R1、o1 系列等)同样适用。**
|
||||||
|
|
||||||
|
### 6.2 段内承接 vs 全片骨架(Prompt 2 v0.2 的灵魂)
|
||||||
|
|
||||||
|
模型最容易栽的跟头是看到"递进""演进""阶梯"几个字就秒判主线演进。但这些字样常常**只在某一段内**(讲两件装备先后、某段背景的时间线等),不是全片骨架。
|
||||||
|
|
||||||
|
判别口诀(已写进 Prompt 2):**先看全片大章节(树干),再看段内细节(树叶)**。章节顺序能不能打乱才是主线判别的唯一依据。
|
||||||
|
|
||||||
|
### 6.3 ground-truth 是活的,不是写死的
|
||||||
|
|
||||||
|
v0.1 → v0.2(改两期)→ v0.2.1(改一期),共改三期。每次修改都因为发现 v0.1 标的判断与 v3 §1.1 自己定的判别规则有冲突,或者多家模型独立得出反向结论。
|
||||||
|
|
||||||
|
**纪律**:基准答案集每次升级,changelog 必须详细记录变更原因,不能"悄悄改"。未来用 pgvector 检索做动态示例集时,固化示例必须明确版本号 + 复议历史。
|
||||||
|
|
||||||
|
### 6.4 同一份卷子比三家 vs 优化单家
|
||||||
|
|
||||||
|
诱惑很大:M3 90% 后只差一题,继续调 Prompt 上 100% 应该不难。但**这样会过度适配 M3 的脾气**——同一个 Prompt 跑 DeepSeek/MiMo 反而下降。
|
||||||
|
|
||||||
|
实践证明:v0.2 Prompt 上 M3 100%,DeepSeek 也吃这套教学(从 70% 升 80%),MiMo 也吃(从 60% 升 70%)。**好的 Prompt 不是为某一家定制,而是把判别规则讲清楚,三家都受益。**
|
||||||
|
|
||||||
|
### 6.5 MiniMax M2.7(Cline 的 Plan/Act 模型)写长文件不稳定
|
||||||
|
|
||||||
|
中段 Cline 改 run_labeling.py 时撞过:
|
||||||
|
- `write_to_file` 长内容截断
|
||||||
|
- 改用辅助脚本生成主文件
|
||||||
|
- 改用 base64 编码绕过
|
||||||
|
- 触发 MiniMax 自己的 context 限制
|
||||||
|
|
||||||
|
**纪律**:涉及 ai-labeling/ 内文件改动,**老文件用 `replace_in_file` 局部改,新文件用 `write_to_file` 整体写**(<200 行才稳)。Prompt 和 ground-truth 这种长文件,**让制片人手工替换最稳**。
|
||||||
|
|
||||||
|
### 6.6 边界期是制片人 + 多家模型共审拍板
|
||||||
|
|
||||||
|
ep12 是个标志性案例:制片人 v0.1 标主线演进,M3/DeepSeek/MiMo 三家独立都判并列结构,经制片人复读稿后改并列。**这种"多家独立一致 + 人工复审"的双重证据机制,未来扩展示例集时是黄金流程。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、待办池(追加到 `backlog.md`)
|
||||||
|
|
||||||
|
继承 v3 §六的 4 条 + v4 新增 4 条:
|
||||||
|
|
||||||
|
### 继承 v3 §六
|
||||||
|
|
||||||
|
- **F1. AI 打标示例集更新纪律【优先级:中,上线后启用】**
|
||||||
|
示例集每月集中替换一次,不碎片化更新(吃 prompt 缓存红利)
|
||||||
|
|
||||||
|
- **F2. Prompt 1(4 分类字段)+ Prompt 3(开篇钩子)撰写【优先级:中,Prompt 2 已验证通过,可启动】**
|
||||||
|
按 Prompt 2 同样套路:Opus 写 → M3 跑基准 → 制片人审 → 锁定
|
||||||
|
|
||||||
|
- **F3. Decision 3 横轴量化方法落地【优先级:中】**
|
||||||
|
v2 §3 已基本定(栏目均值偏离),但还没真正算过 23 期具体数值
|
||||||
|
|
||||||
|
- **F4. 23 期回填确认(继承 v2 §5.5)**
|
||||||
|
ep15 空中坚盾原"空军防空"→确认改 `导弹与反导`?
|
||||||
|
ep16 启程远航装备域缺失,疑似 `海军舰船`
|
||||||
|
ep18 海上先锋·无人舰艇 → `海军舰船` + tech_tag=`无人作战`
|
||||||
|
|
||||||
|
### v4 新增
|
||||||
|
|
||||||
|
- **F5. opening_hook 字段尚未跑过 AI 验证【优先级:中,等 Prompt 3】**
|
||||||
|
10 期 ground-truth 里 opening_hook 是制片人读稿确认的,但还没让 AI 试着判过。Prompt 3 上线后跑一次,对答案看 M3 在开篇钩子上的命中率。
|
||||||
|
|
||||||
|
- **F6. 改 episodes schema 加 6 字段【优先级:高,但必须先切 Plan + Opus 审】**
|
||||||
|
字段:`program_format / equipment_domain / scene_tags / tech_tags / narrative_structure / opening_hook` + 1 个 `confidence` 字段。**纪律**:Cline 不许直接 Act,必须先 Plan + 我审过迁移方案。回补方案包括 23 期已标注的回填脚本。
|
||||||
|
|
||||||
|
- **F7. UI 必须区分置信度三档【优先级:中,Phase 4a/4b 看板设计时落地】**
|
||||||
|
特别警惕"AI 自评高置信但实际错判"的样本(模型不知道自己错了),UI 上要让制片人能一眼分辨"AI 草稿/制片人确认/标题推断"三档。
|
||||||
|
|
||||||
|
- **F8. prompt 缓存月度更新机制【优先级:低,上线后启用】**
|
||||||
|
v3 §3.7 已经写过纪律,执行时机是 AI 打标系统上线后第 1 个月起。
|
||||||
|
|
||||||
|
**追加方式**:你看完后告诉我,我给一段 Cline 指令把 F1-F8 这 8 条追加到 `backlog.md`(如果文件不存在就新建)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、纪律红线(沿用 v3 §七 + v4 增补)
|
||||||
|
|
||||||
|
沿用:
|
||||||
|
- 改表须 Opus 审,Cline 不得自行加字段
|
||||||
|
- AI 只出草稿、给方向,人拍板
|
||||||
|
- 不做编导排名(团队视角走"能力地图")
|
||||||
|
- 未审核字段不上看板,编导只看已确认数据
|
||||||
|
- AI 打标三个 prompt 独立,不合并
|
||||||
|
- 示例集每月集中更新,不碎片化(吃缓存红利)
|
||||||
|
- Prompt 内容不让 Cline 创作——Cline 是执行者不是作者,Prompt 由 Opus 写、Cline 落文件
|
||||||
|
|
||||||
|
**v4 新增红线**:
|
||||||
|
|
||||||
|
- **AI 打标实验工作区(`ai-labeling/`)与生产代码(`backend/`)严格隔离**
|
||||||
|
- **`ai-labeling/` 内改动允许 Cline 直接 Act**(沙盒,改坏重跑就是)
|
||||||
|
- **`backend/` 改动必须切 Plan + Opus 审**(生产代码,改 schema 加字段更要严)
|
||||||
|
- **长文件改动失败时,让制片人手工替换最稳**(避免 Cline 在 write_to_file 截断时套娃式 workaround)
|
||||||
|
- **改 ground-truth 必须留 changelog**(谁、何时、改了什么、为什么改)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、技术备忘(沿用 v3 §八 + 新增)
|
||||||
|
|
||||||
|
沿用:
|
||||||
|
- 栈:React18 + Vite + AntD5 + Zustand | FastAPI + SQLModel + PG16 + pgvector
|
||||||
|
- 图表:ECharts / @ant-design/charts
|
||||||
|
- 配色固化:米色底 `#fbf9f1`、深绿主色 `#6b8e6b`
|
||||||
|
- 三色色板:红 `#c0584f` / 蓝 `#5b8db8` / 绿 `#7aa874`
|
||||||
|
- 基础线 0.6448 / 摸高线 0.8989(2026)
|
||||||
|
|
||||||
|
v4 新增:
|
||||||
|
- AI 打标模型选型:**MiniMax M3** + `ai-labeling/prompts/prompt2_narrative.md` v0.2
|
||||||
|
- `summarize.py` 是模型选型基准工具,未来切其他模型继续用
|
||||||
|
- `experiments/*.json` 不进 git(.gitignore 拦截)
|
||||||
|
- `ground-truth.json` + `transcripts/*.md` 进 git(栏目核心资产)
|
||||||
|
- `requirements.txt` 锁 openai==1.55.0(不要升级)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、Git 状态
|
||||||
|
|
||||||
|
里程碑 commit(2026-06-11 晚):
|
||||||
|
|
||||||
|
```
|
||||||
|
edfb298 chore: TPS 主项目素材积累(海报 logo + 样本 md)
|
||||||
|
38f3728 feat(ai-labeling): AI 打标实验工作区初始化 + 模型选型完成 ← 今天的硬核成果
|
||||||
|
ae04c7f chore: gitignore 忽略前端测试题图截图
|
||||||
|
ae9581e docs: 新增 claude 协作原则文件,backlog 待办池入库
|
||||||
|
b942907 docs: phase3_log 收尾,Task 3/4 记录归位
|
||||||
|
```
|
||||||
|
|
||||||
|
`ai-labeling/` 已在 Gitea 落地,任意时点可回溯。`.env` / `experiments/` / `__pycache__/` 全部被 `.gitignore` 拦住,无敏感泄露。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十一、下次开局第一句
|
||||||
|
|
||||||
|
> "续接 v3 → v4。AI 打标流水线已跑通,**MiniMax M3 + Prompt 2 v0.2 在 ground-truth v0.2.1 上命中率 100%**,模型选型完成。下一步推 Prompt 1(4 分类字段)+ Prompt 3(开篇钩子),按 v4 同样的'Opus 写 Prompt → M3 跑 10 期基准 → 制片人审 → 锁定'三步走。**改 episodes schema 加 6 字段之前必须切 Plan + Opus 审**——这是宪法红线,不能直接 Act。"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附:今日核心结论一句话总结
|
||||||
|
|
||||||
|
> AI 打标流水线从纸面落地;Prompt 2 v0.2 + ground-truth v0.2.1 经两轮复议锁定;三家模型公平对比(M3 100% / DeepSeek 80% / MiMo 70%)后选 MiniMax M3 为生产模型;Git 双 commit 推 Gitea 落库(里程碑 commit `38f3728`)。明天起可以推 Prompt 1 + Prompt 3,但改 episodes schema 必须先 Plan + Opus 审。
|
||||||
Reference in New Issue
Block a user