OVERVIEW GPU 번역 개요

Meta NLLB-200 기반 NMT(Neural Machine Translation) 번역 API입니다. 한↔영, 한↔중, 한↔일 등 12개 언어쌍을 지원하며, 단건과 다건(배치) 번역 모두 가능합니다. 결과는 캐시되어 동일 입력의 반복 번역 시 즉시 반환됩니다.

Meta NLLB-200-distilled-1.3B — Meta AI가 개발한 200개 언어 지원 번역 모델(No Language Left Behind). 1.3B 파라미터 경량 버전으로, 한↔영 BLEU 55/34점의 높은 품질을 제공합니다. Beam Search(5)와 N-gram 반복 억제로 자연스러운 번역을 생성하며, 장문은 자동 분할 후 병합합니다. 라이선스 CC-BY-NC-4.0(비상업적). FP16 VRAM ~3GB.
아키텍처 흐름
# 1. POST → 202 Accepted (request_id 반환)
POST /api/v1/ns/{ns}/gpu/translate
  → 202 { "request_id": "trl-1710000000000-a1b2c3d4", "task_type": "translation", "count": 1, "is_batch": false }

# 2. GET 폴링 → 완료 시 200
GET /api/v1/ns/{ns}/gpu/translate/{request_id}
  → 202 { "status": "queued" }
  → 200 { "status": "completed", "translated_text": "..." }

# 데이터 흐름 (언어코드 변환: ISO 639-1 → NLLB BCP-47)
Client → POST /gpu/translate (ko→en) → Redis Queue → TranslateWorker
  → kor_Hang→eng_Latn → NLLB-200 HTTP API → Redis Outbox → Client
지원 언어쌍 및 모델 정보
항목
번역 엔진Meta NLLB-200 (facebook/nllb-200-distilled-1.3B, FP16)
모델 선정RTX 3060 12GB 채택 — ~3GB VRAM, ko→en BLEU 55.0
고성능 GPU(24GB+): nllb-200-3.3B (BLEU +1점) / 4GB GPU: distilled-600M
지원 언어쌍 koenzhja (12쌍)
단건 최대 길이2,000 자 (NLLB 512 토큰 한계)
배치 최대 건수100 texts
캐시항상 활성 (결정론적 번역 — 동일 입력 = 동일 결과)
캐시 TTL24시간 (86400초)
폴링 권장 간격1초 (LLM보다 빠름)
POST 단건 번역

text 필드로 단일 문자열을 번역합니다. 완료 시 translated_text로 결과를 받습니다.

POST /api/v1/ns/{ns}/gpu/translate
curl 명령 보기

            
POST 다건 배치 번역

texts 배열로 여러 문장을 한 번의 요청으로 번역합니다. 결과는 translated_texts 배열로 반환되며 인덱스가 1:1 대응됩니다. 단건(text)과 다건(texts)은 동시에 사용할 수 없습니다.

POST texts[] 배열 요청
💡 배치 번역 활용: DB 레코드 다건 번역, 리포트 자동 번역 등 동일 언어쌍의 여러 문장을 한 번에 처리할 때 효율적입니다.
1
2
3
curl 명령 보기

            
POST 다건 배치 번역 (장문 포함 시)

texts[] 배열 5건 중 2건이 200자를 초과하는 장문입니다. NLLB 서버는 각 텍스트를 내부적으로 청크 분할하여 번역한 뒤 결과를 다시 합쳐 반환하므로, 클라이언트는 별도 분할 없이 원문 그대로 제출하면 됩니다. 단건(text)과 다건(texts)은 동시에 사용할 수 없습니다.

POST texts[] 배열 요청 — 단문 3건 + 장문 2건
💡 서버 측 자동 청크 분할: NLLB 서버 NLLB_CHUNK_CHAR_LIMIT(기본 200자)를 초과하는 텍스트는 서버가 문장 경계 기준으로 자동 분할·번역·병합합니다. 클라이언트가 직접 분할할 필요 없이 원문 그대로 제출하세요.
1
2
3
4
5
curl 명령 보기

            
장문 수사보고서 — 청크 분할 배치 번역 (NLLB 512 토큰 한계 대응)
⚠ NLLB 512 토큰 한계: 한국어 약 200자 이상이면 모델이 내부적으로 텍스트를 잘라냅니다. 장문은 200자 단위로 분할하여 texts[]로 제출해야 전체 내용이 누락 없이 번역됩니다.
전체 원문
분할 결과 미리보기 (~200자 단위, 문장 경계 우선 — 이 청크들이 texts[]로 전송됩니다)
curl 명령 보기

            
POST 언어쌍 비교

동일한 문장을 한→영, 영→한으로 동시에 번역하여 결과를 나란히 비교합니다. 영→한 역번역으로 번역 품질(재번역 일치도)을 직관적으로 확인할 수 있습니다.

한→영 / 영→한 동시 번역 (역번역 비교)
curl 명령 보기

            
POST 결과 캐시 테스트

번역은 결과가 결정론적이므로 캐시가 항상 활성됩니다 (temperature 무관). 동일한 텍스트·언어쌍 요청을 두 번 보내면 두 번째는 즉시 반환됩니다.

캐시 키: SHA-256(모델명 + source_lang + target_lang + sorted_texts) — 언어쌍을 포함해 오번역 방지
1회차 → 2회차 캐시 적중 확인
curl 명령 보기

            
MANAGE 결과 관리 — 조회 / 삭제 / 취소

