feat: integrate desktop runtime and root workspace updates
This commit is contained in:
1 parent
f5a4a9ee97
commit
168623c459
93 files changed
+19540
-1208
No files matched your search
+10
-388
@@ -1,393 +1,15 @@
|
||||
# ForgeLM API Reference
|
||||
# ForgeLM API docs
|
||||
|
||||
ForgeLM exposes an **OpenAI-compatible REST API** for local LLM inference. Any client that works with the OpenAI API (VSCode extensions, OpenCode, Cline, Roo Code, curl, Python `openai` SDK, etc.) can point at this server with no code changes.
|
||||
Este arquivo antigo foi substituido pela nova documentacao modular em `docs/api/`.
|
||||
|
||||
---
|
||||
Use estes documentos como referencia oficial atual:
|
||||
|
||||
## Base URL
|
||||
- `docs/api/overview.md` - visao geral da arquitetura e da superficie HTTP
|
||||
- `docs/api/endpoints.md` - referencia dos endpoints, payloads, respostas e erros
|
||||
- `docs/api/configuration.md` - variaveis de ambiente, auth, CORS e perfis de runtime
|
||||
|
||||
```
|
||||
http://127.0.0.1:8080
|
||||
```
|
||||
Motivo da mudanca:
|
||||
|
||||
Configure with the `LOCALLLM_ADDR` environment variable (default `127.0.0.1:8080`).
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
Authentication is **optional** and disabled by default.
|
||||
|
||||
| Env var | Description |
|
||||
|---------|-------------|
|
||||
| `LOCALLLM_API_KEY` | If set, all requests must include this key |
|
||||
| `LOCALLLM_AUTH_HEADER` | Header name to check (default: `authorization`) |
|
||||
| `LOCALLLM_AUTH_SCHEME` | Expected scheme prefix (default: `Bearer`) |
|
||||
|
||||
**Sending a key:**
|
||||
|
||||
```http
|
||||
Authorization: Bearer <your-key>
|
||||
```
|
||||
|
||||
or via `x-api-key`:
|
||||
|
||||
```http
|
||||
x-api-key: <your-key>
|
||||
```
|
||||
|
||||
If no key is configured, all requests are accepted without authentication.
|
||||
|
||||
---
|
||||
|
||||
## CORS
|
||||
|
||||
CORS is enabled for all origins by default (`*`). Restrict with:
|
||||
|
||||
```
|
||||
LOCALLLM_CORS_ORIGINS=https://myapp.com,http://localhost:3000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpoints
|
||||
|
||||
### `GET /health`
|
||||
|
||||
Returns server and model status.
|
||||
|
||||
**Response `200 OK`:**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"model_loaded": true,
|
||||
"model_id": "Qwen3.5-4B-Abliterated.i1-Q6_K",
|
||||
"uptime_secs": 142
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `status` | `string` | Always `"ok"` when server is running |
|
||||
| `model_loaded` | `boolean` | Whether a model is currently loaded |
|
||||
| `model_id` | `string \| null` | Canonical model identifier |
|
||||
| `uptime_secs` | `integer` | Seconds since server start |
|
||||
|
||||
---
|
||||
|
||||
### `GET /v1/models`
|
||||
|
||||
Lists available models. Compatible with the OpenAI models endpoint.
|
||||
|
||||
**Response `200 OK`:**
|
||||
|
||||
```json
|
||||
{
|
||||
"object": "list",
|
||||
"data": [
|
||||
{
|
||||
"id": "Qwen3.5-4B-Abliterated.i1-Q6_K",
|
||||
"object": "model",
|
||||
"created": 1711497600,
|
||||
"owned_by": "local",
|
||||
"root": "Qwen3.5-4B-Abliterated.i1-Q6_K"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Model aliases (configured via `LOCALLLM_MODEL_ALIASES`) also appear in the list and resolve to the same underlying model.
|
||||
|
||||
---
|
||||
|
||||
### `POST /v1/chat/completions`
|
||||
|
||||
The main inference endpoint. Fully compatible with the OpenAI Chat Completions API.
|
||||
|
||||
**Request body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "Qwen3.5-4B-Abliterated.i1-Q6_K",
|
||||
"messages": [
|
||||
{ "role": "system", "content": "You are a helpful assistant." },
|
||||
{ "role": "user", "content": "Explain async/await in Rust." }
|
||||
],
|
||||
"max_tokens": 1024,
|
||||
"temperature": 0.15,
|
||||
"top_p": 0.95,
|
||||
"stream": false
|
||||
}
|
||||
```
|
||||
|
||||
#### Request fields
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `model` | `string` | **required** | Model ID or alias |
|
||||
| `messages` | `array` | **required** | Conversation history |
|
||||
| `max_tokens` | `integer` | `1024` | Max tokens to generate (alias: `max_completion_tokens`) |
|
||||
| `temperature` | `float` | `0.15` | Sampling temperature (0 = greedy) |
|
||||
| `top_p` | `float` | `0.95` | Nucleus sampling threshold |
|
||||
| `stream` | `boolean` | `false` | Enable SSE streaming |
|
||||
| `stop` | `string \| array` | `[]` | Stop sequences |
|
||||
| `seed` | `integer` | `null` | Reproducibility seed |
|
||||
| `n` | `integer` | `1` | Number of completions (only `1` supported) |
|
||||
| `response_format` | `object` | `null` | `{"type": "text"}` or `{"type": "json_object"}` |
|
||||
| `tools` | `array` | `[]` | Tool definitions for function calling |
|
||||
| `tool_choice` | `string \| object` | `null` | Tool selection policy |
|
||||
| `stream_options` | `object` | `null` | `{"include_usage": true}` to get usage in stream |
|
||||
|
||||
#### Message roles
|
||||
|
||||
| Role | Description |
|
||||
|------|-------------|
|
||||
| `system` | System-level instructions |
|
||||
| `developer` | Developer-level instructions (treated as system) |
|
||||
| `user` | User turn |
|
||||
| `assistant` | Previous assistant turn |
|
||||
| `tool` | Tool call result |
|
||||
|
||||
#### Non-streaming response `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "chatcmpl-a1b2c3d4",
|
||||
"object": "chat.completion",
|
||||
"created": 1711497600,
|
||||
"model": "Qwen3.5-4B-Abliterated.i1-Q6_K",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "In Rust, `async/await` allows you to write asynchronous code..."
|
||||
},
|
||||
"finish_reason": "stop"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 24,
|
||||
"completion_tokens": 87,
|
||||
"total_tokens": 111,
|
||||
"tokens_per_second": 52.4
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Streaming response (SSE)
|
||||
|
||||
Set `"stream": true` to receive Server-Sent Events:
|
||||
|
||||
```
|
||||
data: {"id":"chatcmpl-a1b2c3d4","object":"chat.completion.chunk","created":1711497600,"model":"Qwen3.5-4B-Abliterated.i1-Q6_K","choices":[{"index":0,"delta":{"role":"assistant","content":"In"},"finish_reason":null}]}
|
||||
|
||||
data: {"id":"chatcmpl-a1b2c3d4","object":"chat.completion.chunk","created":1711497600,"model":"Qwen3.5-4B-Abliterated.i1-Q6_K","choices":[{"index":0,"delta":{"content":" Rust"},"finish_reason":null}]}
|
||||
|
||||
data: {"id":"chatcmpl-a1b2c3d4","object":"chat.completion.chunk","created":1711497600,"model":"Qwen3.5-4B-Abliterated.i1-Q6_K","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
|
||||
|
||||
data: [DONE]
|
||||
```
|
||||
|
||||
To include usage in the final streaming chunk:
|
||||
|
||||
```json
|
||||
{
|
||||
"stream": true,
|
||||
"stream_options": { "include_usage": true }
|
||||
}
|
||||
```
|
||||
|
||||
#### Tool calling
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "Qwen3.5-4B-Abliterated.i1-Q6_K",
|
||||
"messages": [{ "role": "user", "content": "What is the weather in Paris?" }],
|
||||
"tools": [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_weather",
|
||||
"description": "Get current weather for a city",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"city": { "type": "string" }
|
||||
},
|
||||
"required": ["city"]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"tool_choice": "auto"
|
||||
}
|
||||
```
|
||||
|
||||
When the model decides to call a tool, `finish_reason` is `"tool_calls"` and `message.tool_calls` contains the call:
|
||||
|
||||
```json
|
||||
{
|
||||
"choices": [{
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": null,
|
||||
"tool_calls": [{
|
||||
"id": "call_abc123",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_weather",
|
||||
"arguments": "{\"city\": \"Paris\"}"
|
||||
}
|
||||
}]
|
||||
},
|
||||
"finish_reason": "tool_calls"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error responses
|
||||
|
||||
All errors follow the OpenAI error format:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"message": "The model 'unknown-model' does not exist",
|
||||
"type": "invalid_request_error",
|
||||
"param": "model",
|
||||
"code": "model_not_found"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| HTTP status | `type` | When |
|
||||
|-------------|--------|------|
|
||||
| `400` | `invalid_request_error` | Malformed request, empty messages, unsupported `n` |
|
||||
| `401` | `authentication_error` | Missing or invalid API key |
|
||||
| `404` | `invalid_request_error` | Unknown model |
|
||||
| `422` | `invalid_request_error` | Unsupported `response_format` |
|
||||
| `500` | `server_error` | Internal inference failure |
|
||||
|
||||
---
|
||||
|
||||
## Environment variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `LOCALLLM_MODEL` | *(required)* | Path to the GGUF model file |
|
||||
| `LOCALLLM_ADDR` | `127.0.0.1:8080` | Bind address |
|
||||
| `LOCALLLM_PROFILE` | `balanced` | Runtime profile (`fast`, `balanced`, `quality`) |
|
||||
| `LOCALLLM_GPU_LAYERS` | `0` | Number of layers to offload to GPU |
|
||||
| `LOCALLLM_CTX` | `4096` | Context window size |
|
||||
| `LOCALLLM_BATCH` | `512` | Batch size |
|
||||
| `LOCALLLM_UBATCH` | `512` | Micro-batch size |
|
||||
| `LOCALLLM_THREADS` | *(auto)* | CPU threads for generation |
|
||||
| `LOCALLLM_THREADS_BATCH` | *(auto)* | CPU threads for batch processing |
|
||||
| `LOCALLLM_API_KEY` | *(none)* | API key for authentication |
|
||||
| `LOCALLLM_AUTH_HEADER` | `authorization` | Auth header name |
|
||||
| `LOCALLLM_AUTH_SCHEME` | `Bearer` | Auth scheme prefix |
|
||||
| `LOCALLLM_CORS_ORIGINS` | `*` | Comma-separated allowed origins |
|
||||
| `LOCALLLM_SYSTEM_PROMPT` | *(coding assistant)* | Default system prompt |
|
||||
| `LOCALLLM_ENABLE_TOOL_CALLS` | `false` | Enable tool calling support |
|
||||
| `LOCALLLM_MODEL_ALIASES` | *(none)* | Comma-separated `alias=model` pairs |
|
||||
|
||||
---
|
||||
|
||||
## Quick start
|
||||
|
||||
### Start the server
|
||||
|
||||
```bash
|
||||
LOCALLLM_MODEL=./models/Qwen3.5-4B.gguf cargo run --release -p inference-server
|
||||
```
|
||||
|
||||
### Test with curl
|
||||
|
||||
```bash
|
||||
# Health check
|
||||
curl http://localhost:8080/health
|
||||
|
||||
# List models
|
||||
curl http://localhost:8080/v1/models
|
||||
|
||||
# Chat completion
|
||||
curl http://localhost:8080/v1/chat/completions \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "Qwen3.5-4B",
|
||||
"messages": [{"role": "user", "content": "Hello!"}],
|
||||
"max_tokens": 100
|
||||
}'
|
||||
|
||||
# Streaming
|
||||
curl http://localhost:8080/v1/chat/completions \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "Qwen3.5-4B",
|
||||
"messages": [{"role": "user", "content": "Count to 5"}],
|
||||
"stream": true
|
||||
}'
|
||||
```
|
||||
|
||||
### Use with Python openai SDK
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
|
||||
client = OpenAI(
|
||||
base_url="http://localhost:8080/v1",
|
||||
api_key="not-needed" # or your LOCALLLM_API_KEY
|
||||
)
|
||||
|
||||
response = client.chat.completions.create(
|
||||
model="Qwen3.5-4B",
|
||||
messages=[{"role": "user", "content": "Write a Python hello world"}],
|
||||
max_tokens=200
|
||||
)
|
||||
print(response.choices[0].message.content)
|
||||
```
|
||||
|
||||
### Use with VSCode / OpenCode / Cline / Roo Code
|
||||
|
||||
Set the following in your extension settings:
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Base URL | `http://localhost:8080/v1` |
|
||||
| API Key | *(leave empty or set `LOCALLLM_API_KEY`)* |
|
||||
| Model | *(your model ID from `/v1/models`)* |
|
||||
|
||||
---
|
||||
|
||||
## Chat template behavior
|
||||
|
||||
ForgeLM automatically selects the correct chat template based on the model family:
|
||||
|
||||
| Model family | Template |
|
||||
|-------------|----------|
|
||||
| `qwen` | `<\|im_start\|>` / `<\|im_end\|>` tokens |
|
||||
| `gemma` | `<start_of_turn>` / `<end_of_turn>` tokens |
|
||||
| `llama` | `[INST]` / `[/INST]` blocks with `<<SYS>>` |
|
||||
| `kimi` / `moonshot` | `<\|im_system\|>` / `<\|im_user\|>` / `<\|im_assistant\|>` |
|
||||
| *(other)* | Generic `System:` / `User:` / `Assistant:` format |
|
||||
|
||||
Template selection uses the requested model name and any configured aliases, so renaming a model to include a family hint (e.g. `qwen-coder`) is sufficient.
|
||||
|
||||
---
|
||||
|
||||
## Coding defaults
|
||||
|
||||
When no system prompt is provided, ForgeLM injects a coding-focused default:
|
||||
|
||||
> *You are a precise coding assistant running locally. Prioritize correct code, minimal speculation, explicit assumptions, and actionable fixes. When editing or generating code, prefer complete snippets, preserve requested APIs, and explain risks briefly.*
|
||||
|
||||
Sampling defaults are also tuned for code generation:
|
||||
- `temperature: 0.15` (low randomness)
|
||||
- `top_p: 0.95`
|
||||
- `max_tokens: 1024`
|
||||
|
||||
Override any of these per-request or globally via `LOCALLLM_SYSTEM_PROMPT`.
|
||||
- a estrutura antiga era monolitica
|
||||
- ela corria o risco de sugerir uma compatibilidade OpenAI mais ampla do que o codigo atual realmente garante
|
||||
- a nova estrutura separa melhor arquitetura, referencia HTTP e configuracao operacional
|
||||
@@ -0,0 +1,30 @@
|
||||
# Documentacao do ForgeLM
|
||||
|
||||
Esta pasta concentra a documentacao detalhada do projeto. O `README.md` da raiz funciona como ponto de entrada rapido; aqui ficam as referencias completas.
|
||||
|
||||
## API e backend
|
||||
|
||||
- `api/overview.md` - arquitetura do backend, crates envolvidos e comportamento geral da API
|
||||
- `api/endpoints.md` - referencia dos endpoints HTTP, payloads, respostas e erros
|
||||
- `api/configuration.md` - variaveis de ambiente, auth, CORS, aliases de modelo e perfis de runtime
|
||||
|
||||
## CLI
|
||||
|
||||
- `cli/overview.md` - como a CLI se encaixa no projeto, flags globais e formatos de saida
|
||||
- `cli/commands.md` - referencia de comandos, subcomandos, exemplos e limitacoes atuais
|
||||
|
||||
## App desktop
|
||||
|
||||
- `app/overview.md` - arquitetura geral do app Tauri e seus subsistemas
|
||||
- `app/user-guide.md` - guia de uso do runtime manager, selecao de modelos e chat
|
||||
- `app/backend-commands.md` - comandos Tauri expostos pelo backend do app
|
||||
|
||||
## Documentacao para desenvolvedores
|
||||
|
||||
- `developer/architecture.md` - mapa do workspace, relacao entre crates e fluxo entre API, CLI e app
|
||||
|
||||
## Como navegar
|
||||
|
||||
- Usuario final do app: comece em `app/user-guide.md`
|
||||
- Operacao da API/CLI: comece em `api/overview.md` e `cli/overview.md`
|
||||
- Contribuicao tecnica: comece em `developer/architecture.md`
|
||||
@@ -0,0 +1,101 @@
|
||||
# Configuracao do servidor
|
||||
|
||||
Esta pagina resume a configuracao atual do backend local do ForgeLM.
|
||||
|
||||
## Variaveis de ambiente principais
|
||||
|
||||
### Modelo e bind
|
||||
|
||||
- `LOCALLLM_MODEL` - caminho do arquivo `.gguf` a ser carregado
|
||||
- `LOCALLLM_ADDR` - endereco de bind do servidor, default `0.0.0.0:8080`
|
||||
- `LOCALLLM_MODEL_ALIASES` - aliases separados por virgula para o modelo canonico
|
||||
|
||||
### Perfil de runtime
|
||||
|
||||
- `LOCALLLM_PROFILE` - `balanced_9b`, `cpu_fallback` ou default `Turbo4B`
|
||||
- `LOCALLLM_GPU_LAYERS`
|
||||
- `LOCALLLM_CTX`
|
||||
- `LOCALLLM_BATCH`
|
||||
- `LOCALLLM_UBATCH`
|
||||
- `LOCALLLM_THREADS`
|
||||
- `LOCALLLM_THREADS_BATCH`
|
||||
|
||||
Esses campos sobrepoem os defaults do perfil selecionado.
|
||||
|
||||
## Perfis conhecidos
|
||||
|
||||
### Turbo4B
|
||||
|
||||
- `n_gpu_layers = 999`
|
||||
- `n_ctx = 4096`
|
||||
- `n_batch = 512`
|
||||
- `n_ubatch = 128`
|
||||
- `flash_attn = true`
|
||||
- `n_threads = 8`
|
||||
|
||||
### Balanced9B
|
||||
|
||||
- `n_gpu_layers = 999`
|
||||
- `n_ctx = 2048`
|
||||
- `n_batch = 256`
|
||||
- `n_ubatch = 64`
|
||||
- `flash_attn = true`
|
||||
- `n_threads = 8`
|
||||
|
||||
### CpuFallback
|
||||
|
||||
- `n_gpu_layers = 0`
|
||||
- `n_ctx = 2048`
|
||||
- `n_batch = 128`
|
||||
- `n_ubatch = 32`
|
||||
- `flash_attn = false`
|
||||
- `n_threads = available_parallelism()`
|
||||
|
||||
## Auth
|
||||
|
||||
- `LOCALLLM_API_KEY` - habilita auth por chave quando definido
|
||||
- `LOCALLLM_AUTH_HEADER` - nome do cabecalho preferencial; default `authorization`
|
||||
- `LOCALLLM_AUTH_SCHEME` - prefixo opcional para remover antes da comparacao
|
||||
|
||||
Se `LOCALLLM_API_KEY` estiver vazio ou ausente, a API funciona sem auth para `GET /v1/models` e `POST /v1/chat/completions`.
|
||||
|
||||
## CORS
|
||||
|
||||
- `LOCALLLM_CORS_ORIGINS` - lista separada por virgula
|
||||
|
||||
Comportamento atual:
|
||||
|
||||
- sem configuracao explicita, o servidor libera `*`
|
||||
- quando a variavel existe, o backend constroi uma allowlist literal
|
||||
|
||||
## Prompt de sistema e tool calling
|
||||
|
||||
- `LOCALLLM_SYSTEM_PROMPT` - prompt de sistema default injetado quando a request nao traz mensagem `system` ou `developer`
|
||||
- `LOCALLLM_ENABLE_TOOL_CALLS` - habilita/desabilita tool calling no servidor
|
||||
|
||||
## Exemplo de ambiente minimo
|
||||
|
||||
```bash
|
||||
set LOCALLLM_MODEL=D:\modelos\meu-modelo.gguf
|
||||
set LOCALLLM_ADDR=0.0.0.0:8080
|
||||
cargo run -p inference-server
|
||||
```
|
||||
|
||||
## Exemplo com auth
|
||||
|
||||
```bash
|
||||
set LOCALLLM_MODEL=D:\modelos\meu-modelo.gguf
|
||||
set LOCALLLM_API_KEY=dev-secret
|
||||
set LOCALLLM_AUTH_SCHEME=Bearer
|
||||
cargo run -p inference-server
|
||||
```
|
||||
|
||||
## Alias de modelos
|
||||
|
||||
Quando `LOCALLLM_MODEL_ALIASES` esta definido, o backend expoe aliases adicionais em `GET /v1/models`. Esses aliases apontam para o mesmo `root` do modelo canonico e sao resolvidos pelo backend durante a validacao do campo `model`.
|
||||
|
||||
## Observacoes operacionais
|
||||
|
||||
- o banner do servidor imprime `127.0.0.1:<porta>` como endereco recomendado para consumo local quando o bind usa `0.0.0.0`
|
||||
- o app Tauri usa readiness por `GET /health` ao iniciar o runtime local
|
||||
- o backend nao persiste configuracao propria em arquivo; a persistencia de runtime local do app acontece no backend Tauri, nao dentro do `inference-server`
|
||||
@@ -0,0 +1,225 @@
|
||||
# Endpoints HTTP
|
||||
|
||||
Esta pagina documenta a superficie HTTP publica atual do ForgeLM.
|
||||
|
||||
## Base URL
|
||||
|
||||
- default de bind: `0.0.0.0:8080`
|
||||
- endereco recomendado para consumo local: `http://127.0.0.1:8080`
|
||||
|
||||
Quando esta documentacao usa `127.0.0.1`, ela esta descrevendo o endereco tipico de consumo local, nao necessariamente o bind literal do processo.
|
||||
|
||||
## GET /health
|
||||
|
||||
Retorna um snapshot simples do estado do processo.
|
||||
|
||||
### Auth
|
||||
|
||||
- nao exige auth
|
||||
|
||||
### Exemplo
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8080/health
|
||||
```
|
||||
|
||||
### Resposta
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"model_loaded": true,
|
||||
"model_id": "meu-modelo",
|
||||
"uptime_secs": 42
|
||||
}
|
||||
```
|
||||
|
||||
### Observacoes
|
||||
|
||||
- hoje `model_loaded` funciona como um sinal operacional simples do processo em pe
|
||||
- o app desktop usa `GET /health` como parte do readiness check do runtime local
|
||||
|
||||
## GET /v1/models
|
||||
|
||||
Lista o modelo canonico e aliases conhecidos.
|
||||
|
||||
### Auth
|
||||
|
||||
- exige auth apenas se `LOCALLLM_API_KEY` estiver configurada
|
||||
|
||||
### Cabecalhos aceitos
|
||||
|
||||
- `Authorization: Bearer <token>`
|
||||
- `x-api-key: <token>`
|
||||
- ou o cabecalho custom configurado em `LOCALLLM_AUTH_HEADER`
|
||||
|
||||
### Exemplo
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8080/v1/models
|
||||
```
|
||||
|
||||
### Resposta
|
||||
|
||||
```json
|
||||
{
|
||||
"object": "list",
|
||||
"data": [
|
||||
{
|
||||
"id": "default",
|
||||
"object": "model",
|
||||
"created": 1710000000,
|
||||
"owned_by": "local",
|
||||
"root": "meu-modelo",
|
||||
"parent": "meu-modelo",
|
||||
"permission": []
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Observacoes
|
||||
|
||||
- `root` aponta para o modelo canonico
|
||||
- `parent` e usado quando um ID e alias do modelo canonico
|
||||
- o app desktop usa esse endpoint para preencher o seletor de modelo
|
||||
|
||||
## POST /v1/chat/completions
|
||||
|
||||
Endpoint principal de inferencia.
|
||||
|
||||
### Auth
|
||||
|
||||
- exige auth apenas se `LOCALLLM_API_KEY` estiver configurada
|
||||
|
||||
### Campos principais da request
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "default",
|
||||
"messages": [
|
||||
{ "role": "user", "content": "Explique este projeto" }
|
||||
],
|
||||
"max_tokens": 1024,
|
||||
"temperature": 0.15,
|
||||
"top_p": 0.95,
|
||||
"stream": false,
|
||||
"stop": [],
|
||||
"n": 1,
|
||||
"seed": null,
|
||||
"user": null,
|
||||
"response_format": null,
|
||||
"tools": [],
|
||||
"tool_choice": null,
|
||||
"parallel_tool_calls": null,
|
||||
"stream_options": null
|
||||
}
|
||||
```
|
||||
|
||||
### Defaults importantes
|
||||
|
||||
- `max_tokens`: `1024`
|
||||
- `temperature`: `0.15`
|
||||
- `top_p`: `0.95`
|
||||
- `n`: `1`
|
||||
|
||||
### Regras de validacao
|
||||
|
||||
- `model` deve existir no catalogo de modelos
|
||||
- `messages` nao pode ser vazio
|
||||
- `n` precisa ser `1`
|
||||
- `tools` podem ser rejeitadas se tool calling estiver desabilitado
|
||||
|
||||
### Exemplo sem streaming
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8080/v1/chat/completions \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "default",
|
||||
"messages": [{"role": "user", "content": "Diga ola"}],
|
||||
"stream": false
|
||||
}'
|
||||
```
|
||||
|
||||
### Resposta sem streaming
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "chatcmpl-...",
|
||||
"object": "chat.completion",
|
||||
"created": 1710000000,
|
||||
"model": "meu-modelo",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "Ola!"
|
||||
},
|
||||
"finish_reason": "stop"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 12,
|
||||
"completion_tokens": 8,
|
||||
"total_tokens": 20,
|
||||
"tokens_per_second": 31.5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Exemplo com streaming
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8080/v1/chat/completions \
|
||||
-H "Content-Type: application/json" \
|
||||
-N \
|
||||
-d '{
|
||||
"model": "default",
|
||||
"messages": [{"role": "user", "content": "Escreva um resumo"}],
|
||||
"stream": true,
|
||||
"stream_options": {"include_usage": true}
|
||||
}'
|
||||
```
|
||||
|
||||
### Streaming SSE
|
||||
|
||||
O backend envia eventos `data: ...` no formato `chat.completion.chunk` e termina com:
|
||||
|
||||
```text
|
||||
data: [DONE]
|
||||
```
|
||||
|
||||
O ultimo chunk pode incluir `usage` se `include_usage=true`.
|
||||
|
||||
### Erros
|
||||
|
||||
Exemplo de payload de erro:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"message": "Only n=1 is currently supported",
|
||||
"type": "invalid_request_error",
|
||||
"param": "n",
|
||||
"code": "unsupported_value"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Limitacoes atuais
|
||||
|
||||
- o servidor nao implementa toda a plataforma OpenAI
|
||||
- `parallel_tool_calls` nao deve ser tratado como recurso plenamente suportado
|
||||
- o campo `content` de mensagens pode aceitar arrays de partes textuais, mas o backend reduz isso a texto consolidado
|
||||
- reasoning nativo nao aparece como campo separado na API HTTP; o app desktop separa `<think>...</think>` no frontend
|
||||
|
||||
## Codigos de status mais comuns
|
||||
|
||||
- `200 OK` - sucesso
|
||||
- `400 Bad Request` - payload invalido ou modo nao suportado
|
||||
- `401 Unauthorized` - chave ausente/invalida quando auth esta habilitada
|
||||
- `404 Not Found` - modelo nao encontrado
|
||||
|
||||
Para configuracao do servidor e variaveis de ambiente, veja `configuration.md`.
|
||||
@@ -0,0 +1,121 @@
|
||||
# Visao geral da API e backend
|
||||
|
||||
O backend do ForgeLM e um servidor HTTP local escrito em Rust, montado sobre Axum e conectado a uma engine de inferencia em `inference-core`.
|
||||
|
||||
## Componentes principais
|
||||
|
||||
- `crates/inference-server` - inicializacao do servidor, leitura de configuracao por variaveis de ambiente e roteamento HTTP
|
||||
- `crates/api-contracts` - tipos de request/response para chat, health, models e erros
|
||||
- `crates/inference-core` - engine, sessoes, perfis de runtime e sampler
|
||||
- `crates/metrics` - contadores de throughput e metricas de geracao
|
||||
|
||||
## Endpoints publicos
|
||||
|
||||
Hoje o servidor expoe:
|
||||
|
||||
- `GET /health`
|
||||
- `GET /v1/models`
|
||||
- `POST /v1/chat/completions`
|
||||
|
||||
Essa superficie e pequena de proposito: o foco atual do projeto esta em chat local, descoberta de modelos e integracao com o runtime manager do app.
|
||||
|
||||
## Inicializacao do servidor
|
||||
|
||||
O binario principal do backend esta em `crates/inference-server/src/main.rs`.
|
||||
|
||||
Na inicializacao, o servidor:
|
||||
|
||||
1. configura tracing/logs
|
||||
2. le variaveis de ambiente como `LOCALLLM_MODEL`, `LOCALLLM_PROFILE`, `LOCALLLM_ADDR`, `LOCALLLM_GPU_LAYERS` e `LOCALLLM_CTX`
|
||||
3. cria a configuracao da engine a partir do perfil selecionado
|
||||
4. carrega e aquece o modelo (`warmup()`)
|
||||
5. monta o router com CORS e estado compartilhado
|
||||
6. faz bind no endereco configurado e serve as rotas HTTP
|
||||
|
||||
## Perfil de runtime
|
||||
|
||||
Os perfis atuais ficam em `crates/inference-core/src/profile.rs`:
|
||||
|
||||
- `Turbo4B` - foco em throughput, contexto moderado e uso de GPU agressivo
|
||||
- `Balanced9B` - equilibrio entre qualidade e custo
|
||||
- `CpuFallback` - fallback para maquinas sem GPU
|
||||
|
||||
Esses perfis definem defaults como `n_gpu_layers`, `n_ctx`, `n_batch`, `n_ubatch`, `flash_attn` e `n_threads`.
|
||||
|
||||
## Auth e CORS
|
||||
|
||||
A configuracao de compatibilidade HTTP mora em `crates/inference-server/src/compat.rs`.
|
||||
|
||||
- auth e opcional; se `LOCALLLM_API_KEY` nao estiver configurada, a API aceita requests sem chave
|
||||
- `GET /health` nao passa por verificacao de auth
|
||||
- `GET /v1/models` e `POST /v1/chat/completions` passam por `authorize_request()`
|
||||
- CORS aceita `*` por default ou uma lista configuravel por `LOCALLLM_CORS_ORIGINS`
|
||||
|
||||
Cabecalhos aceitos para auth:
|
||||
|
||||
- cabecalho configurado em `LOCALLLM_AUTH_HEADER` (default: `authorization`)
|
||||
- `Authorization`
|
||||
- `x-api-key`
|
||||
|
||||
Se `LOCALLLM_AUTH_SCHEME` estiver configurado, o backend tenta remover esse prefixo antes de comparar a chave.
|
||||
|
||||
## Catalogo de modelos
|
||||
|
||||
O backend monta um catalogo de modelos em memoria a partir do nome canonico do modelo carregado e de aliases opcionais configurados por `LOCALLLM_MODEL_ALIASES`.
|
||||
|
||||
Regras importantes:
|
||||
|
||||
- o modelo carregado vira o ID canonico principal
|
||||
- aliases adicionais podem apontar para o mesmo `root`
|
||||
- `local-model` e `default` entram como aliases comuns quando possivel
|
||||
- `GET /v1/models` retorna tanto o canonico quanto os aliases conhecidos
|
||||
|
||||
## Chat completions
|
||||
|
||||
O endpoint de chat aceita mensagens em formato semelhante ao da OpenAI, com suporte para:
|
||||
|
||||
- roles `system`, `developer`, `user`, `assistant` e `tool`
|
||||
- `stream: true|false`
|
||||
- `stop` como string unica, array de strings ou `null`
|
||||
- `response_format`
|
||||
- `tools` e `tool_choice`
|
||||
- `stream_options.include_usage`
|
||||
|
||||
O servidor, porem, continua com escopo limitado. Alguns campos sao aceitos por compatibilidade de contrato, mas isso nao significa paridade total com a plataforma OpenAI.
|
||||
|
||||
## Streaming
|
||||
|
||||
No modo `stream`, o backend usa SSE e envia chunks no formato `chat.completion.chunk`.
|
||||
|
||||
Dois modos de streaming existem internamente:
|
||||
|
||||
- `LiveTokens` - emite tokens incrementais quando o fluxo suporta token streaming
|
||||
- `Buffered` - produz a resposta inteira e a entrega em blocos compativeis
|
||||
|
||||
O chunk final pode incluir `usage` quando `stream_options.include_usage=true`.
|
||||
|
||||
## Erros e validacao
|
||||
|
||||
Os erros seguem `ErrorResponse { error: ApiError }` com:
|
||||
|
||||
- `message`
|
||||
- `type`
|
||||
- `param` opcional
|
||||
- `code` opcional
|
||||
|
||||
Validacoes conhecidas:
|
||||
|
||||
- `model` inexistente retorna `model_not_found`
|
||||
- `messages` vazia retorna `empty_messages`
|
||||
- `n != 1` retorna `unsupported_value`
|
||||
- `tools` com tool calls desabilitadas retorna `tool_calls_disabled`
|
||||
|
||||
## Limitacoes atuais
|
||||
|
||||
- nao ha endpoints publicos para embeddings, uploads, files ou responses API
|
||||
- `n` diferente de `1` nao e suportado
|
||||
- `response_format` e tool calling passam por compatibilidade de prompt/pos-processamento, nao por enforcement forte de decoder
|
||||
- `parallel_tool_calls` existe no contrato, mas nao deve ser tratado como capacidade plena documentada
|
||||
- `GET /health` e um health check operacional; nao e uma prova profunda de qualidade do modelo
|
||||
|
||||
Para referencia detalhada de requests e respostas, siga para `endpoints.md` e `configuration.md`.
|
||||
@@ -0,0 +1,116 @@
|
||||
# Comandos backend do app desktop
|
||||
|
||||
O backend Tauri exposto ao frontend vive principalmente em `tauri-app/src-tauri/src/lib.rs`.
|
||||
|
||||
Esta pagina documenta os comandos que o frontend usa para runtime, modelos e diagnostico.
|
||||
|
||||
## Runtime manager
|
||||
|
||||
### `bootstrap_runtime_command`
|
||||
|
||||
Carrega a configuracao persistida, reconstrui o snapshot do runtime e pode iniciar o runtime local automaticamente quando a politica e `on_app_launch` e o modo e `local`.
|
||||
|
||||
### `get_runtime_snapshot_command`
|
||||
|
||||
Retorna o `RuntimeSnapshot` atual com:
|
||||
|
||||
- `status`
|
||||
- `ready`
|
||||
- `process_running`
|
||||
- `resolved_url`
|
||||
- `binary_path`
|
||||
- `last_error`
|
||||
- `config`
|
||||
|
||||
### `save_runtime_config_command_handler`
|
||||
|
||||
Persiste `RuntimeConfig` e atualiza o estado backend usado pelo runtime manager.
|
||||
|
||||
Importante:
|
||||
|
||||
- se o processo local estiver rodando e a mudanca exigir restart, o backend pode recusar a alteracao com erro `restart_required`
|
||||
|
||||
### `start_runtime_command`
|
||||
|
||||
Inicia o runtime local usando a configuracao atualmente salva no backend Tauri.
|
||||
|
||||
### `stop_runtime_command`
|
||||
|
||||
Para o runtime local e atualiza o snapshot.
|
||||
|
||||
## GPU e modelos
|
||||
|
||||
### `query_gpu`
|
||||
|
||||
Usa `nvidia-smi` para detectar GPU NVIDIA e sugerir `recommended_layers`.
|
||||
|
||||
### `scan_models(dir)`
|
||||
|
||||
Escaneia um diretorio em busca de arquivos `.gguf`.
|
||||
|
||||
### `pick_models_dir`
|
||||
|
||||
Abre seletor nativo de pasta e devolve o diretorio escolhido junto com os modelos encontrados.
|
||||
|
||||
### `pick_model_files`
|
||||
|
||||
Abre seletor nativo de arquivos para escolher um ou mais `.gguf`.
|
||||
|
||||
### `import_model(src_path, dest_dir)`
|
||||
|
||||
Copia um arquivo `.gguf` para um diretorio de modelos.
|
||||
|
||||
## Configuracao e paths
|
||||
|
||||
### `save_config`
|
||||
|
||||
Compatibilidade legada para salvar `RuntimeConfig` em arquivo.
|
||||
|
||||
### `load_config`
|
||||
|
||||
Leitura da configuracao persistida.
|
||||
|
||||
### `find_server_binary`
|
||||
|
||||
Resolve o caminho do binario `localllm` para diagnostico e start local.
|
||||
|
||||
### `get_app_data_dir`
|
||||
|
||||
Retorna o diretorio de dados do app.
|
||||
|
||||
## Comandos legados de compatibilidade
|
||||
|
||||
O backend ainda expoe:
|
||||
|
||||
- `start_server`
|
||||
- `stop_server`
|
||||
- `server_status`
|
||||
|
||||
Esses comandos existem como shims de compatibilidade. O fluxo principal do frontend atual deve preferir o runtime manager unificado (`bootstrap_runtime_command`, `get_runtime_snapshot_command`, `save_runtime_config_command_handler`, `start_runtime_command`, `stop_runtime_command`).
|
||||
|
||||
## Tipos principais
|
||||
|
||||
### `RuntimeConfig`
|
||||
|
||||
Campos relevantes:
|
||||
|
||||
- `connection_mode`
|
||||
- `start_policy`
|
||||
- `server_url`
|
||||
- `api_key`
|
||||
- `model_path`
|
||||
- `models_dir`
|
||||
- `addr`
|
||||
- `gpu_layers`
|
||||
- `ctx_size`
|
||||
- `extra_model_paths`
|
||||
|
||||
### `RuntimeSnapshot`
|
||||
|
||||
Representa o estado serializado usado pelo frontend para desenhar o runtime card, drawer e logica de start/stop.
|
||||
|
||||
## Observacoes importantes
|
||||
|
||||
- o backend Tauri e a source of truth da configuracao persistida do runtime do app
|
||||
- o frontend usa `useRuntimeManager()` para consumir essa superficie de comandos
|
||||
- readiness do runtime local depende de `GET /health`, nao apenas de socket aberto
|
||||
@@ -0,0 +1,114 @@
|
||||
# Visao geral do app desktop
|
||||
|
||||
O app desktop do ForgeLM vive em `tauri-app/` e combina:
|
||||
|
||||
- frontend React/Vite
|
||||
- backend Tauri em Rust
|
||||
- runtime manager para API local/remota
|
||||
- chat persistente com banco local em memoria exportado para `localStorage`
|
||||
|
||||
## Funcao do app
|
||||
|
||||
O app foi desenhado para ser a interface principal de uso do runtime local. Ele permite:
|
||||
|
||||
- iniciar ou parar a API local quando o modo e `local`
|
||||
- apontar para uma API existente quando o modo e `remote`
|
||||
- escolher/importar modelos `.gguf`
|
||||
- conversar com o backend via `POST /v1/chat/completions`
|
||||
- persistir historico de chats e mensagens
|
||||
- separar trechos de reasoning (`<think>...</think>`) da resposta final no frontend
|
||||
|
||||
## Arquitetura em alto nivel
|
||||
|
||||
### Frontend
|
||||
|
||||
Arquivos principais:
|
||||
|
||||
- `src/App.tsx` - shell principal do app
|
||||
- `src/components/Sidebar.tsx` - sidebar com runtime card, seletor de modelo e lista de chats
|
||||
- `src/components/ChatView.tsx` - fluxo de chat, streaming, memoria e persistencia de mensagens
|
||||
- `src/features/runtime/*` - runtime manager unificado
|
||||
|
||||
### Backend Tauri
|
||||
|
||||
Arquivos principais:
|
||||
|
||||
- `src-tauri/src/lib.rs` - comandos Tauri expostos ao frontend
|
||||
- `src-tauri/src/runtime/*` - estado, config, spawn, health probe e snapshot do runtime local
|
||||
|
||||
## Runtime manager
|
||||
|
||||
O runtime manager e a peca central do app.
|
||||
|
||||
Estados principais:
|
||||
|
||||
- `stopped`
|
||||
- `starting`
|
||||
- `ready`
|
||||
- `degraded`
|
||||
- `stopping`
|
||||
- `error`
|
||||
|
||||
Modos de conexao:
|
||||
|
||||
- `local` - o app controla o processo do backend
|
||||
- `remote` - o app so consome uma API externa ja existente
|
||||
|
||||
O frontend usa `useRuntimeManager()` como source of truth para:
|
||||
|
||||
- snapshot atual do runtime
|
||||
- URL resolvida da API
|
||||
- save de config
|
||||
- start/stop do runtime local
|
||||
|
||||
## Selecao de modelos
|
||||
|
||||
O app carrega modelos via `GET /v1/models` usando `useModels()`.
|
||||
|
||||
Comportamentos importantes:
|
||||
|
||||
- se nao houver endpoint configurado, o estado fica em erro e a lista e limpa
|
||||
- se a API responder sem modelos, o model selector fica vazio
|
||||
- se o modelo antes selecionado nao existir mais na lista, o app seleciona o primeiro disponivel
|
||||
|
||||
## Persistencia local
|
||||
|
||||
O chat usa `sql.js` com schema local gerenciado por `src/lib/db.ts`.
|
||||
|
||||
Tabelas principais:
|
||||
|
||||
- `chats`
|
||||
- `messages`
|
||||
|
||||
Campos persistidos por mensagem incluem:
|
||||
|
||||
- `role`
|
||||
- `content`
|
||||
- `reasoning_content`
|
||||
- `prompt_tokens`
|
||||
- `completion_tokens`
|
||||
- `total_tokens`
|
||||
- `tokens_per_second`
|
||||
|
||||
Importante: isso nao e um banco nativo do sistema operacional. O app injeta `sql.js` por CDN e persiste a exportacao do banco em `localStorage`.
|
||||
|
||||
## Chat e streaming
|
||||
|
||||
`ChatView.tsx` envia requests para `POST /v1/chat/completions`.
|
||||
|
||||
Recursos atuais:
|
||||
|
||||
- streaming opcional
|
||||
- memoria opcional com ate 20 mensagens recentes
|
||||
- separacao visual de reasoning (`<think>...</think>`) no frontend
|
||||
- contadores de tokens por mensagem e por chat
|
||||
- edicao, reenvio e exclusao de mensagens
|
||||
|
||||
## Limitacoes atuais
|
||||
|
||||
- o app depende de um binario `localllm` acessivel quando o modo local e usado
|
||||
- o fallback browser-only nao substitui os recursos desktop do Tauri
|
||||
- o chat depende da pequena API HTTP atual; o app nao expoe magica propria fora dela
|
||||
- o runtime manager faz polling periodico do snapshot; ele nao usa ainda um fluxo completo de eventos push
|
||||
|
||||
Para uso pratico, siga para `user-guide.md`.
|
||||
@@ -0,0 +1,135 @@
|
||||
# Guia de uso do app desktop
|
||||
|
||||
Este guia cobre o fluxo de uso do app Tauri no estado atual do projeto.
|
||||
|
||||
## 1. Abrir o app
|
||||
|
||||
Em desenvolvimento:
|
||||
|
||||
```bash
|
||||
cd tauri-app
|
||||
npm install
|
||||
npm run tauri dev
|
||||
```
|
||||
|
||||
## 2. Entender os modos de conexao
|
||||
|
||||
O Runtime Manager suporta dois modos.
|
||||
|
||||
### Local API
|
||||
|
||||
Use quando o app deve subir e controlar o backend local.
|
||||
|
||||
Voce configura:
|
||||
|
||||
- pasta de modelos
|
||||
- modelo selecionado
|
||||
- endereco de bind (`addr`)
|
||||
- numero de GPU layers
|
||||
- contexto (`ctx_size`)
|
||||
- politica de auto-start
|
||||
|
||||
### Remote API
|
||||
|
||||
Use quando a API ja esta rodando em outro lugar.
|
||||
|
||||
Voce configura:
|
||||
|
||||
- `server_url`
|
||||
- `api_key` opcional
|
||||
|
||||
Nesse modo o app nao tenta iniciar/parar o backend local.
|
||||
|
||||
## 3. Configurar o runtime local
|
||||
|
||||
Na sidebar, abra `Manage` ou o icone de configuracao.
|
||||
|
||||
Fluxo recomendado:
|
||||
|
||||
1. deixe `Connection mode` em `Local API`
|
||||
2. escolha a pasta de modelos com `Browse`, ou adicione arquivos individuais com `Add files`
|
||||
3. selecione o modelo desejado
|
||||
4. ajuste `Listen address`, `GPU layers` e `Context size` se necessario
|
||||
5. use `Save settings` ou `Save and start local API`
|
||||
|
||||
Observacoes:
|
||||
|
||||
- o app tenta descobrir o binario do backend automaticamente
|
||||
- se uma revarredura da pasta vier vazia, o app preserva o `model_path` salvo em vez de limpar a selecao imediatamente
|
||||
- o start local so fica disponivel quando existe binario e modelo selecionado
|
||||
|
||||
## 4. Configurar API remota
|
||||
|
||||
1. abra o Runtime Manager
|
||||
2. mude para `Remote API`
|
||||
3. preencha `Remote server URL`
|
||||
4. opcionalmente, preencha `API key`
|
||||
5. salve a configuracao
|
||||
|
||||
Depois disso, o app passa a usar essa URL para `GET /v1/models` e `POST /v1/chat/completions`.
|
||||
|
||||
## 5. Selecionar modelos no app
|
||||
|
||||
Quando a API estiver acessivel:
|
||||
|
||||
- o seletor de modelo na sidebar sera preenchido por `GET /v1/models`
|
||||
- o app tenta manter a selecao atual quando possivel
|
||||
- se o modelo sumir da API, o app troca para o primeiro disponivel
|
||||
|
||||
## 6. Conversar no chat
|
||||
|
||||
O fluxo principal fica em `ChatView`.
|
||||
|
||||
Recursos de uso:
|
||||
|
||||
- streaming on/off
|
||||
- memory on/off
|
||||
- historico persistente por conversa
|
||||
- edicao e reenvio de mensagens do usuario
|
||||
- edicao de resposta do assistente
|
||||
- copia de conteudo/markdown/codigo
|
||||
|
||||
## 7. Thinking e tokens
|
||||
|
||||
Quando a resposta inclui blocos `<think>...</think>`:
|
||||
|
||||
- o app separa esse conteudo como `Thinking`
|
||||
- o painel de thinking pode ser expandido/recolhido
|
||||
- a resposta final aparece separadamente do thinking
|
||||
|
||||
Metricas visiveis:
|
||||
|
||||
- tokens enviados (`Sent`)
|
||||
- tokens gerados (`Generated`)
|
||||
- total por mensagem e por chat
|
||||
- `tok/s` quando informado pela API
|
||||
|
||||
## 8. Troubleshooting rapido
|
||||
|
||||
### "Configure a local or remote API before sending messages"
|
||||
|
||||
O app esta sem endpoint valido. Abra o Runtime Manager e configure modo local ou remoto.
|
||||
|
||||
### Nenhum modelo aparece
|
||||
|
||||
- confirme que a API esta acessivel
|
||||
- use o botao de refresh da sidebar
|
||||
- no modo local, confirme que o modelo salvo foi iniciado corretamente
|
||||
|
||||
### O start local esta desabilitado
|
||||
|
||||
Verifique:
|
||||
|
||||
- se o binario do backend foi encontrado
|
||||
- se um modelo esta salvo/selecionado
|
||||
- se voce nao esta em modo remoto
|
||||
|
||||
### O runtime sobe mas nunca fica pronto
|
||||
|
||||
O app usa readiness por `GET /health`. Se a API local nao passar nesse check dentro do timeout, o runtime manager marca erro.
|
||||
|
||||
## 9. Persistencia e cuidado com dados
|
||||
|
||||
- chats e mensagens ficam no armazenamento local do app/frontend
|
||||
- o app nao implementa sincronizacao remota de conversas
|
||||
- apagar dados do navegador/webview pode remover o historico local
|
||||
@@ -0,0 +1,235 @@
|
||||
# Referencia de comandos da CLI
|
||||
|
||||
Esta pagina lista a superficie atual da CLI `localllm`.
|
||||
|
||||
## Sintaxe geral
|
||||
|
||||
```bash
|
||||
localllm [flags-globais] <comando> [subcomando] [args]
|
||||
```
|
||||
|
||||
## Flags globais
|
||||
|
||||
- `--server <url>`
|
||||
- `--dry-run`
|
||||
- `--api-key <token>`
|
||||
- `--models-dir <path>`
|
||||
- `--format text|json`
|
||||
|
||||
## status
|
||||
|
||||
Verifica o estado do backend.
|
||||
|
||||
```bash
|
||||
localllm status
|
||||
```
|
||||
|
||||
Uso tipico:
|
||||
|
||||
- testar se o backend esta de pe
|
||||
- validar auth e reachability
|
||||
- integrar checks simples em scripts
|
||||
|
||||
## models
|
||||
|
||||
### models list
|
||||
|
||||
Lista os modelos expostos pelo backend.
|
||||
|
||||
```bash
|
||||
localllm models list
|
||||
```
|
||||
|
||||
### models scan
|
||||
|
||||
Escaneia um diretorio local de modelos.
|
||||
|
||||
```bash
|
||||
localllm --models-dir ./models models scan
|
||||
```
|
||||
|
||||
### models load
|
||||
|
||||
Aceita um nome de modelo e alias opcional.
|
||||
|
||||
```bash
|
||||
localllm models load meu-modelo.gguf --alias default
|
||||
```
|
||||
|
||||
### models unload
|
||||
|
||||
Aceita um modelo opcional.
|
||||
|
||||
```bash
|
||||
localllm models unload
|
||||
localllm models unload default
|
||||
```
|
||||
|
||||
### models use
|
||||
|
||||
Seleciona um modelo por nome.
|
||||
|
||||
```bash
|
||||
localllm models use default
|
||||
```
|
||||
|
||||
### models watch
|
||||
|
||||
Superficie prevista para acompanhar alteracoes/model lifecycle.
|
||||
|
||||
```bash
|
||||
localllm models watch
|
||||
```
|
||||
|
||||
### models download
|
||||
|
||||
Aceita um repositorio como argumento.
|
||||
|
||||
```bash
|
||||
localllm models download org/modelo
|
||||
```
|
||||
|
||||
### models remove
|
||||
|
||||
Remove um modelo por nome.
|
||||
|
||||
```bash
|
||||
localllm models remove default
|
||||
```
|
||||
|
||||
### Observacao importante sobre `models`
|
||||
|
||||
No estado atual do projeto, a parte mais confiavel e comprovada contra o backend HTTP atual e `models list`. Os demais subcomandos devem ser tratados como superficie de operacao em evolucao, local-only ou ainda nao suportada pelo backend publico atual.
|
||||
|
||||
## auth
|
||||
|
||||
### auth status
|
||||
|
||||
```bash
|
||||
localllm auth status
|
||||
```
|
||||
|
||||
### auth enable
|
||||
|
||||
```bash
|
||||
localllm auth enable --mode protected --api-key dev-secret
|
||||
```
|
||||
|
||||
Modos aceitos:
|
||||
|
||||
- `off`
|
||||
- `localonly`
|
||||
- `protected`
|
||||
|
||||
### auth disable
|
||||
|
||||
```bash
|
||||
localllm auth disable
|
||||
```
|
||||
|
||||
### auth set-key
|
||||
|
||||
```bash
|
||||
localllm auth set-key dev-secret
|
||||
```
|
||||
|
||||
### Observacao importante sobre `auth`
|
||||
|
||||
Os subcomandos existem na superficie da CLI, mas o backend HTTP publico atual nao expoe uma API administrativa completa para auth. Documente esses comandos como superficie de controle/planejamento, nao como garantia de operacao remota ja fechada.
|
||||
|
||||
## config
|
||||
|
||||
### config get
|
||||
|
||||
```bash
|
||||
localllm config get <chave>
|
||||
```
|
||||
|
||||
### config set
|
||||
|
||||
```bash
|
||||
localllm config set <chave> <valor>
|
||||
```
|
||||
|
||||
Mesma observacao de `auth`: a superficie existe, mas a administracao remota completa ainda nao esta refletida na pequena API HTTP publica atual.
|
||||
|
||||
## bench
|
||||
|
||||
### bench throughput
|
||||
|
||||
Benchmark de throughput com parametros configuraveis.
|
||||
|
||||
```bash
|
||||
localllm bench throughput --model default --samples 3 --prompt-tokens 256 --completion-tokens 128
|
||||
```
|
||||
|
||||
Parametros atuais:
|
||||
|
||||
- `--model` (default `default`)
|
||||
- `--samples` (default `3`)
|
||||
- `--prompt-tokens` (default `256`)
|
||||
- `--completion-tokens` (default `128`)
|
||||
|
||||
### bench smoke
|
||||
|
||||
```bash
|
||||
localllm bench smoke
|
||||
```
|
||||
|
||||
### bench suite
|
||||
|
||||
```bash
|
||||
localllm bench suite
|
||||
```
|
||||
|
||||
### bench compare
|
||||
|
||||
```bash
|
||||
localllm bench compare baseline candidate
|
||||
```
|
||||
|
||||
### Observacao importante sobre `bench`
|
||||
|
||||
O fluxo mais claramente alinhado com o backend atual e `bench throughput`.
|
||||
|
||||
## logs
|
||||
|
||||
Leitura de logs com limite de linhas.
|
||||
|
||||
```bash
|
||||
localllm logs --lines 200
|
||||
```
|
||||
|
||||
## doctor
|
||||
|
||||
Superficie pensada para diagnostico do ambiente.
|
||||
|
||||
```bash
|
||||
localllm doctor
|
||||
```
|
||||
|
||||
## Exemplos com flags globais
|
||||
|
||||
### JSON
|
||||
|
||||
```bash
|
||||
localllm --format json status
|
||||
```
|
||||
|
||||
### Dry run
|
||||
|
||||
```bash
|
||||
localllm --dry-run models list
|
||||
```
|
||||
|
||||
### Backend remoto com auth
|
||||
|
||||
```bash
|
||||
localllm --server http://127.0.0.1:8080 --api-key dev-secret status
|
||||
```
|
||||
|
||||
## Resumo honesto do estado atual
|
||||
|
||||
- parser e superficie de comandos sao mais amplos que a API HTTP publica atual
|
||||
- para automacao confiavel hoje, priorize `status`, `models list` e `bench throughput`
|
||||
- use `--dry-run` quando estiver explorando comandos administrativos ainda em evolucao
|
||||
@@ -0,0 +1,104 @@
|
||||
# Visao geral da CLI
|
||||
|
||||
O binario `localllm` e a interface de linha de comando do projeto. Ele foi desenhado para diagnostico, automacao e operacao do backend local, com suporte a saida em texto ou JSON.
|
||||
|
||||
## Onde esta a CLI
|
||||
|
||||
- codigo: `crates/localllm-cli/src/main.rs`
|
||||
- nome do binario: `localllm`
|
||||
|
||||
## Flags globais
|
||||
|
||||
As flags globais atuais sao:
|
||||
|
||||
- `--server` - base URL do backend, default `http://127.0.0.1:8080`
|
||||
- `--dry-run` - mostra a acao planejada sem executar a chamada real
|
||||
- `--api-key` - chave de auth opcional
|
||||
- `--models-dir` - diretorio local de modelos, default `./models`
|
||||
- `--format text|json` - formato de saida
|
||||
|
||||
## Superficie de comandos
|
||||
|
||||
Comandos raiz atuais:
|
||||
|
||||
- `status`
|
||||
- `models`
|
||||
- `auth`
|
||||
- `config`
|
||||
- `bench`
|
||||
- `logs`
|
||||
- `doctor`
|
||||
|
||||
## Filosofia atual
|
||||
|
||||
A CLI hoje mistura tres tipos de fluxo:
|
||||
|
||||
- comandos com execucao HTTP real contra o backend atual
|
||||
- comandos locais/de operacao previstos para uma superficie maior de controle
|
||||
- comandos que ja possuem parsing e planejamento, mas ainda nao estao todos ligados a uma acao remota completa
|
||||
|
||||
Essa distincao importa para documentacao: a CLI tem uma superficie ampla, mas a parte realmente comprovada contra o backend HTTP atual e menor.
|
||||
|
||||
## O que esta mais consolidado hoje
|
||||
|
||||
Os fluxos mais maduros no estado atual do repositorio sao:
|
||||
|
||||
- `status`
|
||||
- `models list`
|
||||
- `bench throughput`
|
||||
|
||||
Esses fluxos fazem mais sentido quando o backend `inference-server` esta rodando.
|
||||
|
||||
## Formatos de saida
|
||||
|
||||
### Texto
|
||||
|
||||
Bom para uso humano, leitura manual e diagnostico rapido.
|
||||
|
||||
### JSON
|
||||
|
||||
Bom para scripts, CI e integracoes. Use `--format json`.
|
||||
|
||||
## Dry run
|
||||
|
||||
Use `--dry-run` quando quiser validar qual URL, qual operacao ou qual tipo de acao a CLI pretende executar sem realmente disparar a operacao.
|
||||
|
||||
Exemplo:
|
||||
|
||||
```bash
|
||||
cargo run -p localllm-cli -- --dry-run status
|
||||
```
|
||||
|
||||
## Exemplos rapidos
|
||||
|
||||
### Verificar saude do backend
|
||||
|
||||
```bash
|
||||
cargo run -p localllm-cli -- status
|
||||
```
|
||||
|
||||
### Listar modelos via API
|
||||
|
||||
```bash
|
||||
cargo run -p localllm-cli -- models list
|
||||
```
|
||||
|
||||
### Rodar benchmark de throughput
|
||||
|
||||
```bash
|
||||
cargo run -p localllm-cli -- bench throughput --samples 3 --prompt-tokens 256 --completion-tokens 128
|
||||
```
|
||||
|
||||
### Usar auth
|
||||
|
||||
```bash
|
||||
cargo run -p localllm-cli -- --api-key dev-secret status
|
||||
```
|
||||
|
||||
## Limitacoes atuais
|
||||
|
||||
- nem todos os subcomandos do parser correspondem a capacidades HTTP publicas do backend atual
|
||||
- a CLI foi expandida por etapas; por isso alguns comandos sao melhor entendidos como superficie de controle em evolucao
|
||||
- documente e use os comandos de operacao real com mais confianca em `status`, `models list` e `bench throughput`
|
||||
|
||||
Para a referencia completa, siga para `commands.md`.
|
||||
@@ -0,0 +1,140 @@
|
||||
# Arquitetura do projeto
|
||||
|
||||
Esta pagina resume a arquitetura atual do workspace ForgeLM para quem vai manter ou evoluir o sistema.
|
||||
|
||||
## Mapa do workspace Rust
|
||||
|
||||
O `Cargo.toml` raiz declara os membros:
|
||||
|
||||
- `crates/llama-sys`
|
||||
- `crates/inference-core`
|
||||
- `crates/inference-server`
|
||||
- `crates/api-contracts`
|
||||
- `crates/metrics`
|
||||
- `crates/localllm-cli`
|
||||
|
||||
O app desktop fica fora do workspace Rust principal, em `tauri-app/`, mas conversa diretamente com esse ecossistema por binario, comandos Tauri e HTTP local.
|
||||
|
||||
## Responsabilidade de cada modulo
|
||||
|
||||
### `api-contracts`
|
||||
|
||||
Tipos compartilhados para:
|
||||
|
||||
- chat completions
|
||||
- model listing
|
||||
- health
|
||||
- payloads de erro
|
||||
|
||||
Serve como contrato comum entre `inference-server` e consumidores da API.
|
||||
|
||||
### `inference-core`
|
||||
|
||||
Responsavel pela engine de inferencia local:
|
||||
|
||||
- carga do modelo
|
||||
- sessao de inferencia
|
||||
- sampler
|
||||
- perfis de runtime
|
||||
|
||||
### `inference-server`
|
||||
|
||||
Camada HTTP baseada em Axum:
|
||||
|
||||
- leitura de env vars
|
||||
- montagem de `ServerConfig`
|
||||
- auth, CORS e aliases de modelos
|
||||
- endpoints `/health`, `/v1/models`, `/v1/chat/completions`
|
||||
|
||||
### `localllm-cli`
|
||||
|
||||
CLI de operacao e automacao. Hoje ela ja tem uma superficie ampla, mas a parte com execucao real comprovada contra o backend publico atual esta mais concentrada em `status`, `models list` e `bench throughput`.
|
||||
|
||||
### `metrics`
|
||||
|
||||
Contadores e registros de throughput/token usage usados no backend.
|
||||
|
||||
### `llama-sys`
|
||||
|
||||
Bindings e integracao de baixo nivel com a stack de inferencia.
|
||||
|
||||
### `tauri-app`
|
||||
|
||||
App desktop composto por:
|
||||
|
||||
- frontend React/Vite
|
||||
- backend Tauri em Rust
|
||||
- runtime manager local/remoto
|
||||
- chat persistente com `sql.js`
|
||||
|
||||
## Fluxo entre API, CLI e app
|
||||
|
||||
## 1. Backend HTTP
|
||||
|
||||
`inference-server` sobe, carrega o modelo e expoe a API HTTP.
|
||||
|
||||
## 2. CLI
|
||||
|
||||
A CLI pode falar com a API HTTP por URL configurada via `--server` e `--api-key`.
|
||||
|
||||
## 3. App desktop
|
||||
|
||||
O app usa duas camadas:
|
||||
|
||||
- backend Tauri para gerenciar processo, configuracao e integracoes locais
|
||||
- frontend React para runtime manager, selecao de modelos e chat
|
||||
|
||||
Quando em modo local, o app inicia/para o backend por meio do runtime manager do Tauri. Quando em modo remoto, o app apenas consome uma URL externa.
|
||||
|
||||
## Runtime manager do app
|
||||
|
||||
Arquivos centrais:
|
||||
|
||||
- `tauri-app/src/features/runtime/useRuntimeManager.ts`
|
||||
- `tauri-app/src/features/runtime/types.ts`
|
||||
- `tauri-app/src/features/runtime/components/RuntimeStatusCard.tsx`
|
||||
- `tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx`
|
||||
- `tauri-app/src-tauri/src/runtime/*`
|
||||
|
||||
Conceitos importantes:
|
||||
|
||||
- `RuntimeConfig` e persistido no backend Tauri
|
||||
- `RuntimeSnapshot` e consumido pelo frontend
|
||||
- modo `local` e `remote` compartilham a mesma superficie de configuracao
|
||||
- readiness do modo local depende de `GET /health`
|
||||
|
||||
## Chat e persistencia
|
||||
|
||||
Arquivos centrais:
|
||||
|
||||
- `tauri-app/src/components/ChatView.tsx`
|
||||
- `tauri-app/src/components/MessageBubble.tsx`
|
||||
- `tauri-app/src/lib/db.ts`
|
||||
- `tauri-app/src/lib/chat.ts`
|
||||
|
||||
Caracteristicas importantes:
|
||||
|
||||
- conversas e mensagens ficam em `sql.js` persistido em `localStorage`
|
||||
- o app separa reasoning de resposta final ao analisar `<think>...</think>`
|
||||
- tokens por mensagem e por chat ficam persistidos
|
||||
- memoria do chat envia ate 20 mensagens recentes quando habilitada
|
||||
|
||||
## Limites e fronteiras atuais
|
||||
|
||||
- a API publica ainda e pequena; nao documente ou desenvolva assumindo uma plataforma completa estilo OpenAI
|
||||
- a CLI esta mais avancada no parser/superficie do que nas capacidades HTTP publicas realmente disponiveis
|
||||
- o app desktop e a interface mais rica do projeto hoje, mas ainda depende do backend HTTP local/remoto para inferencia real
|
||||
|
||||
## Termos recomendados
|
||||
|
||||
- `runtime` - processo + configuracao + estado operacional do backend local
|
||||
- `API local` - o `inference-server` rodando na maquina do usuario
|
||||
- `modo local` - o app controla o processo
|
||||
- `modo remoto` - o app consome uma API externa
|
||||
- `snapshot de runtime` - estado serializado do runtime usado pelo frontend
|
||||
|
||||
## Leitura complementar
|
||||
|
||||
- `../api/overview.md`
|
||||
- `../cli/overview.md`
|
||||
- `../app/overview.md`
|
||||
Reference in new issue
Block a user