Implement unified story generation flow
This commit is contained in:
54
docs/technical/environment-configuration.md
Normal file
54
docs/technical/environment-configuration.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# 环境变量配置约定
|
||||
|
||||
DreamWeaver 只把 `backend/.env` 视为应用运行配置文件。根目录 `.env` 可以存在,但它只服务 Docker Compose 本身,不参与后端配置加载。
|
||||
|
||||
## 文件职责
|
||||
|
||||
| 文件 | 读取方 | 放什么 | 不放什么 |
|
||||
| --- | --- | --- | --- |
|
||||
| `backend/.env` | FastAPI、Admin API、Celery worker、Celery beat、Docker 后端服务 | `SECRET_KEY`、`DATABASE_URL`、Redis/Celery URL、Provider 列表、AI key、OAuth key、Admin 账号 | Docker 镜像源、npm registry |
|
||||
| `.env` | Docker Compose 插值 | `PYTHON_BASE_IMAGE`、`NODE_BASE_IMAGE`、`NGINX_BASE_IMAGE`、`NPM_REGISTRY` 等镜像源/registry 覆盖 | AI key、OAuth key、`SECRET_KEY`、后端运行配置 |
|
||||
| `backend/.env.example` | 人读/复制模板 | `backend/.env` 的完整示例 | 真实密钥 |
|
||||
|
||||
## 为什么不让后端读取根目录 `.env`
|
||||
|
||||
`pydantic-settings` 的相对 `env_file=".env"` 会受当前工作目录影响:在仓库根目录启动会读根 `.env`,在 `backend/` 目录启动会读 `backend/.env`。这会导致同一条启动命令在不同目录下使用不同配置。
|
||||
|
||||
当前代码在 `backend/app/core/config.py` 中固定使用绝对路径 `backend/.env`。因此后端从任意工作目录启动时都读取同一个文件。
|
||||
|
||||
## Docker 演示
|
||||
|
||||
Docker 后端服务通过 `env_file: ./backend/.env` 读取应用配置。默认容器内地址应保持为服务名:
|
||||
|
||||
```env
|
||||
DATABASE_URL=postgresql+asyncpg://dreamweaver:dreamweaver_password@db:5432/dreamweaver_db
|
||||
CELERY_BROKER_URL=redis://redis:6379/0
|
||||
CELERY_RESULT_BACKEND=redis://redis:6379/0
|
||||
REDIS_URL=redis://redis:6379/0
|
||||
```
|
||||
|
||||
Postgres 容器只接收 `docker-compose.yml` 中固定的 demo 账号和数据库名,避免把 AI/OAuth key 注入基础设施容器。后端服务读取 `backend/.env` 中的 `DATABASE_URL`。需要改 Docker demo 的数据库账号时,同时修改 `docker-compose.yml` 的 `db.environment` 和 `backend/.env` 的 `DATABASE_URL`。Docker demo 固定暴露 `52432:5432` 和 `52379:6379`,本机直跑后端时按这些宿主机端口连接。
|
||||
|
||||
## 本机直跑后端
|
||||
|
||||
本机直接运行 `uvicorn`、`celery` 或 `alembic` 时也只改 `backend/.env`,把数据库和 Redis URL 改成宿主机端口:
|
||||
|
||||
```env
|
||||
DATABASE_URL=postgresql+asyncpg://dreamweaver:dreamweaver_password@localhost:52432/dreamweaver_db
|
||||
CELERY_BROKER_URL=redis://localhost:52379/0
|
||||
CELERY_RESULT_BACKEND=redis://localhost:52379/0
|
||||
REDIS_URL=redis://localhost:52379/0
|
||||
```
|
||||
|
||||
## 检查命令
|
||||
|
||||
```bash
|
||||
# 后端实际读取哪个 env 文件
|
||||
backend/.venv/bin/python - <<'PY'
|
||||
from app.core.config import BACKEND_ENV_FILE
|
||||
print(BACKEND_ENV_FILE)
|
||||
PY
|
||||
|
||||
# Docker 后端容器实际环境,注意不要把输出贴到公共渠道
|
||||
docker compose exec backend env | sort
|
||||
```
|
||||
@@ -25,7 +25,7 @@
|
||||
- 当 `transcript_confidence` 或 `intent_confidence` 偏低时,后端优先返回确认提示,而不是直接把这一轮写进故事正文
|
||||
- 已补完整确认流:支持“按这个理解继续”“重说本轮”“改成文本输入”
|
||||
- 前端明确展示“本轮系统理解为”与“建议家长确认后再继续”提示
|
||||
- 低置信度确认链路已有后端测试覆盖,可作为下一阶段继续接 ASR 与更细确认交互的基础
|
||||
- 低置信度确认链路已有后端测试覆盖,可作为下一阶段继续验收真实 ASR Key 环境与更细确认交互的基础
|
||||
- 已新增用户转写安全检查、assistant 输出柔性改写与 `safety_flags` 事件记录
|
||||
- finalize 会生成更稳定的标题/摘要,并在条件允许时自动排队封面补全 job
|
||||
- 已新增 `voice session analytics` 聚合指标,可跟踪 turn 成功率、ASR/TTS 失败、低置信度触发、finalize 转化率、输入构成、语音时长、Provider 分布、确认率和平均置信度,并支持按转写 Provider 与会话状态筛选
|
||||
@@ -52,7 +52,7 @@ Phase A 明确不做以下内容:
|
||||
- 不做多人共创
|
||||
- 不做绘本共创主链路
|
||||
- 不做每回合即时插图生成
|
||||
- 不把 ASR / Realtime 能力立刻并入当前 admin Provider 配置面板
|
||||
- 不把 Realtime 能力立刻并入当前 admin Provider 配置面板;ASR 已作为 Alpha 运营观测能力进入 Provider 体系
|
||||
|
||||
换句话说,Phase A 是一个 **回合式 voice session MVP**,不是最终形态。
|
||||
|
||||
@@ -93,13 +93,13 @@ Phase A 明确不做以下内容:
|
||||
- `tts` Provider Router
|
||||
- 现有故事库、故事详情页和后续资产补全链路
|
||||
|
||||
### 4.2 当前明显缺失的能力
|
||||
### 4.2 初始设计时明显缺失、Alpha 已补齐的能力
|
||||
|
||||
- 语音输入识别(ASR / STT)
|
||||
- 会话级状态模型
|
||||
- “剧情修正”语义解析
|
||||
- 会话级可观测事件
|
||||
- 从 voice session 保存为正式 Story 的收束服务
|
||||
- 语音输入识别(ASR / STT):已通过 `asr` Provider capability、demo fallback 和 `openai_asr` 适配器补齐,真实 Key 环境仍需验收。
|
||||
- 会话级状态模型:已落地 `voice_sessions / voice_turns / voice_session_events`。
|
||||
- “剧情修正”语义解析:Alpha 已支持 start / continue / correct 等回合意图。
|
||||
- 会话级可观测事件:已支持 voice session analytics、事件列表和管理端 ASR 摘要。
|
||||
- 从 voice session 保存为正式 Story 的收束服务:已支持 finalize 保存为 Story,并接回 generation job 资产补全。
|
||||
|
||||
---
|
||||
|
||||
@@ -115,7 +115,7 @@ Phase A 明确不做以下内容:
|
||||
`voice_sessions` 管过程,`stories` 管正式结果,避免把会话噪音直接污染正式故事结构。
|
||||
|
||||
4. **先复用 `text` / `tts` 主干,再决定是否拆新 capability**
|
||||
首版把复杂度压到最小,不急着把所有新能力都映射进 admin Provider 面板。
|
||||
首版把复杂度压到最小,不急着把 realtime / barge-in 等新能力映射进 admin Provider 面板。ASR 现在只作为回合式转写能力进入 Provider 体系。
|
||||
|
||||
5. **首版允许“文本可用但语音失败”降级**
|
||||
这与当前 DreamWeaver 主结果优先可读的原则一致。
|
||||
@@ -440,14 +440,29 @@ Phase A 明确不做以下内容:
|
||||
|
||||
**建议**
|
||||
|
||||
- Phase A 先接单一稳定供应商
|
||||
- 暂不并入当前 admin Provider CRUD
|
||||
- 先通过配置文件或单独 service 封装
|
||||
- Phase A 先接单一稳定供应商,并保留 demo fallback
|
||||
- 已并入当前 admin Provider CRUD 和运营摘要,但不引入 realtime 复杂配置
|
||||
- 先通过配置文件或单独 service 封装真实 Key 环境差异
|
||||
- 真实 Key 验收用 `SMOKE_REAL_ASR=1 ./scripts/demo_smoke.sh`,只在显式打开时调用外部 ASR
|
||||
|
||||
理由是:
|
||||
|
||||
- 当前 admin Provider 已扩展到 `text/image/tts/storybook/asr`
|
||||
- Phase A Alpha 已把 ASR 纳入最小 Provider 能力,但仍保留 demo fallback,避免真实转写不可用时阻塞演示
|
||||
- `openai_asr` 默认读取 `OPENAI_API_KEY`、可选 `OPENAI_API_BASE`、`VOICE_TRANSCRIPTION_MODEL` 和 `VOICE_TRANSCRIPTION_LANGUAGE`
|
||||
|
||||
真实 ASR 验收最小 `.env`:
|
||||
|
||||
```env
|
||||
ASR_PROVIDERS=["openai_asr", "demo"]
|
||||
OPENAI_API_KEY=sk-...
|
||||
OPENAI_API_BASE=
|
||||
VOICE_TRANSCRIPTION_MODE=provider
|
||||
VOICE_TRANSCRIPTION_MODEL=gpt-4o-mini-transcribe
|
||||
VOICE_TRANSCRIPTION_LANGUAGE=zh
|
||||
```
|
||||
|
||||
失败时优先看三处:上传接口响应、`turn_transcription_failed` 事件、Admin Provider analytics 的 `capability=asr` failure reasons。常见原因是 key 没进容器、401/403、429/额度不足、模型不可用、`OPENAI_API_BASE` 指向错误或音频格式不被接受。
|
||||
|
||||
### B. Dialogue Orchestrator
|
||||
|
||||
@@ -537,7 +552,36 @@ Phase A 就应该按 turn 记录:
|
||||
- 对话生成成本
|
||||
- TTS 成本
|
||||
|
||||
这部分后续可以汇总到新的语音共创 analytics,而不是一开始就挤进现有故事生成 dashboard。
|
||||
当前 Alpha 已把 ASR 成本和调用摘要接入管理端 Provider analytics。短期这样可以让运营视角统一看到 text/image/tts/storybook/asr;中期如果语音共创继续扩大,应把 voice session analytics 保持为主视图,把 admin Provider analytics 只作为跨能力成本与失败原因摘要。
|
||||
|
||||
### 13.3 服务复杂度自审(2026-05-06)
|
||||
|
||||
当前 Alpha 已经验证主链路,但服务边界开始接近需要拆分的程度:
|
||||
|
||||
| 模块 | 当前职责 | 复杂度信号 | 建议拆分 |
|
||||
| --- | --- | --- | --- |
|
||||
| `voice_session_service.py` | 会话 CRUD、turn 创建、意图识别、故事 patch、低置信度确认、安全改写、TTS、finalize、analytics | 文件已接近 2000 行;同步处理状态机、AI 编排和响应序列化,单次改动容易波及多条路径 | 优先拆 `voice_turn_orchestrator.py`、`voice_session_analytics.py`、`voice_session_finalizer.py` |
|
||||
| `generation_jobs.py` + `admin_provider_analytics.py` | generation job/event、任务控制、provider stats、ops summary;管理端跨用户 Provider/ASR 摘要已拆到独立 service | `generation_jobs.py` 仍偏大,但 ASR 管理端摘要已不再继续塞进 generation job 模块 | 后续继续把 `generation_jobs.py` 内部 provider telemetry helper 拆为共享小模块,保留 generation job 主流程聚焦任务状态 |
|
||||
| `voice_transcription_service.py` | ASR mode 解析与 provider router 调用 | 仍较小,但失败元数据不足,admin ASR 失败只能从事件里读 `error` | 后续补 `VoiceTranscriptionAttempt` 风格的轻量结果结构,统一 provider、latency、cost、error |
|
||||
| 前端 `VoiceStudio.vue` | 页面状态、录音上传、会话列表、turn 展示、analytics 卡片、确认/重试/finalize | 视图文件承担了太多 workflow 判断;继续加实时能力会变得难测 | 拆出 `useVoiceSessionWorkflow`、`VoiceTurnCard`、`VoiceAnalyticsPanel` |
|
||||
|
||||
建议拆分顺序:
|
||||
|
||||
1. 先拆只读 analytics:风险最低,测试可以复用现有 `test_voice_sessions.py` 与 `test_admin_providers.py`。2026-05-06 已先拆出管理端 `admin_provider_analytics.py`。
|
||||
2. 再拆 finalize:边界清晰,输入是 session,输出是 Story / generation job。
|
||||
3. 最后拆 turn orchestrator:它耦合 ASR、意图、故事 patch、安全和 TTS,应等回归矩阵更稳定后再动。
|
||||
|
||||
暂不建议在 Phase A Alpha 末尾做的大改:
|
||||
|
||||
- 不引入工作流引擎替代当前状态机。
|
||||
- 不把 voice session 直接塞进 generation job 主模型。
|
||||
- 不在 ASR 事件上新增迁移字段,除非要做精确延迟分布和供应商级 SLA。
|
||||
|
||||
触发必须拆分的信号:
|
||||
|
||||
- 单个 voice turn 改动需要同时修改 3 个以上测试文件。
|
||||
- 新增一个 analytics 字段需要读写多个无关 service。
|
||||
- Voice Studio 引入实时或准实时能力前,仍没有可复用 composable。
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user