Sorties structurées : obtenir un JSON fiable à partir d'un modèle de langage
La première version de chaque intégration LLM analyse la prose. Vous demandez "les trois risques principaux, un par ligne", répartis sur les nouvelles lignes, et cela fonctionne jusqu'au jour où le modèle écrit en premier une phrase d'introduction. Des sorties structurées existent pour mettre fin à cette boucle : vous remettez au modèle un schéma JSON, le décodeur est contraint afin qu'il ne puisse pas émettre quoi que ce soit qui le viole, et vous récupérez une charge utile avec les champs que vous avez demandés. Cette garantie est réelle mais plus étroite qu’il n’y paraît, et la différence réside dans l’endroit où vivent les bugs.
Ce que couvre réellement la garantie
Garanties de décodage contraint forme. La réponse sera analysée au format JSON, elle contiendra vos clés, les types correspondront et les champs d'énumération contiendront l'une de vos valeurs répertoriées. C’est une grande amélioration par rapport à la rapidité et à l’espoir.
Cela ne garantit rien contenu. Un champ saisi sous forme de chaîne contiendra une chaîne ; que cette chaîne soit exacte ou inventée pour satisfaire le schéma reste inchangé par rapport à avant. En fait, un schéma strict rend l'invention légèrement plus probable, car un champ obligatoire doit être rempli avec quelque chose, et le modèle n'a aucun moyen de dire "non présent dans la source". Il s'agit de l'échec le plus courant en production : un invoice_number dans un document qui n'en a pas.
Concevoir autour de lui. Autoriser null là où l'absence est possible, ajouter un explicite found: boolean ou un "unknown" enum membre, et ne rendez jamais un champ obligatoire à moins que la réponse n'existe réellement dans chaque entrée.
Concevoir un schéma qu'un modèle peut remplir
Les schémas écrits pour la validation et les schémas écrits pour la génération sont différents. Quelques règles valables pour tous les fournisseurs :
- Battements plats imbriqués. Chaque niveau d’imbrication est un endroit où le modèle perd le fil. Trois objets peu profonds extraits en trois appels ont battu un arbre profondément imbriqué.
- Les énumérations battent les chaînes libres. Si un champ comporte cinq valeurs légitimes, répertoriez-les. Vous supprimez une classe entière de code de normalisation et le décodeur contraint l'applique pour vous.
- Les noms de champs sont des instructions.
due_date_iso8601produit un meilleur rendement quedateavec le format expliqué dans une invite distincte. Les noms sont dans le contexte ; utilisez-les. - Utiliser
descriptionsur les champs. La plupart des fournisseurs transmettent les descriptions de schéma au modèle. Une clause par champ ambigu est moins chère et plus fiable qu'un paragraphe d'instructions en prose ci-dessus. - Ensemble
additionalProperties: false. De toute façon, plusieurs fournisseurs l'exigent pour le mode strict, et cela empêche le modèle d'inventer utilement une clé supplémentaire que votre analyseur ignore silencieusement. - Préférez les tableaux d’objets plats aux cartes. Les clés dynamiques (un objet dont les noms de propriétés sont inconnus à l'avance) sont mal prises en charge par les modes stricts et difficiles à saisir par le destinataire.
Les fournisseurs limitent également les mots-clés du schéma JSON qu’ils prennent en charge en mode strict : oneOf, les contraintes de modèle, les limites numériques et la récursion sont généralement limitées ou ignorées. Supposons que le schéma limite uniquement la structure et appliquez vous-même vos règles métier après l'analyse.
Validez quand même
Même avec un mode strict, validez chaque réponse avant qu'elle ne touche votre base de données. Le mode strict peut être désactivé par un changement de configuration, un chemin de secours peut atteindre un modèle qui ne le prend pas en charge, une nouvelle tentative réseau peut renvoyer un objet d'erreur et la réponse peut être tronquée par une limite de jeton au milieu de l'objet - ce qui produit un JSON invalide qu'aucun mode schéma n'empêche.
Lorsqu’une charge utile échoue, la question utile est de savoir quel champ et pourquoi. Le Validateur de schéma JSON prend le document et le schéma et rapporte une ligne par problème, avec le chemin du pointeur JSON, le mot-clé qui a échoué et la valeur réellement trouvée. C'est exactement le formulaire que vous souhaitez pour deux raisons : réparer votre schéma pendant le développement et renvoyer une nouvelle tentative - un rapport de validation échoué collé dans un message de suivi est une invite de réparation remarquablement efficace, puisque le modèle peut voir précisément ce qui ne va pas.
Limitez le nombre de tentatives à une ou deux. Un modèle qui échoue deux fois à un schéma se voit généralement demander quelque chose que l'entrée ne contient pas, et la troisième tentative l'inventera.
D'un exemple de charge utile au code
La plupart des schémas démarrent sous la forme d'un exemple de réponse que quelqu'un a collé dans une discussion. Transformer cela en code tapé et validé à la main est fastidieux et sujet aux erreurs, alors ne le faites pas.
Collez l'échantillon dans Schéma JSON vers Zod et vous obtenez un schéma Zod plus le type TypeScript déduit. Il déduit par champ plutôt que de tout saisir sous forme de chaîne : les valeurs qui ressemblent à des e-mails, des URL, des UUID ou des dates ISO sont obtenues. .email(), .url(), .uuid() et .datetime() au lieu d'un nu z.string(), les tableaux portent leur type d'élément et un champ dont le type varie selon les occurrences devient une union plutôt que de choisir silencieusement le premier qu'il a vu. Ce dernier comportement mérite d'être nourri délibérément : collez trois ou quatre réponses réelles concaténées, et non une, afin que les champs facultatifs et polymorphes apparaissent sous forme d'unions au lieu d'être verrouillés sur ce que contenait le premier échantillon.
Si vous n'avez besoin que de types et non d'une validation d'exécution (car la charge utile provient d'une source en laquelle vous avez déjà confiance) JSON vers TypeScript produit les interfaces directement, avec des objets imbriqués divisés en sous-interfaces nommées plutôt que des blobs anonymes intégrés.
Gardez la direction de la vérité droite : une définition de schéma, avec tout le reste généré à partir de celle-ci. Un schéma Zod et un schéma JSON gérés séparément seront en désaccord dans un délai d'un mois, et le désaccord apparaîtra comme une erreur d'analyse de production plutôt que comme un échec de test.
Lire ce qui est revenu
Les réponses des modèles arrivent réduites sur une seule ligne, ce qui rend leur observation misérable. Le Formateur JSON les indente et les trie en quelque chose de lisible, et sa validation détecte immédiatement le cas de troncature - une charge utile qui se termine au milieu de la chaîne est la signature d'une limite de jeton d'accès, et le correctif est un plafond de sortie plus élevé ou un schéma plus petit, pas un changement rapide.
Lorsque vous comparez ce que deux modèles ont produit à partir de la même entrée ou que vous vérifiez si une modification rapide a modifié la sortie d'une manière que vous n'aviez pas prévue, comparez les charges utiles formatées plutôt que de lire les deux. Les différences structurelles invisibles dans un mur de JSON (un champ qui est progressivement devenu une chaîne de chiffres au lieu d'un nombre) ressortent immédiatement dans une différence.
Gestion des versions
Les schémas changent et la sortie du modèle change avec eux. Placez un champ de version dans la charge utile dès le premier jour, afin que les enregistrements stockés portent la forme sous laquelle ils ont été écrits. La mise à niveau après avoir obtenu un million de lignes de JSON non balisé est le genre de migration pour laquelle personne ne prévoit de temps.
Tous ces outils s'exécutent localement dans votre navigateur, ce qui est plus important que d'habitude pour ce flux de travail : les exemples de charges utiles que vous transformez en schémas sont généralement de véritables réponses API contenant de vraies données client, et ils ne doivent pas être téléchargés vers un service de formatage pour être embellis.
Créateur de TextArray : création d'outils gratuits axés sur la confidentialité qui s'exécutent entièrement dans votre navigateur.