# 桌宠全模态 MOD

这个 MOD 会给妹居物语新增一个“桌宠设置”，让桌宠截图后请求你自己的多模态 API。

## 安装

1. 关闭游戏。
2. 双击 `install.bat`。
3. 打开游戏。
4. 点左下角“桌宠设置”。
5. MOD 默认已经启用。
6. 选择“沿用当前自定义 API”，或单独填写桌宠用的 API。
7. 如果没有现成的 OpenAI/Claude API 渠道，可以先打开左下角“云端大模型”，在“快捷预设”里点“国外模型合集”，然后到 https://gptsapi.net/ 注册并填写自己的 Key。
8. “启用桌宠语音播报”默认是打开的，不想听语音可以取消勾选。
9. 可以按需要调整“回复字数范围”“单次 token 上限”“HTTP 支持时分段显示和分段语音”和“附加 Prompt”。
10. 点“保存设置”，再打开桌宠。

## 使用

- 打开桌宠后，点桌宠上的 AI 按钮。
- 如果看到 `Yuki Vision MOD: ON`，说明正在使用 MOD 的全模态逻辑。
- “测试API”会在设置页显示本次测试真正发送给接口的单图或拼图，方便确认模型到底收到了什么画面。
- 桌宠自带的 AI 开关已被 MOD 锁定为状态提示，不再负责开启或关闭。
- MOD 开启时，桌宠会按你设置的间隔检查是否需要回复；需要回复时才把截图发到你配置的接口。
- 每次召唤桌宠后，MOD 会先等约 5 秒再开始第一次自动截图，避免桌宠刚弹出时识别到不稳定的画面。
- HTTP 多模态现在也会在桌宠下方显示状态条，例如正在截图、请求模型、接收回复、播放语音。
- 桌宠收到回复后会先显示气泡，再用游戏自带语音播报；同一时间只会播放一句。
- 如果语音服务第一次启动比较慢，文字气泡仍会正常显示。
- 桌宠说完一次后，会按“自动回复统一冷却秒数”等待；开启语音时，会等气泡显示和语音播放都结束后再开始算冷却。
- 截图默认会尽量使用高清模式；不同画面理解预设会自动使用不同清晰度，如果当前环境不支持高清抓屏，会自动回退。
- “画面理解预设”默认是“平衡（推荐）”：桌宠会在本地临时缓存高清关键帧；需要上传时，会按“自动回复统一冷却秒数”的时间窗口拼出代表最近变化的图片。
- 聊天气泡会自动放大，尽量一次显示完整回复。
- MOD 关闭时，会恢复软件原本的桌宠 AI 逻辑。

## 画面理解预设

- 省流量：只发送当前截图，消耗最低，适合普通聊天或静态页面。
- 轻量动态：在冷却窗口内发送 3 帧拼图，适合想省一点但又想看出变化。
- 平衡（推荐）：在冷却窗口内发送 4 帧高清拼图。
- 动态：在冷却窗口内发送 6 帧高清拼图，适合游戏、视频、频繁切窗口。
- 高预算：在冷却窗口内发送 8 帧高清拼图，连续感更好，但 API 消耗和响应时间也会更高。
- 多帧：在冷却窗口内发送 10 帧高清拼图，适合图片 token 消耗较低、响应较快的模型。
- 超多帧：在冷却窗口内发送 12 帧高清拼图，连续感最强，建议只给低成本或本地接口使用。

MOD 只缓存少量高清关键帧，用来真正拼图；不再额外采集低清指纹历史，也不再根据画面变化阈值自动降成单图。除“省流量”外，只要缓存里有历史帧，就会按所选预设发送拼图，也不会因为两张截图时间太近或画面相似就丢掉。缓存只放在内存里，不写文件；桌宠关闭、MOD 关闭或 API 不支持图片输入时会清空。

这一版提高了拼图清晰度：平衡档开始会使用更高的截图尺寸和更大的拼图上限；多帧/超多帧最高会生成 4096 长边的拼图。图片更清楚，但接口处理时间和图片 token 可能会上升。

