본문으로 이동
My AI Console

API Docs

FlameBOX 연결부터 첫 API 호출까지.

Quickstart

FlameAI는 FlameBox(설치형 로컬 추론 머신)과 API Gateway를 조합해 동작합니다. 아래 6단계를 순서대로 따라가면 첫 API 호출까지 끝낼 수 있습니다.

1
FlameAI 계정을 만듭니다 (회원가입 또는 Google 로그인).
2
운영체제에 맞는 방법으로 FlameBox를 설치합니다(자세한 설치 옵션은 다운로드 페이지 참고).

Windows — PowerShell에서 실행 (또는 설치파일 .exe를 내려받아 실행)

irm https://flameai.im/install.ps1 | iex

Linux — 터미널에서 실행

curl -fsSL https://flameai.im/install.sh | sh
3
인증 화면으로 가는 경로는 운영체제에 따라 다릅니다.
  • Windows: FlameBox를 처음 실행하면 인증 화면이 바로 열립니다.
  • Linux: 터미널에서 flamebox up을 처음 실행하면 https://flameai.im/registration/{token} 형태의 인증 URL이 출력됩니다.
그 화면(또는 URL)에 접속해 로그인 후 "연결"을 누릅니다 — Linux는 여기서 flamebox up을 한 번 더 실행해야 등록이 완료되어 내 계정에 등록되고 My AI Console에 나타납니다.
4
이제 FlameBox가 홈페이지의 My AI Console에 연결되었습니다. FlameBox(/mypage/flamebox)를 클릭해 상세 페이지로 들어간 뒤, Models 탭에서 사용할 AI 모델을 내려받습니다.
5
같은 상세 페이지에서 Cortex 탭을 클릭하고 "Cortex 생성" 버튼을 눌러 추론 인스턴스(Cortex)를 생성합니다.
6
My AI Console(/mypage/settings)에서 API 경로/Secret Key를 확인하고, 나의 API 호출 주소 규칙대로 방금 만든 Cortex를 호출합니다.

구성 및 연결

외부 클라이언트의 요청이 실제 추론 결과로 돌아오기까지 거치는 경로는 다음과 같습니다.

[외부 클라이언트]
      │  HTTPS + Bearer(Secret Key)
      ▼
[API Gateway]  api-N.flameai.im  ← 로드밸런싱용 물리 노드 풀, API 경로로 계정 식별
      │  FlameBox로 연결 하여 요청 전달
      ▼
[FlameBox]  사용자 PC/서버에 설치된 추론 머신(Inference Machine)
      │  GPU/CPU 자원으로 다수의 Cortex(추론 인스턴스)를 관리
      ▼
[Cortex]    FlameBox 안에서 실행 중인 추론 인스턴스(Inference Instance, 모델 1개 상주)
  • 하나의 계정에 여러 FlameBox를 등록할 수 있습니다 — 각 Cortex는 자신이 생성된 FlameBox에만 속하므로, 그 FlameBox가 온라인 상태일 때만 호출할 수 있습니다.
  • FlameBox 연결이 끊기면 그 안의 Cortex 호출은 모두 실패합니다 — 다시 연결되면 자동으로 호출 가능한 상태로 돌아옵니다.

Inference Structure

FlameBox와 Cortex는 서로 다른 층의 개념입니다 — FlameBox는 추론 머신(Inference Machine), Cortex는 그 머신 위에서 실행되는 추론 인스턴스(Inference Instance)입니다.

구성요소역할
FlameBox
Inference Machine
PC/서버에 설치되는 프로그램 자체. FlameAI 서버와의 상시 연결 유지, 모델 다운로드/보관, 그 안에서 여러 Cortex를 띄우고 관리하는 역할을 합니다.
Cortex
Inference Instance
FlameBox 하나 위에서 실행되는 추론 인스턴스. 모델 파일을 GPU/CPU 메모리에 로드한 상태로 대기하며, API 호출을 받아 실제 추론을 수행합니다. 자세한 설명은 Inference API 섹션 참고.
FlameBox 하나에 여러 Cortex를 만들 수 있습니다 — 예를 들어 코딩용 모델 Cortex 하나, 일반 대화용 모델 Cortex 하나를 같은 FlameBox 위에서 동시에 운용할 수 있습니다(단, GPU/CPU/메모리 자원은 공유되므로 동시에 띄울 수 있는 개수는 하드웨어 사양에 따라 제한됩니다).

Available models

FlameBox가 다운로드해 Cortex로 띄울 수 있는 모델 목록과 각 모델의 사양은 모델 목록 페이지에서 확인할 수 있습니다.

FlameBox 상세 페이지의 "모델 다운로드" 모달은 그 FlameBox가 실제로 다운로드 가능한 모델 카탈로그를 실시간으로 보여줍니다 — 이 문서의 목록과 화면에 보이는 목록이 다르다면 화면 쪽이 최신입니다.

HTTP Endpoint 열기

FlameAI 에 가입하면 API 경로와 Secret Key가 계정당 자동으로 하나 발급됩니다 — 별도로 "발급 신청"을 할 필요가 없습니다.

1
My AI Console의 설정 메뉴로 들어갑니다.
2
Endpoint 박스에서 API 경로, base url, secret key 3가지를 확인합니다. Secret Key는 기본적으로 마스킹되어 있으며 "보기" 토글로 확인할 수 있습니다.
3
base url + API 경로를 이어붙이면 나의 API 호출 주소에서 쓰는 베이스 엔드포인트가 됩니다.
⚠ Secret Key가 유출됐다고 의심되면 같은 화면의 "변경" 버튼으로 즉시 재발급할 수 있습니다. 단, API 경로는 그대로 유지되고 기존 Secret Key로 호출하던 클라이언트는 재발급 즉시 인증에 실패하니 연동 중인 모든 클라이언트를 함께 갱신해야 합니다.

FlameBox 추가

운영체제에 맞는 방법으로 FlameBox를 설치합니다(자세한 설치 옵션은 다운로드 페이지 참고). 새 머신에 설치 후 아래 인증 과정을 거치면 그 머신의 FlameBox가 자동으로 계정에 추가됩니다 — 이 과정을 반복해 여러 대의 FlameBox를 등록할 수 있습니다.

Windows — PowerShell에서 실행 (또는 설치파일 .exe를 내려받아 실행)

irm https://flameai.im/install.ps1 | iex

Linux — 터미널에서 실행

curl -fsSL https://flameai.im/install.sh | sh
1
인증 화면으로 가는 경로는 운영체제에 따라 다릅니다 — Windows는 FlameBox를 처음 실행하면 인증 화면이 바로 열리고, Linux는 터미널에서 flamebox up을 처음 실행하면 https://flameai.im/registration/{token} 형태의 인증 URL이 출력됩니다.
2
그 화면(또는 URL)에서 Google 로그인을 누르거나, 이메일로 로그인한 뒤 "인증 및 연결" 버튼을 누릅니다 — 계정이 없다면 그 자리의 "회원가입" 링크로 바로 가입한 뒤 이어서 연결할 수 있습니다.
3
Linux는 여기서 flamebox up을 한 번 더 실행해야 등록이 완료됩니다. 등록이 끝나면 해당 FlameBox가 로그인한 계정에 등록되고, My AI Console의 FlameBox 목록에서 바로 확인할 수 있습니다.
계정당 최대 5개까지 FlameBox를 등록할 수 있습니다 — 그 이상 필요하시면 문의하기로 연락해 주세요.

Model 다운로드

모델은 계정 단위가 아니라 FlameBox 단위로 다운로드됩니다 — 같은 계정이라도 FlameBox마다 보유한 모델이 다를 수 있습니다.

