FLUX.1 Kontext Max как пользовательский инструмент для Discourse AI

На прошлой неделе Flux выпустила очень впечатляющую модель под названием FLUX.1 Kontext.

Блог с анонсом от Black Forest Labs

Она особенно интересна тем, что немного дешевле моделей OpenAI, которые доступны через персону дизайнера, и при этом демонстрирует отличные результаты.

В действии

В этом посте я хочу поделиться тем, как можно добавить этот инструмент, и продемонстрировать некоторые расширенные функции Discourse AI.

Инструмент для выполнения задачи

Чтобы определить инструмент, вам нужно зарегистрироваться на https://bfl.ai, сгенерировать API-ключ и приобрести кредиты.

После этого:

Определите новый пользовательский инструмент в /admin/plugins/discourse-ai/ai-tools

Описание

Продвинутый создатель и редактор изображений — способен редактировать загрузку Discourse, обозначенную как upload://…

Краткое описание

Редактирует или создаёт изображения с помощью FLUX Kontext

Параметры

  • prompt: строка: Опишите, что вы хотите сгенерировать. 2–3 предложения, будьте подробны для лучших результатов (обязательно)
  • input_image: строка: загрузка upload://…, которую вы хотите изменить
  • seed: число: Случайное зерно. Если вы хотите сохранять выход в одном стиле, оставляйте число неизменным
  • aspect_ratio: строка: Соотношение сторон изображения, должно быть от 21:9 до 9:21. Для квадратных изображений используйте 1:1. По умолчанию 16:9

Скрипт

const apiKey = YOUR_API_KEY;
const apiUrl = "https://api.us1.bfl.ai/v1/flux-kontext-max"; 

function invoke(params) {
  let seed = parseInt(params.seed);
  if (!(seed > 0)) {
    seed = Math.floor(Math.random() * 1000000) + 1;
  }

  const body = {
    prompt: params.prompt,
    seed: seed,
    aspect_ratio: params.aspect_ratio || "16:9"
  };

  // Добавьте input_image, если он предоставлен
  if (params.input_image) {
    body.input_image = upload.getBase64(params.input_image);
  }

  const result = http.post(apiUrl, {
    headers: {
      "x-key": apiKey,
      "Content-Type": "application/json"
    },
    body: JSON.stringify(body)
  });

  if (result.status !== 200) {
    return { error: `Запрос API не удался со статусом ${result.status}`, body: body };
  }
  
  const parsed = JSON.parse(result.body);
  const pollingUrl = parsed.polling_url;
  
  let pollResult = JSON.parse(http.get(pollingUrl).body);
  let checks = 0;
  
  while (pollResult.status === "Pending" && checks < 30) {
      sleep(1000);
      pollResult = JSON.parse(http.get(pollingUrl).body);
      checks++;
  } 
  
  let image;
  
  if (pollResult.status === "Ready") {
      const imageUrl = pollResult.result.sample;
      const base64 = http.get(imageUrl, { base64Encode: true }).body;
      image = upload.create("generated_image.jpg", base64);
      
      const raw = `\n\n![${params.prompt}](${image.short_url})`;
  
      chain.setCustomRaw(raw);
   }
  
  return { 
    result: "Изображение успешно сгенерировано", 
    seed: seed,
    aspect_ratio: params.aspect_ratio || "16:9",
    output_image: image?.short_url
  };
}

function details() {
  return "Сгенерировано изображение с использованием модели Flux Kontext Max от Segmind";
}

Комментарии

Это демонстрирует некоторые из более продвинутых возможностей инструментов, включая несколько, добавленных в https://github.com/discourse/discourse-ai/pull/1391, которые потребуются перед тем, как это заработает.

  1. Отправка POST-запросов с помощью http.post — пользовательские инструменты могут отправлять запросы на любой URL!
const result = http.post(apiUrl, {
  headers: {
    "x-key": apiKey,
    "Content-Type": "application/json"
  },
  body: JSON.stringify(body)
});
  1. Поддержка полезной нагрузки в формате base64 в API

Получение загрузки в формате Base64:

body.input_image = upload.getBase64(params.input_image);

Получение результата HTTP-запроса в формате Base64:

const base64 = http.get(imageUrl, { base64Encode: true }).body;

Создание загрузки из строки base64:

image = upload.create("generated_image.jpg", base64);
  1. Принудительный рендеринг в сообщении, чтобы избежать догадок и сэкономить токены:
chain.setCustomRaw(raw);
  1. API предполагает опрос; Discourse AI предоставляет примитив sleep для ожидания между опросами:
while (pollResult.status === "Pending" && checks < 30) {
  sleep(1000);
  pollResult = JSON.parse(http.get(pollingUrl).body);
  checks++;
}

Надеюсь, это окажется полезным! Не стесняйтесь задавать вопросы или делиться идеями!

4 лайка