Explorar el Código

docs: update dialogue chat engine design, proposal, and task documentation

jimmylee hace 2 meses
padre
commit
3ddfaf791c

+ 11 - 7
openspec/changes/dialogue-chat-engine/design.md

@@ -82,11 +82,14 @@ interface DialogueAPI {
 **实现**: `MockDialogueAPI`(开发用)和 `RealDialogueAPI`(对接真实后端)
 通过前端 prop `mode: 'preview' | 'real'` 切换
 
-### Decision 6: TTS 使用前端 Web Speech API(v1)
+### Decision 6: TTS 使用前端 Azure TTS
 
-**选择**: AI 消息 `done` 后调用 `speechSynthesis.speak()` 朗读
+**选择**: AI 消息 `done` 后,前端整段文本调用 Azure TTS 合成语音并播放
 
-**理由**: 零后端改动,3 行代码立即可用。质量不够后续升级 Azure TTS
+**理由**:
+- 前端已通过 SSE 接收完整文本,直接调 Azure TTS 最简单
+- AI 回复限定 1-2 句(system prompt 约束),不需要分句 TTS
+- 不做服务端 TTS,后端不涉及语音合成
 
 ---
 
@@ -115,7 +118,7 @@ cococlass-english-speaking-api(编排层)
 | LLM | Chat Completions via One-Hub(openai SDK) |
 | ASR | Azure Speech(纯转录模式) |
 | 发音评估 | Azure Speech Pronunciation Assessment(后台) |
-| SSE | FastAPI StreamingResponse |
+| SSE | FastAPI 原生 EventSourceResponse + ServerSentEvent |
 | 数据库 | MySQL + asyncmy + SQLAlchemy 2.0 |
 | 存储 | S3(boto3) |
 | 配置 | pydantic-settings + python-dotenv |
@@ -145,12 +148,12 @@ ASRProvider / LLMProvider / PronunciationAssessor / AudioStorage 四个 Protocol
 ```
 POST /api/speaking/dialogue/session   → JSON { sessionId, aiMessage }
 POST /api/speaking/dialogue/speak     → SSE { transcript, token, done }
-GET  /api/speaking/dialogue/report    → 延后(结果页方案待确认)
+GET  /api/speaking/dialogue/report    → JSON { 对话历史 + 评分 + LLM 总结 }
 ```
 
 ### 数据模型
 
-- **DialogueSession**: id, user_id, topic, role_config, total_rounds, current_round, status, system_prompt, created_at, completed_at
+- **DialogueSession**: id, user_id, topic, role_config, total_rounds, current_round, status, system_prompt, expires_at, summary, created_at, completed_at
 - **DialogueMessage**: id, session_id, round, role, content, audio_url, created_at
 - **PronunciationEvaluation**: id, message_id, session_id, round, status, accuracy/fluency/completeness/prosody scores, word_analysis, created_at, completed_at
 
@@ -162,4 +165,5 @@ GET  /api/speaking/dialogue/report    → 延后(结果页方案待确认)
 - **[流式解析差异]** → 在 adapter 层做格式解析,engine 层只关心 token string
 - **[录音权限拒绝]** → composable 暴露 permissionState,UI 显示引导提示
 - **[内存泄漏]** → 在 composable 的 `onUnmounted` 中统一清理录音 Blob
-- **[后台评估未完成]** → /report 接口最多等 5 秒,超时返回部分结果
+- **[后台评估未完成]** → 前端轮询 GET /report(每 2 秒),30 秒超时后展示已有结果,缺失的标记为"评估不可用"。评估记录在 speak 主流程中创建(保证记录一定存在),后台任务只负责更新结果
+- **[定时结束]** → 后端通过 `expires_at` 判断,`/speak` 时检查是否超时。前端用 `expires_at` 显示倒计时,不再是纯前端控制

+ 15 - 26
openspec/changes/dialogue-chat-engine/proposal.md

@@ -1,25 +1,22 @@
 ## Why
 
-当前 `DialogueChatView.vue` 的对话逻辑全部基于硬编码的 mock 脚本,没有真实的录音采集、LLM 对话、发音评估能力。要实现完整的英语口语对话功能,需要:
-- 前端:将对话引擎从 UI 层解耦,建立三层架构,处理录音 → 上传 → 流式回复的完整 pipeline
-- 后端:新建独立编排服务 `cococlass-english-speaking-api`,串联 ASR、LLM、发音评估
+当前 `DialogueChatView.vue` 的对话逻辑全部基于硬编码的 mock 脚本,没有真实的录音采集、LLM 对话、发音评估能力。要让学生能够进行真正的英语口语对话练习,需要将 mock 替换为完整的前后端对话链路。
 
 ## What Changes
 
 ### 前端
-- **新增 `llmService.ts`**:API 通信层,封装 fetch + ReadableStream 实现流式 SSE 读取
-- **新增 `useDialogueEngine.ts`**:Vue composable,管理对话状态机(loading / done / error)
-- **新增 `useAudioRecorder.ts`**:Vue composable,封装 MediaRecorder API 实现录音采集
-- **重构 `DialogueChatView.vue`**:移除所有 mock 逻辑,改为纯 UI 层
-- **扩展 `PreviewChatMessage` 类型**:新增 `status`(loading/done/error)、`error`、`audioBlob` 字段
-- **新增 TTS**:AI 消息完成后调用 Web Speech API 朗读(v1)
-- **新增倒计时**:支持限制对话时间,时间到后让当前轮完成再自动结束(纯前端,不影响后端)
-
-### 后端(cococlass-english-speaking-api)
-- **POST /session**:创建对话 + AI 开场白
-- **POST /speak**:接收音频 → ASR 转录 → LLM 流式回复(SSE)→ 后台静默发音评估
-- **GET /report**:返回完整对话历史 + 评估结果
-- **init.sql**:3 张表建表脚本(DialogueSession / DialogueMessage / PronunciationEvaluation),git 管理,手动执行
+- 将对话引擎从 UI 组件中解耦为独立的 service + composable 三层架构
+- 新增 LLM 流式通信能力,支持逐 token 渲染 AI 回复
+- 新增浏览器端录音采集能力,含权限处理
+- 重构 `DialogueChatView.vue` 为纯 UI 层,移除所有 mock 逻辑
+- 新增消息状态机(loading / done / error)和重试机制
+- AI 消息完成后调用 TTS 合成语音并播放
+- 后端控制对话时长,前端展示倒计时
+
+### 后端
+- 新建独立编排服务 `cococlass-english-speaking-api`,串联 ASR、LLM、发音评估
+- 提供对话创建、语音对话(流式)、报告查询三个接口
+- 发音评估后台静默执行,不阻塞对话流程
 
 ## Capabilities
 
@@ -33,13 +30,5 @@ _(无已有 specs 需要修改)_
 
 ## Impact
 
-- **前端受影响文件**:
-  - `src/views/Editor/EnglishSpeaking/preview/DialogueChatView.vue`(重构)
-  - `src/types/englishSpeaking.ts`(扩展类型)
-  - `src/views/Editor/EnglishSpeaking/preview/TopicDiscussionPreview.vue`(适配)
-- **前端新增文件**:
-  - `src/views/Editor/EnglishSpeaking/composables/useDialogueEngine.ts`
-  - `src/views/Editor/EnglishSpeaking/composables/useAudioRecorder.ts`
-  - `src/views/Editor/EnglishSpeaking/services/llmService.ts`
-- **前端依赖**:无新增 npm 依赖,使用浏览器原生 API
-- **后端项目**:`cococlass-english-speaking-api`(独立 repo)
+- **前端**:EnglishSpeaking preview 模块重构(DialogueChatView 及关联组件),扩展消息类型定义,新增 composables 和 service 层。无新增 npm 依赖,使用浏览器原生 API
+- **后端**:新增独立项目 `cococlass-english-speaking-api`,需要 MySQL、S3、Azure Speech、One-Hub 等外部依赖

+ 3 - 1
openspec/changes/dialogue-chat-engine/tasks.md

@@ -30,7 +30,9 @@
 - [ ] 4.5 实现轮次推进:收到 done 事件后判断是否结束
 - [ ] 4.6 实现录音按钮锁定:loading 时禁用
 - [ ] 4.7 实现 adapter 注入:通过 mode prop 选择 Mock/Real
-- [ ] 4.8 实现 TTS:AI 消息 done 后调用 Web Speech API 朗读
+- [ ] 4.8 实现 TTS:AI 消息 done 后调用 Azure TTS 合成语音并播放
+- [ ] 4.9 实现倒计时 UI:用后端返回的 `expires_at` 显示倒计时
+- [ ] 4.10 实现报告页轮询:每 2 秒轮询 GET /report,30 秒超时兜底
 
 ### 5. 重构 DialogueChatView.vue