# DreamWeaver 梦语织机 AI 儿童故事生成应用,面向 3-8 岁儿童与家长,支持关键词生成故事、绘本页生成、封面图生成、语音朗读、孩子档案、故事宇宙与 Provider 管理。 当前仓库优先服务一个目标:本地 Docker 环境中稳定跑通完整产品闭环,便于求职演示和后续迭代。 ## 技术栈 - 后端:FastAPI、SQLAlchemy async、PostgreSQL、Celery、Redis - 前端:Vue 3、TypeScript、Pinia、Vue Router、Tailwind CSS、Vite - 认证:OAuth 2.0 + JWT httpOnly cookie,本地演示支持 dev login - AI:文本、图片、TTS、绘本结构生成均通过 adapter/provider router 接入 ## 仓库结构 ```text backend/ FastAPI 后端、Celery 任务、数据库迁移 frontend/ 用户端 Vue 应用 admin-frontend/ 管理端 Vue 应用 docs/ 当前产品、规划与技术文档 docker-compose.yml ``` ## 环境变量文件 仓库里可能同时出现两个被 git 忽略的 env 文件,它们职责不同: - `backend/.env`:应用运行配置。后端 API、管理后端、Celery worker、Celery beat 都读取这个文件;AI key、OAuth key、`SECRET_KEY`、`DATABASE_URL`、Provider 列表都放这里。 - 根目录 `.env`:仅供 Docker Compose 做构建覆盖。这里只放 `PYTHON_BASE_IMAGE`、`NODE_BASE_IMAGE`、`NGINX_BASE_IMAGE`、`NPM_REGISTRY` 等镜像源/registry 变量,不放后端密钥,也不放 AI/OAuth key。 后端代码会按绝对路径读取 `backend/.env`,因此无论你在仓库根目录运行 `uvicorn`,还是 `cd backend` 后运行,读到的都是同一个应用配置文件。`backend/.env.example` 是 `backend/.env` 的模板;根目录 `.env` 没有模板也不是必需文件,只有在需要替换 Docker 基础镜像、npm registry 或端口时才创建。 ## 本地 Docker 演示 1. 准备环境文件: ```bash cp backend/.env.example backend/.env ``` 本地求职演示建议在 `backend/.env` 中使用: ```env DEBUG=true ENABLE_DEMO_PROVIDERS=true TEXT_PROVIDERS=["demo", "gemini", "openai"] IMAGE_PROVIDERS=["demo", "cqtai"] TTS_PROVIDERS=["edge_tts", "minimax", "elevenlabs"] STORYBOOK_PROVIDERS=["demo", "storybook_primary"] ``` `SECRET_KEY` 必须设置为强随机值。`backend/.env` 已被 git 忽略,不要提交真实密钥。 Docker 演示默认使用 `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 ``` 2. 启动完整本地栈: ```bash docker compose up -d --build ``` 3. 访问入口: - 用户端:http://localhost:52080 - 本地开发登录:http://localhost:52080/auth/dev/signin - 管理端:http://localhost:52888,默认演示账号来自 `backend/.env` - 后端健康检查:http://localhost:52000/health - 管理后端健康检查:http://localhost:52800/health 4. 常用命令: ```bash docker compose ps docker compose logs -f backend ./scripts/demo_smoke.sh SMOKE_AUDIO=1 ./scripts/demo_smoke.sh SMOKE_VOICE=1 ./scripts/demo_smoke.sh SMOKE_REAL_ASR=1 ./scripts/demo_smoke.sh docker compose down docker compose down -v ``` `scripts/demo_smoke.sh` 会检查健康状态、本地登录、统一生成后台任务、主记录落库、资产重试、故事列表和 Provider 能力分层。默认跳过 TTS、语音共创和真实 ASR;演示前需要验证朗读链路时使用 `SMOKE_AUDIO=1`,需要验证 Voice Studio Alpha 时使用 `SMOKE_VOICE=1`,需要用真实 OpenAI ASR key 验收上传转写时使用 `SMOKE_REAL_ASR=1`。 语音共创的 ASR 能力已纳入 Provider 分层。默认 `ASR_PROVIDERS=["demo"]` 会使用 `transcript_hint` 或文本上传作为本地演示转写;需要真实转写时可设置 `ASR_PROVIDERS=["openai_asr", "demo"]` 并配置 `OPENAI_API_KEY`。 真实 ASR 验收建议在 `backend/.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 ``` 改完 `backend/.env` 后重启 API/worker,若后台 Provider 表改过 ASR provider,还需要调用 `POST /admin/providers/reload` 并重启 API 进程,确保运行中缓存使用新配置。`SMOKE_REAL_ASR=1` 会自动开启 `SMOKE_VOICE=1`,在 macOS 上默认用 `say`/`afconvert` 生成一段短音频;其他环境可传入 `REAL_ASR_AUDIO_FILE=/path/to/sample.m4a`。 真实 ASR smoke 失败时,脚本会打印上传接口响应、Voice Session 事件和 Admin ASR analytics。常见失败包括 `OPENAI_API_KEY 未配置`、401/403 key 无效或项目无权限、429/insufficient_quota 额度不足、404/model_not_found 模型名不可用、连接超时或 `OPENAI_API_BASE` 指向错误,以及音频文件格式不被转写接口接受。 ## 手动开发 后端: ```bash cd backend pip install -e ".[dev]" alembic upgrade head uvicorn app.main:app --reload --port 8000 ``` 本机直接跑后端时,仍然修改 `backend/.env`,只是把数据库和 Redis 地址换成宿主机端口版本: ```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 ``` Celery: ```bash cd backend celery -A app.core.celery_app worker --loglevel=info celery -A app.core.celery_app beat --loglevel=info ``` 用户前端: ```bash cd frontend npm install npm run dev ``` 管理前端: ```bash cd admin-frontend npm install npm run dev ``` ## 质量检查 ```bash cd backend pytest ruff check app tests cd ../frontend npm run build cd ../admin-frontend npm run build ``` 当前已知情况:完整后端测试可通过;全量 ruff 可通过。前端生产构建建议优先通过 Docker 验证,确保与本地演示环境一致。 ## 核心接口 | 方法 | 路径 | 说明 | | --- | --- | --- | | GET | `/auth/dev/signin` | 本地开发登录,仅 `DEBUG=true` 可用 | | GET | `/auth/github/signin` | GitHub OAuth 登录 | | GET | `/auth/google/signin` | Google OAuth 登录 | | GET | `/auth/session` | 当前会话 | | POST | `/api/generations` | 提交后台生成任务,立即返回 `generation_job_id` | | GET | `/api/generations/{story_id}` | 统一读取生成结果 | | POST | `/api/generations/{story_id}/retry-assets` | 统一重试封面/语音资源 | | GET | `/api/generations/jobs/{job_id}` | 查询生成任务事件流 | | GET | `/api/generations/{story_id}/jobs` | 查询故事生成与重试历史 | | GET | `/api/generations/{story_id}/provider-stats` | 查询 Provider 调用聚合指标 | | GET | `/api/generations/ops-summary` | 查询最近任务运行概览、失败摘要和超时阈值 | | GET | `/api/generations/provider-analytics` | 查询当前用户跨故事 Provider 运营摘要,支持 `days` / `capability` 筛选 | | GET | `/api/audio/{story_id}/status` | 查询音频缓存状态,不触发生成 | | DELETE | `/api/audio/{story_id}/cache` | 清理故事音频缓存 | | GET | `/api/stories` | 故事列表 | | GET | `/api/stories/{story_id}` | 故事详情 | | DELETE | `/api/stories/{story_id}` | 删除故事 | | GET/POST/PUT/DELETE | `/admin/providers` | Provider 管理,需开启管理后台 | | GET | `/admin/providers/capabilities` | Provider 能力分层说明(text/image/tts/storybook/asr),需开启管理后台 | ## 文档入口 - `docs/product/job-search-relaunch-prd.md`:求职版产品重启 PRD - `docs/product/unified-generation-workflow-prd.md`:统一生成工作流 PRD - `docs/planning/week-1-execution-backlog.md`:短期执行 backlog - `docs/planning/week-2-execution-backlog.md`:下一阶段执行 backlog - `docs/planning/week-2-to-4-execution-backlog.md`:Week 2 到 Week 4 总执行 backlog - `docs/planning/demo-checklist.md`:求职演示检查清单 - `docs/planning/demo-package.md`:求职版 Demo 包装页 - `docs/planning/demo-validation-log.md`:本地 Docker 演示验证记录 - `docs/planning/interview-pitch.md`:3 分钟项目讲解稿 - `docs/planning/week-1-sprint-review.md`:Week 1 复盘总结 - `docs/planning/week-4-sprint-review.md`:Week 4 复盘和生产化 backlog - `docs/technical/architecture.md`:求职版架构说明 - `docs/technical/api-compatibility.md`:旧生成 API 兼容层策略 - `docs/technical/environment-configuration.md`:环境变量文件职责与 Docker/本机切换约定 - `docs/technical/generation-job-state.md`:Generation Job 状态落库决策 - `docs/technical/memory-system-dev.md`:记忆系统技术说明 - `docs/technical/provider-routing.md`:Provider 能力与路由策略说明 ## 当前取舍 仓库只保留一个 Docker Compose 入口:`docker-compose.yml`。生产部署、HA 演练、旧 Claude 原型和历史归档已从主仓库移除,避免干扰当前求职演示主线。统一生成接口现在会先创建后台任务,再由 Celery worker 负责真正的故事/绘本生成;因此本地开发或 Docker 演示时需要保证 `worker` 服务可用。音频缓存默认按 `STORY_AUDIO_CACHE_TTL_DAYS=30` 做后台清理,Celery beat 会每日执行一次 prune;生成任务默认按 `GENERATION_JOB_STALE_MINUTES=60` 判定卡住,后台会定时自动收敛为失败态,避免故事长期显示“永远在跑”。