GEOZ

8B 本地模型工具调用从个位数到 84%:Forge 这层护栏怎么做到的

2026/9/22
8B 本地模型工具调用从个位数到 84%:Forge 这层护栏怎么做到的

AIAI Summary (BLUF)

Forge 是一个自托管 LLM 工具调用的可靠性层,通过代理服务器、WorkflowRunner 或中间件三种方式,显著提升本地模型(如 8B 模型从个位数提升至 84%)和云端模型(如 Sonnet 4.6 从 85% 提升至 98%)的工具调用准确率。本文介绍了 Forge 的安装方法、后端配置以及快速上手示例。

核心洞察

这个项目解决的是一个很具体的问题:本地小模型跑工具调用时,经常输出格式不对、参数漏了、或者干脆不按套路出牌。forge 的思路是在模型和你的代码之间加一层“翻译+纠错”,让 8B 模型也能稳定干活。我比较好奇的是它那个 84% 的评测数据,26 个场景的覆盖面到底够不够广,这个后面得实际跑跑看。


核心结论

  1. forge 通过救援解析、重试提醒和响应校验等护栏机制,将 8B 本地模型在 26 个场景评测集上的工具调用准确率从个位数提升至 84%。
  2. Sonnet 4.6 在同一评测集上从 85% 提升至 98%(基于 v0.6.0 数据,v0.7.0 未重跑)。
  3. forge 提供三种使用方式:代理服务器(即插即用,支持 OpenAI 和 Anthropic 双 API)、WorkflowRunner(结构化 agent 循环)和护栏中间件(可组合到自有编排循环中)。
  4. 代理模式默认 --max-retries 为 3,对 Mistral 系模型的格式纠错提升最大;无工具请求跳过校验直接转发。
  5. forge 支持 llama-serverOllama、vLLM、Llamafile、OpenAI 兼容端点和 Anthropic 六种后端,其中 llama-server 为评测推荐的性能最优配置。

项目概览

forge 是给自托管 LLM 做工具调用时加的一层可靠性保障。你把工具集交给它,模型自己决定调哪个、按什么顺序调。工作流结构是可选的,required_stepsprerequisitesterminal_tool 能在需要的时候约束循环,但就算你一个步骤都不定义,forge 的护栏机制(救援解析、重试提醒、响应校验)照样生效。

实测数据方面,forge 把 8B 本地模型在 26 个场景的评测集上从个位数准确率拉到了 84%。Sonnet 4.6 在同一套任务上也从 85% 提到了 98%(Anthropic 的数据是 v0.6.0 测的,v0.7.0 没重跑,因为成本不低)。

forge 不做什么:

  • 不是 agent 编排器。 forge 只在一个 agent 循环内部工作,让工具调用变可靠。多 agent 图、DAG 规划器、跨 agent 协调这些不在它的范围内。
  • 不是编码工具链。 forge 跟具体领域无关。如果你在搭编码 agent(或者已经在用 opencode、aider、Cline 这类工具),代理模式可以直接给你的现有工具链加上 forge 的护栏,不用重写。

三种用法:

  • 代理服务器 — 即插即用的代理(独立发行版里叫 forge-proxy,Python 包里用 python -m forge.proxy),同时支持 OpenAI chat-completions 和 Anthropic Messages(/v1/messages)两套 API,放在任何客户端和本地模型服务器之间。把 OpenAI 兼容的工具(opencode、Continue、aider)或者 Claude Code 指向它,forge 就会透明地加上护栏,客户端以为自己连的是一个更聪明的模型。这是最常用的入口。
  • WorkflowRunner — 定义工具、选后端、跑结构化的 agent 循环。forge 管理完整生命周期:系统提示词、工具执行、上下文压缩、护栏。SlotWorker 额外提供了对共享推理槽的优先级队列访问,支持自动抢占,适合多个专家工作流共享一个 GPU 槽的多 agent 架构。你直接在 forge 上搭建时用这个最合适。
  • 护栏中间件 — 在你自己的编排循环里使用 forge 的可靠性栈(可组合中间件)。循环由你控制,forge 负责校验响应、救援格式错误的工具调用、强制执行必需步骤。

后端支持通用的 OpenAI 兼容端点、Ollama、llama-server(llama.cpp)、Llamafile、vLLM 和 Anthropic。

独立版 Forge Proxy

