API Key 설정이 필요합니다
평소에는 컨테이너가 .env의 키를 /demo/env.js로 자동 주입합니다. 이 배너가 보이면 자동 주입에 실패했거나 키가 CHANGE_ME 상태이니, 상단 설정바에서 Client 선택 후 API Key를 직접 입력하세요.
입력한 키는 브라우저에 자동 저장되며, 클라이언트별로 각각 등록해야 합니다. 키 발급은 API Key Setup 섹션을 참고하세요.
RedGX Overview 개요
RedGX(Redis GPU eXchange)는 Redis를 매개로 GPU 연산 요청과 결과를 교환하는 비동기 GPU 연산 중계 서버입니다.
내부시스템A, 내부시스템B, 내부시스템C 등 이기종 시스템이 REST API로 임베딩·생성·번역·STT·OCR 요청을 제출하면, GPU Worker가 추론 서버에 연산을 위임하고 결과를 Redis를 통해 반환합니다.
핵심 가치: GPU 연산의 비동기 제출·대기·수신을 표준화된 REST/WebSocket API로 제공 — 클라이언트는 모델·GPU를 직접 다루지 않아도 됩니다.

아키텍처

Client (HRM / ERP / CRM) X-API-Key 헤더 / WS: Sec-WebSocket-Protocol 헤더로 인증 Nginx (443/TLS) ──── TLS 종료, 보안 헤더, Rate Limit (10r/s) Docker 내부 HTTP RedGX (8080, 내부) ── API Key 인증 → NS 권한 검사 → 요청 큐 등록 (Redis) │ ▲ │ └────────────────────────────── 결과 수신 (Redis outbox) Redis GPU (6379) ──── 인메모리 큐 (inbox / outbox / cache) 배치 팝 (pop_batch.lua) GPU Worker ──────── embed / generate / translate / stt / ocr HTTP (배치 요청) 추론 서버 ─────────── TEI / vLLM / Whisper / NLLB / PaddleOCR → GPU
Monitoring: Grafana Dashboard ↗ — 실시간 요청 수, 레이턴시, Redis 상태 모니터링 (admin / .env의 GRAFANA_ADMIN_PASSWORD)

비영속 원칙 (Ephemeral)

중요: Redis는 순수 인메모리로 운영됩니다. RDB/AOF 모두 비활성화되어 있으며, 서비스 중단/재시작 시 모든 데이터가 소멸됩니다. 영구 저장이 필요한 데이터는 각 시스템의 자체 DB에 보관해야 합니다.

서버 기본값 & 제한

config/config.yamldefaults 섹션에서 설정됩니다.
항목기본값설명
ttl86,400초 (24시간)GPU 결과 캐시 TTL. ttl: 0이면 만료 없음(PERSIST).
max_value_size1,048,576 (1MB)요청 페이로드 최대 크기. 초과 시 VALUE_TOO_LARGE (400).

네임스페이스 & 권한 모델

각 클라이언트는 API Key로 인증되며, 네임스페이스(NS) 단위로 읽기/쓰기 권한이 분리됩니다. shared 네임스페이스는 모든 시스템이 공유하는 공간입니다.
Client자기 NS (read+write)교차 NS (read only)shared (read+write)
HRMHRMERPshared
ERPERPHRM, CRMshared
CRMCRMERPshared
MONITOR모든 네임스페이스 read only (와일드카드 *)
admin모든 네임스페이스 read+write (와일드카드 *)

Redis 키 형식

namespace{namespace}
:
type prefix{type_prefix}
:
key{key}
GPU 태스크 접두어 (내부 키, Admin API 조회용)
gpu_relay:embed임베딩
gpu_relay:generation텍스트 생성
gpu_relay:translation번역
gpu_relay:stt음성 인식
gpu_relay:ocr문자 인식
예시 (Admin API 키 조회)
HRM: gpu_relay:embed: emb-20260101000000-abc123 HRM:gpu_relay:embed:emb-20260101000000-abc123 임베딩 결과 캐시
ERP: gpu_relay:ocr: ocr-20260101120000-xyz789 ERP:gpu_relay:ocr:ocr-20260101120000-xyz789 OCR 결과 캐시
키 형식 참고 사항
GPU Relay의 Redis 키는 내부적으로 관리되며 클라이언트가 직접 조작하지 않습니다. Admin API(/admin/keys, /admin/info/{ns}/{type}/{key})를 통해 키를 조회할 수 있습니다.
  • inbox — 처리 대기 중인 요청 큐 (Worker가 배치로 팝)
  • outbox — 완료된 결과 저장소 (클라이언트가 조회 또는 WS로 push 수신)
  • cache — 동일 요청 재사용을 위한 결과 캐시
