واجهات برمجة تطبيقات الذكاء الاصطناعي المدمجة: الإجراءات المسموح بها وغير المسموح بها

Published: April 30, 2026

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

إعداد النموذج في وقت مبكر

ينطبق على: جميع واجهات برمجة التطبيقات، مثل Summarizer وTranslator وWriter

الإجراء: ابدأ الجلسة فور التعرّف على نية المستخدم. بما أنّه يجب أن يفعّل المستخدم الجلسة لبدئها، يمكنك استخدام أي تفاعل، مثلاً، النقر في أي مكان على الصفحة التي تقدّم ميزة بالاستناد إلى الذكاء الاصطناعي. يؤدي ذلك إلى إعداد النموذج ووقت التشغيل أثناء تفاعل المستخدم مع واجهة المستخدم. عندما يكون ذلك مناسبًا، ابدأ مهمة الذكاء الاصطناعي التالية الأكثر احتمالاً فور بدء عرض النتيجة.

الإجراء الذي يجب تجنُّبه: لا تنتظر حتى ينقر المستخدم على "إنشاء" لبدء الجلسة. يؤدي ذلك إلى تأخير تشغيل على البارد لعدة ثوانٍ، لأنّه يجب أولاً تحميل النموذج في الذاكرة وإعداد مسار التنفيذ.

ضبط الطلبات الأولية أثناء الإنشاء

ينطبق على: Prompt API

الإجراء: قدِّم تعليمات النظام أثناء بدء الجلسة لتحسين سرعة الطلب الأول.

الإجراء الذي يجب تجنُّبه: لا تبدأ بجلسة فارغة وأرسِل تعليمات النظام كجزء من أول استدعاء لـ prompt(). يؤدي ذلك إلى زيادة وقت الاستجابة لأنّه يجبر النموذج على معالجة هذه التعليمات في اللحظة الأخيرة.

// ✅ DO: Create the session as early as possible (tip on warming up the model early) and use initialPrompts for system instructions in the create call
const session = await LanguageModel.create({
  initialPrompts: [
    { role: 'system', content: 'You are a helpful assistant specialized in code reviews.' }
  ]
});

// A few moments later, when the user triggers the AI feature
const review = await session.prompt(`Review the following code:\n\n${code}`);

// ❌ DON'T: Send instructions using prompt() after creation
// const slowerSession = await LanguageModel.create();
// await slowerSession.prompt(`You are a helpful assistant specialized in code reviews.\n\nReview the following code:\n\n${code}`); // Higher latency

استنساخ الجلسات للمهام المتكررة

ينطبق على: Prompt API

بالنسبة إلى Prompt API، تتتبّع كل جلسة سياق المحادثة، مع أخذ جميع التفاعلات السابقة في الاعتبار. بما أنّ النسخة المستنسخة ترث كل شيء من الجلسة الرئيسية، بما في ذلك الطلبات الأولية وجميع سجلّ التفاعلات حتى نقطة الاستنساخ، يمكنك تنظيم استخدامك لكي ترث ما تحتاجه فقط.

الإجراء:

  • إنشاء جلسة أساسية: للتعامل مع المهام غير ذات الصلة بكفاءة، أنشئ جلسة أساسية لا تحتوي إلا على تعليمات النظام ولا تتضمّن أي سياق محادثة سابق.
  • استنساخ خط الأساس: استخدِم clone() في هذه الجلسة الأساسية للمهام الجديدة لتوفير النفقات العامة لإعادة تحليل تعليمات النظام الكبيرة. يتيح لك ذلك إنشاء محادثات متوازية أو إعادة ضبط مهمة إلى خطها الأساسي.