Forge Proxy 是一个自包含的开发者边车:把 OpenAI 或 Anthropic 兼容的客户端指向它,就能加上 Forge 护栏,不用重写客户端,也不用集成 Python 库。这个命令打包了 Forge、它私有的 Python 运行时和 Anthropic SDK,所以宿主机不需要装 Python 或 pip。它不会安装后端可执行文件、模型、GPU 栈、服务、凭证或客户端配置。

安装最新的稳定版独立 Proxy:

Linux 和 macOS:

curl -fsSL https://raw.githubusercontent.com/antoinezambelli/forge/main/install.sh | sh

Windows PowerShell:

irm https://raw.githubusercontent.com/antoinezambelli/forge/main/install.ps1 | iex

打开一个新终端,然后创建并验证配置文件:

forge-proxy init
forge-proxy check

支持的平台、指定版本安装、配置文件、更新、恢复和卸载,参见 Forge Proxy 安装文档。

Python 库安装

如果你要用 WorkflowRunner、护栏中间件、做开发,或者用 Python 管理 Proxy,就装 Python 包。需要:

  • Python 3.12+
  • 一个运行中的 LLM 后端(见下文)
pip install forge-guardrails                # 仅核心
pip install "forge-guardrails[anthropic]"   # 加上 Anthropic 客户端

Python 包故意不安装全局的 forge-proxy 命令。用 python -m forge.proxy 来运行它的 Proxy 实现;上面的独立安装器是 forge-proxy 命令及其更新/卸载生命周期的唯一所有者。

开发模式:

git clone https://github.com/antoinezambelli/forge.git
cd forge
pip install -e ".[dev]"

后端配置(选一个)

llama-server(推荐,评测前十的配置都跑在 llama-server 上):

# 从 https://github.com/ggml-org/llama.cpp/releases 安装
llama-server -m path/to/Ministral-3-8B-Instruct-2512-Q8_0.gguf --jinja -ngl 999 --port 8080

Ollama(备选,配置更简单,但在较难的任务上稍弱):

# 从 https://ollama.com/download 安装
ollama pull ministral-3:8b-instruct-2512-q4_K_M

Anthropic(API,不需要本地 GPU):

pip install -e ".[anthropic]"
export ANTHROPIC_API_KEY=sk-...

完整说明见后端配置文档,哪个模型适合你的硬件见模型指南。

快速开始

照你平时的方式启动 llama-server(比如在另一个终端里):

llama-server -m path/to/Ministral-3-8B-Instruct-2512-Q8_0.gguf --jinja -ngl 999 --port 8080

然后是你运行的 Python 代码(比如在另一个终端里):

import asyncio
from pydantic import BaseModel, Field
from forge import (
    Workflow, ToolDef, ToolSpec,
    WorkflowRunner, LlamafileClient,
    ContextManager, TieredCompact,
)

def get_weather(city: str) -> str:
    return f"72°F and sunny in {city}"

class GetWeatherParams(BaseModel):
    city: str = Field(description="City name")

workflow = Workflow(
    name="weather",
    description="Look up weather for a city.",
    tools={
        "get_weather": ToolDef(
            spec=ToolSpec(
                name="get_weather",
                description="Get current weather",
                parameters=GetWeatherParams,
            ),
            callable=get_weather,
        ),
    },
    required_steps=[],
    terminal_tool="get_weather",
    system_prompt_template="You are a helpful assistant. Use the available tools to answer the user.",
)

async def main():
    client = LlamafileClient(
        gguf_path="path/to/Ministral-3-8B-Instruct-2512-Q8_0.gguf",
        mode="native",
        recommended_sampling=True,
    )
    ctx = ContextManager(strategy=TieredCompact(keep_recent=2), budget_tokens=8192)
    runner = WorkflowRunner(client=client, context_manager=ctx)
    await runner.run(workflow, "What's the weather in Paris?")

上面那段代码跑通之后,你大概已经摸清了 forge 的基本套路。但真正有意思的是它的代理模式,这才是让现有工具链直接受益的关键。

代理服务器

先提醒一句:如果你是从 0.9 之前的版本升上来的,0.9.0 在代理这块做了一次不兼容改动。官方给了完整的迁移对照表,升级前花两分钟扫一遍,能省掉不少排查时间。

代理的定位很直接:夹在你的客户端和本地模型服务之间,同时说 OpenAI chat-completions 和 Anthropic Messages 两套 API。你把客户端指向代理地址,比如 http://localhost:8081/v1,forge 就在中间悄悄做纠错和格式转换。客户端那边完全无感,以为自己连的是一个更聪明的模型。