1
My AI Console의 FlameBox 목록에서 대상 FlameBox 상세 페이지로 들어갑니다.
2
Models 탭을 클릭합니다.
3
"다운로드된 Models" 영역의 "모델 다운로드" 버튼을 눌러 카탈로그에서 원하는 모델을 선택합니다.
4
다운로드가 진행되는 동안 상태가 실시간(다운로드 중 → 검증 중 → 다운로드 완료)으로 갱신됩니다. 진행 중에도 일시정지/재개/취소가 가능합니다.
⚠ 모델 다운로드는 FlameBox가 온라인 상태로 연결되어 있어야 진행할 수 있습니다.
다운로드가 완료된 모델만 Cortex 생성 시 선택할 수 있습니다.

추론 인스턴스(Cortex) 생성

다운로드된 모델을 실제로 호출 가능한 상태로 띄우려면 Cortex를 생성해야 합니다.

1
FlameBox 상세 페이지에서 "Cortex 생성" 버튼을 누릅니다.
2
다운로드 완료된 모델 중 하나를 선택하고, Cortex 이름을 지정합니다.
3
생성이 끝나면 발급된 cortexId가 해당 FlameBox 상세 페이지(/mypage/flamebox)의 Cortex 탭에 나타납니다 — 이 값을 API 호출의 {cortexId} 자리에 사용합니다.
Cortex 탭에서 로드/추론중지/컨텍스트리셋/언로드/삭제 같은 제어 명령을 실행할 수 있습니다.

Cortex 구조와 특성

Cortex는 LLM 모델을 GPU/CPU 메모리에 로드하여 인스턴스화한 추론 실행 단위입니다. 모델 파일(.gguf)을 매 요청마다 다시 불러오지 않고 메모리에 상주시킨 상태로 대기하며, 요청이 들어오면 즉시 추론을 수행합니다. 이 구조 덕분에 다음과 같은 이점이 있습니다.

  • 즉시 응답 — 모델이 이미 메모리에 로드되어 있어, 요청 시점에 모델을 새로 불러오는 지연(콜드 스타트) 없이 바로 추론을 시작합니다.
  • 효율적인 멀티턴 대화 — KV Cache가 유지되므로 전체 대화 히스토리를 매번 다시 보낼 필요 없이 마지막 메시지만 전송해도 대화가 이어집니다(자세한 내용은 아래 "Stateful 동작 방식" 참고).
  • 대화가 길어져도 일정한 추론 속도 — Stateless 방식은 대화가 쌓일수록 매번 전체 히스토리를 다시 처리해야 해서 추론 시간도 함께 길어지지만, Cortex는 이전 턴의 KV Cache를 그대로 재사용해 새 메시지만큼만 처리하면 되므로 대화 길이와 무관하게 추론 속도가 일정하게 유지됩니다.
  • 용도별 독립 운용 — 하나의 FlameBox 안에 여러 Cortex를 동시에 띄워, 코딩용/일반 대화용처럼 목적에 맞는 모델을 나눠 운용할 수 있습니다.

다만 모델이 메모리에 상주하며 대화 컨텍스트를 유지하는 구조이다 보니, 다음과 같은 제약도 함께 따릅니다.

  • Cortex별 단일 스레드 추론 — 같은 Cortex 안에서는 GPU/CPU 자원을 독점적으로 사용하므로 동시 추론이 불가능합니다. 서로 다른 Cortex끼리는 자원이 허용하는 한 동시에 추론할 수 있습니다.
  • KV Cache 공유 불가 — 대화 컨텍스트는 하나의 점유자에게만 귀속됩니다.
  • 단일 점유 리소스 — 한 번에 하나의 클라이언트만 사용할 수 있습니다.
# 하나의 FlameBox에 여러 Cortex를 생성해 분산 운용할 수 있습니다
[Cortex Client]
      │  REST API
      ▼
[FlameBox]
      ├─ Cortex (7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a)  ← 모델 로드, KV Cache, 대화 컨텍스트 보유
      ├─ Cortex (a13d5e67-8f2b-4c91-b3d4-1e9f7a6c5b02)
      └─ Cortex (c48e2f91-3a7d-4b56-9c1e-8d2f6a4b7e03)

Stateful 동작 방식

Cortex는 내부에 KV Cache를 보유하며 Stateful 방식으로 동작합니다. 추론 완료 후에도 대화의 KV Cache가 메모리에 유지되므로, 다음 요청 시 이전 대화 전체를 다시 전송할 필요 없이 마지막 메시지만 전송해도 컨텍스트가 이어집니다.

# Stateless 방식 (일반적인 OpenAI 호환 서버)
1번 요청: [user: "안녕"]
2번 요청: [user: "안녕", assistant: "안녕하세요", user: "이름이 뭐야?"]  ← 전체 히스토리 재전송

# Stateful 방식 — FlameBox Cortex
1번 요청: [user: "안녕"]                  → KV Cache 유지
2번 요청: [user: "이름이 뭐야?"]           → 마지막 메시지만 전송
점유자가 바뀌어도 KV Cache는 자동으로 초기화되지 않습니다 — 컨텍스트를 비우는 /reset을 직접 호출해야 초기화됩니다. 새로 점유한 클라이언트가 이전과 무관한 새 대화를 시작하려면, 먼저 /reset으로 컨텍스트를 비운 뒤 대화를 시작하는 것을 권장합니다.

점유(Occupancy) 모델

클라이언트는 conversationId를 통해 Cortex를 선점하며, 점유 중인 Cortex에는 동일한 conversationId를 가진 클라이언트만 요청할 수 있습니다.

  • 적은 리소스로 멀티 대화 지원 — Cortex 하나만으로도 여러 conversationId를 필요에 따라 전환해가며 운용할 수 있어, 대화마다 별도 Cortex를 띄우지 않아도 됩니다(단, 전환 시 컨텍스트 재구축은 클라이언트가 대화 히스토리를 다시 전송하는 방식으로 직접 구현해야 합니다).
  • Cortex Pool 라우팅 키로 활용 — conversationId를 애플리케이션의 Cortex 배정 기준으로 사용하면, 여러 Cortex를 운용할 때 "이 대화가 어느 Cortex에 있는지"를 추적/관리하는 키로 쓸 수 있습니다.
  • 컨텍스트 오염 방지 — 점유 중인 Cortex에 다른 conversationId로 요청이 들어오면 즉시 cortex_occupied 에러로 차단되어, 서로 다른 대화의 메시지가 섞이는 문제를 막습니다.

점유 충돌 시 클라이언트 대응 전략

전략설명
재시도 대기현재 점유자가 해제할 때까지 기다린 후 재점유
강제 재점유/switch-conversation로 점유를 빼앗은 후 대화 히스토리로 컨텍스트 재구축
포기에러를 사용자에게 전달하고 다른 Cortex 탐색

일반적인 사용 흐름

1
GET /{my_base_path}/cortexes — 사용 가능한 Cortex 확인 (내 Cortex 목록 참고)
2
POST /{my_base_path}/cortex/{cortexId}/switch-conversation — conversationId로 Cortex 선점
3
POST /{my_base_path}/cortex/{cortexId}/reset — 새 대화이므로 컨텍스트를 비웁니다.
4
POST /{my_base_path}/cortex/{cortexId}/messages — 대화 히스토리 전체 + 새 메시지 전송 (SSE Stream)
5
GET /{my_base_path}/cortex/{cortexId}/status — 컨텍스트 사용량 모니터링
6
POST /{my_base_path}/cortex/{cortexId}/stop — 필요 시 추론 중단
7
POST /{my_base_path}/cortex/{cortexId}/switch-conversation — 다른 conversationId로 전환하거나 ""로 점유 해제

