Довідник API ШІ.

Вивчення DXPR BuilderРозширенняАрхітектура та API

DXPR Builder відкриває три маршрути ШІ. Браузер їх викликає, а контролери проксіюють запит через модуль AI Drupal до провайдера DXPR (ai_provider_dxpr), тож ключ API ніколи не досягає браузера. Маршрути визначено в dxpr_builder.routing.yml; поведінка нижче походить із src/Controller/AiChatController.php і src/Controller/AiImageController.php.

Панель Generate content із промптом Add a paragraph with 3 feature boxes, посиланнями Enhance prompt і Chat mode, кнопкою Generate content і кнопками Choose a template і Add Elements

Вимоги доступу (усі три маршрути)

Вимога Джерело
Метод 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. Мусить бути в списку Allowed models провайдера
stream булеве ні Типово true
prediction об’єкт ні Пропускається наскрізь, наприклад {"type":"content","content":"<p>...</p>"}
providers рядок ні Розділені комами ID провайдерів, наприклад openai,mistral
allowed_html_tags рядок ні Пропускається наскрізь; конструктор надсилає Bootstrap 5 HTML
allowed_html_classes рядок ні Пропускається наскрізь; конструктор надсилає Bootstrap 5 Classes
web_search булеве ні Лише false пересилається
response_format об’єкт ні Пропускається наскрізь, наприклад json_schema-об’єкт

Контролер завжди додає jsonrpc: false до конфігурації провайдера. Перед викликом він об’єднує домени з AI Output Filtering > Allowed domains у фільтр імен хостів модуля AI на час запиту (* перемикає фільтр на повну довіру).

Відповідь

Потоково (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 немає в його списку Allowed models
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.

Що далі?