这条路适合已经有现成工具链的人。opencode、Continue、aider、Cline,只要说 OpenAI 那套 schema 的都能接。Claude Code 走 Anthropic Messages API 也没问题。不用改一行 Python。

推理回放默认是 none。forge 照样会捕获推理内容用于观测,但后续轮次不会把它塞回后端历史里。这是最省 token 的策略,而且在评测集上和全量回放的统计差异可以忽略。想调的话,--reasoning-replay keep-last 只回放最近一段推理,--reasoning-replay full 恢复旧版的全量回放行为。

启动方式分几种:

# 外部 llama-server,后端你自己管,forge 只做代理
python -m forge.proxy --backend-url http://localhost:8080 --backend llamaserver --port 8081

# 下游是 Anthropic 形态的外部服务
python -m forge.proxy --backend-url https://gateway.example --backend anthropic --model claude-route --port 8081

# 托管模式,forge 自己拉起后端再开代理
python -m forge.proxy --backend llamaserver --gguf path/to/model.gguf --port 8081

托管 vLLM 的话,用 --model-path 传模型目录或者 HuggingFace 仓库 ID 就行:

python -m forge.proxy --backend vllm --model-path /path/to/awq-dir --port 8081

托管模式省事,但调试的时候外部模式更透明,后端日志和代理日志分开看,出问题好定位。

托管 vLLM——通过 --model-path 传入模型目录或 HF 仓库 ID

python -m forge.proxy --backend vllm --model-path /path/to/awq-dir --port 8081

然后把客户端的 API base URL 指到 http://localhost:8081/v1 就行。

Claude Code: 代理同时在 POST /v1/messages 上提供 Anthropic Messages API,所以你可以把 Claude Code 接到 forge 守护的本地模型上。给 claude 进程设 ANTHROPIC_BASE_URL=http://localhost:8081ANTHROPIC_AUTH_TOKEN=anything 即可。完整配置(原生 vs 提示词 FC、Anthropic 格式下游、cache_control)见 Using forge with Claude Code

后端兼容性:

  • 托管模式会拉起 llama-server、llamafile 或 vLLM,或者附着到已有的 Ollama 守护进程上。支持的 selector 有 llamaserverllamafileollamavllm(GGUF 系后端用 --gguf,vLLM 用 --model-path,Ollama 用 --model)。停掉 Forge 会卸载选中的 Ollama 模型,但不会停止或接管守护进程本身。
  • 外部模式--backend-url。省略或写 --backend openai 都走通用 OpenAI 兼容;完整的显式 selector 集合是 openaianthropicllamaserverllamafileollamavllm。专用 selector 会选用对应的适配器和元数据行为。在通用 OpenAI/llama 配置下,--model 只是兜底,仅当入站请求没带 model 时才生效;入站值优先。在 Anthropic 和 vLLM 配置下,--model 固定线路身份。对于未固定的 vLLM,第一个推理请求会发现实际服务的身份。--budget-tokens 只独立提供一个报告分母,绝不会阻止必需的未固定身份发现。

代理模式加固了什么

在带工具的推理请求上,forge 按顺序执行:

  1. 响应校验——模型响应里的每个工具调用都会拿请求中的 tools 数组做检查。未知工具名或格式错误的调用会在响应返回客户端之前被拦截。
  2. 救援解析——模型用错格式发出工具调用时(代码围栏里的 JSON、Mistral 的 [TOOL_CALLS]name{args}、Qwen 的 <tool_call>...</tool_call> XML),forge 会提取结构化调用并以规范的 OpenAI tool_calls schema 重新发出。对 Mistral 系模型提升最大。
  3. 带错误追踪的重试循环——校验失败时,forge 会在规范通道上带一条纠正性工具结果消息重试推理,最多 --max-retries 次(默认 3),而不是返回格式错误的响应。从客户端角度看,代理就像一次多花了几毫秒的普通请求。
  4. 可选的合成 respond 工具注入——--inject-respond-tool 在有工具时选择注入一个合成的 respond 工具。默认关闭。启用后,该调用会从出站响应中剥离并变成普通文本。理由见 ADR-013

无工具的请求跳过校验、救援和重试,直接进入选定的后端适配器。

代理模式不做什么

