콘텐츠로 이동

API 레퍼런스

Continuum Router는 모니터링 및 관리를 위한 추가 관리 엔드포인트와 함께 포괄적인 OpenAI 호환 API를 제공합니다. 이 문서는 사용 가능한 모든 엔드포인트, 요청/응답 형식 및 오류 처리에 대한 상세 정보를 제공합니다.

개요

기본 URL

http://localhost:8080

Content Type

별도로 명시되지 않는 한 모든 요청과 응답은 application/json을 사용합니다.

OpenAI 호환성

Continuum Router는 OpenAI API v1과 완벽하게 호환되며 다음을 지원합니다:

  • 스트리밍을 포함한 채팅 완료
  • 텍스트 완료
  • 임베딩 (text-embedding-3-small, text-embedding-3-large, text-embedding-ada-002)
  • 리랭킹 (Cohere 호환 /v1/rerank)
  • 희소 임베딩 (TEI/Jina 호환 /embed_sparse)
  • 이미지 생성 (DALL-E, gpt-image-1)
  • 이미지 편집/인페인팅 (DALL-E 2, gpt-image-1)
  • 이미지 변형 (DALL-E 2)
  • Files API (업로드, 목록, 조회, 삭제)
  • 채팅 완료에서의 파일 해결 (image_file 참조)
  • 모델 목록
  • 오류 응답 형식

인증

Continuum Router는 설정 가능한 적용 모드를 통한 API 키 인증을 지원합니다.

인증 모드

라우터는 API 엔드포인트에 대해 두 가지 인증 모드를 지원합니다:

모드 동작
permissive (기본값) API 키 없는 요청이 허용됩니다. 유효한 API 키가 있는 요청은 인증되어 사용자별 기능에 접근할 수 있습니다.
blocking 인증된 요청만 처리됩니다. 유효한 API 키가 없는 요청은 401 Unauthorized를 받습니다.

설정

api_keys:
  # 인증 모드: "permissive" (기본값) 또는 "blocking"
  mode: blocking

  # API 키 정의
  api_keys:
    - key: "${API_KEY_1}"
      id: "key-production-1"
      user_id: "user-admin"
      organization_id: "org-main"
      scopes: [read, write, files, admin]

보호된 엔드포인트 (mode가 blocking일 때)

  • /v1/chat/completions
  • /v1/completions
  • /v1/responses
  • /v1/images/generations
  • /v1/images/edits
  • /v1/images/variations
  • /v1/models
  • /v1/embeddings

참고: 헬스 엔드포인트 (/health, /healthz)는 항상 인증 없이 접근 가능합니다. Admin, Files, Metrics 엔드포인트는 별도의 인증 메커니즘을 가집니다.

인증된 요청 만들기

Authorization 헤더에 API 키를 포함하세요:

POST /v1/chat/completions HTTP/1.1
Authorization: Bearer sk-your-api-key
Content-Type: application/json

{
  "model": "gpt-4",
  "messages": [{"role": "user", "content": "Hello"}]
}

인증 오류

인증 실패 시 API는 다음을 반환합니다:

{
  "error": {
    "message": "Missing or invalid Authorization header. Expected: Bearer <api_key>",
    "type": "authentication_error",
    "code": "invalid_api_key"
  }
}

상태 코드:

  • 401 Unauthorized: API 키가 없거나 유효하지 않음

Core API 엔드포인트

헬스 체크

라우터 서비스의 헬스 상태를 확인합니다.

GET /health

응답:

{
  "status": "ok",
  "service": "continuum-router"
}

상태 코드:

  • 200: 서비스가 정상

모델 목록

모든 정상 백엔드에서 사용 가능한 모든 모델을 조회합니다.

GET /v1/models

응답:

{
  "object": "list",
  "data": [
    {
      "id": "gpt-4",
      "object": "model",
      "created": 1677610602,
      "owned_by": "openai-compatible",
      "permission": [],
      "root": "gpt-4",
      "parent": null
    },
    {
      "id": "llama2:7b",
      "object": "model",
      "created": 1677610602,
      "owned_by": "local-ollama",
      "permission": [],
      "root": "llama2:7b",
      "parent": null
    }
  ]
}

상태 코드:

  • 200: 모델이 성공적으로 조회됨
  • 503: 모든 백엔드가 비정상

기능:

  • 모델 집계: 모든 정상 백엔드의 모델을 결합
  • 중복 제거: 백엔드 간 중복 모델 제거
  • 캐싱: 기본적으로 5분간 결과 캐시
  • 헬스 인식: 정상 백엔드의 모델만 포함

단일 모델 조회

특정 모델의 정보와 가용성 상태를 조회합니다.

GET /v1/models/{model}

경로 파라미터:

파라미터 타입 필수 설명
model string 모델 식별자 (예: "gpt-4", "llama2:7b")

응답:

{
  "id": "gpt-4",
  "object": "model",
  "created": 1677610602,
  "owned_by": "openai",
  "available": true
}

응답 필드:

필드 타입 설명
id string 모델 식별자
object string 객체 타입 (항상 "model")
created integer 모델 생성 시점의 Unix 타임스탬프
owned_by string 모델을 소유/제공하는 조직
available boolean 모델 사용 가능 여부 (최소 하나의 정상 백엔드에서 제공되면 true)

상태 코드:

  • 200: 모델이 조회되어 정보가 반환됨
  • 404: 구성된 모든 백엔드에 해당 모델이 존재하지 않음

기능:

  • OpenAI 호환: 응답 형식이 OpenAI API와 호환되며 available 필드가 추가됨
  • 헬스 인식: available 필드는 실시간 백엔드 헬스 상태를 반영
  • 프라이버시: 내부 백엔드 정보를 노출하지 않음

요청 예시:

curl http://localhost:8080/v1/models/gpt-4

응답 예시 (모델 사용 가능):

{
  "id": "gpt-4",
  "object": "model",
  "created": 1677610602,
  "owned_by": "openai",
  "available": true
}

응답 예시 (모델 존재하지만 사용 불가):

{
  "id": "gpt-4",
  "object": "model",
  "created": 1677610602,
  "owned_by": "openai",
  "available": false
}

채팅 완료

OpenAI Chat API 형식을 사용하여 채팅 완료를 생성합니다.

POST /v1/chat/completions

요청 본문:

{
  "model": "gpt-3.5-turbo",
  "messages": [
    {
      "role": "system",
      "content": "You are a helpful assistant."
    },
    {
      "role": "user",
      "content": "Explain quantum computing in simple terms."
    }
  ],
  "temperature": 0.7,
  "max_tokens": 150,
  "top_p": 1.0,
  "frequency_penalty": 0.0,
  "presence_penalty": 0.0,
  "stream": false,
  "stop": null,
  "logit_bias": {},
  "user": "user123"
}

파라미터:

파라미터 타입 필수 설명
model string 모델 식별자 (최소 하나의 정상 백엔드에서 사용 가능해야 함)
messages array role과 content를 포함하는 메시지 객체 배열
temperature number 아니오 샘플링 온도 (0.0 ~ 2.0, 기본값: 1.0)
max_tokens integer 아니오 생성할 최대 토큰 수
top_p number 아니오 핵 샘플링 파라미터 (0.0 ~ 1.0)
frequency_penalty number 아니오 빈도 패널티 (-2.0 ~ 2.0)
presence_penalty number 아니오 존재 패널티 (-2.0 ~ 2.0)
stream boolean 아니오 스트리밍 응답 활성화 (기본값: false)
stop string/array 아니오 중지 시퀀스
logit_bias object 아니오 토큰 로짓 바이어스
user string 아니오 추적을 위한 사용자 식별자
reasoning_effort string 아니오 추론 가능 모델의 추론 노력 수준. 유효한 값은 백엔드에 따라 다름 (아래 참조). OpenAI O-series (o1, o3, o4) 및 GPT-5.2 thinking 모델, Gemini thinking 모델 지원.
reasoning object 아니오 대체 중첩 형식: {"effort": "high"}. 자동으로 reasoning_effort로 정규화됨.

백엔드별 유효한 reasoning_effort:

  • OpenAI O-series (o1, o3, o4-mini): low, medium, high
  • OpenAI GPT-5.2 thinking (gpt-5.2, gpt-5.2-thinking, gpt-5.2-pro): low, medium, high, xhigh
    • 참고: xhigh는 GPT-5.2 패밀리 thinking 모델에서만 지원됩니다. 다른 모델에서는 xhigh가 자동으로 high로 다운그레이드됩니다.
  • Gemini (2.0-flash, 2.5-flash, 2.5-pro, 3-flash, 3-pro): none, minimal, low, medium, high
    • 참고: none은 Flash 모델 (2.0-flash, 2.5-flash, 3-flash)에서만 지원됩니다.

라우터는 자동으로 값을 검증하고 지능적인 폴백을 적용합니다 (예: O-series에서 xhighhigh).

응답 (비스트리밍):

{
  "id": "chatcmpl-123456789",
  "object": "chat.completion",
  "created": 1677652288,
  "model": "gpt-3.5-turbo",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Quantum computing is a revolutionary computing paradigm that harnesses quantum mechanical phenomena..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 25,
    "completion_tokens": 150,
    "total_tokens": 175
  }
}

응답 (스트리밍): stream: true일 때 응답은 Server-Sent Events (SSE)를 사용합니다:

data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"gpt-3.5-turbo","choices":[{"delta":{"role":"assistant","content":""},"index":0,"finish_reason":null}]}

data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"gpt-3.5-turbo","choices":[{"delta":{"content":"Quantum"},"index":0,"finish_reason":null}]}

data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"gpt-3.5-turbo","choices":[{"delta":{"content":" computing"},"index":0,"finish_reason":null}]}

data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"gpt-3.5-turbo","choices":[{"delta":{},"index":0,"finish_reason":"stop"}]}

data: [DONE]

상태 코드:

  • 200: 완료가 성공적으로 생성됨
  • 400: 유효하지 않은 요청 형식 또는 파라미터
  • 404: 정상 백엔드에서 모델을 찾을 수 없음
  • 502: 백엔드 연결 오류
  • 504: 요청 타임아웃
  • 503: 모든 백엔드가 비정상

기능:

  • 모델 기반 라우팅: 요청된 모델을 제공하는 백엔드로 자동 라우팅
  • 로드 밸런싱: 정상 백엔드 간 로드 분산
  • 스트리밍 지원: SSE를 통한 실시간 응답 스트리밍
  • 오류 복구: 일시적 실패 시 자동 재시도
  • 요청 중복 제거: 동일한 요청의 중복 처리 방지
  • 추론 파라미터 정규화: 중첩된 reasoning 형식을 평면 reasoning_effort 형식으로 자동 정규화; 지원하지 않는 모델에서는 추론 파라미터 제거

Responses API

OpenAI의 Responses API 형식을 사용하여 응답을 생성합니다. 이 엔드포인트는 Chat Completions에 대한 대안적 인터페이스를 제공하며, 내부적으로 요청을 Chat Completions 형식으로 변환하여 백엔드에서 처리합니다.

POST /v1/responses

요청 본문:

{
  "model": "gpt-4o",
  "input": "양자 컴퓨팅을 간단한 용어로 설명해주세요.",
  "instructions": "당신은 복잡한 주제를 간단하게 설명하는 유용한 어시스턴트입니다.",
  "max_output_tokens": 1000,
  "temperature": 0.7,
  "reasoning": {
    "effort": "high"
  }
}

파라미터:

파라미터 타입 필수 설명
model string 모델 식별자 (최소 하나의 정상 백엔드에서 사용 가능해야 함)
input string/array 입력 텍스트 또는 입력 항목 배열
instructions string 아니오 모델에 대한 시스템 지시사항 (시스템 메시지로 변환됨)
max_output_tokens integer 아니오 생성할 최대 토큰 수
temperature number 아니오 샘플링 온도 (0.0 ~ 2.0)
top_p number 아니오 핵 샘플링 파라미터 (0.0 ~ 1.0)
stream boolean 아니오 스트리밍 응답 활성화 (기본값: false)
include_reasoning boolean 아니오 응답에 추론 콘텐츠 포함
reasoning object 아니오 중첩 형식의 추론 설정 (아래 참조)
tools array 아니오 모델에서 사용 가능한 도구 목록 (플랫 형식)
tool_choice string/object 아니오 도구 사용 제어
previous_response_id string 아니오 다중 턴 대화를 위한 이전 응답 참조

