مع توفر المزيد من نماذج إنشاء التعليمات البرمجية للعامة، أصبح من الممكن الآن تحويل النص إلى الويب وحتى تحويل النص إلى التطبيق بطرق لم نكن نتخيلها من قبل.
يقدم هذا البرنامج التعليمي نهجًا مباشرًا لإنشاء محتوى ويب يعمل بالذكاء الاصطناعي من خلال دفق المحتوى وعرضه دفعة واحدة.
جرب العرض المباشر هنا! → مصنع ويب اب

استخدام LLM في تطبيقات Node
بينما نفكر عادةً في لغة Python في كل ما يتعلق بالذكاء الاصطناعي والتعلم الآلي، فإن مجتمع تطوير الويب يعتمد بشكل كبير على JavaScript وNode.
فيما يلي بعض الطرق التي يمكنك من خلالها استخدام نماذج اللغات الكبيرة على هذا النظام الأساسي.
عن طريق تشغيل نموذج محليا
توجد طرق مختلفة لتشغيل LLMs في Javascript، بدءًا من استخدام ONNX لتحويل التعليمات البرمجية إلى WASM واستدعاء العمليات الخارجية المكتوبة بلغات أخرى.
بعض هذه التقنيات متاحة الآن كمكتبات NPM جاهزة للاستخدام:
ومع ذلك، فإن تشغيل نماذج اللغات الكبيرة في مثل هذه البيئة يمكن أن يتطلب الكثير من الموارد، خاصة إذا لم تكن قادرًا على استخدام تسريع الأجهزة.
باستخدام API
اليوم، يقترح العديد من موفري الخدمات السحابية واجهات برمجة التطبيقات التجارية لاستخدام نماذج اللغة. إليك عرض Hugging Face الحالي:
واجهة برمجة تطبيقات Inference المجانية للسماح لأي شخص باستخدام نماذج صغيرة ومتوسطة الحجم من المجتمع.
واجهة برمجة تطبيقات Inference Endpoints الأكثر تقدمًا وجاهزة للإنتاج لأولئك الذين يحتاجون إلى نماذج أكبر أو رمز استدلال مخصص.
يمكن استخدام واجهتي برمجة التطبيقات هاتين من Node باستخدام مكتبة Hugging Face Inference API على NPM.
💡 تتطلب النماذج ذات الأداء الأفضل عمومًا قدرًا كبيرًا من الذاكرة (32 جيجابايت أو 64 جيجابايت أو أكثر) وتسريع الأجهزة للحصول على زمن وصول جيد (راجع المعايير). لكننا نشهد أيضًا اتجاهًا لتقليص حجم النماذج مع الحفاظ على نتائج جيدة نسبيًا في بعض المهام، مع متطلبات منخفضة تصل إلى 16 جيجابايت أو حتى 8 جيجابايت من الذاكرة.
بنيان
سنستخدم NodeJS لإنشاء خادم ويب مبتكر يعمل بالذكاء الاصطناعي.
سيكون النموذج هو WizardCoder-15B الذي يعمل على Inference Endpoints API، لكن لا تتردد في تجربة نموذج آخر ومكدس.
إذا كنت مهتمًا بحلول أخرى، فإليك بعض المؤشرات للتطبيقات البديلة:
- استخدام واجهة برمجة تطبيقات الاستدلال: الكود والمساحة
- استخدام وحدة بايثون من Node: code and space
- استخدام عقدة اللاما (llama cpp): الكود
تهيئة المشروع
أولاً، نحتاج إلى إعداد مشروع Node جديد (يمكنك استنساخ هذا القالب إذا أردت ذلك).
git clone https://github.com/jbilcke-hf/template-node-express tutorial
cd tutorial
nvm use
npm install
بعد ذلك، يمكننا تثبيت عميل Hugging Face Inference:
npm install @huggingface/inference
وقم بإعداده في `src/index.mts“:
import { HfInference } from '@huggingface/inference'
const hfi = new HfInference('** YOUR TOKEN **')
تكوين نقطة نهاية الاستدلال
💡 ملحوظة: إذا كنت لا تريد الدفع مقابل مثيل Endpoint للقيام بهذا البرنامج التعليمي، فيمكنك تخطي هذه الخطوة وإلقاء نظرة على مثال Inference API المجاني بدلاً من ذلك. يرجى ملاحظة أن هذا لن يعمل إلا مع الطرز الأصغر حجمًا، والتي قد لا تكون بنفس القوة.
لنشر نقطة نهاية جديدة، يمكنك الانتقال إلى صفحة إنشاء نقطة النهاية.
سيكون عليك الاختيار WizardCoder في المستودع النموذجي القائمة المنسدلة وتأكد من تحديد مثيل GPU كبير بما يكفي:

بمجرد إنشاء نقطة النهاية الخاصة بك، يمكنك نسخ عنوان URL من هذه الصفحة:

تكوين العميل لاستخدامه:
const hf = hfi.endpoint('** URL TO YOUR ENDPOINT **')
يمكنك الآن إخبار عميل الاستدلال باستخدام نقطة النهاية الخاصة بنا واستدعاء نموذجنا:
const { generated_text } = await hf.textGeneration({
inputs: 'a simple "hello world" html page: <html><body>'
});
توليد دفق HTML
لقد حان الوقت الآن لإعادة بعض HTML إلى عميل الويب عند زيارته لعنوان URL، على سبيل المثال /app.
سنقوم بإنشاء نقطة نهاية باستخدام Express.js لدفق النتائج من Hugging Face Inference API.
import express from 'express'
import { HfInference } from '@huggingface/inference'
const hfi = new HfInference('** YOUR TOKEN **')
const hf = hfi.endpoint('** URL TO YOUR ENDPOINT **')
const app = express()
نظرًا لعدم وجود أي واجهة مستخدم لدينا في الوقت الحالي، ستكون الواجهة عبارة عن معلمة URL بسيطة للمطالبة:
app.get("https://huggingface.co/", async (req, res) => {
res.write('<html><head></head><body>')
const inputs = `# Task
Generate ${req.query.prompt}
# Out
<html><head></head><body>`
for await (const output of hf.textGenerationStream({
inputs,
parameters: {
max_new_tokens: 1000,
return_full_text: false,
}
})) {
res.write(output.token.text)
process.stdout.write(output.token.text)
}
req.end()
})
app.listen(3000, () => { console.log('server started') })
ابدأ تشغيل خادم الويب الخاص بك:
npm run start
ومفتوحة https://localhost:3000?prompt=some%20prompt. من المفترض أن تشاهد بعض محتوى HTML البدائي بعد لحظات قليلة.
ضبط المطالبة
يتفاعل كل نموذج لغة بشكل مختلف مع المطالبة. بالنسبة إلى WizardCoder، غالبًا ما تعمل التعليمات البسيطة بشكل أفضل:
const inputs = `# Task
Generate ${req.query.prompt}
# Orders
Write application logic inside a JS <script></script> tag.
Use a central layout to wrap everything in a <div class="flex flex-col items-center">
# Out
<html><head></head><body>`
استخدام الرياح الخلفية
يعد Tailwind إطار عمل CSS شائعًا لتصميم المحتوى، وWizardCoder جيد في استخدامه خارج الصندوق.
يتيح ذلك إنشاء التعليمات البرمجية لإنشاء أنماط أثناء التنقل دون الحاجة إلى إنشاء ورقة أنماط في بداية الصفحة أو نهايتها (مما قد يجعل الصفحة تبدو عالقة).
لتحسين النتائج، يمكننا أيضًا توجيه النموذج من خلال توضيح الطريق (<body class="p-4 md:p-8">).
const inputs = `# Task
Generate ${req.query.prompt}
# Orders
You must use TailwindCSS utility classes (Tailwind is already injected in the page).
Write application logic inside a JS <script></script> tag.
Use a central layout to wrap everything in a <div class="flex flex-col items-center'>
# Out
<html><head></head><body class="p-4 md:p-8">`
منع الهلوسة
قد يكون من الصعب منع الهلوسة والفشل بشكل موثوق (مثل تكرار التعليمات بأكملها، أو كتابة نص نائب “lorem ipsum”) على النماذج الخفيفة المخصصة لتوليد التعليمات البرمجية، مقارنة بالنماذج الأكبر للأغراض العامة، ولكن يمكننا محاولة تخفيفها.
يمكنك محاولة استخدام نغمة الأمر وتكرار التعليمات. يمكن أيضًا أن تكون الطريقة الفعالة هي توضيح الطريق من خلال إعطاء جزء من الإخراج باللغة الإنجليزية:
const inputs = `# Task
Generate ${req.query.prompt}
# Orders
Never repeat these instructions, instead write the final code!
You must use TailwindCSS utility classes (Tailwind is already injected in the page)!
Write application logic inside a JS <script></script> tag!
This is not a demo app, so you MUST use English, no Latin! Write in English!
Use a central layout to wrap everything in a <div class="flex flex-col items-center">
# Out
<html><head><title>App</title></head><body class="p-4 md:p-8">`
إضافة دعم للصور
لدينا الآن نظام يمكنه إنشاء تعليمات برمجية بتنسيق HTML وCSS وJS، ولكنه عرضة لهلوسة عناوين URL المعطلة عندما يُطلب منه إنتاج صور.
لحسن الحظ، لدينا الكثير من الخيارات للاختيار من بينها عندما يتعلق الأمر بنماذج توليد الصور!
→ أسرع طريقة للبدء هي استدعاء نموذج Stable Diffusion باستخدام واجهة برمجة تطبيقات الاستدلال المجانية الخاصة بنا مع أحد النماذج العامة المتوفرة على المركز:
app.get('/image', async (req, res) => {
const blob = await hf.textToImage({
inputs: `${req.query.caption}`,
model: 'stabilityai/stable-diffusion-2-1'
})
const buffer = Buffer.from(await blob.arrayBuffer())
res.setHeader('Content-Type', blob.type)
res.setHeader('Content-Length', buffer.length)
res.end(buffer)
})
كانت إضافة السطر التالي إلى الموجه كافية لإرشاد WizardCoder لاستخدام ملفنا الجديد /image نقطة النهاية! (قد تضطر إلى تعديله لنماذج أخرى):
To generate images from captions call the /image API: <img src="https://huggingface.co/image?caption=photo of something in some place" />
يمكنك أيضًا أن تحاول أن تكون أكثر تحديدًا، على سبيل المثال:
Only generate a few images and use descriptive photo captions with at least 10 words!

إضافة بعض واجهة المستخدم
Alpine.js هو إطار عمل بسيط يسمح لنا بإنشاء واجهات مستخدم تفاعلية دون الحاجة إلى أي إعداد أو إنشاء مسار أو معالجة JSX وما إلى ذلك.
يتم كل شيء داخل الصفحة، مما يجعلها مرشحًا رائعًا لإنشاء واجهة المستخدم للعرض التوضيحي السريع.
إليك صفحة HTML ثابتة يمكنك وضعها /public/index.html:
<html>
<head>
<title>Tutorial</title>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
<div class="flex flex-col space-y-3 p-8" x-data="{ draft: '', prompt: '' }">
<textarea
name="draft"
x-model="draft"
rows="3"
placeholder="Type something.."
class="font-mono"
></textarea>
<button
class="bg-green-300 rounded p-3"
@click="prompt = draft">Generate</button>
<iframe :src="`/app?prompt=${prompt}`"></iframe>
</div>
</body>
</html>
لإنجاز هذا العمل، سيتعين عليك إجراء بعض التغييرات:
...
app.use(express.static('public'))
app.get('/app', async (req, res) => {
...
تحسين الإخراج
لقد قمنا حتى الآن بإنشاء تسلسلات كاملة من فئات الأداة المساعدة Tailwind، والتي تعتبر رائعة لمنح حرية التصميم لنموذج اللغة.
لكن هذا النهج أيضًا مطول جدًا، ويستهلك جزءًا كبيرًا من حصتنا المميزة.
ولجعل الإخراج أكثر كثافة، يمكننا استخدام Daisy UI، وهو مكون إضافي لـ Tailwind يقوم بتنظيم فئات أدوات Tailwind في نظام تصميم. تتمثل الفكرة في استخدام أسماء فئات مختصرة للمكونات وفئات المرافق للباقي.
قد لا تمتلك بعض نماذج اللغات معرفة داخلية بـ Daisy UI لأنها مكتبة متخصصة، وفي هذه الحالة يمكننا إضافة وثائق API إلى الموجه:
# DaisyUI docs
## To create a nice layout, wrap each article in:
<article class="prose"></article>
## Use appropriate CSS classes
<button class="btn ..">
<table class="table ..">
<footer class="footer ..">
نذهب أبعد من ذلك
تتضمن المساحة التجريبية النهائية مثالاً أكثر اكتمالاً لواجهة المستخدم.
فيما يلي بعض الأفكار للتوسع في هذا المفهوم:
- اختبر نماذج اللغات الأخرى مثل StarCoder
- إنشاء ملفات وأكواد للغات الوسيطة (React، Svelte، Vue..)
- دمج إنشاء التعليمات البرمجية داخل إطار عمل موجود (مثل NextJS)
- التعافي من عملية إنشاء التعليمات البرمجية الفاشلة أو الجزئية (على سبيل المثال، مشكلات الإصلاح التلقائي في JS)
- قم بتوصيله بمكون إضافي لبرنامج chatbot (على سبيل المثال، قم بتضمين إطارات iframe صغيرة لتطبيق الويب في مناقشة الدردشة)
