项目概览
- 目标:生成纯中文儿童故事,风格干净,无英文与“思考/分析”类文字;自动生成卡通图片并支持语音朗读。
- 技术栈:Spring Boot(后端)、原生 JS + 静态 HTML(前端)、SiliconFlow API(文本与图片)、浏览器 SpeechSynthesis(TTS)。
- 产出:稳定的故事生成与清洗、图片生成、语音朗读、统一美化的前端页面与交互流程。
关键功能
- 纯中文故事生成:最小化提示词,避免英文与非正文输出。
- 正文清理与过滤:移除代码块、尖括号标签、思考/指导性段落、英文与标题前缀。
- 自动卡通图片生成:故事生成成功即触发图片生成并展示。
- 语音朗读:中文朗读、暂停/继续/停止,自动选择中文语音。
- 配置持久化:API Key 保存在
local.properties,免登录与免重填。 - 稳健错误处理:统一超时、限流与鉴权错误的反馈与重试策略。
架构设计
- 后端控制器与服务分层:
StoryController接入点负责请求、响应与输出清理;QianfanService负责与上游模型交互(文本与图片)。 - 前端单页静态:页面元素分区清晰,JS 事件驱动生成故事、自动生成图片与朗读控制。
- 配置导入与容错:通过属性集中配置模型、超时、重试、大小等参数,保护前端体验。
后端实现
- 文本生成与清理
- 生成接口:
/api/generate构造最小提示词与请求,返回清洗后的正文。 - 清洗逻辑:移除代码块、尖括号标签、思考与指导性段落、英文以及“标题/说明/分析/推理”类前缀。
- 代码位置:
src/main/java/org/example/story/controller/StoryController.java:93-145
- 生成接口:
- 图片生成
- 图片接口:
/api/image接收故事正文,构造图片提示词,返回 base64 或 URL,支持自动重试与错误映射。 - 服务方法:
src/main/java/org/example/story/service/QianfanService.java:322-386(模型、请求、重试、错误处理)
- 图片接口:
- 稳健性与错误映射
- 超时 → 504,并附带
Retry-After协调前端重试 - 429 限流 → 429,并附带
Retry-After - 401 鉴权 → 401,提示前端正确配置 Key
- 统一重试与冷却:指数退避、最小间隔、并发信号量防止过载
- 超时 → 504,并附带
前端实现
- 操作流程
- 输入关键词 → 生成故事 → 自动生成卡通图片 → 可选朗读。
- 已移除“查看剩余配额”和“生成图片”按钮,简化为单一“生成故事”入口。
- 朗读控制
- 选择中文语音并朗读;支持暂停/继续/停止;生成新故事自动取消上一次朗读。
- 代码位置:
src/main/resources/static/app.js:207-233(朗读事件),src/main/resources/static/app.js:235-261(暂停/继续/停止)
- 自动生成图片
- 故事生成成功后立即发送
/api/image,对 429/504 自动重试,失败消息友好提示。 - 代码位置:自动图片生成嵌入在生成故事流程中,见
src/main/resources/static/app.js生成成功后的图片逻辑块。
- 故事生成成功后立即发送
- 页面美化
- 统一网站装饰模板:品牌区、栅格卡片、统一配色与阴影、圆角与焦点样式。
- 代码位置:
src/main/resources/static/index.html(统一样式与布局)
错误处理与稳健性
- 超时与限流:带退避重试与
Retry-After,前后端配合平滑重试。 - 鉴权与配额:后端明确 401 与文案提示;配额展示入口已移除,避免用户关注不必要信息。
- 并发保护:信号量限制同时请求,防止爆发式调用导致上游拒绝。
配置与部署
- API Key 持久:
src/main/resources/local.properties中设置qianfan.apiKey,并在应用属性中导入该文件(已忽略版本控制)。 - 构建验证:
./gradlew.bat build -x test保证编译通过;前端为静态资产无需额外打包步骤。
体验优化
- 只输出故事正文:后端清洗彻底,移除“在描述环境时”“故事的发展需要”“总的来说”等指导性文字。
- 自动图片生成:减少用户操作,提升连贯体验。
- 统一美学风格:清爽、现代,适用于儿童故事场景的视觉氛围。
关键代码位置
- 故事生成入口:
src/main/java/org/example/story/controller/StoryController.java:19-48 - 正文清理函数:
src/main/java/org/example/story/controller/StoryController.java:93-145 - 图片生成服务:
src/main/java/org/example/story/service/QianfanService.java:322-386 - 语音朗读逻辑:
src/main/resources/static/app.js:207-233, 235-261 - 前端页面结构:
src/main/resources/static/index.html(品牌区、栅格卡片、操作与内容分区) - 配置持久化:
src/main/resources/local.properties(API Key)
收获与思考
- 最小提示词有助于避免模型模板化输出,与后端清洗组合,能显著稳定纯正文效果。
- 输出清理应多层次:结构块(代码/标签)、段落意图(指导性/分析性)、语言过滤(英文/拼音),联合生效。
- 错误处理应分层:网络/超时、限流、鉴权、非 2xx;前后端以
Retry-After与退避重试打通体验。 - 用户体验越少按钮越好:自动图片生成与语音朗读,使“生成故事”成为单一主流程。
- 配置持久化与私密性:将 Key 放在本地配置并忽略版本控制,避免泄露风险。