Novita AI의 Qwen Image 텍스트-이미지 API는 20B Qwen Image 모델을 사용해 텍스트 프롬프트로 이미지를 생성합니다. 이는 정밀한 편집 작업을 위한 Qwen Image Edit API를 구동하는 것과 동일한 기반입니다. 이 퀵 스타트 가이드는 생성 요청 제출, 태스크 ID 획득, 완료 폴링, 이미지 URL 검색에 이르는 전체 비동기 워크플로우를 다룹니다. 엔드포인트는 POST https://api.novita.ai/v3/async/qwen-image-txt2img입니다.
이 퀵 스타트를 사용해야 하는 경우
다음과 같은 경우 이 가이드를 활용하세요:
POST /v3/async/qwen-image-txt2img를 통해 영어 또는 중국어로 고품질 텍스트 렌더링이 가능한 이미지를 텍스트 프롬프트로 생성해야 할 때- 이미지 내 텍스트 가독성이 중요한 포스터, 그래픽 에셋, 일러스트 콘텐츠를 제작하는 파이프라인을 구축할 때
- 로컬 GPU 인프라에서 20B 모델을 실행하는 대신 호스팅된 API에 대해 신속하게 프로토타입을 제작할 때
Qwen Image 모델은 출력물에 읽기 쉽고 스타일링된 텍스트가 포함된 이미지(포스터, 간판, 제품 목업, 커버 그래픽 등)를 생성하는 데 특히 강점이 있습니다. 기존 이미지를 편집해야 하는 경우 Qwen Image Edit API를 참조하세요. Qwen Image 모델의 전체 기능과 벤치마크에 대한 개요는 Novita AI의 Qwen Image 런치 게시글에서 아키텍처와 벤치마크 결과를 자세히 확인할 수 있습니다.
1단계: Novita API 키 획득
Novita AI 계정을 생성하고 API 키 관리 페이지로 이동하세요. 키를 생성한 후 환경 변수로 저장합니다:
export NOVITA_API_KEY="your_api_key_here"
키는 클라이언트 코드, 프론트엔드 번들, 버전 관리 시스템에 포함하지 않도록 주의하세요.
2단계: 엔드포인트 및 모델 확인
| 항목 | 값 |
|---|---|
| 생성 엔드포인트 | POST https://api.novita.ai/v3/async/qwen-image-txt2img |
| 결과 폴링 엔드포인트 | GET https://api.novita.ai/v3/async/task-result?task_id=<id> |
| 모델 | Qwen Image (20B MMDiT) |
| API 문서 | Novita AI Qwen Image txt2img 레퍼런스 |
이 API는 모든 Novita AI 이미지 생성 엔드포인트에 공통적인 2단계 비동기 패턴을 따릅니다. 생성 호출은 task_id만 반환하며, 태스크가 완료될 때까지 결과 엔드포인트를 별도로 폴링합니다.
가격은 Qwen Image Edit 엔드포인트와 동일하게 이미지당 $0.02입니다. 비용 추정 전에 Novita AI 가격 페이지에서 현재 요금을 확인하세요.
3단계: 첫 번째 요청 보내기
생성 엔드포인트에 prompt와 선택적 size를 포함하여 POST 요청을 보냅니다:
curl -s -X POST https://api.novita.ai/v3/async/qwen-image-txt2img \
-H "Authorization: Bearer $NOVITA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A cinematic mountain landscape at sunrise, warm golden light, ultra-detailed, 8K",
"size": "1024*1024"
}'
성공적인 200 응답은 다음과 같이 반환됩니다:
{
"task_id": "abc123..."
}
task_id를 저장하세요. 다음 단계에서 사용됩니다.
4단계: 결과 폴링하기
태스크 결과 엔드포인트에 task_id를 쿼리 파라미터로 포함하여 GET 요청을 보냅니다:
curl -s "https://api.novita.ai/v3/async/task-result?task_id=abc123..." \
-H "Authorization: Bearer $NOVITA_API_KEY"
응답에는 status 필드가 포함됩니다. 상태가 TASK_STATUS_SUCCEED가 될 때까지 폴링을 계속합니다:
{
"task": {
"task_id": "abc123...",
"status": "TASK_STATUS_SUCCEED"
},
"images": [
{
"image_url": "https://...",
"image_url_ttl": "3600",
"image_type": "png"
}
]
}
image_url은 시간 제한이 있는 URL입니다. image_url_ttl 값(초)은 URL이 유효한 시간을 알려줍니다. 이미지를 즉시 다운로드하거나 장기 접근이 필요하다면 자체 스토리지를 통해 프록시하세요.
처리해야 할 상태 값:
| 상태 | 의미 |
|---|---|
TASK_STATUS_QUEUED |
요청이 대기열에 있으며 아직 시작되지 않음 |
TASK_STATUS_PROCESSING |
생성이 진행 중 |
TASK_STATUS_SUCCEED |
이미지 준비 완료. images[0].image_url 확인 |
TASK_STATUS_FAILED |
생성 실패. task.reason 확인 |
Python 예제: 엔드투엔드
이 스크립트는 생성 요청을 제출하고, 완료될 때까지 폴링하며, 이미지 URL을 출력합니다.
import os
import time
import requests
API_KEY = os.environ["NOVITA_API_KEY"]
BASE_URL = "https://api.novita.ai"
def generate_image(prompt: str, size: str = "1024*1024") -> str:
response = requests.post(
f"{BASE_URL}/v3/async/qwen-image-txt2img",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json={"prompt": prompt, "size": size},
)
response.raise_for_status()
return response.json()["task_id"]
def poll_result(task_id: str, interval: float = 2.0, max_attempts: int = 60) -> str:
for _ in range(max_attempts):
response = requests.get(
f"{BASE_URL}/v3/async/task-result",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"task_id": task_id},
)
response.raise_for_status()
data = response.json()
status = data["task"]["status"]
if status == "TASK_STATUS_SUCCEED":
return data["images"][0]["image_url"]
elif status == "TASK_STATUS_FAILED":
reason = data["task"].get("reason", "unknown")
raise RuntimeError(f"Generation failed: {reason}")
time.sleep(interval)
raise TimeoutError(f"Task {task_id} did not complete after {max_attempts} polls")
if __name__ == "__main__":
prompt = (
"A poster reading 'Welcome to Novita AI' in bold neon letters "
"against a dark city skyline at night, cinematic lighting"
)
task_id = generate_image(prompt, size="1024*1024")
print(f"Task ID: {task_id}")
image_url = poll_result(task_id)
print(f"Image URL: {image_url}")
cURL 예제
전체 워크플로우를 위한 2-명령 패턴:
# Step 1: Submit generation request
TASK_ID=$(curl -s -X POST https://api.novita.ai/v3/async/qwen-image-txt2img \
-H "Authorization: Bearer $NOVITA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A serene Japanese garden with cherry blossoms, koi pond, morning mist, watercolor style",
"size": "1024*1536"
}' | python3 -c "import sys,json; print(json.load(sys.stdin)['task_id'])"
echo "Task ID: $TASK_ID"
# Step 2: Poll until complete
while true; do
STATUS=$(curl -s "https://api.novita.ai/v3/async/task-result?task_id=$TASK_ID" \
-H "Authorization: Bearer $NOVITA_API_KEY")
STATE=$(echo $STATUS | python3 -c "import sys,json; print(json.load(sys.stdin)['task']['status'])")
echo "Status: $STATE"
if [ "$STATE" = "TASK_STATUS_SUCCEED" ]; then
echo $STATUS | python3 -c "import sys,json; print(json.load(sys.stdin)['images'][0]['image_url'])"
break
elif [ "$STATE" = "TASK_STATUS_FAILED" ]; then
echo "Generation failed"
break
fi
sleep 2
done
주요 파라미터
| 파라미터 | 타입 | 필수 | 기본값 | 비고 |
|---|---|---|---|---|
prompt |
string | 예 | — | 생성할 이미지에 대한 텍스트 설명. 영어와 중국어 지원. |
size |
string | 아니요 | 1024*1024 |
�셀 단위의 너비 × 높이, W*H 형식. 각 차원: 256–1536. |
고려할 크기 옵션:
| 사용 사례 | 권장 크기 |
|---|---|
| 정사각형 (소셜, 프로필) | 1024*1024 |
| 세로형 (모바일, 포스터) | 1024*1536 |
| 가로형 (배너, 썸네일) | 1536*1024 |
이 엔드포인트에는 별도의 negative_prompt, steps, cfg_scale 파라미터가 없습니다. 모델이 내부적으로 해당 결정을 처리합니다. 프롬프트는 이미지에 포함되어야 할 내용과 시각적 스타일에 집중하세요.
Qwen Image가 잘 생성하는 것
20B MMDiT 아키텍처는 Qwen Image가 몇 가지 특정 영역에서 확실한 이점을 제공합니다.
이미지 내 텍스트. 대부분의 이미지 생성 모델은 읽을 수 있는 텍스트를 표현하는 데 어려움을 겪습니다. 단어가 흐려지고, 문자가 바뀌며, 여러 줄 레이아웃이 무너집니다. Qwen Image는 영어와 중국어 텍스트를 눈에 띄게 정확하게 처리합니다. 포스터, 간판, 라벨, 캡션이 포함된 그래픽은 운에 맡기는 것이 아니라 실용적인 사용 사례가 됩니다.
의미론적 일관성. 프롬프트가 여러 요소와 특정 공간 관계를 가진 장면을 설명할 때, Qwen Image는 더 작거나 오래된 아키텍처보다 레이아웃 의도를 더 신뢰성 있게 반영하는 경향이 있습니다.
확장된 프롬프트 따르기. 장면, 조명, 스타일, 색상 팔레트, 특정 객체 등 여러 속성을 설명하는 길고 상세한 프롬프트는 하나의 키워드에 집착하기보다는 전체 프롬프트를 반영한 출력을 생성합니다.
적합하지 않은 분야: 실시간 또는 대화형 생성 워크플로우. 비동기 패턴은 요청과 결과 사이에 고유한 대기 시간이 있습니다. 사용 사례에 서브초 단위 피드백이 필요하다면 이 엔드포인트는 적합하지 않습니다.
일반적인 오류 및 해결 방법
401 Unauthorized: Authorization 헤더가 Bearer <key> 형식으로 Bearer 뒤에 공백이 있는지 확인하세요. Novita AI 콘솔에서 키가 활성 상태인지 확인하세요.
400 Bad Request (size 관련): size 파라미터는 구분자로 *를 사용해야 합니다(예: 1024*1024). x, ×, JSON 배열은 사용할 수 없습니다. 각 차원은 256에서 1536 사이여야 합니다.
TASK_STATUS_FAILED (이유 없음): 일반적으로 콘텐츠 필터링을 트리거하는 프롬프트로 인해 발생합니다. 프롬프트를 단순화하고 다시 시도하세요. 명시적인 폭력, 성적 콘텐츠 또는 안전 필터에 걸릴 수 있는 콘텐츠가 포함된 프롬프트는 피하세요.
이미지 URL 만료 (URL에서 403 또는 404): image_url_ttl 필드는 URL의 유효 기간을 알려줍니다. 폴링이 성공한 후 즉시 이미지를 다운로드하거나 자체 객체 스토리지에 저장하세요.
느린 폴링: 생성 시간은 서버 부하에 따라 달라집니다. 2초 간격으로 폴링을 시작하는 것이 합리적입니다. 10초 후에도 태스크가 여전히 TASK_STATUS_QUEUED 상태라면 계속 폴링하세요. 피크 사용 시간에는 대기열 깊이가 급증할 수 있습니다.
FAQ
Qwen Image txt2img를 위한 OpenAI 호환 엔드포인트가 있나요?
아니요. /v3/async/qwen-image-txt2img 엔드포인트는 OpenAI 이미지 생성 형식이 아닌 Novita AI의 네이티브 비동기 이미지 API를 사용합니다. OpenAI 호환 이미지 생성이 필요하다면 Novita AI는 호환 엔드포인트를 통해 FLUX 및 SDXL 모델을 제공합니다. 자세한 내용은 Novita AI 문서를 참조하세요.
이 엔드포인트와 Qwen Image Edit 엔드포인트의 차이점은 무엇인가요?
이 엔드포인트는 텍스트 프롬프트만으로 이미지를 생성합니다. 입력 이미지가 필요하지 않습니다. Qwen Image Edit 엔드포인트는 기존 이미지와 텍스트 명령을 받아 이미지를 수정합니다. 처음부터 생성할 때는 txt2img를, 기존 이미지를 변경해야 할 때는 edit를 사용하세요.
모델이 정사각형 외의 화면 비율을 지원하나요?
네. size 파라미터를 사용하여 너비와 높이를 각 차원당 256에서 1536 픔셀 사이에서 독립적으로 설정할 수 있습니다. 세로 비율(예: 1024*1536)은 세로형 콘텐츠에, 가로 비율(예: 1536*1024)은 배너와 썸네일에 적합합니다.
여러 생성에서 일관된 결과를 얻으려면 어떻게 해야 하나요?
txt2img 엔드포인트에는 seed 파라미터가 없습니다. 각 요청은 다른 결과를 생성합니다. 재현 가능한 출력이 필요하다면 이미지 URL을 즉시 저장하고 재생성하는 대신 자체 스토리지에 이미지를 보관하세요.
이 API를 배치 작업에 사용할 수 있나요?
네. 여러 생성 요청을 제출하고 태스크 ID를 수집한 다음 병렬로 폴링하면 됩니다. 각 요청은 자체 task_id를 반환하므로 배치 워크플로우는 간단합니다. 하나가 완료될 때까지 기다렸다가 다음을 제출할 필요가 없습니다.
