① 排障速查表
第一动作永远是 status_local_llm.bat,然后按下表对号入座。
| 现象 | 含义 | 处理 |
|---|---|---|
llama-server 0 listeners | 模型没加载 | start_local_llm.bat |
llama-server 2+ listeners | 两个实例抢显存(最危险) | stop 再 start |
shared > 1024 MB | 溢出到共享内存,吞吐会崩 | 关占显存的程序;或降 ctx(同步 contextWindow) |
日志结尾没有 listening on | 加载被打断(有东西在杀进程) | 查 proxy 日志的「尝试启动/冷却」 |
| 重新连接中… N/10 | 服务端在返 500 | 看 llama_server.log 的 send_error / Jinja Exception |
| 重连且消息带截图 | 视觉声明与真实能力不符 → 图片请求 500 | 本地不贴图 / 确认 mmproj 已启用 |
重连且日志有 System message must be at the beginning | 旧模板拒绝对话中间的 system 消息 | 用打补丁的模板重启服务 |
| 上下文压缩失败 | 历史超过 contextWindow | 确认配对关系(见接入页) |
in = 超过 97,000 | 提示词超出客户端限制 | 确认 contextWindow;或工具又变多了 |
out = 256 | proxy 的 256 夹子又回来了 | 检查 openai_proxy.py 有没有被改回旧版 |
查 ZCode 到底发了什么(最快):
python D:\_Qwen3.8-27b\_zcode_setup\last_usage.py 10 REM in = 是本次请求的真实提示词大小;基础底噪应在 4.6 万左右 REM 如果还是 10 万+,说明工具开关没生效(需要重启 ZCode)
② 十三个真因(点开看取证)
按发现顺序排列。每个都是「症状 → 根因 → 修法 → 验证」完整闭环。
5.1有回应但只有一句话就没下文高危
根因:proxy 第 609-610 行 if body.get("max_tokens", 0) < 16: body["max_tokens"] = 256——客户端不发 max_tokens 时得到 0,判断恒成立,每轮都被塞成 256,thinking 先吃掉一部分,只剩一句话。
证据:ZCode 数据库 35 条记录 output_tokens 全是 256。
修法:删掉注入。验证:out 恢复正常长度。
5.2反复无效响应高危
根因:provider 配置 contextWindow: 1000000 是假数据(真实 65536)。ZCode 以为有 100 万,永不压缩,实测发过 130,170 和 382,703 token 的请求 → 400 → 默认重试 10 轮。
修法:填真实值,且按配对公式与服务端 -c 联动。验证:in/out 数据与真实用量一致。
5.3压缩失败,12 分钟高危
根因:拿云端 100 万上下文养了很久的老会话(2,128 条消息 / 25.8 MiB / 历史 ~38 万 token)切成本地模型——压缩救不了它自己:不能压缩因为必须发送历史,不能发送因为太大。38 万 token ≈ 13.4 GiB 纯 KV,加权重 29.9 GiB,不开 UE 也占满整卡。
修法:用本地模型就开新会话,这是纪律不是建议。切之前跑 session_sizes.py。
5.4重新连接中… 9/10(reasoning_effort)
根因:llama-server 日志刷屏 Jinja Exception: Unexpected reasoning effort high.——ZCode 默认发 high,模板只认 xhigh/medium/low,直接抛异常 500。
别走的弯路:--reasoning-effort xhigh 和 --chat-template-kwargs 都没用——请求里带的值优先级最高。
修法:print_patched_template.py 从运行中的服务端读回当前模板,把 raise_exception 换成"不认识就退回 xhigh",空白字符一字不变。验证:所有 effort 值全部 200,thinking 保住。
5.5开机后直接用就重连
根因:启动文件夹里 9/14 的旧快捷方式指向手写参数的 start_autostart.bat:-c 16384——比 ZCode 每次请求的基础提示词(~38,000 token)还小,开机后每个请求都是 400,而且没有 -fa / KV 量化 / 补丁模板。
修法:开机走统一启动脚本(幂等 + 隐藏)。验证:开机后 Get-CimInstance 看运行中命令行参数。
5.6新会话里"压缩失败"(余量太薄)
根因:contextWindow 61,440 下放行了真实 64,824 的请求(估算偏低 ~5.5%);压缩请求再加 2,563 指令 = 67,387 > 65,536。原来只留了 1,100 token 余量,实际需要「估算误差 + 压缩开销」≥ 5,900。
修法:contextWindow 降到 49,152(余量 11,114)起步,后续按配对公式逐级上调。
5.7七个附带问题(一次修掉)多个
① 两个 llama-server 抢显存:实测两个实例同时监听 :11435,合计索要 ~39 GiB 直接溢出——启动脚本现在先确认"进程数 0 且端口空"再启动;② HARD_MSG_CAP 丢消息(日志 丢 1 条, 29027→221 tokens);③ _trim_messages 会删光消息(while other_msgs 单条超预算时全删,模型收到空对话);④ 启动脚本假警告('' 不是转义,健康检查恒失败);⑤ 并发自动重启活锁——"杀残留"把上一次正在加载的进程杀掉永远加载不完,修法:加锁 + 180s 冷却 + LLM_SKIP_KILL=1(回归:6 并发 → 只有 1 次启动);⑥ VBS 里 cmd /c ""路径"" 静默不执行;⑦ 重定向锁死日志句柄——状态行改用 Add-Content。
5.8配套:把 38,000 token 底噪降下来
底噪 = 工具定义 + 系统提示。关掉两个用不到的工具源:cloudbase-skills 插件(~40 个工具)、chrome-devtools MCP(~25 个),保留 UE/Blender/Houdini 工作流相关。预期底噪 38,000 → 18,000~20,000,可用对话空间 11,000 → ~30,000。
注意:插件开关需要重启 ZCode 才生效。后续又实测发现 rider MCP 独占 57,596 token(见 5.13)。
5.9压缩 3 次后被放弃(rapid_refill 熔断)
根因:ZCode 熔断器 compact_rapid_refill_breaker——压缩后不到 3 个工具轮次又填满,连续 3 次就放弃。判定阈值写死在程序里,没暴露成设置项。两个叠加原因:可用空间太小 + 工具输出特别大(抓整页 HTML 一次一两万 token)。
错误方向:加大压缩次数只是把失败推迟(每次压缩要发整段历史 ≈ 25 秒 prefill,实测 8 次压缩花 17.6 分钟)。
修法:开大窗口 + 一次只做一件事 + 分块读("只提取正文前 2000 字")+ 真啃不动换云端。
5.10每天首次开机都连不上隐蔽
症状特征:当天第一次开机连不上,隔一会儿或手动跑就好——极易误判成"开机触发时机不对"。
取证:拉 autostart.log 时间线——09-18 12:10 用 Write 工具重写过 .bat 之后,每次开机日志一个字都没有;手动执行输出乱码碎片('01' 不是内部或外部命令)。
真因:Write 工具写出的文件是 LF 行尾,cmd.exe 按字节偏移读批处理,LF-only 把行拆错位——整个脚本等于没跑,而且不留痕迹。波及 22 个脚本(12 个 .bat / 8 个 .ps1 / 2 个 .vbs)。
修法:fix_crlf.ps1 统一转 CRLF(UTF-8 无 BOM)+ 冗余开机入口每次开机先自愈行尾 + 规则写进 AGENTS.md(改完当场手动跑一次)。判行尾不要用 Git Bash 的 grep -c(会骗人),用 LC_ALL=C tr -cd '\r' < 文件 | wc -c。
5.11服务正常却"重新连接中"(带截图的消息)
取证:/health 正常、进程正常,但某一条消息卡两分钟;llama_server.log 尾部 7 条同样报错 image input is not supported - you may need to provide the mmproj。
根因:那条消息带 2 张截图,GGUF 没有视觉投影器,llama-server 对含图请求一律 500;ZCode 判为暂时性故障重试到 10 次。而 provider 配置错误声明了 supportsImage: true。
修法:改 false + 重启 ZCode(9/29 启用 mmproj 后才改回 true)。
能力边界:不要用"丢图转发"的中间层绕过——模型看不到图却照样回答,会一本正经编造,比直接失败更糟。
5.12图片去掉后仍"重新连接中"
取证:日志 Jinja Exception: System message must be at the beginning.——用 curl 精确复现(system/user/system/user 四段),报错与 ZCode 收到的一字不差。
根因:ZCode 会在对话中间插 system 提醒,而官方模板写死"system 只能是第一条",否则抛异常——客户端敢发、服务端不接受。
修法:模板补丁二(中间 system 渲染成 system 回合),生成脚本改成幂等 + 双补丁,锚点找不到直接报错退出。验证:三种请求形态全部 200。
顺带的坑:PowerShell 5.1 读 .ps1 没有 BOM 按 GBK 解析(中文注释乱码),而 .bat 有 BOM 会让第一行失效——fix_crlf.ps1 保留原 BOM 状态。
5.13只问一个问题就把窗口塞满
实测(context_breakdown.py):新会话首轮提示词 103,762 token;同会话压缩请求 14,151——差额 ≈ 89,600 全是工具定义 + 系统提示。逐家 tokenize:rider MCP 102 个工具 = 57,596 token、monolith 28 个 = 11,887、unrealmcp 只有 323。
结论:这些目录每次请求都会重发——"一问就满"跟会话长短无关。不是 UnrealMCP 的错(运行时按需发现工具)。
修法:把 rider 从 config.json 的 mcp.servers 摘掉,重启后底噪 10.4 万 → 4.6 万,留出 3.5 万干活空间。想保留:JetBrains MCP 插件设置里按工具组勾选,关掉 xdebug/dotTrace/数据库/Unity Profiler。
③ 上下文压缩失败的三种形态
| 形态 | 触发条件 | 出路 |
|---|---|---|
| 死锁(382K 老会话) | 历史太大:不能压缩因为必须发历史,不能发因为太大 | 无解——开新会话,老会话永远别切 |
| 余量太薄(新会话也炸) | contextWindow 与真实用量只差 ~1,100 token,加 2,563 压缩指令即爆 | 按配对公式重算并上调 |
| 熔断(rapid_refill) | 压缩后 <3 个工具轮次又填满 ×3 次;典型是抓整页 HTML 的任务 | 窗口开大 + 任务拆细;次数写死不可调 |
共同背景:压缩摘要在历史里永久累积(每次 +2~3.5K),压得越多底噪越大——所以看到"已自动压缩"就该考虑新开会话。
④ 显存抢用(UE vs 模型同开)
标准答案是三层:
- 预防层:预算按"UE 开着"测(基础占用 7,489 MB),ctx 档位据此标定——不要用引擎关着的测量值做预算;
- 自动层:
--sleep-idle-seconds 180空闲把 ~18 GiB 还给 UE,唤醒只要 7.6 秒; - 手动层:
stop_local_llm.bat立即释放。判定溢出看共享内存:shared > 1024 MB说明已经在 PCIe 反复搬运(实测到过 ttft=104 秒)。
反过来"模型被 UE 拖慢"的归因方法见性能页 · 27 t/s 之谜。
⑤ 两个容易误判的点
1. 进程数 ≠ 实例数。这台机器的 Python 有启动器壳,一个 proxy 在进程表里就是两个 python.exe(父子)。判断有没有重复实例要看端口上的 listener 数量——llama-server 是原生 exe,两个进程就真是两个实例。
2. "开局正常,过会儿就坏"≠ 配置问题。第一次用一直好的配置突然重连,优先查三样:消息里有没有图(5.11)、有没有中间 system 消息(5.12)、工具清单是不是变多了(5.13)——这三个都是"特定输入形态才触发"的故障。