amber-bench: benchmark harnessu, nie modelu
Ranking modeli nie powie Ci, czy Twoja pętla agenta jest zepsuta. Zbudowałem benchmark, który ocenia harness i model jako parę. Pierwsze, co znalazł, to błędy w moim własnym harnessie.
Każdy wynik agenta to para: model i harness, który nim steruje. Schematy narzędzi, prompt systemowy, sterowanie pętlą i sposób, w jaki wynik narzędzia jest parsowany i oddawany modelowi, zmieniają to, co model robi. Zmień harness, a ten sam model dostanie inny wynik. Rankingi oceniają sam model, więc nie powiedzą Ci, która połowa pary zawodzi.
amber to moje środowisko uruchomieniowe agentów w C++17. amber-bench to benchmark, który zbudowałem obok, żeby mierzyć sam harness: każda zmiana architektury ma być widoczna jako liczba, a nie jako wrażenie po udanym popołudniu.
Co uruchamia
49 scenariuszy w 10 zestawach:
| Zestaw | Scenariusze | Przykłady |
|---|---|---|
| Kodowanie | 5 | FizzBuzz, sortowanie, bufor cykliczny, LCS, BFS na grafie |
| Trzymanie się promptu | 5 | format koperty, odmowa zakazanego narzędzia, weryfikacja przed stwierdzeniem |
| Refaktoryzacja | 4 | wydzielenie metody, polimorfizm zamiast switch, adapter, strategia |
| Praca w terminalu | 6 | liczenie plików, grep wartości, kompilacja i uruchomienie C++, potoki |
| Wybór narzędzi | 6 | wyszukiwanie zamiast grep, odczyt zamiast cat, zapis zamiast przepisania |
| Błędy agenta | 6 | zbędne wywołania, naprawa po pomyłce, zerwany strumień, puste odpowiedzi |
| Loop-live | 6 | projekt planu, trzymanie się planu, dyscyplina powtórzeń, zakończenie |
| Code review | 8 | architektura, struktury danych, wzorce, jakość kodu |
| Repozytorium | 2 | nawigacja i wyszukiwanie w repozytorium |
| Delegowanie | 1 | delegowanie do subagenta |
Jak liczy wynik
Każdy scenariusz dostaje 0–100 punktów z czterech składowych:
- Poprawność: czy agent doszedł do właściwego wyniku? Sprawdzane z oczekiwaną odpowiedzią i ukrytym testem.
- Wydajność: kroki, zmarnowane i zbędne wywołania, w porównaniu z tym, czego zadanie wymaga.
- Odporność: ponowienia, naprawy i twarde zatrzymania.
- Trzymanie się promptu: zaliczone sprawdzenia promptu minus każde użycie zakazanego narzędzia.
Scenariusze mają wagę trudności od 1 do 5. Wynik modelu to ważona suma, przeskalowana do 1000.
Pierwsze, co znalazł, to moje błędy
Zapisywałem wyniki bazowe harnessu na tym samym modelu, Qwopus3.6-27B, w miarę jak zmieniał się silnik:
| Wersja | Scenariusze | Wynik | Zaliczone |
|---|---|---|---|
| v2, pierwsza kalibracja na żywo | 43 | 769,1 | 39/43 |
| v3, po poprawkach | 43 | 821,6 | 41/43 |
| v4, dodany zestaw loop-live | 49 | 788,2 | 42/49 |
+52,5 punktu między v2 a v3 nie wzięło się z lepszego modelu ani lepszego promptu. Dały je trzy błędy harnessu, które wyszły w przebiegu v2:
- Wyrocznia: normalizacja ścieżek w wyroczni była błędna.
- Wyciąganie JSON-a: zawodziło, gdy model odpowiadał gołym JSON-em.
- Ujście SSE: jego czas życia kończył się za wcześnie.
v4 dodaje sześć scenariuszy dyscypliny pętli, więc jej wyniku nie da się porównać z v3.
Dla skali: na obecnym zestawie 49 scenariuszy różnica między najlepszym a najgorszym z dziesięciu lokalnych modeli to 99,6 punktu. Same błędy harnessu były warte mniej więcej połowę tego.
Dziesięć lokalnych modeli, jeden harness
Każdy model z mojego lokalnego rejestru przechodzi pełne 49 scenariuszy, sekwencyjnie, na jednym slocie GPU:
| Model | Wynik | Zaliczone | Loop-live | Zmarnowane | Zbędne |
|---|---|---|---|---|---|
| Qwen3.6-27B (dense) | 816,2 | 44/49 | 89,0 | 146 | 12 |
| Qwopus3.6-27B-v2-MTP | 808,0 | 42/49 | 76,2 | 142 | 12 |
| Gemma-4-31B | 806,2 | 38/49 | 75,9 | 108 | 8 |
| Gemma-4-12B Q4 | 780,0 | 37/49 | 75,8 | 120 | 17 |
| Ornith-1.0-35B | 770,0 | 40/49 | 75,6 | 192 | 43 |
| Qwen3.6-27B MTP | 768,8 | 41/49 | 77,1 | 166 | 17 |
| Gemma-4-12B Q8 | 756,8 | 37/49 | 75,8 | 135 | 28 |
| Qwen3.6-35B-A3B (MoE) | 742,2 | 36/49 | 65,9 | 183 | 36 |
| Qwen3.6-27B (pi-reasoning) | 723,3 | 36/49 | 63,2 | 197 | 36 |
| Ornith-1.0-9B | 716,6 | 27/49 | 80,0 | 271 | 122 |
Tabela powyżej to migawka. Ranking na żywo, aktualizowany z każdym przebiegiem: trefon.com/pl/benchmarki.
Co z tego czytam:
- Prowadzi dense 27B. Dwa warianty Qwen3.6-27B dense to najmocniejsze lokalne modele agentowe, jakie mam: 816 i 808.
- MoE i tryby rozumowania kosztują dyscyplinę narzędzi. MoE 35B (742) i wariant pi-reasoning (723) przegrywają z mniejszymi od siebie.
- Zaliczenia i ekonomia narzędzi to różne osie. Gemma-4-31B marnuje najmniej wywołań (108 zmarnowanych, 8 zbędnych), ale zalicza tylko 38 z 49.
- Małe modele rozsypują się na pętlach. Ornith-1.0-9B ma 271 zmarnowanych i 122 zbędne wywołania.
Uruchamianie bez modelu
Jest tryb hermetyczny z udawanym LLM. Jest deterministyczny i nie potrzebuje ani modelu, ani GPU, więc harnessowa połowa pary jest testowana w CI przy każdej zmianie.
Co z tego wynoszę
- Napraw harness, zanim wybierzesz model. Najtańsze 52 punkty znalazłem we własnym kodzie.
- Licz marnotrawstwo, nie tylko zaliczenia. Ornith-1.0-35B zalicza więcej scenariuszy niż Gemma-4-31B (40 do 38), przy prawie dwa razy większej liczbie zmarnowanych wywołań (192 do 108). Za zmarnowane wywołania płacisz tokenami i opóźnieniem.
- Mierz dyscyplinę pętli osobno. Zawodzi inaczej niż poprawność, a to ona zamienia zdolny model w agenta, który nigdy się nie zatrzymuje.
Pełne tabele, lista scenariuszy i metodologia: jtrefon.github.io/amber/benchmarks. Kod: github.com/jtrefon/amber.