拼图会自带顶部说明和编号标签，例如 `1/6 约 15 秒前`、`2/6 约 12 秒前`、`当前画面`。这是为了让 Qwen3-VL-Flash 这类模型更容易理解“这是一组连续截图”，而不是只看最后一格静态画面。默认提示词会要求模型不要在回复里直接说出这些具体秒数。

拼图现在会尽量覆盖“自动回复统一冷却秒数”这个窗口。例如冷却是 16 秒并选择高预算 8 帧，正式运行攒够缓存后，拼图大致会从约 16 秒前一路排到当前画面。

如果你把冷却设得比较短，MOD 会自动缩短本地高清关键帧的缓存间隔，尽量在下一次请求前攒够对应档位需要的帧数。这个自适应只影响本地截图缓存，不会增加 API 请求次数。极短冷却配超多帧时，MOD 会以最低约 0.5 秒一张的速度尽量采集，不保证每次都能截满最高档位。

例子：高预算目标是 8 帧。冷却为 16 秒时，MOD 会尽量每 2 秒缓存一张高清关键帧，最终拼图约覆盖这 16 秒；冷却为 60 秒时，则约每 7-8 秒缓存一张。多帧和超多帧也会用同样规则自动调整，但不会增加 API 请求次数。

模型不会被要求在回复里说出具体秒数、帧数或“拼图”等技术词；这些信息只用于让回复更像是在理解连续画面。

设置页里的“测试API”会按当前画面理解预设生成测试图片：省流量会显示单张截图，多帧档会短时间连续抓几张图并拼成一张预览图。这个测试主要用来确认接口能收到并理解拼图格式；正式桌宠运行时会使用真实时间里的缓存帧。

## 回复和 Prompt 设置

- “回复字数范围”可以直接填写最低和最高中文字数。默认是 `20-40`；想更详细可以填 `90-180`。
- 默认提示词会要求桌宠只输出角色对话，不输出动作、神情或旁白；如果玩家正在游戏，会尽量只围绕当前游戏画面给出有用信息，比如敌人位置、危险点、路线、资源、任务或下一步建议；能读文字，但不会复读屏幕上的原文。
- 默认提示词也会要求模型避免刻板复读：不要把前几轮出现过的某个词、外号、比喻或梗反复当口头禅使用。
- “单次 token 上限（不懂勿动，0=自动）”是高级项，普通用户保持 `0` 即可；如果模型经常说到一半，可以试试 `1536` 或 `2048`。
- “附加 Prompt”会追加到作者原本桌宠人设后面，不会覆盖原角色设定。留空就是默认效果。
- 示例附加 Prompt：`回复更像妹妹一点，可以轻微吐槽当前页面，但不要像 AI 助手一样解释太多。`

## 秒数设置例子

“每多少秒检查一次屏幕”不是每次都会上传，它只是桌宠多久看一次“现在能不能触发回复”。

“自动回复统一冷却秒数”是桌宠说完一句后，至少要等多久才允许下一次自动回复。开着语音时，这里的“说完”指气泡显示结束、语音也播放结束。

例子：

```text
每多少秒检查一次屏幕：20
自动回复统一冷却秒数：60
```

这表示桌宠每 20 秒检查一次屏幕；如果刚刚已经说过话，或者还在播放上一句语音，就不会截图、不会请求 API。等气泡和语音结束后，再等 60 秒冷却；冷却结束后，要等下一次 20 秒检查点才会再次触发，所以实际下一次自动回复通常会比纯文字模式更晚一点。

截图拼图的时间窗口主要跟“自动回复统一冷却秒数”走，而不是跟“检查间隔”走。比如检查间隔填 `5`、冷却填 `20`，桌宠仍然每 5 秒检查一次是否该回复，但拼图会尽量覆盖最近约 20 秒内的关键画面。

推荐设置：

```text
安静一点：检查 20 秒，冷却 90 秒
比较平衡：检查 15 秒，冷却 60 秒
更活跃：检查 10 秒，冷却 30 秒
```