나의 API 호출 주소

FlameAI 에 가입하게 되면 나만의 API 호출을 위한 API 경로가 발급됩니다. 이 경로를 아래 형식의 URL에 넣어 API Gateway를 통해 호출합니다.

https://api-N.flameai.im/{my_base_path}/cortex/{cortexId}/{action}

예시: https://api-3.flameai.im/Nx7bQ2mZ/cortex/7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a/messages
  • api-N: 로드밸런싱용 물리 노드 식별자이며 API Gateway 노드의 이름입니다.
  • my_base_path(API 경로): My AI Console(/mypage/settings)에서 확인 가능한 나만의 고유 경로입니다.
  • 인증: Authorization: Bearer {Secret Key} 헤더 필수 (Secret Key도 /mypage/settings에서 확인)
  • 버전: X-API-Version 헤더로 지정(생략 시 기본값 1) — URL에는 버전을 넣지 않습니다.

인증 (Bearer Token)

API Gateway를 통해 호출할 때는 모든 요청에 Bearer Token을 포함해야 합니다.

POST /Nx7bQ2mZ/cortex/7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a/messages HTTP/1.1
Host: api-3.flameai.im
Content-Type: application/json
Authorization: Bearer fai_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
X-API-Version: 1
Secret Key는 FlameAI 회원 가입 후 My AI Console(/mypage/settings)에서 확인/재발급할 수 있습니다.

공통 요청 규칙

모든 요청에 다음 규칙이 공통으로 적용됩니다.

  • Body가 있는 요청(POST 등)은 Content-Type: application/json 헤더가 필수입니다.
  • Body는 UTF-8로 인코딩된 JSON이어야 합니다.
  • X-API-Version 헤더로 API 버전을 지정합니다(선택, 생략 시 기본값 1) — URL에는 버전을 넣지 않습니다.
  • 인증(Bearer Token) 방식은 위 "인증 (Bearer Token)" 섹션을 참고하세요.
Content-Type: application/json
X-API-Version: 1   (선택, 생략 시 기본값 1)

공통 응답 규칙

  • 성공 응답은 HTTP 200과 JSON 본문을 반환합니다.
  • 에러 응답은 HTTP 에러 상태 코드와 함께, 아래 "에러 응답 포맷"의 JSON을 반환합니다.

성공 응답

  • 일반(비스트리밍) 응답은 Content-Type: application/json으로 반환합니다.
  • SSE Stream 응답은 Content-Type: text/event-stream으로 반환합니다.
  • HTTP status가 200이면 정상 응답입니다. 응답이 JSON 포맷일 때는 JSON에 error 필드가 없으면 정상 응답으로 판단할 수 있습니다.

성공 응답 포맷 (비스트림)

Content-Type: application/json

{
  "cortexId":       "7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a",
  "conversationId": "chat-abc123",
  "message": {
    "id":      "msg-1714000000001",
    "role":    "assistant",
    "content": [
      { "type": "text", "text": "안녕하세요" }
    ],
    "usage": { "input_tokens": 12, "output_tokens": 2, "elapsed_ms": 80 }
  }
}

성공 응답 포맷 (스트림)

Content-Type: text/event-stream

event: message.completed
data: {"cortexId":"7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a","conversationId":"chat-abc123","message":{"id":"msg-1714000000001","role":"assistant","content":[{"type":"text","text":"안녕하세요"}],"usage":{"input_tokens":12,"output_tokens":2,"elapsed_ms":80}}}

data: [DONE]
스트림 응답의 전체 이벤트 시퀀스(message.created/message.delta/message.block_done/message.completed)는 대화 요청 엔드포인트 문서를 참고하세요.

에러 응답

  • 에러 응답은 항상 Content-Type: application/json으로 단일 패킷으로 반환합니다.
  • 응답 JSON에는 error 필드가 항상 포함되어 있습니다.
  • HTTP status는 항상 200이 아닌 값으로 반환됩니다.

에러 응답 포맷

{
  "error": {
    "code":       "에러코드",
    "message":    "상세 메시지",
    "httpStatus": 404
  }
}
HTTP상황
400bad request — 파라미터 오류, JSON 파싱 실패
401unauthorized — 인증 실패
403forbidden — 인증은 되었으나 리소스 접근 권한 없음
404not found — URL 또는 리소스를 찾을 수 없음
409conflict — 점유 충돌, 추론 중 등 상태 불일치
500internal error — 서버 내부 오류
503service unavailable — FlameBox가 오프라인이거나 통신할 수 없음

에러 코드

에러가 발생했다는 사실은 HTTP 상태 코드만으로도 알 수 있지만, 정확히 어떤 상황인지는 응답 Body에 담긴 에러 코드로 구분해야 합니다. 이 에러 코드는 문자열 형태이며, 아래와 같습니다.

에러는 발생 지점에 따라 두 종류로 나뉩니다 — API Gateway 자체에서 즉시 반환되는 에러와, 요청이 FlameBox까지 전달된 뒤 FlameBox가 반환하는 에러입니다.

API Gateway 에러 (FlameBox 도달 전)

코드HTTP상황
bad_request400URL 경로 형식 오류(허용되지 않는 문자 포함), JSON 형식 오류, 요청 본문 50MB 초과
bearer_not_found401Authorization 헤더 누락 또는 형식 오류
bearer_invalid401API 경로가 존재하지 않거나 Secret Key가 일치하지 않음
cortexbox_offline503대상 FlameBox가 오프라인 상태
flamebox_io_error503FlameBox와의 통신 오류

FlameBox 에러 (요청이 전달된 뒤 발생)

코드HTTP상황
bad_request400JSON 파싱 실패 또는 파라미터 오류
unsupported_cortex_type400Cortex 종류에 맞지 않는 요청 (예: 이미지 생성 Cortex에 messages, LLM Cortex에 imageGenerate, 판정 전용 Cortex에 messages)
cortex_not_found404없는 cortexId
file_not_found404Cortex 파일 저장소에 없는 파일
not_found404엔드포인트를 찾을 수 없음
cortex_occupied409다른 conversationId가 Cortex를 점유 중
cortex_not_running409모델이 로드되지 않은 상태에서 reset/tokenize 요청
cortex_inferring409해당 Cortex가 추론(생성) 중
internal_error500서버 내부 오류 (모델 로드 실패 포함)

대화 요청

POST/{my_base_path}/cortex/{cortexId}/messages

대화 메시지를 전송하고 AI 응답을 받습니다. SSE 스트리밍과 동기 방식을 모두 지원합니다.

Cortex가 언로드된 상태라면 이 요청을 받는 시점에 자동으로 다시 로드됩니다 — 로드가 끝날 때까지 응답이 잠시 지연될 수 있습니다.

Request Body

{
  "conversationId": "chat-550e8400",
  "tools": [],
  "options": {
    "stream":       true,
    "think":        1,
    "cortex_reset": false
  },
  "messages": [
    { "role": "system", "content": "당신은 유용한 AI 어시스턴트입니다." },
    { "role": "user",   "content": "3 더하기 3은?" }
  ]
}
파라미터타입필수설명
conversationIdstring예 구현자의 APP 내 대화 세션(Chat Session) ID를 그대로 사용해도 됩니다. 최초 대화 시 이 값으로 점유가 자동 발생하며, 이후 요청은 현재 점유 중인 conversationId와 일치해야 함
toolsarray아니오모델이 호출할 수 있는 도구(tool) 정의 배열. 실행은 클라이언트가 합니다 — 아래 "Tool 호출" 참고
options.streamboolean아니오true면 SSE 스트리밍, false면 동기 응답 (기본값: false)
options.thinkint아니오생각(thinking) 강도 — 0 즉답, 1 자동(기본값), 2 생각 강제. 모델마다 해석이 다릅니다(아래 표). false/true도 받으며 각각 0/1로 처리됩니다
options.cortex_resetboolean아니오true면 기존 컨텍스트를 버리고 이번 messages로 새로 구성한 뒤 추론합니다. 다른 conversationId가 점유 중이어도 이 요청의 conversationId로 점유가 넘어옵니다 (기본값: false)
options.apply_samplingboolean아니오true면 함께 보낸 생성 설정 값(temperature 등)을 적용하고 다음 요청에도 유지 — 아래 "생성 설정 바꾸기" 참고
messagesarray예 전달할 메시지 배열(1개 이상). 각 요소는 role과 content(문자열 또는 블록 배열)