代理模式是每请求单次执行;有些 forge 功能需要多轮工作流状态,而 OpenAI chat-completions schema 不携带这些:

  • 前置条件强制和步骤排序——这些需要跨轮次的工作流定义。在 WorkflowRunner 里可用。
  • 上下文压缩和会话记忆——代理模式从不压缩或删除调用方历史。保留的 llama/OpenAI 适配器规范化可能会为后端模板兼容性合并连续可见的同角色消息;这和预算驱动的压缩是两回事。管理滚动窗口是客户端的活。
  • 非托管后端操作——元数据和 --budget-tokens 仅用于报告。模型分配/切换、溢出拒绝、就绪状态和后端故障都由运维方负责。托管代理模式保留 backendmanualforge-fullforge-fast 分配行为。

只读后端元数据仅在 GET /health/v1/health/v1/models/models/props 上转发。Forge 存活状态用 /forge/health。转发是透明的:如果选定的后端没实现某个路由,Forge 原样返回其状态,包括 Ollama 对 /health404/forge/usage 报告一个最近完成的进程本地快照或 204;它不是实时计量器、账本或持久会话 API。Forge Proxy 是每运维方的 sidecar,不认证调用方;--backend-api-key 认证的是 Forge 到后端,不是调用方到 Forge。

要完整的护栏面,直接用 WorkflowRunner。代理用深度换的是"用 forge 配你现有环境,不用重写"。

常用标志

标志 默认值 用途
--max-retries N 3 每次校验失败的重试预算
--no-rescue (救援开启) 禁用救援解析(仅调试用)
--budget-mode {backend,manual,forge-full,forge-fast} backend 托管后端分配/报告模式;代理从不压缩调用方历史
--budget-tokens N 托管 --budget-mode manual 下的正数手动分配;非托管模式下仅作报告分母
--serialize / --no-serialize auto 强制请求串行化(单槽后端)
--extra-flags ... 传给 Forge 拉起的 llama-server、llamafile 或 vLLM 的终端 argv 剩余部分;Ollama 和非托管模式会拒绝

托管 Ollama 还会拒绝它无法应用的进程/KV 控制:cache_type_kcache_type_vn_slotskv_unified

Docker

你可以把 forge 代理跑成 Docker 容器。

构建镜像:

docker build -t forge-proxy .

运行容器:

# 连接到外部后端(比如同一台机器上托管的 vLLM)
docker run -p 8081:8081 forge-proxy --backend-url http://host.docker.internal:8000 --backend vllm --budget-tokens 8192

注意:如果后端跑在宿主机的 localhost 上,用 http://host.docker.internal:PORT(macOS/Windows)或宿主机 IP,让容器能访问到。

后端

