문서

문서

채팅 완료

Kunavo의 /v1/chat/completions 엔드포인트는 Claude 및 GPT 계열에 OpenAI의 chat completions 프로토콜을 제공합니다. 스트리밍, 도구, JSON 출력은 동일한 SDK를 통해 사용할 수 있습니다. reasoning_effort의 기능은 계열에 따라 다르며, 이 페이지에서 각 계열의 동작을 설명합니다.

엔드포인트: POST /v1/chat/completions. 요청 및 응답 형식은 스트리밍과 선택적 tool_calls / reasoning_tokens 필드를 포함해 OpenAI의 chat completions API와 정확히 일치합니다.

기본 호출

resp = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[
        {"role": "system", "content": "You are a senior staff engineer."},
        {"role": "user", "content": "Pros and cons of postgres LISTEN/NOTIFY for a job queue?"},
    ],
    max_tokens=800,
)
print(resp.choices[0].message.content)

매개변수

표준 OpenAI 매개변수는 모두 사용할 수 있습니다. 일부는 특정 공급업체에서만 유효합니다. 변환기가 각 업스트림에서 지원하는 항목을 전달합니다.

매개변수유형참고
model문자열(필수)/v1/models에서 활성화된 아무 슬러그나 사용할 수 있습니다.
messages배열(필수)표준 OpenAI 메시지 형식입니다.
temperature0..2샘플링 온도. 기본값은 1입니다. 이 표에 나열된 모델에는 영향을 주지 않습니다.
top_p0..1누클리어스 샘플링. temperature와 동일한 예외가 적용됩니다.
max_tokensint출력 한도입니다. 둘 다 전송하면 max_completion_tokens가 우선합니다. GPT 모델에서는 추론 토큰도 이 한도에 포함됩니다. 아무것도 지정하지 않고 Claude를 요청하면 기본값은 4,096입니다.
streamboolSSE로 청크를 스트리밍합니다. 아래를 참조하세요.
toolsarray함수/도구 정의입니다. Claude와 GPT 모두 도구 사용을 지원합니다.
tool_choiceauto|none|named특정 도구를 강제로 사용하거나 모델이 결정하도록 합니다.
response_formatobjectJSON 출력입니다. Claude에서는 json_schema가 적용되고 json_object는 적용되지 않습니다. 모든 계열에 대한 설명은 JSON 출력을 참조하세요.
reasoning_effortstringGPT 모델 전용 — reasoning.effort로 전달됩니다. Claude에는 전달되지 않습니다. 추론을 참조하세요.
seedint지원되는 경우 결정론적 샘플링을 수행합니다.
stopstring|array강제 중지 시퀀스입니다.
Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7 및 Claude Sonnet 5 모델은 temperature, top_p 또는 top_k를 허용하지 않습니다. Kunavo는 해당 모델에 보내는 요청에서 이 세 항목을 제거하므로 공급업체의 400 오류를 사용자에게 전달하지 않습니다. 따라서 해당 모델에서는 이 세 항목이 적용되지 않습니다.

스트리밍

stream=True를 설정하세요. Kunavo는 OpenAI와 정확히 같은 형식으로 서버 전송 이벤트를 내보냅니다. 각 청크는 chat.completion.chunk이며 choices[0].delta.content를 포함합니다. 최종 사용량 페이로드는 data: [DONE]와 함께 도착합니다.

stream = client.chat.completions.create(
    model="claude-haiku-4-5",
    messages=[{"role": "user", "content": "Explain B-trees in one paragraph."}],
    stream=True,
)

for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)
모든 채팅 모델에서 스트리밍을 사용할 수 있습니다. Anthropic 프로토콜을 사용하는 업스트림인 Claude의 경우, Anthropic 이벤트 스트림을 OpenAI 델타로 실시간 변환하므로 SDK에서는 차이를 알 수 없습니다.

도구 / 함수 호출

공급업체 전반에서 도구 호출을 사용할 수 있습니다. 도구를 JSON 스키마로 정의하면 모델이 메시지에 tool_calls를 반환합니다. 이를 실행한 뒤 결과를 role: "tool" 메시지로 전달하세요.

