HyperAI
Back to Headlines

Utiliser les ASTs pour Corriger les URLs d'Images Hallucinées dans le Code Généré par LLMs

il y a 18 jours

Utilisation des Arbres de Syntaxe Abstraite (AST) pour la Manipulation Assistée du Code Source par les LLM Récemment, nous avons construit une plateforme permettant aux utilisateurs de créer des applications web à partir de simples instructions, semblables à des outils existants comme V0 ou Loveable. Comme beaucoup de startups technologiques actuelles, nous avons exploité des grands modèles linguistiques (LLM) pour générer le code source, mais nous avons rapidement rencontré plusieurs problèmes allant des incohérences de marque ou de style aux erreurs de syntaxe. Un problème particulier propre au code frontend a été celui des URLs d'images fantaisistes générées par les LLM. Ces URLs ne pointent généralement pas vers des images valides ou pertinentes sur le web. Comment pouvons-nous résoudre cela afin que notre code généré contienne des URLs d'images à la fois valides et pertinentes ? Décomposition du Problème Pour résoudre ce problème, nous l'avons décomposé en plusieurs étapes : Trouver toutes les occurrences d'images dans le code. Utiliser le contexte environnant pour générer des légendes pertinentes pour chaque image. Utiliser un modèle de génération d'images à partir de texte pour créer ces images. Remplacer les URLs d'images fantaisistes par les URLs des images générées. Dans ce texte, nous nous concentrerons principalement sur les étapes 1 et 4, car les autres (la génération de légendes et d'images) sont relativement plus simples et reposent sur des appels standard de LLM. Options Éliminées Regex (Expressions régulières) : À première vue, l'utilisation d'une expression régulière pour trouver tous les éléments d'image dans le JSX semble simple. Cependant, cette approche présente plusieurs limitations. Les images peuvent exister sous différentes formes (balises <img>, balises spécifiques à un framework comme <Image>) et les propriétés des images peuvent faire référence à des listes ou des objets définis en JavaScript, rendant l'approche régulière inadaptée. Modèles Linguistiques (LLM) : Bien que les LLM puissent être suffisamment intelligents pour détecter la plupart des cas, leur utilisation pour extraire simplement une partie du code est excessive. En outre, cela génère des coûts, est lent et comporte une certaine non-déterminisme, ce qui peut conduire à des échecs dans certains scénarios. Solution : Les ASTs (Arbres de Syntaxe Abstraite) Les ASTs fournissent une représentation arborea de la structure du code source, décomposant les éléments comme les balises JSX, les fonctions et les objets JavaScript/TypeScript. Ce format permet une navigation fluide et ciblée dans le code, facilitant la recherche et la modification des éléments image. Construction et Traversée de l'AST Nous avons utilisé Babel, une bibliothèque populaire pour la transformation de code JavaScript, pour construire et traverser notre AST. Voici comment les fonctions findImageNodes et updateImageNodesWithMetaData fonctionnent : ```javascript const babelParser = require('@babel/parser'); const traverse = require('@babel/traverse').default; const generator = require('@babel/generator').default; const t = require('@babel/types'); function findImageNodes(code) { const ast = babelParser.parse(code, { sourceType: 'module', plugins: ['jsx', 'typescript'], }); const candidateNodes = []; // Trouver les images définies comme littéraux d'objet traverse(ast, { ObjectExpression(path) { const properties = path.node.properties; properties.forEach((prop) => { if (prop.type === 'ObjectProperty' && (prop.key.name === 'src' || prop.key.name === 'url' || prop.key.name === 'image')) { const nodeSourceCode = generator(path.node).code; candidateNodes.push(nodeSourceCode); } }); }, JSXElement(path) { const openingElement = path.node.openingElement; const tagName = openingElement.name && openingElement.name.name; if (tagName === 'img' || tagName === 'Image') { const nodeSourceCode = generator(openingElement).code; const existingSrcAttr = openingElement.attributes.find(attr => attr.name.name === 'src'); // Filtrer les attributs src qui sont des littéraux de chaînes if (existingSrcAttr) { if (existingSrcAttr.value.type === 'StringLiteral') { candidateNodes.push(nodeSourceCode); } } else { candidateNodes.push(nodeSourceCode); } } } }); return candidateNodes; } ``` La fonction findImageNodes parcourt l'AST pour identifier tous les nœuds d'images, qu'ils soient définis comme des littéraux d'objet ou des éléments JSX. Elle stocke ces nœuds dans un tableau candidateNodes. Mise à Jour des Nœuds avec les Métadonnées Une fois que nous avons trouvé tous les nœuds candidats, nous les filtrons si nécessaire et mettons à jour leurs propriétés src et alt avec les URLs et légendes générées. Voici la fonction updateImageNodesWithMetaData : ```javascript function updateImageNodesWithMetaData(code, nodeResults) { const ast = babelParser.parse(code, { sourceType: 'module', plugins: ['jsx', 'typescript'], }); // Créer une carte de correspondance entre le code source original des nœuds et leurs résultats const resultMap = new Map(nodeResults); traverse(ast, { ObjectExpression(path) { const properties = path.node.properties; const nodeSourceCode = generator(path.node).code; if (resultMap.has(nodeSourceCode)) { properties.forEach((prop) => { if (prop.type === 'ObjectProperty' && (prop.key.name === 'src' || prop.key.name === 'url' || prop.key.name === 'image')) { prop.value = t.stringLiteral(resultMap.get(nodeSourceCode)['image_url']); const existingAlt = properties.find(p => p.key.name === 'alt'); if (existingAlt) { existingAlt.value = t.stringLiteral(resultMap.get(nodeSourceCode)['description']); } else { const altProperty = t.objectProperty(t.identifier('alt'), t.stringLiteral(resultMap.get(nodeSourceCode)['description'])); path.node.properties.push(altProperty); } } }); } }, JSXElement(path) { const openingElement = path.node.openingElement; const nodeSourceCode = generator(openingElement).code; if (resultMap.has(nodeSourceCode)) { const srcAttr = openingElement.attributes.find(attr => attr.type === 'JSXAttribute' && attr.name.name === 'src'); if (srcAttr) { srcAttr.value = t.stringLiteral(resultMap.get(nodeSourceCode)['image_url']); const existingAltAttr = openingElement.attributes.find(attr => attr.type === 'JSXAttribute' && attr.name.name === 'alt'); if (existingAltAttr) { existingAltAttr.value = t.stringLiteral(resultMap.get(nodeSourceCode)['description']); } else { openingElement.attributes.push(t.jsxAttribute(t.jsxIdentifier('alt'), t.stringLiteral(resultMap.get(nodeSourceCode)['description']))); } } } } }); return generator(ast).code; } ``` La fonction updateImageNodesWithMetaData met à jour les nœuds d'images trouvés avec les nouvelles URLs et légendes, puis reconstruit le code à partir de l'AST modifié. Exemple Pratique Voici un exemple de code source contenant des URLs d'images fantaisistes sous diverses formes (éléments JSX, littéraux d'objets) : ```javascript export default function EcommerceTShirts() { const [menuOpen, setMenuOpen] = useState(false) const [searchOpen, setSearchOpen] = useState(false) const hats = [ { id: 1, name: "Simple Hat", price: "$24.99", image: "/hat.jpg", alt: "existing" }, { id: 2, name: "New Hat", price: "$19.99", image: "/hat-new.jpg" }, ]; return ( Featured T-Shirts [ { id: 1, name: "Graphic Tee", price: "$24.99", image: "/tshirt1.jpg" }, { id: 2, name: "Pocket Tee", price: "$19.99", image: "/tshirt2.jpg" }, { id: 3, name: "V-Neck Tee", price: "$22.99", image: "/tshirt3.jpg" }, { id: 4, name: "Crew Neck Tee", price: "$21.99", image: "/tshirt4.jpg" }, ].map((shirt) => ( {shirt.name} {shirt.price} Add to Cart )) } {hats.map((hat) => ( ))} ) } ``` Après avoir traité ce code avec nos fonctions, voici le résultat : ```javascript export default function EcommerceTShirts() { const [menuOpen, setMenuOpen] = useState(false) const [searchOpen, setSearchOpen] = useState(false) const hats = [ { id: 1, name: "Simple Hat", price: "$24.99", image: "s3.productx.hat.jpg", alt: "A simple classic hat in a neutral tone displayed on a flat surface" }, { id: 2, name: "New Hat", price: "$19.99", image: "s3.productx.hat-new.jpg", alt: "A modern-style hat with a minimalist logo on the front panel" }, ]; return ( Featured T-Shirts [ { id: 1, name: "Graphic Tee", price: "$24.99", image: "s3.productx.tshirt1.jpg", alt: "A white graphic t-shirt featuring bold abstract art" }, { id: 2, name: "Pocket Tee", price: "$19.99", image: "s3.productx.tshirt2.jpg", alt: "A soft grey t-shirt with a front chest pocket" }, { id: 3, name: "V-Neck Tee", price: "$22.99", image: "s3.productx.tshirt3.jpg", alt: "A navy V-neck t-shirt made from breathable cotton" }, { id: 4, name: "Crew Neck Tee", price: "$21.99", image: "s3.productx.tshirt4.jpg", alt: "A classic black crew neck t-shirt with a tailored fit" }, ].map((shirt) => ( {shirt.name} {shirt.price} Add to Cart )) } {hats.map((hat) => ( ))} ) } ``` Cas d'Utilisation Supplémentaires des ASTs Les ASTs ne se limitent pas à la manipulation des URLs d'images. Ils sont également très utiles pour : Linting du Code pour les LLMs : L'article de blog d'Aider explique comment ils utilisent des ASTs pour linter du code généré par des LLMs, garantissant qu'il respecte les normes de qualité et de performance. Maintenance et Manipulation du Code à Grande Échelle : La conférence sur GritQL (qui utilise des ASTs sous le capot) montre comment des outils basés sur des ASTs peuvent faciliter la maintenance et la manipulation du code dans des applications complexes. Contexte Industriel Cette solution utilisant des ASTs est largement saluée par les professionnels de l'industrie pour sa précision et son efficacité. En évitant les méthodes moins fiables comme les expressions régulières ou les appels répétés de LLM, elle offre une alternative robuste et performante. Zeniteq, la startup derrière ce projet, se spécialise dans l'amélioration d'applications frontend grâce à l'intelligence artificielle, contribuant ainsi à la modernisation et à l'efficacité du développement web. Conclusion En conclusion, l'utilisation des ASTs pour la manipulation assistée du code source par les LLMs est une solution élégante et efficace. Elle permet non seulement de résoudre les problèmes d'URLs d'images fantaisistes mais aussi d'offrir des possibilités élargies pour l'analyse et la maintenance du code. Restez connectés à Zeniteq via LinkedIn et suivez-nous pour être au courant des dernières avancées en matière d'IA générative. Inscrivez-vous à notre newsletter et abonnez-vous à notre chaîne YouTube pour rester informé des dernières actualités et mises à jour en lien avec l'IA générative. Ensemble, façonnons l'avenir de l'IA !

Related Links