This commit is contained in:
2026-04-24 16:02:16 +08:00
commit 1d6f0cc370
66 changed files with 9990 additions and 0 deletions

View File

@@ -0,0 +1,410 @@
# Story Extractor — 产品设计文档
> 版本v1.1 · 2026-04-21
---
## 一、产品概述
### 1.1 产品定位
Story Extractor 是一个 **局域网部署的 Web 工具**,用于从直播回放文字稿中自动提取学员个人故事,与讲述者个人信息匹配后,为每位讲述者生成独立的 DOCX 文档。
### 1.2 核心价值
- **自动化**AI 自动从上万行口语化文字稿中提取学员故事,替代人工阅读筛选
- **结构化**:将散乱的直播内容转化为结构化的"人物 + 故事"文档
- **可复用**工具化交付支持后续扩展LLM 升级、搜索引擎等)
### 1.3 使用场景
| 维度 | 描述 |
|------|------|
| **部署环境** | 局域网,多人可访问 |
| **数据规模** | 20+ 份文字稿每份上万行8+ 位讲述者 |
| **用户角色** | 内容运营人员 |
---
## 二、文字稿特征分析
### 2.1 格式特征
每段格式为:**`发言者(时间戳): 内容`**,例如:
```
卢慧老师(00:05:38): 这个我们在我们的启蒙课里面...
14班+HCM(02:39:31): 就是要要打要骂,呵呵...
```
- 有明确的**说话人标记**(老师 / 学员昵称)
- 有**时间戳**,可用于判断发言时长
- 主讲老师占 60-70% 内容,学员发言散落其中
### 2.2 内容构成
| 内容类型 | 占比 | 说明 |
|----------|------|------|
| **课程讲授** | ~55% | 老师讲理论、概念、方法论 |
| **课堂管理** | ~10% | 改昵称、纪律提醒、进组讨论等技术性内容 |
| **疗愈练习** | ~15% | "我愿意看见且释放..." 引导式重复 |
| **学员故事** | ~15% | 学员讲述个人经历,老师追问 |
| **学员短回应** | ~5% | "好的""收到"等 |
### 2.3 故事的实际形态
故事**不是一段完整的自述**,而是**对话式展开**的:
- 老师提问/引导 → 学员回答 → 老师追问 → 学员深入讲述 → 可能穿插疗愈练习
- 一个故事可能跨 **20-30 段对话**,持续 15-30 分钟
- 故事之间没有明显分界,可能上一段还在讲理论,下一段就切入学员故事
### 2.4 典型故事示例
| 讲述者 | 故事概要 |
|--------|----------|
| **14班+HCM** | 从小被妈妈体罚(跪凳子),长大后用同样方式对待女儿,女儿出现躯体化症状 |
| **13-阿纳** | 姥姥因特殊年代藏首饰恐惧自杀,形成"不能有钱"的家族限制性信念 |
| **06班Rena** | 妈妈在怀自己前打掉一个男孩,爸爸重男轻女,自己被当男孩养,对亲密关系有破坏倾向 |
| **11班四维** | 女儿出柜说喜欢同性,追溯到自己出生时妈妈因生女孩而悲伤的家族重男轻女 |
---
## 三、用户流程
### 3.1 流程总览
```
欢迎页 → 上传文件 → 提取故事 → 匹配确认 → 预览导出
```
采用 **线性向导式** 交互,用户依次完成四个步骤。
### 3.2 步骤指示器
- 顶部居中展示 4 个步骤节点(上传文件 → 提取故事 → 匹配确认 → 预览导出)
- 当前步骤高亮(紫色),已完成步骤显示绿色 ✓
- 步骤之间用连线表示进度
- 欢迎页不显示步骤指示器
- 步骤节点可点击跳转(已完成的步骤)
### 3.3 底部导航栏
- 固定在页面底部
- 左侧:上一步按钮(第一步时隐藏)
- 中间:当前步骤提示文案
- 右侧:下一步按钮(最后一步变为"全部导出"
- 欢迎页不显示底部导航栏
---
## 四、页面详细设计
### 4.0 欢迎页
**目的**:产品介绍 + 引导用户开始
**布局**:页面垂直居中
**内容**
- 产品 Logo紫色渐变圆角方块 + 书本图标)
- 产品名称 "Story Extractor"
- 一句话介绍:"从直播回放文字稿中AI 自动提取个人故事,与讲述者信息匹配,一键生成精美文档。"
- 四步流程预览(图标 + 标题 + 副标题):
- 📤 上传文件 — 文字稿 + 个人信息
- 🪄 提取故事 — AI 智能识别
- 🔗 匹配确认 — 人工核对
- 📄 预览导出 — 生成 DOCX
- 大号 CTA 按钮:"开始使用"
**交互**
- 点击"开始使用"进入第一步(上传文件)
- 不显示步骤指示器和底部导航栏
---
### 4.1 第一步:上传文件
**目的**:上传直播文字稿和讲述者个人信息
**布局**:左右两栏
**左栏 — 直播文字稿**
- 标题:直播文字稿(蓝色图标)+ 右侧标注 "DOCX 格式"
- 上传区域(虚线边框拖拽区):
- 图标 + "拖拽文件到此处,或点击上传"
- 提示:支持批量上传 · 仅限 .docx 格式
- 已上传文件列表:
- 每个文件显示:文件图标(蓝色 DOCX+ 文件名 + 元信息(行数、大小)
- 右侧删除按钮
**右栏 — 讲述者信息**
- 标题:讲述者信息(粉色图标)+ 右侧标注 "一人一个 DOCX"
- 上传区域(虚线边框拖拽区):
- 图标 + "拖拽文件到此处,或点击上传"
- 提示:每个讲述者一个 DOCX · 包含个人信息和照片
- 已上传文件列表:
- 每个文件显示:文件图标(粉色)+ 文件名 + 元信息(含几张照片)
- 右侧预览按钮 + 删除按钮
**交互**
- 底部导航提示:"上传文字稿和讲述者信息文件后进入下一步"
- 点击"下一步"进入第二步
---
### 4.2 第二步:提取故事
**目的**AI 自动从所有文字稿中提取学员个人故事
**进入方式**:从第一步点击"下一步"后自动进入,**自动开始提取**,无需手动触发
#### 阶段 A提取进度自动展示
**布局**:单卡片
**内容**
- 标题:"AI 正在工作中" + 右侧百分比(大号加粗)
- 进度条(粗圆角,紫色渐变填充)
- 当前处理状态:
- 运行状态指示灯(紫色脉冲动画)
- 当前文件名:"正在读取xxx.docx"
- 当前动作:
- "预处理:过滤课堂管理内容..."
- "预处理:过滤疗愈练习..."
- "智能分段:识别话题边界..."
- "故事识别:检测学员发言..."
- "故事提取:整理故事内容..."
- 三列状态卡片:
- 文件读取:`X / 23`(已读文件数 / 总文件数)
- 话题分段:`XX 段`(已分段数量)
- 故事发现:`X 个`(已发现故事数量,发现后变绿色)
**进度阶段**
1. 0-15%:读取文件,预处理(过滤课堂管理、短回应)
2. 15-40%:智能话题分段
3. 40-70%:识别学员故事片段
4. 70-95%:提取故事内容,生成标题和摘要
5. 95-100%:汇总结果
**完成时**
- 进度条变绿色
- 状态灯变绿色
- 显示"全部处理完成!共处理 X 份文字稿,发现 X 个故事"
- 1.2 秒后自动切换到故事列表
#### 阶段 B故事列表提取完成后展示
**布局**:单卡片
**内容**
- 标题:"已提取的故事" + 右侧 "共 X 个故事"
- 故事卡片列表,每个卡片包含:
- 故事标题(加粗)
- 讲述者昵称(从文字稿提取,如"14班+HCM"
- 故事摘要2-3 句话)
- 来源信息(文件名 + 行号范围 + 时长)
- 置信度标签(高/中/低)
- 操作按钮:查看原文、编辑、删除
**交互**
- 底部导航提示:"AI 已提取故事,下一步将故事与讲述者匹配"
- 点击"下一步"进入第三步(**无需全部匹配,可直接进入**
---
### 4.3 第三步:匹配确认
**目的**:将提取的故事与讲述者一一对应(可选操作)
**布局**:三栏(故事列表 | 匹配操作 | 讲述者列表)
**左栏 — 故事列表**
- 标题:"故事列表" + 右侧 "X 个故事"
- Tab 切换:全部 / 已匹配 / 未匹配
- 故事卡片列表:
- 故事标题
- 讲述者昵称(文字稿中的昵称,如"14班+HCM"
- 故事摘要(简短版)
- 匹配状态标签(已匹配显示讲述者姓名,未匹配显示"待匹配"
- 点击选中(高亮为橙色背景)
- 操作:删除(不满意的故事可直接删除)
**中间 — 匹配操作**
- 紫色圆形箭头按钮
- 提示文字:"选中故事和讲述者后点击匹配"
**右栏 — 讲述者列表**
- 标题:"讲述者" + 右侧 "共 X 人"
- 讲述者卡片列表:
- 头像(姓氏首字,紫色渐变背景)
- 姓名
- 文字稿昵称映射(如:张小花 → 14班+HCM
- 匹配状态(已匹配 X 个故事 / 未匹配)
- 点击选中(紫色边框高亮)
**交互**
- 选中左侧故事 + 选中右侧讲述者 → 点击中间箭头确认匹配
- 匹配完成后故事状态变为"已匹配"
- **可删除不满意的故事**AI 可能提取出无效故事)
- **无需全部匹配即可进入下一步**(未匹配的故事不会导出)
- 底部导航提示:"将需要的故事与讲述者匹配,未匹配的故事不会导出"
---
### 4.4 第四步:预览导出
**目的**:预览最终文档效果并导出
**布局**:左右两栏
**左栏 — 导出列表**
- 标题:"导出列表" + 右侧 "仅显示已匹配的讲述者"
- 导出项列表,每项包含:
- 状态图标(绿色 ✓ = 已匹配可导出)
- 文件名:"张小花 - 故事集.docx"
- 元信息:"X 个故事 · 含个人信息和照片"
- 预览按钮、下载按钮
- 未匹配的故事不会出现在导出列表中
**右栏 — 文档预览**
- 标题:"文档预览" + 上一个/下一个切换按钮
- 文档预览卡片(模拟 DOCX 效果):
- 顶部:紫色渐变头部
- 圆形头像占位
- 讲述者姓名
- 个人信息(性别 · 年龄 · 城市 · 职业)
- 正文区域:
- "她的故事" 标题(紫色下划线)
- 故事正文(多段落,如有多个故事依次排列)
**交互**
- 点击"上一个/下一个"切换预览不同讲述者的文档
- 点击单个下载按钮导出单个 DOCX
- 底部"全部导出"按钮(绿色)批量导出所有已匹配讲述者的文档
---
### 4.5 系统设置(弹窗)
**触发**:右上角齿轮图标
**布局**:居中弹窗 Modal
**内容**
**LLM 配置**
- API 提供商下拉选择OpenAI (GPT-4) / DeepSeek / 通义千问 / 本地 Ollama / 自定义兼容 API
- 模型名称(文本输入)
- API Base URL文本输入
- API Key密码输入
**提取参数**
- 话题分段最大长度(行数)
- 故事最小长度(行数)
- 置信度阈值(低于此值的故事标记为"低置信度"
- 并发请求数
- Temperature
**操作按钮**
- 取消、测试连接、保存
---
## 五、数据模型
### 5.1 文字稿Transcript
| 字段 | 类型 | 说明 |
|------|------|------|
| id | string | 唯一标识 |
| filename | string | 原始文件名 |
| file_path | string | 服务器存储路径 |
| line_count | int | 总行数 |
| file_size | int | 文件大小(字节) |
| status | enum | pending / processing / done / error |
| uploaded_at | datetime | 上传时间 |
### 5.2 讲述者Person
| 字段 | 类型 | 说明 |
|------|------|------|
| id | string | 唯一标识 |
| name | string | 真实姓名 |
| nickname | string | 文字稿中的昵称(如"14班+HCM" |
| filename | string | 原始 DOCX 文件名 |
| file_path | string | 服务器存储路径 |
| photo_path | string | 提取的照片路径 |
| info | json | 从 DOCX 提取的个人信息(年龄、性别、城市、职业等) |
| uploaded_at | datetime | 上传时间 |
### 5.3 故事Story
| 字段 | 类型 | 说明 |
|------|------|------|
| id | string | 唯一标识 |
| title | string | AI 生成的故事标题 |
| summary | string | AI 生成的故事摘要 |
| content | text | 完整故事内容(仅学员讲述部分,已过滤老师对话) |
| speaker_nickname | string | 文字稿中的讲述者昵称(如"14班+HCM" |
| source_transcript_id | string | 来源文字稿 ID |
| source_lines | json | 在原文中的行号范围 [{start, end}] |
| duration_minutes | float | 预估时长(分钟) |
| confidence | float | 置信度0.0-1.0 |
| person_id | string | 匹配的讲述者 ID可为空 |
| match_status | enum | pending / matched / deleted |
| created_at | datetime | 提取时间 |
### 5.4 系统配置Config
| 字段 | 类型 | 说明 |
|------|------|------|
| llm_provider | string | API 提供商 |
| llm_model | string | 模型名称 |
| llm_base_url | string | API Base URL |
| llm_api_key | string | API Key加密存储 |
| segment_max_lines | int | 话题分段最大行数 |
| story_min_lines | int | 故事最小行数 |
| confidence_threshold | float | 置信度阈值 |
| concurrency | int | 并发请求数 |
| temperature | float | Temperature |
---
## 六、输出文档模板
每个讲述者生成一份 DOCX结构如下
```
┌─────────────────────────────────┐
│ [照片] │
│ 姓名:张小花 │
│ 性别:女 年龄35岁 │
│ 城市:北京 职业:全职妈妈 │
├─────────────────────────────────┤
│ │
│ 她的故事 │
│ ───── │
│ 故事正文第一段... │
│ │
│ 故事正文第二段... │
│ │
│ (如有多个故事,依次排列) │
│ │
└─────────────────────────────────┘
```
- 简洁模板,不花哨
- 个人信息在顶部,照片居中
- 故事正文在下方(仅学员讲述内容,已过滤老师对话)
- 一位讲述者可能有多个故事,依次排列
---
## 七、非功能性需求
| 需求 | 说明 |
|------|------|
| **局域网访问** | 部署在局域网内,多人可通过浏览器访问 |
| **扩展性** | LLM 可替换,后续可扩展文章搜索引擎 |
| **数据安全** | API Key 加密存储,文件仅在服务器本地处理 |
| **并发处理** | 支持多文件并发提取,避免前端长时间等待 |
| **容错性** | 单个文件处理失败不影响其他文件 |