tools = [{
    "type": "function",
    "function": {
        "name": "get_current_weather",
        "description": "Get current weather for a city",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string"},
                "unit": {"type": "string", "enum": ["c", "f"]},
            },
            "required": ["city"],
        },
    },
}]

resp = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
    tools=tools,
    tool_choice="auto",
)

# Inspect tool calls the model wants to make
for call in resp.choices[0].message.tool_calls or []:
    print(call.function.name, call.function.arguments)

JSON 출력(response_format)

response_format는 JSON을 요청합니다. 각 계열의 요청이 서로 다른 업스트림 메커니즘으로 변환되므로 보장 범위는 모델 계열에 따라 다릅니다:

제품군json_schemajson_object
Claude강제 적용됩니다. Anthropic의 구조화된 출력(output_config.format)으로 전송되며, 응답은 사용자의 스키마에 제한됩니다. 2026-09-24 기준 Kunavo에서 제공하는 모든 Claude 모델에서 확인되었습니다.강제 적용되지 않습니다. Anthropic에는 스키마 없는 JSON 모드가 없으므로 이 설정은 허용되지만 무시됩니다. 응답이 설명문이나 코드 펜스로 시작할 수 있습니다.
GPTResponses API의 text.format로 전달되지만 현재 업스트림은 모든 요청에 이를 적용하지 않습니다. 파싱하기 전에 유효성을 검사하세요.text.format로 전달됩니다.
import json

resp = client.chat.completions.create(
    model="claude-haiku-4-5",
    messages=[{"role": "user", "content": "Jane Doe <jane@example.com> wants the Pro plan."}],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "signup",
            "schema": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "email": {"type": "string"},
                    "plan": {"type": "string", "enum": ["free", "pro", "enterprise"]},
                },
                "required": ["name", "email", "plan"],
                "additionalProperties": False,
            },
        },
    },
)
signup = json.loads(resp.choices[0].message.content)  # constrained to the schema

Claude에서 알아둘 점 네 가지:

  • 스키마는 사용자가 작성한 형태에 가깝게 Anthropic으로 전송됩니다. Anthropic은 객체에 additionalProperties: false가 필요하므로 Kunavo는 속성이 나열된 모든 객체에 이를 추가하고, Pydantic의 model_json_schema()가 생성하는 것처럼 속성이 나열되지 않은 객체에서는 설정하지 않습니다. Anthropic이 여전히 거부하고 문제를 명시한 400 오류를 반환하는 경우는 열린 객체(additionalProperties가 false 이외의 값으로 설정되었거나, 나열된 속성이 없고 additionalProperties도 설정되지 않은 경우)와 oneOf입니다. anyOf를 사용하세요. 나머지는 Anthropic의 구조화된 출력 페이지에 나와 있습니다.
  • strict 및 name는 무시됩니다. Anthropic은 허용하는 모든 스키마를 엄격 모드 여부와 관계없이 강제 적용합니다.
  • 스키마는 마지막 assistant 메시지(프리필)와 함께 사용할 수 없습니다. Anthropic은 400 오류를 반환합니다.
  • max_tokens가 객체 중간에 끝나면 JSON이 잘리며, finish_reason는 "length"입니다.

비전 / 멀티모달 입력

vision 기능을 갖춘 모델은 이미지 콘텐츠 블록을 허용합니다. HTTPS URL 또는 data: base64 URI를 사용할 수 있습니다.

# Pass an image URL or a base64 data URI as part of a multimodal message
resp = client.chat.completions.create(
    model="claude-haiku-4-5",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "What's in this image?"},
            {"type": "image_url", "image_url": {
                "url": "https://example.com/cat.jpg"
            }},
        ],
    }],
)
print(resp.choices[0].message.content)

카탈로그의 비전 지원 모델에는 다음이 포함됩니다: Claude Opus 5.5. 나머지는 모델 목록을 참조하세요.