도구 정의 형식:

Responses API는 함수 속성이 type 필드와 같은 레벨에 있는 플랫 도구 형식을 사용합니다. 이는 중첩된 function 객체를 사용하는 Chat Completions API와 다릅니다.

{
  "type": "function",
  "name": "get_weather",
  "description": "위치의 날씨 조회",
  "parameters": {
    "type": "object",
    "properties": {
      "location": {"type": "string", "description": "도시 이름"}
    },
    "required": ["location"]
  },
  "strict": true
}
필드 타입 필수 설명
type string "function"이어야 함
name string 함수 이름
description string 아니오 함수가 수행하는 작업 설명
parameters object 아니오 함수 파라미터에 대한 JSON Schema
strict boolean 아니오 엄격한 파라미터 검증 활성화

기타 지원되는 도구 유형: code_interpreter, file_search, web_search, computer_use

멀티모달 입력 유형:

input이 항목 배열인 경우 각 항목은 멀티모달 콘텐츠 파트를 포함하는 메시지가 될 수 있습니다. 다음 콘텐츠 파트 유형이 지원됩니다:

유형 설명
text 일반 텍스트 콘텐츠
input_text 텍스트 콘텐츠 (Responses API 대체 형식)
input_file 파일 콘텐츠 (PDF, 이미지 또는 기타 파일)
input_image 이미지 콘텐츠
image_url URL 또는 base64 데이터의 이미지

Input File 형식:

input_file 콘텐츠 파트는 세 가지 입력 방법을 지원합니다:

{
  "type": "input_file",
  "filename": "document.pdf",
  "file_data": "data:application/pdf;base64,JVBERi0xLjQ..."
}
필드 유형 설명
filename string 파일의 선택적 파일명
file_data string Base64 데이터 URL (예: data:application/pdf;base64,...)
file_url string 파일의 외부 URL (SSRF 검증됨)
file_id string Files API를 통해 업로드된 파일 참조

Input Image 형식:

{
  "type": "input_image",
  "image_url": "data:image/png;base64,iVBORw0KGgo...",
  "detail": "high"
}
필드 유형 설명
image_url string 이미지 URL 또는 base64 데이터 URL
detail string 이미지 상세 수준: low, high 또는 auto (기본값)

멀티모달 요청 예시:

curl -X POST http://localhost:8080/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o",
    "input": [
      {
        "type": "message",
        "role": "user",
        "content": [
          {"type": "input_text", "text": "이 문서에 무엇이 적혀있나요?"},
          {"type": "input_file", "filename": "report.pdf", "file_data": "data:application/pdf;base64,..."}
        ]
      }
    ]
  }'

보안 참고 사항:

  • file_url의 외부 URL은 SSRF 공격 방지를 위해 검증됩니다
  • 개인 IP 주소와 localhost URL은 거부됩니다
  • 외부 파일에는 HTTPS URL만 권장됩니다
  • file_id 필드는 Files API를 통해 업로드된 파일을 참조합니다. 파일은 백엔드로 전송되기 전에 base64로 변환됩니다. 파일 소유권이 검증되며 파일 주입에 10MB 크기 제한이 적용됩니다

Reasoning 파라미터:

reasoning 파라미터는 추론 가능 모델의 추론 노력 수준을 제어합니다. 중첩 형식을 사용합니다:

{
  "reasoning": {
    "effort": "high"
  }
}

유효한 effort 값:

설명
low 최소 추론 노력, 더 빠른 응답
medium 균형 잡힌 추론 노력
high 최대 표준 추론 노력
xhigh 확장 추론 (GPT-5.2 패밀리 전용)

라우터는 이 중첩 형식을 Chat Completions 백엔드에서 사용하는 평면 reasoning_effort 형식으로 자동 변환합니다. 잘못된 노력 수준은 400 Bad Request 오류로 거부됩니다.

Reasoning을 포함한 요청 예시:

curl -X POST http://localhost:8080/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "o1",
    "input": "이 복잡한 수학 문제를 단계별로 풀어주세요.",
    "reasoning": {
      "effort": "high"
    }
  }'

응답:

{
  "id": "resp_abc123",
  "object": "response",
  "created_at": 1699000000,
  "model": "o1",
  "output": [
    {
      "type": "message",
      "id": "msg_001",
      "role": "assistant",
      "content": [
        {
          "type": "output_text",
          "text": "단계별로 풀어보겠습니다..."
        }
      ]
    }
  ],
  "usage": {
    "input_tokens": 25,
    "output_tokens": 150
  },
  "status": "completed"
}

상태 코드:

  • 200: 응답 생성 성공
  • 400: 잘못된 요청 형식, 파라미터 또는 잘못된 reasoning effort 값
  • 404: 정상 백엔드에서 모델을 찾을 수 없음
  • 502: 백엔드 연결 오류
  • 504: 요청 타임아웃
  • 503: 모든 백엔드가 비정상

기능:

  • 스마트 라우팅: 백엔드 기능에 따라 요청 라우팅 - OpenAI/Azure는 네이티브 패스스루, 기타는 자동 변환
  • 네이티브 패스스루: OpenAI 및 Azure OpenAI 백엔드의 경우 요청이 /v1/responses 엔드포인트로 직접 전달되어 모든 네이티브 기능 유지
  • 자동 변환: 기타 백엔드(Anthropic, Gemini, vLLM, Ollama 등)의 경우 Responses API 형식을 해당 네이티브 형식으로 변환
  • 추론 지원: 타입 안전 검증을 통한 reasoning 파라미터 전체 지원
  • 다중 백엔드 지원: OpenAI, Anthropic, Gemini, Ollama, vLLM 및 기타 백엔드와 호환
  • 스트리밍 지원: stream: true일 때 SSE를 통한 실시간 응답 스트리밍
  • 세션 관리: previous_response_id를 통한 다중 턴 대화 지원

라우팅 전략:

라우터는 각 백엔드에 대해 최적의 전략을 자동으로 결정합니다:

백엔드 유형 전략 설명
OpenAI 패스스루 네이티브 Responses API 지원 - 요청 직접 전달
Azure OpenAI 패스스루 네이티브 Responses API 지원 - 요청 직접 전달
Anthropic 네이티브 변환 네이티브 Anthropic Messages API 형식으로 변환, PDF/이미지 완전 지원
Gemini 변환 Gemini generateContent API 형식으로 변환
vLLM 변환 Chat Completions 형식으로 변환
Ollama 변환 Chat Completions 형식으로 변환
LlamaCpp 변환 Chat Completions 형식으로 변환
Generic 변환 Chat Completions 형식으로 변환

패스스루 이점:

OpenAI 또는 Azure OpenAI 백엔드를 패스스루 모드로 사용할 때:

  • 네이티브 PDF 파일 지원 (Chat Completions는 이미지만 지원)
  • 턴 간 추론 상태 보존으로 성능 향상
  • 내장 도구(websearch, filesearch 등) 접근 가능
  • 향상된 캐시 활용 (OpenAI 문서에 따르면 40-80% 개선)
  • 최신 OpenAI Responses API 기능과의 완벽한 호환성

Anthropic 네이티브 변환 이점:

Anthropic (Claude) 백엔드를 네이티브 변환 모드로 사용할 때:

  • Anthropic 문서 이해 기능을 통한 네이티브 PDF 파일 지원
  • 자동 형식 감지를 통한 이미지 파일 지원
  • Claude 3+ 모델의 확장 사고(Extended Thinking) 지원
  • 외부 파일 URL에 대한 SSRF 보호
  • 보안을 위한 미디어 타입 화이트리스트

이미지 생성

OpenAI의 DALL-E, GPT Image 모델 또는 Google의 Nano Banana (Gemini) 모델을 사용하여 이미지를 생성합니다.

POST /v1/images/generations

요청 본문:

{
  "model": "dall-e-3",
  "prompt": "A serene Japanese garden with cherry blossoms",
  "n": 1,
  "size": "1024x1024",
  "quality": "standard",
  "response_format": "url"
}

파라미터:

파라미터 타입 필수 설명
model string 이미지 모델: dall-e-2, dall-e-3, gpt-image-1, gpt-image-1.5, gpt-image-1-mini, nano-banana, 또는 nano-banana-pro
prompt string 생성할 이미지에 대한 설명
n integer 아니오 이미지 수 (1-10, 모델에 따라 다름)
size string 아니오 이미지 크기 (모델에 따라 다름, 아래 참조)
quality string 아니오 이미지 품질 (모델에 따라 다름, 아래 참조)
style string 아니오 이미지 스타일: vivid 또는 natural (DALL-E 3만)
response_format string 아니오 응답 형식: url 또는 b64_json
output_format string 아니오 출력 파일 형식: png, jpeg, webp (GPT Image 모델만, 기본값: png)
output_compression integer 아니오 jpeg/webp의 압축 레벨 0-100 (GPT Image 모델만)
background string 아니오 배경: transparent, opaque, auto (GPT Image 모델만)
stream boolean 아니오 부분 이미지 스트리밍 활성화 (GPT Image 모델만, 기본값: false)
partial_images integer 아니오 스트리밍 중 부분 이미지 수 0-3 (GPT Image 모델만)
user string 아니오 추적을 위한 사용자 식별자

모델별 제약 조건:

모델 크기 n 품질 참고
dall-e-2 256x256, 512x512, 1024x1024 1-10 N/A 클래식 DALL-E 2
dall-e-3 1024x1024, 1792x1024, 1024x1792 1 standard, hd 프롬프트 수정이 포함된 고품질
gpt-image-1 1024x1024, 1536x1024, 1024x1536, auto 1 low, medium, high, auto 최신 GPT Image 모델, 스트리밍 지원
gpt-image-1.5 1024x1024, 1536x1024, 1024x1536, auto 1 low, medium, high, auto 4배 빠름, 향상된 텍스트 렌더링
gpt-image-1-mini 1024x1024, 1536x1024, 1024x1536, auto 1 low, medium, high, auto 비용 효율적인 옵션
nano-banana 256x256 ~ 1024x1024 1-4 N/A Gemini 2.5 Flash Image (빠름)
nano-banana-pro 256x256 ~ 4096x4096 1-4 N/A Gemini 2.0 Flash Image (고급, 최대 4K)

품질 파라미터 (GPT Image 모델):

하위 호환성을 위해 GPT Image 모델 사용 시 standardmedium으로, hdhigh로 매핑됩니다.

품질 설명
low 낮은 품질로 빠른 생성
medium 품질과 속도의 균형 (기본값)
high 최고 품질, 느린 생성
auto 모델이 최적 품질 선택

출력 형식 옵션 (GPT Image 모델):

형식 설명 투명도 지원
png 무손실 형식 (기본값)
jpeg 손실 형식, 작은 파일 크기 아니오
webp 현대적인 형식, 좋은 압축률

참고: 투명 배경 (background: "transparent")은 png 또는 webp 형식이 필요합니다.

Nano Banana (Gemini) 모델:

Nano Banana는 OpenAI 호환 인터페이스를 통해 Google의 Gemini 이미지 생성 기능에 대한 액세스를 제공합니다:

  • nano-banana: Gemini 2.5 Flash Image에 매핑 - 빠른 범용 이미지 생성
  • nano-banana-pro: Gemini 2.0 Flash Image에 매핑 - 고해상도 지원 고급 모델 (최대 4K)

Nano Banana 크기 매핑:

라우터는 OpenAI 스타일 크기 파라미터를 Gemini의 aspectRatioimageSize 형식으로 자동 변환합니다:

OpenAI 크기 Gemini aspectRatio Gemini imageSize 참고
256x256 1:1 1K Gemini 최소값으로 폴백
512x512 1:1 1K Gemini 최소값으로 폴백
1024x1024 1:1 1K 기본값
1536x1024 3:2 1K 가로 (신규)
1024x1536 2:3 1K 세로 (신규)
1024x1792 9:16 1K 긴 세로
1792x1024 16:9 1K 넓은 가로
2048x2048 1:1 2K Pro만
4096x4096 1:1 4K Pro만
auto 1:1 1K 기본 폴백

변환은 다음 Gemini API 구조를 전송합니다:

{
  "contents": [{"parts": [{"text": "Your prompt"}]}],
  "generationConfig": {
    "imageConfig": {
      "aspectRatio": "3:2",
      "imageSize": "1K"
    }
  }
}

