248 lines
12 KiB
Markdown
248 lines
12 KiB
Markdown
# 互动组件配置JSON生成器 — 需求描述
|
||
|
||
## 项目概述
|
||
从飞书wiki剧本文档出发,经过sheet数据解析、组件类型匹配、LLM驱动的jsonData生成,
|
||
最终输出组件配置JSON并持久化到本地SQLite数据库。
|
||
|
||
## 数据来源
|
||
**剧本文档表格的"组件配置"列**。多维表格(bitable)是旧的数据流程,
|
||
我们基于剧本文档进行自动化生产是新流程,目标是替换多维表格流程。
|
||
bitable数据可用于验证和参考。
|
||
|
||
## 已实现的互动类型
|
||
|
||
### 中互动(27种,v1-v3.1完成)
|
||
覆盖对话类(6)、信息类(6)、图片类(4)、其他(11)共27种中互动组件。
|
||
详见 `scripts/match_component.py` 的 `MID_INTERACTION_TYPES`。
|
||
|
||
- 每种类型使用独立的精确Prompt模板(`prompts/prompt_registry.py`)
|
||
- 角色配置通过section-character映射解析
|
||
- 教研配置文本拆解为结构化字段
|
||
- 语音识别热词自动生成(表达类组件)
|
||
|
||
### 核心互动(5种,v4-v6完成)
|
||
|
||
#### 1. 合作阅读 core_reading_order(v4)
|
||
- 7步LLM调用流水线
|
||
- 输出: taskInfo, materialInfo, flowInfo, studyInfo
|
||
- bitable wiki: H6DJweNkpigCbak2Y5LcTZ8Vnfb
|
||
|
||
#### 2. 看图选词 core_reading_imageDrag(v5)
|
||
- 5步LLM调用流水线
|
||
- 输入: 教研-导览配置 + 教研-互动配置
|
||
- 中间步骤: 学习流程配置, 互动描述
|
||
- 最终JSON: taskInfo, questionGroup, studyInfo
|
||
- bitable wiki: MVo7wugWfimJPIkxhJCcqppFnyf, table: tblKl9CGmARjpw1O
|
||
- prompt模板: `prompts/core_imagedrag_prompts.py`
|
||
|
||
#### 3. 口语快答 core_speaking_reply(v5)
|
||
- 7步LLM调用流水线
|
||
- 输入: 教研-用户视角任务信息 + 教研-任务规则与NPC设定
|
||
- 中间步骤: 学习流程配置, promptInfo配置, 语音识别热词
|
||
- 最终JSON: taskInfo, dialogSetting, dialogConfig, studyInfo
|
||
- bitable wiki: TSwcw0nFmi21khkpUndchNMsn6f, table: tbl4Qg8d45O58Cqf
|
||
- prompt模板: `prompts/core_speaking_prompts.py`
|
||
|
||
#### 4. 口语妙问 core_speaking_inquiry(v6)
|
||
- 7步LLM调用流水线
|
||
- 输入: 教研-用户视角任务信息 + 教研-任务规则与NPC设定
|
||
- 中间步骤: 学习流程配置, promptInfo配置(NPC角色扮演被动问答型), 语音识别热词
|
||
- 最终JSON: taskInfo, dialogSetting, dialogConfig, studyInfo
|
||
- 与口语快答的关键差异: Step2生成被动型NPC角色提示词(含知识库),而非主动提问型
|
||
- bitable wiki: GJUVwNSEkis3EXkrVj0ccbqdn8c, table: tbl1Q68oopST9Mel
|
||
- prompt模板: `prompts/core_speaking_inquiry_prompts.py`
|
||
|
||
#### 5. 看图说话 core_speaking_image(v6)
|
||
- 8步LLM调用流水线
|
||
- 输入: 教研-导览配置 + 教研-对话配置
|
||
- 中间步骤: 学习流程配置, 语音识别热词
|
||
- 最终JSON: taskInfo, dialogConfig, imageInfo, optionList, questionList, studyInfo
|
||
- Step7(dialogConfig)依赖Step6(questionList), Step8(studyInfo)依赖Step1(学习流程配置)
|
||
- bitable wiki: KBOXwzVHfin6ORkKbA3c3eWEnoh, table: tblvi5HF0uSU2GNo
|
||
- prompt模板: `prompts/core_speaking_image_prompts.py`
|
||
|
||
## 通用机制:resourceMapping
|
||
|
||
**所有核心互动都使用统一的 resourceMapping 处理逻辑**,不是某个类型的特有字段:
|
||
|
||
1. **数据来源**: `parse_script.py` 提取两级角色映射:
|
||
- `section_char_map`: 从文档"角色-section对应"表解析,按section分组
|
||
- `character_map`: 从sheet数据全局提取,作为fallback
|
||
2. **解析流程**: `generate_json.py` → `resolve_resource_mapping()` 解析section对应 → 格式化为 `"Name:ID"` 字符串 → 注入prompt的 `{角色配置}` 占位符
|
||
3. **LLM提取**: prompt模板统一指示LLM从 `{角色配置}` 提取 `{"name": int_id}` JSON对象
|
||
4. **npcName#id规则**: 部分类型(合作阅读、合作听力)在 textData/sequenceData 步骤中,npcName字段追加 `#id`(仅限npcName字段,不适用于content等字段)
|
||
|
||
## 已实现的核心互动类型(续)
|
||
|
||
### v7 — 听力类(3种,已完成)
|
||
详见 `prd/v7.md`,bitable 数据已验证
|
||
|
||
| 类型 | cType | LLM步数 | 输出字段 | bitable wiki |
|
||
|------|-------|---------|---------|-------------|
|
||
| 合作听力 | core_listening_order | 6 | taskInfo, materialInfo, flowInfo, studyInfo | FrxtwNRQDizqiikPkATcBzTCnYe |
|
||
| 听力拖拽 | core_listening_drag | 7 | taskInfo, preDialog, dialogList, questionList, studyInfo | K3QrwQnWqiPBm1krhnNcWDTqnhe |
|
||
| 听力选择 | core_listening_choose | 5 | taskInfo, questionGroup, studyInfo | Kwrcw6A4jip2sxkdLn4czd1knvf |
|
||
|
||
- 输入: 合作听力用 `教研配置-任务` + `教研配置-材料`;听力拖拽/选择用 `教研配置-导览配置` + `教研配置-互动配置`
|
||
- 中间步骤: 学习过程配置(LLM生成) + 互动描述(LLM生成)
|
||
- 合作听力的听音选意用2个中文含义选项;听力拖拽/选择改为"对/错"判断题
|
||
- 所有taskInfo均包含 resourceMapping(通用机制)
|
||
- 专有名词对照暂不实现,后续单独处理
|
||
- prompt模板: `prompts/core_listening_order_prompts.py`, `prompts/core_listening_drag_prompts.py`, `prompts/core_listening_choose_prompts.py`
|
||
|
||
## 待实现的核心互动类型
|
||
|
||
### v8 — 写作类(4种,已完成)
|
||
详见 `prd/v8.md`,bitable 数据已验证
|
||
|
||
| 类型 | cType | LLM步数 | 输出字段 | bitable wiki |
|
||
|------|-------|---------|---------|-------------|
|
||
| 看图组句 | core_writing_imgMakeSentence | 6 | taskInfo, textInfo, studyInfo, evalInfo | BkmtwUBwMiHd5Ak7VS6ccE9SnHd |
|
||
| 看图撰写 | core_writing_imgWrite | 6 | taskInfo, textInfo, studyInfo, evalInfo | KwPHwnaqdiWlvNkDm5fcFreDnQh |
|
||
| 邮件组句 | core_writing_questionMakeSentence | 6 | taskInfo, textInfo, studyInfo, evalInfo | M5oTwUP6wiImC4kVJU8cRYnfnyf |
|
||
| 邮件撰写 | core_writing_questionWrite | 6 | taskInfo, textInfo, studyInfo, evalInfo | Brn0wldKYizsLZkBqK6clp1tnKd |
|
||
|
||
- 输入: `教研配置-任务信息` + `教研配置-全文信息`
|
||
- 中间步骤: 学习流程配置(LLM生成) + 互动描述(LLM生成)
|
||
- 4种类型共享通用6步流水线 `_generate_core_writing()`
|
||
- 按输入源特征分为2个prompt文件: `core_writing_img_prompts.py`(看图类) + `core_writing_question_prompts.py`(邮件类)
|
||
- 关键差异: 看图类stemDesc=图片列表+leadIn用image;邮件类stemDesc=题干描述+leadIn用desc
|
||
- 组句类inputType=sentence(optionList+answer);撰写类inputType=write(answerText+hint)
|
||
- prompt模板: `prompts/core_writing_img_prompts.py`, `prompts/core_writing_question_prompts.py`
|
||
|
||
### 其他未实现类型
|
||
- 口语独白、口语探讨
|
||
- 写作互动
|
||
|
||
## v9 — 中互动 cDesc 互动描述预生成(已完成)
|
||
详见 `prd/v9.md`
|
||
|
||
为 10 种中互动类型增加 cDesc(互动描述)LLM 预生成步骤:
|
||
- 信息类(6种): mid_message_trace/spell/combine/fillin/word/sentence
|
||
- 图片类(4种): mid_image_choose/multiple/sequence/drag
|
||
|
||
实现方式:
|
||
- 在 `_generate_with_template()` 中,jsonData 生成前调用 LLM 预生成互动描述
|
||
- 信息类使用 `CDESC_PROMPT_MESSAGE` 模板(输入: 互动名称 + 互动内容)
|
||
- 图片类使用 `CDESC_PROMPT_IMAGE` 模板(输入: 互动名称 + 情境引入 + 互动内容 + 互动反馈 + 后置对话)
|
||
- 生成结果注入 `parsed_fields["互动描述"]`,由主 prompt 模板映射到 jsonData 的 `cDesc` 字段
|
||
- 补全了 `mid_image_sequence` 模板中遗漏的 cDesc 字段定义
|
||
- 始终使用 LLM 生成,覆盖教研配置中可能存在的值
|
||
|
||
## v10 — 知识点匹配 + 触发命令 + HTML增强(已完成)
|
||
详见 `prd/v10.md`
|
||
|
||
### 知识点匹配功能
|
||
- 新增 `scripts/kp_matcher.py`:连接 MySQL `vala_test.vala_kp` 表(2613条有效记录)
|
||
- 两阶段匹配:title 精确/模糊粗召回 → LLM 多候选精筛(用于同名不同释义消歧)
|
||
- kpInfo 中 `kpId` 从数据库 `kp_id` 字段获取,`kpType` 从 `type` 字段获取
|
||
- kpSkill 使用默认值(vocab→vocab_meaning, sentence→sentence_meaning)
|
||
- MySQL 不可达时 fallback 到 kpId=null
|
||
|
||
### 集成改动
|
||
- `generate_json.py`:所有 `_try_rule_based_kp` 调用替换为 `generate_kp_info()` → `kp_matcher.match_knowledge_points()`
|
||
- 所有核心互动生成器(12个)和中互动入口统一使用新接口
|
||
- 新增 `level` 参数贯穿 pipeline → generate_component → 各生成器 → kp_matcher
|
||
|
||
### 触发命令
|
||
- SKILL.md 添加触发场景:`*组件配置-json* {飞书剧本文档链接}`
|
||
- 触发后执行完整 pipeline,返回 HTML 报告
|
||
|
||
### HTML 增强
|
||
- 中互动组件在 HTML 报告中也展示 kpInfo section(之前仅核心互动展示)
|
||
|
||
## v11 — 字段重命名 + 交互式HTML + 推送功能(已完成)
|
||
详见 `prd/v11.md`
|
||
|
||
### 字段重命名(方案B:全量重命名为推送接口字段名)
|
||
- 所有核心互动输出字段统一改名为推送接口字段名
|
||
- 映射: taskData→taskInfo, textData→materialInfo, sequenceData→flowInfo, learningData→studyInfo,
|
||
settingData→dialogSetting, configData→dialogConfig, questionGroupData→questionGroup,
|
||
studyData→studyInfo, preDialogData→preDialog, dialogListData→dialogList, questionListData→questionList
|
||
- 涉及文件: generate_json.py, pipeline.py, db_manager.py, html_report.py, validate_core_v5.py
|
||
|
||
### 交互式HTML报告(v2)
|
||
- 每个JSON section使用 textarea 可直接编辑
|
||
- kpId 使用下拉选择(显示粗筛 top10 候选)
|
||
- 每个组件 header 内嵌两个推送按钮:[配置↑] [知识↑]
|
||
- 顶部固定操作栏:一键推送全部 + 进度条 + 成功/失败统计
|
||
- 推送状态实时指示(loading/ok/fail)
|
||
|
||
### 推送接口
|
||
- POST https://api-test.valavala.com/content/feishu/notify
|
||
- 中互动: `{"componentData": jsonData}`
|
||
- 核心互动: `{"pushType":"core", ...各字段}`(按cType不同组装)
|
||
- 知识点: `{"pushRelationKp": kpInfoObj}`
|
||
|
||
### kp_matcher增强
|
||
- 粗召回加 LIMIT 10
|
||
- 每条知识点匹配结果附带 `candidates` 字段(top10候选)供HTML下拉展示
|
||
|
||
## 参考文档
|
||
- v11需求详细文档: `prd/v11.md`
|
||
- v10需求详细文档: `prd/v10.md`
|
||
- v9需求详细文档: `prd/v9.md`
|
||
- v8需求详细文档: `prd/v8.md`
|
||
- v7需求详细文档: `prd/v7.md`
|
||
- v6需求详细文档: `prd/v6.md`
|
||
- v5需求详细文档: `prd/v5.md`
|
||
- v4需求详细文档: `prd/v4.md`
|
||
- 组件类型注册表: `references/component_registry.md`
|
||
|
||
## v12 — 解析增强 + pipeline 自动 HTML + 进度输出(已完成)
|
||
|
||
### 组件行识别增强(parse_script.py)
|
||
- 支持单行空格分隔格式: `"合作阅读 0000800"` → type_name + cId
|
||
- 支持多行带前缀格式: `"核心互动- 囗语\n听力选择\n0000810"` → 跳过前缀取实际类型
|
||
- LLM 兜底: 正则无法提取时,如果 cell 含中文+5位以上数字,调 LLM 解析(带缓存)
|
||
- 测试文档识别率: 15 → 42 组件
|
||
|
||
### pipeline 自动生成交互式 HTML
|
||
- 无需 `--dry-run --html` 参数,执行完自动生成 v2 交互式 HTML 报告
|
||
- 非 dry-run 模式也保留完整 jsonData/kpInfo 到 report results
|
||
- report 返回 `html_path` 字段供外部调用者使用
|
||
|
||
### 进度输出
|
||
- 每个组件完成后打印 ✓/✗ 状态行
|
||
- 每 5 个组件输出进度摘要(成功/失败/跳过计数)
|
||
- 末尾输出最终统计
|
||
|
||
### cType=None 优雅跳过
|
||
- 未实现类型(口语独白、口语探讨、写作互动)标记为 skipped,不触发异常
|
||
|
||
## v13 — CORS 代理服务(已完成)
|
||
|
||
### 问题背景
|
||
用户直接打开本地HTML文件(file://协议)点击推送按钮时,浏览器发送 `Origin: null`,
|
||
目标API服务端校验 Origin 返回 403。curl 直接测试正常但浏览器无法绕过。
|
||
|
||
### 解决方案:轻量代理中转服务
|
||
- 新增 `scripts/proxy_server.py`:基于 http.server + requests 的转发代理
|
||
- 新增 `config.json`:代理配置(外网IP、端口、速率限制、目标URL)
|
||
- 代理只转发到固定目标地址,加上正确的 Origin 头
|
||
- HTML 报告中 API 地址改为代理地址
|
||
|
||
### 安全措施
|
||
- 硬编码单一目标URL(不可被滥用为开放代理)
|
||
- body 结构校验(必须含 componentData/pushRelationKp/pushType)
|
||
- 可配置速率限制(默认 60 req/min/IP)
|
||
- 专用端口 18080,用户在安全组中精确控制
|
||
|
||
### 集成方式
|
||
- pipeline 执行时自动检测代理运行状态(GET /health)
|
||
- 未运行则 subprocess 自动后台启动
|
||
- 代理 URL 传入 html_report 生成到 HTML 的默认 API 地址中
|
||
|
||
### 配置文件 config.json
|
||
```json
|
||
{
|
||
"proxy": {
|
||
"external_ip": "115.190.225.235",
|
||
"port": 18080,
|
||
"rate_limit_per_minute": 60,
|
||
"target_url": "https://api-test.valavala.com/content/feishu/notify",
|
||
"target_origin": "https://flow-test.valavala.com"
|
||
}
|
||
}
|
||
```
|