本地项目经验:诗韵成歌(gufeng-song-wizard)工程复盘

AI 生成经验手册章节《本地项目经验:诗韵成歌(gufeng-song-wizard)工程复盘》,全文约 3456 字,免费在线研读;读完标记可得积分。属于诗韵乐府古风音乐百科系列。

本地项目经验:诗韵成歌(gufeng-song-wizard)工程复盘

本地项目经验:诗韵成歌(gufeng-song-wizard)工程复盘

本文是对本地已落地的古风 AI 歌曲生成应用「诗韵成歌」(L:\bproj\gufeng-song-wizard,端口 9441)的完整工程复盘。它是一条经过真实运行的端到端管线:诗词灵感 → LLM 填词 → AI 谱曲 → LLM 评分,其中的坑与解法都可以直接迁移到任何 AI 生成古风歌曲的工作流中。

1. 项目概况与总体架构

四步成歌:

步骤实现说明
灵感本地 37.6 万首诗词库(唐诗/宋诗/宋词全文)随机抽 7 类素材(诗人、词牌、意象热词 + 含该词的原诗)组装成可编辑灵感文本
歌词MiniMax lyrics_generation(mode=write_full_song)14 个生产提示词可切换,含「[总控]两步路由」,支持 2-4 个提示词并行出词对比
歌曲MiniMax music_generation(model=music-3.0)异步任务 + 前端轮询,MP3/WAV 落地本地
打分LLM-as-judge 9 维评分SVG 雷达图 + 维度卡 + 评语

技术栈:Node 22 --experimental-strip-types 直跑 TS + node:sqlite + node:http 裸路由,零第三方依赖;前端原生 DOM 拼接构建。

经验 1:灵感素材库是歌词质量的源头。 生产数据库的作者/词牌 rank 表是空的,最后是直接从 37.6 万首 poetry_poems 重新聚合出 900 诗人池、200 词牌池、1500 热词池。教训:不要相信上游数据完备,先查再建。灵感组装时给 LLM 的不是干巴巴的关键词,而是「热词 + 含该词的原诗全文」,歌词的底蕴明显更足——因为模型拿到了真实语境。

经验 2:多版本对比比单版精修更划算。 与其让一个提示词反复重写,不如 2-4 个不同方向提示词并行出词 → 预览 → 挑一版再去谱曲。谱曲比出词贵得多,把选择权放在谱曲之前,省钱且质量上限更高。

2. 歌词生成:[总控]两步路由与「降级直出」

生产系统的歌词生成是两步路由

  1. 第一步用 [总控]v9 提示词让 LLM 输出 JSON:评估 8 个方向(严肃/爆款/戏腔/边塞/禅意/治愈/嘻哈/赛博)对当前灵感的适配度,给出 recommended: ["A","B"] + primary
  2. 第二步按随机选中的方向加载对应子模板(词牌格律、爆款铁律、戏腔公式等)正式填词。

踩坑 A:两步路由的第一步经常"跑飞"。 让模型只输出方向 JSON,它经常无视指令直接把歌词写出来了。原版的处理是解析失败→同 prompt 重试一遍(浪费一次调用)。改进方案是「降级直出」:如果输出已经是一份完整歌词,就直接采用,标记"降级直出"溯源,省一次调用。教训:对 LLM 的输出永远写"宽容解析器",把失败输出变成可用输出,而不是机械重试。

踩坑 B:思考模型会把 max_tokens 吃光在 <think> 上。 起标题任务给 max_tokens=50,结果 MiniMax-M3 是思考模型,50 token 全被 <think> 段吃掉,正文永远是空的,系统永远返回兜底标题「古风新韵」。连 highspeed 快速模型也会思考(reasoning_tokens 1500+)。修复:给思考模型的 max_tokens 预算放到 2000。这是一个非常隐蔽的 bug——表现为"永远返回同一个兜底值",任何给思考模型的小 max_tokens 都可能中招。

3. 谱曲:异步任务与 API 要点

  • MiniMax music_generation{ model: 'music-3.0', prompt: 风格描述(≤2000字), lyrics },返回音频 hex/base64 → 落地为本地文件。
  • 同步请求会阻塞 1-3 分钟,改为 POST /api/songs 立即返回任务号 + 前端 2.5s 轮询,可关页面。
  • 服务重启时的僵尸任务:init/running 状态的任务永远不会回来,启动时 cleanupStuckSongs 统一标 failed,否则曲库永远卡着"生成中"。
  • 风格描述(style prompt)不要塞超过 2000 字——超长会被截断,编曲指令丢失时表现为"后半首风格漂移"。

4. 打分:LLM-as-judge 的锚定技巧

9 维评分(0-10,可带一位小数):musicality 整体音乐性 / melody 旋律 / harmony 和声 / rhythm 节奏 / lyric_quality 歌词 / coherence 连贯 / structure 结构 / aesthetic 意境 + overall 总分。实测有效的提示词工程手段:

  1. 保守锚定:明确写"AI 生成的古风歌平均水准约 6-7 分;只有真正优秀的维度才给 8+",否则 LLM 打分普遍虚高到 8-9,分数失去区分度。
  2. 无音频通道要明说:模型听不到歌,直接指令"旋律/编配/节奏等音频维度保守给 6.0±0.5,除非从风格标签/歌词结构能看出明显线索",防止它凭空想象打高分。
  3. 维度缺失语义化:8 维不全时 overall 强制 NULL(而不是硬算平均值),让前端显示"评分不完整"而不是假分数。
  4. temperature=0.2 + JSON 容错解析(剥 markdown 代码围栏、找第一个 { 到最后一个 })。
  5. overall 缺失时用 8 维平均补齐;comment 限 20-80 字防跑题。

5. 测试与演示:mock 模式是生命线

  • MOCK_MINIMAX=1 或未配 key 时走确定性 mock(按 prompt hash 生成假歌词/假 WAV/假评分),全流程可体验。41 项 smoke 断言 + 24 项 Playwright UI 走查全部跑在 mock 上,不花 API 费、可离线、可重复。
  • mock 要按输入特征分支(评分 prompt 返回 9 维 JSON;总控 prompt 返回方向 JSON;含"3-4 个字"的返回标题池),这样测试才能真正覆盖解析逻辑而不只是 HTTP 层。

6. 其他工程教训速查

  • 拼接构建(多文件 TS 拼一个 app.js)下,少一个右括号这类语法错误报 Expected ',' got ';'无行号。写多层嵌套 DOM 构造时,结尾括号数 = 当前打开的调用数。
  • 37.6 万首诗词全文进 SQLite 约 99MB,单文件完全可行;热词反查原诗用 LIKE '%词%' 建议加前缀索引或预建倒排,否则首次查询慢。
  • 歌词状态存 localStorage,四步向导刷新不丢——AI 生成类应用每一步产物都可能被用户珍视,持久化到本地是基本修养
  • 音频文件服务要支持 HTTP Range(拖动进度条),下载加 ?dl=1 带 Content-Disposition。

7. 这条管线验证过的「灵感→歌词」配方

实测效果最好的灵感组装格式(喂给 LLM 的第一行到最后一行):


【诗词灵感】

朝代/诗人:<诗人>(代表作:<标题>)

词牌:<词牌名>

意象热词:<热词1>、<热词2>、<热词3>

含"<热词>"的原诗:

<原诗全文,通常 4-8 句>

创作方向:<总控评估出的方向,如"戏腔/边塞">

要点:给原诗全文而不只是词明确方向(总控先评估);方向与主题错配会系统性低分(边塞模板写思妇、戏腔模板写咏物都是灾难,总控提示词里为此专门写了"不适合"列)。