مرجع API للذكاء الاصطناعي.
يكشف DXPR Builder عن ثلاثة مسارات ذكاء اصطناعي. فيستدعيها المتصفح،
وتُمرّر المتحكمات الطلب عبر وحدة الذكاء الاصطناعي في Drupal إلى موفّر DXPR
(ai_provider_dxpr)، فلا يصل مفتاح API أبدًا إلى
المتصفح. والمسارات معرّفة في
dxpr_builder.routing.yml؛ والسلوك أدناه صادر عن
src/Controller/AiChatController.php و
src/Controller/AiImageController.php.

متطلبات الوصول (المسارات الثلاثة كلها)
| المتطلب | المصدر |
|---|---|
طريقة HTTP POST |
methods: [POST] في المسار |
الصلاحية edit with dxpr builder |
_permission |
| مستخدم مُحاسَب (مقعد ترخيص صالح) | _dxpr_builder_billable_user، يتحقق منه DxprBuilderBillableUserAccessCheck |
رمز CSRF في token من معامل الاستعلام |
_csrf_token: 'TRUE' |
| كوكي جلسة Drupal لمستخدم مسجل | تعمل فحوصات وصول Drupal لكل مستخدم |
الرمز هو رمز CSRF الخاص بمسار Drupal لمسار المسار. ويولّده DXPR Builder من جهة
الخادم ويضمّنه في drupalSettings.dxprBuilder.aiAgent
كـ endpointUrl وimageEndpointUrl و
imageEditEndpointUrl (انظر
DxprBuilderFormatter). اقرؤوا إحدى تلك القيم
من صفحة يُحمَّل فيها المحرّر للحصول على
URL يعمل. ويعيد فحص الوصول الفاشل استجابة
403 المعيارية في Drupal.
تُنشئ المتحكمات دائمًا موفّر dxpr؛ فالموفّر المضبوط في
/admin/config/ai/settings لا يُستخدم.
المحادثة
POST /dxpr_builder/ajax/ai/chat?token=...
تستخدمه أوامر النصوص وإنشاء الصفحات واقتراحات
الأوامر. فيقرأ المتحكم متن JSON
ويستدعي $provider->chat().
متن الطلب
| الحقل | النوع | مطلوب | ملاحظات |
|---|---|---|---|
messages |
مصفوفة من {role, content} |
نعم | role هو system أو user أو assistant |
model |
سلسلة | لا | الافتراضي kavya-m1. ويجب أن يكون في قائمة النماذج المسموحة لدى الموفّر |
stream |
منطقي | لا | الافتراضي true |
prediction |
كائن | لا | يُمرَّر كما هو، مثلًا {"type":"content","content":"<p>...</p>"} |
providers |
سلسلة | لا | معرّفات موفّرين مفصولة بفواصل، مثلًا openai,mistral |
allowed_html_tags |
سلسلة | لا | يُمرَّر كما هو؛ فيرسل المنشئ Bootstrap 5 HTML |
allowed_html_classes |
سلسلة | لا | يُمرَّر كما هو؛ فيرسل المنشئ Bootstrap 5 Classes |
web_search |
منطقي | لا | تُمرَّر القيمة false فقط |
response_format |
كائن | لا | يُمرَّر كما هو، مثلًا json_schema ككائن |
يضيف المتحكم دائمًا jsonrpc: false إلى
إعدادات الموفّر. وقبل الاستدعاء يدمج
النطاقات من ترشيح مخرجات الذكاء الاصطناعي > النطاقات
المسموحة في مرشّح أسماء المضيفين الخاص بوحدة الذكاء الاصطناعي لمدة
الطلب (* يحوّل المرشّح
إلى ثقة كاملة).
الاستجابة
متدفقة (stream بقيمة true، وهي الافتراضية):
200، Content-Type: text/event-stream. فكل
حدث هو data: {json} متبوعًا بسطر فارغ،
وينتهي التدفق بـ data: [DONE].
data: {"choices":[{"delta":{"content":"Hello"}}],"id":"...","model":"kavya-m1","usage":{...}}
data: [DONE]
id وobject وcreated وmodel و
original_model وusage تُنسخ من القطعة الخام للموفّر عند وجودها.
غير متدفقة (stream بقيمة false): 200،
application/json:
{"choices":[{"message":{"role":"assistant","content":"..."}}]}
الأخطاء
| الحالة | المتن |
|---|---|
400 |
نص عادي Invalid request: messages required |
403 |
{"error":{"code":"model_not_allowed","message":"The selected model is not allowed. Please refresh the page to update your model options."}} عندما تكون ai_provider_dxpr مثبّتة وmodel ليس في قائمة النماذج المسموحة الخاصة بها |
500 |
{"error":{"message":"The request could not be completed."}} (التفاصيل في قناة سجل dxpr_builder) |
مثال
const url = drupalSettings.dxprBuilder.aiAgent.endpointUrl;
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "kavya-m1",
stream: false,
messages: [
{ role: "system", content: "You are a copywriter." },
{ role: "user", content: "Shorten: <p>Our team ...</p>" }
]
})
});
const data = await res.json();
console.log(data.choices[0].message.content);
توليد الصور
POST /dxpr_builder/ajax/ai/image?token=...
يستدعي $provider->textToImage().
متن الطلب
| الحقل | النوع | مطلوب | ملاحظات |
|---|---|---|---|
prompt |
سلسلة | نعم | وصف نصي للصورة |
model |
سلسلة | لا | الافتراضي kavya-image |
size |
سلسلة | لا | يرسل المنشئ 1024x1024 أو 1536x1024 أو 1024x1536؛ ويُحذَف مع Auto |
quality |
سلسلة | لا | تُمرَّر إلى الموفّر دون تغيير |
background |
سلسلة | لا | تُمرَّر إلى الموفّر دون تغيير |
الاستجابة
200، application/json. تُعاد الصورة الأولى فقط،
مرمّزة base64. ويطلب موفّر DXPR مخرجات
webp.
{"data":[{"b64_json":"UklGRi..."}]}
الأخطاء
| الحالة | المتن |
|---|---|
400 |
{"error":{"message":"Invalid request: prompt required"}} |
500 |
{"error":{"message":"No image was generated"}} |
500 |
{"error":{"message":"Image generation failed. Please try again."}} |
مثال
curl -X POST "https://example.com/dxpr_builder/ajax/ai/image?token=TOKEN" \
-H "Content-Type: application/json" \
-H "Cookie: SESSxxx=..." \
-d '{"prompt":"Flat illustration of a rocket","size":"1536x1024"}'
تحرير الصور
POST /dxpr_builder/ajax/ai/image/edit?token=...
يستدعي $provider->imageToImage() مع
الصورة المرفوعة والأمر.
متن الطلب
| الحقل | النوع | مطلوب | ملاحظات |
|---|---|---|---|
prompt |
سلسلة | نعم | تعليمات التحرير |
image |
سلسلة | نعم | بيانات الصورة base64 دون بادئة data:؛ وفك ترميز صارم |
mimeType |
سلسلة | لا | الافتراضي image/png؛ ويصبح النوع الفرعي امتداد الملف |
model |
سلسلة | لا | الافتراضي kavya-image |
size وquality وbackground |
سلسلة | لا | كما في توليد الصور |
الاستجابة
الشكل نفسه كتوليد الصور:
{"data":[{"b64_json":"..."}]}.
الأخطاء
| الحالة | المتن |
|---|---|
400 |
{"error":{"message":"Invalid request: prompt and image required"}} |
400 |
{"error":{"message":"Invalid image data: base64 decode failed"}} |
500 |
{"error":{"message":"No image was generated"}} |
500 |
{"error":{"message":"Image editing failed. Please try again."}} |
مثال
const url = drupalSettings.dxprBuilder.aiAgent.imageEditEndpointUrl;
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
prompt: "Remove the background",
image: base64String,
mimeType: "image/jpeg"
})
});
const { data } = await res.json();
تخزين الصورة المولّدة
تعيد المسارات بايتات الصورة فقط. فيحوّل المنشئ
b64_json إلى ملف webp ويرفعه
إلى POST /dxpr_builder/ajax/file_upload
(drupalSettings.dxprBuilder.fileUploadUrl، حقل النموذج
upload[])، فيرد بعنصري الملف
url وfid. ويصبح الأمر اسم الملف
(أول 80 حرفًا) وسمة alt.