导入
跑团这东西,一直想玩,但规则厚得劝退,人也永远凑不齐。现在大模型这么强了,让 AI 来当主持人(DM),一个人开团似乎也不是不行。刚好之前做过一个全双工实时语音对话的项目,管道是现成的,于是在它基础上做了这个语音跑团应用:全程不用打字,开口说话就能玩一场二三十分钟的单人冒险。
玩法
接入之后,接待你的先是「剧本推荐员」,一个桌游店老板人设的 AI,聊聊你喜欢什么题材、想避开什么,然后给你推荐剧本。选定之后它就切换成这个剧本的专属主持人,念开场白,正式开局。
开局之后的行动是完全自由的,没有选项列表这种东西。想撬锁就撬锁,想套话就套话,想掉头就跑也行,主持人会按你的意图接着往下编。需要判定的时候掷骰子,走到结局之后它会给你做个复盘点评,然后回到大厅,换本再来。
目前内置了十个剧本,悬疑、武侠、赛博朋克、克苏鲁、童话喜剧都有,具体列表就不贴了,README 里写得很全。剧本本身就是一个 JSON 文件,想加新本的话,让 AI 参考现有的仿一个就行,这一点README也有教程。
几个做得比较认真的地方
骰子是代码掷的,不是 AI 编的。 这点我觉得是跑团的底线。AI 说要判定时会调用工具,点数由代码真实随机产生,它必须照着点数编后果,大成功就是大成功,翻车就是翻车。不然整个游戏就变成 AI 哄你开心了。
主持人有记忆。 滑动窗口加滚动摘要加结构化事实三层,你半小时前拿到的钥匙、答应过 NPC 的事,它都记得。不会玩到后面忘了前面。
可以随时打断。 主持人说到一半你可以直接插话「等等,我不这么做」,它会顺着你的新意图继续,不会把整段重新念一遍。长段叙述做了防误触,咳嗽一声不会把开场白打断。
每个 NPC 有自己的声音。 本地用 CosyVoice2 做合成,不同 NPC 不同音色,还带情绪,愤怒、低语、悲伤都能听出来。没有显卡的话也有纯云端的方案,语音识别和合成都走 API,具体看仓库里的文档。
低延迟不是调几个 API 就行
表面上看,语音对话就是识别、大模型、合成几个 API 串起来。但真要变成一条可打断、可测量、低延迟的实时流水线,中间全是工程。
比如判断玩家「说完了」不能像对讲机一样等松开按键,得靠 VAD 做轮次判定:判停时间长了反应迟钝,短了又把玩家一句话拦腰截断。比如打断(barge-in):玩家随时插话,正在合成和播放的音频要立刻作废,可「立刻作废」在流式系统里是竞态重灾区——旧回合的音频块晚到了怎么办?这里的做法是给每个回合一个代际编号(gen_id),凡是过期回合的产出一律丢弃,一条铁律管到底。再比如回声消除:扬声器放着 AI 的声音,麦克风又把它收回去,这个在 Web、Windows、Android 三套平台上的处理各不一样。
还有延迟打点。每回合从玩家闭嘴到听见声音,中间每个环节的耗时都会落到日志里,能渲染出 p50/p95 的瀑布图。没这个东西,「到底哪里慢」永远只能靠猜。
这些底座层面的工程大多来自 Realtime-Voice,跑团项目自己又在上面加了一层:LLM 的输出要流式切成句子送合成,NPC 的声线和情绪标记要在 token 流里边走边解析,相邻同声线的句子还得合并起来防止语气句间跳变;模型回复被长度上限截断时要自动接着续写;甚至「这句台词是哪个 NPC 说的」都不能全指望模型自觉,得有代码级的归属兜底。这些事单看都不大,但凑在一起,就是「玩起来顺」和「玩起来卡壳」的区别。
技术上的一句话总结
每一环都可插拔,想换别的模型照着接口加一个就行;前端网页是个哑终端,所有智能都在服务端。部署这块就不展开了,仓库里有份给 AI 助手读的部署指南,丢给它一句话就能装好。
结语
做完之后自己完整玩了几局,体验比预期好不少。最大的感受是,「自由行动」和「真实掷骰」这两条保住了,AI 跑团就有了跑团的魂,而不是一个披着跑团皮的聊天机器人。感兴趣的话可以 clone 下来玩玩看,也欢迎自己写剧本。