GPU 태스크 가이드 태스크 선택
RedGX는 5가지 GPU 태스크를 비동기 REST API로 제공합니다. 처리 목적에 따라 적절한 태스크를 선택하세요.
태스크모델입력출력실전 예시
Embedding BGE-M3 (TEI) 텍스트 벡터 (float[]) 유사도 검색 문서 클러스터링 RAG
Generation EXAONE (vLLM) 텍스트 (프롬프트) 생성 텍스트 요약 보고서 초안 Q&A
Translation NLLB-200 텍스트 + 언어쌍 번역 텍스트 ko→en en→ko 다국어 보고서
STT Faster-Whisper 오디오 파일 (Base64) 전사 텍스트 + 세그먼트 회의록 음성 기록 자막 생성
OCR PaddleOCR 이미지 파일 (Base64) 인식 텍스트 + 박스 좌표 문서 스캔 지문 카드 인식 증거물 텍스트

요청 흐름 (공통)

1. 요청 제출
POST /api/v1/ns/{ns}/gpu/{task} → req_id 반환 (202 Accepted)
2. 결과 대기 (권장: WebSocket)
WS wss://{host}/api/v1/ns/{ns}/gpu/{task}/{req_id}/wait → 완료 시 결과 push (close 4008=timeout)
2. 결과 조회 (대안: 폴링)
GET /api/v1/ns/{ns}/gpu/{task}/{req_id} → 완료 시 200 + 결과 / 처리 중 404
3. (선택) 취소
POST /api/v1/ns/{ns}/gpu/{task}/{req_id}/cancel → 처리 전 취소 가능
WS vs 폴링
WebSocket /wait는 서버가 완료를 push하므로 불필요한 HTTP 왕복이 없습니다. HTTP 폴링은 simple하지만 처리 시간에 비례해 요청이 증가합니다. 실시간 응답이 필요한 경우 WS를 권장합니다.
Response Format & Error Codes 응답 형식
모든 API는 일관된 JSON 형식으로 응답합니다. 클라이언트 개발 시 아래 형식을 기준으로 파싱하세요.

성공 응답