الإجراء الذي يجب تجنُّبه:

  • لا تُعِد استخدام الجلسة نفسها للمهام غير ذات الصلة، وتجنَّب استنساخ أي جلسة تحتوي على سجلّ تفاعلات غير ضروري. يمكن أن يؤدي كلا النمطَين إلى تداخُل السياق السابق غير ذي الصلة مع مهمتك الحالية.
  • لا تستدعِ create() بشكل متكرّر باستخدام تعليمات النظام المتطابقة والكبيرة. استخدِم نمط الاستنساخ بدلاً من ذلك لتحسين الأداء.
// ✅ DO: Create a baseline session and clone it for each new task
const baseSession = await LanguageModel.create({
  initialPrompts: [{
    role: 'system',
    content: 'You are a technical editor...',
  }],
});

// Clone the base session once for the first task
const task1 = await baseSession.clone();
const response1 = await task1.prompt("Review this first draft...");
// ... Repeat the cloning pattern for subsequent independent tasks
// Each task starts fresh from the baseline system instructions

// ❌ DON'T:
// Bad performance pattern: repeated create() calls for identical tasks.
// This forces the model to re-parse instructions every time, increasing latency.
// const sessionA = await LanguageModel.create({ initialPrompts: [...] });
// await sessionA.prompt("Task 1...");
// const sessionB = await LanguageModel.create({ initialPrompts: [...] });
// await sessionB.prompt("Task 2...");
// Bad quality pattern: reusing the same session for unrelated tasks.
// const session = await LanguageModel.create();
// await session.prompt("Analyze this financial report...");
// Unrelated task in the same session:
// await session.prompt("Now write a children's story...");

إيقاف الجلسات غير المستخدَمة

ينطبق على: جميع واجهات برمجة التطبيقات

الإجراء: استدعِ destroy() بشكل صريح في الجلسات التي لم تعُد بحاجة إليها، لتحرير الذاكرة عندما لا تعود إحدى الميزات قيد الاستخدام. إذا كنت تستخدم نمط الاستنساخ، احتفِظ بالجلسة الأساسية وأوقِف النسخ المستنسخة التي لم تعُد بحاجة إليها.

الإجراء الذي يجب تجنُّبه: لا تُبقِ جلسات كبيرة متعددة نشطة. تستهلك كل جلسة الذاكرة، ما يؤدي إلى استخدام غير ضروري للموارد وقد يصبح مشكلة. سيتم تنظيف الجلسات بشكل طبيعي من خلال أداة جمع البيانات غير الضرورية، ولكنّ استدعاء destroy() يحرّر الذاكرة بسرعة أكبر.

// ✅ DO: Use the clone and destroy it immediately after
const clone = await baseSession.clone();
const response = await clone.prompt("Quick task...");
// Free memory right away: destry the clone, keep the baseSession
clone.destroy();

عرض الردود المتدفقة بأمان وكفاءة

ينطبق على: جميع واجهات برمجة التطبيقات التي تتيح ميزة التدفق (Prompt وSummarizer وWriter وRewriter وTranslator)

الإجراء: تعامَل مع جميع نواتج النماذج اللغوية الكبيرة على أنّها محتوى غير موثوق به. نظِّف الناتج المجمّع الكامل، وليس الأجزاء فقط، لأنّه يمكن تقسيم الرمز البرمجي الضار بين التعديلات. قبل العرض، استخدِم Sanitizer API حيثما كانت متوافقة. لتجنُّب انخفاض الأداء، استخدِم محلِّلاً لعلامات Markdown المتدفقة مثل streaming-markdown.

الإجراء الذي يجب تجنُّبه: لا تضبط innerHTML مباشرةً في كل تعديل لجزء. يكون ذلك بطيئًا، خاصةً مع التنسيق المعقّد، مثل تمييز البنية، وعرضةً للهجمات.

import * as smd from "streaming-markdown";
// Set up virtual buffer and Sanitizer API
const sanitizer = new Sanitizer({
  allowElements: ['figure', 'figcaption', 'p', 'br', 'strong', 'em', 'img', 'a'],
  allowAttributes: {
    'loading': ['img'], 'decoding': ['img'], 'src': ['img'], 'href': ['a']
  }
});

