Sări la conținut

Ieșiri structurate: obținerea unui JSON fiabil dintr-un model de limbaj

Blog / Publicat 

Prima versiune a fiecărei integrări LLM analizează proza. Cereți „cele trei riscuri principale, unul pe rând”, împărțit pe linii noi și funcționează până în ziua în care modelul scrie mai întâi o propoziție introductivă. Ieșiri structurate există pentru a pune capăt acelei bucle: îi înmânați modelului o schemă JSON, decodorul este constrâns, astfel încât să nu emită nimic care o încalcă și primiți înapoi o sarcină utilă cu câmpurile pe care le-ați cerut. Această garanție este reală, dar mai restrânsă decât pare, iar diferența este locul unde trăiesc bug-urile.

Ce acoperă de fapt garanția

Garanții de decodare constrânsă formă. Răspunsul va fi analizat ca JSON, va avea cheile dvs., tipurile se vor potrivi și câmpurile enumerate vor conține una dintre valorile dvs. enumerate. Aceasta este o îmbunătățire mare față de prompt-and-speranță.

Nu garantează nimic despre conţinut. Un câmp tastat ca șir va conține un șir; dacă acel șir este corect sau inventat pentru a satisface schema, este neschimbat față de înainte. De fapt, o schemă strictă face ca invenția să fie puțin mai probabilă, deoarece un câmp obligatoriu trebuie completat cu ceva, iar modelul nu are cum să spună „nu este prezent în sursă”. Acesta este cel mai frecvent eșec în producție: un necesar invoice_number într-un document care nu are niciunul.

Proiectați în jurul lui. Permite null acolo unde absența este posibilă, adaugă un explicit found: boolean sau a "unknown" enum membru și nu faceți niciodată un câmp obligatoriu decât dacă răspunsul există cu adevărat în fiecare intrare.

Proiectarea unei scheme pe care un model poate fi completat

Schemele scrise pentru validare și schemele scrise pentru generare arată diferit. Câteva reguli care se aplică tuturor furnizorilor:

Furnizorii limitează, de asemenea, cuvintele cheie ale schemei JSON pe care le acceptă în modul strict: oneOf, constrângerile de tipar, limitele numerice și recursiunea sunt de obicei limitate sau ignorate. Presupuneți că schema constrânge numai structura și aplicați singur regulile de afaceri după analizare.

Validați oricum

Chiar și cu un mod strict, validați fiecare răspuns înainte de a vă atinge baza de date. Modul strict poate fi dezactivat printr-o modificare de configurare, o cale de rezervă poate lovi un model care nu o acceptă, o reîncercare de rețea poate returna un obiect de eroare, iar răspunsul poate fi trunchiat de o limită de simbol la mijlocul obiectului - care produce JSON nevalid, nici un mod de schemă nu împiedică.

Când o sarcină utilă eșuează, întrebarea utilă este ce câmp și de ce. The Validator de schemă JSON preia documentul și schema și raportează o linie pe problemă, cu calea pointerului JSON, cuvântul cheie care a eșuat și valoarea găsită efectiv. Acesta este exact forma pe care o doriți pentru două scopuri: remedierea schemei în timpul dezvoltării și reintroducerea unei reîncercări - un raport de validare eșuat lipit într-un mesaj de urmărire este un prompt de reparare remarcabil de eficient, deoarece modelul poate vedea exact ce a greșit.

Limitați reîncercările la una sau două. Un model care eșuează de două ori o schemă i se cere de obicei ceva ce nu conține intrarea, iar a treia încercare îl va inventa.

De la un eșantion de încărcare utilă la cod

Majoritatea schemelor încep viața ca un exemplu de răspuns pe care cineva l-a lipit într-un chat. Transformarea manuală a acestuia într-un cod tastat și validat este obositoare și predispusă la erori, așa că nu.

Lipiți proba în Schema JSON la Zod și obțineți o schemă Zod plus tipul TypeScript dedus. Se deduce pe câmp, mai degrabă decât să tasteze totul ca șir: valorile care arată ca e-mailuri, URL-uri, UUID-uri sau date ISO primesc .email(), .url(), .uuid() şi .datetime() în loc de un gol z.string(), tablourile poartă tipul lor de element, iar un câmp al cărui tip variază în funcție de apariție devine o uniune, mai degrabă decât să-l aleagă în tăcere pe primul pe care l-a văzut. Acest ultim comportament merită alimentat în mod deliberat: lipiți trei sau patru răspunsuri reale concatenate, nu unul, astfel încât câmpurile opționale și polimorfe să apară ca uniuni în loc să fie blocate în orice ar fi conținut primul eșantion.

Dacă aveți nevoie doar de tipuri și nu de validare în timp de execuție - deoarece sarcina utilă provine dintr-o sursă în care aveți deja încredere - JSON la TypeScript produce interfețele direct, cu obiectele imbricate defalcate ca sub-interfețe numite, mai degrabă decât blob-uri anonime înlineate.

Păstrați direcția adevărului dreaptă: o singură definiție a schemei, cu tot restul generat de ea. O schemă Zod și o schemă JSON menținute separat nu vor fi de acord în decurs de o lună, iar dezacordul va apărea ca o eroare de analiză a producției, mai degrabă decât un eșec al testului.

Citind ce s-a întors

Răspunsurile modelului sosesc reduse pe o singură linie, ceea ce face ca observarea lor să fie mizerabilă. The Formatator JSON indentează și le sortează în ceva ce poate fi citit, iar validarea sa prinde imediat cazul de trunchiere - o sarcină utilă care se termină la mijlocul șirului este semnătura unei limite de jeton de accesare, iar remedierea este o limită de ieșire mai mare sau o schemă mai mică, nu o schimbare promptă.

Când comparați ceea ce au produs două modele din aceeași intrare sau verificați dacă o modificare promptă a modificat rezultatul în moduri pe care nu le-ați intenționat, diferențiați încărcăturile utile formatate în loc să citiți ambele. Diferențele structurale care sunt invizibile într-un perete de JSON - un câmp care a devenit în liniște un șir de cifre în loc de un număr - ies imediat în evidență într-o diferență.

Versiune

Schemele se schimbă, iar rezultatul modelului se modifică odată cu ele. Puneți un câmp de versiune în încărcarea utilă din prima zi, astfel încât înregistrările stocate să aibă forma sub care au fost scrise. Adaptarea după ce aveți un milion de rânduri de JSON neetichetat este genul de migrare pentru care nimeni nu programează timp.

Toate aceste instrumente rulează local în browserul dvs., ceea ce contează mai mult decât de obicei pentru acest flux de lucru: exemplele de încărcături utile pe care le transformați în scheme sunt, de obicei, răspunsuri API reale cu date reale ale clienților în ele și nu ar trebui să fie încărcate într-un serviciu de formatare pentru a fi îmbunătățite.

Scris de Ján Turský

Creatorul lui TextArray — creează instrumente gratuite, care au prioritate confidențialitatea, care rulează în întregime în browserul tău.