https 이미지의 경우, 일부 업스트림에서 이미지 URL만 전달하면 무시하기 때문에 Kunavo가 파일을 직접 다운로드해 모델에 인라인으로 전달합니다. 제한: 요청당 이미지 16개, 이미지당 5 MB, 전체 20 MB, 다운로드당 10초입니다. 가져올 수 없는 이미지가 있으면 건너뛰지 않고 해당 이미지 이름을 포함한 오류를 반환합니다.

추론

각 계열의 요청이 서로 다른 업스트림 API로 변환되므로 이 엔드포인트의 추론 제어 기능은 계열에 따라 다릅니다:

제품군reasoning_effort사용량의 추론 토큰
GPTResponses API의 reasoning.effort로 GPT-6 Astra, GPT-6 Sol, GPT-6 Luna, GPT-5.6 Sol, GPT-5.6 Terra 및 GPT-5.5에서 값을 그대로 전달합니다. 허용되는 값은 모델 자체가 정의하며, GPT-6 Sol 및 GPT-6 Luna에서는 none 값이 추론을 끄고 max 값이 최상위 설정입니다.completion_tokens에 포함되고 completion_tokens_details.reasoning_tokens로 별도 표시되며, 출력 요금으로 청구됩니다.
Claude전달되지 않습니다. Anthropic 요청은 고정된 필드 목록인 model, max_tokens, messages, stream, temperature, top_p, top_k, stop, tools, tool_choice, response_format을 사용해 구성됩니다. 따라서 여기서는 reasoning_effort, thinking 및 목록에 없는 모든 항목이 제거됩니다.별도 내역은 없습니다. Anthropic은 모든 사고 토큰을 output_tokens에 포함하며, 이는 completion_tokens에 보고됩니다.
# GPT models: reasoning_effort is forwarded as the Responses API's
# reasoning.effort. Reasoning tokens are part of completion_tokens.
resp = client.chat.completions.create(
    model="gpt-6-sol",
    messages=[{"role": "user", "content": "Plan a 3-week MLOps migration."}],
    reasoning_effort="high",
)
details = resp.usage.completion_tokens_details   # absent when no reasoning ran
print(details.reasoning_tokens if details else 0)
Claude의 확장 사고 기능은 네이티브 Messages API를 통해 사용하며, thinking가 번역 없이 Anthropic에 전달됩니다.

프롬프트 캐싱

긴 시스템 프롬프트, 참조 문서, 몇 개의 퓨샷 예시 — 안정적인 접두부라면 무엇이든 업스트림에 캐시한 뒤 이후 호출에서 입력 비용을 크게 낮춰 재사용할 수 있습니다. 캐시 적중은 사용량 객체에서 prompt_tokens_details.cached_tokens로 표시됩니다.

GPT 모델은 자동으로 캐시하므로 요청을 변경할 필요가 없습니다. cached_tokens는 prompt_tokens의 하위 항목이며, 캐시 읽기 할인 요율이 적용됩니다.

Claude는 cache_control 중단점까지만 캐시하며, 프롬프트가 길면 이 엔드포인트가 중단점을 대신 설정합니다. 설정 위치는 시스템 프롬프트, 도구 정의, 그리고 대화에 어시스턴트 턴이 포함되어 있으면 마지막 메시지입니다. 접두부를 직접 고르려면 아래와 같이 콘텐츠 블록에 cache_control을 지정하세요. Kunavo는 사용자가 넣은 중단점을 유지하고, 비워 둔 위치에만 자체 중단점을 추가합니다:

# Claude caches prefixes you mark with cache_control. Attach it to a content
# block; later calls reusing that prefix read it at ~10% of the input price.
resp = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[{
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": LONG_DOCUMENT,            # the stable, reused prefix
                "cache_control": {"type": "ephemeral"},
            },
            {"type": "text", "text": "Summarize the document above."},
        ],
    }],
)
print(resp.usage.prompt_tokens_details.cached_tokens)
시스템 프롬프트와 도구 정의 캐싱, 여러 중단점, 네이티브 cache_creation_input_tokens / cache_read_input_tokens 사용량 필드 등 Claude 프롬프트 캐싱을 완전히 제어하려면 네이티브 Messages API를 사용하세요. 이 엔드포인트도 시스템 프롬프트와 도구 정의를 캐시하고, 한 요청에 여러 중단점을 받으며, 캐시 쓰기는 cache_creation_input_tokens로, 캐시 읽기는 prompt_tokens_details.cached_tokens로 보고합니다. 네이티브 엔드포인트만 하는 일은 중단점을 추가하지 않고 본문을 그대로 전달하는 것입니다.

