跳转到内容

使用本地 llama.cpp 模型运行 Bub

本教程演示如何让 Bub 使用本地 llama.cpp server。完成后,Bub 的模型调用会发往你机器上运行的 GGUF Gemma 模型,而不是托管 API。

当你需要在开发环境、私有实验、离线 demo,或贴近应用的低延迟任务中使用本地模型时,可以使用这条路径。本教程不覆盖模型 benchmark、fine-tuning、生产加固,也不讨论如何为所有工作负载选择最佳模型。

示例使用 ggml-org/gemma-4-E2B-it-GGUF,这是 Google Gemma 4 E2B instruction-tuned 模型的 GGUF 版本。Google 的 Gemma 4 overview 把 E2B 和 E4B 描述为适合移动和边缘设备的高效模型;Gemma 4 model card 记录了能力、限制和负责任使用相关注意事项。

你需要:

  • Bub 已安装,且 uv run bub --help 可以运行。
  • 已安装 Docker。
  • ~/.cache/llama.cpp/ 下有 GGUF 模型文件。
  • 系统内存足够运行所选量化版本。Gemma 4 E2B 的 Q8 GGUF 文件约 5 GB;实际运行内存还会受上下文长度、batching、GPU offload 等设置影响。

本教程使用下面两个文件名:

~/.cache/llama.cpp/ggml-org_gemma-4-E2B-it-GGUF_gemma-4-E2B-it-Q8_0.gguf
~/.cache/llama.cpp/ggml-org_gemma-4-E2B-it-GGUF_mmproj-gemma-4-E2B-it-Q8_0.gguf

如果你的文件名不同,需要相应修改 Docker 命令里的 -m--mmproj 路径。

先为本地 server 设置一个 API key:

export LLAMA_API_KEY="${LLAMA_API_KEY:-test}"

启动 llama-server

sudo docker run --rm -it \
  --security-opt label=disable \
  -p 127.0.0.1:8080:8080 \
  -v "$HOME/.cache/llama.cpp:/root/.cache/llama.cpp:ro" \
  ghcr.m.daocloud.io/ggml-org/llama.cpp:full \
  --server \
  --host 0.0.0.0 \
  --port 8080 \
  --api-key "$LLAMA_API_KEY" \
  -m /root/.cache/llama.cpp/ggml-org_gemma-4-E2B-it-GGUF_gemma-4-E2B-it-Q8_0.gguf \
  --mmproj /root/.cache/llama.cpp/ggml-org_gemma-4-E2B-it-GGUF_mmproj-gemma-4-E2B-it-Q8_0.gguf

Docker 端口绑定到 127.0.0.1,因此这个 server 只在本机可访问。只有在明确需要其他机器访问时,才调整端口绑定。

在 SELinux 系统上,--security-opt label=disable 可以避免容器读取 ~/.cache/llama.cpp 下模型文件时遇到 bind mount 权限问题。如果只需要文本输入,可以删除 --mmproj 那一行。

如果 Docker 输出 no ROCm-capable device is detected,容器仍然可能回退到 CPU inference。这足够验证接入路径,但响应速度会更慢。

在另一个终端发送一个小 chat 请求:

curl http://localhost:8080/v1/chat/completions \
  -H "Authorization: Bearer $LLAMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemma-4-E2B-it",
    "messages": [
      {"role": "user", "content": "hello"}
    ]
  }'

正常工作的 server 会返回一个 chat.completion JSON 对象,其中包含 assistant message。

把 Bub 指向本地 server:

export BUB_API_BASE="http://localhost:8080/v1"
export BUB_API_KEY="$LLAMA_API_KEY"
export BUB_MODEL="openai:gemma-4-E2B-it"

运行一个 Bub turn:

uv run bub run "Reply with one short sentence: hello from a local model."

现在 Bub 会通过本地 OpenAI-compatible endpoint 进行模型调用。turn pipeline、channels、tools 和 tapes 都不需要改变。

~/bubbuild/bub$ uv run bub run "Reply with one short sentence: hello from a local model."
2026-05-19 01:32:40.601 | INFO     | bub.builtin.agent:_run_tools_with_auto_handoff:271 - loop.step step=1 tape=becda04eb9f7369c__0b871d5e50e7c192 model=openai:gemma-4-E2B-it
2026-05-19 01:32:46.747 | INFO     | bub.builtin.store:fork:122 - Merged 7 entries into tape "becda04eb9f7369c__0b871d5e50e7c192"
[cli:local]
hello from a local model.

4. 更换工作负载前检查模型文档

Section titled “4. 更换工作负载前检查模型文档”

当你切换模型或量化版本时,先检查上游模型文档:

  • Hugging Face GGUF card 会列出支持的本地运行方式和可用量化文件。
  • Gemma 4 model card 会说明输入模态、上下文窗口、预期用途、许可和风险。
  • 本地运行不等于免评测。本地模型仍然可能生成错误、有偏见或不安全的输出。

适合优先尝试小型本地模型的,是那些更看重延迟、隐私、成本或离线能力,而不是最高模型质量的工作负载。对于高风险或面向产品的工作流,应先在有代表性的任务上评估模型,再接入真实用户路径。

Ctrl-C 停止 Docker 容器。

如果要恢复到之前的 provider,清理 Bub 覆盖配置:

unset BUB_API_BASE BUB_API_KEY BUB_MODEL LLAMA_API_KEY