第 2 课
不花钱跑通:接本地 Ollama,学会无头模式
把本机 Ollama 的 qwen3:1.7b 配成 Custom Provider;用无头模式直接提问、管道喂文件、输出 JSON 给 jq 解析;关掉自动记忆让一次性调用从 1 分 43 秒降到 14 秒,并看清小模型改不了代码的原因。
课程目录第 2 / 3 课
学习位置仅保存在当前浏览器,有效期 180 天。
不花钱跑通:接本地 Ollama,学会无头模式
本课对照 Qwen Code 官方 Model Providers(本地自托管模型一节)与 Headless Mode 文档编写;在 8 核无显卡的 Debian 13 测试机上实跑,Qwen Code 0.27.3 + Ollama 0.40.13 + qwen3:1.7b(2026-11-14)。
本课目标
- 不花钱、不注册,用本机 Ollama 跑的千问小模型当 Qwen Code 的「Custom Provider」
- 学会无头模式的三种用法:直接带提示词、用管道喂文件、输出 JSON 给脚本解析
- 亲眼看到小模型的能力边界,知道改代码这类任务该换什么模型
前置条件
- 已完成第 1 课,
qwen --version能输出版本号 - 已安装 Ollama,
ollama --version能输出版本号,服务监听在默认端口 11434 - 内存建议 4 GB 以上空闲;本课用的 qwen3:1.7b 下载约 1.4 GB
- 安装了
jq(Debian / Ubuntu 用sudo apt install jq,macOS 用brew install jq)
第 1 步:拉取本地模型
ollama pull qwen3:1.7b
对照结果(结尾几行):
pulling 3d0b790534fe: 100% ▕██████████████████▏ 1.4 GB
verifying sha256 digest
writing manifest
success
再确认 Ollama 的 OpenAI 兼容接口能看到这个模型:
curl -s http://localhost:11434/v1/models | jq -r '.data[].id'
对照结果里应当有一行 qwen3:1.7b。
第 2 步:把 Ollama 写进 settings.json
官方文档说明,Ollama、vLLM、LM Studio 这类本地推理服务都提供 OpenAI 兼容接口,按 openai 协议加一个本地 baseUrl 即可。Ollama 不校验 Key,OLLAMA_API_KEY 随便填一个值就行。
如果第 1 课已经写过 ~/.qwen/settings.json,先备份一份:
mkdir -p ~/.qwen
cp ~/.qwen/settings.json ~/.qwen/settings.json.bak 2>/dev/null
然后写入下面的内容:
cat > ~/.qwen/settings.json <<'EOF'
{
"env": {
"OLLAMA_API_KEY": "ollama"
},
"modelProviders": {
"openai": [
{
"id": "qwen3:1.7b",
"name": "Qwen3 1.7B (Ollama)",
"envKey": "OLLAMA_API_KEY",
"baseUrl": "http://localhost:11434/v1",
"generationConfig": {
"timeout": 300000,
"contextWindowSize": 32768
}
}
]
},
"security": {
"auth": {
"selectedType": "openai"
}
},
"model": {
"name": "qwen3:1.7b"
}
}
EOF
timeout 是单次请求的超时(毫秒)。CPU 上跑模型很慢,官方示例给本地模型配的就是 300000,也就是 5 分钟。
第 3 步:准备一个练习项目
mkdir -p ~/hello-qwen && cd ~/hello-qwen
git init -q
printf 'def add(a, b):\n return a + b\n' > calc.py
git add calc.py
cat calc.py
对照结果:
def add(a, b):
return a + b
git add 先把文件放进暂存区,之后智能体改了什么,用 git diff 一眼就能看出来。
第 4 步:无头模式问第一句
把提示词直接写在 qwen 后面,就是一次性的无头调用,答完自动退出:
time qwen "用一句中文介绍你自己"
对照结果(测试机实跑):
我是一名助手,旨在为您提供帮助和支持。
real 2m18.000s
官方文档里的写法是 qwen -p "…",效果相同;不过 0.27.3 的 qwen --help 已经把 -p 标记为 deprecated,推荐直接写提示词。
第 5 步:用管道把文件喂给它
标准输入的内容会和提示词拼在一起发给模型:
time (cat calc.py | qwen "用两句中文解释这段代码")
对照结果:
这段代码定义了一个名为`add`的函数,接收两个参数`a`和`b`,
通过`+`运算符将它们相加后返回结果。函数本质上是一个简单的
加法操作,用于计算两个数值的总和。
real 1m2.204s
终端里这段话是一整行,这里为了好读手动折了行。小模型每次的措辞都会不同,意思对上即可。
第 6 步:输出 JSON,交给脚本解析
加 --output-format json 后,输出是一个 JSON 数组:第一项是 system 初始化消息(含模型名、工具列表、审批模式),中间是 assistant 消息,最后一项是 result。用 jq 只取最终答案:
time (qwen "只回答一个数字:3 乘以 7 等于几" --output-format json \
| jq -r '.[] | select(.type == "result") | .result')
对照结果:
3乘以7等于21。
real 1m43.840s
总耗时 1 分 43 秒。可我们在同一台机器上另跑同一句时,JSON 里记录模型作答耗时的 duration_ms 只有 17408,也就是 17 秒。多出来的时间花在答完以后:官方 Headless 文档说明,一次性调用输出结果后,会等后台的自动记忆整理(auto-memory)做完才退出。CPU 上的小模型整理得很慢,做练习时可以先关掉:
python3 - <<'PYEOF'
import json, pathlib
p = pathlib.Path.home() / ".qwen/settings.json"
s = json.loads(p.read_text())
s["memory"] = {"enableManagedAutoMemory": False,
"enableManagedAutoDream": False}
p.write_text(json.dumps(s, indent=2, ensure_ascii=False))
PYEOF
这段脚本只是在 settings.json 里加上一段 "memory" 配置,手动编辑也一样。再跑一次,顺便取几个写脚本常用的字段:
time (qwen "只回答一个数字:3 乘以 7 等于几" --output-format json \
| jq -c '.[] | select(.type == "result")
| {result, num_turns, duration_ms}')
对照结果:
{"result":"21","num_turns":1,"duration_ms":13289}
real 0m14.159s
总耗时从 1 分 43 秒降到 14 秒。写脚本时用 .is_error 和进程退出码判断成败:is_error 为 false、退出码为 0 就是成功。
第 7 步:试试让小模型改代码
time qwen "在 calc.py 里新增函数 multiply(a, b),返回 a * b" \
--approval-mode auto-edit
cat calc.py
--approval-mode auto-edit 表示改文件自动批准、执行 Shell 命令仍要确认。测试机上的真实结果(模型回复较长,这里按句折行,结尾的 JSON 示例从略):
The error occurred because the `tool_call` function required
the `name` parameter, which was missing in the parameters
provided. To resolve this, ensure the `name` is included as a
required field when invoking the tool. ……
real 2m16.544s
def add(a, b):
return a + b
模型没有改文件,反而解释起了自己的报错,calc.py 还是原样。
我们另外用 --output-format json 复跑了两次(其中一次用 --core-tools read_file edit 只开放读文件和改文件两个工具),记录显示 qwen3:1.7b 每次都没按工具格式调用,Qwen Code 返回 [tool_call bridge refused] params must have required property 'name',calc.py 一行都没改。这说明 1.7B 的模型能聊天、能读管道进来的文本,却撑不起「读文件、改文件」这种多步工具调用。
要真正改代码,就换第 1 课配好的云端模型,用 --model 临时切换;也可以在本地换参数量更大的模型。想让两种模型都能选,把两课的 modelProviders 条目合进同一个 openai 数组,env 里两个 Key 都保留:
qwen "在 calc.py 里新增函数 multiply(a, b),返回 a * b" \
--approval-mode auto-edit --model qwen3-coder-plus
git diff
本课的测试机没有配云端 Key,这条命令没有实跑。跑完以后用 git diff 确认 calc.py 里多了 multiply 函数即可。
常见坑
- 答完了进程还不退出:这不是卡死,是在等自动记忆整理,见第 6 步。关掉
memory.enableManagedAutoMemory和memory.enableManagedAutoDream后,测试机上一次问答从 1 分 43 秒降到 14 秒。换回云端大模型时可以再打开,跨会话记忆是很有用的功能 - 连接被拒绝:先
curl http://localhost:11434/v1/models确认 Ollama 在运行;baseUrl末尾的/v1不能漏 model.name对不上:model.name必须和modelProviders里某一项的id一字不差,Ollama 的模型名带冒号,例如qwen3:1.7b- CPU 上太慢:Qwen Code 每次都会带上很长的系统提示词和工具说明,测试机上一句简单问答要 1 到 2 分钟,有显卡的机器会快很多
- 覆盖了第 1 课的配置:本课的
cat >会整个覆盖settings.json,要恢复就把settings.json.bak复制回去
小结
只靠一份 settings.json,Qwen Code 就能接上任何 OpenAI 兼容的本地服务。无头模式的直接提问、管道输入和 JSON 输出,足够把它塞进 shell 脚本和 CI。小模型适合练手和做问答,改代码要换更强的模型。下一课给项目立规矩:写 QWEN.md、选审批模式、挂 MCP 服务。

