Hugging Face Blog

We got local models to triage the OpenClaw repo for FREE!*

8.5内容质量

TL;DR · AI 摘要

Hugging Face 使用本地模型 Gemma 和 Qwen 实现 OpenClaw 仓库的自动化分类,无需依赖云端模型。

核心要点

  • 使用本地模型 Gemma 和 Qwen 可实现 OpenClaw 仓库的实时分类任务。
  • 本地模型运行成本低,仅需支付电费,无需订阅云端服务。
  • 通过结构化输出和代理系统,本地模型可高效分类 PR 和 issues。

结构提纲

按章节快速跳转。

  1. 文章介绍了使用本地模型替代云端模型进行 OpenClaw 仓库分类任务的背景和动机。

  2. 本地模型运行成本低,且能提供实时分类能力,避免依赖云端服务。

  3. 文章测试了 GemmaQwen 两种模型,并通过性能优化提升分类效率。

  4. 通过结构化输出和代理系统,本地模型可高效分类 PR 和 issues。

  5. 文章定义了有限的分类标签,用于对 issues 和 PRs 进行分类。

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • 本地模型在 OpenClaw 的应用
    • 背景与动机
      • 云端模型风险
      • 本地模型优势
    • 实现方法
      • 模型选择
      • 代理系统
      • 分类标签

金句 / Highlights

值得收藏与分享的关键句。

#Hugging Face#本地模型#AI 代理#OpenClaw#分类任务
打开原文

我们利用本地模型免费对 OpenClaw 仓库进行分类处理!

返回文章列表

[-1

]

