Files
ForgeLM/README.md
T

9.2 KiB
Raw Blame History

ForgeLM

Inferência local de LLMs .gguf em Rust: API HTTP no estilo OpenAI, CLI e app desktop Tauri com chat persistente e gerenciador de modelos — tudo rodando na sua máquina.

Linguagem Desktop Licença

Início rápido · Recursos · Como funciona · Limitações · Documentação

Note

Estado do projeto: em desenvolvimento (último commit em abril/2026). Segundo .planning/ROADMAP.md, as fases 1–4 (estado de rascunho do runtime, segurança dos comandos de ciclo de vida, workspace unificado e download de modelos do Hugging Face) estão concluídas e a fase 5 (validação de fontes de modelo) segue aberta. O histórico também registra os planos 06-01 a 06-03 (redesign do chat e da página de Configurações).

Important

A API sobe aberta por padrão. Sem LOCALLLM_API_KEY não há autenticação, o bind default é 0.0.0.0:8080 e o CORS libera *. Para uso fora de uma máquina confiável, defina a chave e restrinja LOCALLLM_ADDR e LOCALLLM_CORS_ORIGINS (veja docs/api/configuration.md).

O que existe hoje

Superfície Onde O que entrega
API HTTP local crates/inference-server GET /health, GET /v1/models e POST /v1/chat/completions (com streaming SSE e stream_options.include_usage)
CLI localllm crates/localllm-cli Comandos status, models, auth, config, bench, logs e doctor; flags globais --server, --api-key, --models-dir, --format text|json e --dry-run
App desktop tauri-app Runtime manager (modo local ou remote), chat persistente e página de Configurações com gerenciador de modelos
Perfis de runtime crates/inference-core Turbo4B (default), balanced_9b e cpu_fallback, ajustáveis por LOCALLLM_GPU_LAYERS, LOCALLLM_CTX, LOCALLLM_BATCH, etc.
Runtime llama.cpp gerenciado crates/runtime-deps Baixa o llama.cpp b8358 (variantes CPU e CUDA 12.4), valida SHA-256 e guarda em cache local

No app desktop:

  • Runtime manager com estados stopped, starting, ready, degraded, stopping e error; o modo local inicia/para o processo e usa GET /health para saber se está pronto.
  • Gerenciador de modelos: escaneia/importa .gguf, busca modelos no Hugging Face, baixa em streaming com progresso e cancelamento (token do Hugging Face opcional), troca o modelo carregado com um clique (hot-swap: para, grava o novo model_path e reinicia), apaga arquivos e abre a pasta no explorador.
  • Chat: streaming, memória opcional de até 20 mensagens recentes, separação visual do raciocínio (<think>…</think>) da resposta final, contagem de tokens (por mensagem e por chat) e tokens/s, edição, reenvio e exclusão de mensagens.

Início rápido

Warning

Na primeira execução o servidor baixa o runtime do llama.cpp. Se o runtime não for encontrado (LLAMA_DLL_PATH, ao lado do binário ou vendor legado), o runtime-deps baixa o pacote de github.com/ggml-org/llama.cpp (b8358). A variante CUDA 12.4 são dois zips (≈ 227 MB + ≈ 391 MB conforme o manifesto); a CPU, um zip de ≈ 37 MB. O servidor escolhe CUDA quando as camadas em GPU são > 0 e cai para CPU caso não exista variante de GPU para o alvo.

1. Subir a API local (Windows cmd; em bash use export):

set LOCALLLM_MODEL=D:\caminho\modelo.gguf
cargo run -p inference-server

curl http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/v1/models

2. Usar a CLI:

cargo run -p localllm-cli -- status
cargo run -p localllm-cli -- models list

3. Abrir o app desktop:

cd tauri-app
npm install
npm run tauri dev

No app, abra o Runtime Manager, escolha modo local ou remote e depois use o chat.

Requisitos: toolchain Rust atual, Node.js/NPM (app Tauri) e um modelo .gguf local. GPU NVIDIA é opcional — existe o perfil cpu_fallback.

Como funciona