Nano Banana 요청 예제:

{
  "model": "nano-banana",
  "prompt": "A white siamese cat with blue eyes, photorealistic",
  "n": 1,
  "size": "1024x1024",
  "response_format": "b64_json"
}

응답:

{
  "created": 1677652288,
  "data": [
    {
      "url": "https://oaidalleapiprodscus.blob.core.windows.net/...",
      "revised_prompt": "A tranquil Japanese garden featuring..."
    }
  ]
}

응답 (b64_json 포함):

{
  "created": 1677652288,
  "data": [
    {
      "b64_json": "/9j/4AAQSkZJRgABAQAA...",
      "revised_prompt": "A tranquil Japanese garden featuring..."
    }
  ]
}

Nano Banana 응답 참고 사항:

  • Nano Banana에서 response_format: "url"을 사용할 때, Gemini의 네이티브 API가 인라인 base64 데이터를 반환하므로 이미지는 data URL (data:image/png;base64,...)로 반환됩니다
  • revised_prompt 필드에는 생성된 이미지를 설명하는 Gemini의 텍스트 응답이 포함됩니다

스트리밍 이미지 생성 (GPT Image 모델):

GPT Image 모델에 대해 stream: true가 지정되면 응답이 Server-Sent Events (SSE)로 스트리밍됩니다:

스트리밍 요청 예제:

{
  "model": "gpt-image-1",
  "prompt": "A beautiful sunset over mountains",
  "stream": true,
  "partial_images": 2,
  "response_format": "b64_json"
}

스트리밍 응답 형식:

data: {"type":"image_generation.partial_image","partial_image_index":0,"b64_json":"...","created":1702345678}

data: {"type":"image_generation.partial_image","partial_image_index":1,"b64_json":"...","created":1702345679}

data: {"type":"image_generation.complete","b64_json":"...","created":1702345680}

data: {"type":"image_generation.usage","usage":{"input_tokens":25,"output_tokens":1024}}

data: {"type":"done"}

SSE 이벤트 타입:

이벤트 타입 설명
image_generation.partial_image 생성 중 중간 이미지
image_generation.complete 최종 완성 이미지
image_generation.usage 토큰 사용량 정보 (비용 추적용)
done 스트림 완료 마커

새 옵션이 포함된 GPT Image 요청 예제:

{
  "model": "gpt-image-1.5",
  "prompt": "A white cat with blue eyes, photorealistic",
  "size": "auto",
  "quality": "high",
  "output_format": "webp",
  "output_compression": 85,
  "background": "transparent",
  "response_format": "b64_json"
}

상태 코드:

  • 200: 이미지가 성공적으로 생성됨
  • 400: 유효하지 않은 요청 (예: 모델에 대해 유효하지 않은 크기, DALL-E 3에서 n > 1)
  • 401: 유효하지 않은 API 키
  • 429: 속도 제한 초과
  • 500: 백엔드 오류
  • 503: Gemini 백엔드 사용 불가 (Nano Banana 모델의 경우)

타임아웃 설정: 이미지 생성 요청은 설정 가능한 타임아웃을 사용합니다 (기본값: 3분). 설정의 timeouts.request.image_generation을 참조하세요.


이미지 편집 (인페인팅)

OpenAI의 인페인팅 기능을 사용하여 기존 이미지를 편집합니다. 이 엔드포인트를 사용하면 텍스트 프롬프트와 선택적 마스크를 기반으로 이미지의 특정 영역을 수정할 수 있습니다. GPT Image 모델과 DALL-E 2를 지원합니다.

POST /v1/images/edits
Content-Type: multipart/form-data

요청 파라미터 (multipart/form-data):

파라미터 타입 필수 설명
image file 편집할 소스 이미지 (PNG, < 4MB, 정사각형)
prompt string 원하는 편집에 대한 설명
mask file 아니오 편집 영역을 나타내는 마스크 이미지 (PNG, 이미지와 동일한 크기)
model string 아니오 사용할 모델 (기본값: gpt-image-1)
n integer 아니오 생성할 이미지 수 (1-10, 기본값: 1)
size string 아니오 출력 크기 (모델에 따라 다름, 기본값: 1024x1024)
response_format string 아니오 응답 형식: url 또는 b64_json (기본값: url)
user string 아니오 추적을 위한 고유 사용자 식별자

지원되는 모델 및 크기:

모델 크기 참고
gpt-image-1 1024x1024, 1536x1024, 1024x1536, auto 최신 GPT Image 모델 (권장)
gpt-image-1-mini 1024x1024, 1536x1024, 1024x1536, auto 비용 최적화 버전
gpt-image-1.5 1024x1024, 1536x1024, 1024x1536, auto 향상된 지시 따르기 기능의 최신 버전
dall-e-2 256x256, 512x512, 1024x1024 레거시 DALL-E 2 모델

참고: DALL-E 3와 Gemini (nano-banana)는 이 엔드포인트를 통한 이미지 편집을 지원하지 않습니다. Gemini는 자연어를 통한 시맨틱 마스킹을 사용하며, 이는 OpenAI의 마스크 기반 편집 형식과 호환되지 않습니다.

이미지 요구 사항:

  • 형식: PNG만
  • 크기: 4MB 미만
  • 크기: 정사각형이어야 함 (가로 = 세로)

마스크 요구 사항:

  • 형식: 알파 채널이 있는 PNG (RGBA)
  • 크기: 소스 이미지와 정확히 일치해야 함
  • 투명 영역: 편집/생성할 영역을 나타냄
  • 불투명 영역: 보존할 영역을 나타냄

요청 예제:

curl -X POST http://localhost:8080/v1/images/edits \
  -F "image=@source_image.png" \
  -F "mask=@mask.png" \
  -F "prompt=A sunlit indoor lounge area with a pool containing a flamingo" \
  -F "n=1" \
  -F "size=1024x1024" \
  -F "response_format=url"

요청 예제 (마스크 없이):

curl -X POST http://localhost:8080/v1/images/edits \
  -F "image=@source_image.png" \
  -F "prompt=Add a sunset in the background" \
  -F "n=1" \
  -F "size=512x512"

응답:

{
  "created": 1677652288,
  "data": [
    {
      "url": "https://oaidalleapiprodscus.blob.core.windows.net/..."
    }
  ]
}

응답 (b64_json 포함):

{
  "created": 1677652288,
  "data": [
    {
      "b64_json": "/9j/4AAQSkZJRgABAQAA..."
    }
  ]
}

상태 코드:

  • 200: 이미지가 성공적으로 편집됨
  • 400: 유효하지 않은 요청 (예: 정사각형이 아닌 이미지, 유효하지 않은 크기, 필수 필드 누락)
  • 401: 유효하지 않은 API 키
  • 503: OpenAI 백엔드 사용 불가

오류 예제:

정사각형이 아닌 이미지:

{
  "error": {
    "message": "Image must be square (800x600 is not square)",
    "type": "invalid_request_error",
    "param": "image",
    "code": "image_not_square"
  }
}

마스크 크기 불일치:

{
  "error": {
    "message": "Mask dimensions (256x256) do not match image dimensions (512x512)",
    "type": "invalid_request_error",
    "param": "mask",
    "code": "dimension_mismatch"
  }
}

지원되지 않는 모델:

{
  "error": {
    "message": "Model 'dall-e-3' does not support image editing. Supported models: gpt-image-1, gpt-image-1-mini, gpt-image-1.5, dall-e-2. Note: dall-e-3 does NOT support image editing.",
    "type": "invalid_request_error",
    "param": "model",
    "code": "unsupported_model"
  }
}

참고 사항:

  • 지원되는 모델: gpt-image-1, gpt-image-1-mini, gpt-image-1.5, dall-e-2
  • DALL-E 3는 API를 통한 이미지 편집을 지원하지 않습니다
  • Gemini (nano-banana)는 지원되지 않음 - 다른 편집 접근 방식 사용 (시맨틱 마스킹)
  • 마스크가 제공되지 않으면 전체 이미지가 수정될 수 있습니다
  • 마스크 없이 편집하는 경우 소스 이미지에 투명 영역이 있어야 합니다
  • 요청 타임아웃은 이미지 생성 타임아웃 설정을 사용합니다

이미지 변형

OpenAI의 DALL-E 2 모델을 사용하여 기존 이미지의 변형을 생성합니다.

POST /v1/images/variations
Content-Type: multipart/form-data

폼 필드:

파라미터 타입 필수 설명
image file 변형을 위한 소스 이미지 (PNG, < 4MB, 정사각형이어야 함)
model string 아니오 사용할 모델 (기본값: dall-e-2)
n integer 아니오 생성할 변형 수 (1-10, 기본값: 1)
size string 아니오 출력 크기: 256x256, 512x512, 1024x1024 (기본값: 1024x1024)
response_format string 아니오 응답 형식: url 또는 b64_json (기본값: url)
user string 아니오 추적을 위한 사용자 식별자

요청 예제:

curl -X POST http://localhost:8080/v1/images/variations \
  -F "image=@source_image.png" \
  -F "model=dall-e-2" \
  -F "n=2" \
  -F "size=512x512" \
  -F "response_format=url"

응답:

{
  "created": 1677652288,
  "data": [
    {
      "url": "https://oaidalleapiprodscus.blob.core.windows.net/..."
    },
    {
      "url": "https://oaidalleapiprodscus.blob.core.windows.net/..."
    }
  ]
}

응답 (b64_json 포함):

{
  "created": 1677652288,
  "data": [
    {
      "b64_json": "/9j/4AAQSkZJRgABAQAA..."
    }
  ]
}

모델 지원:

모델 변형 지원 참고
dall-e-2 예 (네이티브) 완전 지원, 1-10개 변형
dall-e-3 아니오 OpenAI API에서 지원하지 않음
gpt-image-1 아니오 지원되지 않음
nano-banana 아니오 Gemini는 변형 API를 지원하지 않음
nano-banana-pro 아니오 Gemini는 변형 API를 지원하지 않음

이미지 요구 사항:

  • 형식: PNG만
  • 크기: 4MB 미만
  • 크기: 정사각형이어야 함 (가로 == 세로)
  • 지원되는 입력 크기: 모든 정사각형 크기 (모델에서 처리됨)

오류 시나리오:

오류 상태 설명
PNG가 아닌 이미지 400 PNG 형식만 지원됨
정사각형이 아닌 이미지 400 이미지 크기가 동일해야 함
이미지가 너무 큼 400 이미지가 4MB 크기 제한 초과
지원되지 않는 모델 400 요청된 모델이 변형을 지원하지 않음
이미지 누락 400 image 필드 필수
유효하지 않은 n 값 400 n은 1과 10 사이여야 함
유효하지 않은 크기 400 크기는 지원되는 값 중 하나여야 함

상태 코드:

  • 200: 변형이 성공적으로 생성됨
  • 400: 유효하지 않은 요청 (유효하지 않은 형식, 정사각형이 아닌 이미지, 지원되지 않는 모델)
  • 401: 유효하지 않은 API 키
  • 429: 속도 제한 초과
  • 500: 백엔드 오류
  • 503: 백엔드 사용 불가

텍스트 완료

OpenAI Completions API 형식을 사용하여 텍스트 완료를 생성합니다.

POST /v1/completions

요청 본문:

{
  "model": "gpt-3.5-turbo-instruct",
  "prompt": "Once upon a time in a distant galaxy",
  "max_tokens": 100,
  "temperature": 0.7,
  "top_p": 1.0,
  "frequency_penalty": 0.0,
  "presence_penalty": 0.0,
  "stream": false,
  "stop": null,
  "logit_bias": {},
  "user": "user123"
}

응답:

{
  "id": "cmpl-123456789",
  "object": "text_completion",
  "created": 1677652288,
  "model": "gpt-3.5-turbo-instruct",
  "choices": [
    {
      "text": ", there lived a young explorer named Zara who dreamed of discovering new worlds...",
      "index": 0,
      "finish_reason": "stop",
      "logprobs": null
    }
  ],
  "usage": {
    "prompt_tokens": 10,
    "completion_tokens": 90,
    "total_tokens": 100
  }
}

상태 코드: 채팅 완료와 동일


임베딩

OpenAI 임베딩 API 형식을 사용하여 입력 텍스트에 대한 임베딩을 생성합니다.

POST /v1/embeddings