messages의 role

role의미
system모델의 최상위 동작 규칙 (역할, 말투, 정책 등)
developer개발자가 넣는 앱/에이전트 지침
user사용자 입력. 파일 첨부(image/document 블록)와 도구 실행 결과(tool_result 블록)도 여기에 넣습니다
assistant모델의 이전 응답 (대화 히스토리 재전송, few-shot 예시)
tool도구 실행 결과를 문자열로 돌려줄 때

options.think 모델별 동작

모델01 (기본)2
Qwen 3 / Qwen 3.5생각 없이 즉답모델이 스스로 판단항상 생각한 뒤 답변
Gemma 4생각 끔생각 켬생각 켬 (1과 같음 — 켜고 끄기 두 단계뿐)
GPT-OSS얕게 생각보통깊게 생각 (생각을 아예 끌 수는 없음)
모델에 따라 think: 0이어도 thinking 블록이 올 수 있습니다. thinking 블록의 signature는 항상 빈 문자열입니다.

파일 첨부 — 이미지·문서

먼저 Cortex 파일 API로 파일을 올린 뒤, 응답의 file 값을 user 메시지의 content 배열에 블록으로 넣습니다. 블록은 놓인 순서대로 모델에 들어갑니다.

{ "role": "user", "content": [
    { "type": "image",    "source": { "type": "file", "file": "files/upload-20261016-101500-a1b2.jpg" } },
    { "type": "document", "source": { "type": "file", "file": "files/upload-20261016-101512-c3d4.txt" } },
    { "type": "text",     "text": "사진과 문서 내용을 비교해서 설명해줘" }
] }
블록규칙
image이미지를 이해하는 모델(비전 모델)의 Cortex에서만 사용할 수 있습니다 — 상태 보기의 capabilities.inputs에 "type": "image"가 있는지 확인하세요. PNG·JPEG만 가능(webp 불가), 요청당 최대 4장. 이미지 1장이 수백~천여 토큰을 차지하며 usage.input_tokens에 포함됩니다. 이미지는 대화 컨텍스트에 남아 다음 요청에서 "아까 사진에서…"처럼 이어 물을 수 있습니다(cortex_reset: true면 지워짐)
document텍스트 파일(txt/md/csv/json, UTF-8, 최대 256KB). 본문이 그 자리에 텍스트로 들어가며, 컨텍스트를 그만큼 차지합니다
파일은 반드시 먼저 업로드해서 "source": { "type": "file" }로 가리켜야 합니다 — base64·URL 방식은 지원하지 않습니다. 텍스트에 <__media__> 문자열을 직접 쓰면 bad_request가 됩니다.

생성 설정 바꾸기 (apply_sampling)

options에 "apply_sampling": true와 바꿀 값을 함께 보내면 이번 요청부터 적용되고 다음 요청에도 유지됩니다. 대화 내용은 그대로 이어집니다.

{ "conversationId": "chat-abc123",
  "options": { "stream": true, "apply_sampling": true, "temperature": 0.3, "top_p": 0.9, "max_tokens": 1024 },
  "messages": [ { "role": "user", "content": "조금 더 정확하게 다시 설명해줘" } ] }
키범위설명
temperature0 ~ 20이면 항상 가장 확률 높은 토큰
top_p0 ~ 11이면 끔
top_k0 ~0이면 끔
min_p0 ~ 10이면 끔
seed-1 ~ 4294967294-1이면 무작위
repeat_penalty1.0 ~ 2.01.0이면 끔
max_tokens1 ~ 컨텍스트 크기응답 최대 토큰 수
  • apply_sampling이 없거나 false면 위 값을 보내도 무시됩니다.
  • 보낸 키만 바뀌고, 빠진 키는 마지막으로 적용한 값을 유지합니다.
  • cortex_reset: true, conversationId 변경, 모델 언로드 때 Cortex 기본 설정으로 돌아갑니다.
  • 지금 적용 중인 값은 응답 usage.sampling과 상태 보기의 sampling으로 확인합니다.
  • 고정 seed로 같은 결과를 재현하려면 요청마다 apply_sampling: true와 seed를 다시 보냅니다.
  • 범위를 벗어나면 bad_request(400)이고 아무 값도 바뀌지 않습니다.

Tool 호출

모델이 도구를 쓰기로 하면 응답 content에 tool_use 블록이 옵니다. 클라이언트가 그 도구를 실행한 뒤, 결과를 tool_result 블록으로 다시 보내면 모델이 이어서 답합니다.

# 1) 도구 정의와 함께 요청
{ "conversationId": "chat-001",
  "tools": [ { "name": "bash", "description": "Execute a bash command.",
               "parameters": { "type": "object", "properties": { "cmd": { "type": "string" } }, "required": ["cmd"] } } ],
  "messages": [ { "role": "user", "content": "현재 디렉터리 파일 목록 보여줘." } ] }

# 2) 응답 — tool_use 블록
"content": [ { "type": "tool_use", "id": "call_001", "raw": "<모델이 출력한 tool call 원문>" } ]

# 3) 실행 결과를 tool_result 블록으로 전송
{ "conversationId": "chat-001",
  "messages": [ { "role": "user", "content": [
      { "type": "tool_result", "tool_use_id": "call_001", "content": "total 48\ndrwxr-xr-x ..." } ] } ] }

# 4) 응답 — 최종 text 블록
  • raw에는 모델이 출력한 도구 호출 원문이 그대로 담깁니다. 형식은 모델마다 다르므로(예: Qwen 3은 JSON, Qwen 3.5는 XML) 클라이언트가 직접 파싱합니다.
  • tool_result의 tool_use_id에는 받은 tool_use.id 값을 넣어야 짝이 맞습니다.
  • Cortex가 대화를 기억하므로, 같은 conversationId라면 3단계에서 앞의 대화를 다시 보내지 않아도 됩니다.

Response — stream: false

{
  "cortexId":       "7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a",
  "conversationId": "chat-abc123",
  "message": {
    "id":   "msg-1714000000001",
    "role": "assistant",
    "content": [
      { "type": "thinking", "thinking": "3 더하기 3을 계산해보면 6이다.", "signature": "" },
      { "type": "text",     "text": "6입니다." }
    ],
    "usage": {
      "input_tokens": 42, "output_tokens": 10, "elapsed_ms": 320, "prefill_ms": 85,
      "ctx_used": 52, "ctx_size": 10000, "stop_reason": "eot"
    }
  }
}
필드설명
content블록 배열 — thinking(생각 과정) → text(답변) → tool_use(도구 호출) 순
usage.input_tokens이번 요청의 입력 토큰 수
usage.output_tokens생성한 토큰 수 (모든 블록 합계)
usage.prefill_ms입력(프롬프트)을 처리하는 데 걸린 시간(ms)
usage.elapsed_ms입력 처리 후 생성이 끝나기까지 걸린 시간(ms) — prefill_ms는 포함하지 않음
usage.ctx_used생성이 끝난 시점에 컨텍스트에 쌓인 토큰 수 (대화를 이어가면 누적)
usage.ctx_size컨텍스트 최대 토큰 수
usage.stop_reason끝난 이유 — eot 정상 종료, n_predict 최대 생성 길이 도달, hardcap 서버 안전 상한(8192 토큰) 도달, abort 중지 요청, decode_error 생성 중 오류
usage.sampling이번 생성에 적용된 생성 설정 값 (temperature 등)

