# Documentação Completa do Backend - ForgeLM ## Sumário Executivo O ForgeLM é um sistema de inferência de LLMs locais composto por dois componentes principais: 1. **HTTP API Server** (`inference-server`) - Servidor Axum que expõe endpoints compatíveis com OpenAI 2. **Tauri Desktop Backend** - Backend do aplicativo desktop que gerencia o ciclo de vida do servidor --- ## Arquitetura Geral ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ ForgeLM Backend │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────┐ ┌─────────────────────────────────────────┐ │ │ │ Tauri App (Frontend)│ │ HTTP API Server (Axum) │ │ │ │ - React + TypeScript│ │ - Port: 8080 (default) │ │ │ │ - sql.js + localStorage│ │ - OpenAI-compatible API │ │ │ └──────────┬───────────┘ └──────────────┬──────────────────────────┘ │ │ │ │ │ │ │ Tauri Commands │ │ │ ▼ │ │ │ ┌──────────────────────┐ │ │ │ │ Tauri Backend │◄────────────────────┘ │ │ │ - Runtime lifecycle │ HTTP requests │ │ │ - Model management │ │ │ │ - GPU detection │ │ │ └──────────┬───────────┘ │ │ │ │ │ │ Spawns Process │ │ ▼ │ │ ┌──────────────────────┐ ┌─────────────────────────────────────────┐ │ │ │ inference-server │ │ inference-core │ │ │ │ (Binary Executable) │──────► - Engine │ │ │ │ │ │ - GenerationSession │ │ │ └──────────────────────┘ └──────────────┬──────────────────────────┘ │ │ │ │ │ │ FFI │ │ ▼ │ │ ┌─────────────────┐ │ │ │ llama-sys │ │ │ │ (llama.dll) │ │ │ └─────────────────┘ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` --- ## 1. Crates e Estrutura do Workspace ### Estrutura do Workspace ``` Cargo.toml (workspace root) ├── crates/ │ ├── llama-sys/ # FFI bindings para llama.cpp │ ├── runtime-deps/ # Gerenciamento de dependências do runtime │ ├── inference-core/ # Lógica de inferência (Engine, Session, Sampler) │ ├── inference-server/ # Servidor HTTP Axum │ ├── api-contracts/ # Schemas de request/response │ ├── metrics/ # Contadores de performance e TPS │ └── localllm-cli/ # CLI para gerenciamento │ └── tauri-app/ └── src-tauri/ └── src/ ├── lib.rs # Entry point Tauri ├── runtime/ # Gerenciamento do ciclo de vida ├── model_library/ # Biblioteca de modelos HuggingFace ├── model_files.rs # Operações com arquivos .gguf ├── model_alias.rs # Resolução de aliases └── gpu.rs # Detecção de GPU ``` ### Dependências do Workspace | Categoria | Crates | |-----------|--------| | Async Runtime | `tokio`, `axum`, `hyper`, `tower`, `tower-http` | | Serialization | `serde`, `serde_json` | | Error Handling | `anyhow`, `thiserror` | | Logging | `tracing`, `tracing-subscriber` | | FFI | `libloading`, `once_cell` | | Utilities | `uuid`, `chrono`, `futures`, `tokio-stream` | --- ## 2. HTTP API Server (inference-server) ### Entry Point - `main.rs` O servidor é iniciado em `crates/inference-server/src/main.rs`. #### Configuração via Environment Variables | Variável | Descrição | Padrão | |----------|-----------|--------| | `LOCALLLM_MODEL` | Caminho para arquivo GGUF | (obrigatório) | | `LOCALLLM_PROFILE` | Perfil de performance (`turbo_4b`, `balanced_9b`, `cpu_fallback`) | `turbo_4b` | | `LOCALLLM_CTX` | Tamanho do contexto (tokens) | depende do perfil | | `LOCALLLM_BATCH` | Tamanho do batch | 4096 (max) | | `LOCALLLM_GPU_LAYERS` | Camadas GPU (-1 = auto) | depende do perfil | | `LOCALLLM_THREADS` | Threads CPU | depende do perfil | | `LOCALLLM_ADDR` | Endereço de bind | `0.0.0.0:8080` | | `LOCALLLM_API_KEY` | Chave API para autenticação | (opcional) | | `LOCALLLM_LOG_FORMAT` | Formato de log (`json`, `pretty`) | `pretty` | | `LOCALLLM_MODEL_ALIASES` | Aliases para modelos (CSV) | (opcional) | | `LOCALLLM_ENABLE_TOOL_CALLS` | Habilitar tool calls | `true` | ### Rotas HTTP - `routes.rs` O roteador é construído em `crates/inference-server/src/routes.rs`. ```rust pub fn build_router(state: AppState) -> Router { Router::new() .route("/health", get(health_handler)) .route("/v1/models", get(models_handler)) .route("/v1/chat/completions", post(chat_completions_handler)) .layer(ServiceBuilder::new().layer(trace_layer).layer(cors)) .with_state(state) } ``` #### Endpoints | Método | Endpoint | Descrição | |--------|----------|-----------| | `GET` | `/health` | Health check do servidor | | `GET` | `/v1/models` | Lista modelos disponíveis | | `POST` | `/v1/chat/completions` | Chat completions (OpenAI-compatible) | #### AppState ```rust #[derive(Clone)] pub struct AppState { pub engine: Arc>, // Motor de inferência pub counters: Arc, // Contadores de performance pub model_name: Arc, // Nome do modelo atual pub server_config: Arc, // Configurações do servidor pub start_time: std::time::Instant, // Timestamp de início } ``` ### Compatibilidade OpenAI - `compat.rs` Arquivo: `crates/inference-server/src/compat.rs` #### ServerConfig Gerencia configurações de autenticação, CORS, e catálogo de modelos: ```rust #[derive(Debug, Clone)] pub struct ServerConfig { pub api_key: Option, pub auth_header: String, pub auth_scheme: Option, pub cors_origins: Vec, pub default_system_prompt: String, pub enable_tool_calls: bool, pub model_catalog: ModelCatalog, } ``` #### ModelCatalog Resolve aliases de modelos (case-insensitive): ```rust pub struct ModelCatalog { models: Vec, aliases: HashMap, } pub struct ModelDescriptor { pub id: String, pub root: String, pub parent: Option, } ``` **Aliases padrão:** `local-model`, `default` #### Chat Templates Suportados O sistema detecta automaticamente o template baseado no nome do modelo: | Modelo | Template | Formatos | |--------|----------|----------| | Qwen | `<\|im_start\|>`, `<\|im_end\|>` | `system`, `user`, `assistant`, `tool` | | Gemma | ``, `` | `model`, `user` | | Llama | `[INST]`, `[/INST]` | com `<>` para system | | Kimi/Moonshot | `<\|im_system\|>`, `<\|im_user\|>`, `<\|im_assistant\|>` | - | | Genérico | `Role: content` | Padrão | #### Autorização Suporta múltiplos headers de autenticação: - Header configurado (`LOCALLLM_AUTH_HEADER`) - `Authorization: Bearer ` - `X-API-Key: ` #### Validação de Requests Validações implementadas: - Modelo existe no catálogo - Lista de mensagens não está vazia - `n=1` (apenas uma completion por request) - Tool calls habilitado se tools presentes --- ## 3. inference-core ### Engine - `engine.rs` Local: `crates/inference-core/src/engine.rs` O `InferenceEngine` é o núcleo de inferência que gerencia: - Carregamento do modelo GGUF via llama-sys FFI - Inicialização do contexto llama.cpp - Criação de sessões de geração #### EngineConfig ```rust pub struct EngineConfig { pub model_path: PathBuf, // Caminho para arquivo GGUF pub profile: RuntimeProfile, // Perfil de performance pub n_gpu_layers: i32, // Camadas GPU (-1 = todas) pub n_ctx: u32, // Contexto (tokens) pub n_batch: u32, // Batch size (prefill) pub n_ubatch: u32, // Micro-batch (geração) pub n_threads: i32, // Threads CPU pub n_threads_batch: i32, // Threads para batch pub flash_attn: bool, // Flash Attention pub use_mmap: bool, // Usar memory mapping pub seed: u32, // Seed RNG } ``` #### Runtime Profiles | Perfil | n_ctx | n_gpu_layers | Descrição | |--------|-------|--------------|-----------| | `Turbo4B` | 8192 | 999 | GPU total, otimizado para modelos até 4B | | `Balanced9B` | 16384 | 999 | Equilibrado para modelos até 9B | | `CpuFallback` | 4096 | 0 | CPU-only fallback | #### Ciclo de Vida do Engine ```rust // 1. Carregar engine let mut engine = InferenceEngine::load(config)?; // 2. Warmup (aloca buffers CUDA) engine.warmup()?; // 3. Criar sessão de geração let session = engine.new_session(prompt, sampler_cfg)?; // 4. Gerar tokens while let Some(token) = session.next_token() { print!("{}", token); } ``` **Nota sobre segurança:** O engine é `Send` mas NÃO é `Sync`. Acesso deve ser coordenado (o servidor usa `tokio::sync::Mutex`). ### Session - `session.rs` ```rust pub struct GenerationSession { // ... } impl GenerationSession { pub fn next_token(&mut self) -> Option; pub fn prompt_tokens(&self) -> u32; } ``` ### Sampler - `sampler.rs` Configurações de sampling: ```rust pub struct SamplerConfig { pub temperature: f32, // 0.0 - 2.0 pub top_p: f32, // 0.0 - 1.0 pub max_tokens: u32, pub stop_sequences: Vec, pub repeat_penalty: f32, // 1.15 (normal), 1.0 (tools) pub repeat_last_n: usize, // 256 tokens pub seed: u32, } ``` --- ## 4. API Contracts Local: `crates/api-contracts/src/` ### Chat Completion Request (`chat.rs`) ```rust pub struct ChatCompletionRequest { pub model: String, pub messages: Vec, pub max_tokens: u32, // default: 1024 pub temperature: f32, // default: 0.15 pub top_p: f32, // default: 0.95 pub stream: bool, // default: false pub stop: Vec, pub n: u32, // default: 1 (apenas 1 suportado) pub seed: Option, pub user: Option, pub response_format: Option, pub tools: Vec, pub tool_choice: Option, pub stream_options: Option, } ``` ### ChatMessage ```rust pub struct ChatMessage { pub role: Role, // System, Developer, User, Assistant, Tool pub content: Option, pub name: Option, pub tool_calls: Option>, pub tool_call_id: Option, } ``` ### ResponseFormat ```rust pub struct ResponseFormat { pub format_type: String, // "json_object", "json_schema", "text" pub json_schema: Option, } ``` ### ToolCalling ```rust pub struct ToolDefinition { pub tool_type: ToolType, pub function: FunctionDefinition, } pub struct FunctionDefinition { pub name: String, pub description: Option, pub parameters: Value, // JSON Schema } pub struct ToolCall { pub id: String, pub tool_type: ToolType, pub function: ToolFunctionCall, } pub struct ToolFunctionCall { pub name: String, pub arguments: String, // JSON string } ``` --- ## 5. Tauri Desktop Backend ### Entry Point - `lib.rs` Local: `tauri-app/src-tauri/src/lib.rs` O backend Tauri gerencia: - Ciclo de vida do runtime (start/stop) - Gerenciamento de modelos locais - Downloads do HuggingFace - Detecção de GPU - Sistema ForgeAgent (multi-agente) ### Commands Tauri ```rust .invoke_handler(tauri::generate_handler![ query_gpu, // Detectar GPU NVIDIA scan_models, // Escanear arquivos .gguf pick_models_dir, // Selecionar diretório pick_model_files, // Selecionar arquivos import_model, // Importar modelo search_hugging_face_models_command, // Buscar no HF start_hugging_face_download_command, // Download do HF cancel_hugging_face_download_command,// Cancelar download swap_model_command, // Trocar modelo delete_model_file, // Deletar arquivo open_model_folder_command, // Abrir pasta list_model_library_entries_command, // Listar biblioteca get_model_library_state_command, // Estado da biblioteca bootstrap_runtime_command, // Bootstrap runtime get_runtime_snapshot_command, // Snapshot do runtime save_runtime_config_command_handler, // Salvar config start_runtime_command, // Iniciar runtime stop_runtime_command, // Parar runtime resolve_startup_model_command, // Resolver modelo inicial get_app_data_dir, // Diretório de dados find_server_binary, // Localizar binário start_forgeagent_session_command, // Iniciar ForgeAgent ]) ``` ### Runtime Types - `runtime/types.rs` #### ConnectionMode ```rust pub enum ConnectionMode { Local, // Servidor local spawnado Remote, // Conectar a servidor externo } ``` #### RuntimeStatus ```rust pub enum RuntimeStatus { Stopped, Starting, Loading, Ready, Degraded, Stopping, Error, } ``` #### RuntimeConfig ```rust pub struct RuntimeConfig { pub connection_mode: ConnectionMode, pub start_policy: StartPolicy, // Manual, OnAppLaunch pub server_url: String, // Para Remote mode pub api_key: String, pub model_path: Option, pub models_dir: Option, pub addr: String, // "127.0.0.1:8080" pub gpu_layers: i32, pub ctx_size: u32, // default: 4096 pub extra_model_paths: Vec, pub selected_model_id: Option, pub remote_presets: Vec, pub hugging_face_token: String, pub preferred_startup_model_alias: Option, } ``` #### RuntimeSnapshot ```rust pub struct RuntimeSnapshot { pub status: RuntimeStatus, pub ready: bool, pub process_running: bool, pub resolved_url: String, pub binary_path: Option, pub last_error: Option, pub active_command: RuntimeLifecycleCommand, pub last_command_result: RuntimeLifecycleResult, pub config: RuntimeConfig, } ``` ### Model Library - `model_library/` #### Tipos ```rust pub struct ModelLibraryEntry { pub id: String, pub name: String, pub repo_id: String, pub description: String, pub tags: Vec, pub size_gb: f64, pub default_file: String, pub installed: bool, pub installed_path: Option, } pub struct HuggingFaceModelResult { pub id: String, pub model_id: String, pub downloads: i64, pub likes: i32, pub tags: Vec, pub gguf_files: Vec, } ``` ### Model Files - `model_files.rs` ```rust #[derive(Serialize)] pub struct ModelFileInfo { pub path: String, pub file_name: String, pub size_bytes: u64, pub modified: Option, } ``` --- ## 6. Fluxo de Dados ### 1. Requisição Chat Completion ``` ┌──────────┐ ┌─────────────┐ ┌──────────────┐ ┌─────────────┐ │ Client │───►│ Axum Router │───►│ compat.rs │───►│ routes.rs │ └──────────┘ └─────────────┘ └──────────────┘ └──────┬──────┘ │ ▼ ┌──────────┐ ┌─────────────┐ ┌──────────────┐ ┌─────────────┐ │ Client │◄───│ JSON │◄───│ Generation │◄───│ Engine │ │ │ │ Response │ │ Session │ │ (Mutex) │ └──────────┘ └─────────────┘ └──────────────┘ └──────┬──────┘ │ ▼ ┌─────────────────┐ │ llama-sys │ │ (llama.dll) │ └─────────────────┘ ``` ### 2. Streaming vs Blocking **Streaming Mode:** 1. Cria stream SSE 2. Gera tokens em `spawn_blocking` 3. Envia chunks via channel 4. Client recebe tokens em tempo real **Blocking Mode:** 1. Gera completion completa 2. Retorna JSON único ### 3. Ciclo de Vida do Modelo ``` ┌─────────────┐ │ Stopped │ └──────┬──────┘ │ start_runtime_command() ▼ ┌─────────────┐ │ Starting │ └──────┬──────┘ │ Processo spawnado ▼ ┌─────────────┐ │ Loading │ └──────┬──────┘ │ Modelo carregado ▼ ┌─────────────┐ │ Ready │◄──────────┐ └──────┬──────┘ │ │ stop_runtime() │ swap_model_command() ▼ │ ┌─────────────┐ │ │ Stopping │ │ └─────────────┘ │ │ ├─────────────────────────┤ │ swap │ │ ┌─────┐ ┌─────┐ │ │ │Stop │──►│Start│ │ │ └─────┘ └─────┘ │ └─────────────────────────┘ ``` --- ## 7. ForgeAgent - Sistema Multi-Agente ### Especialistas | ID | Nome | Emoji | Função | |----|------|-------|--------| | `analyst` | Analista | 🔍 | Análise técnica e decomposição | | `architect` | Arquiteto | 🏗️ | Arquitetura de software e padrões | | `developer` | Desenvolvedor | 💻 | Implementação pragmática | | `critic` | Crítico | ⚖️ | Revisão e identificação de riscos | ### Fluxo de Eventos ``` start_forgeagent_session_command() │ ▼ ┌─────────────────────────┐ │ forgeagent:start │──► Envia plano estruturado └─────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ forgeagent:step-started │──► Início de cada passo └─────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ forgeagent:step-completed│──► Passo concluído └─────────────────────────┘ │ ▼ ┌───────────────────────────────┐ │ forgeagent:specialist-thought │──► Pensamento do especialista └───────────────────────────────┘ │ ▼ ┌──────────────────────────────────┐ │ forgeagent:specialist-response │──► Resposta do especialista └──────────────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ forgeagent:plan-completed│──► Resumo final └─────────────────────────┘ ``` --- ## 8. API HTTP - Exemplos ### Health Check ```bash curl http://localhost:8080/health ``` **Response:** ```json { "status": "ok", "model_loaded": true, "model_id": "qwen2.5-7b-instruct", "uptime_secs": 3600 } ``` ### Listar Modelos ```bash curl http://localhost:8080/v1/models \ -H "Authorization: Bearer sua-chave" ``` **Response:** ```json { "object": "list", "data": [ { "id": "local-model", "object": "model", "created": 1234567890, "owned_by": "local", "root": "qwen2.5-7b-instruct", "parent": "qwen2.5-7b-instruct", "permission": [] } ] } ``` ### Chat Completion (Non-streaming) ```bash curl http://localhost:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sua-chave" \ -d '{ "model": "local-model", "messages": [ {"role": "user", "content": "Olá!"} ], "max_tokens": 1024, "temperature": 0.7 }' ``` **Response:** ```json { "id": "uuid-123", "object": "chat.completion", "created": 1234567890, "model": "qwen2.5-7b-instruct", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "Olá! Como posso ajudar?" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 10, "completion_tokens": 20, "total_tokens": 30, "tokens_per_second": 45.5 } } ``` ### Chat Completion (Streaming) ```bash curl http://localhost:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sua-chave" \ -d '{ "model": "local-model", "messages": [ {"role": "user", "content": "Conte uma piada"} ], "stream": true }' ``` **Response (SSE):** ``` data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{"role":"assistant"}}]} data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{"content":"Por"}}]} data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{"content":" que"}}]} ... data: {"id":"...","object":"chat.completion.chunk","choices":[{"finish_reason":"stop"}]} data: [DONE] ``` ### Tool Calling ```bash curl http://localhost:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sua-chave" \ -d '{ "model": "local-model", "messages": [ {"role": "user", "content": "Liste os arquivos"} ], "tools": [ { "type": "function", "function": { "name": "list_files", "description": "Lista arquivos do projeto", "parameters": { "type": "object", "properties": { "path": {"type": "string"} } } } } ], "tool_choice": "auto" }' ``` --- ## 9. Configuração e Deploy ### Compilação ```bash # Servidor $env:LOCALLLM_LOG_FORMAT="json" cargo build --release -p inference-server # CLI cargo build --release -p localllm-cli # Tauri App cd tauri-app cargo tauri build ``` ### Execução ```bash # Com variáveis de ambiente $env:LOCALLLM_MODEL="D:\models\model.gguf" $env:LOCALLLM_PROFILE="balanced_9b" $env:LOCALLLM_API_KEY="minha-chave-secreta" $env:LOCALLLM_ADDR="0.0.0.0:8080" .\target\release\inference-server.exe ``` ### Docker (se aplicável) ```bash docker run -p 8080:8080 \ -v /path/to/models:/models \ -e LOCALLLM_MODEL=/models/model.gguf \ -e LOCALLLM_API_KEY=secret \ forgelm/inference-server:latest ``` --- ## 10. Estrutura de Arquivos ### Diretórios Importantes ``` %LOCALAPPDATA%/ForgeLM/ # Windows ~/.local/share/ForgeLM/ # Linux ~/Library/Application Support/ForgeLM/ # macOS ├── models/ # Modelos baixados ├── runtime/ # Binários do runtime └── config.json # Configuração do runtime ``` ### Frontend (Tauri App) ``` tauri-app/ ├── src/ │ ├── lib/ │ │ ├── db.ts # Persistência local (sql.js) │ │ └── types.ts # Tipos TypeScript │ ├── main.tsx # Entry React │ └── App.tsx # App shell └── src-tauri/ ├── src/ │ ├── lib.rs # Entry Tauri │ ├── runtime/ # Gerenciamento runtime │ ├── model_library/ # HuggingFace integration │ ├── model_files.rs # Arquivos locais │ ├── model_alias.rs # Resolução aliases │ └── gpu.rs # Detecção GPU └── taury.conf.json # Config Tauri ``` --- ## 11. Glossário | Termo | Descrição | |-------|-----------| | **GGUF** | Format binary for LLMs (GPT-Generated Unified Format) | | **KV Cache** | Key-Value cache for attention mechanism | | **Prefill** | Initial prompt processing phase | | **Decode** | Token generation phase | | **Context Window** | Maximum tokens the model can process | | **Batch** | Number of tokens processed together | | **GPU Layers** | Number of model layers offloaded to GPU | | **Flash Attention** | Optimized attention implementation | | **Tool Calling** | Function calling capability for LLMs | | **SSE** | Server-Sent Events for streaming | --- ## 12. Referências Rápidas ### Arquivos Principais | Função | Arquivo | |--------|---------| | Entry Server | `crates/inference-server/src/main.rs` | | Rotas HTTP | `crates/inference-server/src/routes.rs` | | Compat OpenAI | `crates/inference-server/src/compat.rs` | | Engine | `crates/inference-core/src/engine.rs` | | Session | `crates/inference-core/src/session.rs` | | Sampler | `crates/inference-core/src/sampler.rs` | | Schemas | `crates/api-contracts/src/chat.rs` | | Entry Tauri | `tauri-app/src-tauri/src/lib.rs` | | Runtime Types | `tauri-app/src-tauri/src/runtime/types.rs` | ### Env Vars Completas ```bash # Modelo e Performance LOCALLLM_MODEL="/path/to/model.gguf" LOCALLLM_PROFILE="turbo_4b" # turbo_4b, balanced_9b, cpu_fallback LOCALLLM_CTX=8192 LOCALLLM_BATCH=4096 LOCALLLM_GPU_LAYERS=-1 LOCALLLM_THREADS=4 LOCALLLM_THREADS_BATCH=4 # Servidor LOCALLLM_ADDR="0.0.0.0:8080" LOCALLLM_API_KEY="secret" LOCALLLM_AUTH_HEADER="authorization" LOCALLLM_AUTH_SCHEME="Bearer" LOCALLLM_CORS_ORIGINS="*,https://example.com" # Features LOCALLLM_ENABLE_TOOL_CALLS="true" LOCALLLM_MODEL_ALIASES="alias1,alias2" LOCALLLM_SYSTEM_PROMPT="Você é um assistente..." # Logging LOCALLLM_LOG_FORMAT="json" # ou pretty RUST_LOG="info" ``` --- ## Conclusão Este documento cobre a arquitetura completa do backend ForgeLM, incluindo: 1. **HTTP Server** - API compatível com OpenAI usando Axum 2. **Inference Core** - Motor de inferência via llama.cpp 3. **Tauri Backend** - Gerenciamento desktop do ciclo de vida 4. **API Contracts** - Schemas de request/response 5. **Fluxos de Dados** - Como as requisições fluem pelo sistema Para mais detalhes, consulte os arquivos de código fonte mencionados nas referências.