OpenAI API
OpenAI API
이 페이지는 SGLang 확산 HTTP 서버의 OpenAI 호환 API를 설명해요. 이미지 및 비디오 생성을 위한 엔드포인트와 LoRA 어댑터 관리를 다뤄요.
출처: 문서
본문
SGLang 확산 HTTP 서버는 이미지 및 비디오 생성과 LoRA 어댑터 관리를 위한 OpenAI 호환 API를 구현해요.
전제 조건 (Prerequisites)
- OpenAI Python SDK를 사용할 계획이라면 Python 3.11 이상.
서빙 (Serve)
sglang serve 명령으로 서버를 실행해요.
서버 시작 (Start the server)
SERVER_ARGS=(
--model-path Wan-AI/Wan2.1-T2V-1.3B-Diffusers
--served-model-name wan-t2v
--text-encoder-cpu-offload
--pin-cpu-memory
--num-gpus 4
--ulysses-degree=2
--ring-degree=2
--port 30010
)
sglang serve "${SERVER_ARGS[@]}"
- --model-path: 모델 경로 또는 모델 ID.
- --served-model-name: 서빙 API가 노출하는 안정적인 모델 이름. 기본값은 설정 시
--model-id, 그렇지 않으면--model-path. - --port: 수신할 HTTP 포트 (기본값:
30000).
서빙 모델 이름 (Served model name)
--served-model-name은 공개 API 정체성과 체크포인트 위치를 분리해요. 복제본이 다른 로컬 마운트 경로를 사용하거나 게이트웨이가 하나의 안정적인 모델 이름을 필요로 할 때 유용해요:
sglang serve \
--model-path /models/Wan2.1-T2V-1.3B-Diffusers \
--served-model-name wan-t2v \
--port 30010
--model-id는 자유 형식 배포 별칭이 아니에요. 로컬 경로로 식별할 수 없는 체크포인트에 대해 등록된 모델 구성을 선택해요. --served-model-name은 서빙 API가 노출하는 이름만 제어해요. 둘 다 설정되면 API 응답에서는 서빙된 이름이 우선해요.
서빙 모델 발견 (Discover the served model)
엔드포인트: GET /v1/models
공개 모델 이름과 확산별 런타임 정보를 반환해요.
Curl 예시:
curl -sS "http://localhost:30010/v1/models"
응답 예시:
{
"object": "list",
"data": [
{
"id": "wan-t2v",
"object": "model",
"created": 1786348800,
"owned_by": "sglang",
"root": "wan-t2v",
"parent": null,
"max_model_len": null,
"num_gpus": 4,
"task_type": "T2V",
"dit_precision": "bf16",
"vae_precision": "fp16",
"pipeline_name": "WanPipeline",
"pipeline_class": "WanPipeline"
}
]
}
서빙된 이름으로 동일한 모델 검색:
curl -sS "http://localhost:30010/v1/models/wan-t2v"
GET /server_info도 게이트웨이 발견을 위해 served_model_name을 보고해요. 비디오와 액션 응답은 요청이 모델을 명시적으로 제공하지 않을 때 이 이름을 사용해요.
엔드포인트 (Endpoints)
모델별 요청 필드 (Model-specific request fields)
이미지 및 비디오 요청 스키마는 OpenAI 필드와 모델 패밀리 간에 공유되는 안정적인 SGLang 확장만 포함해요. 모델별 컨트롤은 OpenAI Python 클라이언트를 사용할 때 extra_body에 넣어요:
from openai import OpenAI
client = OpenAI(api_key="EMPTY", base_url="http://localhost:30010/v1")
response = client.images.generate(
model="ideogram-ai/ideogram-4-nf4",
prompt="A typeset poster",
extra_body={"preset": "V4_QUALITY_48"},
)
원시 JSON 요청은 이 필드를 최상위로 보낼 수 있어요. Multipart 비디오 요청은 개별 선언된 폼 필드 또는 extra_params의 하나의 JSON 객체를 보낼 수 있어요. SGLang은 활성 모델이 필드를 선언할 때만 모델별 확장을 전달하므로, 한 모델 패밀리를 위한 필드가 다른 모델을 조용히 바꾸지 않아요.
이미지 생성 (Image Generation)
서버는 /v1/images 네임스페이스 아래에 OpenAI 호환 Images API를 구현해요.
이미지 생성
엔드포인트: POST /v1/images/generations
요청 품질 (Request quality)
quality는 누적 요청 수준 최적화 등급을 선택해요: lossless는 선택된 배포의 참조 경로와 모든 무조건적 비트 정확 대체를 유지하고, extra-high는 요청 게이팅된 DiT/VAE 커널 융합만 추가로 활성화하며, high는 전체 extra-high 집합을 포함하고 모델 소유의 sparse, caching, 저정밀 또는 기타 근사 경로도 활성화할 수 있어요. 이 등급은 별도로 구성된 양자화, 어텐션 또는 캐싱 옵션을 덮어쓰지 않아요. lossless 런타임 기본값을 유지하려면 생략하거나(또는 OpenAI 기본 auto 전송) 하세요. 이는 출력 파일 압축만 제어하는 output_quality와 구별돼요. 동일한 확장이 이미지 편집과 비디오 요청에도 수용돼요.
Python 예시 (b64_json 응답):
import base64
from openai import OpenAI
client = OpenAI(api_key="«redacted:sk-…»", base_url="http://localhost:30010/v1")
img = client.images.generate(
prompt="A calico cat playing a piano on stage",
size="1024x1024",
n=1,
response_format="b64_json",
)
image_bytes = base64.b64decode(img.data[0].b64_json)
with open("output.png", "wb") as f:
f.write(image_bytes)
Curl 예시:
curl -sS -X POST "http://localhost:30010/v1/images/generations" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ***" \
-d '{
"prompt": "A calico cat playing a piano on stage",
"size": "1024x1024",
"n": 1,
"response_format": "b64_json"
}'
Note
response_format=url을 사용하고 클라우드 저장소가 구성되지 않으면 API는/v1/images/<IMAGE_ID>/content같은 상대 URL을 반환해요.
이미지 편집
엔드포인트: POST /v1/images/edits
이 엔드포인트는 입력 이미지와 텍스트 프롬프트가 있는 multipart 폼 업로드를 받아요. 서버는 base64 인코딩 이미지 또는 이미지를 내려받을 URL을 반환할 수 있어요.
Curl 예시 (b64_json 응답):
curl -sS -X POST "http://localhost:30010/v1/images/edits" \
-H "Authorization: Bearer ***" \
-F "image=@local_input_image.png" \
-F "url=image_url.jpg" \
-F "prompt=A calico cat playing a piano on stage" \
-F "size=1024x1024" \
-F "response_format=b64_json"
Curl 예시 (URL 응답):
curl -sS -X POST "http://localhost:30010/v1/images/edits" \
-H "Authorization: Bearer ***" \
-F "image=@local_input_image.png" \
-F "url=image_url.jpg" \
-F "prompt=A calico cat playing a piano on stage" \
-F "size=1024x1024" \
-F "response_format=url"
이미지 콘텐츠 내려받기
POST /v1/images/generations 또는 POST /v1/images/edits에서 response_format=url을 사용하면 API는 /v1/images/<IMAGE_ID>/content 같은 상대 URL을 반환해요.
엔드포인트: GET /v1/images/{image_id}/content
Curl 예시:
curl -sS -L "http://localhost:30010/v1/images/<IMAGE_ID>/content" \
-H "Authorization: Bearer ***" \
-o output.png
비디오 생성 (Video Generation)
서버는 /v1/videos 네임스페이스 아래에 OpenAI Videos API의 일부를 구현해요.
비디오 생성 (text-to-video)
엔드포인트: POST /v1/videos
Python 예시:
from openai import OpenAI
client = OpenAI(api_key="«redacted:sk-…»", base_url="http://localhost:30010/v1")
video = client.videos.create(
prompt="A calico cat playing a piano on stage",
size="1280x720"
)
print(f"Video ID: {video.id}, Status: {video.status}")
Curl 예시:
curl -sS -X POST "http://localhost:30010/v1/videos" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ***" \
-d '{
"prompt": "A calico cat playing a piano on stage",
"size": "1280x720"
}'
비디오 생성 (image-to-video)
I2V 또는 TI2V 모델(예: Wan2.1 I2V, LTX-2.3 two-stage)의 경우 multipart 폼 업로드 또는 참조 URL로 입력 이미지를 전달해요.
Curl 예시 (multipart 폼 업로드):
curl -sS -X POST "http://localhost:30010/v1/videos" \
-H "Authorization: Bearer ***" \
-F "prompt=A cat playing a piano" \
-F "input_reference=@input_image.png" \
-F "size=1280x720"
Curl 예시 (참조 URL):
curl -sS -X POST "http://localhost:30010/v1/videos" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ***" \
-d '{
"prompt": "A cat playing a piano",
"reference_url": "https://example.com/input_image.png",
"size": "1280x720"
}'
비디오 목록
엔드포인트: GET /v1/videos
Python 예시:
videos = client.videos.list()
for item in videos.data:
print(item.id, item.status)
Curl 예시:
curl -sS -X GET "http://localhost:30010/v1/videos" \
-H "Authorization: Bearer ***"
비디오 콘텐츠 내려받기
엔드포인트: GET /v1/videos/{video_id}/content
Python 예시:
import time
# Poll for completion
while True:
page = client.videos.list()
item = next((v for v in page.data if v.id == video_id), None)
if item and item.status == "completed":
break
time.sleep(5)
# Download content
resp = client.videos.download_content(video_id=video_id)
with open("output.mp4", "wb") as f:
f.write(resp.read())
Curl 예시:
curl -sS -L "http://localhost:30010/v1/videos/<VIDEO_ID>/content" \
-H "Authorization: Bearer ***" \
-o output.mp4
LoRA 관리 (LoRA Management)
서버는 LoRA 어댑터의 동적 로딩, 병합, 병합 해제를 지원해요.
중요한 참고 사항:
- 상호 배제: 한 번에 대상당 하나의 LoRA 구성만 활성화 가능
- 전환:
unmerge_lora_weights로 현재 LoRA를 비활성화한 다음 새 것으로set - 캐싱: 서버는 로드된 LoRA 가중치를 메모리에 캐시해요. 이전에 로드된 LoRA(동일 경로)로의 전환은 비용이 거의 없어요.
LoRA 어댑터 설정
하나 이상의 LoRA 어댑터를 로드하고 모델에 적용해요. 기본적으로 일반 가중치는 정적으로 병합되고, FSDP-샤딩 가중치는 전체 gather 메모리 피크를 피하기 위해 동적 LoRA를 사용해요.
엔드포인트: POST /v1/set_lora
파라미터:
lora_nickname(string 또는 string 목록, 필수): LoRA 어댑터의 고유 식별자. 단일 문자열 또는 여러 LoRA의 문자열 목록일 수 있음lora_path(string 또는 string/None 목록, 선택):.safetensors파일 경로 또는 Hugging Face repo ID. 첫 로드에 필요하며, 캐시된 nickname을 재활성화할 때는 선택. 목록이면lora_nickname과 길이 일치해야 함target(string 또는 string 목록, 선택): LoRA를 적용할 트랜스포머. 목록이면lora_nickname과 길이 일치해야 함. 유효한 값:"all"(기본값): 모든 트랜스포머에 적용"transformer": 기본 트랜스포머에만 적용 (Wan2.2의 고노이즈)"transformer_2": transformer_2에만 적용 (Wan2.2의 저노이즈)"critic": critic 모델에만 적용
strength(float 또는 float 목록, 선택): 병합용 LoRA 강도, 기본 1.0. 목록이면lora_nickname과 길이 일치해야 함.< 1.0값은 효과를 줄이고> 1.0값은 효과를 증폭merge_mode(string, 선택):"auto"(기본 서버 정책),"merge"(정적 병합 강제) 또는"dynamic"(forward 시 LoRA 적용)
단일 LoRA 예시:
curl -X POST http://localhost:30010/v1/set_lora \
-H "Content-Type: application/json" \
-d '{
"lora_nickname": "lora_name",
"lora_path": "/path/to/lora.safetensors",
"target": "all",
"strength": 0.8
}'
여러 LoRA 예시:
curl -X POST http://localhost:30010/v1/set_lora \
-H "Content-Type: application/json" \
-d '{
"lora_nickname": ["lora_1", "lora_2"],
"lora_path": ["/path/to/lora1.safetensors", "/path/to/lora2.safetensors"],
"target": ["transformer", "transformer_2"],
"strength": [0.8, 1.0]
}'
동일 대상의 여러 LoRA:
curl -X POST http://localhost:30010/v1/set_lora \
-H "Content-Type: application/json" \
-d '{
"lora_nickname": ["style_lora", "character_lora"],
"lora_path": ["/path/to/style.safetensors", "/path/to/character.safetensors"],
"target": "all",
"strength": [0.7, 0.9]
}'
Note 여러 LoRA를 사용할 때:
- 모든 목록 파라미터(
lora_nickname,lora_path,target,strength)는 길이가 같아야 함target또는strength가 단일 값이면 모든 LoRA에 적용됨- 같은 대상에 적용되는 여러 LoRA는 순서대로 적용됨
LoRA 가중치 병합
현재 설정된 LoRA 가중치를 기본 모델에 수동 병합해요.
Note FSDP-샤딩 가중치에서 수동 병합은 전체 gather를 요구하고 OOM할 수 있어요. 낮은 피크 경로에는
merge_mode="auto"또는"dynamic"으로set_lora를 사용해요.
엔드포인트: POST /v1/merge_lora_weights
파라미터:
target(string, 선택): 병합할 트랜스포머. "all"(기본), "transformer", "transformer_2", "critic" 중 하나strength(float, 선택): 병합용 LoRA 강도, 기본 1.0.< 1.0값은 효과를 줄이고> 1.0값은 효과를 증폭
Curl 예시:
curl -X POST http://localhost:30010/v1/merge_lora_weights \
-H "Content-Type: application/json" \
-d '{"strength": 0.8}'
LoRA 가중치 병합 해제
현재 활성 LoRA 가중치를 기본 모델에서 병합 해제하여 원래 상태로 복원해요. 다른 LoRA를 설정하기 전에 반드시 호출해야 해요.
엔드포인트: POST /v1/unmerge_lora_weights
Curl 예시:
curl -X POST http://localhost:30010/v1/unmerge_lora_weights \
-H "Content-Type: application/json"
LoRA 어댑터 나열
로드된 LoRA 어댑터와 모듈별 현재 적용 상태를 반환해요.
엔드포인트: GET /v1/list_loras
Curl 예시:
curl -sS -X GET "http://localhost:30010/v1/list_loras"
응답 예시:
{
"loaded_adapters": [
{ "nickname": "lora_a", "path": "/weights/lora_a.safetensors" },
{ "nickname": "lora_b", "path": "/weights/lora_b.safetensors" }
],
"active": {
"transformer": [
{
"nickname": "lora2",
"path": "tarn59/pixel_art_style_lora_z_image_turbo",
"merged": true,
"mode": "merged",
"strength": 1.0
}
]
}
}
참고 사항:
- 현재 파이프라인에서 LoRA가 활성화되지 않으면 서버가 오류를 반환해요.
num_lora_layers_with_weights는 활성 어댑터에 대해 LoRA 가중치가 적용된 레이어만 셈.
LoRA 전환 예시 (Example: Switching LoRAs)
- LoRA A 설정:
curl -X POST http://localhost:30010/v1/set_lora -d '{"lora_nickname": "lora_a", "lora_path": "path/to/A"}' - LoRA A로 생성...
- LoRA A 병합 해제:
curl -X POST http://localhost:30010/v1/unmerge_lora_weights - LoRA B 설정:
curl -X POST http://localhost:30010/v1/set_lora -d '{"lora_nickname": "lora_b", "lora_path": "path/to/B"}' - LoRA B로 생성...
출력 품질 조정 (Adjust Output Quality)
서버는 output-quality와 output-compression 파라미터를 통해 이미지 및 비디오 생성의 출력 품질과 압축 수준을 조정하는 것을 지원해요.
파라미터
-
output-quality(string, 선택): 압축을 자동 설정하는 사전 품질 수준. 기본값은"default". 유효한 값:"maximum": 최고 품질 (100)"high": 고품질 (90)"medium": 중간 품질 (55)"low": 저품질 (35)"default": 미디어 유형에 따라 자동 조정 (비디오 50, 이미지 75)
-
output-compression(integer, 선택): 직접 압축 수준 오버라이드 (0-100). 기본값은None. 제공되면(None이 아니면)output-quality보다 우선함.0: 최저 품질, 최소 파일 크기100: 최고 품질, 최대 파일 크기
참고 사항
- 우선순위:
output-quality와output-compression이 모두 제공되면output-compression이 우선해요. - 형식 지원: 품질 설정은 JPEG와 비디오 형식에 적용돼요. PNG는 무손실 압축을 사용하고 이 설정을 무시해요.
- 파일 크기 vs 품질: 더 낮은 압축 값(또는 "low" 품질 프리셋)은 더 작은 파일을 만들지만 보이는 아티팩트가 생길 수 있어요.