SSE Stream 응답 포맷

Content-Type: text/event-stream

event: message.created
data: {"cortexId":"7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a","conversationId":"chat-abc123","message_id":"msg-1714000000001"}

event: message.delta
data: {"type":"text","delta_index":0,"delta":"안녕"}

event: message.delta
data: {"type":"text","delta_index":1,"delta":"하세요"}

event: message.block_done
data: {"type":"text","token_count":2,"elapsed_ms":80}

event: message.completed
data: {"cortexId":"7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a","conversationId":"chat-abc123","message":{"id":"msg-1714000000001","role":"assistant","content":[{"type":"text","text":"안녕하세요"}],"usage":{"input_tokens":12,"output_tokens":2,"elapsed_ms":80}}}

data: [DONE]
이벤트설명
message.created스트림 시작 (1회)
message.deltathinking/text 블록의 텍스트 조각 (여러 번). delta_index는 스트림 전체의 조각 순번
message.block_done블록 하나 완료 (블록마다 1회). tool_use 블록은 delta 없이 이 이벤트로만 오며 id, raw가 함께 옵니다
message.completed전체 완료 — 완성된 message 객체 포함 (1회)
data: [DONE]스트림 종료 표시 (JSON 아님)
event: message.block_done
data: {"type":"tool_use","id":"call_001","raw":"<모델이 출력한 tool call 원문>","token_count":12,"elapsed_ms":150}
message.completed 이벤트의 data: 한 줄에 완성된 message 객체(content 블록 전체 + usage)가 이미 다 들어있습니다 — 델타를 직접 누적하지 않고 이 마지막 이벤트만 파싱해도 됩니다.

Errors

코드HTTP상황
bad_request400messages/conversationId 누락, 생성 설정 값이 범위를 벗어남, image 블록 규칙 위반(이미지를 받지 않는 Cortex, PNG/JPEG 아님, 장수 초과, 컨텍스트 초과 등)
unsupported_cortex_type400LLM이 아닌 Cortex(이미지 생성·판정 전용)에 요청
cortex_not_found404없는 cortexId
file_not_found404image/document 블록이 가리키는 파일이 없음
cortex_occupied409다른 conversationId가 점유 중 (cortex_reset: false)
cortex_inferring409이미 추론 중
internal_error500모델 로드 실패 등 서버 내부 오류

상태 보기

GET/{my_base_path}/cortex/{cortexId}/status

Cortex의 현재 점유 상태와 Context 토큰 사용량을 반환합니다. 추론 중에도 조회 가능합니다.

Response — 200 OK

{
  "cortexId":            "b47778cd-24d9-4912-830c-6745e1253cc5",
  "status":              "idle",
  "conversationId":      "conv_mtwfir2fyi0o",
  "last_response_id":    "msg-1789099310429",
  "capabilities":        { "api": "messages", "outputs": ["text"],
                           "inputs": [ { "type": "image", "max": 4, "mime": ["image/png", "image/jpeg"] } ] },
  "sampling":            { "temperature": 0.7, "top_p": 0.9, "top_k": 40, "min_p": 0.05, "seed": -1, "repeat_penalty": 1.0, "max_tokens": 2048 },
  "context_size":        4096,
  "context_used":        621,
  "context_remain":      3475,
  "context_used_pct":    15,
  "kv_cache_bytes":      91578517,
  "totalOutputTokens":   722,
  "sessionOutputTokens": 722,
  "currentOutputTokens": 722,
  "lastOutputTokens":    722
}
필드타입설명
statusstringidle | busy(추론 진행/중단 처리 중)
conversationIdstring|null현재 점유 중인 conversationId. 점유자가 없으면 null — idle/busy 여부와 무관하게 유지됨(점유는 별도 상태)
last_response_idstring|null가장 최근에 완료된 응답의 ID. 아직 없으면 null
capabilitiesobject이 Cortex가 쓰는 API와 받을 수 있는 파일 — 아래 표 참고. 모델이 로드되지 않아도 정확한 값이 옵니다
samplingobject(LLM, 모델이 로드된 경우) 현재 적용 중인 생성 설정. 대화 요청의 apply_sampling으로 바꾼 값 포함
context_sizeint모델 최대 컨텍스트 토큰 수 (모델이 로드되지 않았으면 0)
context_usedint현재 KV Cache에 사용된 토큰 수
context_remainint남은 컨텍스트 토큰 수
context_used_pctint컨텍스트 사용 비율(%)
kv_cache_bytesintKV Cache가 차지하는 메모리 크기(byte)
totalOutputTokensint세션(모델 로드) 이후 누적 생성된 전체 출력 토큰 수
sessionOutputTokensint마지막 /reset 이후 누적 생성된 출력 토큰 수
currentOutputTokensint가장 최근 생성의 출력 토큰 수 — 진행 중이면 실시간으로 증가하고, 완료 후에는 다음 생성이 시작되기 전까지 그 값을 유지
lastOutputTokensint가장 최근에 완료된 생성의 출력 토큰 수

capabilities

Cortex마다 어떤 API로 호출하는지, 어떤 파일을 첨부할 수 있는지 알려줍니다. 화면에서 첨부 버튼을 보여줄지 정할 때 이 값을 쓰면 됩니다.

필드설명
api생성에 쓰는 API — messages(LLM) | choice(판정 전용 모델) | imageGenerate(이미지 생성)
outputs결과 종류 — text | choice | image
inputs텍스트 외에 첨부할 수 있는 파일 목록. 비어 있으면 파일 첨부 불가
inputs[].type파일 종류 — 현재 image
inputs[].role(이미지 생성만) reference = ref_images로 넣는 참조 이미지
inputs[].max요청 하나에 넣을 수 있는 최대 개수
inputs[].mime받는 파일 형식 (업로드 Content-Type과 같은 값)
// LLM (비전 모델) — messages 에 이미지 첨부 가능
{ "api": "messages", "outputs": ["text"], "inputs": [ { "type": "image", "max": 4, "mime": ["image/png", "image/jpeg"] } ] }
// LLM (텍스트 전용)
{ "api": "messages", "outputs": ["text"], "inputs": [] }
// 판정 전용 모델
{ "api": "choice", "outputs": ["choice"], "inputs": [] }
// 이미지 생성 (편집 가능)
{ "api": "imageGenerate", "outputs": ["image"],
  "inputs": [ { "type": "image", "role": "reference", "max": 4, "mime": ["image/png", "image/jpeg", "image/webp"] } ] }

Errors

코드HTTP상황
cortex_not_found404없는 cortexId

추론 중지

POST/{my_base_path}/cortex/{cortexId}/stop

진행 중인 추론(대화 생성, 이미지 생성)을 즉시 중단합니다. 추론 중이면 1초 이내에 중단되고 SSE Stream이 종료됩니다. 점유 중인 conversationId와 달라도 중단할 수 있습니다.

Request Body

{ "conversationId": "chat-550e8400" }   // 생략 가능

Response — 200 OK

{
  "ok":       true,
  "cortexId": "7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a",
  "message":  "inference stopped"
}
추론 중이 아니었다면 아무것도 바꾸지 않고 "message": "already stopped"로 성공 응답합니다 — 여러 번 호출해도 안전합니다.

