Forge - ガードレールで8Bモデルのエージェント作業性能を53%から99%へ引き上げるツール
(github.com/antoinezambelli)- Forge は、セルフホスト型LLMのツール呼び出し向けの信頼性レイヤーであり、多段階エージェントワークフローにおける小型ローカルモデルの安定性向上に重点を置いている
- 中核機能は、誤ったツール呼び出しを復旧する rescue parsing、再試行の誘導、必須ステップの強制、VRAMを考慮したトークン予算、階層型コンテキスト圧縮で構成される
- 現在の最上位セルフホスト構成である Ministral-3 8B Instruct Q8 on llama-server は、26件の評価シナリオで86.5%、最難関ティアで76%を記録している
- 利用方法は3つあり、
WorkflowRunnerにエージェントループ全体を任せる方法、Guardrails middleware を既存のオーケストレーションループに組み込む方法、OpenAI互換プロキシサーバーとして透過的に適用する方法がある WorkflowRunnerはシステムプロンプト、ツール実行、コンテキスト圧縮、ガードレールを管理し、SlotWorkerは共有GPU推論スロットに優先度キューと自動プリエンプト機能を追加する- プロキシサーバーは
python -m forge.proxyで実行され、opencode、Continue、aider のようなOpenAI互換クライアントとローカルモデルサーバーの間に入り、ガードレールを適用する - プロキシは、ツールを含むリクエストに合成
respondツールを自動挿入し、モデルが通常のテキストの代わりにrespond(message="...")を呼び出すようにする一方、レスポンスではこれを除去して、クライアントには通常のテキスト応答のように見せる - 対応バックエンドは Ollama、llama-server(llama.cpp)、Llamafile、Anthropic で、llama-server は最高の性能と制御性を、Ollama は設定の容易さを、Llamafile は単一バイナリ実行を、Anthropic はフロンティア基準線とハイブリッドワークフローを担う
- インストールは
pip install forge-guardrailsで可能で、Anthropic クライアントはpip install "forge-guardrails[anthropic]"で追加でき、要件は Python 3.12+ と稼働中のLLMバックエンドである - 評価ハーネスは26件のシナリオでモデルとバックエンドの組み合わせにおける多段階ツール呼び出しの安定性を測定し、OG-18基準ティアと8つの advanced_reasoning ティアに分かれている
- テスト構成には、LLMバックエンドを必要としない865件の決定的ユニットテストと、実バックエンド向けの評価ハーネスが含まれる
- Forge ガードレールフレームワークと ablation study は Forge: A Reliability Layer for Self-Hosted LLM Tool-Calling として公開されており、ライセンスは MIT である
1件のコメント
Hacker Newsのコメント
この分野の作業は好きで役にも立つと思っているが、クラウドベースのLLMは避けていて、主に4B〜30A3Bパラメータのローカルモデルを使っている
なので最新LLMの性能や精度の感覚は弱いものの、ローカルモデルで期待できる水準やボトルネックについてはよく分かっているつもりだ
記事はざっと目を通して抄録を読んだが、簡単な調整で10倍速くなったり遅くなったりし得るという言及はある一方で、指標やデータはほとんど精度にしか焦点が当たっていないように見える。速度を扱うべきだ
特にエージェント型ワークフローとローカルモデルでは、関数/ツール呼び出し精度は個人的にはQwenCoder3あたりから過去6〜12か月の間ずっと大きな問題ではなく、重要なのはコンテキスト管理と時間への影響だ。エージェントがプロンプトを頻繁に変えると、プロンプトキャッシュのような時間最適化が壊れる
ここにガードレールや再試行のような層やラッパーが追加されるようだが、ローカルモデルでは特にエージェント用途だと遅延のせいで使い物にならないレベルになる可能性がある
すでに真正面から扱っていたなら申し訳ないが、時間への影響の話があまりに少ないので、実際の改善幅を隠しているか誇張しているように感じる。速度面の経験を聞きたい。ほかの人がこれを指摘していないのも少し気になるが、自分のやり方が間違っているのか、それともみんな実際にはローカルモデルを使っていないのかと思ってしまう
ちゃんとしたハーネスさえあれば、小さなローカルモデルでも驚くほどよくやれるとずっと言ってきた
何でも試せるシステムなら、その途中で間違った結果を出せないようにさえしておけば、最終的には正解にたどり着ける
作業が十分に複雑なら最新モデルでもこの問題はあり、小さなモデルではさらに大きく増幅される
推論もかなり良く、多くの場合それで十分だ。たまに軌道に戻してやるだけで、自力で解いてくれる
自分が時間を取って作りたかったものを、はるかにうまく作ってくれていてうれしい。ひとつ質問があるのだが、たとえば再試行ループでは並列化の余地があるのだろうか
ローカルモデルは一般にコンシューマ向けハードウェアでも限られた数、ざっくり二桁程度の同時リクエストをかなりうまく処理でき、そうすると実効トークン/秒が10倍以上になることもある
こういうものを活用するワークフローをしばらく考えていて、「このエラーを直せ」は完璧ではなくても適用先になりそうに見える。どう考えているのか気になる
この領域でいくつかアイデアがあって、自分のハーネスに入れているところだ。自分のハーネスはかなり特化しているので、一般化できるかどうかはよく分からない
問題を計画された実行に分解し、実行エージェントがどのツールを呼ぶかや、成功した実行の基準のような明示的な目標を含む初期計画を与える。ハーネスはその計画を順番に実行する
ツール呼び出しが含まれる各ステップでは、ツール呼び出しを構成要素に分解する。ハーネスが現在のツール引数について有効なパラメータ値をエージェントに尋ね、ツール定義には各引数ごとのバリデータがある。検証に失敗すると、ハーネスが会話を巻き戻し、失敗理由を次の試行に注入する
引数に対して有効な応答が出たら次の引数に進み、すべての引数が埋まったらツールを呼び出す。エージェントの初期期待値と実際の値、発生したエラーを一緒に渡し、結果に満足しているかを尋ねる
満足していなければ、エージェントが理由を示し、ハーネスは会話を巻き戻して再試行の理由を入れたうえで、ツール呼び出しの過程を最初からやり直す
エージェントは初期計画の欠陥を見つけたら再計画を要求でき、ハーネス側も連続失敗が多すぎると再計画を試みる
この方法はツール呼び出し失敗を減らすのにかなり効果的だ。利点のひとつは、下位エージェントがミスのない完璧な会話履歴を受け取れることだ。ただ、実際のタスク完了率がより良いかどうかはまだベンチマークしていない
会話の巻き戻しに関しては、メインエージェント、つまりユーザーと会話するエージェントに似たツール呼び出し折りたたみを実装した。タスクが終わったらツール呼び出し履歴を折りたたんでコンテキストをきれいに保ったが、サイズというより衛生のために近かった
ハーネスがモデルに細かく問い詰める部分は少し違っていて、そのアプローチは試していない。Forgeは専用のエラーモードを避けるためにモデルの自己修正に依存しているが、スキーマのようなものを基に質問プロセスを抽象化して自動化できるなら、可能そうではある
全体としてクリーンな会話履歴という点では良いが、引数の多いツールでは「とりあえず失敗させて一度促す」より往復がはるかに多くなる可能性がありそうだ。それでも、より難しいシナリオやタスクには面白いアイデアだ
小さなモデルで50kトークン/秒以上が出せるなら、かなり大きいはずだ
ただ今は会社の仕事と別プロジェクトに縛られていて、実現可能かを見るためにプロンプトを数十個試しただけの状態だ
素晴らしい。今はコストのためにローカル推論は使えないが、OpenRouterで小さなモデルを使うときにツール呼び出しが心配だった
pytest優先の引数テストフレームワークDokimasia(do-kee-ma-see-ah)を作っているのだが、意見を聞きたい: https://github.com/deevus/dokimasia
引数テストはForgeに必要なものではないかもしれないが、AIツールを深く作っているので考えがあるのではと思った
Forgeより一段上にある感じで、実際のワークフローや、その中で現れる統合ポイント、たとえばどのツールがMCPアクセスを提供するかをテストする側に近い
両者を一緒に重ねて使うのも大きな問題はなさそうだ
気になるのは、こうしたモデルの非決定性をどう扱うのかという点だ。あるときはツール呼び出しを正しく行い、あるときは壊れたJSONを吐く。テストスイートは複数回試行するのだろうか?
ツール呼び出しの曖昧さは最前線モデル規模でも経験する。Claude Code、Codex、Gemini CLIを毎日並列で開発に使っているが、最も一般的な失敗モードはgrep/findが終了コード1、つまり一致なしで終わるときだ
モデルはこれを「検索は実行されて何も見つからなかった」ではなく「ツールが失敗した」と読んでしまい、諦めたり検索範囲を広げたりする代わりに、文法だけ少し変えて再試行する
再試行-ナッジ層は、自分が1時間のうちに何度も手動でやっていることとほぼ1対1で対応している。「いや、ツール失敗じゃなくて、そのファイルにそのパターンがないだけだ。Xを試してみて」というようなことだ
これをフレームワークレベルでエンコードする方向は正しそうに見える
こうしたガードレールが、長いタスクにおいて小さな最前線モデルとのギャップを縮めるかどうかも見たのか気になる。直感では、Sonnetでの87→99の差は50ステップを超えるとそのまま維持はされない気がする。その先では再試行の意味論よりコンテキストドリフトのほうが支配的だからだ
必要な手掛かりとして、forgeは技術的にはモデル品質ではなくツール呼び出し実行に関心がある。実際の答えはこうだ
14B級の小さなモデルでは、制約要因は有効注意だった。訓練コンテキストウィンドウの大きさの中に十分収まっていても、ある地点を超えると性能低下が見え始めた。正確な数値はないが、Opusのようなモデルはその地点からはるかに長く持ちこたえられる
いつかforgeで直接使うかもしれない、ツール呼び出しメッセージ履歴の折りたたみ機能も作った。本質的にはメッセージ履歴を賢く整理して、モデルが追跡を失いにくくする方法だ
それでもエージェント型コーディングハーネスのコーディング評価スイートにはリファクタリングタスクや機能追加タスクがあり、どれも実際のサンドボックスリポジトリで実行される。小さなモデルでも50〜60回のツール呼び出しまで押し進めて、そうしたタスクをやり切れる。とはいえ、同じセッションでそういう仕事を2つ以上任せることはしないと思う
少し話は変わるが、Texas Instrumentsにいるなら、TI Explorer Lispマシンの知的財産権の状態がどうなったのか調べられるか気になる
Generaの知的財産権の所有者は知っているが、TIのLisp OSについては突き止められていない
「エージェント安全」スタックをより広く考える人にとっては、この方向性はKontextのkontext-cli(github.com/kontext-dev/kontext-cli)やOneCLI(github.com/onecli/onecli)のようなものと相補的に感じられる
「同じMistral-Nemo 12B重みがllama-serverのネイティブ関数呼び出しでは7%精度、Llamafileのプロンプトモードでは83%」という部分がある
Llamafileは単にモデルとllama.cppを単一バイナリに束ねたものだと思っていたが、この差はLlamafileがデフォルトのシステムプロンプトを注入することと、生のllama-serverエンドポイントをハーネスなしで呼ぶことの違いなのか?
これはリンゴとアップルパイを比較しているように見えて、中間の材料が抜けている
ただ、それだけではLamaserverプロンプトとllamafileの間の約+4%p差や、llamaserverネイティブとllamafileのほぼ中間に位置するOllamaの約+30%p差は説明できない
サービングバックエンドはほぼすべてのモデル系統に影響していて、この点は実際ほとんど話題になっているのを見たことがなかった
これは本当に素晴らしい方向性だ。1ビットbonsaiモデルでも信じられないほど良い結果が出ていて、lmstudioとも相性がいい
これで余っているマシンに7900XTXを挿して地下室に置き、とんでもない目標を投げて放っておく、というのが完全に現実的になった