OVERVIEW
GPU 임베딩 개요
BAAI/bge-m3 모델 기반 텍스트 임베딩 API입니다. 텍스트를 1024차원 숫자 벡터로 변환하며, 의미적으로 유사한 텍스트는 가까운 벡터를 가집니다. 단건 및 배치(최대 100개) 모두 지원하며, 동일 입력의 반복 요청은 캐시에서 즉시 반환됩니다.
BAAI/bge-m3 — 베이징인공지능연구원(BAAI)이 개발한 다국어 임베딩 모델. 100개 이상의 언어를 단일 모델로 처리하며, Dense·Sparse·ColBERT 3가지 검색 방식을 동시에 지원합니다. 8192 토큰까지의 긴 문서도 처리 가능하고, 한국어·영어·중국어·일본어에서 우수한 성능을 보입니다. HuggingFace TEI(Text Embeddings Inference)로 서빙하여 Continuous Batching과 Flash Attention으로 높은 처리량을 확보합니다. VRAM ~2GB.
모델 정보
| 항목 | 값 |
|---|---|
| 모델 | BAAI/bge-m3 |
| VRAM | ~2 GB (FP16) |
| 출력 차원 | 1024 dim |
| 지원 언어 | 100개 언어 (한국어 포함) |
| 특징 | Dense + Sparse + ColBERT 멀티 벡터 지원 (Dense 사용) |
요청 흐름
POST /api/v1/ns/{ns}/gpu/embed → 202 +
↓ Worker가 bge-m3 모델로 추론
GET /api/v1/ns/{ns}/gpu/embed/{request_id} → 200 + 벡터 결과
DEL /api/v1/ns/{ns}/gpu/embed/{request_id} → 결과 삭제 (선택)
request_id↓ Worker가 bge-m3 모델로 추론
GET /api/v1/ns/{ns}/gpu/embed/{request_id} → 200 + 벡터 결과
DEL /api/v1/ns/{ns}/gpu/embed/{request_id} → 결과 삭제 (선택)
⚠️ 활성화 확인: Embedding 태스크가 활성화되어 있어야 합니다.
REDGX_GPU_EMBEDDING_ENABLED=true 환경변수 및 모델(BAAI/bge-m3) 로드 상태를 상단 설정바에서 확인하세요.
💡 시작 전 확인:
상단 설정바에서 API Key를 입력하세요. 쓰기 권한(
write)이 있는 키가 필요합니다.
Namespace는 HRM로 기본 설정되어 있습니다.
POST 기본 임베딩 요청
텍스트 1개를 제출하고 벡터 결과를 조회합니다.
1 요청
→
2 대기
→
3 결과
curl 명령 보기
POST 배치 임베딩
여러 텍스트를 한 번에 제출합니다. 순서가 보장됩니다.
curl 명령 보기
반환 구조:
vectors[i].index가 입력 순서와 일치하도록 보장됩니다.
모든 텍스트가 하나의 request_id로 묶여 처리됩니다.
POST 캐시 동작 확인
동일한 텍스트를 두 번 요청하면 두 번째는 GPU 없이 캐시에서 반환됩니다.
curl 명령 보기
캐시 키: SHA-256(모델명 + 텍스트 목록)로 생성됩니다.
같은 모델, 같은 텍스트면 언제나 캐시에서 반환됩니다. (
cached: true)
POST 코사인 유사도 계산
두 텍스트를 임베딩하고 의미적 유사도를 계산합니다.
curl 명령 보기
코사인 유사도: 1.0에 가까울수록 의미가 유사, 0에 가까울수록 관련 없음.
normalize: true로 임베딩 시 내적(dot product)이 곧 코사인 유사도입니다.
결과 조회 / 삭제 / 취소
결과 명시 삭제, auto_clear 옵션, 대기 중 취소를 테스트합니다.
GET 결과 조회 + auto_clear
curl 명령 보기
상태 코드 의미
| status | 의미 |
|---|---|
| queued | 큐 대기 중 (HTTP 202) |
| processing | GPU 추론 중 (HTTP 202) |
| completed | 완료 — 결과 포함 (HTTP 200) |
| failed | 추론 실패 (HTTP 200) |
| not_found | 결과 없음 / 만료 / 삭제됨 (HTTP 404) |
POST 배치 상태 일괄 조회
여러 request_id의 처리 상태를 한 번에 조회합니다.
curl 명령 보기
ERROR
에러 케이스
인증 실패, 잘못된 파라미터, 비활성 태스크 등 다양한 에러 상황을 테스트합니다.
에러 코드 목록
| 코드 | HTTP | 설명 |
|---|---|---|
UNAUTHORIZED | 401 | API Key 누락 또는 잘못됨 |
NAMESPACE_DENIED | 403 | Namespace 접근 권한 없음 |
| — | 422 | texts 빈 배열 등 Pydantic 유효성 오류 (FastAPI 기본 형식: {"detail":[...]}, error.code 없음) |
GPU_INVALID_INPUT | 400 | texts 100개 초과 (max_texts_per_request) |
GPU_NOT_FOUND | 404 | request_id 없음 또는 만료 (outbox TTL 3600s) |
GPU_PROCESSING | 409 | 취소 불가 — 이미 처리 중 (cancel 엔드포인트) |
GPU_TASK_DISABLED | 503 | embedding 태스크 비활성 (REDGX_GPU_EMBEDDING_ENABLED=false) |
GPU_UNAVAILABLE | 503 | Worker 워밍업 중 또는 drain 모드 |
GPU_QUEUE_FULL | 503 | 큐 용량 초과 (max_inflight 또는 max_requests 도달) |
GPU_CIRCUIT_OPEN | 200 (failed) | Worker 결과 — 추론 서버 Circuit Breaker OPEN 상태로 호출 차단 |
GPU_INFERENCE_FAILED | 200 (failed) | Worker 결과 — 추론 서버 호출 실패 / 예외 |
GPU_TIMEOUT | WS 4008 | WebSocket /wait 결과 대기 timeout 초과 |
| — | 429 | nginx Rate Limit 초과 (IP당 10 r/s, burst 20). 응답은 plain HTML, JSON 코드 없음 |
API 레퍼런스
전체 엔드포인트와 요청/응답 스키마입니다.
POST /api/v1/ns/{ns}/gpu/embed — 임베딩 요청
응답: 202 Accepted
{
"texts": ["텍스트1", "텍스트2"], // 필수, 1~100개
"model": null, // 선택, null이면 서버 기본값 (BAAI/bge-m3)
"normalize": true // 선택, L2 정규화 여부 (기본 true)
}{
"ok": true,
"data": {
"request_id": "emb-1710000000000-a1b2c3d4",
"task_type": "embedding",
"chunk_count": 1
}
}GET /api/v1/ns/{ns}/gpu/embed/{req_id} — 결과 조회
완료: 200 OK | 대기/처리중: 202 Accepted | 없음/만료: 404
// 완료 — HTTP 200, status: "completed"
// 결과 필드가 data 바로 아래 펼쳐짐 (중첩 없음)
{
"ok": true,
"data": {
"request_id": "emb-...",
"status": "completed",
"model": "BAAI/bge-m3",
"vectors": [
{
"index": 0,
"text": "원본 텍스트",
"embedding": "base64_encoded_float32_vector...",
"dim": 1024
}
],
"cached": false,
"elapsed_ms": 42.5
}
}
// 대기 중 — HTTP 202, status: "queued"
{ "ok": true, "data": { "request_id": "emb-...", "status": "queued" } }
// GPU 처리 중 — HTTP 202, status: "processing"
{ "ok": true, "data": { "request_id": "emb-...", "status": "processing" } }
// 추론 실패 — HTTP 200, status: "failed"
{ "ok": true, "data": { "request_id": "emb-...", "status": "failed", "error": {...} } }
// 없음/만료/삭제됨 — HTTP 404
{ "ok": false, "error": { "code": "GPU_NOT_FOUND", "message": "..." } }WS /api/v1/ns/{ns}/gpu/embed/{req_id}/wait — 결과 Push 대기
Redis Pub/Sub으로 완료 알림을 수신 후 즉시 결과를 전송합니다. GET 폴링보다 지연이 적습니다.
// 인증: Sec-WebSocket-Protocol 헤더로 API 키 전달 (URL 쿼리 미지원) // 브라우저: new WebSocket(url, ["redgx_ak_hrm_..."]) wss://<host>/api/v1/ns/HRM/gpu/embed/emb-xxx/wait?timeout=10 // timeout: 최대 대기 시간(초), 기본 10, 최대 300
// 완료 — status: "completed" (REST GET과 동일 구조)
{ "ok": true, "data": { "request_id": "emb-...", "status": "completed",
"model": "BAAI/bge-m3", "vectors": [...], "cached": false, "elapsed_ms": 42.5 } }
// 실패 — status: "failed"
{ "ok": true, "data": { "request_id": "emb-...", "status": "failed", "error": {...} } }
// 인증 실패 (API key 누락/오류, ns 권한 없음) → HTTP 403 (WebSocket upgrade 거부, accept 전)
// Not Found → { "ok": false, "error": { "code": "GPU_NOT_FOUND" } } + close(4004)
// Timeout → { "ok": false, "error": { "code": "GPU_TIMEOUT" } } + close(4008)헤더
| 헤더 | 설명 |
|---|---|
X-API-Key | 필수. 클라이언트 API 키 |
Content-Type: application/json | POST 요청 시 필수 |