数值越小，桌宠越容易频繁说话，API 消耗也会更多。
如果你希望她更像“偶尔搭话”，可以把检查设为 20 秒、冷却设为 90 秒；如果希望更活跃，可以把检查设为 10 秒、冷却设为 30 秒。

## 语音说明

- MOD 使用游戏内置的 YUKI 语音，不恢复作者的 RTC/豆包链路。
- HTTP 多模态如果接入的 OpenAI 兼容模型支持流式输出，会边接收边更新同一个气泡，并按完整句子提前生成语音；不支持流式时会自动回到完整回复后再分段播报。
- 语音生成失败时，只会少一次播报，不影响截图、API 和文字气泡。
- 停止桌宠会话时，当前语音会停止，排队中的语音也会清空。

## API 说明

没有现成 API 渠道的用户，可以在左下角“云端大模型”的“快捷预设”里使用“国外模型合集”：

```text
API Base URL: https://api.gptsapi.net
模型名称: gemini-3-flash-preview
注册链接: https://gptsapi.net/
```

这个预设只会填 Base URL 和模型名称，API Key 仍然需要用户自己注册后填写。

OpenAI 兼容模式会请求：

```text
{Base URL}/chat/completions
```

自定义端点模式会发送 JSON：

```json
{
  "prompt": "角色提示词",
  "text": "触发文本",
  "screenshotDataUrl": "data:image/jpeg;base64,...",
  "activeWindowName": "当前前台程序名",
  "history": [],
  "replyMinChars": 20,
  "replyMaxChars": 40,
  "maxOutputTokens": 0,
  "extraPrompt": "用户附加 Prompt",
  "visionPreset": "balanced",
  "visionFrameCount": 4,
  "visionSpanSeconds": 12,
  "visionObservationSpanSeconds": 60,
  "isVisionCollage": true,
  "visionCollageMaxDim": 2816,
  "visionCollageJpegQuality": 76,
  "imageMaxDim": 1408,
  "imageJpegQuality": 82,
  "capturedAt": "时间"
}
```

响应里返回 `text`、`message`、`reply`，或 OpenAI 格式的 `choices[0].message.content` 都可以。

### DeepSeek 说明

DeepSeek 官方 Chat Completions 接口当前按纯文本消息解析，不支持 `image_url` 截图输入。
如果你在桌宠设置里沿用或填写 DeepSeek API，MOD 会自动改成文字模式，只发送触发文本、对话历史和当前前台程序名，不上传截图。这样可以避免 HTTP 400，但也不会有真正的屏幕图片识别能力。

想使用桌宠全模态截图识别，请改用支持图片输入的 OpenAI 兼容模型，或使用“自定义端点”接收 `screenshotDataUrl`。

### Qwen / 通义千问说明

如果使用阿里云百炼 DashScope 的 OpenAI 兼容接口，Base URL 通常类似：

```text
https://dashscope.aliyuncs.com/compatible-mode/v1
```

请填写支持图片输入的视觉模型，例如 `qwen-vl-plus`、`qwen-vl-max`、`qwen3-vl-plus`、`qwen2.5-vl-72b-instruct`、`qwen-vl-ocr`、`qvq` 或 Qwen-Omni 系列。

`qwen-plus`、`qwen-max` 这类普通文本模型不能识别截图，MOD 会自动改用文字模式，避免接口 400。

MOD 已对 Qwen 做兼容处理：

- 图片字段不再发送 OpenAI 的 `detail: high`。
- DashScope 视觉模型会自动带上高清图片参数。
- QVQ 或部分非流式 400 的 Qwen 视觉模型，会自动尝试流式兼容模式。

### Gemini 说明

Gemini 的 OpenAI 兼容接口有时会把口语回复截在半句。默认自动模式下，MOD 不再给 Gemini 额外设置 `max_tokens`，而是用更明确的中文字数限制约束回复；如果检测到疑似截断，会自动重试一次，让模型重新输出一条完整回复。

如果仍然经常不完整，可以在“单次 token 上限”里手动填 `1536` 或 `2048`，或者换响应更稳定的多模态模型。

## Qwen Realtime 说明