Errors

코드HTTP상황
cortex_not_found404없는 cortexId

모델 언로드

POST/{my_base_path}/cortex/{cortexId}/unload

로드된 모델을 메모리에서 내려 GPU/메모리를 비웁니다. Cortex 자체는 남아 있으며, 다음 messages/choice/imageGenerate 요청 때 자동으로 다시 로드됩니다. Body는 필요하지 않습니다.

Response — 200 OK

{
  "ok":       true,
  "cortexId": "7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a",
  "message":  "unloaded"
}
이미 언로드된 상태에서 다시 호출해도 에러 없이 "message": "already unloaded"로 성공 처리됩니다(idempotent). 추론 중이었다면 먼저 중단시키고, 추론이 실제로 끝날 때까지 최대 5초 기다린 뒤 언로드합니다.

Errors

코드HTTP상황
cortex_not_found404없는 cortexId
cortex_inferring409중단을 요청했지만 5초 안에 추론이 끝나지 않음 — 언로드하지 않았으니 잠시 후 다시 시도

컨텍스트 초기화

POST/{my_base_path}/cortex/{cortexId}/reset

Cortex의 KV Cache(대화 컨텍스트)를 초기화합니다. 이후 요청 시 대화 히스토리 전체를 다시 전송해야 합니다. Body는 필요하지 않습니다.

Response — 200 OK

{
  "ok":       true,
  "cortexId": "7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a",
  "message":  "context reset"
}

Errors

코드HTTP상황
cortex_not_found404없는 cortexId
unsupported_cortex_type400LLM이 아닌 Cortex(이미지 생성·판정 전용)에 요청
cortex_not_running409모델이 로드되지 않음
cortex_inferring409추론 중

대화 세션 전환

POST/{my_base_path}/cortex/{cortexId}/switch-conversation

대화 세션(conversationId)으로 Cortex를 선점합니다. 이미 다른 클라이언트가 점유 중인 Cortex를 강제로 빼앗거나, 점유를 해제하는 데도 사용합니다.

⚠ /switch-conversation는 점유 전환을 허용합니다. 점유 중 다른 클라이언트의 탈취를 방지하려면 상위 레이어(API 프록시 등)에서 접근 제어를 수행해야 합니다.

동작 규칙

상황동작
Cortex가 idle 상태conversationId를 등록하고 즉시 점유 성공
동일한 conversationId로 재요청점유 유지 (no-op)
다른 conversationId로 요청기존 점유를 해제하고 새 conversationId로 전환 (강제 탈취)
conversationId를 ""로 요청점유 해제 (idle 상태로 전환)

Request Body

{
  "conversationId": "chat-550e8400"  // 빈 문자열 ""이면 점유 해제
}

Response — 200 OK

{
  "ok":      true,
  "message": "conversationId changed to chat-550e8400"
}

Errors

코드HTTP상황
bad_request400JSON 파싱 실패
unsupported_cortex_type400LLM이 아닌 Cortex(이미지 생성·판정 전용)에 요청
cortex_not_found404없는 cortexId

선택지 판정

POST/{my_base_path}/cortex/{cortexId}/choice

주어진 선택지(choices) 중 query에 가장 맞는 것을 판정합니다. 텍스트를 생성하지 않고 한 번의 계산으로 끝나서 빠르며, 결과를 선택지별 확률로 돌려줍니다. 문의 분류, 의도 파악, 정책 위반 판정처럼 "정해진 보기 중 하나를 고르는" 작업에 씁니다.

  • 일반 LLM Cortex와 판정 전용 모델(예: Laya) Cortex 모두 같은 요청 형식을 씁니다. cortexId만 바꾸면 두 방식을 비교할 수 있습니다 — 응답의 method가 llm_label(LLM) 또는 laya(판정 전용 모델)로 옵니다.
  • conversationId(점유)를 확인하지도 바꾸지도 않으며, LLM Cortex에서 진행 중인 대화 컨텍스트에도 영향을 주지 않습니다. 언로드된 Cortex는 자동으로 로드됩니다.

Request Body

{
  "instruction": "다음 고객 문의의 유형을 고르세요.",
  "query": "어제 주문한 상품을 취소하고 돈을 돌려받고 싶습니다.",
  "choices": ["환불", "배송조회", "단순문의", "스팸"],
  "temperature": 1.0,
  "debias": false
}
파라미터타입필수설명
instructionstring아니오판정 질문. 생략하거나 빈 문자열이면 "Choose the option that best fits the query."
querystring | object | array예판단 대상. 문자열이 아니면 JSON 텍스트로 넣습니다. 업로드한 텍스트 파일을 document 블록(또는 text/document 블록 배열)으로 줄 수도 있습니다 — image 블록은 지원하지 않음
choicesstring[]예선택지. LLM Cortex는 2 ~ 26개, 판정 전용 모델은 2 ~ 255개. 빈 문자열/중복 불가
temperaturenumber아니오확률 분포 온도, 0보다 커야 함. LLM Cortex 기본값 1.0, 판정 전용 모델은 생략 시 모델에 내장된 보정 온도 사용(생략 권장)
debiasbool아니오LLM Cortex 전용 — 선택지 순서를 뒤집어 한 번 더 계산해 평균(위치 편향 보정, 비용 2배). 기본 false. 판정 전용 모델은 무시

Response — 200 OK

{
  "cortexId":    "7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a",
  "method":      "llm_label",
  "best_choice": "환불",
  "confidence":  0.9845,
  "probabilities": { "환불": 0.9845, "배송조회": 0.0112, "단순문의": 0.0041, "스팸": 0.0002 },
  "usage": { "input_tokens": 98, "elapsed_ms": 41, "passes": 1 }
}
필드설명
method계산 방식 — llm_label(LLM Cortex) 또는 laya(판정 전용 모델)
best_choice확률이 가장 높은 선택지 (동률이면 앞의 것)
confidencebest_choice의 확률 (0 ~ 1)
probabilities선택지 → 확률 (요청 choices 순서 유지, 합계 1)
truncated판정 전용 모델만 — 질문/선택지가 길어 모델 입력 한도에 맞춰 잘렸으면 true
usage.input_tokens평가한 입력 토큰 수 (debias면 두 번의 합)
usage.elapsed_ms판정 소요 시간(ms)
usage.passes계산 횟수 (1, debias면 2)

Errors

코드HTTP상황
bad_request400JSON 오류, query/choices 누락, 선택지 개수 위반, 빈/중복 선택지, instruction이 문자열이 아님, temperature <= 0, debias가 bool이 아님
unsupported_cortex_type400이미지 생성 Cortex에 요청
cortex_not_found404없는 cortexId
cortex_inferring409이미 추론/판정 중
internal_error500모델 로드 실패, 입력이 모델 한도 초과 등
판정 전용 모델 Cortex는 /choice만 처리합니다 — messages, switch-conversation, reset은 unsupported_cortex_type(400)으로 거절됩니다.

이미지 생성

POST/{my_base_path}/cortex/{cortexId}/imageGenerate

이미지 생성 모델(예: Qwen Image, FLUX) Cortex로 이미지를 만들거나 편집합니다. 생성된 이미지는 그 Cortex의 파일 저장소에 저장되고, 응답의 files에 files/gen-….png 형태로 옵니다. 이 값을 /{my_base_path}/cortex/{cortexId}/ 뒤에 붙이면 다운로드 주소가 됩니다(아래 "Cortex 파일" 참고).

Request Body

