项目实训个人博客(六):双模块 AI 剧本生成初步开发
接上篇前后端接口联调完成,本周重心放在两套 AI 剧本生成功能的开发,拆分ai-generate 一键整生成页面、create 手动编辑页局部 AI 辅助两大模块,从后端数据表适配、接口编写、大模型对接,再到前端表单重构、生成顺序约束、交互细节打磨,一步步把原先静态假 AI 文案改成对接真实大模型、内容可落库的可用功能。我按照后端先行、前端跟进、反复联调优化的节奏,完成全流程开发。
一、开发前:拆分需求,把业务需求转成落地规范
正式敲代码前先梳理清楚两套 AI 功能的区别,防止后续代码冗余难维护,把口头需求整理成开发标准:
- 独立页 ai-generate:面向快速生成剧本的用户,仅需要填写基础配置,AI 一次性产出全套剧本内容,生成内容自动存入数据库,不需要手动分段编辑。表单只保留必要配置项,枚举类选项统一做成下拉,仅预计时长保留自定义输入框。
- 手动创作 create 页:面向精细化写本的创作者,分字段单独调用 AI,用户写到哪缺内容就生成哪。核心痛点是原先自由生成导致人名、世界观前后矛盾,因此定下硬性规则:固定生成顺序,必须按「世界观→背景故事→角色→剧本简介→剧本导语」解锁 AI 按钮,后段生成必须携带前面所有已填写内容作为参考。
- 后端通用规则:大模型调用失败自动降级返回原有静态文案,不能直接页面报错崩溃;所有生成的完整剧本拆分多表存入 PostgreSQL,主表 + 角色 / 线索 / 分幕 / 真相分表存储。
- 前端表单规范:基础配置项(主题、剧本类型、难度、游玩人数)全部由手动输入改为下拉选择,封面取消 URL 手动填写,替换成本地图片上传组件。
二、核心开发 1:后端分层开发
后端整体分成三层依次落地:数据表存储逻辑、新增业务接口、大模型调用改造。
1、数据库持久化代码完善
项目已经通过初始化 SQL 建好五张关联数据表:scripts 剧本主表、script_characters 角色表、script_clues 线索表、script_stages 分幕表、script_truths 真相表。我主要完善script_repo.py仓库代码:
- 编写
save_script_package存储方法,接收大模型输出的完整剧本结构体,拆分字段依次写入五张数据表,先存主表拿到主键 ID,再循环保存关联的角色、线索等子数据; - 配套
load_script_package反向读取函数,根据剧本 ID 从多表查询数据,拼装成前端可用的完整剧本对象;
2、新增一键生成接口
在 router 里新增/game/scripts/generate接口,整体执行链路:前端传配置参数→实例剧本生成核心类→调用大模型生成完整剧本→数据校验→调用 repo 方法入库→返回剧本 ID 和基础摘要,额外增加save_to_db入参开关,调试阶段可以选择不入库,避免测试数据污染数据库。
3、create 页面 AI 接口改造
原先 create 页面所有 AI 生成返回的都是硬编码静态文本,本次全量改造_build_ai_generate_response:
- 删掉所有写死的演示文案,接入项目封装好的 LLM 客户端,依靠.env 配置的密钥、接口地址调用大模型;
- 按五个不同生成字段单独定制提示词,每次入参携带前端传来的全量上下文;
- LLM 超时、调用失败时自动切回老静态数据,保障页面不会异常崩溃。
4、关键 bug 排查:大模型返回内容解析异常
调试初期出现明显问题:大模型日志显示调用成功,但最终返回固定兜底剧本,is_fallback标记为 true。顺着调用链路逐层打印日志排查: 原解析代码默认 AI 返回{"text":"json字符串"}格式,但实际大模型直接输出 JSON 数组,代码强行从 text 字段取值为空,JSON 解析失败自动降级兜底。 修复:优化 LLM 解析逻辑,优先识别原生字典 / 数组,取不到内容再截取 text 内字符串,修复后可正常读取 AI 原生返回的剧本数据。 后续又碰到角色生成返回空数组问题:底层 LLM 工具返回数组时外层自动套 data 对象,后端直接判断入参是否为 list 导致取值为空,同步修改取值逻辑,兼容字典套数组、原生数组两种返回格式。
三、核心开发 2:前端页面重构
1、ai-generate 一键生成页面改造
原页面全部是文本输入框,按照需求优化表单组件:
- 剧本主题、玩家人数、NPC 数量改成下拉选择,提前录入常用选项;
- 预计时长保留输入框,支持用户自定义填写;
- 封装统一请求钩子,点击生成按钮触发接口,生成完毕弹窗预览剧本,提供保存工坊、跳转编辑两个操作。
2、create 手动编辑页面
模块 1:生成顺序与解锁逻辑
新增GENERATE_ORDER固定数组记录生成顺序,用 state 数组记录已完成字段,实时计算当前可解锁按钮:没轮到顺序的 AI 按钮直接置灰,鼠标悬浮弹出提示「请先生成 XX 字段」。
const GENERATE_ORDER = ["world_setting","background_story","characters","summary","script_intro"]
每次点击生成时实时读取当前表单全量数据,用户中途手动修改过前面任意内容,下次生成会携带修改后的最新内容,不会沿用旧缓存数据。
模块 2:表单基础字段规范化
原先主题、类型、难度、人数全是手写输入,统一替换下拉选择;封面输入框换成上传组件,支持图片预览、本地上传,不再手动粘贴图片链接。
模块 3:按钮加载状态优化
之前点击 AI 生成无任何反馈,用户容易误以为页面卡死,拆分三种按钮状态:空闲可点击、生成中(旋转图标 + 动画)、已完成(绿色标识)。生成期间按钮置灰禁止重复点击,直观展示程序正在运行。
3、提示词后端同步优化
后端根据生成顺序调整 prompt 约束:第一次生成世界观无前置内容可自由创作,后续字段必须沿用前文的人名、地点,已有设定不能随意新增,从 AI 生成源头解决内容前后冲突。
四、开发中遇到的难点与解决方案
难点 1:AI 生成前后人设、故事设定互相矛盾
问题:无生成顺序、无上下文传递,AI 每次凭空生成,人名前后不一致。 解决:前端固定生成顺序 + 实时全量上下文透传,后端 prompt 添加硬性约束,三层手段控制 AI 生成内容贴合已有文案。
难点 2:LLM 调用成功但返回兜底静态剧本
问题:代码解析逻辑和 AI 返回格式不匹配,误判解析失败。 解决:打印原始返回日志,优化 JSON 解析,兼容纯数组、嵌套 data 数组两种返回格式。
难点 3:用户修改前面字段后,后续 AI 还沿用旧内容
问题:上下文缓存固定第一次生成数据,没有实时读取表单。 解决:每次点击 AI 生成,从 React 表单 state 实时拉取最新所有字段,用户修改即时生效。
难点 4:表单输入杂乱无章,用户随便填无效内容
问题:全文本输入容易出现格式错误。 解决:枚举项改用下拉,文件改用上传,精简无效输入。
难点 5:生成按钮无反馈,用户重复频繁点击
问题:缺少 loading 状态。 解决:新增加载标识、动画,生成中禁用按钮。
五、本周深度收获
- 区分同类功能的差异化开发思路,两个 AI 生成看似都是调用大模型,但使用场景不同,接口和前端逻辑分开设计,后期迭代更容易维护。
- 学会从全链路排查接口异常,从前端入参→后端接口→LLM 调用→数据解析→入库,分段打日志定位报错,不用盲目改代码。
- 做产品不能只实现基础功能,交互细节、容错兜底、使用门槛优化同样关键,下拉、加载反馈、悬浮提示都是提升易用性的关键点。
- 想要 AI 内容统一,既要前端做好数据携带,也要后端从提示词层面约束生成规则。
六、下周计划
- 支持单字段局部重新生成,用户对某一段 AI 内容不满意可单独重写,不改动其他已生成内容;
- 预留自定义提示词配置入口,后续可按需调整 AI 生成风格;
- 对接工坊剧本列表,完善 AI 生成剧本后的列表展示逻辑。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)