flowchart LR
    UI["App Tauri<br/>React + Rust"] -->|"HTTP /v1/chat/completions"| S
    UI -->|"inicia / para / health"| S["inference-server<br/>Axum · binário localllm"]
    CLI["localllm-cli"] -->|HTTP| S
    S --> C["inference-core<br/>engine · sessão · sampler · perfis"]
    C --> L["llama-sys<br/>carga dinâmica (libloading)"]
    L --> R["llama.dll<br/>llama.cpp b8358"]
    D["runtime-deps<br/>download + SHA-256"] --> R
    S --> D
    UI -->|"busca e download"| HF["Hugging Face"]
    S -.-> M["metrics<br/>tokens e throughput"]
Crates e módulos
Módulo Responsabilidade
crates/api-contracts Tipos compartilhados: chat completions, lista de modelos, health e erros
crates/inference-core Engine de inferência local: carga do modelo, sessão, sampler e perfis de runtime
crates/inference-server Camada HTTP em Axum: variáveis de ambiente, auth, CORS e aliases de modelo
crates/localllm-cli CLI de operação e automação (clap)
crates/metrics Contadores de uso de tokens e throughput
crates/llama-sys Integração de baixo nível: carrega llama.dll dinamicamente via libloading
crates/runtime-deps Resolve o runtime (override por env, binário adjacente, vendor legado ou cache gerenciado) e instala a partir de vendor/llama-runtime/manifest.json
tauri-app/ App desktop: frontend React 18 + Vite + Tailwind, backend Tauri 2 em Rust

Variáveis de ambiente do servidor (principais): LOCALLLM_MODEL, LOCALLLM_ADDR, LOCALLLM_MODEL_ALIASES, LOCALLLM_PROFILE, LOCALLLM_API_KEY, LOCALLLM_AUTH_HEADER, LOCALLLM_AUTH_SCHEME, LOCALLLM_CORS_ORIGINS, LOCALLLM_SYSTEM_PROMPT e LOCALLLM_ENABLE_TOOL_CALLS. Detalhes em docs/api/configuration.md.

Limitações conhecidas

  • A API expõe só três endpoints; a compatibilidade com a OpenAI é parcial e focada no fluxo de chat (n precisa ser 1, parallel_tool_calls não é tratado como recurso suportado, content em partes vira texto consolidado).
  • O raciocínio não aparece como campo separado na API; quem separa <think>…</think> é o frontend do app.
  • Na CLI, a execução ao vivo está mais consolidada em status, models list e bench throughput; o restante da superfície é mais avançado no parser do que nas capacidades HTTP públicas.
  • O chat usa sql.js carregado por CDN e persiste o banco exportado em localStorage — não é um banco nativo do sistema.
  • No modo local o app precisa encontrar o binário localllm; o runtime manager faz polling periódico do snapshot (sem fluxo de eventos push).
  • O manifesto do runtime (vendor/llama-runtime/manifest.json) só lista variantes windows-x64 (CPU e CUDA 12.4). Em outros alvos o servidor só sobe com um runtime já presente (binário adjacente ou LLAMA_DLL_PATH).
  • Os scripts scripts/build-dev.sh e scripts/build-prod.sh compilam vendor/llama.cpp e exigem esse submódulo, que não está declarado no repositório (não há .gitmodules).
  • inference-server e localllm-cli declaram ambos um binário chamado localllm; use cargo run -p <crate> para escolher qual executar.

Execução local

cargo run -p inference-server          # API em 0.0.0.0:8080 (precisa de LOCALLLM_MODEL)
cargo run -p localllm-cli -- status    # CLI

cd tauri-app
npm install
npm run dev          # só o frontend (Vite, porta 1420)
npm run tauri dev    # app desktop completo
npm run build        # tsc + vite build
npm test             # vitest run

Documentação

Documento Conteúdo
docs/README.md Índice da documentação
docs/api/overview.md · endpoints.md · configuration.md API: visão geral, referência HTTP e configuração
docs/cli/overview.md · commands.md CLI: visão geral e referência de comandos
docs/app/overview.md · user-guide.md · backend-commands.md App desktop: visão geral, guia de uso e comandos Tauri
docs/developer/architecture.md Arquitetura do workspace e fluxos entre módulos

Avisos

  • Os binários de inferência vêm do llama.cpp (releases oficiais baixadas e verificadas por SHA-256); modelos são buscados no Hugging Face e seguem a licença de cada autor.
  • Licença do workspace: MIT (declarada em Cargo.toml; o repositório não inclui arquivo LICENSE).