요청 본문:

{
  "model": "text-embedding-3-small",
  "input": "The quick brown fox jumps over the lazy dog",
  "encoding_format": "float",
  "dimensions": 512,
  "user": "user123"
}

요청 파라미터:

필드 타입 필수 설명
model string 사용할 모델의 ID (예: text-embedding-3-small, text-embedding-3-large, text-embedding-ada-002)
input string 또는 array 임베딩할 입력 텍스트. 단일 문자열, 문자열 배열 또는 토큰 배열이 될 수 있음
encoding_format string 아니오 임베딩 반환 형식: float 또는 base64 (기본값: float)
dimensions integer 아니오 출력 임베딩의 차원 수 (text-embedding-3-* 모델만 지원)
user string 아니오 최종 사용자의 고유 식별자

입력 형식 예시:

단일 문자열:

{
  "model": "text-embedding-3-small",
  "input": "Hello, world!"
}

문자열 배열:

{
  "model": "text-embedding-3-large",
  "input": [
    "임베딩할 첫 번째 텍스트",
    "임베딩할 두 번째 텍스트",
    "임베딩할 세 번째 텍스트"
  ]
}

토큰 배열:

{
  "model": "text-embedding-ada-002",
  "input": [[1234, 5678, 9012], [3456, 7890, 1234]]
}

응답:

{
  "object": "list",
  "data": [
    {
      "object": "embedding",
      "index": 0,
      "embedding": [0.0023064255, -0.009327292, 0.0045318254, ...]
    }
  ],
  "model": "text-embedding-3-small",
  "usage": {
    "prompt_tokens": 8,
    "total_tokens": 8
  }
}

응답 필드:

필드 타입 설명
object string 항상 "list"
data array 임베딩 객체 배열
data[].object string 항상 "embedding"
data[].index integer 입력 배열에서 임베딩의 인덱스
data[].embedding array 임베딩 벡터 (부동소수점 배열)
model string 임베딩 생성에 사용된 모델
usage object 토큰 사용 정보
usage.prompt_tokens integer 입력의 토큰 수
usage.total_tokens integer 사용된 총 토큰 (임베딩의 경우 prompt_tokens와 동일)

지원 모델:

백엔드 모델 참고
OpenAI text-embedding-3-small 기본 1536 차원, dimensions 파라미터 지원
OpenAI text-embedding-3-large 기본 3072 차원, dimensions 파라미터 지원
OpenAI text-embedding-ada-002 1536 차원, 레거시 모델
Gemini text-embedding-004 OpenAI 호환 엔드포인트 사용
자체 호스팅 bge-m3 1024 차원, 100개 이상 언어, 8192 컨텍스트. Dense, sparse, ColBERT 검색 지원
자체 호스팅 bge-large-en-v1.5 1024 차원, 영어 전용, 512 컨텍스트
자체 호스팅 multilingual-e5-large 1024 차원, 100개 이상 언어, 514 컨텍스트
vLLM 배포별 다름 배포된 모델에 따라 다름
llama.cpp 배포별 다름 네이티브 /v1/embeddings 지원
TEI 배포별 다름 Hugging Face Text Embeddings Inference 서버
Ollama 배포별 다름 Ollama 임베딩 모델 사용

상태 코드:

  • 200: 임베딩이 성공적으로 생성됨
  • 400: 유효하지 않은 요청 (model/input 누락, 유효하지 않은 dimensions)
  • 401: 유효하지 않은 API 키
  • 404: 모델을 찾을 수 없거나 임베딩을 지원하지 않음
  • 429: 속도 제한 초과
  • 500: 백엔드 오류
  • 503: 백엔드 사용 불가

기능:

  • 다양한 입력 형식: 단일 문자열, 문자열 배열 또는 토큰 배열 지원
  • 차원 제어: text-embedding-3 모델의 경우 축소된 벡터 크기를 위한 사용자 정의 차원 지정
  • 백엔드 독립적: 모델에 따라 적절한 백엔드로 라우팅
  • 로드 밸런싱: 설정된 로드 밸런싱 전략 적용
  • 오류 처리: 유효하지 않은 요청에 대한 상세 오류 메시지 제공

요청 예제:

curl -X POST http://localhost:8080/v1/embeddings \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-api-key" \
  -d '{
    "model": "text-embedding-3-small",
    "input": "The quick brown fox jumps over the lazy dog",
    "encoding_format": "float"
  }'

여러 입력 예제:

curl -X POST http://localhost:8080/v1/embeddings \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-api-key" \
  -d '{
    "model": "text-embedding-3-large",
    "input": [
      "첫 번째 문서 텍스트",
      "두 번째 문서 텍스트",
      "세 번째 문서 텍스트"
    ]
  }'

사용자 정의 차원 예제:

curl -X POST http://localhost:8080/v1/embeddings \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-api-key" \
  -d '{
    "model": "text-embedding-3-small",
    "input": "샘플 텍스트",
    "dimensions": 512
  }'

리랭킹

Cohere 호환 Rerank API를 사용하여 쿼리와의 관련성을 기준으로 문서를 리랭킹합니다. 이는 일반적으로 초기 벡터 검색 후 정확도를 향상시키기 위한 2단계 검색 단계로 사용됩니다.

POST /v1/rerank

요청 본문:

{
  "model": "bge-reranker-v2-m3",
  "query": "머신러닝이란 무엇인가요?",
  "documents": ["문서 1 내용", "문서 2 내용", "문서 3 내용"],
  "top_n": 3,
  "return_documents": false
}

요청 파라미터:

필드 타입 필수 설명
model string 사용할 리랭킹 모델의 ID (예: bge-reranker-v2-m3, rerank-english-v3.0, jina-reranker-v2-base-multilingual)
query string 문서와 비교할 검색 쿼리
documents array 리랭킹할 문서 목록. 문자열 배열 또는 text 필드가 있는 객체 배열이 될 수 있음
top_n integer 아니오 반환할 상위 결과 수. 지정하지 않으면 모든 문서가 순위대로 반환됨
return_documents boolean 아니오 응답에 문서 텍스트를 포함할지 여부 (기본값: false)
max_chunks_per_doc integer 아니오 긴 문서 처리를 위해 문서당 처리할 최대 청크 수

문서 형식 옵션:

단순 문자열 배열:

{
  "model": "bge-reranker-v2-m3",
  "query": "딥러닝이란 무엇인가요?",
  "documents": [
    "딥러닝은 여러 층의 신경망을 사용합니다",
    "머신러닝은 인공지능의 하위 분야입니다",
    "자연어 처리는 텍스트 이해를 다룹니다"
  ]
}

text 필드가 있는 구조화된 문서:

{
  "model": "rerank-english-v3.0",
  "query": "딥러닝이란 무엇인가요?",
  "documents": [
    {"text": "딥러닝은 여러 층의 신경망을 사용합니다"},
    {"text": "머신러닝은 인공지능의 하위 분야입니다"}
  ]
}

응답:

{
  "results": [
    {
      "index": 0,
      "relevance_score": 0.95
    },
    {
      "index": 2,
      "relevance_score": 0.72
    },
    {
      "index": 1,
      "relevance_score": 0.45
    }
  ],
  "model": "bge-reranker-v2-m3",
  "id": "rerank-abc123",
  "usage": {
    "prompt_tokens": 150,
    "total_tokens": 150
  }
}

문서 포함 응답 (return_documents: true 인 경우):

{
  "results": [
    {
      "index": 0,
      "relevance_score": 0.95,
      "document": {
        "text": "딥러닝은 여러 층의 신경망을 사용합니다"
      }
    }
  ],
  "model": "bge-reranker-v2-m3"
}

응답 필드:

필드 타입 설명
results array 관련성 점수 순으로 정렬된 리랭킹 결과 목록 (높은 순)
results[].index integer 원본 입력 목록에서 문서의 인덱스
results[].relevance_score number 관련성 점수 (일반적으로 0.0에서 1.0, 높을수록 더 관련됨)
results[].document object 문서 텍스트 (return_documentstrue인 경우에만 존재)
model string 리랭킹에 사용된 모델
id string 이 요청의 고유 식별자 (선택적)
usage object 토큰 사용 정보 (선택적)

지원 백엔드:

백엔드 엔드포인트 참고
vLLM /v1/rerank Cohere 호환, BGE, Jina 리랭커 지원
llama.cpp /v1/rerank 시작 시 --reranking 플래그 필요
Hugging Face TEI /rerank Text Embeddings Inference 서버
Cohere API /v1/rerank 네이티브 Cohere rerank 엔드포인트
Jina AI /v1/rerank 네이티브 Jina rerank 엔드포인트

상태 코드:

  • 200: 문서가 성공적으로 리랭킹됨
  • 400: 유효하지 않은 요청 (model/query/documents 누락, 빈 documents 배열)
  • 401: 유효하지 않은 API 키
  • 404: 모델을 찾을 수 없거나 리랭킹을 지원하지 않음
  • 429: 속도 제한 초과
  • 500: 백엔드 오류
  • 503: 백엔드 사용 불가

사용 사례:

  • 2단계 검색: 벡터 검색으로 후보를 검색한 다음 더 높은 정밀도를 위해 리랭킹
  • RAG 시스템: LLM 처리 전에 검색된 문서를 리랭킹하여 컨텍스트 품질 향상
  • 검색 결과 정제: 의미적 관련성에 따라 검색 결과 재정렬

요청 예제:

curl -X POST http://localhost:8080/v1/rerank \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-api-key" \
  -d '{
    "model": "bge-reranker-v2-m3",
    "query": "재생 에너지의 장점은 무엇인가요?",
    "documents": [
      "태양광 패널은 햇빛을 전기로 변환합니다",
      "풍력 터빈은 바람에서 전력을 생성합니다",
      "석탄은 전기에 사용되는 화석 연료입니다"
    ],
    "top_n": 2
  }'

희소 임베딩

TEI/Jina 호환 Sparse Embedding API를 사용하여 입력 텍스트에 대한 희소 임베딩을 생성합니다. 희소 임베딩(예: SPLADE)은 명시적인 용어 가중치를 통해 어휘 정보를 보존하여 하이브리드 검색에서 밀집 임베딩을 보완합니다.

POST /embed_sparse

요청 본문:

{
  "model": "naver/splade-v3",
  "input": "희소 임베딩이란 무엇인가요?"
}

요청 파라미터:

필드 타입 필수 설명
model string 사용할 희소 임베딩 모델의 ID (예: naver/splade-v3, naver/splade-cocondenser-ensembledistil)
input string 또는 array 임베딩할 입력 텍스트. 단일 문자열 또는 문자열 배열이 될 수 있음

입력 형식 예시:

단일 문자열:

{
  "model": "naver/splade-v3",
  "input": "희소 임베딩이란 무엇인가요?"
}

문자열 배열:

{
  "model": "naver/splade-v3",
  "input": [
    "임베딩할 첫 번째 텍스트",
    "임베딩할 두 번째 텍스트",
    "임베딩할 세 번째 텍스트"
  ]
}

응답:

{
  "data": [
    {
      "index": 0,
      "sparse_embedding": {
        "indices": [123, 456, 789, 1024, 2048],
        "values": [0.5, 0.3, 0.1, 0.8, 0.2]
      }
    }
  ],
  "model": "naver/splade-v3",
  "usage": {
    "prompt_tokens": 8,
    "total_tokens": 8
  }
}

응답 필드:

필드 타입 설명
data array 희소 임베딩 객체 배열
data[].index integer 입력 배열에서 임베딩의 인덱스
data[].sparse_embedding object 희소 임베딩 벡터
data[].sparse_embedding.indices array 어휘에서 0이 아닌 요소의 인덱스
data[].sparse_embedding.values array 해당 인덱스의 값
model string 임베딩 생성에 사용된 모델 (선택적)
usage object 토큰 사용 정보 (선택적)

희소 벡터 이해:

희소 벡터는 어휘 인덱스와 함께 0이 아닌 값만 저장합니다. 예를 들어:

  • indices: [123, 456, 789] - 어휘에서의 위치
  • values: [0.5, 0.3, 0.1] - 해당 용어의 가중치

이는 0이 아닌 요소가 적은 고차원 벡터에 대해 메모리 효율적입니다 (일반적으로 30,000개 이상의 어휘 크기 중 100-500개의 0이 아닌 값).

지원 백엔드:

백엔드 엔드포인트 참고
vLLM /embed_sparse OpenAI 호환 서버를 통한 SPLADE 모델 지원
Hugging Face TEI /embed_sparse --pooling splade 플래그 필요
Jina AI 네이티브 네이티브 희소 임베딩 지원

상태 코드:

  • 200: 희소 임베딩이 성공적으로 생성됨
  • 400: 유효하지 않은 요청 (model/input 누락, 빈 입력)
  • 401: 유효하지 않은 API 키
  • 404: 모델을 찾을 수 없거나 희소 임베딩을 지원하지 않음
  • 429: 속도 제한 초과
  • 500: 백엔드 오류
  • 503: 백엔드 사용 불가

사용 사례:

  • 하이브리드 검색: 더 나은 결과를 위해 밀집(의미) 및 희소(어휘) 검색 결합
  • 키워드 매칭: 학습된 가중치를 통한 정확한 용어 매칭
  • 도메인별 검색: 전문 용어 및 희귀 단어의 더 나은 처리
  • 교차 언어 검색: 일부 SPLADE 모델은 다국어 희소 검색 지원

요청 예제:

curl -X POST http://localhost:8080/embed_sparse \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-api-key" \
  -d '{
    "model": "naver/splade-v3",
    "input": "검색을 위한 희소 임베딩의 장점은 무엇인가요?"
  }'

여러 입력 예제:

curl -X POST http://localhost:8080/embed_sparse \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-api-key" \
  -d '{
    "model": "naver/splade-v3",
    "input": [
      "첫 번째 쿼리 텍스트",
      "두 번째 쿼리 텍스트"
    ]
  }'

Files API

Files API를 사용하면 채팅 완료에서 파일을 업로드, 관리 및 사용할 수 있습니다. 업로드된 파일은 image_file 콘텐츠 타입을 사용하여 메시지에서 참조할 수 있으며, 라우터가 파일 콘텐츠를 주입하여 이러한 참조를 자동으로 해결합니다.

파일 업로드

채팅 완료에서 사용할 파일을 업로드합니다.

POST /v1/files
Content-Type: multipart/form-data

폼 필드:

필드 타입 필수 설명
file file 업로드할 파일
purpose string 파일의 용도: vision, assistants, fine-tune, batch, user_data, evals

예제:

curl -X POST http://localhost:8080/v1/files \
  -F "file=@image.png" \
  -F "purpose=vision"

응답:

{
  "id": "file-abc123def456",
  "object": "file",
  "bytes": 12345,
  "created_at": 1699061776,
  "filename": "image.png",
  "purpose": "vision"
}

상태 코드:

  • 200: 파일이 성공적으로 업로드됨
  • 400: 유효하지 않은 요청 (파일 누락, 유효하지 않은 용도)
  • 413: 파일이 너무 큼 (설정된 maxfilesize 초과)

파일 목록

업로드된 파일 목록을 조회합니다.

GET /v1/files
GET /v1/files?purpose=vision

쿼리 파라미터:

파라미터 타입 필수 설명
purpose string 아니오 용도별 필터링

응답:

{
  "object": "list",
  "data": [
    {
      "id": "file-abc123def456",
      "object": "file",
      "bytes": 12345,
      "created_at": 1699061776,
      "filename": "image.png",
      "purpose": "vision"
    }
  ]
}


파일 메타데이터 가져오기

특정 파일의 메타데이터를 조회합니다.

GET /v1/files/{file_id}

응답:

{
  "id": "file-abc123def456",
  "object": "file",
  "bytes": 12345,
  "created_at": 1699061776,
  "filename": "image.png",
  "purpose": "vision"
}

상태 코드:

  • 200: 파일 메타데이터 조회됨
  • 404: 파일을 찾을 수 없음

파일 콘텐츠 다운로드

업로드된 파일의 콘텐츠를 다운로드합니다.

GET /v1/files/{file_id}/content

응답: 적절한 Content-Type 헤더와 함께 바이너리 파일 콘텐츠.

상태 코드:

  • 200: 파일 콘텐츠 반환됨
  • 404: 파일을 찾을 수 없음

파일 삭제

업로드된 파일을 삭제합니다.

DELETE /v1/files/{file_id}

응답:

{
  "id": "file-abc123def456",
  "object": "file",
  "deleted": true
}

상태 코드:

  • 200: 파일이 성공적으로 삭제됨
  • 404: 파일을 찾을 수 없음

채팅 완료에서의 파일 해결

라우터는 채팅 완료 요청에서 파일 참조를 자동으로 해결합니다. 메시지에 image_file 콘텐츠 블록이 포함되면 라우터는:

  1. 파일 ID 형식을 검증합니다
  2. 스토리지에서 파일 콘텐츠를 로드합니다
  3. 파일을 base64 data URL로 변환합니다
  4. image_file 블록을 image_url 블록으로 대체합니다

파일 참조가 포함된 요청:

{
  "model": "gpt-4-vision-preview",
  "messages": [
    {
      "role": "user",
      "content": [
        {"type": "text", "text": "What's in this image?"},
        {"type": "image_file", "image_file": {"file_id": "file-abc123def456"}}
      ]
    }
  ]
}

변환된 요청 (백엔드로 전송됨):

{
  "model": "gpt-4-vision-preview",
  "messages": [
    {
      "role": "user",
      "content": [
        {"type": "text", "text": "What's in this image?"},
        {"type": "image_url", "image_url": {"url": "data:image/png;base64,..."}}
      ]
    }
  ]
}

파일 해결 오류:

오류 상태 설명
유효하지 않은 파일 ID 형식 400 파일 ID는 file-로 시작해야 함
파일을 찾을 수 없음 404 참조된 파일이 존재하지 않음
파일 참조가 너무 많음 400 요청에 20개 이상의 파일 참조 포함
해결 타임아웃 504 파일 해결에 30초 이상 소요

지원되는 MIME 타입:

  • image/png - 모든 백엔드
  • image/jpeg - 모든 백엔드
  • image/gif - 모든 백엔드
  • image/webp - 모든 백엔드
  • application/pdf - OpenAI, Anthropic (최대 32MB, 100페이지)
  • text/plain - Anthropic (최대 32MB)

Anthropic 네이티브 API

Continuum Router는 Anthropic의 API 형식을 직접 사용하면서도 라우터의 로드 밸런싱, 장애 조치 및 다중 백엔드 라우팅 기능을 활용할 수 있는 네이티브 Anthropic API 엔드포인트를 제공합니다.

메시지 API

Anthropic의 네이티브 API 형식을 사용하여 메시지를 전송합니다.

POST /anthropic/v1/messages

헤더:

헤더 필수 설명
x-api-key 예* 인증용 API 키 (blocking 모드에서 필수)
anthropic-version 아니오 API 버전 (예: 2023-06-01). 네이티브 Anthropic 백엔드로 전달됨
anthropic-beta 아니오 베타 기능 (예: prompt-caching-2024-07-31). 네이티브 Anthropic 백엔드로 전달됨

요청 본문:

{
  "model": "claude-sonnet-4-20250514",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "안녕하세요, Claude!"
    }
  ],
  "stream": false
}

요청 파라미터:

파라미터 타입 필수 설명
model string 모델 식별자
max_tokens integer 생성할 최대 토큰 수
messages array 메시지 객체 배열
system string/array 아니오 시스템 프롬프트 (문자열 또는 콘텐츠 블록 배열)
stream boolean 아니오 스트리밍 활성화 (기본값: false)
temperature number 아니오 샘플링 온도 (0-1)
top_p number 아니오 핵 샘플링 파라미터
top_k integer 아니오 Top-k 샘플링 파라미터
stop_sequences array 아니오 정지 시퀀스
metadata object 아니오 요청 메타데이터
tools array 아니오 함수 호출을 위한 도구 정의
tool_choice object 아니오 도구 선택 설정

응답 (비스트리밍):

{
  "id": "msg_01XFDUDYJgAACzvnptvVoYEL",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "안녕하세요! 무엇을 도와드릴까요?"
    }
  ],
  "model": "claude-sonnet-4-20250514",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 12,
    "output_tokens": 15,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 0
  }
}

백엔드 라우팅:

라우터는 대상 백엔드에 따라 요청을 자동으로 변환합니다:

백엔드 타입 변환
Anthropic 네이티브 API 형식으로 패스스루
Gemini Gemini 형식으로 직접 변환
OpenAI/vLLM/Ollama OpenAI 형식으로 변환 후 응답을 다시 변환

토큰 카운팅

메시지 요청 페이로드의 토큰 수를 계산합니다.

POST /anthropic/v1/messages/count_tokens

요청 본문:

{
  "model": "claude-sonnet-4-20250514",
  "messages": [
    {
      "role": "user",
      "content": "안녕하세요, 어떠세요?"
    }
  ],
  "system": "당신은 도움이 되는 어시스턴트입니다."
}

응답:

{
  "input_tokens": 18
}

계층적 토큰 카운팅

토큰 카운팅은 백엔드 타입에 따라 다른 전략을 사용합니다:

백엔드 타입 전략 정확도
Anthropic 네이티브 /v1/messages/count_tokens API 프록시 정확
llama.cpp 백엔드 /tokenize 엔드포인트 프록시 정확
vLLM 백엔드 /tokenize 엔드포인트 프록시 정확
기타 문자 기반 추정 (~4자/토큰) 근사

참고: 네이티브 토큰화를 지원하지 않는 백엔드의 경우, 라우터는 토큰당 약 4자를 기준으로 하는 문자 기반 추정을 사용합니다. 이는 계획 목적으로 합리적인 근사치를 제공하지만 모델이 사용하는 정확한 토큰 수와 일치하지 않을 수 있습니다.

모델 목록

Anthropic API 형식으로 사용 가능한 모델을 나열합니다.

GET /anthropic/v1/models

응답:

{
  "data": [
    {
      "id": "claude-sonnet-4-20250514",
      "type": "model",
      "display_name": "Claude Sonnet 4",
      "created_at": "2025-05-14T00:00:00Z"
    },
    {
      "id": "claude-opus-4-20250514",
      "type": "model",
      "display_name": "Claude Opus 4",
      "created_at": "2025-05-14T00:00:00Z"
    }
  ],
  "has_more": false,
  "first_id": "claude-sonnet-4-20250514",
  "last_id": "claude-opus-4-20250514"
}

Claude Code 호환성

Anthropic 네이티브 API는 Claude Code 및 고급 기능이 필요한 기타 Anthropic API 클라이언트와의 완전한 호환성을 포함합니다.

프롬프트 캐싱

프롬프트 캐싱은 콘텐츠 블록의 cache_control 필드를 통해 완벽하게 지원됩니다:

{
  "model": "claude-sonnet-4-20250514",
  "max_tokens": 1024,
  "system": [
    {
      "type": "text",
      "text": "당신은 광범위한 지식을 가진 유용한 코딩 어시스턴트입니다...",
      "cache_control": {"type": "ephemeral"}
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "이전 컨텍스트...",
          "cache_control": {"type": "ephemeral"}
        },
        {
          "type": "text",
          "text": "현재 질문"
        }
      ]
    }
  ]
}

지원되는 cache_control 위치:

  • 시스템 프롬프트 텍스트 블록
  • 사용자 메시지 텍스트 블록
  • 사용자 메시지 이미지 블록
  • 도구 정의
  • 도구 사용 블록
  • 도구 결과 블록

베타 기능 헤더

anthropic-beta 헤더는 네이티브 Anthropic 백엔드로 전달되어 베타 기능을 활성화합니다:

curl -X POST http://localhost:8080/anthropic/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: prompt-caching-2024-07-31,interleaved-thinking-2025-05-14" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-20250514",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "안녕하세요"}]
  }'

스트리밍에서의 캐시 사용량

네이티브 Anthropic 백엔드로 스트리밍할 때 캐시 사용량 정보가 message_start 이벤트에 포함됩니다:

{
  "type": "message_start",
  "message": {
    "id": "msg_01XFDUDYJgAACzvnptvVoYEL",
    "type": "message",
    "role": "assistant",
    "content": [],
    "model": "claude-sonnet-4-20250514",
    "usage": {
      "input_tokens": 2159,
      "cache_creation_input_tokens": 2048,
      "cache_read_input_tokens": 0
    }
  }
}

인터리브드 씽킹