桌宠设置里可以把“桌宠引擎”切换为 `Qwen Realtime`。这个模式不会使用作者 RTC/豆包链路，而是用你自己的 DashScope API Key 直连 Qwen Realtime WebSocket。

默认模型预设：

```text
qwen3.5-omni-flash-realtime-2026-03-15
qwen3.5-omni-plus-realtime-2026-03-15
```

默认语音来源是“游戏内置语音”：Qwen Realtime 只返回字幕文字，桌宠再调用游戏自带 Yuki TTS 播放，因此不受 Qwen 音色限制。

如果手动切到“Qwen 模型语音”，才需要填写 Qwen 支持的音色。Qwen3.5 Realtime 默认音色使用 `Tina`；手动填 `Cherry` 可能会返回 voice not supported，`Cherry` 更适合 Qwen3-Omni-Flash-Realtime 系列。

如果 snapshot 模型提示不存在，可以选择“自定义模型名”，改填无日期别名，例如：

```text
qwen3.5-omni-flash-realtime
qwen3.5-omni-plus-realtime
```

Realtime 模式默认使用右 Alt 按住说话，松开发送。安装器会加载一个 Windows 右 Alt 监听小桥；如果热键桥失败，桌宠旁会出现“按住”按钮作为兜底。

Qwen Realtime 默认使用中国北京线路，屏幕帧频率固定为 1fps。它不再使用大拼图，而是发送连续小 JPEG 帧；每张图会按你选择的图片质量档位压缩。注意：Qwen Realtime 的 WebSocket 单帧限制约 256KB，图片转成 base64 再放进消息后会变大，所以 MOD 会把单张 JPEG 控制在约 185KB 以内。这个模式更接近实时感，但 API 消耗和隐私风险都高于 HTTP 冷却截图模式。

Realtime 图片质量档位：

- 极省流量：最长边 640，单图约 45KB，只保留大致场景。
- 低流量：最长边 800，单图约 65KB，比极省流量清楚一点。
- 省流量：最长边 960，单图约 90KB，适合省成本。
- 标准：最长边 1080，单图约 130KB，适合长期常驻。
- 高清：最长边 1440，单图约 160KB，更适合游戏 UI 和小字。
- 极限吃满：最长边 1920，单图约 185KB，尽量贴近 Qwen WebSocket 安全上限，优先识别效果。

如果你觉得上传速率很低，优先试试“高清”或“极限吃满”。极限档仍然会遵守 Qwen WebSocket 单帧限制，超过时会自动降低 JPEG 质量，避免连接被服务端断开。

如果不想一直主动对话，也可以打开“无人说话时自动观察回复”。开启后，右 Alt 按住说话仍然保留；当桌宠空闲、没有播放语音、没有正在生成回复时，它会按你设置的秒数自己看一次屏幕并说一句。

可调选项：

- 自动观察冷却秒数：多久允许一次自动回复，最低 5 秒；用户刚说完话后也会按同一个秒数等待，避免马上插话。
- 自动回复风格：安静陪伴、游戏辅助、活跃陪聊。

例子：自动观察冷却填 `60`，代表桌宠说完一句后至少等 60 秒才会主动观察；如果你刚用右 Alt 跟它说过话，也会先安静 60 秒。正在播语音或正在等模型回复时不会触发新的自动观察。

## 豆包 RTC 高级实验通道

桌宠设置里也可以把“桌宠引擎”切换为 `豆包 RTC（实验）`。这个模式不走作者服务器，使用你自己填写的火山/方舟/RTC/ASR/TTS 配置创建 RTC 房间；豆包负责实时语音识别、屏幕流理解、返回字幕和远端语音。默认直接播放火山远端 TTS，以降低延迟；设置里仍保留“游戏本地 Yuki TTS”作为旧方案兜底。

需要准备：

```text
火山 OpenAPI Access Key ID
火山 OpenAPI Secret Access Key
RTC AppId
RTC AppKey
火山方舟 Endpoint ID
豆包语音 ASR AppId
豆包语音 ASR Access Token（大模型 ASR）
豆包语音 TTS AppId / Access Token
```

