文档 工具

头顶气泡与本地模型

让游戏里任意单位以任意身份头顶弹出对话气泡;接上本地大模型,一句话进、一句回复出在单位头上。

气泡是观赏层:不影响胜负,适合直播、解说、调试。

  • 任意单位、任意身份说话;多个单位可以同时说;
  • 每个气泡的字号、颜色、宽度、尾巴、透明度、打字速度都能单独定制;
  • 能直接接本地大模型(LM Studio),支持流式输出:边生成边更新气泡。

从 Bot 里用

最简单的方式是 SDK 自带的 say:

g.say(hero, "跟我冲!", seconds=4)

启动和界面

最省事:远见首页「控制中心」——先点「本地大模型 → 启动并载入模型」(LM Studio 本地服务 + 把配好的模型载进显存),再点「头顶聊天气泡 → 启动」。卡片上能看日志、停止、重启。

界面在远见左侧的「头顶气泡」页:让单位说话(选单位、写字、调样式、和模型对话)、农民茶话会、镜头对白、战况触发、模型设置,按顶栏选的实例操作。

命令行也可以:

python speech/speak_launch.py              # 起本地模型服务 + 载入模型并预热 + 起气泡接口
python speech/speak_launch.py --restart    # 改了代码后重起接口
python speech/speak_launch.py --stop       # 停接口,并把模型从显存卸掉

每一步都是「在就跳过」,重复运行没有副作用。

HTTP 接口

默认 http://127.0.0.1:8872/(端口在 openwar3.json 的 ports.speech),任何程序都能调。

让单位说话 POST /api/say

{
  "inst": 16,
  "bubbles": [
    { "unit": "0x14A12614", "name": "山丘之王", "text": "跟我冲!" },
    { "unit": "0x14A12924", "name": "大法师", "text": "我来放暴风雪。",
      "style": { "font_px": 26, "text_color": "#FFE080", "bg_color": "#C0102040" } },
    { "screen": [960, 110], "key": 1, "name": "旁白", "text": "第一波兽人还有 30 秒到达。",
      "style": { "tail": false, "type_ms": 0 } },
    { "world": [-4684, 2644], "key": 2, "text": "集合点", "style": { "font_px": 16 } }
  ]
}
字段说明
unit / world / screen三选一:跟着单位走(有血条时贴在血条正上方)/ 地图坐标 / 屏幕像素(旁白用)
name第一行显示的说话人,随便写,不必是这个单位
text正文,自动换行
duration_ms显示多久;0 = 自动 3 ~ 5 秒
key世界 / 屏幕气泡的编号,同 key 的新消息顶掉旧的
update已有同一个气泡时只换文字、不重置计时(流式输出用)
stylefont_px、max_width_px、text_color、bg_color、border_color、tail、side_px、opacity、type_ms、font……

同时最多 32 个气泡;每帧开销平均约 0.1 ~ 0.2 ms。

和本地模型对话 POST /api/chat

{
  "inst": 16, "unit": "0x14A12614", "name": "山丘之王",
  "persona": "你扮演魔兽争霸里的山丘之王穆拉丁,豪爽、爱喝酒。一两句口语,不超过40个字。",
  "message": "前面有一群食人魔,我们冲不冲?",
  "stream": true
}

返回 {"reply": "...", "first_token_ms": 283, "total_ms": 342},同时这句回复已经出现在那个单位头上。同一个单位会记住最近 6 轮对话。

其它

接口说明
GET /api/instances在跑的游戏
GET /api/units?inst=16&mine=true&heroes=true单位列表(带中文名、坐标、血量)
POST /api/clear清掉一个或全部气泡
GET /api/llm、POST /api/llm看 / 改模型配置(base_url、model、max_tokens、temperature)
POST /api/banter农民茶话会:家里的工人按人设轮流吐槽,开局报幕(战况全是真数据)
POST /api/camtalk镜头对白:镜头里的英雄和随从按身份对话
POST /api/events战况触发:开战、打完、英雄阵亡、升本、被拆……出事了才说

本地模型怎么选

在一张 RTX 5090 上实测(5 句游戏台词):

模型显存速度一句回复结论
Qwen3.6-35B-A3B(MoE,每次只激活 3B),Q4,关思考20.6 GB约 142 token/s约 0.3 秒(首字约 0.27 秒)推荐:快、中文角色扮演自然
gpt-oss-20b(MXFP4),推理 low11.3 GB约 280 token/s0.3 ~ 0.8 秒显存紧时用,中文略平
Qwen3.6-27B(稠密),Q417.2 GB约 39 token/s5.5 秒还在思考不适合实时对话
  • 速度看「每次激活的参数量」,不看总参数:35B 的 MoE 只激活 3B,比 27B 稠密快 3 ~ 4 倍。
  • 必须关掉「思考」:不关的话 token 全花在思考上、一个字都没回。
  • 气泡逐字打出约每秒 22 个字,生成速度已经不是瓶颈,真正影响体验的是首字延迟。

让台词「像真的」

给模型的战况一律用真数据(场次、胜负、兵力、库存),并明确「只许用这些事实」。实测不加这条限制时,模型会编出没发生过的战斗。