前言

最近尝试在本地服务器上部署一个 27B 级别的大模型,目标不是单纯跑通聊天,而是希望它能作为本地代码 Agent 的后端模型使用。

这次选择的是 Qwen3.6-27B 的 GGUF 量化版本,通过 LM Studio 加载模型,再用 OpenAI Compatible API 接入 OpenCode。

整个过程看起来只是“下载模型、加载模型、填一个 API 地址”,但实际踩了不少坑:下载速度、远程桌面、上下文长度、KV Cache、OpenCode 工具调用、显存占用、Tailscale 传输速度等问题都遇到了一遍。

因此这篇文章主要记录这次部署过程。它不是一篇从零开始的完整教程,更像是一份配置复盘和排错记录。

硬件与网络环境

服务器主要配置如下:

项目配置
GPUNVIDIA GeForce RTX 4090 D
显存24GB
CPUIntel Xeon Gold 6330
系统内存30GiB
系统Ubuntu 22.04
远程连接Tailscale + ToDesk / 远程桌面
本机环境Windows + WSL / Git Bash

显卡是 4090D,跑 Q4 量化的 27B 模型没有问题,但显存并不算特别宽裕。尤其是长上下文场景下,真正吃资源的不是模型权重本身,而是 KV Cache。

Tailscale 组网已经打通。测试时可以直接 SSH 到服务器:

1
ssh ubuntu@100.101.72.21

后来也检查过 Tailscale 是否走中继:

1
tailscale ping 100.101.72.21

输出类似:

1
pong from ubuntu-super-server (100.101.72.21) via 120.196.181.230:41641 in 17ms

这里的 via 120.196.181.230:41641 表示是直连,而不是 DERP 中继。

安装 LM Studio

LM Studio 的 Linux 安装包地址类似:

1
https://installers.lmstudio.ai/linux/x64/0.4.18-1/LM-Studio-0.4.18-1-x64.deb

一开始下载时还遇到一个小问题:链接末尾如果少了一个 b,写成 .de,当然会失败。

正确文件名是:

1
LM-Studio-0.4.18-1-x64.deb

服务器直连下载比较慢,所以先在 Windows 本机通过 Clash 下载:

1
2
3
curl.exe -L -C - -x http://127.0.0.1:7897 `
-o "$env:USERPROFILE\Downloads\LM-Studio-0.4.18-1-x64.deb" `
"https://installers.lmstudio.ai/linux/x64/0.4.18-1/LM-Studio-0.4.18-1-x64.deb"

下载完成后通过 Tailscale 传到服务器:

1
scp "$env:USERPROFILE\Downloads\LM-Studio-0.4.18-1-x64.deb" ubuntu@100.101.72.21:/home/ubuntu/Downloads/LM-Studio-0.4.18-1-x64.deb

服务器上安装:

1
sudo apt install /home/ubuntu/Downloads/LM-Studio-0.4.18-1-x64.deb

这里有一个细节:一开始 scp/home/ubuntu/Downloads/ 报错,是因为远程目录不存在。先创建目录即可:

1
mkdir -p /home/ubuntu/Downloads

模型选择与下载

这次使用的是:

1
lmstudio-community/Qwen3.6-27B-GGUF

量化文件选择:

1
Qwen3.6-27B-Q4_K_M.gguf

文件大小大约 16.55GB。

一开始尝试在 LM Studio 图形界面里直接下载,速度非常慢。后来尝试本机下载后通过 Tailscale 传输,但 17GB 文件传起来也很慢。

虽然 Tailscale 是直连,但本机上传大文件时仍然可能受到家庭宽带上行、SSH/SFTP 加密、WSL 读写 Windows 文件系统等因素限制。用 Python Paramiko 分块并行上传时,速度大约只有 1MiB/s 左右,实际并不理想。

最后采用服务器端直接下载的方式,也就是用 hf-mirror 配合 hfdaria2

先安装 aria2:

1
sudo apt-get install -y aria2

下载 hfd:

1
2
3
cd /home/ubuntu/Github
wget -O hfd.sh https://hf-mirror.com/hfd/hfd.sh
chmod a+x hfd.sh

设置镜像端点:

1
export HF_ENDPOINT=https://hf-mirror.com

然后只下载需要的 GGUF 文件:

1
2
3
4
5
6
./hfd.sh lmstudio-community/Qwen3.6-27B-GGUF \
--include Qwen3.6-27B-Q4_K_M.gguf \
--local-dir /home/ubuntu/Github \
--tool aria2c \
-x 10 \
-j 1

这里 -x 最大只能设置到 10。一开始写成 16,hfd 会直接报错:

1
[Error] threads (-x) must be 1-10

另外还遇到过一个 hfd 的小坑:没有安装 jq 时,脚本用 grep/awk 解析 JSON,文件大小被解析成了科学计数法:

1
1.65474e+10

Bash 算术不认识这种写法,于是报错:

1
语法错误:无效的算术运算符

解决方法是安装 jq

1
sudo apt-get install -y jq

如果仍然遇到科学计数法进度问题,可以给 hfd.sh 的进度函数做一个小补丁,把科学计数法转成整数后再参与 Bash 算术。

LM Studio 加载配置

模型下载完成后,在 LM Studio 里加载 Qwen3.6-27B-Q4_K_M.gguf

这次最终尝试的配置大致如下:

项目设置
Context Length262144
GPU Offload64
CPU Thread Pool Size24
Evaluation Batch Size2048
Physical Batch Size512
Unified KV Cache开启
Offload KV Cache to GPU Memory开启
Keep Model in Memory开启
Try mmap()开启

LM Studio 显示模型支持:

1
262144 tokens

这里有一个重要认识:上下文长度不是不够就自动扩展到内存的东西

它分两层:

  1. Context Length 是模型加载时确定的硬上限;
  2. KV Cache 才是真正随着上下文增长而占用显存或内存的部分。

也就是说,如果模型启动时只设置了 8192 context,那么超过 8192 就会直接报:

1
Context size has been exceeded.

即使机器还有内存,它也不会自动变成 64K 或 128K。

128K 对应的数值是:

1
131072

因为:

1
128 * 1024 = 131072

LM Studio API 测试

LM Studio 的 Local Server 启动后,API 信息如下:

参数
Base URLhttp://127.0.0.1:1234/v1
API Keylm-studio
Model IDqwen3.6-27b

可以先用 curl 测试:

1
2
3
4
5
6
curl http://127.0.0.1:1234/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.6-27b",
"messages": [{"role": "user", "content": "你好"}]
}'

如果能正常返回模型回答,说明 LM Studio API 这层已经打通。

接入 OpenCode

OpenCode 已经安装在服务器上:

1
opencode --version

当时版本为:

1
1.17.9

OpenCode 使用 LM Studio 这种 OpenAI Compatible API 时,需要安装 provider 包:

1
2
cd ~/.config/opencode
npm install @ai-sdk/openai-compatible

配置文件位置:

1
/home/ubuntu/.config/opencode/opencode.jsonc

核心配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
"$schema": "https://opencode.ai/config.json",
"model": "lmstudio/qwen3.6-27b",
"small_model": "lmstudio/qwen3.6-27b",
"instructions": ["~/.config/opencode/lmstudio-qwen-tooling.md"],
"snapshot": false,
"compaction": {
"auto": true,
"prune": true,
"reserved": 2000
},
"provider": {
"lmstudio": {
"npm": "@ai-sdk/openai-compatible",
"name": "LM Studio (Qwen3.6 local)",
"options": {
"baseURL": "http://127.0.0.1:1234/v1",
"apiKey": "lm-studio",
"timeout": 600000,
"chunkTimeout": 120000
},
"models": {
"qwen3.6-27b": {
"name": "Qwen3.6-27B (LM Studio local)",
"limit": {
"context": 131072,
"output": 4096
},
"options": {
"temperature": 0.1
}
}
}
}
}
}

这里的:

1
"context": 131072

表示告诉 OpenCode 这个模型可以按 128K 上下文使用。

需要注意的是:这个值不能超过 LM Studio 实际加载模型时的 Context Length。否则 OpenCode 以为能塞进去,LM Studio 仍然会报上下文超限。

工具调用提示规则

接入 OpenCode 后,还遇到过一个问题:Qwen 在复杂 Agent 场景中偶尔会把 bash 工具参数写错。

OpenCode 报错类似:

1
2
The bash tool was called with invalid arguments:
SchemaError(Missing key at ["command"])

直接用 LM Studio 的 tools API 测试时,Qwen 可以正确返回:

1
{"command": "pwd"}

说明模型不是完全不支持 tool calling,而是在 OpenCode 的复杂上下文里偶发不稳定。

于是额外加了一个工具调用说明文件:

1
/home/ubuntu/.config/opencode/lmstudio-qwen-tooling.md

内容大致如下:

1
2
3
4
5
6
7
8
9
10
11
# LM Studio Qwen Tooling Rules

When using OpenCode tools, arguments must strictly match the tool JSON schema.

For the bash tool, always call it with exactly this shape:

{"command":"the shell command to run"}

Never call bash with a raw string, an array, markdown, or keys such as cmd, input, script, code, or args.
If you are not sure which exact command to run, ask or explain instead of calling bash.
Keep tool calls small and simple.

这个不能保证完全解决工具调用稳定性问题,但能明显减少模型乱写参数的概率。

不要在 home 目录直接跑 codegraph

这次最容易误判的一个问题是:

1
Context size has been exceeded.

一开始以为是 LM Studio 上下文没有开大。后来检查发现,LM Studio 实际已经设置到 262144 tokens。

真正的问题之一是:OpenCode 在 /home/ubuntu 目录下做 codegraph,而 /home/ubuntu 太大太杂。

简单看一下目录占用:

1
2
3
4
5
/home/ubuntu/.lmstudio      18G
/home/ubuntu/.cache 15G
/home/ubuntu/miniconda3 11G
/home/ubuntu/.vscode-server 900M
/home/ubuntu/Downloads 636M

其中最大的文件就是模型本体:

1
/home/ubuntu/.lmstudio/models/lmstudio-community/Qwen3.6-27B-GGUF/Qwen3.6-27B-Q4_K_M.gguf

如果让 OpenCode 在 /home/ubuntu 下面分析 codegraph,它会碰到大量无关目录、缓存、模型文件和环境文件,很容易把上下文塞爆。

正确做法是进入具体项目目录:

1
2
cd /home/ubuntu/Github/llm-local-deployment-evaluation
opencode --model lmstudio/qwen3.6-27b

而不是:

1
2
cd /home/ubuntu
opencode

同时在 OpenCode 配置里加入 watcher ignore,排除大目录和二进制文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
"watcher": {
"ignore": [
".cache/**",
".lmstudio/**",
".local/**",
".config/**",
".codegraph/**",
".vscode/**",
".vscode-server/**",
"miniconda3/**",
"Downloads/**",
"下载/**",
"snap/**",
"venv*/**",
"**/*.gguf",
"**/*.deb",
"**/*.run",
"**/*.zip",
"**/*.tar",
"**/*.tar.gz",
"**/*.whl",
"**/node_modules/**",
"**/.git/**"
]
}

当前资源占用

在 LM Studio 和 OpenCode 同时运行时,服务器资源占用大致如下:

1
2
3
4
5
GPU: RTX 4090 D
显存总量: 24564 MiB
显存已用: 20084 MiB
显存剩余: 3995 MiB
GPU 利用率: 15%左右

系统内存:

1
2
3
4
RAM 总量: 30Gi
RAM 已用: 9.5Gi
RAM available: 19-20Gi
Swap: 2.0Gi 已用满

主要进程里,LM Studio worker 大约占 3GB RAM,OpenCode 大约占 0.9GB RAM。

这个状态说明:当前还没有爆显存,也没有立刻把内存压死。但 swap 已经满了,说明之前运行过程中出现过内存压力。

可以用下面命令持续观察:

1
watch -n 1 'nvidia-smi --query-gpu=memory.used,memory.free,utilization.gpu,temperature.gpu,power.draw --format=csv,noheader,nounits; free -h'

这次踩到的坑

这次主要踩了这些坑:

  1. LM Studio 安装包链接写错

    .deb 写成 .de,少了一个 b

  2. 服务器直接下载慢

    安装包可以本机代理下载再传输,模型文件更适合服务器用 hfd + hf-mirror 下载。

  3. scp 到不存在的目录

    远程 /home/ubuntu/Downloads 不存在时,scp 会失败。需要先 mkdir -p

  4. Tailscale 直连不代表传输一定快

    Tailscale 是直连,但大文件上传仍然受本机上行、SSH/SFTP 加密、WSL 文件系统等因素影响。

  5. hfd 线程数不能超过 10

    -x 16 会报错,应该用 -x 10 或更小。

  6. hfd 没有 jq 时解析大文件大小出错

    安装 jq 可以避免 grep/awk 把大文件大小解析成科学计数法。

  7. 上下文长度不是自动扩容

    LM Studio 加载模型时设置多少 Context Length,就是实际硬上限。

  8. OpenCode 的 context limit 要和 LM Studio 对齐

    如果 OpenCode 配得太小,会提前认为上下文超限;如果配得太大,LM Studio 也可能实际拒绝。

  9. 不要在 home 目录跑 OpenCode codegraph

    /home/ubuntu 不是项目目录,里面有模型、缓存、conda、vscode server 等大量无关内容。

  10. Qwen3.6-27B 做 OpenCode 工具调用还不算特别稳

聊天和普通 API 没问题,但复杂 Agent 场景下工具调用参数可能偶发不符合 schema。

最终使用方式

LM Studio 保持 Local Server 运行:

1
2
3
Base URL: http://127.0.0.1:1234/v1
API Key: lm-studio
Model ID: qwen3.6-27b

OpenCode 在具体项目目录中启动:

1
2
cd /home/ubuntu/Github/llm-local-deployment-evaluation
opencode --model lmstudio/qwen3.6-27b

如果要确认模型是否被 OpenCode 识别:

1
opencode models lmstudio

应该能看到:

1
lmstudio/qwen3.6-27b

总结

这次部署的结论是:4090D 24GB 跑 Qwen3.6-27B Q4_K_M 是可行的,LM Studio 也确实是目前比较省心的本地部署方式。

不过,如果目标是接入 OpenCode 这类代码 Agent,问题就不只是“模型能不能跑起来”。还要考虑:

  • 模型是否稳定支持 tool calling;
  • 上下文长度是否和工具端配置一致;
  • codegraph 是否扫描了过大的目录;
  • 显存和 KV Cache 是否有足够余量;
  • 长上下文下速度和稳定性是否可接受。

目前这套配置已经可以让 OpenCode 调用本地 Qwen3.6-27B,但它还不是完全无脑稳定的状态。后续如果主要用于编程 Agent,也许还可以继续尝试更偏代码和工具调用的模型,例如 Qwen Coder 系列。

本地大模型部署的体验很有意思:模型本身能跑只是第一步,真正让它进入工作流,还要处理一堆工程细节。也正是这些细节,决定了它到底只是一个本地聊天窗口,还是可以真的参与开发工作的 Agent 后端。