HyperAI
Back to Headlines

استخدام أدوات تعبير الشجرة النحوية المجردة (AST) لإصلاح عناوين الصور الخاطئة في رموز البرمجيات المجانية من الذكاء الاصطناعي

منذ 18 أيام

استخدام شجرة البناء المجرّدة (AST) لمساعدة النماذج اللغوية الكبيرة (LLM) على التعامل مع كود البرمجة المصدر في وقتٍ قريب، كان فريقنا يبني منصة تتيح للمستخدمين إنشاء تطبيقات ويب باستخدام تعليمات بسيطة، مشابهة لما يقدمه موقع v0 وlovABLE. ومع ذلك، واجهنا العديد من المشكلات عند استخدام النماذج اللغوية الكبيرة (LLM) لإنشاء كود البرمجة، بدءًا من عدم اتساق العلامات التجارية والتصميمات وصولاً إلى أخطاء النحو. المشكلة واحدة من المشكلات الفريدة التي واجهتنا في كود الجبهة الأمية (Frontend) كانت مشكلة روابط الصور المتخيلة (Hallucinated Image URLs). كما يمكنك تخيله، يحتوي كود صفحة الويب غالبًا على عناصر صورة، وعندما يتم إنشاؤه بواسطة LLM، فإن روابط الصور غالبًا ما تكون غير صالحة وغير مرتبطة بصور حقيقية على الإنترنت. السؤال الآن هو: كيف يمكننا حل هذه المشكلة بحيث يحتوي الكود المُنشأ على روابط صور صالحة ومتعلقة بالموضوع؟ تقسيم المشكلة يمكن تقسيم المشكلة إلى وحدات أصغر كالتالي: 1. العثور على جميع المواقع في الكود التي تتعلق بالصور. 2. استخدام السياق المحيط والمعلومات الإضافية لإنشاء تعليق مناسب لكل صورة. 3. استخدام نموذج تحويل النص إلى صورة لإنشاء الصور بناءً على التعليقات. 4. استبدال روابط الصور المتخيلة بالروابط المُنشئة. الخيارات المتاحة التعبيرات النمطية (Regex): قد يبدو أن العثور على روابط الصور باستخدام التعبيرات النمطية أمرًا بسيطًا، ولكن هذا ليس صحيحًا دائمًا لعدة أسباب: - الصور في JSX يمكن أن تظهر بعدة أشكال، مثل عناصر HTML <img> أو عناصر الصور الخاصة بالإطارات <Image>. - قد يتم تمثيل الصور أيضًا كمكونات مخصصة <ProfileImage>. - قد يشير علامة الصورة إلى قائمة أو كائن معرّف في JavaScript. النماذج اللغوية الكبيرة (LLM): إذا لم تكن التعبيرات النمطية مفيدة، فلماذا لا نستخدم LLM لاستخراج جميع حالات الصور بغض النظر عن موقعها أو اتفاقياتها التسمية؟ لكن هذه الطريقة تأتي مع سلبيات: - استخدام LLM فقط لاستخراج جزء من الكود يعتبر تضخيمًا غير مبرر. - هناك تكلفة مالية حتى وإن كانت صغيرة، ولكنها قد تتراكم مع الوقت. - طلبات API لـ LLM تستغرق عدة ثوانٍ لحلها. - النتائج غير مؤكدة وقد تتعرض للأخطاء في بعض السيناريوهات. الحل مع استبعاد خيارات التعبيرات النمطية والنماذج اللغوية الكبيرة، دعونا ننظر في خيار أكثر واقعية: شجرة البناء المجرّدة (Abstract Syntax Tree - AST). شجرة البناء المجرّدة (AST): شجرة البناء المجرّدة هي تمثيل "شجري" لكود البرمجة المصدر. إنها تفكك الكود إلى مكونات نحوية مثل عناصر JSX، الدوال، كائنات JavaScript/تعبيراتها، وتُرتبها في بنية شجرية يمكن تصفحها. بفضل أداة Babel، يمكننا فعل ذلك بسهولة لـ JavaScript/Typescript. الخطوات العملية: 1. إنشاء AST: نقوم بإنشاء AST من الكود المعطى باستخدام Babel Parser. 2. التصفح للبحث عن العقد: نستخدم Babel Traverser للبحث عن عناصر الصور (JSX Elements) وكائنات JavaScript التي تتوافق مع معاييرنا. 3. تحديث العقد: نقوم بتحديث خصائص هذه العقد (مثل src و alt) بالروابط والتعليقات الجديدة. 4. تحويل AST مرة أخرى إلى كود مصدر: نُعيد تحويل AST إلى كود مصدر باستخدام Babel Generator. الكود العملي: ```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 = []; // البحث عن الصور المعرفة ككائنات حرفية 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'); if (existingSrcAttr && existingSrcAttr.value.type === 'StringLiteral') { candidateNodes.push(nodeSourceCode); } else if (!existingSrcAttr) { candidateNodes.push(nodeSourceCode); } } } }); return candidateNodes; } function updateImageNodesWithMetaData(code, nodeResults) { const ast = babelParser.parse(code, { sourceType: 'module', plugins: ['jsx', 'typescript'] }); 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; } ``` مثال عملي: في هذا القسم، نقدم مثالًا للكود المصدر الذي يحتوي على روابط صور متخيلة بعدة أشكال (عناصر JSX، كائنات حرفية)، والتي يتم استبدالها بروابط وأوصاف مُنشئة دون التأثير على سلامة الهيكل أو النحو. المدخل: 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 ( <div className="flex flex-col min-h-screen bg-gray-50"> <main className="flex-grow mt-20"> <section className="py-16"> <div className="container mx-auto px-4"> <h2 className="text-3xl font-bold mb-8 text-center text-gray-800">Featured T-Shirts</h2> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8"> {[ { 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) => ( <Card key={shirt.id} className="transition transform hover:scale-105 hover:shadow-lg"> <CardHeader> <Image src={shirt.image} alt={shirt.name} width={300} height={300} className="w-full h-64 object-cover rounded-t-lg" /> </CardHeader> <CardContent> <CardTitle className="text-xl font-semibold">{shirt.name}</CardTitle> <p className="text-gray-600">{shirt.price}</p> </CardContent> <CardFooter> <Button className="w-full bg-indigo-600 text-white hover:bg-indigo-700 transition duration-300"> Add to Cart </Button> </CardFooter> </Card> ))} </div> </div> </section> <section className="py-16"> <div> <img src="/placeholder.jpg?height=400&width=1200" alt="A featured hat displayed in a stylish setting, showcasing a vibrant background with a gradient blending from blue to indigo, creating an inviting atmosphere for potential customers." className="w-full h-96 object-cover opacity-50" id="08ba0c93-1f24-4a28-a459-4f115299849f" /> </div> </section> <section className="py-16"> <div> <Image height={900} src="/placeholder.png" alt="A placeholder image for a t-shirt" width={1200} className="w-full h-96 object-cover opacity-50" id="08ba0c93-1f24-4a28-a459-4f115299849f"/> </div> </section> <section className="py-16"> <div> {hats.map((hat) => ( <img key={hat.id} src={hat.image} alt={hat.name} className="w-full h-96 object-cover opacity-50" id={hat.id.toString()}/> ))} </div> </section> </main> </div> ) } المخرج: 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 ( <div className="flex flex-col min-h-screen bg-gray-50"> <main className="flex-grow mt-20"> <section className="py-16"> <div className="container mx-auto px-4"> <h2 className="text-3xl font-bold mb-8 text-center text-gray-800">Featured T-Shirts</h2> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8"> {[ { 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) => ( <Card key={shirt.id} className="transition transform hover:scale-105 hover:shadow-lg"> <CardHeader> <Image src={shirt.image} alt={shirt.alt} width={300} height={300} className="w-full h-64 object-cover rounded-t-lg" /> </CardHeader> <CardContent> <CardTitle className="text-xl font-semibold">{shirt.name}</CardTitle> <p className="text-gray-600">{shirt.price}</p> </CardContent> <CardFooter> <Button className="w-full bg-indigo-600 text-white hover:bg-indigo-700 transition duration-300"> Add to Cart </Button> </CardFooter> </Card> ))} </div> </div> </section> <section className="py-16"> <div> <img src="s3.productx.placeholder.jpg" alt="A featured hat displayed in a stylish setting with a vibrant background that fades from blue to indigo, enhancing visual appeal" className="w-full h-96 object-cover opacity-50" id="08ba0c93-1f24-4a28-a459-4f115299849f" /> </div> </section> <section className="py-16"> <div> <Image height={900} src="s3.productx.placeholder.png" alt="A placeholder image representing a featured t-shirt on a blank background" width={1200} className="w-full h-96 object-cover opacity-50" id="08ba0c93-1f24-4a28-a459-4f115299849f"/> </div> </section> <section className="py-16"> <div> {hats.map((hat) => ( <img key={hat.id} src={hat.image} alt={hat.alt} className="w-full h-96 object-cover opacity-50" id={hat.id.toString()}/> ))} </div> </section> </main> </div> ) } تقييم الحدث من قبل المختصين يُعتبر استخدام شجرة البناء المجرّدة (AST) حلًّا فعالًا ومُستدامًا لمعالجة مشكلة روابط الصور المتخيلة في كود الجبهة الأمية. هذا النهج يوفر دقةً عاليةً ويقلل من الأخطاء التي قد تحدث عند استخدام التعبيرات النمطية أو النماذج اللغوية الكبيرة. كما أنه يحافظ على سلامة الكود ومرونته، مما يجعله خيارًا مفضّلًا للمشاريع الكبيرة والمعقّدة. نبذة تعريفية عن الشركة الشركة المذكورة في هذا السياق هي Zeniteq، وهي شركة متخصصة في تطوير التكنولوجيا والذكاء الاصطناعي. تعمل Zeniteq على تطوير منصات وحلول تكنولوجية مبتكرة تسهل عملية إنشاء التطبيقات والخدمات الرقمية. يمكنك متابعة Zeniteq على LinkedIn أو الاشتراك في نشرتهم الإخبارية وقناة YouTube الخاصة بهم للبقاء على اطلاعٍ بأحدث الأخبار والتحديثات في مجال الذكاء الاصطناعي.

Related Links