Metadata-Version: 2.5
Name: firefox-translations
Version: 0.1.2
Summary: Fast, local neural machine translation in Python powered by Firefox Translations models and CTranslate2.
Project-URL: Homepage, https://github.com/mozilla/translations
Project-URL: Repository, https://github.com/mozilla/translations
Project-URL: Documentation, https://mozilla.github.io/translations/
Author: makhlwf
License: MPL-2.0
License-File: LICENSE
Keywords: ai,ctranslate2,firefox-translations,machine-translation,nlp,nmt,offline-translation,sentencepiece,translation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Text Processing :: Linguistic
Requires-Python: >=3.10
Requires-Dist: ctranslate2>=4.0.0
Requires-Dist: requests>=2.28.0
Requires-Dist: sentencepiece>=0.2.0
Requires-Dist: tqdm>=4.66.0
Requires-Dist: zstandard>=0.22.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: twine>=4.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# Firefox Translations for Python

[![License: MPL 2.0](https://img.shields.io/badge/License-MPL_2.0-blue.svg)](https://opensource.org/licenses/MPL-2.0)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)

Fast, private, local neural machine translation in Python powered by official [Firefox Translations](https://github.com/mozilla/firefox-translations-models) models.

---

## Features

- ⚡ **In-Memory Model Persistence**: Preload models once in memory with zero per-request reloading latency.
- 🚀 **GPU & CPU Acceleration**: Automatic hardware detection (`cuda` / `cpu`), configurable thread counts, and precision quantization (`int8`, `float16`, `bfloat16`).
- 🌊 **Synchronous & Asynchronous Streaming**: First-class streaming iterators (`translate_stream` & `translate_stream_async`) for real-time translation pipelines and web frameworks.
- 📦 **Automated Model Management**: Automatically fetches, verifies, and converts official Mozilla Marian models to high-efficiency CTranslate2 format with smart caching.
- 🔒 **100% Private & Offline Capable**: Zero cloud dependencies or API keys required. Models run completely on your local machine.
- 🛠️ **Full-Featured CLI**: Command-line tool `firefox-translate` for interactive usage, stdin pipelines, and batch model pre-downloads.

---

## Installation

Install using [`uv`](https://github.com/astral-sh/uv) (recommended) or `pip`:

```bash
# Using uv
uv add firefox-translations

# Using standard pip
pip install firefox-translations
```

For development and running the test suite:

```bash
git clone https://github.com/mozilla/translations.git
cd translations/firefox_translations
uv sync --extra dev
uv run pytest -v
```

---

## Quickstart

### 1. Basic Single & Batch Translation

```python
from firefox_translations import Translator

# Initialize translator (models are downloaded and cached automatically on first run)
translator = Translator(src_lang="en", trg_lang="es", device="auto")

# Single string translation
result = translator.translate("Hello world! Machine translation runs completely on device.")
print(result)
# Output: ¡Hola mundo! La traducción automática se ejecuta completamente en el dispositivo.

# Batch translation with optimized batching
texts = [
    "Good morning!",
    "Privacy-preserving machine translation is essential.",
    "Firefox Translations runs locally in Python."
]
results = translator.translate_batch(texts, batch_size=16)
for src, trg in zip(texts, results):
    print(f"{src} -> {trg}")
```

### 2. Listing Available Language Pairs

```python
from firefox_translations import ModelRegistry

registry = ModelRegistry()
pairs = registry.list_available_pairs()

print(f"Supported language pairs ({len(pairs)}):")
for src, trg in sorted(pairs):
    print(f"  {src} -> {trg}")
```

---

## In-Memory Retention & Performance

`firefox-translations` keeps models resident in memory to ensure microsecond-level invocation overhead for real-time web services, bots, and high-throughput pipelines.

```python
from firefox_translations import Translator

# Explicitly manage memory lifecycle
translator = Translator(src_lang="en", trg_lang="fr", device="auto")

print(translator.is_loaded)  # True

# Unload from memory if needed (e.g. idle timeout or freeing GPU VRAM)
translator.unload()
print(translator.is_loaded)  # False

# Preload back into memory before high-traffic bursts
translator.preload()
```

### Threading & Concurrency

Tune CPU thread utilization with `inter_threads` (parallel batch workers) and `intra_threads` (threads per computation):

```python
translator = Translator(
    src_lang="en",
    trg_lang="de",
    inter_threads=2,  # Number of concurrent workers
    intra_threads=4,  # CPU cores per worker
)
```

---

## GPU & CPU Acceleration

Configure computation device and quantization parameters:

```python
# Auto-detect CUDA GPU, falling back to CPU
translator = Translator(src_lang="en", trg_lang="es", device="auto")

# Force CUDA on GPU device index 0 with INT8 quantization for minimal VRAM footprint
translator_gpu = Translator(
    src_lang="en",
    trg_lang="es",
    device="cuda",
    device_index=0,
    compute_type="int8_float16"  # Options: default, int8, int8_float16, float16, bfloat16
)

# Multi-GPU inference
translator_multi = Translator(
    src_lang="en",
    trg_lang="es",
    device="cuda",
    device_index=[0, 1]
)
```

---

## Streaming & Async API

### Synchronous Streaming

Process large files, line-by-line generators, or token streams without loading all data into memory:

```python
def text_stream():
    yield "First paragraph to translate."
    yield "Second paragraph arriving in the stream."
    yield "Final closing thoughts."

translator = Translator(src_lang="en", trg_lang="it")

for translated_chunk in translator.translate_stream(text_stream(), batch_size=2):
    print(translated_chunk)
```

### Asynchronous Streaming (FastAPI / Quart / aiohttp)

```python
import asyncio
from firefox_translations import Translator

async def async_token_source():
    messages = [
        "Welcome to our real-time service.",
        "Your translations are computed asynchronously.",
        "Enjoy fast inference!"
    ]
    for msg in messages:
        await asyncio.sleep(0.05)
        yield msg

async def main():
    translator = Translator(src_lang="en", trg_lang="es")
    
    async for translated in translator.translate_stream_async(async_token_source(), batch_size=2):
        print("Received async translation:", translated)

asyncio.run(main())
```

---

## Command Line Interface (CLI)

The package provides the `firefox-translate` command:

### Translate Text Directly

```bash
firefox-translate --from en --to es "Local machine translation is fast and private."
```

### Stream via Standard Input (Piping)

```bash
cat article.txt | firefox-translate -f en -t fr > article_fr.txt
```

### List Available Models

```bash
firefox-translate --list-models
```

### Pre-download & Cache Model

```bash
# Download and convert model ahead of time for offline use
firefox-translate --from en --to uk --download
```

### Specify Inference Device & Quantization

```bash
firefox-translate --from en --to de --device cuda --compute-type float16 "Translate using CUDA GPU."
```

---

## API Reference

### `Translator`

```python
Translator(
    src_lang: str,
    trg_lang: str,
    model_dir: Optional[Union[str, Path]] = None,
    device: str = "auto",                  # "auto", "cuda", or "cpu"
    device_index: Union[int, List[int]] = 0,
    compute_type: str = "default",        # "default", "int8", "float16", "int8_float16", "bfloat16"
    inter_threads: int = 1,
    intra_threads: int = 0,
    cache_dir: Optional[Union[str, Path]] = None,
    beam_size: int = 1
)
```

- `translate(text: str, beam_size: Optional[int] = None) -> str`
- `translate_batch(texts: List[str], batch_size: int = 32, beam_size: Optional[int] = None) -> List[str]`
- `translate_stream(stream: Iterable[str], batch_size: int = 16, beam_size: Optional[int] = None) -> Iterator[str]`
- `translate_stream_async(async_stream: AsyncIterable[str], batch_size: int = 16, beam_size: Optional[int] = None) -> AsyncIterator[str]`
- `preload() -> None`
- `unload() -> None`
- `is_loaded: bool`

### `ModelRegistry` & `ModelManager`

- `ModelRegistry.list_available_pairs() -> List[Tuple[str, str]]`: Returns available source and target language pairs.
- `ModelRegistry.get_model_metadata(src_lang: str, trg_lang: str) -> Dict[str, Any]`: Retrieves model metadata from registry.
- `ModelManager.ensure_model(src_lang: str, trg_lang: str) -> Path`: Downloads, caches, and returns path to converted model.

---

## License

This project is licensed under the [Mozilla Public License 2.0 (MPL-2.0)](LICENSE).
Model weights are provided under their respective Mozilla and Bergamot open-source licenses.
