
Wydajemy miliardy na trenowanie maszyn, które potrafią wygenerować prawie wszystko. Potem, w produkcji, poświęcamy ogromny wysiłek na to, aby generowały tylko to, czego system może użyć.
Większość rozmów o LLM-ach dotyczy generowania: większej kreatywności, większych możliwości, większej liczby wyników z tego samego wejścia. Constrained decoding dotyczy problemu odwrotnego. Należy do produkcyjnej fazy integracji LLM-ów, gdzie pytanie nie brzmi "czy model może coś wygenerować?", ale "czy może wygenerować coś poprawnego?".
Czym jest constrained decoding?#
Constrained decoding wymusza, aby wynik LLM-a trzymał się z góry określonej struktury już w trakcie generowania.
Podczas inferencji model ocenia możliwe kolejne tokeny. Te oceny nazywamy logitami: są surową preferencją modelu dla każdego tokenu w jego słowniku. Ograniczony dekoder filtruje te opcje, zanim kolejny token zostanie zaakceptowany, blokując tokeny, które uczyniłyby częściowy wynik niepoprawnym.
Wyobraźmy sobie na przykład agenta text-to-SQL generującego taką częściową kwerendę:
SELECT COUNT(*) FROM clients WHERE salary >W tym miejscu poprawne kontynuacje mogłyby wyglądać tak:
8000
9000
10000Niepoprawne kontynuacje mogłyby wyglądać tak:
FROM
DROP
helloModel nadal generuje, ale dekoder zawęża możliwą ścieżkę.
Zastosowania#
Weźmy text-to-SQL. Obietnica jest prosta: użytkownik zadaje pytanie o bazę danych w języku naturalnym, a model pisze SQL. Ale SQL to nie tylko tekst; to tekst, który wykona inny system. Jeśli model napisze niepoprawny SQL, zapytanie się nie powiedzie. Jeśli napisze poprawny SQL z błędnym joinem albo filtrem, odpowiedź może wyglądać dobrze, choć będzie błędna.
Autorzy TeCoD zwracają uwagę, że text-to-SQL może wyglądać mocno w uśrednionych benchmarkach, a mimo to źle działać na konkretnych schematach firmowych. Dla niektórych baz danych raportują dokładność na poziomie 20-30%, gdy wyniki rozbije się według schematu.
Właśnie tutaj pomaga constrained decoding. Zamiast pozwolić modelowi wymyślać całą kwerendę od zera, system może ograniczyć go do znanego szablonu SQL i poprosić o uzupełnienie pól:
SELECT COUNT(T1.client_id)
FROM client AS T1
INNER JOIN district AS T2
ON T1.district_id = T2.district_id
WHERE T1.gender = [gender]
AND T2.A3 = [district_name]
AND T2.A11 > [salary]Model nadal wykonuje użyteczną pracę, ale najbardziej ryzykowna część przestrzeni wyszukiwania została usunięta.
Ten sam pomysł pojawia się przy wynikach strukturalnych. Gdy prosimy model o JSON, problemem nie jest to, że model nigdy nie widział JSON-a. Problemem jest to, że "wygląda jak JSON" to nie to samo co JSON, który parser zawsze może odczytać. JSONSchemaBench ocenia systemy constrained decoding na rzeczywistych JSON Schema, mierząc nie tylko poprawność, ale też efektywność, pokrycie i jakość wyniku.
Kompromis#
Mówienie nie ma swoją cenę. Wybierając najbardziej poprawny następny token, dekoder może zablokować ścieżkę, która byłaby bardziej kreatywna albo semantycznie użyteczna. Constrained decoding może sprawić, że duże modele zachowują się jak mniejsze, bardziej wyspecjalizowane systemy, bo ogranicza to, co wolno im zrobić.
Agenci często używają podobnego wzorca poza dekoderem. Agent programistyczny może swobodnie wygenerować kod, a potem uruchomić bun lint, tsc albo testy, aby odrzucić niepoprawny wynik. To nie jest constrained decoding w ścisłym sensie, bo ograniczenie następuje po wygenerowaniu, ale produkcyjny odruch jest ten sam: generuj, sprawdź, odrzuć, napraw.
Dziś ograniczenia mogą brzmieć jak zakładanie kagańca poecie. Nowsze podejścia, takie jak backtracking albo rozumowanie przed generowaniem strukturalnym, sugerują lepszy kierunek: pozwolić modelowi eksplorować, ale upewnić się, że ostatecznie trafi do wyniku, któremu system może zaufać.
Constrained decoding to sztuka mówienia nie podczas inferencji. Nie sprawia, że model ma rację, ale może zatrzymać całe klasy niepoprawnych wyników, zanim trafią na produkcję.