方舟 Endpoint ID 必须来自方舟里已经部署成功、可以连到可用模型的 Endpoint。不要填写模型名称、API Key ID、应用 ID 或其它资源 ID。如果测试日志只有 `conv/thinking`，但一直没有 `subv` 字幕，优先检查这个 Endpoint 是否真的能在火山 Demo 中跑通。

豆包语音识别、语音合成等模型通常共用同一个 AppId / Access Token。MOD 里 ASR 和 TTS 会分开填写，方便用户确认当前使用的是哪一套语音配置。

ASR / TTS 页面里看到的 Secret Key 暂时不用填进 MOD。豆包 RTC 的 VoiceChat 链路使用的是 ASR Access Token 和 TTS Token；Secret Key 多用于它们各自的直连接口。

豆包 RTC 固定使用大模型 ASR，ASR Resource ID 使用 MOD 内置默认值，不需要手动填写。

设置页里还有“豆包 RTC 语音输出”选项，默认是“火山远端 TTS”。如果远端语音在你的环境里无法播放，或者你更想保留原本的 Yuki 音色，可以切到“游戏本地 Yuki TTS”。TTS Secret Key 不需要填写；TTS Voice Type 只在选择火山远端 TTS 时显示。

豆包 RTC 的屏幕流现在有两套实现方式，可以在设置页选择：

- `作者 Web SDK 方案（推荐）`：仿照原版桌宠，在桌宠窗口里用 Web SDK 发布会话级屏幕流。它会额外生成一个屏幕流用户加入同一个 RTC 房间，兼容性通常比原生采集更好；如需完全关闭视觉，请把屏幕流模式改为“关闭屏幕流”。
- `原生 veRTC 方案（实验）`：这是之前的 MOD 实现，直接调用 veRTC Electron 原生屏幕采集。少数电脑可能在启动屏幕采集时闪退，主要用于对比和诊断。

豆包视觉截图高度会跟随“屏幕流清晰度”联动，只显示不高于当前屏幕流高度的选项。例如屏幕流选择 1280x720 时，截图高度最高只会出现 720；屏幕流选择 1920x1080 时，最高才会出现 1080。数值越高越利于识别小字和细节，但也可能增加延迟与资源占用。

如果你的电脑测试原生方案会闪退，请切回“作者 Web SDK 方案”。HTTP 多模态和 Qwen Realtime 的截图/视觉逻辑不受影响。

豆包 RTC 的交互和 Qwen Realtime 一样：

- 右 Alt 按住说话，松开发送。
- 热键不可用时，用桌宠旁“按住”按钮兜底。
- 可以开启空闲自动观察。
- 字幕会尽量分段流式显示，语音默认直接播放火山远端 TTS。
- 如果切到“游戏本地 Yuki TTS”，MOD 会按自然分句提前生成语音，尽量做到一段播着、下一段已经准备好。
- 回复完成前会锁定输入，避免重复触发。

注意事项：

- 这是高级实验通道，配置项比 HTTP 和 Qwen Realtime 多很多。
- 不要把 AK/SK、RTC AppKey、ASR Token、RTC Token 发给别人。
- 日志会脱敏 Key/Token，不保存截图原图和音频内容。
- 如果 StartVoiceChat、进房、ASR、Endpoint 或跨服务授权失败，设置页和桌宠气泡会显示中文错误；先点“复制最近日志”排查。

## Realtime 日志

如果 Realtime 聊几次后卡住，打开“桌宠设置”，在“Realtime 调试日志”里点“复制最近日志”，把复制出来的内容发给排查人员即可。

日志只记录状态、事件、耗时、图片/音频大小和错误信息，不保存 API Key、截图原图或音频内容。也可以点“打开日志文件夹”查看本机日志文件，位置在：

```text
AppData\Roaming\urban-friendship-story\yuki-vision-mod\logs
```

## 卸载

关闭游戏后双击 `uninstall.bat`。

用户配置会保留在：

```text
AppData\Roaming\urban-friendship-story\yuki-vision-mod\config.json
```