{
  "prompt": "a lovely cat holding a sign says 'flamebox'",
  "negative_prompt": "blurry",
  "width": 1024, "height": 1024,
  "steps": 20, "cfg_scale": 6.0, "seed": -1,
  "sampler": "euler", "count": 1, "stream": false
}
파라미터필수설명
prompt예그릴 내용
negative_prompt아니오피하고 싶은 내용
width, height아니오이미지 크기 — 모델이 정한 배수(Qwen Image 2.1은 32의 배수). 생략 시 모델/Cortex 기본값
steps, cfg_scale, sampler, scheduler, count아니오생략 시 기본값. 최댓값은 Cortex 설정(limits)을 넘을 수 없음
seed아니오-1이면 무작위 (응답에 실제 사용한 seed가 옴 — 같은 결과를 다시 얻을 때 사용)
ref_images아니오편집용 참조 이미지 배열 — "files/<이름>" 문자열 또는 image 블록. 먼저 "Cortex 파일" API로 업로드합니다. 아래 "이미지 편집" 참고
stream아니오true면 SSE로 진행률을 받음. 기본 false

모르는 파라미터를 보내면 bad_request(400)입니다.

Response — stream: false (생성이 끝나면 응답)

{
  "cortexId": "7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a",
  "files": ["files/gen-20261006-195252-3294.png"],
  "seed": 7, "width": 1024, "height": 1024, "steps": 20,
  "elapsed_ms": 78000, "method": "sd.cpp"
}

생성 중에 /stop으로 중지되면 { "cortexId": "…", "status": "cancelled" }가 옵니다.

Response — stream: true (SSE, 마지막 이벤트가 result / error / cancelled)

event: generation.queued      data: {"cortexId": "..."}                       (다른 생성이 진행 중일 때만)
event: generation.progress    data: {"cortexId": "...", "step": 3, "steps": 20, "elapsed_ms": 4100}
event: generation.result      data: {"cortexId": "...", "files": ["files/gen-….png"], "seed": 12345, ...}
이미지 생성은 수십 초 이상 걸릴 수 있습니다(해상도·steps·PC 성능에 따라 다름). 진행률을 보여주려면 stream: true를 권장합니다. 한 PC에서 이미지 생성은 한 번에 하나씩 처리되며, 대기 중인 요청은 generation.queued를 먼저 받습니다.

이미지 편집 — 참조 이미지(ref_images)

업로드한 사진이나 앞 생성 결과를 ref_images로 주고, prompt에 바꿀 내용을 적으면 그 이미지를 고친 결과를 만듭니다.

{
  "prompt": "Change only the background to a snowy mountain. Keep the same man, face, clothes and pose.",
  "ref_images": ["files/upload-20261016-101500-a1b2.jpg"],
  "width": 832, "height": 1248, "seed": 42
}
항목규칙
사용 가능한 Cortex상태 보기의 capabilities.inputs에 { "type": "image", "role": "reference" }가 있는 Cortex만. 없으면 bad_request(400)
형식PNG, JPEG, webp
여러 장배열 순서대로 모델에 들어갑니다(최대 4장). 프롬프트에서 역할을 지정하세요 — 예: "Use the face of the man in the first image and put him into the scene of the second image"
연속 편집응답의 files/gen-….png를 다음 요청의 ref_images로 넣습니다. 이미지 모델은 이전 요청을 기억하지 않으므로 매번 참조 이미지와 바꿀 내용을 함께 보냅니다. 편집을 거듭할수록 화질이 조금씩 흐려지므로 원본 사진을 함께 넣으면(2장) 인물 유지에 도움이 됩니다
출력 크기width/height를 생략하면 Cortex 기본 크기로 나와 원본과 비율이 달라질 수 있습니다 — 참조 이미지 비율에 맞춘 크기(모델 배수)를 주는 것을 권장합니다(예: 540×810 → 832×1248)
프롬프트바꿀 것은 Change only …, 유지할 것은 Keep the same …으로 함께 적으면 바뀌는 범위가 좁아집니다

Errors

코드HTTP상황
bad_request400입력 오류(필수값 누락, 크기 배수 위반, 상한 초과, 모르는 파라미터, 참조 이미지를 받지 않는 Cortex, 장수 초과, 읽을 수 없는 이미지 등)
unsupported_cortex_type400이미지 생성 Cortex가 아님
file_not_found404ref_images에 없는 파일 이름
cortex_inferring409이미 생성 중
internal_error500모델 로드 실패 등

Cortex 파일

Cortex마다 파일 저장소가 있습니다. 생성 결과(gen-…)를 내려받거나, 생성에 쓸 입력 파일(예: 편집용 참조 이미지)을 올립니다. 모델 종류나 로드 여부와 상관없이 모든 Cortex에서 동작합니다.

메서드경로설명
POST/{my_base_path}/cortex/{cortexId}/files업로드 — Body는 파일 바이트 그대로, Content-Type으로 형식 지정(최대 50MB). 응답 { "cortexId", "file": "files/upload-….png", "size", "mime" }
GET/{my_base_path}/cortex/{cortexId}/files목록 — { "cortexId", "files": [ { "name", "size", "mime", "createdAt" } ] } (이름순)
GET/{my_base_path}/cortex/{cortexId}/files/{name}다운로드 — 파일 바이트 그대로(Content-Type = 파일 형식)
POST/{my_base_path}/cortex/{cortexId}/files/{name}다운로드 — GET과 같음
DELETE/{my_base_path}/cortex/{cortexId}/files/{name}삭제 — { "ok": true, "cortexId", "file" }
  • 업로드 파일 이름은 서버가 정합니다: upload-<yyyyMMdd-HHmmss>-<hex>.<ext>. 생성 결과는 gen-…입니다.
  • API가 주고받는 파일은 files/<이름> 형식입니다. 이 값을 그대로 대화 요청의 image/document 블록, 이미지 생성의 ref_images에 넣습니다(<이름>만 써도 됩니다).
  • 허용 형식(Content-Type): image/png, image/jpeg, image/webp, audio/wav, video/webm, video/mp4, text/plain, application/json — 그 외는 bad_request(400). 단, 대화 요청의 image 블록은 PNG/JPEG만 받습니다.
  • 파일 이름 규칙: 영문·숫자·.·_·-만, 128자 이하, .으로 시작하거나 .. 포함 불가.
  • 다운로드는 Authorization 헤더가 필요하므로, 브라우저 <img src>에 주소를 바로 넣을 수는 없습니다 — 서버에서 받아 전달하거나 Blob으로 받아서 표시하세요.

Errors

코드HTTP상황
bad_request400허용되지 않는 형식, 파일 이름 규칙 위반, 50MB 초과
file_not_found404없는 파일
cortex_not_found404없는 cortexId
# 이미지 생성 → 결과 다운로드 → 삭제
curl -s -X POST https://api-3.flameai.im/Nx7bQ2mZ/cortex/{cortexId}/imageGenerate \
  -H "Authorization: Bearer YOUR_SECRET_KEY" -H "Content-Type: application/json" \
  -d '{ "prompt": "a lovely cat holding a sign says flamebox", "width": 1024, "height": 1024 }'

curl -s https://api-3.flameai.im/Nx7bQ2mZ/cortex/{cortexId}/files/gen-20261006-195252-3294.png \
  -H "Authorization: Bearer YOUR_SECRET_KEY" -o result.png

curl -s -X DELETE https://api-3.flameai.im/Nx7bQ2mZ/cortex/{cortexId}/files/gen-20261006-195252-3294.png \
  -H "Authorization: Bearer YOUR_SECRET_KEY"

# 편집용 참조 이미지 업로드
curl -s -X POST https://api-3.flameai.im/Nx7bQ2mZ/cortex/{cortexId}/files \
  -H "Authorization: Bearer YOUR_SECRET_KEY" -H "Content-Type: image/png" --data-binary @input.png

