Forge – ein Tool, das 8B-Modelle bei Agentenaufgaben mit Guardrails von 53 % auf 99 % bringt
(github.com/antoinezambelli)- Forge ist eine Reliability-Schicht für Tool-Calling bei selbst gehosteten LLMs und fokussiert sich darauf, die Stabilität kleiner lokaler Modelle in mehrstufigen Agent-Workflows zu erhöhen
- Die Kernfunktionen bestehen aus Rescue Parsing zur Wiederherstellung fehlerhafter Tool-Calls, erzwungenen Wiederholungsversuchen, dem Erzwingen erforderlicher Schritte, VRAM-bewusster Token-Budgetierung und hierarchischer Kontextkomprimierung
- Die derzeit beste selbst gehostete Konfiguration, Ministral-3 8B Instruct Q8 auf llama-server, erreicht in 26 Evaluierungsszenarien 86,5 % und in der schwierigsten Tier 76 %
- Es gibt drei Nutzungsarten: den gesamten Agent-Loop mit
WorkflowRunnerausführen, die Guardrails-Middleware in einen bestehenden Orchestrierungs-Loop einfügen oder sie transparent über einen OpenAI-kompatiblen Proxy-Server anwenden WorkflowRunnerverwaltet System-Prompts, Tool-Ausführung, Kontextkomprimierung und Guardrails, währendSlotWorkereinem gemeinsam genutzten GPU-Inferenz-Slot Prioritätswarteschlangen und automatische Präemption hinzufügt- Der Proxy-Server wird mit
python -m forge.proxygestartet und sitzt zwischen OpenAI-kompatiblen Clients wie opencode, Continue oder aider und einem lokalen Modellserver, um Guardrails anzuwenden - Der Proxy injiziert bei Anfragen mit Tools automatisch ein synthetisches
respond-Tool, damit das Modell statt normalem Textrespond(message="...")aufruft; in den Antworten wird dies wieder entfernt, sodass es für den Client wie eine normale Textantwort aussieht - Unterstützte Backends sind Ollama, llama-server (llama.cpp), Llamafile und Anthropic; llama-server bietet die beste Leistung und Kontrolle, Ollama die einfachste Einrichtung, Llamafile die Ausführung als einzelne Binärdatei und Anthropic dient als Frontier-Baseline und für hybride Workflows
- Die Installation erfolgt mit
pip install forge-guardrails; der Anthropic-Client kann mitpip install "forge-guardrails[anthropic]"ergänzt werden; Voraussetzung sind Python 3.12+ und ein laufendes LLM-Backend - Das Evaluierungs-Harness misst in 26 Szenarien die Zuverlässigkeit mehrstufiger Tool-Calls für Modell- und Backend-Kombinationen und ist in eine OG-18-basierte Tier sowie acht
advanced_reasoning-Tiers unterteilt - Die Testkonfiguration umfasst 865 deterministische Unit-Tests ohne erforderliches LLM-Backend sowie ein Evaluierungs-Harness gegen reale Backends
- Das Forge-Guardrails-Framework und die Ablation Study wurden unter dem Titel Forge: A Reliability Layer for Self-Hosted LLM Tool-Calling veröffentlicht; die Lizenz ist MIT
1 Kommentare
Hacker-News-Kommentare
Ich mag Aufgaben in diesem Bereich und finde sie hilfreich, vermeide aber Cloud-basierte LLMs und nutze meist lokale Modelle mit 4B bis 30A3B Parametern
Deshalb fehlt mir zwar etwas das Gefühl für die aktuelle Leistung oder Genauigkeit moderner LLMs, aber ich denke, ich kenne gut das Niveau und die Engpässe, die man von lokalen Modellen erwarten kann
Ich habe den Beitrag nur grob überflogen und das Abstract gelesen; dort wird erwähnt, dass einfache Anpassungen etwas 10-mal schneller oder langsamer machen können, aber die Metriken und Daten scheinen sich fast nur auf Genauigkeit zu konzentrieren. Geschwindigkeit sollte behandelt werden
Besonders bei agentischen Workflows und lokalen Modellen war die Genauigkeit von Funktions-/Tool-Calls für mich persönlich seit etwa QwenCoder3 in den letzten 6–12 Monaten kein großes Problem mehr; entscheidend sind Kontextverwaltung und Zeiteinfluss. Wenn ein Agent den Prompt häufig verändert, gehen Zeitoptimierungen wie Prompt-Caching kaputt
Hier scheinen zusätzliche Schichten und Wrapper wie Guardrails und Retries dazuzukommen, was bei lokalen Modellen, besonders für Agenten-Einsätze, wegen der Latenz unbrauchbar werden könnte
Falls das schon direkt behandelt wurde, entschuldige bitte, aber es wird so wenig über den Zeiteinfluss gesprochen, dass es so wirkt, als würde die tatsächliche Verbesserung verborgen oder aufgebläht. Ich würde gern etwas über die Geschwindigkeitserfahrung hören. Dass andere das nicht angesprochen haben, beunruhigt mich auch etwas; vielleicht mache ich etwas falsch oder sonst nutzt niemand lokale Modelle wirklich
Ich sage schon lange, dass selbst kleine lokale Modelle mit einem richtigen Harness erstaunlich gut sein können
Wenn man ein System hat, das alles ausprobieren kann, dann kann es am Ende richtig liegen, solange man nur verhindert, dass es zwischendurch falsche Ergebnisse ausgibt
Wenn die Aufgabe komplex genug ist, haben selbst moderne Modelle dieses Problem, und bei kleinen Modellen verstärkt es sich noch stärker
Auch ihr Reasoning ist ziemlich gut und in vielen Fällen ausreichend. Manchmal muss man sie nur gelegentlich wieder auf Kurs bringen, dann lösen sie es selbstständig
Es freut mich, dass jemand das, was ich mir einmal bauen wollte, viel besser umgesetzt hat. Eine Frage ist, ob es zum Beispiel in einer Retry-Schleife Spielraum für Parallelisierung gibt
Lokale Modelle können selbst auf Consumer-Hardware in der Regel eine begrenzte Zahl, grob gesagt im zweistelligen Bereich, an gleichzeitigen Requests ziemlich gut verarbeiten, wodurch effektive Tokens pro Sekunde um mehr als das 10-Fache steigen können
Ich denke schon länger über Workflows nach, die so etwas ausnutzen, und „behebe diesen Fehler“ scheint, auch wenn nicht perfekt, ein möglicher Anwendungsfall zu sein. Würde mich interessieren, wie du das siehst
Ich habe ein paar Ideen in diesem Bereich und baue sie gerade in mein Harness ein. Mein Harness ist ziemlich spezialisiert, daher weiß ich nicht, wie gut sich das verallgemeinern lässt
Ich zerlege das Problem in eine geplante Ausführung und liefere einen anfänglichen Plan, der explizite Ziele enthält, etwa welche Tools der Ausführungsagent aufrufen soll und woran eine erfolgreiche Ausführung gemessen wird. Das Harness führt diesen Plan der Reihe nach aus
Bei jedem Schritt mit Tool-Call zerlege ich den Tool-Call in Komponenten. Das Harness fragt den Agenten nach einem gültigen Parameterwert für das aktuelle Tool-Argument, und in der Tool-Definition gibt es für jedes Argument einen Validator. Wenn die Validierung fehlschlägt, spult das Harness die Konversation zurück und speist den Grund für das Scheitern in den nächsten Versuch ein
Sobald es eine gültige Antwort für ein Argument gibt, geht es zum nächsten weiter, und wenn alle Argumente ausgefüllt sind, wird das Tool aufgerufen. Dann werden die ursprünglichen Erwartungen des Agenten, die tatsächlichen Werte und eventuell aufgetretene Fehler gemeinsam übergeben, und der Agent wird gefragt, ob er mit dem Ergebnis zufrieden ist
Falls nicht, nennt der Agent den Grund, und das Harness spult die Konversation zurück, fügt den Grund für den Retry ein und startet den Tool-Call-Prozess von vorn
Wenn der Agent Mängel im ursprünglichen Plan entdeckt, kann er Re-Planning anfordern, und auch das Harness versucht bei zu vielen aufeinanderfolgenden Fehlschlägen ein Re-Planning
Dieser Ansatz ist ziemlich wirksam dabei, Fehlschläge bei Tool-Calls zu reduzieren. Ein Vorteil ist, dass Sub-Agenten einen perfekten, fehlerfreien Gesprächsverlauf bekommen. Ich habe allerdings noch nicht gebenchmarkt, ob die tatsächliche Abschlussrate von Aufgaben dadurch besser ist
Im Zusammenhang mit dem Zurückspulen von Gesprächen habe ich beim Hauptagenten, also dem Agenten, der mit dem Nutzer spricht, ein ähnliches Zusammenfalten von Tool-Calls implementiert. Wenn eine Aufgabe abgeschlossen war, wurden die Tool-Call-Protokolle zusammengefaltet, um den Kontext sauber zu halten; es ging eher um Hygiene als um Größe
Der Teil, in dem dein Harness das Modell gezielt ausfragt, ist etwas anders, und diesen Ansatz habe ich nicht ausprobiert. Forge verlässt sich auf die Selbstkorrektur des Modells, um einen speziellen Fehlermodus zu vermeiden, aber wenn sich der Frageprozess auf Basis von Dingen wie einem Schema abstrahieren und automatisieren ließe, scheint das möglich
Insgesamt gefällt mir der Aspekt eines sauberen Gesprächsverlaufs, aber bei Tools mit vielen Argumenten könnte es deutlich mehr Hin-und-her geben als bei „lass es erst einmal scheitern und gib dann einen kleinen Schubs“. Für schwierigere Szenarien oder Aufgaben ist das aber dennoch eine interessante Idee
Wenn mit kleinen Modellen mehr als 50k Tokens/s möglich sind, wäre das ziemlich groß
Im Moment bin ich allerdings mit Arbeit und anderen Projekten ausgelastet, deshalb habe ich bisher nur ein paar Dutzend Prompts getestet, um zu sehen, ob es grundsätzlich funktioniert
Großartig. Wegen der Kosten kann ich lokale Inferenz derzeit nicht nutzen, aber bei kleinen Modellen über OpenRouter hatte ich Sorgen wegen Tool-Calling
Ich baue gerade Dokimasia (do-kee-ma-see-ah), ein Argument-Test-Framework mit pytest-first-Ansatz, und würde gern Feedback hören: https://github.com/deevus/dokimasia
Vielleicht sind Argument-Tests für Forge nicht nötig, aber da du tief mit AI-Tools arbeitest, dachte ich, du hättest vielleicht eine Meinung dazu
Es scheint eine Ebene über Forge zu liegen und eher darauf ausgerichtet zu sein, reale Workflows und die darin sichtbar werdenden Integrationspunkte zu testen, zum Beispiel welches Tool einen MCP-Zugriff bereitstellt
Beide zusammen übereinander zu verwenden, dürfte kein großes Problem sein
Was mich interessiert, ist, wie du mit der Nichtdeterministik dieser Modelle umgehst. Manchmal machen sie den Tool-Call korrekt, manchmal spucken sie fehlerhaftes JSON aus. Lässt die Testsuite mehrere Versuche zu?
Die Mehrdeutigkeit von Tool-Calls erlebe ich selbst bei Frontier-Modellen. Ich nutze Claude Code, Codex und Gemini CLI täglich parallel für Entwicklung, und der häufigste Fehlermodus ist, dass grep/find mit Exit-Code 1 endet, also ohne Treffer
Das Modell liest das dann nicht als „Die Suche wurde ausgeführt und hat nichts gefunden“, sondern als „Das Tool ist fehlgeschlagen“, und gibt entweder auf oder versucht statt einer Erweiterung des Suchraums nur mit leicht veränderter Syntax erneut
Eine Retry-und-Nudge-Schicht entspricht fast 1:1 dem, was ich selbst mehrmals pro Stunde manuell mache. So etwas wie: „Nein, das Tool ist nicht fehlgeschlagen, dieses Muster existiert nur in der Datei nicht. Versuch X“
Es scheint der richtige Weg zu sein, das auf Framework-Ebene zu kodieren
Mich würde interessieren, ob ihr auch geprüft habt, ob solche Guardrails bei langen Aufgaben den Abstand zu kleinen Frontier-Modellen verkleinern. Mein Bauchgefühl sagt, dass der Unterschied bei Sonnet von 87→99 ab ungefähr 50 Schritten nicht einfach erhalten bleibt. Danach dominiert eher Kontext-Drift als Retry-Semantik
Als hilfreicher Hinweis: forge interessiert sich technisch gesehen nicht für Modellqualität, sondern für die Ausführung von Tool-Calls. Die eigentliche Antwort lautet so
Bei kleinen Modellen der 14B-Klasse war der begrenzende Faktor die effektive Aufmerksamkeit. Selbst wenn genug innerhalb des trainierten Kontextfensters lag, war ab einem gewissen Punkt ein Leistungsabfall zu sehen. Ich habe keine exakten Zahlen, aber Modelle wie Opus können an diesem Punkt deutlich länger durchhalten
Ich habe auch eine Funktion zum Zusammenfalten des Nachrichtenverlaufs von Tool-Calls gebaut, die ich vielleicht irgendwann direkt in forge einsetzen könnte. Im Kern organisiert sie den Nachrichtenverlauf intelligent um, damit das Modell weniger leicht den Faden verliert
Trotzdem enthält die Coding-Evaluierungssuite des agentischen Coding-Harness Refactoring-Aufgaben und Aufgaben zum Hinzufügen von Features, alle in realen Sandbox-Repositories. Selbst kleine Modelle können solche Aufgaben schaffen und dabei auf 50–60 Tool-Calls hochgehen. Ich würde ihnen allerdings wahrscheinlich nicht mehr als eine solche Aufgabe in derselben Sitzung geben
Etwas anderes Thema, aber falls du bei Texas Instruments bist: Könntest du vielleicht herausfinden, wie der Status der geistigen Eigentumsrechte an der TI Explorer Lisp Machine ist?
Wem das geistige Eigentum an Genera gehört, weiß ich, aber zur Lisp-OS von TI konnte ich nichts herausfinden
Für Leute, die den „Agent Safety“-Stack breiter betrachten, fühlt sich diese Richtung komplementär zu Dingen wie Kontexts kontext-cli (github.com/kontext-dev/kontext-cli) oder OneCLI (github.com/onecli/onecli) an
Da steht: „Dieselben Mistral-Nemo-12B-Gewichte erreichen beim nativen Function-Calling von llama-server 7 % Genauigkeit, im Prompt-Modus von Llamafile dagegen 83 %“
Ich dachte, Llamafile sei einfach nur das Modell plus llama.cpp in einem einzelnen Binary gebündelt; ist dieser Unterschied also der zwischen der Injektion eines Standard-System-Prompts durch Llamafile und dem direkten Aufruf des rohen llama-server-Endpunkts ohne Harness?
Das wirkt auf mich wie ein Vergleich von Äpfeln mit Apfelkuchen, bei dem Zwischenschritte fehlen
Aber das erklärt weder den Vorsprung von etwa +4 Prozentpunkten von llamaserver prompt gegenüber llamafile noch den Vorsprung von Ollama mit etwa +30 Prozentpunkten, das fast genau zwischen llamaserver nativ und llamafile liegt
Das Serving-Backend hatte Auswirkungen auf fast alle Modellfamilien, und darüber wird meiner Erfahrung nach kaum gesprochen
Das ist wirklich eine hervorragende Richtung. Selbst mit 1-Bit-bonsai-Modellen bekommt man absurd gute Ergebnisse, und es funktioniert auch gut mit lmstudio
Damit ist es völlig realistisch geworden, einfach eine 7900XTX in ein übrig gebliebenes System im Keller zu stecken, ihr ein absurdes Ziel zu geben und es dann zu vergessen