지난주 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`;
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에 포함된 여러 추가 기능 등, 보다 고급적인 도구 기능을 보여줍니다. 이 기능이 작동하려면 해당 변경 사항이 선행되어야 합니다.
http.post를 사용한 POST 요청 — 커스텀 도구는 어떤 URL로든 POST 요청을 보낼 수 있습니다!
const result = http.post(apiUrl, {
headers: {
"x-key": apiKey,
"Content-Type": "application/json"
},
body: JSON.stringify(body)
});
- 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);
- 추측을 피하고 토큰을 절약하기 위해 포스트의 렌더링 강제:
chain.setCustomRaw(raw);
- API는 폴링(polling)을 포함합니다. Discourse AI는 폴링 사이에 대기할 수 있도록
sleep원시 함수를 제공합니다:
while (pollResult.status === "Pending" && checks < 30) {
sleep(1000);
pollResult = JSON.parse(http.get(pollingUrl).body);
checks++;
}
이 글이 도움이 되기를 바랍니다! 질문이나 아이디어를 자유롭게 공유해 주세요!