토큰 세기

POST/{my_base_path}/cortex/{cortexId}/tokenize

문자열을 이 Cortex 모델의 토크나이저로 나눠 토큰 id 배열과 토큰 수를 돌려줍니다. 토큰 수는 모델마다 다르므로, 보낼 프롬프트가 컨텍스트에 들어가는지 미리 확인할 때 씁니다. LLM과 판정 전용 모델 Cortex에서 쓸 수 있습니다.

Request Body

{
  "text": "안녕하세요. 오늘 날씨가 좋네요.",
  "options": { "autoLoad": false }
}
파라미터타입필수설명
textstring예 토큰화할 문자열
options.autoLoadboolean아니오true면 모델이 로드되지 않은 경우 먼저 로드한 뒤 토큰화합니다. 기본값 false

Response — 200 OK

{
  "cortexId": "7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a",
  "tokens":   [148924, 154982, 88005, 13],
  "count":    4
}

Errors

코드HTTP상황
bad_request400text 누락 또는 JSON 파싱 실패
unsupported_cortex_type400이미지 생성 Cortex에 요청
cortex_not_found404없는 cortexId
cortex_not_running409모델이 로드되지 않았고 options.autoLoad가 false
internal_error500모델 로드 실패 등

curl 테스트 예시

아래 예시의 Nx7bQ2mZ(my_base_path)는 My AI Console(/mypage/settings)에서 확인한 실제 값으로, 7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a은 실제 등록된 cortexId로 교체하세요.

Cortex 선점

curl -s -X POST https://api-3.flameai.im/Nx7bQ2mZ/cortex/7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a/switch-conversation \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "conversationId": "chat-test-001" }' | python3 -m json.tool

대화 요청 (SSE 스트리밍)

curl -s -N -X POST https://api-3.flameai.im/Nx7bQ2mZ/cortex/7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a/messages \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "conversationId": "chat-test-001",
    "options": { "stream": true, "think": 1 },
    "messages": [
      { "role": "user", "content": "안녕하세요. 간단히 자기소개 해줘." }
    ]
  }'

이미지 질문 (비전 모델 Cortex)

# 1) 이미지 업로드 → 응답의 "file" 값을 확인
curl -s -X POST https://api-3.flameai.im/Nx7bQ2mZ/cortex/7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a/files \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Content-Type: image/jpeg" --data-binary @photo.jpg

# 2) 그 파일을 image 블록으로 넣어 질문
curl -s -X POST https://api-3.flameai.im/Nx7bQ2mZ/cortex/7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a/messages \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "conversationId": "chat-img-001",
    "options": { "stream": false, "think": 0 },
    "messages": [ { "role": "user", "content": [
      { "type": "image", "source": { "type": "file", "file": "files/upload-20261016-101500-a1b2.jpg" } },
      { "type": "text",  "text": "이 사진에 무엇이 있는지 설명해줘" } ] } ]
  }' | python3 -m json.tool

컨텍스트 재구성 (cortex_reset)

curl -s -N -X POST https://api-3.flameai.im/Nx7bQ2mZ/cortex/7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a/messages \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "conversationId": "chat-test-001",
    "options": { "stream": true, "cortex_reset": true },
    "messages": [
      { "role": "user",      "content": "파이썬이란 무엇인가?" },
      { "role": "assistant", "content": "파이썬은 범용 프로그래밍 언어입니다." },
      { "role": "user",      "content": "그렇다면 파이썬의 장점은?" }
    ]
  }'

상태 조회

curl -s https://api-3.flameai.im/Nx7bQ2mZ/cortex/7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a/status \
  -H "Authorization: Bearer YOUR_SECRET_KEY" | python3 -m json.tool

추론 중단

curl -s -X POST https://api-3.flameai.im/Nx7bQ2mZ/cortex/7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a/stop \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "conversationId": "chat-test-001" }' | python3 -m json.tool

점유 해제

curl -s -X POST https://api-3.flameai.im/Nx7bQ2mZ/cortex/7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a/switch-conversation \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "conversationId": "" }' | python3 -m json.tool

다른 API와의 차이

Claude(Anthropic) API나 OpenAI API를 써 본 개발자가 헷갈리기 쉬운 차이점입니다.

항목FlameAIClaude APIOpenAI API
대화 상태Stateful — Cortex가 대화를 기억, conversationId로 점유Stateless — 매번 전체 대화 전송Stateless — 매번 전체 대화 전송
스트리밍 지정options.stream최상위 stream최상위 stream
응답 구조단일 message 객체 (usage는 그 안에)단일 messagechoices[0].message, 최상위 usage
SSE 이벤트message.created / delta / block_done / completedcontent_block_start / content_block_delta 등choices[0].delta.content
종료 이유usage.stop_reason (eot, n_predict 등)stop_reason (end_turn 등)finish_reason
도구 호출tool_use 블록, 호출 내용은 원문 그대로 raw (클라이언트가 파싱)tool_use 블록, 파싱된 inputtool_calls 배열
도구 결과user 메시지의 tool_result 블록 (role: "tool" + 문자열도 허용)user 메시지의 tool_result 블록role: "tool" + tool_call_id
thinking 서명signature는 항상 빈 문자열서명 값을 다시 보내야 함-
모델명응답에 없음 (Cortex가 모델을 정함)model 필드model 필드
처리 시간elapsed_ms, prefill_ms 제공없음없음

WORKSPACE

WORKSPACE는 사용자에게 제공되는 공간으로, FlameAI 가입 시 자동으로 생성됩니다. 각 WORKSPACE에는 연결되는 가상의 my_base_path(API 경로)가 주어지며, 이 경로를 통해 사용자가 관리하는 Cortex 등을 API로 핸들링할 수 있습니다.

내 Cortex 목록

GET/{my_base_path}/cortexes

이 계정이 가진 Cortex 전체 목록을 조회합니다. FlameBox 자신의 /v1/cortexes(FlameBox 1대 단위)와 달리, 이 엔드포인트는 API Gateway 자신이 응답을 만듭니다 — 한 계정이 여러 FlameBox에 걸쳐 있을 수 있어서, FlameBox 하나가 답할 수 있는 질문이 아니기 때문입니다.

Response — 200 OK

{
  "cortexes": [
    {
      "cortexId":     "7f3c9a12-4e6b-4d8f-9a21-6b5e8c1f2d3a",
      "name":         "코딩 어시스턴트",
      "status":       "ONLINE",
      "flameboxId":   "fb-abc123",
      "flameboxName": "내 데스크탑"
    }
  ]
}
필드타입설명
cortexIdstringCortex 식별자
namestringCortex 이름(비어있으면 cortexId로 대체)
statusstringONLINE | OFFLINE — 이 Cortex가 속한 FlameBox의 온라인 여부(Cortex 자체의 idle/busy 여부가 아님)
flameboxIdstring이 Cortex가 속한 FlameBox 식별자
flameboxNamestring그 FlameBox의 이름
지금은 이 계정이 직접 소유한 FlameBox의 Cortex만 포함됩니다 — 다른 계정으로부터 공유받은 FlameBox(/mypage/share의 "내가 공유받은 FlameBox")의 Cortex는 아직 이 목록에 나오지 않습니다.

curl 테스트 예시

아래 예시의 Nx7bQ2mZ(my_base_path)는 My AI Console(/mypage/settings)에서 확인한 실제 값으로 교체하세요.

내 Cortex 목록 조회

curl -s https://api-3.flameai.im/Nx7bQ2mZ/cortexes \
  -H "Authorization: Bearer YOUR_SECRET_KEY" | python3 -m json.tool