# AI创作系统设计文档 ## 一、功能矩阵 | 功能 | 入口 | 输入 | 输出 | 配额消耗 | |-----|------|------|------|---------| | AI改写结局 | 结局页 | 原结局+用户指令 | 新结局文本 | 1次 | | AI改写节点 | 章节选择页 | 原节点+用户指令 | 新节点+选项 | 1次 | | AI续写 | 故事播放页 | 当前节点+用户指令 | 后续2-3个节点 | 2次 | | AI创作大纲 | 创作中心 | 题材/关键词 | 标题+简介+大纲 | 1次 | | AI完整创作 | 创作中心 | 大纲确认 | 完整故事节点树 | 5次 | | AI润色 | 编辑器 | 原文本 | 优化后文本 | 1次 | --- ## 二、核心流程 ``` ┌─────────────────────────────────────────────────────────────────┐ │ AI创作完整流程 │ └─────────────────────────────────────────────────────────────────┘ 用户触发 ──► 配额检查 ──► 构建Prompt ──► 调用AI ──► 解析响应 ──► 存储记录 │ │ │ │ │ ▼ ▼ ▼ │ 配额不足? [ai_generations] 解析失败? │ │ 记录调用 │ │ ▼ ▼ │ 引导充值/看广告 重试/降级 │ ▼ 展示结果 ◄── 用户操作 ──► 采纳? ──► 写入故事表 ──► 进入审核流程 │ ▼ 放弃/编辑 ``` --- ## 三、Prompt模板设计 ### 3.1 改写结局 ``` [系统提示] 你是一个互动故事创作专家。根据用户的改写指令,重新创作故事结局。 要求: - 保持原故事的世界观和人物性格 - 结局要有张力和情感冲击 - 字数控制在200-400字 - 输出格式:纯文本 [用户提示] 故事标题:{title} 故事分类:{category} 原结局名称:{ending_name} 原结局内容:{ending_content} --- 用户改写指令:{user_prompt} --- 请创作新的结局: ``` ### 3.2 续写剧情 ``` [系统提示] 你是一个互动故事创作专家。根据当前剧情,续写后续发展。 要求: - 提供2-3个剧情走向选项 - 每个选项后续写1个节点内容 - 保持悬念和代入感 - 输出JSON格式 [用户提示] 故事标题:{title} 当前剧情:{current_content} 已做选择:{choices_history} --- 用户期望:{user_prompt} --- 请续写剧情,输出格式: { "choices": [ {"text": "选项1文本", "content": "选择后的剧情内容", "speaker": "角色名"}, {"text": "选项2文本", "content": "选择后的剧情内容", "speaker": "角色名"} ] } ``` ### 3.3 完整创作 ``` [系统提示] 你是一个互动故事创作专家。根据用户提供的关键词,创作一个完整的互动故事。 要求: - 故事有3-5个关键分支点 - 至少2个不同结局(好结局/坏结局) - 每个节点100-200字 - 输出完整的节点树JSON [用户提示] 题材:{genre} 关键词:{keywords} 主角设定:{protagonist} 核心冲突:{conflict} --- 请创作完整故事,输出格式: { "title": "故事标题", "description": "故事简介", "nodes": { "start": {"content": "开头内容", "speaker": "", "choices": [...]}, "node_1": {...}, "ending_good": {"content": "好结局", "is_ending": true, "ending_type": "good"}, "ending_bad": {"content": "坏结局", "is_ending": true, "ending_type": "bad"} } } ``` --- ## 四、API设计 ### 4.1 AI改写结局 ``` POST /api/ai/rewrite-ending Request: { "story_id": 123, "ending_name": "双向奔赴", "ending_content": "原结局内容...", "prompt": "让主角逆袭" } Response: { "code": 0, "data": { "generation_id": 456, "content": "新结局内容...", "ending_name": "双向奔赴(改写版)", "tokens_used": 580, "quota_remaining": 4 } } ``` ### 4.2 AI续写 ``` POST /api/ai/continue Request: { "story_id": 123, "current_node_key": "node_5", "choices_history": ["选项A", "选项B"], "prompt": "希望有反转" } Response: { "code": 0, "data": { "generation_id": 457, "choices": [ {"text": "追上去", "content": "你快步追上...", "next_key": "ai_node_1"}, {"text": "放手离开", "content": "你转身离去...", "next_key": "ai_node_2"} ], "nodes": { "ai_node_1": {"content": "...", "choices": [...]}, "ai_node_2": {"content": "...", "is_ending": true} } } } ``` ### 4.3 AI完整创作 ``` POST /api/ai/create Request: { "genre": "都市言情", "keywords": "霸总,契约婚姻,追妻火葬场", "protagonist": "独立女性设计师", "conflict": "假结婚变真爱" } Response: { "code": 0, "data": { "generation_id": 458, "draft_story_id": 789, "title": "契约总裁的心动法则", "description": "...", "node_count": 12, "ending_count": 3 } } ``` ### 4.4 配额查询 ``` GET /api/user/ai-quota Response: { "code": 0, "data": { "daily_free_remaining": 3, "purchased_remaining": 10, "vip_bonus": 5, "total_available": 18, "reset_time": "2026-03-04 00:00:00" } } ``` --- ## 五、配额与计费 ### 5.1 配额规则 | 用户类型 | 每日免费 | 购买包 | 说明 | |---------|---------|-------|------| | 普通用户 | 3次 | 10次/6元 | 看广告+1次 | | 月卡VIP | 10次 | 同上 | 月费18元 | | 年卡VIP | 20次 | 同上 | 年费168元 | ### 5.2 消耗逻辑 ```javascript // 扣费优先级:每日免费 > 赠送 > 购买 > VIP额外 async function consumeQuota(userId, amount = 1) { const quota = await UserAIQuota.findByPk(userId); // 检查是否需要重置每日配额 if (quota.daily_reset_date !== today) { quota.daily_free_used = 0; quota.daily_reset_date = today; } // 计算可用配额 const dailyFreeRemain = quota.daily_free_total - quota.daily_free_used; const available = dailyFreeRemain + quota.gift_quota + quota.purchased_quota + quota.vip_daily_bonus; if (available < amount) { throw new Error('QUOTA_INSUFFICIENT'); } // 按优先级扣除 let toConsume = amount; if (dailyFreeRemain > 0) { const use = Math.min(toConsume, dailyFreeRemain); quota.daily_free_used += use; toConsume -= use; } // ... 依次扣除其他配额 await quota.save(); } ``` --- ## 六、审核流程 ``` 用户发布 ──► 机器审核 ──► 通过?──► 直接上架 │ │ ▼ ▼ 疑似违规 人工审核 ──► 通过/拒绝 │ ▼ 进入人工队列 ``` ### 6.1 机器审核维度 - 敏感词检测(sensitive_words表) - 内容安全API(腾讯云/阿里云) - AI生成内容标记检测 ### 6.2 审核状态流转 ``` 草稿(0) ──► 提交审核 ──► 审核中(1) ──► 已发布(2) │ ▼ 已拒绝(4) ──► 修改后重新提交 ``` --- ## 七、数据统计 ### 7.1 核心指标 - AI调用成功率 - 平均响应时间 - 用户采纳率 - 生成内容发布率 - Token消耗/成本 ### 7.2 日报表聚合 ```sql -- 每日定时任务聚合到 ai_daily_stats INSERT INTO ai_daily_stats (stat_date, gen_type, model_name, call_count, ...) SELECT DATE(created_at), gen_type, model_name, COUNT(*), SUM(CASE WHEN status=1 THEN 1 ELSE 0 END), SUM(input_tokens), SUM(output_tokens), AVG(latency_ms) FROM ai_generations WHERE DATE(created_at) = CURDATE() - INTERVAL 1 DAY GROUP BY DATE(created_at), gen_type, model_name; ``` --- ## 八、技术实现要点 ### 8.1 服务端架构 ``` ┌─────────────────────────────────────────────┐ │ API Gateway │ └──────────────────────┬──────────────────────┘ │ ┌──────────────┼──────────────┐ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ 故事服务 │ │ AI服务 │ │ 用户服务 │ └─────────┘ └────┬────┘ └─────────┘ │ ┌────────────┼────────────┐ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ OpenAI │ │ Claude │ │ 本地模型 │ └─────────┘ └─────────┘ └─────────┘ ``` ### 8.2 AI服务封装 ```javascript // services/ai.js class AIService { constructor() { this.providers = { openai: new OpenAIProvider(), claude: new ClaudeProvider(), local: new LocalProvider() }; } async generate(options) { const { type, provider = 'openai', ...params } = options; const template = await this.getPromptTemplate(type); const prompt = this.buildPrompt(template, params); const startTime = Date.now(); try { const result = await this.providers[provider].chat(prompt); return { success: true, content: result.content, tokens: result.usage, latency: Date.now() - startTime }; } catch (error) { return { success: false, error: error.message }; } } } ``` ### 8.3 前端交互优化 - 流式输出:使用SSE实时展示生成过程 - 骨架屏:生成中显示打字动画 - 失败重试:自动重试2次,超时30秒 - 结果缓存:相同输入5分钟内复用 --- ## 九、后续迭代 ### Phase 1(当前) - [x] AI改写结局 - [ ] 配额系统接入 - [ ] 基础审核流程 ### Phase 2 - [ ] AI续写功能 - [ ] AI创作大纲 - [ ] 创作中心入口 ### Phase 3 - [ ] AI完整创作 - [ ] UGC发布流程 - [ ] 创作者认证 - [ ] 收益分成