后端 最适合 原生 FC?
OpenAI 兼容 已有的本地或托管的 OpenAI 格式端点
Ollama 最简设置,内置模型管理
llama-server 最佳性能,完全控制 是(配合 --jinja
Llamafile 单二进制,零依赖 是,或提示词注入
vLLM 高吞吐服务,AWQ/GPTQ 权重 是(服务端解析器)
Anthropic 前沿基线,混合工作流

安装见 Backend Setup,选哪个模型见 Model Guide

运行测试

python -m pytest tests/ -v --tb=short
python -m pytest tests/ --cov=forge --cov-report=term-missing

改了代理的话,还要跑 Contributing 里描述的确定性代理冒烟测试和手动真实后端健全性检查。

评测框架

场景衡量一个模型加后端的组合在多步工具调用工作流中导航的可靠程度,带一个基线层级和一个 advanced_reasoning 层级用于高端区分。

评测这块,Forge 提供了完整的 CLI 工具链。具体的场景清单和完整参数说明在 Eval Guide 里,这里只过一下常用命令。

已发布的 run-level 结果语料库在 Hugging Face 上:Forge eval dataset

# llama-server(先在另一个终端启动,参考 Eval Guide)
python -m tests.eval.eval_runner --backend llamafile --llamafile-mode prompt --gguf "path/to/Ministral-3-8B-Instruct-2512-Q8_0.gguf" --runs 10 --stream --verbose

# 批量评测(JSONL 输出,支持自动断点续跑)
python -m tests.eval.batch_eval --config all --runs 50

# 报告 — 默认输出 ASCII 表格;--html / --markdown 导出其他格式
python -m tests.eval.report eval_results.jsonl
python -m tests.eval.report eval_results.jsonl --html docs/results/dashboard.html
python -m tests.eval.report eval_results.jsonl --markdown docs/results/

项目结构

src/forge/
  __init__.py          # 公开 API 导出
  errors.py            # ForgeError 异常体系
  server.py            # setup_backend()、ServerManager、BudgetMode
  core/
    messages.py        # Message、MessageRole、MessageType、MessageMeta
    workflow.py        # ToolSpec、ToolDef、ToolCall、TextResponse、Workflow
    inference.py       # run_inference() — 共享前半段(压缩、折叠、校验、重试)
    runner.py          # WorkflowRunner — 智能体循环
    slot_worker.py     # SlotWorker — 优先级队列的槽位访问
    steps.py           # StepTracker
  guardrails/
    guardrails.py      # Guardrails 门面 — 在外部循环中应用完整防护栈
    nudge.py           # Nudge 数据类
    response_validator.py  # ResponseValidator、ValidationResult
    step_enforcer.py   # StepEnforcer、StepCheck
    error_tracker.py   # ErrorTracker
  clients/
    base.py            # ChunkType、StreamChunk、LLMClient 协议
    ollama.py          # OllamaClient(原生函数调用)
    llamafile.py       # LlamafileClient(原生函数调用或提示注入)
    openai_compat.py   # OpenAICompatClient(通用 OpenAI 格式端点)
    vllm.py            # VLLMClient(vLLM 专属标识与响应处理)
    anthropic.py       # AnthropicClient(前沿基线)
  context/
    manager.py         # ContextManager、CompactEvent
    strategies.py      # CompactStrategy、NoCompact、TieredCompact、SlidingWindowCompact
    hardware.py        # HardwareProfile、detect_hardware()
  prompts/
    templates.py       # 工具提示构建器(提示注入路径)
    nudges.py          # 重试与步骤强制提示模板
  tools/
    respond.py         # 合成 respond 工具(respond_tool()、respond_spec())
  proxy/
    __main__.py        # CLI 入口:python -m forge.proxy
    proxy.py           # ProxyServer — 编程式启停 API
    server.py          # 原生 asyncio HTTP 服务器,SSE 流式
    handler.py         # 请求处理器 — HTTP 与 run_inference 之间的桥接
    convert.py         # OpenAI messages ↔ forge Messages 转换
tests/
  unit/                # 确定性测试 — 不需要 LLM 后端
  eval/                # 评测框架 — 针对真实后端的模型资格测试

文档

论文

Forge 防护栏框架及消融实验已发表:

Zambelli, A. Forge: Closing the Agentic Reliability Gap Between Self-Hosted and Frontier Language Models.
https://doi.org/10.1145/3786335.3813193

预印本也保留在 docs/forge_ieee_preprint.pdf,作为历史存档。引用请用上面已发表的版本,DOI 链接可能因出版商发布时间而暂时无法访问。

许可证

MIT — Copyright (c) 2025-2026 Antoine Zambelli

常见问题(FAQ)

Forge 的代理服务器模式怎么用?需要改客户端代码吗?

不需要改客户端。把 OpenAI 兼容工具(opencode、Continue、aider)或 Claude Code 指向 forge-proxy,它同时支持 chat-completions 和 Anthropic Messages 两套 API,forge 会透明加上护栏,客户端以为连的是更聪明的模型。

Forge 支持哪些本地和云端后端?推荐哪个?

支持通用 OpenAI 兼容端点、Ollama、llama-server、Llamafile、vLLM 和 Anthropic。推荐 llama-server,评测前十的配置都跑在它上面;Ollama 配置更简单,但较难任务上稍弱。

Forge 能提升多少工具调用准确率?评测覆盖多少场景?

在 26 个场景的评测集上,forge 把 8B 本地模型从个位数准确率拉到 84%,Sonnet 4.6 从 85% 提到 98%。Anthropic 数据是 v0.6.0 测的,v0.7.0 因成本未重跑。

晓婷深圳
本文由 晓婷 审核,最后更新于 2026年9月22日
联系编辑 →
← 返回文章列表
分享到:微博

版权与免责声明:本文仅用于信息分享与交流,不构成任何形式的法律、投资、医疗或其他专业建议,也不构成对任何结果的承诺或保证。

文中提及的商标、品牌、Logo、产品名称及相关图片/素材,其权利归各自合法权利人所有。本站内容可能基于公开资料整理,亦可能使用 AI 辅助生成或润色;我们尽力确保准确与合规,但不保证完整性、时效性与适用性,请读者自行甄别并以官方信息为准。

若本文内容或素材涉嫌侵权、隐私不当或存在错误,请相关权利人/当事人联系本站,我们将及时核实并采取删除、修正或下架等处理措施。也请勿在评论或联系信息中提交身份证号、手机号、住址等个人敏感信息。