llama.cpp 本地部署常见问题排查与解决
1. 基础调用与参数配置
使用 llama.cpp 调用模型时,可将启动脚本保存为 bat 文件,放在与 llama-server.exe 同目录下运行。确保模型路径正确,并根据机器能力调整 GPU_LAYERS 和 THREADS。
@echo off
setlocal
set "MODEL_PATH=F:\Models\Yakyu"
set "MODEL_FILE=Qwen3-235B-A22B-Instruct-2507-UD-Q8.gguf"
set CTX_SIZE=32768
set HOST=127.0.0.1
set PORT=1234
echo 正在启动 OpenAI 兼容 API 服务...
echo 模型:%MODEL_PATH%\%MODEL_FILE%
echo 端口:http://%HOST%:%PORT%
echo.
llama-server.exe ^
-m "%MODEL_PATH%\%MODEL_FILE%" ^
--ctx-size %CTX_SIZE% ^
--host %HOST% ^
--port %PORT%
echo.
echo 服务已停止。按任意键关闭窗口...
pause >nul
CMD 窗口出现'all slots are idle'说明模型加载完成,此时可以调用。如果出现乱码,将 .bat 文件保存为 ANSI 编码格式即可。
注:通过 llama-server.exe -h 命令可以看到默认开启了自动适应设备内存(--fit on),因此 --gpu-layers、--n-cpu-moe 等参数不填也行。根据相关技术文档,合理设置 --n-cpu-moe 的值能提速,具体视设备情况而定。
可调参数版本示例:
@echo off
setlocal
set "MODEL_PATH=F:\Models\Yakyu"
set "MODEL_FILE=Qwen3-Next-80B-A3B-Instruct-abliterated-Q8_0.gguf"
set GPU_LAYERS=64
set THREADS=64
set CTX_SIZE=32768
set HOST=127.0.0.1
set PORT=1234
echo 正在启动 OpenAI 兼容 API 服务...
echo 模型:%MODEL_PATH%\%MODEL_FILE%
echo 端口:http://%HOST%:%PORT%
echo.
llama-server.exe ^
-m "%MODEL_PATH%\%MODEL_FILE%" ^
--gpu-layers %GPU_LAYERS% ^
--threads %THREADS% ^
--ctx-size %CTX_SIZE% ^
--n-cpu-moe 10 ^
--host %HOST% ^
--port %PORT%
echo.
echo 服务已停止。按任意键关闭窗口...
pause >nul
多个分片(shard)组成的 GGUF 分片模型需先用 llama-gguf-split 合并成一个才能使用:
D:\Yakyu\llama-b7640-bin-win-cuda-12.4-x64\llama-gguf-split.exe --merge F:/Models/Yakyu/Qwen3-235B-A22B-Instruct-202507/Qwen3-235B-A22B-Instruct-202507-UD-Q8_K_XL-00001-of-00006.gguf F:/Models/Yakyu/Qwen3-235B-A22B-Instruct-202507-UD-Q8.gguf
打开 CMD 输入上述代码即可执行。
2. SillyTavern 调用时报错
当加载的模型是 DeepSeek 时,酒馆可能会报错:Chat Completion API Assistant response prefill is incompatible with enable_thinking。
解决方案
- 换用文本补全模式。
- 在 bat 代码中增加
--reasoning-budget 0来关闭思考功能。
完整代码如下:
@echo off
setlocal
set "MODEL_PATH=F:\Models\Yakyu"
set "MODEL_FILE=DeepSeek-V3.1-Terminus-MXFP4_MOE.gguf"
set CTX_SIZE=32768
set HOST=127.0.0.1
set PORT=1234
echo 模型:%MODEL_PATH%\%MODEL_FILE%
echo 端口:http://%HOST%:%PORT%
echo.
llama-server.exe ^
-m "%MODEL_PATH%\%MODEL_FILE%" ^
--reasoning-budget 0 ^
--chat-template-file "Unslothdeepseek-v3-chat-template.jinja" ^
--ctx-size %CTX_SIZE% ^
--host %HOST% ^
--port %PORT%
echo.
echo 服务已停止。按任意键关闭窗口...
pause >nul
指定 chat-template 是因为关闭思考后可能出现输出空白或内容与输入无关的问题,这通常与内置聊天模板有关。使用 Unsloth 提供的修复模板可解决此问题。
模板内容如下:
{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% if enable_thinking is defined and enable_thinking is false %}{% set thinking = false %}{% elif enable_thinking is defined and enable_thinking is true %}{% set thinking = true %}{% elif not thinking is defined %}{% set thinking = false %}{% endif %}{% set ns = namespace(is_first=false, is_tool=false,, is_first_sp=true, is_last_user=false) %}{%- for message in messages %}{%- if message['role'] == 'system' %}{%- if ns.is_first_sp %}{% set ns.system_prompt = ns.system_prompt + message['content'] %}{% set ns.is_first_sp = false %}{%- else %}{% set ns.system_prompt = ns.system_prompt + '\n\n' + message['content'] %}{%- endif %}{%- endif %}{%- endfor %}{{ bos_token }}{{ ns.system_prompt }}{%- for message in messages %}{%- if message['role'] == 'user' %}{%- set ns.is_tool = false -%}{%- set ns.is_first = false -%}{%- set ns.is_last_user = true -%}{{'<|User|>' + message['content']}}{%- endif %}{%- if message['role'] == 'assistant' and message['tool_calls'] is defined and message['tool_calls'] is not none %}{%- if ns.is_last_user %}{{'<|Assistant|></think>'}}{%- endif %}{%- set ns.is_last_user = false -%}{%- set ns.is_first = false %}{%- set ns.is_tool = false -%}{%- for tool in message['tool_calls'] %}{%- if not ns.is_first %}{%- if message['content'] is none %}{{'<|tool▁calls▁begin|><|tool▁call▁begin|>'+ tool['function']['name'] + '<|tool▁sep|>' + (tool['function']['arguments'] if tool['function']['arguments'] is string else tool['function']['arguments'] | tojson) + '<|tool▁call▁end|>'}}{%- else %}{{message['content'] + '<|tool▁calls▁begin|><|tool▁call▁begin|>' + tool['function']['name'] + '<|tool▁sep|>' + (tool['function']['arguments'] if tool['function']['arguments'] is string else tool['function']['arguments'] | tojson) + '<|tool▁call▁end|>'}}{%- endif %}{%- set ns.is_first = true -%}{%- else %}{{'<|tool▁call▁begin|>'+ tool['function']['name'] + '<|tool▁sep|>' + (tool['function']['arguments'] if tool['function']['arguments'] is string else tool['function']['arguments'] | tojson) + '<|tool▁call▁end|>'}}{%- endif %}{%- endfor %}{{'<|tool▁calls▁end|><|end▁of▁sentence|>'}}{%- endif %}{%- if message['role'] == 'assistant' and (message['tool_calls'] is not defined or message['tool_calls'] is none) %}{%- if ns.is_last_user %}{{'<|Assistant|>'}}{%- if message['prefix'] is defined and message['prefix'] and thinking %}{{''}}{%- endif %}{%- endif %}{%- set ns.is_last_user = false -%}{%- if ns.is_tool %}{{message['content'] + '<|end▁of▁sentence|>'}}{%- set ns.is_tool = false -%}{%- else %}{%- set content = message['content'] -%}{%- if '</think>' in content %}{%- set splitted = content.split('</think>') -%}{%- set content = splitted[1:] | join('</think>') -%}{%- endif %}{{content + '<|end▁of▁sentence|>'}}{%- endif %}{%- endif %}{%- if message['role'] == 'tool' %}{%- set ns.is_last_user = false -%}{%- set ns.is_tool = true -%}{{'<|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}{%- endif %}{%- endfor -%}{%- if add_generation_prompt and ns.is_last_user and not ns.is_tool %}{{'<|Assistant|>'}}{%- if not thinking %}{{'</think>'}}{%- else %}{{'<think>'}}{%- endif %}{% endif %}
将模板文件放置在与 llama-server.exe 同一文件夹内。
3. llama-server 端口绑定失败
在使用 bat 脚本启动 llama-server 并指定端口(如 1234)时,若日志显示监听的是默认端口 8080,说明 --port 参数未生效。
检查方法:
netstat -ano | findstr :1234
若发现没有程序占用该端口,但服务仍使用默认端口,可能是有其他客户端(如另一台电脑上的 SillyTavern)通过端口转发持续连接该端口导致冲突。
解决方法:关闭占用端口的其他客户端软件(如 SillyTavern),重启服务即可正常绑定指定端口。