[0

2026年6月22日发布

GitHub 上的更新

点赞

3

[

Onur Solmaz

osolmaz

关注

ben burtenshaw

burtenshaw

shaun smith

evalstate

Pedro Cuenca

pcuenq

Lysandre

*这里的“免费”指的是不包括电费成本,假设你已经拥有相关硬件

2026年6月将被铭记为人们意识到封闭模型可以被撤回的时刻。鉴于Anthropic最新旗舰模型Claude Fable 5刚刚被移除,人们可以理解为何现在比以往任何时候都更加重要,拥有自己的AI堆栈并在本地运行模型,特别是如果你的业务是建立在AI之上的。

在这方面,我们想分享我们如何在代理框架中使用本地模型,如Gemma和Qwen,来进行分类任务[^1]。这种方法不同于使用BERT进行分类。在像Pi这样的代理框架中,本地模型可以与结构化输出一起使用,以分配标签。我们选择这种方法是因为我们已经有了本地模型和框架,并且坚信随着本地模型能力的提升,类似的设置将越来越受欢迎。[^2]

我们的起点是OpenClaw仓库中的开源贡献。OpenClaw每天都会收到数百个问题和PR,这些都需要进行分类、优先级排序并路由给维护者。我,Onur,正在努力让本地模型与OpenClaw良好配合。作为这个特定领域的维护者,我需要快速响应任何P0问题。

使用像GPT-5、Opus或Sonnet这样的最先进封闭模型,这是一项相当直接的任务。但我不幸拥有128 GB的统一内存,即NVIDIA GB10。因此,我接受了这个任务:

我能否构建一个实时通知系统,仅使用本地开放权重模型来过滤并通知我负责的问题?

这个小盒子,即DGX Spark,可以以高并发性运行gemma-4-26b-a4b,并每秒生成数百个令牌。

如果我在每月200美元的ChatGPT Pro计划上设置OpenClaw主代理,以在每个新问题或PR上触发任务,这将消耗我的配额。我可能改为每2小时或每6小时运行一次。这将使问题在更长的时间段内进行批处理,因此我们将用延迟处理来换取实时通知。

如果我在已经运行的硬件上使用本地模型运行此任务,我不仅将获得近乎即时的通知,而且还可以免费完成(或者更准确地说,只需支付电费)。

对问题和PR进行分类

我们确定了一组有限的标签,代表我们需要分类的问题类别,然后使用本地模型将每个问题分类到这些类别之一,如local_models、self_hosted_inference、acp、agent_runtime、codex、ui_tui等。[^3]

但如何对拉取请求进行分类?是否只需向Chat Completions端点发送一个简单的请求,使用工具JSON模式,将主题作为枚举?

某种程度上是的。但这是2026年,而不是2023年,我们有代理。我们可以做得更好!

在本地模型的选择上,我们测试了gemma-4-26b-a4b和qwen3.6-35b-a3b。通过性能优化,两者都可以在本地每秒生成数百个令牌。

我们使用代理框架来驱动分类运行。为此,我们将pi打包为一个框架,可以调用本地模型端点。

默认情况下,代理在第一个提示中会接收到 PR 的标题、正文以及 PR diff 的截断摘录。然后,它可以选择使用 bash 工具对 OpenClaw 仓库执行只读操作(如果需要查看代码库),或者使用 final_json 工具提交最终的分类结果。

在高吞吐量的设置中,你不希望为本地运行的模型提供完整的 bash 访问权限,因为如果存在提示注入的 issue 或 PR,可能会引导模型执行与分类无关的操作。

出于这个原因,我们使用 reposhell 而不是 bash:这是一个受限的 bash 类 shell,仅允许对 OpenClaw 仓库执行只读操作(如 ls、find、cat、grep 等)。模型认为它在使用 bash,但任何不允许的操作都会被拒绝:

code
reposhell bound cwd=/repo/openclaw repos=openclaw
type help for allowed commands; exit or quit to leave

reposhell /repo/openclaw> help
allowed: pwd, ls, find, rg, grep, sed -n, cat, head, tail, wc -l, git status --short, git show --name-only, git grep, git ls-files
search: rg -n -i "lm studio" or grep -R -n -i "lm studio" .
files: rg --files -g "*.ts" or git ls-files src
examples: rg -n reposhell README.md | sed is not allowed; use one simple command at a time

reposhell /repo/openclaw> head README.md
# 🦞 OpenClaw — Personal AI Assistant

<p align="center">
    <picture>
        <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/openclaw/openclaw/main/docs/assets/openclaw-logo-text-dark.svg">
        <img src="https://raw.githubusercontent.com/openclaw/openclaw/main/docs/assets/openclaw-logo-text.svg" alt="OpenClaw" width="500">
    </picture>
</p>

<p align="center">

reposhell /repo/openclaw> curl localhost
reposhell policy denied command: unsupported command "curl"
exit_code=2

reposhell /repo/openclaw>

这里有一个具体的例子说明了这一点的重要性。在一个保存的会话示例中,qwen3.6-35b-a3b 正在对 openclaw/openclaw#84621 进行分类,该 PR 的标题为 Fix Kimi tool-call rewriting stop reason handling。思考块显示模型最初考虑了 coding_agent_integrations,因为更改的路径 extensions/kimi-coding 看起来是合理的。模型使用 reposhell 通过简单的只读命令(如 ls extensions、ls extensions/kimi-coding 和 cat extensions/kimi-coding/package.json)检查了本地仓库。该包元数据表明,该扩展实际上是 @openclaw/kimi-provider,一个 OpenClaw Kimi 提供程序插件。因此,模型将最终标签更正为 inference_api 和 tool_calling,并明确排除了 coding_agent_integrations。

我们之前提到过,我们捆绑了一个特定的 pi 配置,只能执行只读操作并返回分类输出。我们称其为 localpager-agent,以 localpager 命名,这是此项目的主要名称。每个 PR 和 issue 都会生成一个提示,然后与其它参数一起传递给 CLI,如下所示:

code
localpager-agent \
  --model
"<model-id>"
\
  --base-url
"<openai-compatible-base-url>"
\
  --session-dir
"<session-output-dir>"
\
  --final-schema
"<runtime-schema.json>"
\
  --tools bash,final_json \
  --reposhell-socket
"<reposhell.sock>"
\
  --reposhell-default-repo
"<repo-id>"
\
  --reposhell-visible-repos
"<repo-id>[,<repo-id>...]"
\
  -p
"
$(cat <rendered-prompt.md>)
"

处理传入的 PR 和 issue

那么,从收到的 PR/issue 到最终在 Discord 上的通知,中间的整个流程是由什么来协调的呢?

最终过滤后的 Discord 通知看起来是这样的:关于所需垂直方向的 PR 会被路由到我这里。

这个协调过程非常简单;只有分类步骤涉及到了 LLM:

  • 我们使用 openclaw/gitcrawl 作为仓库的本地镜像。每当有新的 PR 或 issue 时,每个项目都会被标准化为相同的格式,并写入 localpager 自己的 SQLite 数据库。如果该项目是新的,localpager 会为它创建一个分类任务。
  • 然后,一个 worker 会从该队列中领取任务。它会构建一个 GitHub 上下文对象,包含 issue 或 PR 的标题、正文、标签、作者、状态,以及可选的评论、修改的文件和选定的 diff 摘要。这意味着本地模型大多数时候不需要浏览 GitHub 或打开 URL,它会直接获得所有相关的上下文信息。
  • 上下文对象被渲染成一个提示,并传递给 localpager-agent,如前一节所述。agent 可以进行思考并使用 reposhell,但最终必须按照定义的架构输出分类结果。
  • 输出结果会被存储回 localpager 的 SQLite 数据库,并根据用户配置的通知策略发送到 Discord(例如,通知我这些主题,但不通知其他主题)。

下面是展示 localpager 整体架构的图示:

该架构是半代理式的。标签的生成是通过代理完成的,而发送通知则由确定性的规则处理。这样做的目的是通过去除任务中最简单部分的推理需求,使通知流程更快。本地推理是免费的,但每个任务都有资源竞争成本:GPU 带宽应保留给那些确实需要推理的任务。这还可以减少通知过程中出错的可能性。

本地模型能否对 PR 进行分类?

坦率地说,这个系统的早期本地版本存在很多噪音。第一个测试的模型 gemma-4-e4b-it 对于让整个本地流程正常运行是有帮助的,但它也倾向于给 PR 或 issue 添加过多不相关的标签。误报的标签会使 Discord 的信息流变得嘈杂,并且无法让我关注到真正重要的问题。这促使我们转向测试更大的本地模型,包括 gemma-4-26b-a4b 和 qwen3.6-35b-a3b,使用下面的 330 行评估集。

在早期的提示工作方面,我们还通过 antirez 的 DS4 实现使用了 DeepSeek-V4-Flash[^4] 来创建早期数据集的标签。该设置使用了 DS4 服务器和 CUDA。最终我们放弃了 DS4 作为标签器,因为它在不同运行中无法保持标签的一致性。我们也没有将其视为 localpager-agent 的主要模型,因为它太大了,我们的硬件无法获得足够的吞吐量:DS4 服务器每秒只能处理大约 14 个 token,最大并发数为 1。

为了测试模型性能,我们选择了 330 个 GitHub issue 和 PR,并为它们生成了标签。每个项目被标记了五次(3 次 GPT-5.5 和 2 次 Opus 4.8),模型之间需要达成一致才能被接受。这个过程包括手动裁定、改进标签定义并突出显示模型的内部产品设计选择。这为我们提供了一组稳定且可重复的标签,以便与较小的模型进行比较。

在对这个评估集获得有用结果之前,我们无需对 gemma-4-26b-a4b 或 qwen3.6-35b-a3b 进行提示优化。使用相同的路由提示,Gemma 的召回率更高,每行的墙钟时间更少,而 Qwen 的精确率更高,完全匹配率更高,假阳性更少。我们还运行了 DeepSeek-V4-Flash 作为参考,使用相同的集合。它假阳性最少,但由于模型大小和吞吐量,它在 NVIDIA GB10 上实时执行这些任务是不切实际的。由于每一行可能有多个标签,假阳性和假阴性是所有行的总标签数。下面的 Qwen 结果是在模型在调用 final_json 之前输出标记用尽时重试结构化输出失败后得出的。对于 Gemma 和 Qwen,重复运行的指标报告了三次运行的平均值 ± 样本标准差。DeepSeek-V4-Flash 作为参考仅运行了一次。

指标

code
gemma-4-26b-a4b
code
qwen3.6-35b-a3b
code
DeepSeek-V4-Flash

精确率

0.716 ± 0.010

0.831 ± 0.007

0.938

召回率

0.905 ± 0.004

0.818 ± 0.006

0.714

F1

0.800 ± 0.008

0.824 ± 0.002

0.811

完全匹配

0.410 ± 0.014

0.540 ± 0.014

0.509

假阳性

227.0 ± 10.5

105.7 ± 6.4

30

假阴性

60.0 ± 2.6

115.3 ± 4.0

181

每行墙秒数

1.41 ± 0.04

13.51 ± 0.79

144.14

每工作者输出标记/秒

25

50

13

输出标记/秒总计

402.6

145.3

并发数

16

4

1

总参数

26B

35B

284B

活动参数

4B

3B

13B

这里的吞吐量和墙钟时间并不是这些模型在该硬件上的最终最大性能数字。它们是我们当时使用的设置,以及我们当时可用的优化。例如,在一个单独的探测中,gemma-4-26b-a4b 也支持并发 32,并且达到了每秒超过 700 的总输出标记。

在 330 行标签集上的基准比较。每个面板使用自己的垂直刻度;蓝色标记该指标的最佳值。精确率和召回率的误差条显示 Gemma 和 Qwen 在三次运行中的样本标准差。

对于 Gemma 基准测试,我们使用 vLLM 为 gemma-4-26b-a4b 提供服务,使用我们为该设置找到的可用优化。其中很大一部分是 NVFP4 量化:在 GB10 类 Blackwell 硬件上,它不仅仅是一个更小的模型文件,而是一种对硬件友好的格式,相比 Q4_K_M 这样的可移植 GGUF 量化,它能够更直接地使用 NVIDIA/vLLM 执行路径。实际上,这意味着更少的内存流量和更多的批处理空间。我们还启用了前缀缓存、FP8 KV 缓存、CUTLASS MoE 后端和仅语言模型模式。在并发 16 的情况下,完整的 330 行运行大约需要 7.5 分钟。

使用 OpenClaw 跟踪和验证实时性能

我们之前提到过,我们不需要为每个新问题或 PR 运行一个使用本地模型的任务,而是可以每隔 n 小时(例如每 2 小时)运行一个使用 SOTA 云模型(如在 OpenClaw 中运行的 GPT-5.5)的批量任务,以达到相同的效果。[^5]

在这种情况下,我们需要一个 ChatGPT Pro 计划。由于模型是 SOTA,即使将 2 小时的问题/PR 批处理在一起,我们仍然可以期望它表现得相当好。

因为我们想看看本地分类器在与 GPT-5.5 对比时的表现如何,所以我们同时运行两者,并让 GPT-5.5 每 2 小时作为判断假阳性和假阴性的标准。

为了确保安全,我们在沙箱环境中运行 OpenClaw 任务,仅允许其访问我们报告结果的公共仓库。在我们的情况下,我们让 OpenClaw 任务更新一个机器可读的文件,然后一个简单的脚本读取 Codex 分配的标签并计算误报/漏报状态。示例输出如下:

误报 Issue #88499 openai-responses 提供商:在 store=false(默认)时,previous_response_id 返回 404(默认)库存区域:OpenAI 兼容/代理;通知主题:agent_runtime、api_surface、sessions;通知:无

误报 PR #88275 fix(models-config):允许在 models.json 中不带 apiKey 的自托管提供商(#88267)通知兴趣:i0;主题:self_hosted_inference、local_model_providers、config;通知:已发送

PR #88266 refactor:提取模型目录核心包通知兴趣:i1;主题:config、api_surface、local_model_providers;通知:已发送

PR #88247 feat:添加托管模型提供商通知兴趣:i0;主题:local_model_providers、model_serving、docs、api_surface;通知:已发送

如何对分类进行操作、编辑机器可读文件、使用脚本获取误报和漏报的说明,包含在一个代理技能中,该技能被 OpenClaw 的定时任务引用,该任务每两小时运行一次。OpenClaw 代理随后会摄入任何新的问题或 PR,将其添加到带有适当标签的 JSON 文件中,运行脚本并在相同的 Discord 频道中报告结果。这样,我们每隔几个小时就可以观察本地模型的性能,并收到漏报的通知。

结论

我们认为,问题/PR 的分类任务是更广泛任务集的一个具体案例,我们称之为“高吞吐量分类”。本文探讨了使用本地模型在单一领域(即开源贡献)中实时过滤信息的想法。像 gemma-4-26b-a4b 和 qwen3.6-35b-a3b 这样的中等规模本地模型能够在无需微调的情况下,以较高的准确率进行一次分类,这使它们成为快速原型设计的首选,然后再转向更经济高效的传统的分类模型。

然而,同样的方法也可以应用于其他领域:

  • 记者在新闻分类中的应用
  • 在社交媒体和论坛(如 X 或 Reddit)中筛选感兴趣的帖子
  • 客户支持工单的分类
  • 内容审核申诉的分类
  • 在销售过程中筛选潜在的联系人
  • 在研究过程中在 arXiv 上筛选特定主题

这个列表还可以继续扩展,但我们认为这个想法是清晰的。

除了分类,我们还探讨了如何通过在安全环境中运行快速本地模型的代理工具进行分类。这种方法可以很好地命名为“代理分类”:模型并不是一开始就接收全部信息,而是在返回结构化数据之前可以搜索更多上下文。虽然我们不能确切地说这是一种全新的方法,但我们希望这篇博客文章能成为 Pi + 限制性 shell + final_json 配方的一个良好参考。

[^1]: 对于本文所讨论的用例,我们发现将 PR/Issue 拆分为产品表面能够被正确理解和标注的方式是一个具有挑战性的问题。[^2]: 尽管在我们的测试中没有这样做,但模型得出下一步是收集信息并使用外部分类器的结论是完全合理的。代理方法和传统方法并不是相互排斥的。[^3]: 请在此处查看完整的话题列表和其他配置[^4]: 我们使用了 antirez/deepseek-v4-gguf 中的 DeepSeek-V4-Flash-IQ2XXS-w2Q2K-AProjQ8-SExpQ8-OutQ8-chat-v2.gguf。[^5]: 虽然我们意识到使用 LLM 作为判断者会削弱“免费”这一特性,但我们的具体实现是为了研究目的。在实践中,可以在试用期间同时使用一个更大且更昂贵的模型进行校准,之后系统将完全过渡到较小的模型。在最近的运行中,这个审计循环在每 2 小时的检查中使用了大约 40,000 个 GPT-5.5 令牌,主要是缓存的上下文,按 API 定价计算,每次运行成本约为 2-3 美分,每天运行 12 次的话,每月成本约为 9 美元。这是对所有新项目进行的一次批量审计,而不是每个项目都进行一次判断;如果每个项目都进行判断,成本可能会高出数倍。

本文中提到的模型 1

本文中提到的数据集 1

更多来自我们博客的文章

部署

开源协作

bentoml

使用 BentoML 部署 Hugging Face 模型:DeepFloyd IF 的实际应用

2023 年 8 月 9 日

指南

社区

介绍 BERTopic 与 Hugging Face Hub 的集成

12

2023 年 5 月 31 日

社区

编辑

预览

通过拖拽到文本输入框、粘贴或

点击此处

上传图片、音频和视频。

轻点或粘贴此处上传图片

评论

· 注册或登录以发表评论