인터리브드 출력을 포함한 확장 사고(Extended Thinking)는 스트리밍 모드에서 지원됩니다. 모델이 사고와 텍스트 콘텐츠를 교대로 생성할 때, 스트리밍 이벤트는 각 블록에 대해 적절한 content_block_start, content_block_delta, content_block_stop 이벤트와 함께 이 인터리브드 구조를 올바르게 표현합니다.


관리 엔드포인트

백엔드 상태

설정된 모든 백엔드에 대한 상세 상태 정보를 가져옵니다.

GET /admin/backends

응답:

{
  "backends": [
    {
      "name": "local-ollama",
      "url": "http://localhost:11434",
      "is_healthy": true,
      "consecutive_failures": 0,
      "consecutive_successes": 15,
      "last_check": "2024-01-15T10:30:45Z",
      "last_error": null,
      "response_time_ms": 45,
      "models": ["llama2", "mistral", "codellama"],
      "weight": 1,
      "total_requests": 150,
      "failed_requests": 2
    },
    {
      "name": "openai-compatible",
      "url": "https://api.openai.com",
      "is_healthy": false,
      "consecutive_failures": 3,
      "consecutive_successes": 0,
      "last_check": "2024-01-15T10:29:30Z",
      "last_error": "Connection timeout after 5s",
      "response_time_ms": null,
      "models": [],
      "weight": 1,
      "total_requests": 45,
      "failed_requests": 8
    }
  ],
  "healthy_count": 1,
  "total_count": 2,
  "summary": {
    "total_models": 3,
    "total_requests": 195,
    "total_failures": 10,
    "average_response_time_ms": 45
  }
}

필드:

필드 타입 설명
name string 설정의 백엔드 식별자
url string 백엔드 기본 URL
is_healthy boolean 현재 헬스 상태
consecutive_failures integer 연속 실패한 헬스 체크
consecutive_successes integer 연속 성공한 헬스 체크
last_check string 마지막 헬스 체크의 ISO 타임스탬프
last_error string/null 비정상 시 마지막 오류 메시지
response_time_ms integer/null 마지막 헬스 체크 응답 시간
models array 이 백엔드의 사용 가능한 모델
weight integer 로드 밸런싱 가중치
total_requests integer 이 백엔드로 라우팅된 총 요청 수
failed_requests integer 이 백엔드에 대한 실패한 요청 수

상태 코드:

  • 200: 백엔드 상태가 성공적으로 조회됨

서비스 헬스

전체 서비스 헬스 및 컴포넌트 상태를 가져옵니다.

GET /admin/health

응답:

{
  "status": "healthy",
  "version": "1.0.0",
  "uptime": "2h 15m 30s",
  "timestamp": "2024-01-15T10:30:45Z",
  "services": {
    "backend_service": {
      "status": "healthy",
      "message": "All backends operational",
      "healthy_backends": 2,
      "total_backends": 2
    },
    "model_service": {
      "status": "healthy",
      "message": "Model cache operational",
      "cached_models": 15,
      "cache_hit_rate": 0.95,
      "last_refresh": "2024-01-15T10:25:00Z"
    },
    "proxy_service": {
      "status": "healthy",
      "message": "Request routing operational",
      "total_requests": 1250,
      "failed_requests": 12,
      "average_latency_ms": 85
    },
    "health_service": {
      "status": "healthy",
      "message": "Health monitoring active",
      "check_interval": "30s",
      "last_check": "2024-01-15T10:30:00Z"
    }
  },
  "metrics": {
    "requests_per_second": 5.2,
    "error_rate": 0.008,
    "memory_usage_mb": 125,
    "cpu_usage_percent": 15.5
  }
}

상태 값:

  • healthy: 서비스가 정상 작동 중
  • degraded: 서비스가 제한된 기능으로 작동 중
  • unhealthy: 서비스에 문제가 발생함

상태 코드:

  • 200: 서비스 헬스가 성공적으로 조회됨
  • 503: 서비스가 비정상

설정 요약

핫 리로드 상태를 포함한 현재 설정 요약을 가져옵니다.

GET /admin/config

응답:

{
  "server": {
    "bind_address": "0.0.0.0:8080",
    "workers": 4,
    "connection_pool_size": 100
  },
  "backends": {
    "count": 3,
    "names": ["openai", "local-ollama", "gemini"]
  },
  "health_checks": {
    "interval": "30s",
    "timeout": "10s",
    "unhealthy_threshold": 3,
    "healthy_threshold": 2
  },
  "rate_limiting": {
    "enabled": false
  },
  "circuit_breaker": {
    "enabled": true
  },
  "selection_strategy": "RoundRobin",
  "hot_reload": {
    "available": true,
    "note": "Configuration changes will be automatically detected and applied"
  }
}

필드:

필드 타입 설명
server object 서버 설정 (bindaddress, workers, connectionpool_size)
backends object 백엔드 설정 요약 (count, names)
health_checks object 헬스 체크 설정
rate_limiting object 속도 제한 상태
circuit_breaker object 서킷 브레이커 상태
selection_strategy string 현재 로드 밸런싱 전략
hot_reload object 핫 리로드 가용성 및 상태

상태 코드:

  • 200: 설정 요약이 성공적으로 조회됨

참고: 민감한 정보 (API 키 등)는 응답에서 자동으로 수정됩니다.


핫 리로드 상태

핫 리로드 기능 및 설정 항목 분류에 대한 상세 정보를 가져옵니다.

GET /admin/config/hot-reload-status

응답:

{
  "enabled": true,
  "description": "Hot reload is enabled. Configuration file changes are automatically detected and applied.",
  "capabilities": {
    "immediate_update": {
      "description": "Changes applied immediately without service interruption",
      "items": [
        "logging.level",
        "rate_limiting.*",
        "circuit_breaker.*",
        "retry.*",
        "global_prompts.*"
      ]
    },
    "gradual_update": {
      "description": "Existing connections maintained, new connections use new config",
      "items": [
        "backends.*",
        "health_checks.*",
        "timeouts.*"
      ]
    },
    "requires_restart": {
      "description": "Changes logged as warnings, restart required to take effect",
      "items": [
        "server.bind_address",
        "server.workers"
      ]
    }
  }
}

필드:

필드 타입 설명
enabled boolean 핫 리로드 활성화 여부
description string 핫 리로드 상태에 대한 읽기 쉬운 설명
capabilities object 핫 리로드 기능별 설정 항목 분류
capabilities.immediate_update object 중단 없이 즉시 업데이트되는 항목
capabilities.gradual_update object 새 연결에만 적용되는 항목
capabilities.requires_restart object 서버 재시작이 필요한 항목

설정 항목 분류:

즉시 업데이트 (서비스 중단 없음):

  • logging.level - 로그 레벨 변경이 즉시 적용
  • rate_limiting.* - 속도 제한 설정이 실시간으로 업데이트
  • circuit_breaker.* - 서킷 브레이커 임계값 및 타임아웃
  • retry.* - 재시도 정책 및 백오프 전략
  • global_prompts.* - 전역 시스템 프롬프트 주입 설정

점진적 업데이트 (기존 연결 유지):

  • backends.* - 백엔드 추가/제거/수정 (새 요청이 업데이트된 풀 사용)
  • health_checks.* - 헬스 체크 간격 및 임계값
  • timeouts.* - 새 요청에 대한 타임아웃 값

재시작 필요 (경고로 로깅):

  • server.bind_address - TCP 바인드 주소
  • server.workers - 워커 스레드 수

상태 코드:

  • 200: 핫 리로드 상태가 성공적으로 조회됨

사용 예제:

# 핫 리로드 활성화 여부 확인
curl http://localhost:8080/admin/config/hot-reload-status | jq '.enabled'

# 즉시 업데이트를 지원하는 항목 목록
curl http://localhost:8080/admin/config/hot-reload-status | jq '.capabilities.immediate_update.items'


설정 관리 API

설정 관리 API를 사용하면 서버 재시작 없이 런타임에 라우터 설정을 보고 수정할 수 있습니다. 이는 프로덕션 환경에서 동작을 조정하고, 백엔드를 추가하고, 설정을 미세 조정하는 데 운영 유연성을 제공합니다.

개요

주요 기능:

  • 런타임 설정: 서버 재시작 없이 설정 보기 및 수정
  • 핫 리로드 지원: 지원되는 설정에 변경 사항 즉시 적용
  • 검증: 적용 전 설정 변경 사항 검증
  • 히스토리 및 롤백: 설정 변경 추적 및 이전 버전으로 롤백
  • 내보내기/가져오기: 환경 간 설정 백업 및 복원
  • 보안: 민감한 정보 (API 키, 비밀번호, 토큰)가 자동으로 마스킹됨

설정 쿼리 API

전체 설정 가져오기

보안을 위해 민감한 정보가 마스킹된 전체 현재 설정을 반환합니다.

GET /admin/config/full

응답:

{
  "server": {
    "bind_address": "0.0.0.0:8080",
    "workers": 4,
    "connection_pool_size": 100
  },
  "backends": [
    {
      "name": "openai",
      "url": "https://api.openai.com",
      "api_key": "sk-****...**",
      "weight": 1,
      "models": ["gpt-4", "gpt-3.5-turbo"]
    },
    {
      "name": "local-ollama",
      "url": "http://localhost:11434",
      "weight": 1,
      "models": []
    }
  ],
  "health_checks": {
    "interval": "30s",
    "timeout": "10s",
    "unhealthy_threshold": 3,
    "healthy_threshold": 2
  },
  "logging": {
    "level": "info",
    "format": "json"
  },
  "retry": {
    "max_attempts": 3,
    "backoff": "exponential",
    "initial_delay_ms": 100
  },
  "timeouts": {
    "connect": "5s",
    "request": "60s"
  },
  "rate_limiting": {
    "enabled": false
  },
  "circuit_breaker": {
    "enabled": true,
    "failure_threshold": 5,
    "recovery_timeout": "30s"
  }
}

참고 사항:

  • API 키, 비밀번호, 토큰은 마스킹됨 (예: sk-****...**)
  • 모든 설정 섹션이 응답에 포함됨
  • 개별 섹션 세부 정보는 /admin/config/{section} 사용

상태 코드:

  • 200: 설정이 성공적으로 조회됨

설정 섹션 목록

사용 가능한 모든 설정 섹션 목록을 반환합니다.

GET /admin/config/sections

응답:

{
  "sections": [
    "server",
    "backends",
    "health_checks",
    "logging",
    "retry",
    "timeouts",
    "rate_limiting",
    "circuit_breaker",
    "global_prompts",
    "admin",
    "fallback",
    "files",
    "api_keys",
    "metrics",
    "routing"
  ],
  "total": 15
}

상태 코드:

  • 200: 섹션 목록이 성공적으로 조회됨

설정 섹션 가져오기

핫 리로드 기능 정보와 함께 특정 섹션의 설정을 반환합니다.

GET /admin/config/{section}

경로 파라미터:

파라미터 타입 필수 설명
section string 설정 섹션 이름

요청 예제:

curl http://localhost:8080/admin/config/logging

응답:

{
  "section": "logging",
  "config": {
    "level": "info",
    "format": "json",
    "output": "stdout",
    "include_timestamps": true
  },
  "hot_reload_capability": "immediate_update",
  "description": "Changes to this section apply immediately without service interruption"
}

핫 리로드 기능 값:

설명
immediate_update 서비스 중단 없이 변경 사항 즉시 적용
gradual_update 기존 연결 유지, 새 연결이 새 설정 사용
requires_restart 변경 사항 적용에 서버 재시작 필요

상태 코드:

  • 200: 섹션 설정이 성공적으로 조회됨
  • 404: 유효하지 않은 섹션 이름

오류 응답:

{
  "error": {
    "message": "Configuration section 'invalid_section' not found",
    "type": "not_found",
    "code": 404,
    "details": {
      "requested_section": "invalid_section",
      "available_sections": ["server", "backends", "logging", "..."]
    }
  }
}


설정 스키마 가져오기

설정 검증을 위한 JSON Schema를 반환합니다. 변경 사항 제출 전 클라이언트 측 검증에 유용합니다.

GET /admin/config/schema

