Initial commit (with migration template)
BIN
docs/architecture/helios_logo.jpg
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
docs/architecture/litellm_detailed_response_flow.png
Normal file
|
After Width: | Height: | Size: 599 KiB |
228
docs/architecture/litellm_internal_process_flowchart.md
Normal file
@@ -0,0 +1,228 @@
|
||||
# HeliosLLM Router 내부 처리 프로세스 명세서 (요청/응답 상세 흐름 분리)
|
||||
|
||||
<p align="center">
|
||||
<img src="./helios_logo.jpg" alt="HELIOS Logo" width="400">
|
||||
</p>
|
||||
|
||||
이 문서는 이 프로젝트 환경에 실제로 구동 중인 **HeliosLLM Router** (LiteLLM Proxy 기반 커스텀 라우터) 및 모니터링 시스템의 물리적 포트, 환경 변수, 설정 파일, 소스 코드 로직을 매핑하여 실제 구현 사양을 기반으로 작성한 상세 명세서입니다.
|
||||
|
||||
프로세스의 구체적인 컴포넌트와 세부 정보를 유지하면서 **요청(Request) 처리 흐름**과 **응답(Response) 처리 흐름**을 분리하여 설명합니다.
|
||||
|
||||
---
|
||||
|
||||
## Part 1. 요청 처리 프로세스 (Request Flow)
|
||||
|
||||
요청 처리 흐름은 클라이언트가 API를 호출한 시점부터 HeliosLLM Router가 요청을 전처리하고 적절한 백엔드 LLM 인스턴스를 선택하여 요청을 전달하기까지의 과정을 다룹니다. 이 과정에서 유입된 요청 수(RPS) 및 대상 모델 정보 등의 메트릭이 실시간으로 프로메테우스 스택에 카운팅됩니다.
|
||||
|
||||
### 1. 요청 흐름 상세 플로우차트 (상세 디테일 / Light Theme)
|
||||
|
||||