결과는 outbox에 1시간(3600초) 보관됩니다.

GET 결과 조회
curl 명령 보기

            
DELETE 결과 삭제
curl 명령 보기

            
POST 요청 취소
큐 대기 중인 요청만 취소 가능. 처리 중이면 409 반환.
curl 명령 보기

            
POST 배치 상태 일괄 조회

여러 request_id 상태를 한 번의 API 호출로 조회합니다.

POST /gpu/translate/batch-status
curl 명령 보기

            
ERROR 에러 케이스

번역 전용 에러(INVALID_LANG_PAIR)를 포함한 다양한 오류 상황을 테스트합니다.

REF API 레퍼런스
POST /api/v1/ns/{ns}/gpu/translate — 요청 파라미터
필드타입기본값설명
textstring | null단건 번역 텍스트. texts와 동시 사용 불가 (둘 중 하나 필수)
textsstring[] | null다건 번역 텍스트 배열. text와 동시 사용 불가
source_langstring필수원어 ISO 639-1 코드 (ko, en)
target_langstring필수번역 언어 ISO 639-1 코드
modelstring | null서버 기본값NMT 모델명 (null = 서버 설정값)
POST 202 Accepted 응답
{
  "ok": true,
  "data": {
    "request_id": "trl-1710567890123-a1b2c3d4",
    "task_type":  "translation",
    "count":      3,        // texts 배열 길이
    "is_batch":   true      // texts[] 사용 시 true
  }
}
GET 완료 응답 구조 (HTTP 200)
// 단건 (text 사용 시)
{
  "ok": true,
  "data": {
    "request_id":      "trl-1710567890123-a1b2c3d4",
    "status":          "completed",
    "translated_text": "The suspect left the scene at 2 PM on March 5th...",
    "translated_texts": null,
    "source_lang":     "ko",
    "target_lang":     "en",
    "count":           1,
    "model":           "facebook/nllb-200-distilled-1.3B",
    "cached":          false,
    "elapsed_ms":      312.5
  }
}

// 다건 (texts[] 사용 시)
{
  "ok": true,
  "data": {
    "translated_text":  null,
    "translated_texts": ["Fingerprints matched...", "3 shell casings..."],
    "count": 2,
    ...
  }
}
필드설명
request_id요청 ID
statuscompleted 또는 failed
translated_text단건 번역 결과 문자열 (다건 시 null)
translated_texts다건 번역 결과 배열 (단건 시 null)
source_lang원어 코드
target_lang번역 언어 코드
count번역된 텍스트 수
model실제 사용된 NMT 모델명
cached캐시 적중 여부
elapsed_ms전체 처리 시간 (ms)
에러 코드
코드HTTP설명
INVALID_LANG_PAIR400미지원 언어쌍 (supported_pairs 목록 외)
GPU_INVALID_INPUT400텍스트 길이 초과(2000자) 또는 texts 건수 초과(100건)
UNAUTHORIZED401API Key 누락 또는 잘못됨
NAMESPACE_DENIED403Namespace 접근 권한 없음
GPU_NOT_FOUND404Request ID 없음 또는 만료 (TTL 3600s)
GPU_TASK_DISABLED503translation 태스크 비활성 (REDGX_GPU_TRANSLATION_ENABLED=false)
GPU_UNAVAILABLE503CUDA 불가 또는 NLLB-200 모델 로드 실패
GPU_QUEUE_FULL503큐 용량 초과
GPU_PROCESSING409취소 불가 — 이미 처리 중
422파라미터 유효성 오류 (text/texts 동시 지정 등) — FastAPI 기본 형식: {"detail":[...]}, error.code 없음
429nginx Rate Limit 초과 (IP당 10 r/s, burst 20). 응답은 plain HTML, JSON 코드 없음
WS /api/v1/ns/{ns}/gpu/translate/{req_id}/wait — 결과 Push 대기

Redis Pub/Sub으로 완료 알림을 수신 후 즉시 번역 결과를 전송합니다.

// 인증: Sec-WebSocket-Protocol 헤더로 API 키 전달 (URL 쿼리 미지원)
// 브라우저: new WebSocket(url, ["redgx_ak_erp_..."])
wss://<host>/api/v1/ns/ERP/gpu/translate/trl-xxx/wait?timeout=10          // timeout 기본 10, 최대 300
// 완료 — 단건 (text 사용 시)
{ "ok": true, "data": { "request_id": "trl-...", "status": "completed",
    "translated_text": "Hello", "translated_texts": null,
    "source_lang": "ko", "target_lang": "en", "count": 1,
    "model": "facebook/nllb-200-distilled-1.3B", "cached": false, "elapsed_ms": 210.0 } }

// 완료 — 다건 (texts[] 사용 시)
{ "ok": true, "data": { "request_id": "trl-...", "status": "completed",
    "translated_text": null, "translated_texts": ["Hello", "World"],
    "source_lang": "ko", "target_lang": "en", "count": 2,
    "model": "facebook/nllb-200-distilled-1.3B", "cached": false, "elapsed_ms": 215.0 } }

// 인증 실패 → HTTP 403 (upgrade 거부, accept 전 — 4001 close 프레임 미전송)
// close 코드: 4004=NotFound, 4008=Timeout