{ "ok": true, "data": { // 요청에 따라 달라지는 데이터 "value": "running", // KV의 경우 "fields": { ... }, // Map의 경우 }, "meta": { "ns": "ERP", // 네임스페이스 "key": "case:001", // 키 이름 "type": "hash", // Redis 데이터 타입 "ttl": 86400 // 남은 TTL (초), -1=무기한 } }

에러 응답

{ "detail": { "ok": false, "error": { "code": "NAMESPACE_DENIED", "message": "Access to namespace 'HRM' with 'write' permission is not allowed for client 'CRM'" } } }

HTTP 상태 코드

코드의미발생 상황대응
200OK정상 조회/수정/삭제data 필드 사용
400Bad Request키 형식 오류, 필수 필드 누락, 값 크기 초과요청 파라미터 확인
401UnauthorizedAPI Key 누락 또는 잘못됨X-API-Key 헤더 확인
403Forbidden해당 NS에 대한 권한 없음권한 매트릭스 확인
404Not Found키가 존재하지 않음키 이름/NS 확인
409ConflictNX(분산 락)에서 키 이미 존재이미 락이 잡혀 있음
422Unprocessable Entity요청 본문 검증 실패 (필드 타입 오류 등)요청 JSON 구조 확인
429Too Many RequestsRate Limit 초과 (10r/s)요청 빈도 줄이기
500Internal Server ErrorRedis 연결 실패, 예기치 않은 서버 오류서버 로그 확인

에러 코드 상세

에러 응답의 error.code 필드에 반환되는 코드입니다. 클라이언트에서 이 코드를 기준으로 분기 처리하세요.
에러 코드HTTP발생 상황
UNAUTHORIZED401API Key 누락 또는 유효하지 않음
NAMESPACE_DENIED403해당 네임스페이스에 대한 권한(read/write) 없음
ADMIN_REQUIRED403관리자 전용 엔드포인트에 일반 키로 접근
INVALID_NAMESPACE400네임스페이스 형식 오류 (영숫자, _, - / 1~64자)
INVALID_KEY400키 형식 오류 (영숫자, _, ., :, -, / / 1~256자)
VALUE_TOO_LARGE400값 크기가 max_value_size(기본 1MB) 초과
KEY_NOT_FOUND404Admin API에서 조회한 키가 Redis에 존재하지 않음
429nginx Rate Limit 초과 (IP당 10 r/s, burst 20). 응답은 plain HTML, JSON 코드 없음
INTERNAL_ERROR500Redis 연결 실패 또는 내부 오류
API Key Setup 설정 안내
RedGX의 모든 API(Health 제외)는 X-API-Key 헤더를 통한 인증이 필요합니다. API Key는 관리자가 config/config.yaml에 등록하며, 운영 시에는 환경변수로 오버라이드합니다.

1. API Key 발급

API Key는 관리자에게 발급받습니다.
설정 파일(config/config.yaml)의 clients 항목에 등록되며, 환경변수 REDGX_CLIENT_{ID}_API_KEY로 오버라이드됩니다.
예: REDGX_CLIENT_ERP_API_KEY=your-actual-key-here

2. 이 페이지에서 API Key 설정

아래 순서로 상단 설정바에 API Key를 등록하면, 모든 테스트에서 자동으로 사용됩니다.
단계설명
Step 1상단 Client 드롭다운에서 HRM 선택
Step 2API Key 입력란에 HRM용 실제 키 입력 (자동 저장됨)
Step 3Client를 ERP로 변경 후 ERP용 키 입력
Step 4Client를 CRM로 변경 후 CRM용 키 입력
Step 5(선택) Client를 MONITOR으로 변경 후 모니터링 키 입력
Step 6(선택) Client를 admin으로 변경 후 관리자 키 입력
자동 저장: 입력한 키는 브라우저의 localStorage에 클라이언트별로 저장됩니다. 페이지를 새로고침하거나 재방문해도 유지됩니다.

3. API 호출 시 인증

# 모든 API 요청에 X-API-Key 헤더를 포함 curl -s -X GET "https://host/api/v1/ns/HRM/gpu/embed/emb-20260101000000-abc123" \ -H "X-API-Key: your-api-key-here" # WebSocket은 Sec-WebSocket-Protocol 헤더로 키 전달 (URL 쿼리 미지원) wss://host/api/v1/ns/HRM/gpu/embed/emb-20260101000000-abc123/wait?timeout=10 // 키: Sec-WebSocket-Protocol 헤더

4. curl 호출 시 API Key 설정

매번 긴 API Key를 입력하지 않도록 환경변수로 등록해 두면 편리합니다. .env 파일의 값을 사용하세요.
# .env에서 API Key 로드 source .env # 또는 시스템별 API Key를 직접 환경변수로 등록 export HRM_API_KEY=$REDGX_CLIENT_HRM_API_KEY export ERP_API_KEY=$REDGX_CLIENT_ERP_API_KEY export CRM_API_KEY=$REDGX_CLIENT_CRM_API_KEY export MONITOR_API_KEY=$REDGX_CLIENT_MONITOR_API_KEY export ADMIN_API_KEY=$REDGX_ADMIN_API_KEY # 이후 curl 호출 시 변수 참조 curl -s -X POST "https://host/api/v1/ns/HRM/gpu/embed" \ -H "X-API-Key: ${HRM_API_KEY}" \ -H "Content-Type: application/json" \ -d '{"text": "지문 감식 대상 텍스트"}'
API Key 구분 — 상수 vs 가변
변수구분설명
ADMIN_API_KEY상수RedGX 관리용 (stats, TTL 설정, 키 삭제 등) — 어떤 환경이든 필수
MONITOR_API_KEY상수전 네임스페이스 읽기 전용 — 운영 모니터링 시 필요
HRM_API_KEY가변연동 대상 시스템에 따라 추가·삭제·변경
본 튜토리얼의 HRM / ERP / CRM는 데모용 예시이며,
실 환경에서는 config/config.yaml의 clients에 맞게 구성
ERP_API_KEY가변
CRM_API_KEY가변
Patterns & Recipes 활용 패턴
GPU 연산 요청을 제출하고 결과를 수신하는 실전 활용 패턴입니다.

1. WebSocket 대기 (권장 패턴)

요청 제출 후 WebSocket으로 결과를 실시간으로 수신합니다. 서버가 완료를 push하므로 불필요한 HTTP 왕복이 없습니다.
Step 1 [요청 제출] POST /api/v1/ns/HRM/gpu/embed body: {"text": "지문 감식 대상 텍스트"} → 202 Accepted + {"ok": true, "data": {"req_id": "emb-20260101000000-abc123"}} ↓ Step 2 [WS 연결 — 결과 대기] WS wss://host/api/v1/ns/HRM/gpu/embed/emb-20260101000000-abc123/wait?timeout=10 → 완료 시: {"ok": true, "data": {"embeddings": [...]}} → 타임아웃: close code 4008 → 인증 실패: HTTP 403 (upgrade 거부, accept 전)

2. 폴링 (간단 대안)

WebSocket을 사용할 수 없는 환경에서 결과를 주기적으로 조회합니다. 처리 시간이 길수록 HTTP 요청 수가 늘어나므로 WS 방식을 권장합니다.
Step 1 [요청 제출] POST /api/v1/ns/ERP/gpu/translate body: {"text": "수사 보고서", "source_lang": "ko", "target_lang": "en"} → 202 + req_id: "tra-20260101120000-xyz789" ↓ Step 2 [폴링 — 1초 간격] GET /api/v1/ns/ERP/gpu/translate/tra-20260101120000-xyz789 → 처리 중: 404 (아직 결과 없음) → 완료: 200 + {"ok": true, "data": {"translated_text": "Investigation report"}}

3. STT — 오디오 파일 전사

오디오 파일을 Base64로 인코딩하여 제출하고, 전사 텍스트와 세그먼트를 수신합니다. 처리 시간이 길어 WS 대기 권장 (timeout=120 이상).
Step 1 [오디오 인코딩] AUDIO_B64=$(base64 -w 0 meeting.wav) ↓ Step 2 [요청 제출] POST /api/v1/ns/ERP/gpu/stt body: {"audio_data": "$AUDIO_B64", "audio_format": "wav", "language": "ko"} → 202 + req_id: "stt-20260101130000-def456" ↓ Step 3 [WS 대기] WS wss://host/api/v1/ns/ERP/gpu/stt/stt-20260101130000-def456/wait?timeout=120 → {"ok": true, "data": {"text": "회의 내용...", "segments": [...]}}

4. 작업 취소

아직 Worker가 처리하지 않은 요청을 취소합니다. 이미 처리 중인 요청은 취소되지 않습니다.
POST /api/v1/ns/HRM/gpu/embed/emb-20260101000000-abc123/cancel → 취소 성공: 200 + {"ok": true, "data": {"cancelled": true}} → 이미 처리됨: 200 + {"ok": true, "data": {"cancelled": false}} → req_id 없음: 404

5. 네임스페이스 교차 접근

권한 모델에 따라 다른 NS에서 제출된 GPU 결과를 조회할 수 있습니다. ERP는 HRM의 임베딩 결과를 read 권한으로 조회 가능합니다.
[HRM — 임베딩 제출 및 결과 저장] POST /api/v1/ns/HRM/gpu/embed → req_id: "emb-xxx" ↓ (결과 완료 후) [ERP — 교차 조회 성공] GET /api/v1/ns/HRM/gpu/embed/emb-xxx → ERP는 HRM에 대해 read 권한 있음 → 200 OK[CRM — 교차 조회 거부] GET /api/v1/ns/HRM/gpu/embed/emb-xxx → CRM는 HRM read 권한 없음 → 403 NAMESPACE_DENIED
E2E 시나리오 통합 테스트
실제 업무 흐름 시뮬레이션: OCR → 임베딩 → ERP 교차 조회
[HRM] 지문 카드 이미지 → OCR 요청 제출 + WS 대기
   ↓
[HRM] OCR 결과(텍스트) → 임베딩 요청 제출 + WS 대기
   ↓
[HRM] 임베딩 벡터 수신 → 검색 DB에 저장
   ↓
[ERP] HRM 임베딩 결과 교차 조회 (read 권한) → 유사도 검색
# Step 1: OCR 요청 IMG_B64=$(base64 -w 0 fingerprint-card.jpg) REQ=$(curl -s -X POST "https://host/api/v1/ns/HRM/gpu/ocr" \ -H "X-API-Key: ${HRM_API_KEY}" \ -H "Content-Type: application/json" \ -d "{\"image_data\": \"$IMG_B64\", \"image_format\": \"jpg\"}") OCR_ID=$(echo $REQ | python -c "import sys,json; print(json.load(sys.stdin)['data']['req_id'])") # Step 2: WS로 OCR 결과 대기 (별도 프로세스/언어에서 처리) # OCR_TEXT = WS wss://host/api/v1/ns/HRM/gpu/ocr/$OCR_ID/wait?timeout=60 # Step 3: 임베딩 요청 EMB=$(curl -s -X POST "https://host/api/v1/ns/HRM/gpu/embed" \ -H "X-API-Key: ${HRM_API_KEY}" \ -H "Content-Type: application/json" \ -d "{\"text\": \"$OCR_TEXT\"}") EMB_ID=$(echo $EMB | python -c "import sys,json; print(json.load(sys.stdin)['data']['req_id'])") # Step 4: ERP 교차 조회 (HRM NS에 read 권한) curl -s "https://host/api/v1/ns/HRM/gpu/embed/$EMB_ID" \ -H "X-API-Key: ${ERP_API_KEY}"
Health & Ready 운영 · 무인증
LB / 모니터링 시스템이 호출하는 헬스체크 엔드포인트입니다. 모두 인증 불필요하며, 200 / 503 코드로 분기됩니다.
/health
Redis 연결 + 메모리 사용량. degraded 시에도 HTTP 200 유지 (status 필드로 판정)
GET
GET/health
{
  "status": "healthy",
  "redis": {"connected": true, "latency_ms": 0.5, "used_mb": 1.8, "limit_mb": 256, "usage_pct": 0.7}
}
/health/gpu
추론 서버 5종 + Worker 상태 — GPU Relay 비활성 시 503
GET
GET/health/gpu
{
  "status": "healthy",                 // healthy / degraded / unhealthy / idle
  "gpu_relay": true,
  "inference_servers": {"tei": {"healthy": true, "status_code": 200, ...}, ...},
  "tasks": {
    "embedding": {"enabled": true, "worker_alive": true, "client_connected": true,
                  "inference_server": "tei", "inference_server_healthy": true},
    ...
  }
}
/ready 신규
GPU Worker 워밍업 완료 + drain 모드 아님 — LB 트래픽 라우팅 결정용
GET
GET/ready
// 모든 활성 task ready → 200
{"ready": true, "gpu_relay": true, "reason": "ready", "draining": false,
 "tasks": {"translation": {"ready": true, "reason": "ready"}, ...}}

// 일부 task 워밍업 중 → 503 (LB가 트래픽 보내면 안 됨)
{"ready": false, "gpu_relay": true, "reason": "warming up", "draining": false,
 "tasks": {"stt": {"ready": false, "reason": "warming_up"}, ...}}

// drain 모드 (SIGTERM 후) → 503 (LB가 트래픽 빼야 함)
{"ready": false, "gpu_relay": true, "reason": "draining", "draining": true, ...}
LB 헬스체크는 /health(Redis ping)가 아니라 /ready(GPU 준비)를 봐야 합니다. 워밍업 중인 노드에 트래픽이 들어가지 않고, SIGTERM 시 trap → drain → 트래픽 자연 분산됩니다.
GPU Monitor 실시간
GPU Relay Worker 상태, 추론 서버 연결 상태, 로드된 모델을 실시간으로 모니터링합니다.
GPU Health는 인증 없이 조회 가능하며, Worker 상태 / 모델 정보admin API Key가 필요합니다.
GPU Health
추론 서버 연결 상태 · 태스크별 Worker 생존 여부 — 인증 불필요
GET
GET/health/gpu
새로고침을 눌러 조회하세요.
Worker 상태
태스크별 Worker 실행/일시정지, 큐 대기 수, 처리 중 수 — admin API Key 필요
GET
GET/admin/gpu-relay/status
새로고침을 눌러 조회하세요.
모델 정보
로드된 모델명, 추론 서버 연결 여부 — admin API Key 필요
GET
GET/admin/gpu-relay/models
새로고침을 눌러 조회하세요.
모델 카탈로그 /v1/models
OpenAI 호환 카탈로그 형식 + RedGX 확장 정보를 한 번에 노출합니다. 인증 불필요 — Worker 상태 / Circuit Breaker 상태 / 큐 깊이 / inflight 모두 한 응답에서 확인 가능.
GET /v1/models 신규
활성 task의 모델 목록 + worker/CB/queue 상태 일괄 조회
GET
GET/v1/models
{
  "object": "list",
  "data": [
    {"id": "BAAI/bge-m3", "object": "model", "created": 0, "owned_by": "redgx", "task": "embedding"},
    {"id": "LGAI-EXAONE/EXAONE-4.0-1.2B", "object": "model", "owned_by": "redgx", "task": "generation"}
  ],
  "redgx": {
    "gpu_relay": true,
    "draining": false,
    "tasks": {
      "embedding": {
        "enabled": true,
        "model": "BAAI/bge-m3",
        "inference_server": {"id": "tei", "base_url": "http://gpu-tei-embedding:8080"},
        "worker": {"running": true, "paused": false, "ready": true, "reason": "ready"},
        "queue_depth": 0,
        "inflight": 0,
        "circuit_breaker": {"state": "closed", "failure_count": 0, "trips_total": 0, ...}
      },
      "generation": {"enabled": false}, ...
    }
  }
}
OpenAI 클라이언트 호환client.models.list()로 호출 가능. 단 data[].task 필드는 RedGX 확장.
Prometheus 메트릭 관측성
두 종류의 메트릭 엔드포인트를 노출합니다. 운영 도구 종류에 따라 적절한 것을 사용하세요.
/metrics admin 인증
HTTP 요청 메트릭 + Redis 상태 (request 카운터, latency 분포, NS별 키 수 등)
GET
GET/metrics
# HELP redgx_requests_total Total requests by HTTP status
# TYPE redgx_requests_total counter
redgx_requests_total{status="200"} 1763
redgx_request_duration_ms_bucket{le="5"} 695
redgx_redis_memory_bytes 1878296
...
/metrics/prom 신규 · 무인증
GPU Relay 전용 시리즈 — 큐/inflight/배치 크기/추론 지연/에러 분류
GET
GET/metrics/prom
# Counter
redgx_gpu_submitted_total{task="embedding"} 1234
redgx_gpu_completed_total{task="embedding"} 1230
redgx_gpu_inference_errors_total{task="embedding",kind="timeout"} 2

# Gauge (실시간)
redgx_gpu_queue_depth{task="embedding"} 5
redgx_gpu_inflight{task="embedding"} 8

# Histogram (배치 크기)
redgx_gpu_batch_size_bucket{task="embedding",le="8"} 100
redgx_gpu_batch_size_sum{task="embedding"} 450
redgx_gpu_batch_size_count{task="embedding"} 100

# Histogram (추론 지연 — task × server 라벨)
redgx_gpu_inference_latency_seconds_bucket{task="embedding",server="tei",le="0.5"} 50
redgx_gpu_inference_latency_seconds_sum{task="embedding",server="tei"} 12.3
redgx_gpu_inference_latency_seconds_count{task="embedding",server="tei"} 100
error kind: timeout · http_5xx · http_4xx · connect · parse_error · other — 추론 서버 장애 분류 추적.
Prometheus scraper는 본 endpoint(/metrics/prom)만 수집해도 GPU 시리즈 전체 획득.
본 endpoint는 nginx 레벨에서 내부 IP 대역(10/8, 172.16/12, 192.168/16, 127.0.0.1)만 허용. 외부 노출 금지.
GPU Relay GPU 연산 중계
RedGX의 핵심 기능입니다. GPU가 없는 일반 서버에서 Redis 큐를 통해 GPU 연산(임베딩·생성·번역·STT·OCR)을 비동기로 요청하고 결과를 수거합니다.
각 태스크는 독립 큐와 Worker를 가지며, 202 Accepted → 폴링 → 200 OK 흐름으로 동작합니다.
공통 요청 흐름
  1. POST /api/v1/ns/{ns}/gpu/{task}202 Accepted + req_id 반환
  2. GET /api/v1/ns/{ns}/gpu/{task}/{req_id} 폴링 → status: queued/processing/completed/failed
  3. status: completed 이후 결과 수거 (또는 ?auto_clear=true로 자동 삭제)
Embedding
텍스트 → 고밀도 벡터 (BAAI/bge-m3)
튜토리얼 →
POST /gpu/embed
유사도 검색 · RAG · 문서 클러스터링에 활용
Generation
텍스트 생성 LLM (EXAONE-4.0)
튜토리얼 →
POST /gpu/generate
요약 · 분류 · 질의응답 · 텍스트 완성
Translation
다국어 번역 (NLLB-200)
튜토리얼 →
POST /gpu/translate
한↔영 · 한↔중 · 한↔일 등 200개 언어 지원
STT
음성 인식 (Whisper-large-v3)
튜토리얼 →
POST /gpu/stt
오디오 파일 → 텍스트 (multipart/form-data)
OCR
문서 인식 (PaddleOCR PP-OCRv4)
튜토리얼 →
POST /gpu/ocr
이미지 · PDF → 구조화 텍스트 (multipart/form-data)
Backpressure: 큐가 가득 찬 경우 503 GPU_QUEUE_FULL이 반환됩니다. GPU Relay가 비활성 상태이면 503 GPU_TASK_DISABLED가 반환됩니다.
Readiness: Worker 워밍업 미완료 또는 drain 모드일 때도 503 GPU_UNAVAILABLE이 반환됩니다. 라우터 게이트 (check_backpressure)에 통합돼 있어 별도 호출 불필요.

운영 가시성 — Correlation ID · 워밍업 · Drain · Circuit Breaker

X-Request-ID: 요청에 X-Request-ID 헤더를 보내면 응답 헤더로 echo + audit 로그 (request_id_ext 필드) + 추론 서버 호출 헤더로 자동 전파됩니다. 보내지 않으면 RedGX가 UUID4 hex(32자)를 생성. 단일 요청 추적용 — 장애 발생 시 ID로 grep 가능.
X-Batch-ID: Worker가 묶음 처리한 단위. 응답 헤더에는 노출 안 되지만 audit 로그(batch_id 필드)와 추론 서버 호출 헤더에 자동 추가.
워밍업: Worker는 시작 직후 추론 서버에 더미 추론 1회를 비동기로 발사합니다. 성공 전까지 /ready는 503을 반환 — LB가 트래픽을 보내지 않도록. 실패 시 지수 백오프로 무한 재시도 (2 → 5 → 10 → 30 → 60초). /v1/modelstasks.{task}.worker.ready로 개별 task 상태 확인.
Graceful Drain: SIGTERM 수신 시 (1) /ready 503 시작 (2) pre_delay REDGX_DRAIN_PRE_DELAY_SECONDS(기본 2초) 대기 (3) Worker가 inflight 배치 완료 (4) task별 drain timeout 적용 — embedding/translation/stt/ocr 30초, generation 120초. 환경변수 REDGX_DRAIN_TIMEOUT_{TASK}_SECONDS로 오버라이드. docker-compose stop_grace_period: 130s가 보장 — 짧으면 SIGKILL로 inflight 손실.
Circuit Breaker: 추론 서버 server_id 단위로 상태 머신. 연속 실패 REDGX_CB_FAILURE_THRESHOLD(기본 5) 이상 → OPEN(차단). REDGX_CB_OPEN_TIMEOUT_SECONDS(기본 30초) 후 HALF_OPEN(probe). 성공 → CLOSED, 실패 → OPEN 재진입. OPEN 시 새 배치는 즉시 GPU_CIRCUIT_OPEN 에러로 fail-fast — 큐 적체 회피. /v1/modelstasks.{task}.circuit_breaker에서 상태 + 누적 trip 횟수 조회.
OpenAI 호환 API /v1/*
OpenAI Chat Completions / Embeddings 스펙 일부를 호환합니다. 기존 OpenAI Python/Node SDK · LangChain · LlamaIndex · OpenWebUI 등에서 코드 변경 없이 호출 가능 — base_url만 RedGX로 변경.
내부적으로는 RedGX 비동기 큐(/api/v1/ns/.../gpu/.)와 동일 Worker로 라우팅됩니다.

인증

두 헤더 모두 허용 (Bearer 우선):
  • Authorization: Bearer <api_key> — OpenAI 클라이언트 표준
  • X-API-Key: <api_key> — 기존 RedGX 클라이언트 호환
키 저장소·권한 모델은 단일 (config/config.yamlclients). ns는 client.client_id가 자동 사용 — 자기 namespace에 격리.
/v1/chat/completions
generation Worker로 라우팅 — 비동기 큐 → Pub/Sub 대기 → OpenAI 형식 응답 (timeout 기본 120초)
POST
POST/v1/chat/completions
// 요청
{
  "model": "LGAI-EXAONE/EXAONE-4.0-1.2B",
  "messages": [
    {"role": "system", "content": "당신은 한국어 비서입니다."},
    {"role": "user", "content": "파이썬과 자바의 차이점을 한 문장으로"}
  ],
  "max_tokens": 256,
  "temperature": 0.7
}

// 응답 (200)
{
  "id": "chatcmpl-xxx",
  "object": "chat.completion",
  "created": 1714200000,
  "model": "LGAI-EXAONE/EXAONE-4.0-1.2B",
  "choices": [{"index": 0, "message": {"role": "assistant", "content": "..."}, "finish_reason": "stop"}],
  "usage": {"prompt_tokens": 30, "completion_tokens": 50, "total_tokens": 80}
}

메시지 매핑 규칙

  • role: system → RedGX inbox system_prompt (다중이면 \n\n 결합)
  • role: user / assistant → chat-style 직렬화 (User: ...\nAssistant: ...)로 prompt에 합침
  • 마지막에 Assistant:를 붙여 모델 응답 유도

지원/비지원 필드

지원스트리밍 전용 (stream=true 시에만 forward)비지원 (무시 + 첫 호출 시 WARN 로그)거부 (400)
model · messages · max_tokens · temperature · stream top_p · stop tools · tool_choice · function_call · functions · logprobs · top_logprobs · frequency_penalty · presence_penalty · user · seed · response_format n != 1
top_p·stop비스트리밍 호출에서는 본문에 포함해도 무시됩니다 (Worker가 vLLM에 전달 안 함). 스트리밍(stream=true)에서만 vLLM에 직접 forward.
/v1/embeddings
embedding Worker로 라우팅 — RedGX 내부는 base64 vector, 응답은 float 배열(OpenAI 표준)
POST
POST/v1/embeddings
// 요청
{
  "model": "BAAI/bge-m3",
  "input": ["문장 1", "문장 2"],     // str 또는 list[str]
  "encoding_format": "float"        // "float"(기본) 또는 "base64"
}

// 응답 (200)
{
  "object": "list",
  "data": [
    {"object": "embedding", "index": 0, "embedding": [0.123, -0.456, ...]},
    {"object": "embedding", "index": 1, "embedding": [0.789, ...]}
  ],
  "model": "BAAI/bge-m3",
  "usage": {"prompt_tokens": 0, "total_tokens": 0}    // RedGX는 토큰 카운트 미제공
}
대량 호출 시 encoding_format: "base64" 권장 — float 변환 비용·대역폭 ~4배 절감. 단 클라이언트가 base64 디코딩 코드 보유해야 함.
SSE 스트리밍 (chat/completions stream=true) 신규
vLLM에 직접 프록시 — Redis 큐 우회. 토큰 단위 latency 최소화.
POST
POST/v1/chat/completions
// 요청
{
  "model": "LGAI-EXAONE/EXAONE-4.0-1.2B",
  "messages": [{"role": "user", "content": "파이썬 hello world"}],
  "stream": true
}

// 응답 (text/event-stream)
data: {"id":"...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":""}}]}

data: {"id":"...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"print"}}]}

data: {"id":"...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"(\"hello\")"}}]}

data: {"id":"...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: [DONE]
스트리밍 경로는 Redis 큐를 거치지 않습니다 (배치 효과 없음 — generation은 응답이 길어 큐 효과가 작음). Circuit Breaker는 동일하게 적용 — server_id 단위.
nginx에서 proxy_buffering off 필수 — 이미 nginx.conf.templatelocation = /v1/chat/completions에서 처리됨.

에러 형식 (OpenAI 표준)

// /v1/* 모든 에러는 detail wrap 없는 OpenAI 표준 형식
{"error": {"message": "...", "type": "invalid_api_key | invalid_request_error | server_error | timeout", "code": "..."}}

// 401 invalid_api_key
{"error": {"message": "Invalid API key", "type": "invalid_api_key", "code": "invalid_api_key"}}

// 400 invalid_request_error
{"error": {"message": "n != 1 not supported", "type": "invalid_request_error", "code": "invalid_request_error"}}

// 503 server_error (task disabled, queue full, warming up, draining, CB open)
// 504 timeout (Pub/Sub 대기 timeout)
// 502 server_error (추론 실패, result parse 실패)
Quick Reference 전체 API 요약
RedGX GPU Relay API 엔드포인트를 태스크별로 정리한 빠른 참조표입니다. Base URL: /api/v1

운영 / 모니터링 (무인증)

MethodPath설명Status 코드
GET/healthRedis 연결 + 메모리200 (degraded 시 status 필드)
GET/health/gpu추론 서버 5종 + Worker 상태200 / 503 (GPU Relay 비활성)
GET/ready워밍업 완료 + drain 모드 아님200 / 503 (warming up · draining)
GET/v1/models활성 task 모델 + worker/CB/queue 상태200
GET/metrics/promGPU Relay Prometheus 시리즈 (내부 IP만)200

운영 / 모니터링 (admin 인증)

MethodPath설명
GET/metricsHTTP 요청 메트릭 + Redis 상태
GET/admin/gpu-relay/statusWorker 실행/일시정지/큐 상태
GET/admin/gpu-relay/models로드된 모델 정보

OpenAI 호환 (Bearer 또는 X-API-Key)

MethodPath설명Worker
POST/v1/chat/completionsChat Completion (n=1, stream 옵션)generation
POST/v1/embeddingsEmbedding (input str/list, encoding_format)embedding

신규 환경변수 (기본값)

변수기본값설명
REDGX_DRAIN_TIMEOUT_GENERATION_SECONDS120generation Worker drain timeout
REDGX_DRAIN_TIMEOUT_{EMBEDDING|TRANSLATION|STT|OCR}_SECONDS30나머지 task drain timeout
REDGX_DRAIN_PRE_DELAY_SECONDS2drain 시작 후 LB 트래픽 분산 대기
REDGX_CB_FAILURE_THRESHOLD5Circuit Breaker OPEN 진입 연속 실패 수
REDGX_CB_OPEN_TIMEOUT_SECONDS30OPEN → HALF_OPEN 자동 전이 대기
REDGX_CB_SUCCESS_THRESHOLD1HALF_OPEN → CLOSED 성공 임계
REDGX_OPENAI_COMPAT_TIMEOUT_SECONDS120OpenAI 호환 비스트리밍 결과 대기 timeout

공통 헤더

헤더방향설명
X-Request-ID요청 ↔ 응답클라이언트 요청에 보내면 응답·로그·추론 서버 호출 헤더에 전파. 미전송 시 RedGX가 UUID4 hex 자동 생성.
X-Batch-ID추론 서버 호출 시Worker가 묶음 처리한 단위 ID. audit 로그·추론 서버 호출 헤더에 자동 추가 (응답 헤더 노출 안 함).
X-API-Key요청RedGX 자체 API 키 인증
Authorization: Bearer요청OpenAI 호환 라우터(/v1/*)에서 우선 인식