// Create an off-screen fragment so the parser doesn't cause flicker
// or trigger XSS in the live DOM during the building process.
const buffer = new DocumentFragment();
const parser = smd.parser_new(buffer);

// Use sanitizer as a gatekeeper / cleaner function so we can combine it with the streaming Markdown parser
function syncSanitized(target, sourceFragment) {
  // .sanitize() returns a fresh, clean DocumentFragment
  const cleanFragment = sanitizer.sanitize(sourceFragment);
  // replaceChildren is the modern high-performance way to swap DOM content
  target.replaceChildren(cleanFragment);
}

// Streaming Logic
// `chunks` keeps track of the raw string (useful for logs/debug)
chunks += chunk;
// Let the parser build the DOM incrementally in the buffer.
// This is high-performance because the buffer is not live
smd.parser_write(parser, chunk);
// Use the Sanitizer API to port the content safely to the container.
syncSanitized(container, buffer);

تحسين الإدخال لزيادة السرعة

ينطبق على: جميع واجهات برمجة التطبيقات

الإجراء: لا تُمرِّر إلى النموذج إلا ما هو ضروري للغاية. أزِل كل ما لا صلة له بالمهمة الحالية. بالنسبة إلى مجموعات البيانات الكبيرة، قدِّم نظرة عامة قصيرة ومجموعة صغيرة من العناصر ذات الصلة.

الإجراء الذي يجب تجنُّبه: لا تُرسِل إلى واجهات برمجة التطبيقات نصًا أوليًا غير مُعالَج أو بيانات وصفية غير ضرورية أو علامات HTML أو قوائم كبيرة غير مفلترة. يزداد وقت الاستجابة بشكل كبير مع حجم الإدخال، ما قد يجعل ميزة الذكاء الاصطناعي تبدو معطّلة على العديد من الأجهزة.

// ✅ DO: Send only relevant text
const cleanText = document.querySelector('#article').innerText;
const summary = await Summarizer.summarize(cleanText);

// ❌ DON'T: Send the entire DOM structure
// const dirtyText = document.querySelector('#article').innerHTML;

استخدام ناتج منظَّم للحصول على نتائج يمكن التنبؤ بها

ينطبق على: Prompt API

الإجراء: عندما تحتاج إلى أن يعرض النموذج بيانات بتنسيق معيّن، استخدِم ناتجًا منظَّمًا من خلال تقديم حقل responseConstraint لتوفير JSON Schema. يضمن ذلك أن يكون الناتج قابلاً للتنبؤ به ويمنعك من الحاجة إلى المعالجة اللاحقة المعقّدة أو التحليل اليدوي.

الإجراء الذي يجب تجنُّبه: لا تعتمِد على تعليمات اللغة الطبيعية (مثل "عرض JSON فقط") وحدها. قد تتضمّن النماذج حشوًا حواريًا يؤدي إلى إيقاف المحلِّل.

// ✅ DO: Use a JSON Schema for predictable results
const schema = {
  type: "object",
  properties: {
    isTopicCats: { type: "boolean" }
  }
};

const result = await session.prompt(`Is this post about cats?\n\n${post}`, {
  responseConstraint: schema,
});
console.log(JSON.parse(result).isTopicCats);

فصل عملية الإنشاء عن قيود الطول

ينطبق على: Prompt API، لأنّها واجهة برمجة التطبيقات الوحيدة التي تتيح مخططات الناتج المنظَّم.

الإجراء: اسمح للنموذج بإنشاء ردّه بشكل طبيعي، ثم استخدِم منطقًا من جهة العميل لقص النص ليناسب واجهة المستخدم.