사용량 객체

모든 응답과 스트리밍의 마지막 청크에는 usage 객체가 포함됩니다:

필드의미
prompt_tokens청구된 입력 토큰 수 — 캐시된 토큰 포함.
prompt_tokens_details.cached_tokens캐시된 입력 토큰 수 — prompt_tokens의 하위 항목이며, 캐시 읽기 할인 요율이 적용됩니다.
completion_tokens청구한 출력 토큰입니다. GPT 모델에서는 추론 토큰이 포함되며, Claude에서는 Anthropic의 output_tokens입니다.
completion_tokens_details.reasoning_tokensGPT 모델의 경우 completion_tokens 중 추론에 사용된 토큰 수입니다. 값이 0이면 표시되지 않으며 Claude에서는 보고되지 않습니다.
total_tokensprompt_tokens + completion_tokens.

Ollama OpenAI 호환성 — /v1/chat/completions

Ollama는 http://localhost:11434/v1에서 OpenAI 호환 API를 통해 로컬 모델을 제공하며, 이 페이지에 설명된 것과 동일한 /chat/completions 계약을 구현합니다. 따라서 클라이언트에서는 서로 바꿔 사용할 수 있습니다. Ollama의 v1 API를 대상으로 작성한 코드는 기본 URL과 모델만 바꾸면 Kunavo에서도 실행됩니다.

from openai import OpenAI

# Before — Ollama's OpenAI-compatible API, local models
client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama",                       # ignored locally
)
resp = client.chat.completions.create(
    model="llama3.2",
    messages=[{"role": "user", "content": "Summarize this changelog."}],
)

# After — the same call against hosted frontier models.
# Two lines changed. Everything below them is untouched.
client = OpenAI(
    base_url="https://api.kunavo.com/v1",   # <- was localhost:11434/v1
    api_key=os.environ["KUNAVO_API_KEY"],
)
resp = client.chat.completions.create(
    model="claude-sonnet-5",  # <- was llama3.2
    messages=[{"role": "user", "content": "Summarize this changelog."}],
)

일반적으로 제공자를 바꿀 때 문제가 생기는 부분도 여기서는 와이어 형식이 같기 때문에 그대로 작동합니다:

기능Ollama v1Kunavo v1
엔드포인트 경로/v1/chat/completions/v1/chat/completions
스트리밍SSE, chat.completion.chunk동일 — 델타 형식도 동일
도구 호출tools / tool_callsClaude와 GPT에서 동일
비전 입력멀티모달 로컬 모델의 image_url 블록동일한 블록입니다. URL 또는 base64 데이터 URI
api_key자리표시자이며 무시됨실제 Kunavo 키
model다운로드한 태그(llama3.2)호스팅 슬러그(claude-sonnet-5)
usage 추가 항목토큰 수만 제공cached_tokens와 reasoning_tokens 추가
채팅 외 기능completions, embeddings이미지, 비디오, 오디오 엔드포인트도 포함
두 가지를 함께 사용하시나요? base_url, model, 키를 환경 변수에서 읽고 환경별로 전환하세요. 오프라인 반복 작업에는 로컬 모델을, 품질이 중요한 작업에는 호스팅 모델을 사용하면서 하나의 코드 경로를 유지할 수 있습니다. Ollama의 OpenAI 호환 인터페이스가 지원하는 기능과 지원하지 않는 기능을 포함한 전체 안내는 Ollama OpenAI 호환 API 가이드를 참조하세요.

Ollama의 OpenAI 호환 /v1/chat/completions 엔드포인트 공식 문서는 어디에 있나요?

