Discourse AI용 맞춤형 도구로 활용되는 FLUX.1 Kontext Max

지난주 Flux는 FLUX.1 Kontext라는 매우 인상적인 모델을 출시했습니다.

Black Forest Labs 공지 블로그

이 모델은 디자이너 페르소나를 통해 이용 가능한 OpenAI 모델보다 약간 저렴하면서도 뛰어난 결과를 제공한다는 점에서 특히 흥미롭습니다.

실제 동작 모습

https://discuss.samsaffron.com/discourse-ai/ai-bot/shared-ai-conversations/XxzK8W8lzxLOzzmm7F-ngQ

이 글에서는 해당 도구를 추가하는 방법과 Discourse AI의 고급 기능 중 몇 가지를 자세히 살펴보겠습니다.

작업을 수행하는 도구

도구를 정의하려면 https://bfl.ai에 가입하고 API 키를 생성한 후 크레딧을 구매해야 합니다.

준비가 완료되면:

/admin/plugins/discourse-ai/ai-tools에서 새로운 커스텀 도구를 정의합니다.

설명(Description)

고급 이미지 생성기 및 편집기 - upload://… 로 표시된 Discourse 업로드를 편집할 수 있습니다.

요약(Summary)

FLUX Kontext를 사용하여 이미지를 편집하거나 생성합니다.

매개변수(Parameters)

  • prompt: string: 생성하려는 내용을 설명합니다. 2~3문장으로, 최상의 결과를 위해 자세히 기술하세요 (필수)
  • input_image: string: 수정하려는 upload://… 경로
  • seed: number: 랜덤 시드. 동일한 스타일의 출력을 유지하려면 이 숫자를 동일하게 유지하세요
  • aspect_ratio: string: 이미지의 종횡비입니다. 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 request failed with status ${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: "Image generated successfully", 
    seed: seed,
    aspect_ratio: params.aspect_ratio || "16:9",
    output_image: image?.short_url
  };
}

function details() {
  return "Generated image using Segmind's Flux Kontext Max model";
}

코멘터리

이 예시는 https://github.com/discourse/discourse-ai/pull/1391에 포함된 여러 추가 기능 등, 보다 고급적인 도구 기능을 보여줍니다. 이 기능이 작동하려면 해당 변경 사항이 선행되어야 합니다.

  1. http.post를 사용한 POST 요청 — 커스텀 도구는 어떤 URL로든 POST 요청을 보낼 수 있습니다!
const result = http.post(apiUrl, {
  headers: {
    "x-key": apiKey,
    "Content-Type": "application/json"
  },
  body: JSON.stringify(body)
});
  1. API에서 Base64 인코딩된 페이로드 지원

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는 폴링(polling)을 포함합니다. Discourse AI는 폴링 사이에 대기할 수 있도록 sleep 원시 함수를 제공합니다:
while (pollResult.status === "Pending" && checks < 30) {
  sleep(1000);
  pollResult = JSON.parse(http.get(pollingUrl).body);
  checks++;
}

이 글이 도움이 되기를 바랍니다! 질문이나 아이디어를 자유롭게 공유해 주세요!

4개의 좋아요