我们使用本地模型免费对OpenClaw仓库进行问题分类!*
摘要
这篇博文介绍了在代理框架中使用Gemma、Qwen等本地开源权重模型,自动对OpenClaw仓库中的问题和拉取请求进行分类,从而实现实时通知,无需依赖昂贵的封闭API模型。
查看缓存全文
缓存时间: 2026/06/23 07:39
reposhell /repo/openclaw> curl localhost reposhell policy denied command: unsupported command “curl” exit_code=2 reposhell /repo/openclaw> ``
这里有一个具体例子说明了这一点。在之前保存的会话示例中(https://huggingface.co/datasets/dutifuldev/openclaw-classification-dataset/blob/main/session-examples/README.md),qwen3.6-35b-a3b 正在对 openclaw/openclaw#84621(https://github.com/openclaw/openclaw/pull/84621)进行分类,其标题为“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(https://github.com/osolmaz/localpager/tree/main/localpager-agent),以其所属的主项目 localpager 命名。每个 PR 和 issue 都会生成一个提示,然后与其它参数一起传递给 CLI,如下所示:
localpager-agent \
--model "" \
--base-url "" \
--session-dir "" \
--final-schema "" \
--tools bash,final_json \
--reposhell-socket "" \
--reposhell-default-repo "" \
--reposhell-visible-repos "[,...]" \
-p "$(cat )"
https://huggingface.co/blog/local-models-pr-triage#processing-incoming-prs-and-issues 处理传入的 PR 和 Issue
那么,是什么在编排传入的 PR/issue 与 Discord 最终通知之间的所有环节呢?
Localpager Discord 通知
这就是最终的过滤后 Discord 通知的样子:一个关于所需垂直领域的 PR 被路由到我这里。
背后的编排非常简单;只有分类步骤涉及 LLM:
- 我们使用 openclaw/gitcrawl(http://github.com/openclaw/gitcrawl)作为仓库的本地镜像。每当有新的 PR 或 issue 时,每个条目都会被规范化为相同的格式,并写入 localpager 自己的 SQLite 数据库中。如果该条目是新的,localpager 会为其创建一个分类任务。
- 然后,一个工作线程从该队列中领取任务。它构建一个包含 issue 或 PR 标题、正文、标签、作者、状态,以及可选的评论、变更文件和选定 diff 片段的 GitHub 上下文对象。这意味着大多数时候,本地模型不需要自行浏览 GitHub 或打开 URL。它会获得所有相关的上下文信息。
- 上下文对象被渲染成提示,并按照上一节所述传递给
localpager-agent。代理可以思考并使用 reposhell,但最终必须按照定义的 schema 输出分类结果。 - 输出结果被存回 localpager 的 SQLite 数据库,并根据用户配置的通知策略(即,通知我这些主题,但不通知那些主题)转发到 Discord。
下图显示了 localpager 的总体架构:
Localpager 架构
该架构是半代理式的。标注以代理方式完成,而发送通知则通过确定性规则处理。这样做的目的是通过移除任务中最直接的推理环节,使通知流水线更快。本地推理是免费的,但每个任务都有资源争用成本:GPU 带宽应保留给绝对需要推理的任务。这也减少了通知出错的几率。
https://huggingface.co/blog/local-models-pr-triage#can-local-models-triage-prs 本地模型能否对 PR 进行分类?
坦率地说:这个系统的早期本地版本噪声很大。第一个测试的模型——gemma-4-e4b-it——虽然有助于让端到端本地流水线跑起来,但它也倾向于给 PR 或 issue 添加太多不相关的标签。误报标签使 Discord 信息流变得杂乱,无法将我的注意力集中在正确的问题上。
这促使我们测试更大的本地模型,包括 gemma-4-26b-a4b 和 qwen3.6-35b-a3b,并使用了下面 330 行的评估集。在早期的提示工程工作中,我们还使用 DeepSeek-V4-Flash(通过 antirez DS4 实现1)来创建早期的数据集标签。该设置使用运行在 CUDA 上的 DS4 服务器。我们最终放弃了将 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 之前输出 token 用尽)之后的结果。对于 Gemma 和 Qwen,重复运行指标报告的是三次运行的平均值 ± 样本标准差。DeepSeek-V4-Flash 作为参考运行了一次。
| 指标 | gemma-4-26b-a4b | qwen3.6-35b-a3b | 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 | 3.51 ± 0.79 | 144.14 |
| 输出 token/秒/工作线程 | 25 | 50 | 13 |
| 聚合输出 token/秒 | 402.6 | 145.3 | 13 |
| 并发数 | 16 | 4 | 1 |
| 总参数量 | 26B | 35B | 284B |
| 激活参数量 | 4B | 3B | 13B |
这里的吞吐量和处理时间数据并非这些模型在此硬件上的最终最大性能表现,而是我们当时在可用优化条件下所使用的设置。例如,在另一次探测中,gemma-4-26b-a4b 也支持并发 32,并达到了超过 700 个聚合输出 token/秒。
330 行标签集上的基准对比
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 分钟内完成。
https://huggingface.co/blog/local-models-pr-triage#tracking-and-validating-real-time-performance-using-openclaw 使用 OpenClaw 跟踪和验证实时性能
我们之前提到过,与其为每个新 issue 或 PR 都运行一个本地模型任务,我们可以每隔 n 小时(例如每 2 小时)使用运行在 OpenClaw 中的 SOTA 云模型(如 GPT-5.5)批量运行一次任务,以达到相同的最终目的。2 在这种情况下,我们需要一个 ChatGPT Pro 计划。由于该模型是 SOTA 级别的,尽管是将 2 小时内的 issues/PRs 批量处理在一起,我们仍然可以预期其表现相当不错。
因为我们想了解本地分类器与 GPT-5.5 相比的表现如何,所以我们同时运行两者,并每 2 小时让 GPT-5.5 作为判断误报和漏报的裁判。为了安全起见,我们在沙箱中运行 OpenClaw 任务,只允许访问我们报告结果的 public 仓库(https://github.com/osolmaz/onurclaw)。在我们的案例中,我们让 OpenClaw 任务更新一个机器可读的文件,然后一个简单的脚本读取 Codex 分配的标签,并计算误报/漏报状态。
示例输出:
漏报
- Issue #88499 openai-responses provider: 404 on previous_response_id when store=false (default)
- 库存区域: OpenAI-compatible/proxy; 通知主题: agent_runtime, api_surface, sessions; 通知: 无
误报
- PR #88275 fix(models-config): allow self-hosted providers without apiKey in models.json (#88267)
- 通知兴趣: i0; 主题: self_hosted_inference, local_model_providers, config; 通知: 已发送
- PR #88266 refactor: extract model catalog core package
- 通知兴趣: i1; 主题: config, api_surface, local_model_providers; 通知: 已发送
- PR #88247 feat: add hosted model providers
- 通知兴趣: i0; 主题: local_model_providers, model_serving, docs, api_surface; 通知: 已发送
关于如何分类、编辑机器可读文件以及使用脚本获取误报和漏报的说明,都包含在一个 agent skill(https://github.com/osolmaz/onurclaw/blob/main/.agents/skills/openclaw-onur-inventory/SKILL.md)中,该 skill 被一个每 2 小时运行一次的 OpenClaw cron job(https://docs.openclaw.ai/automation/cron-jobs)引用。然后,OpenClaw 代理会摄入任何新的 issue 或 PR,将其添加到 JSON 文件中并分配适当的标签,运行脚本,并在同一个 Discord 频道中报告结果。这样,我们可以每隔几小时观察本地模型的性能,并得到漏分的通知。
https://huggingface.co/blog/local-models-pr-triage#conclusion 结论
我们认为,issue/PR 分类任务是一类更广泛任务中的特定案例,我们称之为“高通量分类”。本文探讨了使用本地模型仅在一个领域(即开源贡献)中实时过滤信息的想法。像 gemma-4-26b-a4b 和 qwen3.6-35b-a3b 这样的中型本地模型,能够在无需微调的情况下一次性准确分类,这使它们在快速原型设计中成为不错的第一选择,之后再转向更具成本效益的传统分类器模型。
然而,同样的方法也可以应用于其他领域:
- 新闻业的新闻分类
- 在社交媒体和论坛(如 X 或 Reddit)中筛选感兴趣的内容
- 分类客户支持工单
- 分类内容审核申诉
- 在销售过程中筛选潜在客户
- 在研究时筛选 arXiv 上的特定主题
这个列表还可以扩展,但我们认为这个想法已经很清晰了。除了分类之外,我们还探索了如何使用运行快速本地模型的代理框架以安全的方式进行分类。称这种方法为代理式分类很合适:模型并非一开始就获得所有信息,而是可以在返回结构化数据之前搜索更多上下文。
虽然我们不能完全说这是一种新颖的方法,但我们希望这篇博客文章能为特定的 Pi (https://pi.dev/) + 受限 shell + final_json 配方提供一个良好的参考。
对于本文中的用例,我们发现,以一种能够正确理解并标注产品表面的方式来分解 PR/Issue 是一个难题。
尽管在我们的测试中没有出现——但模型完全可以合理地得出结论,需要下一步收集信息或使用外部分类器。代理式方法和传统方法并非互斥。
完整主题列表和其他配置请参见这里(https://github.com/osolmaz/localpager/blob/main/examples/profiles/openclaw-routing-topics.json)。
我们使用了来自 antirez/deepseek-v4-gguf(https://huggingface.co/antirez/deepseek-v4-gguf)的 DeepSeek-V4-Flash-IQ2XXS-w2Q2K-AProjQ8-SExpQ8-OutQ8-chat-v2.gguf 模型。
虽然我们意识到使用 LLM 作为裁判会削弱“免费”的优势,但我们的具体实现是为了研究目的才这么做的。在实践中,可以在试用期内将更大、更昂贵的模型配合使用进行校准,之后系统将完全过渡到较小的模型。在最近的运行中,这个审计循环每两小时大约使用 40k 个 GPT-5.5 token(主要是缓存的上下文),按照 API 定价,每次运行成本约为 2-3 美分,如果每天运行 12 次,大约每月 9 美元。这是对所有新条目的一次性批量审计,而非每个条目单独调用裁判;如果按条目进行,成本可能会高出数倍。
相似文章
我们将OpenClaw托管完全免费化
OpenClaw现在提供完全免费的托管服务,支持一键部署和按量付费(PAYG)Token定价,让开发者无需管理设置或运维,更轻松地使用代理构建应用。
寻找早期用户试用我们的 OpenClaw 模型方案,并告诉我们哪里有问题(15-30 分钟)
OpenClaw 正在寻找早期用户测试其开源模型推理方案,该方案按并发槽位销售,具有高吞吐量且无共享池,以换取免费使用和反馈。
解放你的 OpenClaw
Hugging Face 提供了一份迁移指南,帮助你将 OpenClaw 智能体从受限的 Anthropic Claude 模型迁移到开源替代方案,可通过 Hugging Face Inference Providers 或借助 Llama.cpp 等工具在本地硬件上运行。
@atomicbot_ai: Hermes Agent vs OpenClaw 使用 Qwen 35B 本地模型 我们要求代理抓取两个工具的 GitHub 星标历史,找出…
Hermes Agent 与 OpenClaw 使用 Qwen 35B 本地模型的对比,代理抓取 GitHub 星标历史,识别增长高峰,并构建实时仪表板。OpenClaw 耗时 12 分 01 秒(203k 令牌),Hermes 耗时 33 分 01 秒(257k 令牌),采用不同方法。
@steipete:感谢腾讯团队与我们合作,为提升 OpenClaw 的 harness 性能提供评测!我们……
腾讯提供评测数据,帮助提升 OpenClaw 的 harness 性能,并协助将修复方案回馈至开源仓库。