응답:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "server": {
      "type": "object",
      "properties": {
        "bind_address": {
          "type": "string",
          "pattern": "^[0-9.]+:[0-9]+$",
          "description": "Server bind address in host:port format"
        },
        "workers": {
          "type": "integer",
          "minimum": 1,
          "maximum": 256,
          "description": "Number of worker threads"
        },
        "connection_pool_size": {
          "type": "integer",
          "minimum": 1,
          "maximum": 10000,
          "description": "HTTP connection pool size per backend"
        }
      },
      "required": ["bind_address"]
    },
    "backends": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Unique backend identifier"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Backend base URL"
          },
          "weight": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "default": 1,
            "description": "Load balancing weight"
          },
          "models": {
            "type": "array",
            "items": {"type": "string"},
            "description": "Explicit model list (optional)"
          }
        },
        "required": ["name", "url"]
      }
    },
    "logging": {
      "type": "object",
      "properties": {
        "level": {
          "type": "string",
          "enum": ["trace", "debug", "info", "warn", "error"],
          "description": "Log level"
        },
        "format": {
          "type": "string",
          "enum": ["json", "text", "pretty"],
          "description": "Log output format"
        }
      }
    }
  }
}

상태 코드:

  • 200: 스키마가 성공적으로 조회됨

설정 수정 API

설정 섹션 대체

전체 설정 섹션을 대체합니다. 검증을 트리거하고 해당하는 경우 핫 리로드합니다.

PUT /admin/config/{section}

경로 파라미터:

파라미터 타입 필수 설명
section string 설정 섹션 이름

요청 본문: 전체 섹션 설정 객체.

요청 예제:

curl -X PUT http://localhost:8080/admin/config/logging \
  -H "Content-Type: application/json" \
  -d '{
    "level": "debug",
    "format": "json",
    "output": "stdout",
    "include_timestamps": true
  }'

응답:

{
  "success": true,
  "section": "logging",
  "hot_reload_applied": true,
  "message": "Configuration updated and applied immediately",
  "previous": {
    "level": "info",
    "format": "json",
    "output": "stdout",
    "include_timestamps": true
  },
  "current": {
    "level": "debug",
    "format": "json",
    "output": "stdout",
    "include_timestamps": true
  },
  "version": 15
}

상태 코드:

  • 200: 설정이 성공적으로 업데이트됨
  • 400: 유효하지 않은 설정 형식 또는 검증 오류
  • 404: 유효하지 않은 섹션 이름

설정 섹션 부분 업데이트

JSON 병합 패치 의미론을 사용하여 부분 업데이트를 수행합니다. 지정된 필드만 업데이트되고 지정되지 않은 필드는 현재 값을 유지합니다.

PATCH /admin/config/{section}

경로 파라미터:

파라미터 타입 필수 설명
section string 설정 섹션 이름

요청 본문: 업데이트할 필드가 포함된 부분 설정 객체.

요청 예제:

curl -X PATCH http://localhost:8080/admin/config/logging \
  -H "Content-Type: application/json" \
  -d '{
    "level": "warn"
  }'

응답:

{
  "success": true,
  "section": "logging",
  "hot_reload_applied": true,
  "message": "Configuration partially updated and applied",
  "changes": {
    "level": {
      "from": "info",
      "to": "warn"
    }
  },
  "current": {
    "level": "warn",
    "format": "json",
    "output": "stdout",
    "include_timestamps": true
  },
  "version": 16
}

병합 동작:

  • 스칼라 값은 대체됨
  • 객체는 재귀적으로 병합됨
  • 배열은 전체가 대체됨 (병합 안 됨)
  • null 값은 필드를 제거함 (선택 사항인 경우)

상태 코드:

  • 200: 설정이 성공적으로 업데이트됨
  • 400: 유효하지 않은 설정 형식 또는 검증 오류
  • 404: 유효하지 않은 섹션 이름

설정 검증

변경 사항을 적용하지 않고 설정을 검증합니다. 설정 변경 사항을 안전하게 테스트하기 위한 dry_run 모드를 지원합니다.

POST /admin/config/validate

요청 본문:

{
  "section": "backends",
  "config": {
    "name": "new-backend",
    "url": "http://localhost:8000",
    "weight": 2
  },
  "dry_run": true
}

파라미터:

파라미터 타입 필수 설명
section string 검증할 설정 섹션
config object 검증할 설정
dry_run boolean 아니오 true인 경우, 적용 준비 없이 검증만 (기본값: true)

응답 (유효):

{
  "valid": true,
  "section": "backends",
  "warnings": [
    "Backend 'new-backend' has no explicit model list; models will be auto-discovered"
  ],
  "info": {
    "hot_reload_capability": "gradual_update",
    "estimated_impact": "New requests may be routed to this backend after apply"
  }
}

응답 (유효하지 않음):

{
  "valid": false,
  "section": "backends",
  "errors": [
    {
      "field": "url",
      "message": "Invalid URL format: missing scheme",
      "value": "localhost:8000"
    },
    {
      "field": "weight",
      "message": "Weight must be between 0 and 100",
      "value": 150
    }
  ],
  "warnings": []
}

상태 코드:

  • 200: 검증 완료 (결과는 valid 필드 확인)
  • 400: 유효하지 않은 요청 형식

보류 중인 변경 사항 적용

보류 중인 설정 변경 사항을 즉시 적용합니다. 적용 가능한 설정에 대해 핫 리로드를 트리거합니다.

POST /admin/config/apply

요청 본문 (선택 사항):

{
  "sections": ["logging", "rate_limiting"],
  "force": false
}

파라미터:

파라미터 타입 필수 설명
sections array 아니오 적용할 특정 섹션 (기본값: 모든 보류 중)
force boolean 아니오 경고가 있어도 강제 적용 (기본값: false)

응답:

{
  "success": true,
  "applied_sections": ["logging", "rate_limiting"],
  "results": {
    "logging": {
      "status": "applied",
      "hot_reload": "immediate_update"
    },
    "rate_limiting": {
      "status": "applied",
      "hot_reload": "immediate_update"
    }
  },
  "version": 17,
  "timestamp": "2024-01-15T10:45:30Z"
}

상태 코드:

  • 200: 변경 사항이 성공적으로 적용됨
  • 400: 보류 중인 변경 사항이 없거나 검증 오류
  • 409: 동시 수정과 충돌

설정 저장/복원 API

설정 내보내기

지정된 형식으로 현재 설정을 내보냅니다.

POST /admin/config/export

요청 본문:

{
  "format": "yaml",
  "include_sensitive": false,
  "sections": ["server", "backends", "logging"]
}

파라미터:

파라미터 타입 필수 설명
format string 아니오 내보내기 형식: yaml, json, 또는 toml (기본값: yaml)
include_sensitive boolean 아니오 마스킹 안 된 민감 데이터 포함 (권한 상승 필요, 기본값: false)
sections array 아니오 내보낼 특정 섹션 (기본값: 전체)

응답 (format: json):

{
  "format": "json",
  "content": "{\"server\":{\"bind_address\":\"0.0.0.0:8080\",...}}",
  "sections_exported": ["server", "backends", "logging"],
  "exported_at": "2024-01-15T10:45:30Z",
  "version": 17,
  "checksum": "sha256:a1b2c3d4..."
}

응답 (format: yaml):

{
  "format": "yaml",
  "content": "server:\n  bind_address: \"0.0.0.0:8080\"\n  workers: 4\n...",
  "sections_exported": ["server", "backends", "logging"],
  "exported_at": "2024-01-15T10:45:30Z",
  "version": 17,
  "checksum": "sha256:a1b2c3d4..."
}

상태 코드:

  • 200: 내보내기 성공
  • 400: 지정된 형식이 유효하지 않음
  • 403: include_sensitive: true에 대해 권한 상승 필요

설정 가져오기

제공된 콘텐츠에서 설정을 가져옵니다.

POST /admin/config/import

요청 본문:

{
  "format": "yaml",
  "content": "server:\n  bind_address: \"0.0.0.0:8080\"\n  workers: 8\nlogging:\n  level: debug",
  "dry_run": true,
  "merge": false
}

파라미터:

파라미터 타입 필수 설명
format string 콘텐츠 형식: yaml, json, 또는 toml
content string 가져올 설정 콘텐츠
dry_run boolean 아니오 적용 없이 검증만 (기본값: false)
merge boolean 아니오 기존 설정과 병합 vs 대체 (기본값: false)

응답 (dry_run: true):

{
  "valid": true,
  "dry_run": true,
  "changes_preview": {
    "server": {
      "workers": {"from": 4, "to": 8}
    },
    "logging": {
      "level": {"from": "info", "to": "debug"}
    }
  },
  "sections_affected": ["server", "logging"],
  "warnings": [
    "server.workers change requires restart to take effect"
  ]
}

응답 (dry_run: false):

{
  "success": true,
  "imported_sections": ["server", "logging"],
  "hot_reload_results": {
    "logging": "applied_immediately",
    "server": "requires_restart"
  },
  "version": 18,
  "timestamp": "2024-01-15T10:50:00Z"
}

상태 코드:

  • 200: 가져오기 성공 (또는 dry_run 검증 통과)
  • 400: 유효하지 않은 형식 또는 콘텐츠 파싱 오류
  • 422: 설정 검증 실패

설정 히스토리 가져오기

설정 변경 히스토리를 조회합니다.

GET /admin/config/history

쿼리 파라미터:

파라미터 타입 필수 설명
limit integer 아니오 반환할 최대 항목 수 (기본값: 20, 최대: 100)
offset integer 아니오 건너뛸 항목 수 (기본값: 0)
section string 아니오 섹션 이름으로 필터링

요청 예제:

curl "http://localhost:8080/admin/config/history?limit=10&section=logging"

응답:

{
  "history": [
    {
      "version": 18,
      "timestamp": "2024-01-15T10:50:00Z",
      "sections_changed": ["logging"],
      "source": "api",
      "user": "admin",
      "changes": {
        "logging": {
          "level": {"from": "info", "to": "debug"}
        }
      }
    },
    {
      "version": 17,
      "timestamp": "2024-01-15T09:30:00Z",
      "sections_changed": ["backends"],
      "source": "file_reload",
      "user": null,
      "changes": {
        "backends": {
          "added": ["new-backend"],
          "modified": [],
          "removed": []
        }
      }
    },
    {
      "version": 16,
      "timestamp": "2024-01-14T15:20:00Z",
      "sections_changed": ["rate_limiting"],
      "source": "api",
      "user": "admin",
      "changes": {
        "rate_limiting": {
          "enabled": {"from": false, "to": true}
        }
      }
    }
  ],
  "total": 18,
  "limit": 10,
  "offset": 0
}

Source 값:

Source 설명
api 설정 관리 API를 통해 변경됨
file_reload 설정 파일 핫 리로드를 통해 변경됨
startup 서버 시작 시 초기 설정
rollback 이전 버전에서 복원됨

상태 코드:

  • 200: 히스토리가 성공적으로 조회됨

설정 롤백

이전 설정 버전으로 롤백합니다.

POST /admin/config/rollback/{version}

경로 파라미터:

파라미터 타입 필수 설명
version integer 롤백할 버전 번호

요청 본문 (선택 사항):

{
  "dry_run": false,
  "sections": ["logging", "backends"]
}

파라미터:

파라미터 타입 필수 설명
dry_run boolean 아니오 적용 없이 변경 사항 미리보기 (기본값: false)
sections array 아니오 롤백할 특정 섹션 (기본값: 변경된 모든 섹션)

응답:

{
  "success": true,
  "rolled_back_from": 18,
  "rolled_back_to": 15,
  "sections_restored": ["logging", "backends"],
  "changes": {
    "logging": {
      "level": {"from": "debug", "to": "info"}
    },
    "backends": {
      "removed": ["new-backend"]
    }
  },
  "new_version": 19,
  "timestamp": "2024-01-15T11:00:00Z"
}

상태 코드:

  • 200: 롤백 성공
  • 400: 대상 설정에 대한 검증 오류
  • 404: 히스토리에서 버전을 찾을 수 없음

백엔드 관리 API

이 엔드포인트는 전체 백엔드 설정 섹션을 수정하지 않고 백엔드를 관리하기 위한 편리한 단축키를 제공합니다.

백엔드 추가

라우터에 새 백엔드를 동적으로 추가합니다.

POST /admin/backends

요청 본문:

{
  "name": "new-ollama",
  "url": "http://192.168.1.100:11434",
  "weight": 2,
  "models": ["llama2", "codellama"],
  "api_key": null,
  "health_check_path": "/api/tags"
}

