API Reference
FlameAI API를 사용해 FlameBox(CortexBox)의 AI 추론 기능을 외부 프로그램에서 호출하는 방법을 안내합니다.
문서 버전 v1.0.2 · 최종 업데이트 2026-06-27Overview
Cortex는 LLM 모델을 GPU/CPU 메모리에 로드하여 인스턴스화한 추론 실행 단위입니다. 모델 파일(.gguf)을 메모리에 상주시킨 상태로 대기하며, 요청이 들어오면 즉시 추론을 수행합니다.
모델 로드는 수 초~수십 초가 소요되므로 한 번 생성된 Cortex는 메모리에 상주한 채로 유지됩니다. 이 구조 때문에 다음 특성을 가집니다.
# 하나의 CortexBox에 여러 Cortex를 생성해 분산 운용할 수 있습니다
[Cortex Client]
│ REST API (/v1/)
▼
[CortexBox]
├─ Cortex (cortex-001) ← 모델 로드, KV Cache, 대화 컨텍스트 보유
├─ Cortex (cortex-002)
└─ Cortex (cortex-003)
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가 초기화됩니다. 이 경우 대화 히스토리 전체를 다시 전송해 컨텍스트를 재구축해야 합니다.클라이언트는 occupancyId를 통해 Cortex를 선점하며, 점유 중인 Cortex에는 동일한 occupancyId를 가진 클라이언트만 요청할 수 있습니다.
| 상태 | 설명 |
|---|---|
idle | 점유자 없음. 누구든 첫 요청으로 점유 가능 |
busy | 특정 occupancyId가 점유 중. 타 클라이언트 접근 불가 |
| 전략 | 설명 |
|---|---|
| 재시도 대기 | 현재 점유자가 해제할 때까지 기다린 후 재점유 |
| 강제 재점유 | /occupy로 점유를 빼앗은 후 대화 히스토리로 컨텍스트 재구축 |
| 포기 | 에러를 사용자에게 전달하고 다른 Cortex 탐색 |
GET /v1/cortexList — 사용 가능한 Cortex 확인POST /v1/{cortexId}/occupy — occupancyId로 Cortex 선점POST /v1/{cortexId}/messages — 대화 히스토리 전체 + 새 메시지 전송 (SSE Stream)GET /v1/{cortexId}/status — 컨텍스트 사용량 모니터링POST /v1/{cortexId}/stop — 필요 시 추론 중단POST /v1/{cortexId}/occupy — 다른 occupancyId로 전환하거나 ""로 점유 해제How to Call
FlameBox가 실행 중인 머신에서 직접 호출하는 방식입니다.
http://localhost:{port}/v1/{cortexId}/...
예시: http://localhost:10815/v1/cortex-001/messages
FlameBox를 FlameAI에 등록하면 외부에서 접근 가능한 API 엔드포인트가 발급됩니다.
https://api-{id}.flameai.im/v1/{cortexId}/...
예시: https://api-j121b.flameai.im/v1/cortex-001/messages
Authorization: Bearer {API_KEY} 헤더 필수API Gate를 통해 호출할 때는 모든 요청에 Bearer Token을 포함해야 합니다.
POST /v1/cortex-001/messages HTTP/1.1
Host: api-j121b.flameai.im
Content-Type: application/json
Authorization: Bearer eyJhbGci...
Common Rules
Content-Type: application/json
Content-Type: text/event-stream으로 반환합니다.error 필드가 없으면 정상 응답입니다.{
"error": {
"code": "에러코드",
"message": "상세 메시지",
"httpStatus": 404
}
}
| HTTP | 상황 |
|---|---|
| 400 | bad request — 파라미터 오류, JSON 파싱 실패 |
| 401 | unauthorized — 인증 실패 |
| 403 | forbidden — 인증은 되었으나 리소스 접근 권한 없음 |
| 404 | not found — URL 또는 리소스를 찾을 수 없음 |
| 409 | conflict — 점유 충돌, 추론 중 등 상태 불일치 |
| 500 | internal error — 서버 내부 오류 |
| 코드 | HTTP | 상황 |
|---|---|---|
| bad_request | 400 | JSON 파싱 실패 또는 파라미터 오류 |
| cortex_not_found | 404 | 없는 cortexId |
| cortex_occupied | 409 | 다른 occupancyId가 Cortex를 점유 중 |
| context_not_running | 409 | stop 요청 시 추론 중이 아님 |
| cortex_inferring | 409 | 해당 Cortex가 추론 중 |
| forbidden | 403 | 권한 없음 (occupancyId 불일치 등) |
| not_found | 404 | 엔드포인트를 찾을 수 없음 |
| internal_error | 500 | 서버 내부 오류 |
Endpoints
사용 가능한 Cortex 목록과 각 Cortex의 상태를 반환합니다.
{
"cortexList": [
{
"cortexId": "cortex-001",
"name": "코딩 어시스턴트",
"description": "코딩 및 개발 지원",
"status": "ready"
}
]
}
| 필드 | 타입 | 설명 |
|---|---|---|
cortexId | string | Cortex 식별자 |
name | string | Cortex 이름 |
description | string | Cortex 설명 |
status | string | ready | busy | unavailable |
대화 메시지를 전송하고 AI 응답을 받습니다. SSE 스트리밍과 동기 방식을 모두 지원합니다.
04-api_messages.md를 참조하세요. 여기서는 기본 사용법만 안내합니다.{
"occupancyId": "chat-550e8400",
"options": {
"stream": true,
"think": false,
"cortex_reset": false
},
"messages": [
{ "role": "user", "content": "안녕하세요" }
]
}
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
occupancyId | string | 예 | 현재 점유 중인 occupancyId와 일치해야 함 |
options.stream | boolean | 아니오 | true면 SSE 스트리밍, false면 동기 응답 (기본값: true) |
options.think | boolean | 아니오 | 사고 과정(thinking) 출력 여부 |
options.cortex_reset | boolean | 아니오 | true면 KV Cache 초기화 후 messages 전체로 컨텍스트 재구축 |
messages | array | 예 | 대화 히스토리. role: user|assistant|system |
Content-Type: text/event-stream
data: {"delta": "안녕"}
data: {"delta": "하세요"}
data: [DONE]
| 코드 | HTTP | 상황 |
|---|---|---|
| cortex_not_found | 404 | 없는 cortexId |
| cortex_occupied | 409 | 다른 occupancyId가 점유 중 |
| cortex_inferring | 409 | 이미 추론 중 |
| forbidden | 403 | occupancyId 불일치 |
Cortex의 현재 점유 상태와 Context 토큰 사용량을 반환합니다. 추론 중에도 조회 가능합니다.
{
"cortexId": "cortex-001",
"status": "busy",
"occupancyId": "chat-550e8400",
"context_size": 131072,
"context_used": 45230,
"context_remain": 85842
}
| 필드 | 타입 | 설명 |
|---|---|---|
status | string | idle | busy |
occupancyId | string|null | 현재 점유 중인 occupancyId. idle이면 null |
context_size | int | 모델 최대 컨텍스트 토큰 수 |
context_used | int | 현재 사용된 토큰 수 |
context_remain | int | 남은 토큰 수 |
진행 중인 LLM 추론을 즉시 중단합니다. 추론 중이면 1초 이내에 중단되고 SSE Stream이 종료됩니다.
{ "occupancyId": "chat-550e8400" }
{
"ok": true,
"cortexId": "cortex-001",
"message": "inference stopped"
}
| 코드 | HTTP | 상황 |
|---|---|---|
| cortex_not_found | 404 | 없는 cortexId |
| forbidden | 403 | occupancyId 불일치 |
| context_not_running | 409 | 추론 중이 아님 |
Cortex의 KV Cache(대화 컨텍스트)를 초기화합니다. 이후 요청 시 대화 히스토리 전체를 다시 전송해야 합니다.
{ "occupancyId": "chat-550e8400" }
{
"ok": true,
"cortexId": "cortex-001",
"message": "context reset"
}
Cortex를 선점(Occupy)합니다. 이미 다른 클라이언트가 점유 중인 Cortex를 강제로 빼앗거나, 점유를 해제하는 데도 사용합니다.
/occupy는 점유 전환을 허용합니다. 점유 중 다른 클라이언트의 탈취를 방지하려면 상위 레이어(API 프록시 등)에서 접근 제어를 수행해야 합니다.| 상황 | 동작 |
|---|---|
| Cortex가 idle 상태 | occupancyId를 등록하고 즉시 점유 성공 |
| 동일한 occupancyId로 재요청 | 점유 유지 (no-op) |
| 다른 occupancyId로 요청 | 기존 점유를 해제하고 새 occupancyId로 전환 (강제 탈취) |
occupancyId를 ""로 요청 | 점유 해제 (idle 상태로 전환) |
{
"occupancyId": "chat-550e8400" // 빈 문자열 ""이면 점유 해제
}
{
"ok": true,
"message": "occupancyId changed to chat-550e8400"
}
| 코드 | HTTP | 상황 |
|---|---|---|
| cortex_not_found | 404 | 없는 cortexId |
| bad_request | 400 | JSON 파싱 실패 |
Examples
서버 기본 주소: http://localhost:9080 — cortex-001은 실제 등록된 cortexId로 교체하세요.
curl -s http://localhost:9080/v1/cortexList | python3 -m json.tool
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
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": "안녕하세요. 간단히 자기소개 해줘." } ] }'
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
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": "오늘 날씨 어때?" } ] }'