الإجراء الذي يجب تجنُّبه: لا تفرِض حدودًا صارمة على عدد الأحرف، مثل maxLength: 125 باستخدام مخططات الناتج المنظَّم. عندما يكون ردّ النموذج أطول من الحدّ الذي ضبطته، قد ينتقل النموذج إلى الرموز المميّزة عالية الكثافة، مثل اللغات الأجنبية أو الرموز التعبيرية، لضغط المعنى، ما يؤدي إلى ناتج غير منطقي.

/*  DO: Handle overflow using CSS */
.result {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis; /* Displays '…' */
}
// ❌ DON'T: Force length in the prompt
const result = await session.prompt("Write a bio in exactly 50 characters.");

إدارة صبر المستخدم

ينطبق على: جميع واجهات برمجة التطبيقات

الإجراء: استخدِم الصور المتحركة وتقنيات واجهة المستخدم لإدارة صبر المستخدم. يعتمد النهج الأمثل على حالة الاستخدام والطول المتوقّع لناتج واجهة برمجة التطبيقات. بعض الأفكار:

  • التدفق للمحتوى الطويل: بالنسبة إلى الملخّصات أو المحادثات، يؤدي التدفق إلى إنشاء تأثير آلة كاتبة لكل رمز مميّز تلقائيًا. قد يبدو ذلك طبيعيًا ويقدّم ملاحظات فورية.
  • عدم التدفق للمهام القصيرة (أو المهام الطويلة غير المتزامنة): بالنسبة إلى النواتج القصيرة، مثلاً، النص البديل، يمكن أن يؤدي عدم التدفق إلى إنشاء واجهة مستخدم أكثر دقة. ويوفّر أيضًا وقتًا لإعداد مهمة الذكاء الاصطناعي التالية بشكل استباقي أثناء عرض المهمة الحالية. ينطبق هذا النهج أيضًا على المهام غير المتزامنة أو المهام التي يتم تنفيذها في الخلفية الأطول. إذا لم يتم حظر المستخدم من الناتج لمواصلة رحلته، ما مِن حاجة ملحّة لإنتاج الناتج أثناء حدوثه. أشِر إلى أنّ العملية قيد التنفيذ في واجهة المستخدم.
  • الانتقالات المرئية للتعديلات: عند ترجمة النص أو إعادة كتابته، استخدِم الصور المتحركة، مثلاً، تغيير شكل الكلمات.

الإجراء الذي يجب تجنُّبه: لا تُعدِّل واجهة المستخدم بدون إشارات مرئية.

التوافق مع النموذج الذهني للمستخدم للوقت والعمل

ينطبق على: جميع واجهات برمجة التطبيقات

الإجراء: ضع في اعتبارك تأخيرًا اصطناعيًا لمدة ثانية أو ثانيتَين إذا كان الردّ فوريًا تقريبًا. على نحو متناقض، قد يجد المستخدمون النتائج أكثر جدارة بالثقة عندما يرون عملية إنشاء تتوافق مع الصعوبة التي يتصوّرونها للمهمة. استخدِم الصور المتحركة للإشارة إلى حدوث عملية بالاستناد إلى الذكاء الاصطناعي.

الإجراء الذي يجب تجنُّبه: لا تفاجئ المستخدمين بعمليات استبدال فورية لواجهة المستخدم.

السماح للمستخدمين بالتنقّل بسرعة بين التعديلات التي تم إجراؤها بالاستناد إلى الذكاء الاصطناعي والتراجع عنها

ينطبق على: جميع واجهات برمجة التطبيقات

الإجراء: زوِّد واجهة المستخدم بمؤشر أو سجلّ تنقّل يتيح للمستخدمين استكشاف نتائج مختلفة بثقة، والسماح لهم بالتراجع بسرعة عن التعديلات التي تم إجراؤها بالاستناد إلى الذكاء الاصطناعي. يضمن ذلك أن تظل النُسخ المختلفة متاحة بسهولة.

الإجراء الذي يجب تجنُّبه: لا تكتب فوق المسودة السابقة للمستخدم أو نتيجة بالاستناد إلى الذكاء الاصطناعي قد تكون أعجبته بدون طريقة للرجوع أو الاستعادة أو المقارنة بين النُسخ.

