API Reference

FlameAI API 레퍼런스

FlameAI API를 사용해 FlameBox(CortexBox)의 AI 추론 기능을 외부 프로그램에서 호출하는 방법을 안내합니다.

문서 버전 v1.0.2 · 최종 업데이트 2026-06-27

Overview

Cortex란?

Cortex는 LLM 모델을 GPU/CPU 메모리에 로드하여 인스턴스화한 추론 실행 단위입니다. 모델 파일(.gguf)을 메모리에 상주시킨 상태로 대기하며, 요청이 들어오면 즉시 추론을 수행합니다.

모델 로드는 수 초~수십 초가 소요되므로 한 번 생성된 Cortex는 메모리에 상주한 채로 유지됩니다. 이 구조 때문에 다음 특성을 가집니다.

  • 단일 스레드 추론 — GPU/CPU 자원을 독점적으로 사용하므로 동시 추론이 불가능합니다.
  • KV Cache 공유 불가 — 대화 컨텍스트는 하나의 점유자에게만 귀속됩니다.
  • 단일 점유 리소스 — 한 번에 하나의 클라이언트만 사용할 수 있습니다.
# 하나의 CortexBox에 여러 Cortex를 생성해 분산 운용할 수 있습니다
[Cortex Client]
      │  REST API (/v1/)
      ▼
[CortexBox]
      ├─ Cortex (cortex-001)  ← 모델 로드, KV Cache, 대화 컨텍스트 보유
      ├─ Cortex (cortex-002)
      └─ Cortex (cortex-003)

Stateful 동작 방식

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

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

# Stateful 방식 — CortexBox Cortex
1번 요청: [user: "안녕"]                  → KV Cache 유지
2번 요청: [user: "이름이 뭐야?"]           → 마지막 메시지만 전송
점유자가 바뀌거나 /reset을 호출하면 KV Cache가 초기화됩니다. 이 경우 대화 히스토리 전체를 다시 전송해 컨텍스트를 재구축해야 합니다.

점유(Occupancy) 모델

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

상태설명
idle점유자 없음. 누구든 첫 요청으로 점유 가능
busy특정 occupancyId가 점유 중. 타 클라이언트 접근 불가

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

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

일반적인 사용 흐름

1
GET /v1/cortexList — 사용 가능한 Cortex 확인
2
POST /v1/{cortexId}/occupy — occupancyId로 Cortex 선점
3
POST /v1/{cortexId}/messages — 대화 히스토리 전체 + 새 메시지 전송 (SSE Stream)
4
GET /v1/{cortexId}/status — 컨텍스트 사용량 모니터링
5
POST /v1/{cortexId}/stop — 필요 시 추론 중단
6
POST /v1/{cortexId}/occupy — 다른 occupancyId로 전환하거나 ""로 점유 해제

How to Call

방법 1 — localhost 직접 호출

FlameBox가 실행 중인 머신에서 직접 호출하는 방식입니다.

http://localhost:{port}/v1/{cortexId}/...

예시: http://localhost:10815/v1/cortex-001/messages
  • 인증: 현재 버전에서는 인증 없음. 네트워크 접근 제어로 보호합니다.
  • 용도: 로컬 개발, 테스트, 동일 머신 내 서비스 간 연동

방법 2 — FlameAI API Gate 경유 호출

FlameBox를 FlameAI에 등록하면 외부에서 접근 가능한 API 엔드포인트가 발급됩니다.

https://api-{id}.flameai.im/v1/{cortexId}/...

예시: https://api-j121b.flameai.im/v1/cortex-001/messages
  • 인증: Authorization: Bearer {API_KEY} 헤더 필수
  • 용도: 외부 클라이언트, 웹 서비스, 모바일 앱 등 원격 연동

인증 (Bearer Token)

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

POST /v1/cortex-001/messages HTTP/1.1
Host: api-j121b.flameai.im
Content-Type: application/json
Authorization: Bearer eyJhbGci...
API Key는 FlameAI 회원 가입 후 CortexBox 등록 시 발급됩니다.

Common Rules

공통 요청 규칙

Content-Type: application/json

공통 응답 규칙

  • 성공 응답은 HTTP 200과 JSON 본문을 반환합니다.
  • SSE Stream 응답은 Content-Type: text/event-stream으로 반환합니다.
  • 응답 JSON에 error 필드가 없으면 정상 응답입니다.

에러 응답 포맷

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

에러 코드

코드HTTP상황
bad_request400JSON 파싱 실패 또는 파라미터 오류
cortex_not_found404없는 cortexId
cortex_occupied409다른 occupancyId가 Cortex를 점유 중
context_not_running409stop 요청 시 추론 중이 아님
cortex_inferring409해당 Cortex가 추론 중
forbidden403권한 없음 (occupancyId 불일치 등)
not_found404엔드포인트를 찾을 수 없음
internal_error500서버 내부 오류

Endpoints

GET /v1/cortexList

사용 가능한 Cortex 목록과 각 Cortex의 상태를 반환합니다.

Response — 200 OK

