文件 工具
頭頂氣泡與本機模型
讓遊戲裡任意單位以任意身分在頭頂彈出對話氣泡;接上本機 LLM,一句話輸入,一句回覆就出現在單位頭上。
氣泡屬於觀賞層:不影響勝負,適合直播、賽事解說和偵錯。
- 任意單位、任意身分都能說話;多個單位可以同時說;
- 每個氣泡的字級、顏色、寬度、尾巴、透明度、打字速度都能個別自訂;
- 能直接接上本機 LLM(LM Studio),支援串流輸出:一邊生成一邊更新氣泡。
從 Bot 裡使用
最簡單的方式是 SDK 內建的 say:
g.say(hero, "跟我衝!", seconds=4)
啟動與介面
最省事:遠見首頁「控制中心」——先點「本地大模型 → 啟動並載入模型」(LM Studio 本機服務 + 把設定好的模型載入顯示記憶體),再點「頭頂聊天氣泡 → 啟動」。卡片上能看日誌、停止、重新啟動。
介面在遠見左側的「頭頂氣泡」頁:讓單位說話(選單位、輸入文字、調整樣式、和模型對話)、農民茶話會、鏡頭對白、戰況觸發、模型設定,都針對頂端列選取的實例操作。
也可以用命令列:
python speech/speak_launch.py # 啟動本機模型服務 + 載入模型並預熱 + 啟動氣泡 API
python speech/speak_launch.py --restart # 修改程式碼後重新啟動 API
python speech/speak_launch.py --stop # 停止 API,並把模型從顯示記憶體卸載
每一步都是「已存在就略過」,重複執行沒有副作用。
HTTP API
預設為 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 | 已有同一個氣泡時只替換文字、不重設計時(串流輸出用) |
style | font_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 輪對話。
其他
| API | 說明 |
|---|---|
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),推理 low | 11.3 GB | 約 280 token/s | 0.3 ~ 0.8 秒 | 顯示記憶體吃緊時使用,中文略顯平淡 |
| Qwen3.6-27B(稠密),Q4 | 17.2 GB | 約 39 token/s | 5.5 秒後仍在思考 | 不適合即時對話 |
- 速度看「每次啟用的參數量」,不看總參數量:35B 的 MoE 只啟用 3B,比 27B 稠密模型快 3 ~ 4 倍。
- 一定要關閉「思考」:不關的話 token 全花在思考上,一個字都沒回。
- 氣泡逐字打出的速度約每秒 22 個字,生成速度已經不是瓶頸,真正影響體驗的是首字延遲。
讓台詞「像真的」
給模型的戰況一律使用真實資料(場次、勝負、兵力、庫存),並明確要求「只能使用這些事實」。實測發現,不加這條限制時,模型會編造出沒發生過的戰鬥。