|
||||
|
||||
### 2. 요청 흐름 상세 플로우차트 (Mermaid)
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
%% 스타일 정의
|
||||
classDef client fill:#e1f5fe,stroke:#0288d1,stroke-width:2px;
|
||||
classDef proxy fill:#efebe9,stroke:#5d4037,stroke-width:2px;
|
||||
classDef hook fill:#ede7f6,stroke:#5e35b1,stroke-width:2px;
|
||||
classDef router fill:#fff3e0,stroke:#f57c00,stroke-width:2px;
|
||||
classDef backend fill:#e8f5e9,stroke:#388e3c,stroke-width:2px;
|
||||
classDef metrics fill:#fce4ec,stroke:#c2185b,stroke-width:2px;
|
||||
|
||||
%% Client 영역
|
||||
subgraph ClientZone [클라이언트 영역]
|
||||
Client([API Client])
|
||||
end
|
||||
class Client client;
|
||||
|
||||
%% Gateway & Proxy Core
|
||||
subgraph ProxyCore [HeliosLLM Router Gateway]
|
||||
PortMapping[Docker Port Forwarding<br/>Host 8010 ──► Container 4000]
|
||||
ProxyServer[HeliosLLM Router Core<br/>FastAPI / LiteLLM Proxy]
|
||||
PortMapping --> ProxyServer
|
||||
end
|
||||
class PortMapping,ProxyServer proxy;
|
||||
Client -->|1. HTTP POST /v1/chat/completions<br/>Payload: model, messages, stream| PortMapping
|
||||
|
||||
%% Pre-Call Hook (Multimodal Router)
|
||||
subgraph PreCallHookZone [사전 전처리 필터: custom_logger.py]
|
||||
HookEntry[MultimodalRouterHandler<br/>async_pre_call_hook]
|
||||
|
||||
CheckType{type이 'video_url' 이거나<br/>image_url 내 비디오 확장자<br/>.mp4, .webm 등이 있는가?}
|
||||
|
||||
CheckText{일반 텍스트(str/text) 내에<br/>비디오 URL 패턴이<br/>포함되어 있는가?}
|
||||
|
||||
RewriteModel[model 필드 값을<br/>'Helios-VL'로 재작성]
|
||||
KeepModel[기존 요청 model명 유지]
|
||||
|
||||
ProxyServer -->|2. Hook Trigger| HookEntry
|
||||
HookEntry --> CheckType
|
||||
CheckType -->|Yes| RewriteModel
|
||||
CheckType -->|No| CheckText
|
||||
CheckText -->|Yes (비디오 URL 포함)| RewriteModel
|
||||
CheckText -->|No| KeepModel
|
||||
end
|
||||
class HookEntry,CheckType,CheckText,RewriteModel,KeepModel hook;
|
||||
|
||||
%% Routing & Load Balancing (config.yaml)
|
||||
subgraph RoutingZone [라우팅 및 분기 판단]
|
||||
Router[HeliosLLM Router Core]
|
||||
Decision{최종 model명이<br/>Helios-VL 인가?}
|
||||
|
||||
SimpleShuffle[simple-shuffle 로드밸런서<br/>50:50 Shuffle 분배]
|
||||
|
||||
RewriteModel -->|3. 가공된 데이터 반환| Router
|
||||
KeepModel -->|3. 기존 데이터 반환| Router
|
||||
Router --> Decision
|
||||
Decision -->|Yes (멀티모달)| Port8003[Backend 3: Helios-VL<br/>Qwen3-VL-8B-Instruct<br/>Port 8003]
|
||||
Decision -->|No (텍스트)| SimpleShuffle
|
||||
|
||||
SimpleShuffle -->|50% 확률 분배| Port8001[Backend 1: Helios-LLM<br/>Nex-N2-mini<br/>Port 8001]
|
||||
SimpleShuffle -->|50% 확률 분배| Port8002[Backend 2: Helios-LLM<br/>Nex-N2-mini-fp8<br/>Port 8002]
|
||||
end
|
||||
class Router,Decision,SimpleShuffle router;
|
||||
class Port8001,Port8002,Port8003 backend;
|
||||
|
||||
%% Monitoring Pipeline
|
||||
subgraph ReqMetricsZone [실시간 메트릭 로깅]
|
||||
PromCallback[Prometheus Callback]
|
||||
MetricUpdate[litellm_request_total 누적 카운트<br/>Labels: model, api_key_hash]
|
||||
|
||||
Router -->|4. 요청 메트릭 로깅 트리거| PromCallback
|
||||
PromCallback --> MetricUpdate
|
||||
end
|
||||
class PromCallback,MetricUpdate metrics;
|
||||
```
|
||||
|
||||
### 2. 요청 흐름 세부 절차
|
||||
|
||||
#### ① API 요청 수집 및 포트 포워딩
|
||||
- 클라이언트가 `http://localhost:8010/v1/chat/completions` 주소로 ChatCompletion POST 요청을 보냅니다.
|
||||
- Docker Compose 포트 매핑(`8010:4000`)을 거쳐 컨테이너 내부 4000 포트에서 실행 중인 **HeliosLLM Router Core** 프로세스로 패킷이 인입됩니다.
|
||||
|
||||
#### ② Pre-Call Hook을 통한 멀티모달 자동 라우팅
|
||||
- Router에 설정된 커스텀 로거 콜백에 의해 [custom_logger.py](file:///home/admin2/Workspace/LiteLLM/custom_logger.py)의 `MultimodalRouterHandler` 클래스 내 `async_pre_call_hook` 함수가 즉시 호출됩니다.
|
||||
- **멀티모달 감지**:
|
||||
- **이미지 검출**: 요청 JSON 바디의 `messages` 배열 내에 `{"type": "image_url"}` 데이터가 존재하는지 검사합니다.
|
||||
- **동영상 검출**: `{"type": "video_url"}` 데이터가 존재하거나, `image_url` 타입 내의 url 주소가 동영상 확장자(`.mp4`, `.webm`, `.mov`, `.avi`, `.mkv`)를 포함하고 있는지 검사합니다.
|
||||
- **텍스트 내 비디오 검출**: 메시지의 `content`가 일반 문자열(`str`)이거나 `type: "text"` 필드인 경우에도, 텍스트 내용 내에 `http` 링크와 비디오 확장자명이 함께 존재하는지 검사하여 동영상 요청으로 판별합니다.
|
||||
- **모델 재작성 (Rewriting)**: 이미지 또는 동영상이 감지되었고 동시에 클라이언트가 지정한 타겟 모델이 일반 텍스트 모델인 **`Helios-LLM`**일 경우, 요청 딕셔너리의 `model` 필드 값을 VLM(비전-언어 모델) 전용 모델인 **`Helios-VL`**로 강제 교체합니다.
|
||||
|
||||
#### ③ Router의 백엔드 매핑 및 로드 밸런싱 (`config.yaml`)
|
||||
- **Helios-LLM 분기**:
|
||||
- `routing_strategy: simple-shuffle` 설정에 의해, 아래 두 백엔드 인스턴스로 요청이 균등하게 분산(Shuffle)됩니다.
|
||||
- **백엔드 1**: `openai/nex-agi/Nex-N2-mini` (물리주소: 환경변수 `LLM_API_BASE_1`, Port `8001`)
|
||||
- **백엔드 2**: `openai/nex-agi/Nex-N2-mini-fp8` (물리주소: 환경변수 `LLM_API_BASE_2`, Port `8002`)
|
||||
- **Helios-VL 분기**:
|
||||
- 사전 훅에서 모델명이 변경되었거나 처음부터 `Helios-VL`로 인입된 요청은 비전 전용 백엔드로 직접 라우팅됩니다.
|
||||
- **백엔드 3**: `openai/Qwen/Qwen3-VL-8B-Instruct` (물리주소: 환경변수 `LLM_API_BASE_3`, Port `8003`)
|
||||
|
||||
#### ④ 요청 시점의 실시간 메트릭 로깅 (Request Monitoring)
|
||||
- 클라이언트로부터 요청이 수신되는 즉시, Router의 Prometheus 콜백은 요청 상태를 체크하여 다음과 같은 동적 누적 메트릭을 기록합니다.
|
||||
- **요청 횟수 누적**: `litellm_request_total` 카운터를 증가하여 초당 요청 수(RPS)를 측정할 수 있도록 합니다.
|
||||
- **대상 모델 및 API 키 속성 기록**: 라우팅 대상 모델(`Helios-LLM` 또는 `Helios-VL`)과 요청에 사용된 API Key 해시 정보를 태그로 맵핑하여 Prometheus 메트릭 수집기(`/metrics`)에 실시간 반영합니다.
|
||||
|
||||
#### ⑤ API 포맷 규격 변환 및 API 전송
|
||||
- Router Core 모듈이 선택된 타겟 백엔드의 API 주소(`api_base`) 규격에 맞게 HTTP Payload를 최종 직렬화(Serialization)하여 대상 서버로 비동기 호출을 실행합니다.
|
||||
|
||||
---
|
||||
|
||||
## Part 2. 응답 처리 프로세스 (Response Flow)
|
||||
|
||||
응답 처리 흐름은 백엔드 LLM 서버가 추론 결과를 반환한 시점부터 HeliosLLM Router가 이를 감지하여 규격을 가공하고, 지연 시간 및 토큰 소모량 메트릭을 계산한 후 최종 클라이언트에 응답을 전송하고 이를 시각화하기까지의 과정을 다룹니다.
|
||||
|
||||
### 1. 응답 및 모니터링 흐름 상세 플로우차트 (상세 디테일 / Light Theme)
|
||||
|
||||

|
||||
|
||||
### 2. 응답 및 모니터링 흐름 상세 플로우차트 (Mermaid)
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
%% 스타일 정의
|
||||
classDef client fill:#e1f5fe,stroke:#0288d1,stroke-width:2px;
|
||||
classDef proxy fill:#efebe9,stroke:#5d4037,stroke-width:2px;
|
||||
classDef hook fill:#ede7f6,stroke:#5e35b1,stroke-width:2px;
|
||||
classDef backend fill:#e8f5e9,stroke:#388e3c,stroke-width:2px;
|
||||
classDef monitor fill:#fffde7,stroke:#fbc02d,stroke-width:2px;
|
||||
classDef prometheus fill:#ffebee,stroke:#ef5350,stroke-width:2px;
|
||||
|
||||
%% Backends
|
||||
subgraph BackendZone [실제 추론 서버]
|
||||
Port8001[Backend 1: Nex-N2-mini<br/>Port 8001]
|
||||
Port8002[Backend 2: Nex-N2-mini-fp8<br/>Port 8002]
|
||||
Port8003[Backend 3: Helios-VL<br/>Port 8003]
|
||||
end
|
||||
class Port8001,Port8002,Port8003 backend;
|
||||
|
||||
%% Router Core Response processing
|
||||
subgraph RouterResponseZone [HeliosLLM Router Core 응답 처리]
|
||||
ResponseReceiver[HTTP 응답 수신 모듈<br/>스트림 청크 / 일반 JSON]
|
||||
ResponseTranslator[Response Translation<br/>OpenAI 표준 JSON 규격 변환]
|
||||
PostCallHook[Post-Call Callback 실행]
|
||||
|
||||
Port8001 -->|1. 추론 응답 반환| ResponseReceiver
|
||||
Port8002 -->|1. 추론 응답 반환| ResponseReceiver
|
||||
Port8003 -->|1. 추론 응답 반환| ResponseReceiver
|
||||
|
||||
ResponseReceiver --> ResponseTranslator
|
||||
ResponseTranslator --> PostCallHook
|
||||
end
|
||||
class ResponseReceiver,ResponseTranslator,PostCallHook proxy;
|
||||
|
||||
%% Metrics calculation
|
||||
subgraph MetricsCalculation [성능 지표 비동기 연산]
|
||||
CalcLatency[API 소요 지연시간 연산<br/>ResponseTime - RequestTime]
|
||||
CalcTokens[usage 필드 파싱 및 집계<br/>prompt_tokens, completion_tokens]
|
||||
MetricServer[Prometheus Metrics Exporter<br/>/metrics Endpoint 노출]
|
||||
|
||||
PostCallHook -->|2. 비동기 지표 갱신| CalcLatency
|
||||
PostCallHook -->|2. 비동기 지표 갱신| CalcTokens
|
||||
CalcLatency --> MetricServer
|
||||
CalcTokens --> MetricServer
|
||||
end
|
||||
class CalcLatency,CalcTokens,MetricServer prometheus;
|
||||
|
||||
%% Client Return
|
||||
subgraph ClientReturnZone [클라이언트 최종 반환]
|
||||
Client([API Client])
|
||||
PostCallHook -->|3. OpenAI 규격화된 HTTP Response 반환| Client
|
||||
end
|
||||
class Client client;
|
||||
|
||||
%% Monitoring visualization 스택
|
||||
subgraph MonitoringStack [실시간 모니터링 시각화 파이프라인]
|
||||
PrometheusServer[Prometheus Server<br/>Port 9090]
|
||||
GrafanaServer[Grafana Server<br/>Port 3000]
|
||||
|
||||
MetricServer -->|4. 15초 주기 Metrics Scrape| PrometheusServer
|
||||
GrafanaServer -->|5. Prometheus 데이터 소스 쿼리| PrometheusServer
|
||||
PrometheusServer -->|6. 시계열 지표 반환| GrafanaServer
|
||||
end
|
||||
class PrometheusServer,GrafanaServer monitor;
|
||||
```
|
||||
|
||||
### 2. 응답 흐름 세부 절차
|
||||
|
||||
#### ① 백엔드 응답(Response/Stream) 수신
|
||||
- 호출된 백엔드 LLM/VLM API 서버(Port 8001/8002/8003)가 추론 처리를 마치고 HTTP 응답을 반환합니다.
|
||||
- **스트리밍(stream: true)인 경우**: 백엔드가 점진적으로 출력하는 SSE(Server-Sent Events) 스트림 데이터 트래픽을 감지하여 지속적인 커넥션을 유지하며 청크(Chunk) 단위로 읽어들입니다.
|
||||
- **논스트리밍인 경우**: 단일 JSON 완성 객체를 수신합니다.
|
||||
|
||||
#### ② Response Translation (OpenAI 포맷 표준화)
|
||||
- HeliosLLM Router Core는 수신한 응답 페이로드를 실시간으로 해체 및 파싱합니다.
|
||||
- 다양한 종류의 백엔드 자체 응답 구조를 일관된 **OpenAI ChatCompletionResponse 규격**의 표준 JSON(또는 OpenAI stream 포맷)으로 재구조화하여 단일화합니다.
|
||||
|
||||
#### ③ Post-Call Callbacks (실시간 지표 계산 및 로깅)
|
||||
- 표준 가공이 완료되면 사후 등록된 콜백들이 비동기로 실행되어 성능 지표를 분석합니다:
|
||||
- **지연 시간(Latency) 연산**: 요청 시각과 응답 완료 시각의 차이를 계산하여 API 총 소요 속도 도출.
|
||||
- **토큰 사용량(Usage) 측정**: 최종 응답 내부의 `usage` 필드를 파싱하여 입력 프롬프트 토큰 수(`prompt_tokens`) 및 완료 토큰 수(`completion_tokens`)를 추출.
|
||||
- 버퍼에 수집된 수치는 Router의 `http://localhost:8010/metrics` 경로에 프로메테우스 표준 포맷의 시계열 메트릭 데이터로 업데이트되어 노출됩니다.
|
||||
|
||||
#### ④ HTTP Response 최종 반환
|
||||
- 변환 완료된 OpenAI 표준 JSON 페이로드 혹은 SSE 스트림 데이터 라인을 대기 중이던 클라이언트에게 HTTP Response 패킷으로 최종 응답합니다.
|
||||
|
||||
#### ⑤ 모니터링 시각화 파이프라인 연동
|
||||
- **Prometheus (Port 9090)**: 15초 간격으로 HeliosLLM Router의 `/metrics` 주소를 스크래핑(Scrape)하여 시계열 데이터베이스(TSDB)에 실시간으로 통계를 축적합니다.
|
||||
- **Grafana (Port 3000)**: Prometheus를 데이터 소스로 연동하여, 수집된 시계열 메트릭(RPS, 대기 지연시간, 토큰 소모량 등)을 그라파나 대시보드 화면에 실시간 그래프와 대시보드 형태로 시각화합니다.
|
||||
BIN
docs/architecture/litellm_request_flow_final.png
Normal file
|
After Width: | Height: | Size: 581 KiB |
BIN
docs/architecture/litellm_request_flow_v2.png
Normal file
|
After Width: | Height: | Size: 692 KiB |
BIN
docs/architecture/litellm_request_flow_with_monitoring.png
Normal file
|
After Width: | Height: | Size: 535 KiB |
|
After Width: | Height: | Size: 553 KiB |
BIN
docs/architecture/litellm_response_flow_final.png
Normal file
|
After Width: | Height: | Size: 587 KiB |
BIN
docs/architecture/litellm_response_flow_v2.png
Normal file
|
After Width: | Height: | Size: 534 KiB |
53
docs/architecture/system_architecture_20260714.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 시스템 아키텍처 다이어그램 (2026년 07월 14일 업데이트)
|
||||
|
||||
기존 시스템 구조에서 **두 모델 모두 256K Context를 지원**하도록 상향 적용된 변경 사항을 반영한 아키텍처 다이어그램입니다.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
%% 스타일 정의
|
||||
classDef clientNode fill:#f4f6f9,stroke:#6c7a89,stroke-width:1px
|
||||
classDef serverBox fill:#ffffff,stroke:#a6acaf,stroke-width:2px,rx:10,ry:10
|
||||
classDef proxyNode fill:#e9ecef,stroke:#adb5bd,stroke-width:1px,rx:5,ry:5
|
||||
classDef modelNode fill:#fcf3cf,stroke:#f1c40f,stroke-width:1px,rx:5,ry:5
|
||||
classDef storageNode fill:#fef9e7,stroke:#f39c12,stroke-width:1px
|
||||
|
||||
subgraph ClientAppZone [" "]
|
||||
ClientApp["💻 Client application<br/>React GUI"]:::clientNode
|
||||
end
|
||||
|
||||
subgraph FrontServer ["Front Server"]
|
||||
Nginx["🌐 Nginx Host Proxy"]:::proxyNode
|
||||
end
|
||||
|
||||
subgraph DockerGUI ["Docker: GUI Container"]
|
||||
Express["⚙️ Express Backend"]:::proxyNode
|
||||
SessionMgt["🔑 Session<br/>Management"]:::proxyNode
|
||||
FileStore[("📁 File Storage<br/>data/sessions.json")]:::storageNode
|
||||
end
|
||||
|
||||
subgraph LLMServer1 ["LLM Server 1"]
|
||||
Router["🔀 LLM Router<br/>Helios LLM - LiteLLM<br/>based"]:::proxyNode
|
||||
Model1["🤖 nvidia/Gemma-4-31B-IT-NVFP4<br/>256K Context (Multimodal)"]:::modelNode
|
||||
end
|
||||
|
||||
subgraph LLMServer2 ["LLM Server 2"]
|
||||
Model2["🤖 google/gemma-4-26B-A4B-it<br/>256K Context (Multimodal)"]:::modelNode
|
||||
end
|
||||
|
||||
%% 연결선 (Client -> Front Server)
|
||||
ClientApp -- "HTTP / WebSocket" --> Nginx
|
||||
|
||||
%% 연결선 (Front Server -> GUI Container)
|
||||
Nginx -- "Reverse Proxy" --> Express
|
||||
|
||||
%% GUI Container 내부
|
||||
Express <--> SessionMgt
|
||||
SessionMgt <--> FileStore
|
||||
|
||||
%% 연결선 (GUI Container -> LLM Server 1)
|
||||
Express -- "API Request / Stream" --> Router
|
||||
|
||||
%% LLM Router 라우팅
|
||||
Router -- "Local Route" --> Model1
|
||||
Router -- "Remote Route" --> Model2
|
||||
```
|
||||