{
  "cortexList": [
    {
      "cortexId":    "cortex-001",
      "name":        "코딩 어시스턴트",
      "description": "코딩 및 개발 지원",
      "status":      "ready"
    }
  ]
}
필드타입설명
cortexIdstringCortex 식별자
namestringCortex 이름
descriptionstringCortex 설명
statusstringready | busy | unavailable

POST /v1/{cortexId}/messages

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

상세 명세는 04-api_messages.md를 참조하세요. 여기서는 기본 사용법만 안내합니다.

Request Body

{
  "occupancyId": "chat-550e8400",
  "options": {
    "stream":       true,
    "think":        false,
    "cortex_reset": false
  },
  "messages": [
    { "role": "user", "content": "안녕하세요" }
  ]
}
파라미터타입필수설명
occupancyIdstring현재 점유 중인 occupancyId와 일치해야 함
options.streamboolean아니오true면 SSE 스트리밍, false면 동기 응답 (기본값: true)
options.thinkboolean아니오사고 과정(thinking) 출력 여부
options.cortex_resetboolean아니오true면 KV Cache 초기화 후 messages 전체로 컨텍스트 재구축
messagesarray대화 히스토리. role: user|assistant|system

SSE Stream 응답 포맷

Content-Type: text/event-stream

data: {"delta": "안녕"}
data: {"delta": "하세요"}
data: [DONE]

Errors

코드HTTP상황
cortex_not_found404없는 cortexId
cortex_occupied409다른 occupancyId가 점유 중
cortex_inferring409이미 추론 중
forbidden403occupancyId 불일치

GET /v1/{cortexId}/status

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

Response — 200 OK

{
  "cortexId":       "cortex-001",
  "status":         "busy",
  "occupancyId":    "chat-550e8400",
  "context_size":   131072,
  "context_used":   45230,
  "context_remain": 85842
}
필드타입설명
statusstringidle | busy
occupancyIdstring|null현재 점유 중인 occupancyId. idle이면 null
context_sizeint모델 최대 컨텍스트 토큰 수
context_usedint현재 사용된 토큰 수
context_remainint남은 토큰 수

POST /v1/{cortexId}/stop

진행 중인 LLM 추론을 즉시 중단합니다. 추론 중이면 1초 이내에 중단되고 SSE Stream이 종료됩니다.

Request Body

{ "occupancyId": "chat-550e8400" }

Response — 200 OK

{
  "ok":       true,
  "cortexId": "cortex-001",
  "message":  "inference stopped"
}

Errors

코드HTTP상황
cortex_not_found404없는 cortexId
forbidden403occupancyId 불일치
context_not_running409추론 중이 아님

POST /v1/{cortexId}/reset

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

Request Body

{ "occupancyId": "chat-550e8400" }

Response — 200 OK

{
  "ok":       true,
  "cortexId": "cortex-001",
  "message":  "context reset"
}

POST /v1/{cortexId}/occupy

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

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

동작 규칙

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

Request Body

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

Response — 200 OK

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

Errors

코드HTTP상황
cortex_not_found404없는 cortexId
bad_request400JSON 파싱 실패

Examples

curl 테스트 예시

서버 기본 주소: http://localhost:9080cortex-001은 실제 등록된 cortexId로 교체하세요.

Cortex 목록 조회

curl -s http://localhost:9080/v1/cortexList | python3 -m json.tool

Cortex 선점

curl -s -X POST http://localhost:9080/v1/cortex-001/occupy \
  -H "Content-Type: application/json" \
  -d '{ "occupancyId": "chat-test-001" }' | python3 -m json.tool

대화 요청 (SSE 스트리밍)

curl -s -N -X POST http://localhost:9080/v1/cortex-001/messages \
  -H "Content-Type: application/json" \
  -d '{
    "occupancyId": "chat-test-001",
    "options": { "stream": true, "think": false },
    "messages": [
      { "role": "user", "content": "안녕하세요. 간단히 자기소개 해줘." }
    ]
  }'

컨텍스트 재구성 (cortex_reset)

curl -s -N -X POST http://localhost:9080/v1/cortex-001/messages \
  -H "Content-Type: application/json" \
  -d '{
    "occupancyId": "chat-test-001",
    "options": { "stream": true, "cortex_reset": true },
    "messages": [
      { "role": "user",      "content": "파이썬이란 무엇인가?" },
      { "role": "assistant", "content": "파이썬은 범용 프로그래밍 언어입니다." },
      { "role": "user",      "content": "그렇다면 파이썬의 장점은?" }
    ]
  }'

상태 조회

curl -s http://localhost:9080/v1/cortex-001/status | python3 -m json.tool

추론 중단

curl -s -X POST http://localhost:9080/v1/cortex-001/stop \
  -H "Content-Type: application/json" \
  -d '{ "occupancyId": "chat-test-001" }' | python3 -m json.tool

점유 해제

curl -s -X POST http://localhost:9080/v1/cortex-001/occupy \
  -H "Content-Type: application/json" \
  -d '{ "occupancyId": "" }' | python3 -m json.tool

API Gate 경유 호출 (Bearer Token)

curl -s -N -X POST https://api-j121b.flameai.im/v1/cortex-001/messages \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "occupancyId": "chat-test-001",
    "options": { "stream": true },
    "messages": [
      { "role": "user", "content": "오늘 날씨 어때?" }
    ]
  }'