Ollama는 자체 저장소의 docs/openai.md에서 OpenAI 호환 계층을 문서화하며, 이 문서가 로컬 서버에서 구현하는 OpenAI 필드를 확인할 수 있는 기준 자료입니다. 이 페이지는 Kunavo의 호스팅 /v1/chat/completions 엔드포인트에 해당하는 레퍼런스입니다. 위에서 필드별로 설명한 동일한 OpenAI chat completions 규약이므로 두 인터페이스를 직접 비교할 수 있습니다. 요약하면 요청 및 응답 형식은 동일합니다. Ollama는 로컬에서 가져온 모델을 대상으로 http://localhost:11434/v1에서 제공하고, Kunavo는 호스팅 Claude 및 GPT 모델을 대상으로 https://api.kunavo.com/v1에서 제공합니다.

Kunavo의 /v1/chat/completions는 Ollama의 OpenAI API와 호환되나요?

예 — 둘 다 동일한 OpenAI chat completions 규약을 구현하므로 Ollama의 http://localhost:11434/v1을 대상으로 작성한 클라이언트를 https://api.kunavo.com/v1에서 수정 없이 사용할 수 있습니다. 요청 필드(messages, temperature, max_tokens, stream, tools, tool_choice, response_format, stop, seed)와 응답 필드(choices[].message, 스트림의 choices[].delta, usage)가 일치합니다. 차이는 호스팅 모델에 따른 것입니다. api_key에는 플레이스홀더가 아닌 실제 키를 사용하고, model에는 llama3.2 같은 가져온 태그 대신 claude-sonnet-5 같은 호스팅 슬러그를 지정해야 합니다. usage에는 로컬 모델이 보고하지 않는 cached_tokens 및 reasoning_tokens가 포함됩니다.

Ollama 앱을 호스팅 Claude 또는 GPT로 어떻게 마이그레이션하나요?

두 줄을 변경하세요. base_url을 http://localhost:11434/v1에서 https://api.kunavo.com/v1로 바꾸고, model을 로컬 태그에서 호스팅 슬러그로 바꿉니다. Ollama가 무시하는 플레이스홀더 대신 유효한 Kunavo 키를 전달하세요. SSE 및 tool_calls 형식이 동일하므로 스트리밍, 도구 호출, 비전 코드 경로는 변경할 필요가 없습니다.

개발 환경에서는 Ollama를 사용하고 프로덕션에서는 호스팅 모델을 사용할 수 있나요?

예, 흔히 사용하는 구성입니다. base URL, 모델, 키를 환경 변수에서 읽고 환경에 따라 전환하세요. 양쪽 모두 동일한 OpenAI 프로토콜을 사용하므로 별도의 코드 경로를 유지할 필요가 없습니다. 오프라인 반복 작업에는 로컬 Llama 또는 Qwen을, 품질이 중요한 경우에는 호스팅 Claude 또는 GPT를 사용할 수 있습니다. 도구 정의와 스트리밍 처리기는 그대로 공유할 수 있습니다.

Kunavo는 Ollama 호환 인터페이스에 어떤 OpenAI 엔드포인트를 추가하나요?

Ollama의 OpenAI 호환 인터페이스는 /chat/completions, /completions, /embeddings 및 /models를 지원합니다. Kunavo는 동일한 키로 사용할 수 있는 미디어 엔드포인트를 추가합니다: /v1/images/generations, /v1/images/edits, /v1/video/generations, /v1/videos 및 /v1/audio/music. 또한 네이티브 Anthropic /v1/messages 엔드포인트에서 Claude를 제공합니다. 반대 방향의 유의 사항도 두 가지 있습니다. /v1/audio/speech, /v1/audio/transcriptions 및 /v1/embeddings는 와이어 형식으로 구현되어 있지만 현재 연결된 모델이 없어 지금은 성공하지 않습니다. 또한 Ollama와 달리 Kunavo는 모델을 로컬에서 실행하지 않습니다. 호출 가능한 항목은 언제나 GET /v1/models에서 확인할 수 있습니다.

다음 단계