파라미터:

파라미터 타입 필수 설명
name string 고유한 백엔드 식별자
url string 백엔드 기본 URL
weight integer 아니오 로드 밸런싱 가중치 (기본값: 1)
models array 아니오 명시적 모델 목록 (비어 있으면 자동 검색)
api_key string 아니오 인증을 위한 API 키
health_check_path string 아니오 커스텀 헬스 체크 엔드포인트

응답:

{
  "success": true,
  "backend": {
    "name": "new-ollama",
    "url": "http://192.168.1.100:11434",
    "weight": 2,
    "models": ["llama2", "codellama"],
    "is_healthy": null,
    "status": "pending_health_check"
  },
  "message": "Backend added successfully. Health check scheduled.",
  "config_version": 20
}

상태 코드:

  • 200: 백엔드가 성공적으로 추가됨
  • 400: 유효하지 않은 백엔드 설정
  • 409: 이 이름의 백엔드가 이미 존재함

백엔드 설정 가져오기

특정 백엔드의 설정을 조회합니다.

GET /admin/backends/{name}

경로 파라미터:

파라미터 타입 필수 설명
name string 백엔드 식별자

응답:

{
  "name": "local-ollama",
  "url": "http://localhost:11434",
  "weight": 1,
  "models": ["llama2", "mistral", "codellama"],
  "api_key": null,
  "health_check_path": "/api/tags",
  "is_healthy": true,
  "consecutive_failures": 0,
  "consecutive_successes": 25,
  "last_check": "2024-01-15T10:55:00Z",
  "total_requests": 1250,
  "failed_requests": 3
}

상태 코드:

  • 200: 백엔드 설정 조회됨
  • 404: 백엔드를 찾을 수 없음

백엔드 설정 업데이트

기존 백엔드의 설정을 업데이트합니다.

PUT /admin/backends/{name}

경로 파라미터:

파라미터 타입 필수 설명
name string 백엔드 식별자

요청 본문:

{
  "url": "http://localhost:11434",
  "weight": 3,
  "models": ["llama2", "mistral", "codellama", "phi"],
  "api_key": null
}

응답:

{
  "success": true,
  "backend": {
    "name": "local-ollama",
    "url": "http://localhost:11434",
    "weight": 3,
    "models": ["llama2", "mistral", "codellama", "phi"]
  },
  "changes": {
    "weight": {"from": 1, "to": 3},
    "models": {"added": ["phi"], "removed": []}
  },
  "config_version": 21
}

상태 코드:

  • 200: 백엔드가 성공적으로 업데이트됨
  • 400: 유효하지 않은 설정
  • 404: 백엔드를 찾을 수 없음

백엔드 삭제

라우터에서 백엔드를 제거합니다.

DELETE /admin/backends/{name}

경로 파라미터:

파라미터 타입 필수 설명
name string 백엔드 식별자

쿼리 파라미터:

파라미터 타입 필수 설명
drain boolean 아니오 활성 요청이 완료될 때까지 대기 (기본값: true)
timeout integer 아니오 드레인 타임아웃 (초) (기본값: 30)

요청 예제:

curl -X DELETE "http://localhost:8080/admin/backends/old-backend?drain=true&timeout=60"

응답:

{
  "success": true,
  "deleted_backend": "old-backend",
  "drained": true,
  "active_requests_completed": 5,
  "config_version": 22,
  "message": "Backend removed from rotation"
}

상태 코드:

  • 200: 백엔드가 성공적으로 삭제됨
  • 404: 백엔드를 찾을 수 없음
  • 409: 마지막 남은 백엔드를 삭제할 수 없음

백엔드 가중치 업데이트

백엔드의 로드 밸런싱 가중치만 업데이트합니다.

PUT /admin/backends/{name}/weight

경로 파라미터:

파라미터 타입 필수 설명
name string 백엔드 식별자

요청 본문:

{
  "weight": 5
}

응답:

{
  "success": true,
  "backend": "local-ollama",
  "weight": {
    "from": 1,
    "to": 5
  },
  "config_version": 23
}

상태 코드:

  • 200: 가중치가 성공적으로 업데이트됨
  • 400: 유효하지 않은 가중치 값
  • 404: 백엔드를 찾을 수 없음

백엔드 모델 업데이트

백엔드의 모델 목록만 업데이트합니다.

PUT /admin/backends/{name}/models

경로 파라미터:

파라미터 타입 필수 설명
name string 백엔드 식별자

요청 본문:

{
  "models": ["llama2", "mistral", "codellama", "phi", "gemma"],
  "mode": "replace"
}

파라미터:

파라미터 타입 필수 설명
models array 모델 목록
mode string 아니오 업데이트 모드: replace, add, 또는 remove (기본값: replace)

응답:

{
  "success": true,
  "backend": "local-ollama",
  "models": {
    "previous": ["llama2", "mistral", "codellama"],
    "current": ["llama2", "mistral", "codellama", "phi", "gemma"],
    "added": ["phi", "gemma"],
    "removed": []
  },
  "config_version": 24
}

상태 코드:

  • 200: 모델이 성공적으로 업데이트됨
  • 400: 유효하지 않은 모델 목록
  • 404: 백엔드를 찾을 수 없음

오류 처리

오류 응답 형식

모든 오류는 일관된 JSON 구조를 따릅니다:

{
  "error": {
    "message": "Human-readable error description",
    "type": "error_type_identifier",
    "code": 404,
    "details": {
      "additional": "context information"
    }
  }
}

오류 타입

타입 HTTP 코드 설명
bad_request 400 유효하지 않은 요청 형식 또는 파라미터
unauthorized 401 인증 필요 (향후 기능)
forbidden 403 접근 거부 (향후 기능)
model_not_found 404 요청된 모델을 사용할 수 없음
rate_limit_exceeded 429 속도 제한 초과 (향후 기능)
internal_error 500 라우터 내부 오류
bad_gateway 502 백엔드 연결/응답 오류
service_unavailable 503 모든 백엔드가 비정상
gateway_timeout 504 백엔드 요청 타임아웃

오류 응답 예제

모델을 찾을 수 없음:

{
  "error": {
    "message": "Model 'invalid-model' not found on any healthy backend",
    "type": "model_not_found",
    "code": 404,
    "details": {
      "requested_model": "invalid-model",
      "available_models": ["gpt-4", "gpt-3.5-turbo", "llama2"]
    }
  }
}

백엔드 오류:

{
  "error": {
    "message": "Failed to connect to backend 'local-ollama'",
    "type": "bad_gateway",
    "code": 502,
    "details": {
      "backend": "local-ollama",
      "backend_error": "Connection refused"
    }
  }
}

서비스 사용 불가:

{
  "error": {
    "message": "All backends are currently unhealthy",
    "type": "service_unavailable",
    "code": 503,
    "details": {
      "healthy_backends": 0,
      "total_backends": 3
    }
  }
}

속도 제한

참고: 속도 제한은 현재 구현되지 않았지만 향후 릴리스에서 계획되어 있습니다.

향후 속도 제한은 다음을 지원할 예정입니다:

  • IP별 속도 제한
  • API 키별 속도 제한
  • 모델별 속도 제한
  • 슬라이딩 윈도우 알고리즘
  • 응답의 속도 제한 헤더

스트리밍

Server-Sent Events (SSE)

stream: true가 지정되면 응답은 다음과 함께 Server-Sent Events로 전송됩니다:

Content-Type: text/event-stream Cache-Control: no-cache Connection: keep-alive

SSE 형식

data: {"id":"chatcmpl-123","object":"chat.completion.chunk",...}

data: {"id":"chatcmpl-123","object":"chat.completion.chunk",...}

data: [DONE]

SSE 호환성

라우터는 최대 호환성을 위해 여러 SSE 형식을 지원합니다:

  • 표준 형식: data: {...}
  • 스페이스 형식: data: {...}
  • 혼합 줄 바꿈: \r\n, \n, \r 처리
  • 빈 줄: 청크 구분자 올바르게 처리

연결 관리

  • Keep-Alive: 스트리밍 중 연결 유지
  • 타임아웃: 장시간 실행 요청에 대해 5분 타임아웃
  • 오류 처리: 부분 응답에 오류 정보 포함
  • 클라이언트 연결 해제: 클라이언트 연결 해제를 정상적으로 처리

예제

기본 채팅 완료

curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-3.5-turbo",
    "messages": [
      {"role": "user", "content": "Hello, how are you?"}
    ]
  }'

스트리밍 채팅 완료

curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-3.5-turbo",
    "messages": [
      {"role": "user", "content": "Write a short story"}
    ],
    "stream": true,
    "max_tokens": 200
  }'

파라미터가 포함된 텍스트 완료

curl -X POST http://localhost:8080/v1/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-3.5-turbo-instruct",
    "prompt": "The future of AI is",
    "max_tokens": 50,
    "temperature": 0.8,
    "top_p": 0.9
  }'

백엔드 상태 확인

curl http://localhost:8080/admin/backends | jq

서비스 헬스 모니터링

curl http://localhost:8080/admin/health | jq '.services'

사용 가능한 모델 목록

curl http://localhost:8080/v1/models | jq '.data[].id'

Python 클라이언트 예제

import requests
import json

# 클라이언트 설정
BASE_URL = "http://localhost:8080"

def chat_completion(messages, model="gpt-3.5-turbo", stream=False):
    """채팅 완료 요청 전송"""
    response = requests.post(
        f"{BASE_URL}/v1/chat/completions",
        headers={"Content-Type": "application/json"},
        json={
            "model": model,
            "messages": messages,
            "stream": stream,
            "temperature": 0.7
        },
        stream=stream
    )

    if stream:
        # 스트리밍 응답 처리
        for line in response.iter_lines():
            if line:
                line = line.decode('utf-8')
                if line.startswith('data: '):
                    data = line[6:]  # 'data: ' 접두사 제거
                    if data == '[DONE]':
                        break
                    try:
                        chunk = json.loads(data)
                        content = chunk['choices'][0]['delta'].get('content', '')
                        if content:
                            print(content, end='', flush=True)
                    except json.JSONDecodeError:
                        continue
        print()  # 스트리밍 후 새 줄
    else:
        # 비스트리밍 응답 처리
        result = response.json()
        return result['choices'][0]['message']['content']

# 사용 예제
messages = [
    {"role": "user", "content": "Explain machine learning in simple terms"}
]

print("스트리밍 응답:")
chat_completion(messages, stream=True)

print("\n비스트리밍 응답:")
response = chat_completion(messages, stream=False)
print(response)

JavaScript/Node.js 클라이언트 예제

const fetch = require('node-fetch');

const BASE_URL = 'http://localhost:8080';

async function chatCompletion(messages, options = {}) {
    const response = await fetch(`${BASE_URL}/v1/chat/completions`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            model: options.model || 'gpt-3.5-turbo',
            messages: messages,
            stream: options.stream || false,
            temperature: options.temperature || 0.7,
            ...options
        })
    });

    if (options.stream) {
        // 스트리밍 응답 처리
        const reader = response.body.getReader();
        const decoder = new TextDecoder();

        while (true) {
            const { done, value } = await reader.read();
            if (done) break;

            const chunk = decoder.decode(value);
            const lines = chunk.split('\n');

            for (const line of lines) {
                if (line.startsWith('data: ')) {
                    const data = line.slice(6);
                    if (data === '[DONE]') return;

                    try {
                        const parsed = JSON.parse(data);
                        const content = parsed.choices[0]?.delta?.content;
                        if (content) {
                            process.stdout.write(content);
                        }
                    } catch (e) {
                        // JSON 파싱 오류 무시
                    }
                }
            }
        }
        console.log(); // 새 줄
    } else {
        const result = await response.json();
        return result.choices[0].message.content;
    }
}

// 사용 예제
const messages = [
    { role: 'user', content: 'What is the meaning of life?' }
];

// 스트리밍
console.log('스트리밍 응답:');
await chatCompletion(messages, { stream: true });

// 비스트리밍
console.log('\n비스트리밍 응답:');
const response = await chatCompletion(messages);
console.log(response);

이 API 레퍼런스는 Continuum Router와 통합하기 위한 포괄적인 문서를 제공합니다. 라우터는 강력한 다중 백엔드 라우팅 및 관리 기능을 추가하면서 완전한 OpenAI API 호환성을 유지합니다.