عنصر واجهة مستخدم "الخطوات" يعرض سجلّ التنقّل.
نمط واجهة المستخدم: رفض الاقتراح / قبوله (مستندات Google)
زر التراجع عن جميع تعديلات الوكيل في واجهة مستخدم Google Antigravity
نمط واجهة المستخدم: التراجع عن جميع تعديلات البرنامج (Google Antigravity)
أزرار رفض الاقتراح أو قبوله في "مستندات Google"
نمط واجهة المستخدم: المؤشر (عرض توضيحي للنص البديل)

تعزيز تحكّم المستخدم وعمليات الإلغاء

ينطبق على: جميع واجهات برمجة التطبيقات

الإجراء: اسمح دائمًا للمستخدم باتخاذ القرار النهائي. قدِّم طريقة لتجاوز الاقتراحات يدويًا. قد تقدّم واجهات برمجة التطبيقات نتائج غير صحيحة.

الإجراء الذي يجب تجنُّبه: لا تفرِض نتيجة تم إنشاؤها بالاستناد إلى الذكاء الاصطناعي كخيار وحيد.

تخزين النتائج مؤقتًا للمهام المتكررة

ينطبق على: جميع واجهات برمجة التطبيقات

الإجراء: نفِّذ ذاكرة تخزين مؤقتة محلية للنتائج (على سبيل المثال، باستخدام sessionStorage أو IndexedDB) للإدخالات أو طلبات البحث المتكررة. يمكنك تنسيق الإدخال عن طريق إزالة المسافات البيضاء وتحويل الأحرف إلى صغيرة لزيادة عدد النتائج التي يتم العثور عليها في ذاكرة التخزين المؤقت. بالنسبة إلى الإدخالات الكبيرة، مثلاً، الصور، أنشئ رمزًا هشًا لاستخدامه كمفتاح لذاكرة التخزين المؤقت. اضبط مدة بقاء (TTL) متحفظة لذاكرة التخزين المؤقت (أو اعرض النتائج المخزّنة مؤقتًا أثناء تعديلها في الخلفية). اسمح للمستخدم بتشغيل استنتاج جديد إذا كانت النتيجة غير مرضية.

الإجراء الذي يجب تجنُّبه: لا تعِد تشغيل الاستنتاج نفسه لطلب بحث متكرّر أو إدخال بيانات متطابقة ، مثلاً، عندما يتنقّل المستخدم ذهابًا وإيابًا بين نتائج البحث. على الرغم من أنّ الاستنتاج على الجهاز فقط مجاني من حيث التكاليف المستندة إلى السحابة الإلكترونية، فإنّه مكلف من حيث وقت المستخدم وعمر البطارية.

// ✅ DO: Check a local cache before running inference
async function getAiResponse(userInput, forceRefresh = false) {
  // Normalize the query to increase cache hits
  const query = userInput.trim().toLowerCase();
  const cacheKey = `ai_results_${query}`;
  const TTL_MS = 3600000; // 1 hour conservative TTL

  if (!forceRefresh) {
    const itemStr = localStorage.getItem(cacheKey);
    if (itemStr) {
      const item = JSON.parse(itemStr);
      const now = Date.now();

      // Check if the item has expired
      if (now < item.expiry) {
        // Lightweight safety check before rendering
        if (isValid(item.value)) return item.value;
      } else {
        // Delete the stale entry if the TTL has passed
        localStorage.removeItem(cacheKey);
      }
    }
  }

  // Fallback: Run inference if no valid cache exists
  const session = await LanguageModel.create();
  const response = await session.prompt(userInput);

  // Store the result for future use (with an expiration)
  const cacheData = {
    value: response,
    expiry: Date.now() + TTL_MS
  };
  localStorage.setItem(cacheKey, JSON.stringify(cacheData));

  return response;
}