Metadata-Version: 2.4
Name: fast-translate
Version: 0.2.0
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Rust
Classifier: Operating System :: OS Independent
Classifier: Topic :: Text Processing :: Linguistic
Summary: Portable, self-contained EN<->PT-BR translation with a native Rust engine (no external binary) and baked-in models
Keywords: translation,portuguese,pt-br,offline,bergamot,marian,rust
Author: TL PTBR Contributors
License: MIT
Requires-Python: >=3.8
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Homepage, https://github.com/cnmoro/fast-translate
Project-URL: Repository, https://github.com/cnmoro/fast-translate

# fast-translate

Tradução offline rápida em CPU, 100% local e sem dependências externas:

- `en -> pt-BR`
- `pt-BR -> en`

```python
from fast_translate import Translator

tr = Translator()
print(tr.translate("How are you today?"))               # -> "Como você está hoje?"
print(tr.translate("Como você está hoje?", "pt-en"))    # -> "How are you today?"
tr.close()
```

## O que mudou na 0.2.0

A versão 0.2.0 substitui o `translateLocally` por um **motor de tradução próprio,
escrito em Rust e embutido no pacote**. O comportamento e a API são os mesmos; o que
muda é o que roda por baixo.

- **Self-contained de verdade.** Não há mais binário externo, subprocesso, Native
  Messaging, dependência de Qt, nem download de nada em tempo de execução. Os modelos
  `en-pt` e `pt-en` já vêm dentro do pacote. `pip install` e pronto.
- **Muito mais rápido em escala.** ~5,9× mais vazão com múltiplas threads e cauda de
  latência (p95) ~5× menor — não há mais o custo e a instabilidade do subprocesso.
- **Memória estável e compartilhada.** O modelo é carregado uma vez e compartilhado
  entre todas as threads. Sem cópia por thread e sem crescimento ao longo do tempo
  (o problema de RAM que crescia com o `translateLocally` acabou).
- **Thread-safe.** A tradução libera o GIL, então basta compartilhar uma instância de
  `Translator` entre threads para escalar entre os núcleos da CPU.
- **Mesma qualidade.** Em frases reais a saída é idêntica à do `translateLocally`.
- **Sem novas dependências Python.** O pacote não requer mais `httpx`/`zstandard`.

## Instalação

```bash
pip install fast-translate
```

Wheels pré-compiladas são publicadas para Linux, macOS e Windows — não é preciso ter
Rust instalado para usar. (Para compilar do código-fonte é necessário o toolchain Rust
e um compilador C.)

## Uso

```python
from fast_translate import Translator

tr = Translator()
tr.translate("The children were playing happily in the garden.")   # en -> pt-BR
tr.translate("As crianças estavam brincando no jardim.", "pt-en")  # pt-BR -> en
tr.close()
```

Alta vazão — compartilhe **uma** instância entre threads:

```python
import concurrent.futures as cf

tr = Translator(cache_size=1024)
with cf.ThreadPoolExecutor(max_workers=8) as ex:
    results = list(ex.map(tr.translate, sentences))
tr.close()
```

`Translator` também funciona como context manager (`with Translator() as tr: ...`).

### Conteúdo técnico (código e LaTeX)

Trechos de código e fórmulas são preservados; só o texto natural ao redor é traduzido:

- código: ```` ```...``` ````, `~~~...~~~`, inline `` `...` ``
- LaTeX: `$$...$$`, `\(...\)`, `\[...\]` e ambientes (`equation`, `align`, ...)

## Desempenho

`AMD Ryzen 7 3700X` (8 núcleos), frases reais, sem cache. Antigo = `translateLocally`
via subprocesso (um worker); Novo = motor Rust em processo:

| Métrica                     | Antigo            | Novo (0.2.0)       | Ganho          |
|-----------------------------|-------------------|--------------------|----------------|
| Vazão (8 threads)           | ~65 frases/s      | **~384 frases/s**  | **~5,9×**      |
| Latência p95                | ~83 ms            | **~16 ms**         | **~5,2× menor**|
| Latência p50 (1 thread)     | ~10 ms            | ~13 ms             | ~1,3× maior    |

O ganho está na vazão e na cauda de latência (eliminar o subprocesso/IPC). A latência
mediana de **uma** chamada isolada é um pouco maior, porque o motor usa `f32` portável
em vez das kernels `int8` do bergamot — em cargas com muitas frases, a vazão domina.

## Memória

O modelo é carregado uma vez e compartilhado entre as threads; não cresce com o tempo.

| Estado                          | RAM (RSS)                          |
|---------------------------------|------------------------------------|
| Só `en-pt` carregado            | ~94 MB                             |
| Ambas as direções               | ~163 MB                            |
| Após 5000 traduções (1 thread)  | ~163 MB (estável, sem vazamento)   |
| Pico com 8 threads              | ~175 MB (+~12 MB, não por thread)  |

Para RAM mínima: carregue só a direção que usa (o carregamento é preguiçoso, na
primeira chamada) e compartilhe uma única instância de `Translator` entre as threads.

## Variáveis de ambiente

- `FAST_TRANSLATE_CACHE_SIZE` — tamanho do cache LRU (default `64`)
- `FAST_TRANSLATE_CACHE_MAX_ENTRY_CHARS` — tamanho máximo por item de cache (default `512`)

## Como funciona (resumo)

O motor reimplementa em Rust o modelo *bergamot tiny11* (encoder transformer de 6
camadas + decoder SSRU de 2 camadas, com shortlist léxica e decodificação greedy),
carregando os pesos `int8` embutidos e a tokenização SentencePiece. Uma fina camada
Python cuida do cache, do pós-processamento pt-BR e da preservação de código/LaTeX.

