qwen-image-3.0-pro
복잡한 레이아웃, 글자, 사실적인 세부 표현에 중점을 둔 텍스트 기반 이미지 생성 모델입니다. 포스터, 스토리보드, 메뉴, 요소가 촘촘하게 배치된 콘텐츠에 적합합니다.
- Ailoot · 이미지
POST /v1/images/generationsqwen-image-3.0-pro - Ailoot · 이미지
POST /v1/images/generationsqwen-image - Ailoot · 이미지
POST /v1/images/generationsqwen-image-latest
모델 소개
이 설명은 모델의 기능을 다룹니다. Ailoot에서 사용할 수 있는 입력, 출력 및 옵션은 아래에 선택한 메서드별로 표시됩니다.
Qwen-Image-3.0-Pro는 구도, 글자, 작은 세부 요소가 중요한 이미지의 생성과 편집을 위한 Alibaba 모델입니다. 요소가 많은 레이아웃, 이미지 속 이미지, 신문 지면, 스토리보드, 메뉴, 학습지가 주요 활용 분야에 포함됩니다. 현재 Ailoot 카드에는 텍스트 지시에 따른 이미지 생성 모드가 표시되어 있습니다. Alibaba는 편집과 참고 이미지 사용도 제공하지만, 이러한 작업에는 입력 이미지에 대한 별도 지원이 필요하며 현재 카드의 호출 방식에는 포함되어 있지 않습니다.
이미지 속 글자와 세부 표현
개발사는 최대 4.5천 토큰의 긴 지시, 12개 언어의 글자, 여러 글꼴 사용을 강조합니다. 이는 설명된 지시 처리 능력이며, 공식 컨텍스트 윈도 크기가 공개된 것은 아닙니다. 발표된 특성에는 10픽셀 크기의 작은 글자, 피부와 머리카락의 질감, 미세한 표정 변화의 표현이 포함됩니다. 이런 세부 표현은 이미지를 가까이에서 살펴보는 자료를 준비할 때 유용합니다.
Qwen-Image-3.0-Pro는 웹 페이지, 게임, 라이브 방송 화면의 시각적 콘셉트 제작에도 사용하도록 설계되었습니다. 결과물 안에 일러스트, 화면 구조, 디자인된 글자를 결합할 수 있습니다. 모델이 만드는 것은 레이아웃 이미지이며, 작동하는 애플리케이션을 만들려면 별도로 구현해야 합니다.
Alibaba 사양에 명시된 편집
Alibaba는 편집 모드에 이미지 1~3개를 사용할 수 있다고 명시합니다. 개발사의 이 방식에서는 대상을 참고 이미지 번호와 연결하고 자료의 결합 방식을 설명할 수 있습니다. 대상 추가, 삭제, 이동, 동작, 스타일, 세부 요소, 텍스트 변경을 지원합니다. 부정 지시문으로 원하지 않는 요소를 지정할 수 있습니다.
개발사의 편집 모드는 JPG, JPEG, PNG, BMP, TIFF, WEBP, GIF 입력 자료를 지원합니다. 애니메이션 GIF는 첫 프레임을 사용합니다. 각 파일은 최대 10MB이며, 개발사는 각 변이 384~3072픽셀인 이미지를 권장합니다. 이는 입력 자료에 대한 권장 사항이며 완성된 결과물의 크기가 아닙니다.
개발사 사양에는 요청당 PNG 출력 이미지 1~6개가 명시되어 있습니다. 결과물의 면적 범위는 262 144~4 194 304픽셀이며, 정사각형 이미지로는 512 × 512~2048 × 2048에 해당합니다. 1:8~8:1의 화면 비율을 허용하므로, 길쭉한 구도의 경우 변의 길이는 선택한 화면 비율에도 영향을 받습니다. 생성 전에 지시를 추가로 다듬는 기능도 마련되어 있습니다.
Ailoot · 이미지 POST /v1/images/generations qwen-image-3.0-pro
qwen-image-3.0-proqwen-image-3.0-proqwen-imageqwen-image-latest
시작하기
복잡한 레이아웃, 글자, 사실적인 세부 표현에 중점을 둔 텍스트 기반 이미지 생성 모델입니다. 포스터, 스토리보드, 메뉴, 요소가 촘촘하게 배치된 콘텐츠에 적합합니다.
- 허용 입력
- 텍스트
- 결과
- 이미지
Ailoot에서 사용 가능 · 입력 및 메서드
Ailoot · 이미지 POST /v1/images/generations
- 입력
text- 출력
image- 출력 형식
- 이미지 파일
| 필드 | 유형 | 요건 | 값과 한도 | 기본값 |
|---|---|---|---|---|
필드model | 유형string | 요건필수 | 값과 한도 qwen-image-3.0-pro | 기본값— |
필드prompt | 유형string | 요건필수 | 값과 한도 최소 길이: 1 | 기본값— |
필드n | 유형integer | 요건선택 사항 | 값과 한도 최솟값: 1 | 기본값1 |
필드response_format | 유형string | 요건선택 사항 | 값과 한도 url, b64_json | 기본값— |
필드stream | 유형boolean | 요건선택 사항 | 값과 한도 | 기본값false |
필드size | 유형string | 요건선택 사항 | 값과 한도 모델에 따라 다름 | 기본값— |
필드partial_images | 유형integer | 요건선택 사항 | 값과 한도 모델에 따라 다름 | 기본값— |
필드images[].image_url | 유형string | 요건지원되지 않음 | 값과 한도 디코딩 후 최대 바이트 수: 10,485,760 MIME 유형: image/png, image/jpeg 배열당 최대 이미지 수: 3 조건: images[] 객체마다 실제 URL 하나를 사용합니다. 배열 항목 수와 이 문자열 말단 값은 서로 다릅니다. 적용 조건: JSON images/edits만 해당합니다. JSON images/generations는 images 참조 자료를 파싱하지 않습니다. | 기본값— |
필드image | 유형file | 요건선택 사항 | 값과 한도 디코딩 후 최대 바이트 수: 10,485,760 MIME 유형: image/png, image/jpeg 적용 조건: multipart/form-data 생성 | 기본값— |
필드image[] | 유형file[] | 요건선택 사항 | 값과 한도 최대 항목 수: 3 디코딩 후 최대 바이트 수: 10,485,760 MIME 유형: image/png, image/jpeg 적용 조건: multipart/form-data 생성 | 기본값— |
입력 자료 조합
텍스트로 이미지 생성 · 필수: prompt
reference_images_generation · 필수: prompt
메서드 매개변수와 수명 주기
| 매개변수 | 명세 |
|---|---|
매개변수material_types | 명세text |
매개변수required | 명세model, prompt |
매개변수optional_controls | 명세null |
매개변수content_type | 명세application/json |
수명 주기: synchronous_result_then_owned_library
GET /v1/media/tasks/{task_id} · 실제로 반환된 task_id 또는 미디어 라이브러리 기록
GET /v1/media/assets/{asset_id}/content
GET /v1/media/assets
GET /v1/media/assets/{asset_id}
메서드 형식과 ID는 정확합니다. 공급자의 기능 지원과 요청 수락은 별개입니다.
요금
Ailoot 메서드 요금
POST /v1/images/generations- 입력
- US$0.003 입력 이미지당
- 출력
- US$0.04 1K 이미지당
- 출력
- US$0.075 2K 이미지당
Ailoot는 요청 전에 예상 금액을 미리 확보합니다. 결과를 받은 뒤 측정된 사용량을 기준으로 최종 요금을 정산합니다. 스트리밍 정산에는 최종 사용량 기록을 사용합니다. 금액 확보와 정산 방식 →
요청 예제
Ailoot · 이미지
set -eu
: "${AILOOT_API_KEY:?Set your Ailoot API key}"
export AILOOT_API_KEY
export AILOOT_API_KEY
: "${AILOOT_PROMPT_FILE:?Set your actual UTF-8 image brief}"
export AILOOT_PROMPT_FILE
python3 - <<'PY_REQUEST'
import json,os
from pathlib import Path
p=json.loads('{"model": "qwen-image-3.0-pro", "prompt": ""}')
f=Path(os.environ["AILOOT_PROMPT_FILE"])
if not f.is_file():raise SystemExit("Choose your actual UTF-8 brief")
p['prompt']=f.read_text(encoding="utf-8")
if not p['prompt'].strip():raise SystemExit("Brief must contain text")
Path("request.json").write_text(json.dumps(p,ensure_ascii=False))
PY_REQUEST
curl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/images/generations \
-H "Authorization: Bearer $AILOOT_API_KEY" -H 'Content-Type: application/json' \
--data-binary @request.json -D response-headers.txt -o result.json
python3 - <<'PY_RESULT'
import base64, json, os, subprocess
from pathlib import Path
from urllib.parse import urlsplit, urljoin
def save_images(items):
if not items: raise SystemExit("No completed images; retain the full response")
for index, item in enumerate(items):
encoded=item.get("b64_json")
uri=item.get("url", "")
if not encoded and uri.startswith("data:image/"):
header, separator, encoded=uri.partition(",")
if not separator or ";base64" not in header: raise SystemExit("Unsupported image data URI")
if encoded:
raw=base64.b64decode(encoded,validate=True)
elif uri:
uri=urljoin("https://api.ailoot.ai",uri)
parsed=urlsplit(uri)
if parsed.scheme!="https" or not parsed.netloc or parsed.username or parsed.password:
raise SystemExit("Invalid returned image URL")
owned=parsed.netloc=="api.ailoot.ai" and parsed.path.startswith("/v1/media/assets/") and parsed.path.endswith("/content")
args=["curl","--fail-with-body","--silent","--show-error",uri]
if owned: args += ["-H","Authorization: Bearer "+os.environ["AILOOT_API_KEY"]]
temporary=Path(f"image-{index}.bin")
subprocess.run(args+["-o",str(temporary)],check=True)
raw=temporary.read_bytes()
temporary.unlink()
else: raise SystemExit("Image has neither bytes nor URL")
if not raw: raise SystemExit("Empty image result")
ext="png" if raw.startswith(b"\x89PNG") else "jpg" if raw.startswith(b"\xff\xd8") else "webp" if raw[:4]==b"RIFF" and raw[8:12]==b"WEBP" else "svg" if raw.lstrip().startswith((b"<svg",b"<?xml")) else "bin"
Path(f"image-{index}.{ext}").write_bytes(raw)
print("Every returned image saved; complete response metadata retained")
save_images(json.loads(Path("result.json").read_text())["data"])
PY_RESULT
from openai import OpenAI
import base64, json, os, subprocess
from pathlib import Path
from urllib.parse import urlsplit, urljoin
def save_images(items):
if not items: raise SystemExit("No completed images; retain the full response")
for index, item in enumerate(items):
encoded=item.get("b64_json")
uri=item.get("url", "")
if not encoded and uri.startswith("data:image/"):
header, separator, encoded=uri.partition(",")
if not separator or ";base64" not in header: raise SystemExit("Unsupported image data URI")
if encoded:
raw=base64.b64decode(encoded,validate=True)
elif uri:
uri=urljoin("https://api.ailoot.ai",uri)
parsed=urlsplit(uri)
if parsed.scheme!="https" or not parsed.netloc or parsed.username or parsed.password:
raise SystemExit("Invalid returned image URL")
owned=parsed.netloc=="api.ailoot.ai" and parsed.path.startswith("/v1/media/assets/") and parsed.path.endswith("/content")
args=["curl","--fail-with-body","--silent","--show-error",uri]
if owned: args += ["-H","Authorization: Bearer "+os.environ["AILOOT_API_KEY"]]
temporary=Path(f"image-{index}.bin")
subprocess.run(args+["-o",str(temporary)],check=True)
raw=temporary.read_bytes()
temporary.unlink()
else: raise SystemExit("Image has neither bytes nor URL")
if not raw: raise SystemExit("Empty image result")
ext="png" if raw.startswith(b"\x89PNG") else "jpg" if raw.startswith(b"\xff\xd8") else "webp" if raw[:4]==b"RIFF" and raw[8:12]==b"WEBP" else "svg" if raw.lstrip().startswith((b"<svg",b"<?xml")) else "bin"
Path(f"image-{index}.{ext}").write_bytes(raw)
print("Every returned image saved; complete response metadata retained")
f=Path(os.environ["AILOOT_PROMPT_FILE"])
if not f.is_file():raise SystemExit("Set your actual UTF-8 image brief file")
request={'model': 'qwen-image-3.0-pro', 'prompt': ''}
request["prompt"]=f.read_text(encoding="utf-8")
client=OpenAI(base_url="https://api.ailoot.ai/v1",api_key=os.environ["AILOOT_API_KEY"],max_retries=0)
result=client.images.generate(**request)
Path("sdk-result.txt").write_text(str(result),encoding="utf-8")
save_images([{"b64_json":getattr(item,"b64_json",None),"url":getattr(item,"url",None)} for item in result.data])
import OpenAI from "openai";
import { readFileSync, writeFileSync } from "node:fs";
const key=process.env.AILOOT_API_KEY;
if(!key) throw new Error("Set your actual Ailoot API key");
const client=new OpenAI({baseURL:"https://api.ailoot.ai/v1",apiKey:key,maxRetries:0});
const request={"model": "qwen-image-3.0-pro", "prompt": ""};
if(!process.env.AILOOT_PROMPT_FILE)throw new Error("Set your actual UTF-8 image brief file");
request.prompt=readFileSync(process.env.AILOOT_PROMPT_FILE,"utf8");
const result=await client.images.generate(request);
writeFileSync("sdk-result.json",JSON.stringify(result,null,2));
if(!result.data?.length) throw new Error("No completed images");
for(let index=0;index<result.data.length;index++) {
const item=result.data[index];let encoded=item.b64_json,uri=item.url||"",raw;
if(!encoded && uri.startsWith("data:image/")) {
const comma=uri.indexOf(",");if(comma<0 || !uri.slice(0,comma).includes(";base64")) throw new Error("Unsupported image data URI");
encoded=uri.slice(comma+1);
}
if(encoded) {
if(encoded.length%4!==0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)) throw new Error("Invalid Base64");
raw=Buffer.from(encoded,"base64");
} else if(uri) {
const u=new URL(uri,"https://api.ailoot.ai");
if(u.protocol!=="https:" || u.username || u.password) throw new Error("Invalid returned URL");
const owned=u.origin==="https://api.ailoot.ai" && u.pathname.startsWith("/v1/media/assets/") && u.pathname.endsWith("/content");
const response=await fetch(u,{headers:owned?{Authorization:"Bearer "+key}:{},redirect:"manual"});
if(!response.ok) throw new Error("Image content download failed: "+response.status);
raw=Buffer.from(await response.arrayBuffer());
} else throw new Error("Image has neither bytes nor URL");
if(!raw.length) throw new Error("Empty image result");
const ext=raw.subarray(0,4).equals(Buffer.from([137,80,78,71]))?"png":raw[0]===255&&raw[1]===216?"jpg":raw.toString("ascii",0,4)==="RIFF"&&raw.toString("ascii",8,12)==="WEBP"?"webp":raw.toString("utf8").trimStart().startsWith("<svg")||raw.toString("utf8").trimStart().startsWith("<?xml")?"svg":"bin";
writeFileSync(`image-${index}.${ext}`,raw);
}
console.log("Every returned image saved; sdk-result.json retains complete metadata");
결과 수신 및 저장
Ailoot · 이미지
반환된 각 이미지를 다운로드하거나 Base64 내용을 저장하세요
GET /v1/media/tasks/{task_id}GET /v1/media/assets/{asset_id}/contentGET /v1/media/assetsGET /v1/media/assets/{asset_id}
완료된 결과 모두 보관
완료된 이미지를 모두 저장하세요. 반환된 각 URL에서 가져오거나 Base64 내용을 디코딩하세요.
모든 데이터 항목을 저장하세요. 각 b64_json을 디코딩하거나 반환된 모든 서명된 URL에서 가져오세요. 실제 MIME/바이트에 따라 파일 확장자를 선택하세요.
원래 응답을 확인해야 할 경우
이미지 생성 또는 편집 결과를 확인해야 하는 경우 최초 operation_id/X-Client-Request-ID와 반환된 결과 정보를 보관하세요. 실제 task_id 또는 asset_id 값으로 미디어 라이브러리에서 기존의 소유한 결과를 복구하세요. 생성/편집 요청을 다시 제출하거나 operation_id로 폴링 URL을 구성하지 마세요.
응답 필드
| 필드 | 유형 |
|---|---|
필드created | 유형integer |
필드data[].url | 유형string |
필드data[].b64_json | 유형base64 string |
필드usage | 유형object |
오류와 다음 단계
| 응답 | 조건 | 다음 단계 |
|---|---|---|
응답400 · invalid_request_error | 조건필수 필드, 자료 표현 방식 또는 파라미터 값이 올바르지 않음 | 다음 단계새 생성 요청 전에 표시된 필드를 수정하세요. |
응답server_error | 조건반환된 응답에 작업 또는 결과 확인이 필요하다고 표시되어 있습니다 | 다음 단계최초로 반환된 작업/태스크 ID, 요청 헤더와 응답을 보관하고, 지원되는 조회 방식으로 해당 최초 작업을 계속 조회하세요. 생성 요청을 다시 제출하지 마세요. |
별칭
모델 별칭
Ailoot qwen-image-3.0-pro, qwen-image, qwen-image-latest
메서드 경로 별칭
위에 표시된 메서드 경로를 사용하세요.
관련 호출용 ID
Ailoot · 이미지 POST /v1/images/generations qwen-image
qwen-imageqwen-image-3.0-proqwen-imageqwen-image-latest
시작하기
복잡한 레이아웃, 글자, 사실적인 세부 표현에 중점을 둔 텍스트 기반 이미지 생성 모델입니다. 포스터, 스토리보드, 메뉴, 요소가 촘촘하게 배치된 콘텐츠에 적합합니다.
- 허용 입력
- 텍스트
- 결과
- 이미지
Ailoot에서 사용 가능 · 입력 및 메서드
Ailoot · 이미지 POST /v1/images/generations
- 입력
text- 출력
image- 출력 형식
- 이미지 파일
| 필드 | 유형 | 요건 | 값과 한도 | 기본값 |
|---|---|---|---|---|
필드model | 유형string | 요건필수 | 값과 한도 qwen-image | 기본값— |
필드prompt | 유형string | 요건필수 | 값과 한도 최소 길이: 1 | 기본값— |
필드n | 유형integer | 요건선택 사항 | 값과 한도 최솟값: 1 | 기본값1 |
필드response_format | 유형string | 요건선택 사항 | 값과 한도 url, b64_json | 기본값— |
필드stream | 유형boolean | 요건선택 사항 | 값과 한도 | 기본값false |
필드size | 유형string | 요건선택 사항 | 값과 한도 모델에 따라 다름 | 기본값— |
필드partial_images | 유형integer | 요건선택 사항 | 값과 한도 모델에 따라 다름 | 기본값— |
필드images[].image_url | 유형string | 요건지원되지 않음 | 값과 한도 디코딩 후 최대 바이트 수: 10,485,760 MIME 유형: image/png, image/jpeg 배열당 최대 이미지 수: 3 조건: images[] 객체마다 실제 URL 하나를 사용합니다. 배열 항목 수와 이 문자열 말단 값은 서로 다릅니다. 적용 조건: JSON images/edits만 해당합니다. JSON images/generations는 images 참조 자료를 파싱하지 않습니다. | 기본값— |
필드image | 유형file | 요건선택 사항 | 값과 한도 디코딩 후 최대 바이트 수: 10,485,760 MIME 유형: image/png, image/jpeg 적용 조건: multipart/form-data 생성 | 기본값— |
필드image[] | 유형file[] | 요건선택 사항 | 값과 한도 최대 항목 수: 3 디코딩 후 최대 바이트 수: 10,485,760 MIME 유형: image/png, image/jpeg 적용 조건: multipart/form-data 생성 | 기본값— |
입력 자료 조합
텍스트로 이미지 생성 · 필수: prompt
reference_images_generation · 필수: prompt
메서드 매개변수와 수명 주기
| 매개변수 | 명세 |
|---|---|
매개변수material_types | 명세text |
매개변수required | 명세model, prompt |
매개변수optional_controls | 명세null |
매개변수content_type | 명세application/json |
수명 주기: synchronous_result_then_owned_library
GET /v1/media/tasks/{task_id} · 실제로 반환된 task_id 또는 미디어 라이브러리 기록
GET /v1/media/assets/{asset_id}/content
GET /v1/media/assets
GET /v1/media/assets/{asset_id}
메서드 형식과 ID는 정확합니다. 공급자의 기능 지원과 요청 수락은 별개입니다.
요금
Ailoot 메서드 요금
POST /v1/images/generations- 입력
- US$0.003 입력 이미지당
- 출력
- US$0.04 1K 이미지당
- 출력
- US$0.075 2K 이미지당
Ailoot는 요청 전에 예상 금액을 미리 확보합니다. 결과를 받은 뒤 측정된 사용량을 기준으로 최종 요금을 정산합니다. 스트리밍 정산에는 최종 사용량 기록을 사용합니다. 금액 확보와 정산 방식 →
요청 예제
Ailoot · 이미지
set -eu
: "${AILOOT_API_KEY:?Set your Ailoot API key}"
export AILOOT_API_KEY
export AILOOT_API_KEY
: "${AILOOT_PROMPT_FILE:?Set your actual UTF-8 image brief}"
export AILOOT_PROMPT_FILE
python3 - <<'PY_REQUEST'
import json,os
from pathlib import Path
p=json.loads('{"model": "qwen-image", "prompt": ""}')
f=Path(os.environ["AILOOT_PROMPT_FILE"])
if not f.is_file():raise SystemExit("Choose your actual UTF-8 brief")
p['prompt']=f.read_text(encoding="utf-8")
if not p['prompt'].strip():raise SystemExit("Brief must contain text")
Path("request.json").write_text(json.dumps(p,ensure_ascii=False))
PY_REQUEST
curl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/images/generations \
-H "Authorization: Bearer $AILOOT_API_KEY" -H 'Content-Type: application/json' \
--data-binary @request.json -D response-headers.txt -o result.json
python3 - <<'PY_RESULT'
import base64, json, os, subprocess
from pathlib import Path
from urllib.parse import urlsplit, urljoin
def save_images(items):
if not items: raise SystemExit("No completed images; retain the full response")
for index, item in enumerate(items):
encoded=item.get("b64_json")
uri=item.get("url", "")
if not encoded and uri.startswith("data:image/"):
header, separator, encoded=uri.partition(",")
if not separator or ";base64" not in header: raise SystemExit("Unsupported image data URI")
if encoded:
raw=base64.b64decode(encoded,validate=True)
elif uri:
uri=urljoin("https://api.ailoot.ai",uri)
parsed=urlsplit(uri)
if parsed.scheme!="https" or not parsed.netloc or parsed.username or parsed.password:
raise SystemExit("Invalid returned image URL")
owned=parsed.netloc=="api.ailoot.ai" and parsed.path.startswith("/v1/media/assets/") and parsed.path.endswith("/content")
args=["curl","--fail-with-body","--silent","--show-error",uri]
if owned: args += ["-H","Authorization: Bearer "+os.environ["AILOOT_API_KEY"]]
temporary=Path(f"image-{index}.bin")
subprocess.run(args+["-o",str(temporary)],check=True)
raw=temporary.read_bytes()
temporary.unlink()
else: raise SystemExit("Image has neither bytes nor URL")
if not raw: raise SystemExit("Empty image result")
ext="png" if raw.startswith(b"\x89PNG") else "jpg" if raw.startswith(b"\xff\xd8") else "webp" if raw[:4]==b"RIFF" and raw[8:12]==b"WEBP" else "svg" if raw.lstrip().startswith((b"<svg",b"<?xml")) else "bin"
Path(f"image-{index}.{ext}").write_bytes(raw)
print("Every returned image saved; complete response metadata retained")
save_images(json.loads(Path("result.json").read_text())["data"])
PY_RESULT
from openai import OpenAI
import base64, json, os, subprocess
from pathlib import Path
from urllib.parse import urlsplit, urljoin
def save_images(items):
if not items: raise SystemExit("No completed images; retain the full response")
for index, item in enumerate(items):
encoded=item.get("b64_json")
uri=item.get("url", "")
if not encoded and uri.startswith("data:image/"):
header, separator, encoded=uri.partition(",")
if not separator or ";base64" not in header: raise SystemExit("Unsupported image data URI")
if encoded:
raw=base64.b64decode(encoded,validate=True)
elif uri:
uri=urljoin("https://api.ailoot.ai",uri)
parsed=urlsplit(uri)
if parsed.scheme!="https" or not parsed.netloc or parsed.username or parsed.password:
raise SystemExit("Invalid returned image URL")
owned=parsed.netloc=="api.ailoot.ai" and parsed.path.startswith("/v1/media/assets/") and parsed.path.endswith("/content")
args=["curl","--fail-with-body","--silent","--show-error",uri]
if owned: args += ["-H","Authorization: Bearer "+os.environ["AILOOT_API_KEY"]]
temporary=Path(f"image-{index}.bin")
subprocess.run(args+["-o",str(temporary)],check=True)
raw=temporary.read_bytes()
temporary.unlink()
else: raise SystemExit("Image has neither bytes nor URL")
if not raw: raise SystemExit("Empty image result")
ext="png" if raw.startswith(b"\x89PNG") else "jpg" if raw.startswith(b"\xff\xd8") else "webp" if raw[:4]==b"RIFF" and raw[8:12]==b"WEBP" else "svg" if raw.lstrip().startswith((b"<svg",b"<?xml")) else "bin"
Path(f"image-{index}.{ext}").write_bytes(raw)
print("Every returned image saved; complete response metadata retained")
f=Path(os.environ["AILOOT_PROMPT_FILE"])
if not f.is_file():raise SystemExit("Set your actual UTF-8 image brief file")
request={'model': 'qwen-image', 'prompt': ''}
request["prompt"]=f.read_text(encoding="utf-8")
client=OpenAI(base_url="https://api.ailoot.ai/v1",api_key=os.environ["AILOOT_API_KEY"],max_retries=0)
result=client.images.generate(**request)
Path("sdk-result.txt").write_text(str(result),encoding="utf-8")
save_images([{"b64_json":getattr(item,"b64_json",None),"url":getattr(item,"url",None)} for item in result.data])
import OpenAI from "openai";
import { readFileSync, writeFileSync } from "node:fs";
const key=process.env.AILOOT_API_KEY;
if(!key) throw new Error("Set your actual Ailoot API key");
const client=new OpenAI({baseURL:"https://api.ailoot.ai/v1",apiKey:key,maxRetries:0});
const request={"model": "qwen-image", "prompt": ""};
if(!process.env.AILOOT_PROMPT_FILE)throw new Error("Set your actual UTF-8 image brief file");
request.prompt=readFileSync(process.env.AILOOT_PROMPT_FILE,"utf8");
const result=await client.images.generate(request);
writeFileSync("sdk-result.json",JSON.stringify(result,null,2));
if(!result.data?.length) throw new Error("No completed images");
for(let index=0;index<result.data.length;index++) {
const item=result.data[index];let encoded=item.b64_json,uri=item.url||"",raw;
if(!encoded && uri.startsWith("data:image/")) {
const comma=uri.indexOf(",");if(comma<0 || !uri.slice(0,comma).includes(";base64")) throw new Error("Unsupported image data URI");
encoded=uri.slice(comma+1);
}
if(encoded) {
if(encoded.length%4!==0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)) throw new Error("Invalid Base64");
raw=Buffer.from(encoded,"base64");
} else if(uri) {
const u=new URL(uri,"https://api.ailoot.ai");
if(u.protocol!=="https:" || u.username || u.password) throw new Error("Invalid returned URL");
const owned=u.origin==="https://api.ailoot.ai" && u.pathname.startsWith("/v1/media/assets/") && u.pathname.endsWith("/content");
const response=await fetch(u,{headers:owned?{Authorization:"Bearer "+key}:{},redirect:"manual"});
if(!response.ok) throw new Error("Image content download failed: "+response.status);
raw=Buffer.from(await response.arrayBuffer());
} else throw new Error("Image has neither bytes nor URL");
if(!raw.length) throw new Error("Empty image result");
const ext=raw.subarray(0,4).equals(Buffer.from([137,80,78,71]))?"png":raw[0]===255&&raw[1]===216?"jpg":raw.toString("ascii",0,4)==="RIFF"&&raw.toString("ascii",8,12)==="WEBP"?"webp":raw.toString("utf8").trimStart().startsWith("<svg")||raw.toString("utf8").trimStart().startsWith("<?xml")?"svg":"bin";
writeFileSync(`image-${index}.${ext}`,raw);
}
console.log("Every returned image saved; sdk-result.json retains complete metadata");
결과 수신 및 저장
Ailoot · 이미지
반환된 각 이미지를 다운로드하거나 Base64 내용을 저장하세요
GET /v1/media/tasks/{task_id}GET /v1/media/assets/{asset_id}/contentGET /v1/media/assetsGET /v1/media/assets/{asset_id}
완료된 결과 모두 보관
완료된 이미지를 모두 저장하세요. 반환된 각 URL에서 가져오거나 Base64 내용을 디코딩하세요.
모든 데이터 항목을 저장하세요. 각 b64_json을 디코딩하거나 반환된 모든 서명된 URL에서 가져오세요. 실제 MIME/바이트에 따라 파일 확장자를 선택하세요.
원래 응답을 확인해야 할 경우
이미지 생성 또는 편집 결과를 확인해야 하는 경우 최초 operation_id/X-Client-Request-ID와 반환된 결과 정보를 보관하세요. 실제 task_id 또는 asset_id 값으로 미디어 라이브러리에서 기존의 소유한 결과를 복구하세요. 생성/편집 요청을 다시 제출하거나 operation_id로 폴링 URL을 구성하지 마세요.
응답 필드
| 필드 | 유형 |
|---|---|
필드created | 유형integer |
필드data[].url | 유형string |
필드data[].b64_json | 유형base64 string |
필드usage | 유형object |
오류와 다음 단계
| 응답 | 조건 | 다음 단계 |
|---|---|---|
응답400 · invalid_request_error | 조건필수 필드, 자료 표현 방식 또는 파라미터 값이 올바르지 않음 | 다음 단계새 생성 요청 전에 표시된 필드를 수정하세요. |
응답server_error | 조건반환된 응답에 작업 또는 결과 확인이 필요하다고 표시되어 있습니다 | 다음 단계최초로 반환된 작업/태스크 ID, 요청 헤더와 응답을 보관하고, 지원되는 조회 방식으로 해당 최초 작업을 계속 조회하세요. 생성 요청을 다시 제출하지 마세요. |
별칭
모델 별칭
Ailoot qwen-image-3.0-pro, qwen-image, qwen-image-latest
메서드 경로 별칭
위에 표시된 메서드 경로를 사용하세요.
관련 호출용 ID
Ailoot · 이미지 POST /v1/images/generations qwen-image-latest
qwen-image-latestqwen-image-3.0-proqwen-imageqwen-image-latest
시작하기
복잡한 레이아웃, 글자, 사실적인 세부 표현에 중점을 둔 텍스트 기반 이미지 생성 모델입니다. 포스터, 스토리보드, 메뉴, 요소가 촘촘하게 배치된 콘텐츠에 적합합니다.
- 허용 입력
- 텍스트
- 결과
- 이미지
Ailoot에서 사용 가능 · 입력 및 메서드
Ailoot · 이미지 POST /v1/images/generations
- 입력
text- 출력
image- 출력 형식
- 이미지 파일
| 필드 | 유형 | 요건 | 값과 한도 | 기본값 |
|---|---|---|---|---|
필드model | 유형string | 요건필수 | 값과 한도 qwen-image-latest | 기본값— |
필드prompt | 유형string | 요건필수 | 값과 한도 최소 길이: 1 | 기본값— |
필드n | 유형integer | 요건선택 사항 | 값과 한도 최솟값: 1 | 기본값1 |
필드response_format | 유형string | 요건선택 사항 | 값과 한도 url, b64_json | 기본값— |
필드stream | 유형boolean | 요건선택 사항 | 값과 한도 | 기본값false |
필드size | 유형string | 요건선택 사항 | 값과 한도 모델에 따라 다름 | 기본값— |
필드partial_images | 유형integer | 요건선택 사항 | 값과 한도 모델에 따라 다름 | 기본값— |
필드images[].image_url | 유형string | 요건지원되지 않음 | 값과 한도 디코딩 후 최대 바이트 수: 10,485,760 MIME 유형: image/png, image/jpeg 배열당 최대 이미지 수: 3 조건: images[] 객체마다 실제 URL 하나를 사용합니다. 배열 항목 수와 이 문자열 말단 값은 서로 다릅니다. 적용 조건: JSON images/edits만 해당합니다. JSON images/generations는 images 참조 자료를 파싱하지 않습니다. | 기본값— |
필드image | 유형file | 요건선택 사항 | 값과 한도 디코딩 후 최대 바이트 수: 10,485,760 MIME 유형: image/png, image/jpeg 적용 조건: multipart/form-data 생성 | 기본값— |
필드image[] | 유형file[] | 요건선택 사항 | 값과 한도 최대 항목 수: 3 디코딩 후 최대 바이트 수: 10,485,760 MIME 유형: image/png, image/jpeg 적용 조건: multipart/form-data 생성 | 기본값— |
입력 자료 조합
텍스트로 이미지 생성 · 필수: prompt
reference_images_generation · 필수: prompt
메서드 매개변수와 수명 주기
| 매개변수 | 명세 |
|---|---|
매개변수material_types | 명세text |
매개변수required | 명세model, prompt |
매개변수optional_controls | 명세null |
매개변수content_type | 명세application/json |
수명 주기: synchronous_result_then_owned_library
GET /v1/media/tasks/{task_id} · 실제로 반환된 task_id 또는 미디어 라이브러리 기록
GET /v1/media/assets/{asset_id}/content
GET /v1/media/assets
GET /v1/media/assets/{asset_id}
메서드 형식과 ID는 정확합니다. 공급자의 기능 지원과 요청 수락은 별개입니다.
요금
Ailoot 메서드 요금
POST /v1/images/generations- 입력
- US$0.003 입력 이미지당
- 출력
- US$0.04 1K 이미지당
- 출력
- US$0.075 2K 이미지당
Ailoot는 요청 전에 예상 금액을 미리 확보합니다. 결과를 받은 뒤 측정된 사용량을 기준으로 최종 요금을 정산합니다. 스트리밍 정산에는 최종 사용량 기록을 사용합니다. 금액 확보와 정산 방식 →
요청 예제
Ailoot · 이미지
set -eu
: "${AILOOT_API_KEY:?Set your Ailoot API key}"
export AILOOT_API_KEY
export AILOOT_API_KEY
: "${AILOOT_PROMPT_FILE:?Set your actual UTF-8 image brief}"
export AILOOT_PROMPT_FILE
python3 - <<'PY_REQUEST'
import json,os
from pathlib import Path
p=json.loads('{"model": "qwen-image-latest", "prompt": ""}')
f=Path(os.environ["AILOOT_PROMPT_FILE"])
if not f.is_file():raise SystemExit("Choose your actual UTF-8 brief")
p['prompt']=f.read_text(encoding="utf-8")
if not p['prompt'].strip():raise SystemExit("Brief must contain text")
Path("request.json").write_text(json.dumps(p,ensure_ascii=False))
PY_REQUEST
curl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/images/generations \
-H "Authorization: Bearer $AILOOT_API_KEY" -H 'Content-Type: application/json' \
--data-binary @request.json -D response-headers.txt -o result.json
python3 - <<'PY_RESULT'
import base64, json, os, subprocess
from pathlib import Path
from urllib.parse import urlsplit, urljoin
def save_images(items):
if not items: raise SystemExit("No completed images; retain the full response")
for index, item in enumerate(items):
encoded=item.get("b64_json")
uri=item.get("url", "")
if not encoded and uri.startswith("data:image/"):
header, separator, encoded=uri.partition(",")
if not separator or ";base64" not in header: raise SystemExit("Unsupported image data URI")
if encoded:
raw=base64.b64decode(encoded,validate=True)
elif uri:
uri=urljoin("https://api.ailoot.ai",uri)
parsed=urlsplit(uri)
if parsed.scheme!="https" or not parsed.netloc or parsed.username or parsed.password:
raise SystemExit("Invalid returned image URL")
owned=parsed.netloc=="api.ailoot.ai" and parsed.path.startswith("/v1/media/assets/") and parsed.path.endswith("/content")
args=["curl","--fail-with-body","--silent","--show-error",uri]
if owned: args += ["-H","Authorization: Bearer "+os.environ["AILOOT_API_KEY"]]
temporary=Path(f"image-{index}.bin")
subprocess.run(args+["-o",str(temporary)],check=True)
raw=temporary.read_bytes()
temporary.unlink()
else: raise SystemExit("Image has neither bytes nor URL")
if not raw: raise SystemExit("Empty image result")
ext="png" if raw.startswith(b"\x89PNG") else "jpg" if raw.startswith(b"\xff\xd8") else "webp" if raw[:4]==b"RIFF" and raw[8:12]==b"WEBP" else "svg" if raw.lstrip().startswith((b"<svg",b"<?xml")) else "bin"
Path(f"image-{index}.{ext}").write_bytes(raw)
print("Every returned image saved; complete response metadata retained")
save_images(json.loads(Path("result.json").read_text())["data"])
PY_RESULT
from openai import OpenAI
import base64, json, os, subprocess
from pathlib import Path
from urllib.parse import urlsplit, urljoin
def save_images(items):
if not items: raise SystemExit("No completed images; retain the full response")
for index, item in enumerate(items):
encoded=item.get("b64_json")
uri=item.get("url", "")
if not encoded and uri.startswith("data:image/"):
header, separator, encoded=uri.partition(",")
if not separator or ";base64" not in header: raise SystemExit("Unsupported image data URI")
if encoded:
raw=base64.b64decode(encoded,validate=True)
elif uri:
uri=urljoin("https://api.ailoot.ai",uri)
parsed=urlsplit(uri)
if parsed.scheme!="https" or not parsed.netloc or parsed.username or parsed.password:
raise SystemExit("Invalid returned image URL")
owned=parsed.netloc=="api.ailoot.ai" and parsed.path.startswith("/v1/media/assets/") and parsed.path.endswith("/content")
args=["curl","--fail-with-body","--silent","--show-error",uri]
if owned: args += ["-H","Authorization: Bearer "+os.environ["AILOOT_API_KEY"]]
temporary=Path(f"image-{index}.bin")
subprocess.run(args+["-o",str(temporary)],check=True)
raw=temporary.read_bytes()
temporary.unlink()
else: raise SystemExit("Image has neither bytes nor URL")
if not raw: raise SystemExit("Empty image result")
ext="png" if raw.startswith(b"\x89PNG") else "jpg" if raw.startswith(b"\xff\xd8") else "webp" if raw[:4]==b"RIFF" and raw[8:12]==b"WEBP" else "svg" if raw.lstrip().startswith((b"<svg",b"<?xml")) else "bin"
Path(f"image-{index}.{ext}").write_bytes(raw)
print("Every returned image saved; complete response metadata retained")
f=Path(os.environ["AILOOT_PROMPT_FILE"])
if not f.is_file():raise SystemExit("Set your actual UTF-8 image brief file")
request={'model': 'qwen-image-latest', 'prompt': ''}
request["prompt"]=f.read_text(encoding="utf-8")
client=OpenAI(base_url="https://api.ailoot.ai/v1",api_key=os.environ["AILOOT_API_KEY"],max_retries=0)
result=client.images.generate(**request)
Path("sdk-result.txt").write_text(str(result),encoding="utf-8")
save_images([{"b64_json":getattr(item,"b64_json",None),"url":getattr(item,"url",None)} for item in result.data])
import OpenAI from "openai";
import { readFileSync, writeFileSync } from "node:fs";
const key=process.env.AILOOT_API_KEY;
if(!key) throw new Error("Set your actual Ailoot API key");
const client=new OpenAI({baseURL:"https://api.ailoot.ai/v1",apiKey:key,maxRetries:0});
const request={"model": "qwen-image-latest", "prompt": ""};
if(!process.env.AILOOT_PROMPT_FILE)throw new Error("Set your actual UTF-8 image brief file");
request.prompt=readFileSync(process.env.AILOOT_PROMPT_FILE,"utf8");
const result=await client.images.generate(request);
writeFileSync("sdk-result.json",JSON.stringify(result,null,2));
if(!result.data?.length) throw new Error("No completed images");
for(let index=0;index<result.data.length;index++) {
const item=result.data[index];let encoded=item.b64_json,uri=item.url||"",raw;
if(!encoded && uri.startsWith("data:image/")) {
const comma=uri.indexOf(",");if(comma<0 || !uri.slice(0,comma).includes(";base64")) throw new Error("Unsupported image data URI");
encoded=uri.slice(comma+1);
}
if(encoded) {
if(encoded.length%4!==0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)) throw new Error("Invalid Base64");
raw=Buffer.from(encoded,"base64");
} else if(uri) {
const u=new URL(uri,"https://api.ailoot.ai");
if(u.protocol!=="https:" || u.username || u.password) throw new Error("Invalid returned URL");
const owned=u.origin==="https://api.ailoot.ai" && u.pathname.startsWith("/v1/media/assets/") && u.pathname.endsWith("/content");
const response=await fetch(u,{headers:owned?{Authorization:"Bearer "+key}:{},redirect:"manual"});
if(!response.ok) throw new Error("Image content download failed: "+response.status);
raw=Buffer.from(await response.arrayBuffer());
} else throw new Error("Image has neither bytes nor URL");
if(!raw.length) throw new Error("Empty image result");
const ext=raw.subarray(0,4).equals(Buffer.from([137,80,78,71]))?"png":raw[0]===255&&raw[1]===216?"jpg":raw.toString("ascii",0,4)==="RIFF"&&raw.toString("ascii",8,12)==="WEBP"?"webp":raw.toString("utf8").trimStart().startsWith("<svg")||raw.toString("utf8").trimStart().startsWith("<?xml")?"svg":"bin";
writeFileSync(`image-${index}.${ext}`,raw);
}
console.log("Every returned image saved; sdk-result.json retains complete metadata");
결과 수신 및 저장
Ailoot · 이미지
반환된 각 이미지를 다운로드하거나 Base64 내용을 저장하세요
GET /v1/media/tasks/{task_id}GET /v1/media/assets/{asset_id}/contentGET /v1/media/assetsGET /v1/media/assets/{asset_id}
완료된 결과 모두 보관
완료된 이미지를 모두 저장하세요. 반환된 각 URL에서 가져오거나 Base64 내용을 디코딩하세요.
모든 데이터 항목을 저장하세요. 각 b64_json을 디코딩하거나 반환된 모든 서명된 URL에서 가져오세요. 실제 MIME/바이트에 따라 파일 확장자를 선택하세요.
원래 응답을 확인해야 할 경우
이미지 생성 또는 편집 결과를 확인해야 하는 경우 최초 operation_id/X-Client-Request-ID와 반환된 결과 정보를 보관하세요. 실제 task_id 또는 asset_id 값으로 미디어 라이브러리에서 기존의 소유한 결과를 복구하세요. 생성/편집 요청을 다시 제출하거나 operation_id로 폴링 URL을 구성하지 마세요.
응답 필드
| 필드 | 유형 |
|---|---|
필드created | 유형integer |
필드data[].url | 유형string |
필드data[].b64_json | 유형base64 string |
필드usage | 유형object |
오류와 다음 단계
| 응답 | 조건 | 다음 단계 |
|---|---|---|
응답400 · invalid_request_error | 조건필수 필드, 자료 표현 방식 또는 파라미터 값이 올바르지 않음 | 다음 단계새 생성 요청 전에 표시된 필드를 수정하세요. |
응답server_error | 조건반환된 응답에 작업 또는 결과 확인이 필요하다고 표시되어 있습니다 | 다음 단계최초로 반환된 작업/태스크 ID, 요청 헤더와 응답을 보관하고, 지원되는 조회 방식으로 해당 최초 작업을 계속 조회하세요. 생성 요청을 다시 제출하지 마세요. |
별칭
모델 별칭
Ailoot qwen-image-3.0-pro, qwen-image, qwen-image-latest
메서드 경로 별칭
위에 표시된 메서드 경로를 사용하세요.
관련 호출용 ID
FAQ · qwen-image-3.0-pro
- 어떤 입력과 결과를 사용할 수 있나요?
POST /v1/images/generations·qwen-image-3.0-pro:text→imagePOST /v1/images/generations·qwen-image:text→imagePOST /v1/images/generations·qwen-image-latest:text→image- 요청은 어떤 필드를 사용하나요?
POST /v1/images/generations·qwen-image-3.0-pro:model,prompt,n,response_format,stream,image,image[]POST /v1/images/generations·qwen-image:model,prompt,n,response_format,stream,image,image[]POST /v1/images/generations·qwen-image-latest:model,prompt,n,response_format,stream,image,image[]- 어떤 제한이 적용되나요?
POST /v1/images/generations·qwen-image-3.0-pro:n.minimum:1POST /v1/images/generations·qwen-image:n.minimum:1POST /v1/images/generations·qwen-image-latest:n.minimum:1