Будівництво three lumcid-nmt: Production- ready (EasyNMT сумісне) Translation Service (Українська (Ukrainian))

Будівництво three lumcid-nmt: Production- ready (EasyNMT сумісне) Translation Service

Saturday, 08 November 2025

//

45 minute read

Вступ

Реалізація FastAPI EXACT копіює чудовий, але покинутий проект роботи з нейронним апаратом. https: // gitub.com/UKPLAB/EasyNMT).

Але я додав БАГАТЬОХ гарних рис, щоб збільшити надійність і підготувати її до використання у виробничій системі.Думайте про те, що швидкий переклад сам підтримується...).

З самого початку цього блогу, великим захопленням стали статті у автотрансляційних блогах.

ТАК Я знаю, що "Google робить це в браузерах і т.д., але справа не в цьому.mostlylucid-nmtЯ хотіла знати, як це зробити!

Крім того, приємно вітати людей, які не читають англійською (навіть якщо вони читають англійську як другу мову, це важче опрацювати).Тож я вирішив, як це зробити, і поділився тим, як побудувати таку систему.О, і вона дала мені ідеї щодо того, як використовувати текст у ASP.NET для автоматичного локалізації тексту (включаючи динамічний текст) за допомогою SNR & хитрої системи оновлення реального часу. (

Залишайтеся на зв'язкуО, і я зробив демонстрацію доступною тут; https: // nmtdemo. methulicid.net/demo / вона працює лише у старому ноутбуку без GPU, але надає вам ідею (і дозволяє мені перевірити lengevity).По суті, люди пишуть нісенітниці текст, який є ДУЖЕ шумним для машин, щоб ефективно поводитися.

Отже, багато з них з'ясовували, як працювати з FasyNMT (це був справді дослідний проект).

Зараз

призначена для того, щоб бути випробуваною битвою (також перекладаючи десятки тисяч слів тут!) корисною системою для будь - якого перекладу. Вавельський API. У нього також є всі знання, які я маю від трьох десятиліть створення виробничих серверів та систем. Перебіг з 429 кодів, щоб повідомити клієнтам про вихід, повернувши метадані про переклади, щоб допомогти клієнтам, додатковим кінцевим пунктам отримати більше даних і COURSE сторінка демонстрації

що дозволяє мені обом розвиватися так само добре, як тобі піти на гру.

Iзаписано цілу системуhttp://<server>:<port>/demoщоб це сталося з чудовим проектом під назвою EasyNMT.

Demo

[TOC]

ЯК ЖЕ, якщо ви тільки-но перевірили, що експропріатор, ви знаєте, є проблема... вона не була зворушена протягом РОКІВ.

Це простий, швидкий спосіб отримати API перекладу без потреби платити за якусь послугу або запустити повний розмір LLM для отримання перекладу (повільно).

На наших попередніх дописах ми обговорювали, як інтегрувати JestyNMT з програмами ASP.NET для фонового перекладу.

**Але з часом почали з'являтися тріщини.**Прийшов час на щось краще.

**Як завжди на GitHub і все безкоштовно для використання і т.д.**Docker pulls

  • cpu: Reusing loaded model for en->de (3/10 models in cache)
  • cpu- min: Need to load model for en->fr (3/10 models in cache)
  • gpugpu-min
  • **Демонстрація... Пізніше перегляньте демонстрацію сторінки!**Повнофункціональна сторінка демонстрації (здебільшого)
  • або лише корінь)
  • **Що нового?**Перш ніж ми перейдемо до швидкого початку гри, ось що робить цю версію зміною гри:

Основні оновлення (версія 3. 1) - Розвідка і видимістьСтворити у v3. 1:

  • **Найсвіжіша версія - це грандіозне вдосконалення надійності, швидкодії та розумний вибір моделі!**1.
  • Смарт- модель катування з видимістю- Посмотрите, что происходит.
  • Журнал XIT кешуЖурнал MISS для кешу
  • Стеження за станом кешу: Показує відсоток завантаження і завантажені моделі
  • Попередження про евіфікацію: Чіткі попередження, якщо кеш переповнений, а моделі виселяються.
  • Збільшує місткість:
    ====================================================================================================
      🚀 DOWNLOADING MODEL
      Model: facebook/mbart-large-50-many-to-many-mmt
      Family: mbart50
      Direction: en → bn
      Device: GPU (cuda:0)
      Total Size: 2.46 GB
      Files: 6 main files
    ====================================================================================================
    [Progress bars for each file...]
    ====================================================================================================
      ✅ MODEL READY
      Model: facebook/mbart-large-50-many-to-many-mmt
      Translation: en → bn is now available
    ====================================================================================================
    

**: Типовий розмір кешу зв' язано з 10 моделями (з 6)**Журналювання за моделюванням пристрою

  • : Ознайомтеся з тим, який спосіб використання GPU/CPU використовує кожна з моделей2.
  • Покращений поступ звантаження- Мене більше не цікавить, чи він застряг:
  • Розмір перед звантаженням:
    [Pivot] Languages reachable from en: 85 languages
    [Pivot] Languages that can reach bn: 42 languages
    [Pivot] Found 38 possible pivot languages
    [Pivot] Selected pivot: en → hi → bn (both legs verified)
    
  • **: Показує загальний розмір звантаження (наприклад, " Тотал Розмір: 2. 46 ГБ ")**Кількість файлів
  • : показує кількість файлів для звантаженняПоказ пристроїв

: Показує пристрій призначення (GPU/CPU) у банціСмужка поступу

  • **: Чудовий прогрес tqdm для кожного файла (коли на TTY)**Прапорець завершення
  • : Очистити повідомлення про успіх, якщо модель готоваПриклад виводу
  • 3.:
    Request: en→bn with opus-mt
    Trying families: ['opus-mt', 'mbart50', 'm2m100']  ✓ All three!
    opus-mt: Failed (model doesn't exist)
    mbart50: Success! (auto-fallback worked)
    

Data- Driven Intesent Pivot Вибір- Більше ніяких сліпих спроб:

  • Логіка кмітливого перетинуLoading mbart50 model on GPU (cuda:0)
  • : знаходить мови, де існують ноги-поворотні лінії BOTHModel loaded on device: cuda:0
  • Уникає невдалих спробSuccessfully loaded... on GPU (cuda:0)

: Не буде намагатися en →bn, якщо es→bn не існуєПриклад для en→bn

  • Зворотний пріоритетen->hi, hi->bn
  • : Англійська → Іспанська → Французька → Німецька → Китайська → Російська
  • Прозорий ведення журналу[Pivot] Both legs loaded and cached. Ready to translate.

: з'ясувати, чому було обрано або пропущено кожен з поворотів4.

  • Моноширинне автоматичне повернення
    • Більше ніяких подвійних течій:model_familyЗавжди пробувати зворотні результати
  • : Навіть якщо сім'я воліє підтримувати пару

Одна спроба на сім'ю

**: Більше ніяких спроб однієї моделі двічі.**Приклад потоку

  • Яскравість GPU
    • Завжди знаєш, де твої моделі:
  • Кожне завантаження моделі показує:
  • Після завантаження підтверджується:

**Повідомлення про успіх містить:**6.

  • Кечування моделі Pivot- Достатнє повторне використання:
  • **Обидві ноги каркасу окремо:**Наступного разу, en→hi або hi →bn потрібні, миттєве кешування!
  • **Спорожнити журнал:**7.
  • Вибір моделі для перевірки

**- Вже працює в демонстраційному режимі:**За допомогою спадного списку Демонстрація можна обрати opus- mt, mbart50 або m2m100

  • Відсотки сервера
  • параметр на запит
  • Моделі, розташовані окремо сім'єю для миттєвого перемикання
  • Основні оновлення (версія 3. 0)
  • 1.requirements-prod.txtПокращена демонстрація сторінка

**- Готовий до створення інтерактивний інтерфейс:**Повне компонування viewport (100vw/ 100vh) для незахоплюючих перекладів

  • **Правильний вибір зі спадними списком (більше немає списку даних- внесків/ даних)**Зміна гарнітури (Operus- MT, mBART50, M2M100)
  • Завантаження динамічної мови на основі вибраної моделіПрокручувати області виводу для великих перекладів
  • **2.**Типові параметри швидкодії
    • "Найменше, наскільки це можливо" поза ящиком:
  • GPU

**: увімкнено FP16, BATCH_ SIZE=64, MAX_ INFWYL=1 (додатковий для окремого GPU)**Процесор

  • : WEB_ CONCURRENCY=4, MAX_ INFLYPE=4, BATCH_ SIZE=16 (дослідити всі ядра)
  • Швидке завершення роботи
  • : 5- секундний граційний час очікування (більше не 20- секундне вішання)
  • Контейнери зупиняються чисто без страшних повідомлень SIGKILL
  • Оптимізація розробки збирання

**- Менші, швидші зображення:**Вилучено залежності перевірки (pytest, pytest- cov) з побудови

  • Зберігає ~200МБ на зображенняЗображення процесора: ~8- 10GB (full), ~3- 4GB (мін)
  • **Зображення GPU: ~12- 15GB (full), ~6- 8GB (min)**Всі використовувати
  • для мінімального сліду4.

Точне тестування і завантаження- Перевірте все:

  • Комплекс тестування API для Live
  • (30+ тести) для здоров'я, перекладу, виявлення, відкриття
  • k6 завантаження тестування

з реалістичними типами трафікуКросплатформові скрипти перевірки

  • /discover/opus-mt(Повершель + Баш)
  • /discover/mbart50Повернення тестів на створення моделей звантажень і перекладу turn
  • /discover/m2m100Автоматизовані тести на швидку перевірку диму

**5.**Документація з впровадженням

    • Виготовлення-готове з першого дня:
  • 4 Сценарії налаштування: Max Tracput, Latency, High Concurrence, Consecurated
  • Набір прикладів з налаштуваннями GPU/CPU

Kubernetes показується з PVC, обмеження ресурсів, перевірки стану здоров'яПриклади контейнерів Azure

  • scottgal/mostlylucid-nmt:cpuЗавантажити вказівки для перевірки та моніторингу:latestОбъясняние распространяемых торговых событий
  • scottgal/mostlylucid-nmt:cpu-min6.
  • scottgal/mostlylucid-nmt:gpuТри зразкові сім'ї
  • scottgal/mostlylucid-nmt:gpu-min- Виберіть найкраще для ваших потреб:

Opus-MT: 1200+пари, найкраща якість (вимірювання моделей)

  • mBART50latest, min, gpu, gpu-min: 50 мов, єдина модель 2.4GB, 2.450 пар
  • M2M10020250108.143022: 100 мов, єдина модель 2.2GB, 9 900 пар

Автоматичний відступ- Розумно вибирає найкращу модель:

  • **Встановити початкову родину (наприклад, Opus- MT для якості)**Автоматично виконувати mBART50/M2M100, якщо пара недоступна
  • Максимальна обкладинка без остаточної якості8.
  • Відкриття моделі- Динамічні запити наявні моделі:
    • Всі пари 1200+ з Heback Face

- Всі пари mBART50- Всі пари M2M100

  • Мінімальні зображення

- Менший, гнучкіший простір:

Немає попередньо завантажених моделей (завантажувати на- деменд)

Постійний кеш, накреслений гучністю

Перемкнути зразкові сім'ї без перебудовування**Десять.**Сховище окремих об' єктів

  • Всі варіанти в одному місці: |-----|-----------------|------|-------------|----------| | cpu(абоlatest) | scottgal/mostlylucid-nmt:cpu) - Процесор | cpu-min | scottgal/mostlylucid-nmt:cpu-min- Мінімум ЦП | gpu | scottgal/mostlylucid-nmt:gpu- GPU з CUDA 12.6 | gpu-min | scottgal/mostlylucid-nmt:gpu-min- Мінімум GPU

**11.**Правильна версія

    • Всі зображення містять версію дати:
  • Мітки з назвою (
  • ) завжди вказує на останнє збирання
  • Незмінні теґи версій (наприклад,

) для окремих споруд

Повноцінні мітки OCI для стеження за версіями, датами збирання і внесками git

docker run -d \
  --name mostlylucid-nmt \
  -p 8000:8000 \
  scottgal/mostlylucid-nmt

12.

curl -X POST "http://localhost:8000/translate" \
  -H "Content-Type: application/json" \
  -d '{
    "text": ["Hello, how are you?"],
    "target_lang": "de"
  }'

Останні базові зображення

{
  "translated": ["Hallo, wie geht es Ihnen?"],
  "target_lang": "de",
  "source_lang": "en",
  "translation_time": 0.34
}

- Покращення безпеки і швидкодії:

Python 3. 12- slim

docker run -d \
  --name mostlylucid-nmt \
  --gpus all \
  -p 8000:8000 \
  -e EASYNMT_MODEL_ARGS='{"torch_dtype":"fp16"}' \
  scottgal/mostlylucid-nmt:gpu

для зображень процесора (адреси Python 3. 11 можливостей)

CUDA 12. 6

з Ubuntu 24. 04 для зображень GPU (latest NVIDIA стос)

docker run -d \
  --name mostlylucid-nmt \
  -p 8000:8000 \
  -v $HOME/model-cache:/models \
  -e MODEL_CACHE_DIR=/models \
  scottgal/mostlylucid-nmt:cpu-min

PyTorch with CUDA 12.4

docker run -d `
  --name mostlylucid-nmt `
  -p 8000:8000 `
  -v ${HOME}/model-cache:/models `
  -e MODEL_CACHE_DIR=/models `
  scottgal/mostlylucid-nmt:cpu-min

(сумісна з СУДА 12.6)

docker run -d ^
  --name mostlylucid-nmt ^
  -p 8000:8000 ^
  -v %USERPROFILE%/model-cache:/models ^
  -e MODEL_CACHE_DIR=/models ^
  scottgal/mostlylucid-nmt:cpu-min

Всі залежності оновлено до останніх безпечних версій

13.

curl http://localhost:8000/healthz

Попереджальні попередження про фіксоване амортизацію

- Запевняю вас у майбутньому:

Вилучено застаріле REFORMERS_ CCHACE (тепер з використанням HF_ HOME)Сумісний з Transformers v5Швидкий запуск (5 хвилин)

http://localhost:8000/demo/

Demo

### Хочеш перекладати?

Ось абсолютний найпростіший спосіб запуску biglucid-nmt:

Доступні зображення панелі

  • Всі варіанти доступні з
  • одне сховище
  • з різними мітками:

Передня частина зображення має бути розміщена так, щоб вона була розміщена у центрі уваги.

  • (або

  • +GB + GPU з кодом CUDA} ГПУС
  • +4GB} GPU minimal, немає заздалегідь завантажених моделей} GPU з об'ємом- картами кешу}

Мінімальні зображення

  • рекомендуємо для:
  • Виробництво з кешем у вигляді об' єму
  • Використання mBART50 або M2M100 (великі моделі)

Зберігати розміри контейнера малими

  • Гнучкість до заміни моделей сімей без перебудуванняПростий запуск (Popus- MT процесор)
    • Тягніть і біжіть:
  • **2.**Перекладіть текст:
    • Відповідь:
    • GPU Acceled (10x Fast)

Потрібний час запуску NVIDIA:

  • З постійним кешем моделейЗвантажити моделі один раз і залишити їх між перезапусками контейнера:
  • **Linux/Mac:**Windows (PowerShell):
  • **Вікна (CMD):**Моделі автоматично звантажуються при першому використанні і залишаються у вашому локальному каталозі!

Перевірка здоров'я:

  • Це п'ятихвилинний швидкий старт!
    • **Для виробництва, конфігурації та додаткових можливостей продовжуйте читати.**Інтерактивна демонстрація сторінка
    • До служби включено повнофункціональну службуІнтерактивна сторінка демонстрації
    • **що спрощує перевірку перекладів без написання жодного коду.**Доступ до нього за адресою:
  • Демонстраційні можливості

На сторінці демонстрацій передбачено повноцінне середовище для перевірки перекладів за допомогою:

// Example: Translating a 5000-word article
Input: Long article with multiple paragraphs

Step 1: Split by paragraphs (preserves structure)
  → Paragraph 1 (800 chars)
  → Paragraph 2 (1200 chars)
  → Paragraph 3 (600 chars)
  ...

Step 2: Group into ~1000 character chunks
  → Chunk 1: Paragraphs 1-2
  → Chunk 2: Paragraph 3-4
  → Chunk 3: Paragraphs 5-6

Step 3: Translate each chunk sequentially
  → Shows progress: "Translating chunk 1/3..."
  → Shows progress: "Translating chunk 2/3..."
  → Shows progress: "Translating chunk 3/3..."

Step 4: Reassemble with paragraph breaks
  → Final output: Complete translated article with preserved formatting

Вибір мови

Автозаселення мов зі спадного меню служби

  • Поміняти місцями мови джерела/ призначення одним клацанням
  • Підтримує всі 100+ мови, налаштовані у службі
  • Кмітлива текстова розмітка

Автоматично виконувати великі текстові входи будь- якого розміру

  • Інтелектуальне розділення абзацами, збереження структури документа
  • Переводить назад до речення розділюючись на дуже довгі абзаци
  • Показує поступ для багатофункційних перекладів ("Перетворення шматка 2/5 ...")
  • Безперервно нагромаджуються шматки з відповідними проміжками.

3.

  • Виявлення мови
  • Визначити мову джерела одним клацанням
  • Автоматично заселює спадний список мови джерела
  • Робота з текстом до 5000 символів

4.

  1. Додаткові параметри:

    • Розмір зерна
    • : Контрольна якість перекладу (1- 10)
    • Вищі значення = кращу якість, але повільніші
    • Нижні значення = швидший прохід
  2. Розділення речень:

    • : увімкнути або вимкнути автоматичне розбиття речень
    • Увімкнено (типовий): розділює довгі тексти на речення для кращої якості
    • Вимкнено: перекладає весь текст як один блок (швидше для коротких текстів)
  3. Статистика реального часу:

    • Час перекладу
    • : Показує поточну тривалість перекладу на стороні сервера
    • Кількість символів
    • : Підрахуйте скільки набираєте

Індикатор стану

: Бездіяльний → Трансляція → Виконано/ Помилка

  • **6.**Знаходження моделі сім'ї
  • **Використання пар перекладів для кожної зразкової сім' ї:**Opus-MT
  • : 1200+пари мовmBART50
  • : 50 мовами, 2.450 парM2M100

: 100 мовами, 9700 пар/demo/Визначити, які пари мов доступні перед перекладом

Як працює текстова розшифровка

Демонстрація реалізує інтелектуальний фрагмент тексту на стороні клієнта:Чому слід використовувати демонізм?Швидке тестуванняПеревіряти переклади без коду записуПеревірити доступність пари мов

Порівняти якість перекладу з різними розмірами променя

  1. **Тестові випадки ребер (емоджі, символи, спеціальні символи)**Допомога у розробці
  2. Див. точний формат запиту/ репонентів APIПеревіряти стан служби перед об'єднанням
  3. Перевірка швидкодії з різними розмірами текстуВідкрити наявні гарні сім'ї
  4. Довідка клієнтаПоказує відповідні шаблони використання API
  5. **Демонструє роботу з помилками (429, виявлення мови)**Приклад реалізації шматків
  6. Повторна логіка реального світуПриклад використанняПростий переклад.
  7. **Вставте текст: "Привіт, як справи сьогодні?"**Вибір мети: німецька
  8. **Натисніть " Транзиту "**Результат: "Hallo, welle geht es Ihnen hute?"

Довгий переклад документа

Вставити весь допис блогу (5000 слів)Демонстрація автоматично зрізає її на частини, які можна налаштуватиПоказує поступ під час перекладу кожного шматка

Повертає документ повністю перекладений

Виявлення мовиВставити текст невідомою мовоюНатисніть " Вилучити мову "

Демонстрація ідентифікувати мову і оновлення

  • Готовий до перекладу негайноТехнічні подробиці
  • **Сторінка демонстрації:**Самодостатнє
  • : Окремий HTML файл з вбудованим JavaScriptНуль залежностей
  • : Не потрібно зовнішніх бібліотекПриязний до мобільнихComment
  • **: Конструкція працює на всіх пристроях.**Виробництво готове
  • **: У ваших програмах можна використовувати ту саму логічну логіку.**Доступ до живої демонстрації в

у вашому запущеному екземплярі!

  • Проблеми з легкою пам'яттюТепер це не злине на
  • EasyNMTі я будую.
  • МАЛО проектів, що використовують його
  • **Він просто довго в зубах, так що... які у нас проблеми?**Боже, їх багато.
  • **EasyNMT було побудовано майже десять років тому.**Технологія просунулася... до того, що вона ніколи не мала бути виробничою системою.
  • **Унизу подаємо деякі спірні питання:**Невдаха.

Він не розрахований на те, щоб відновитися від проблем, так часто його просто не видно.

  • **Це SUER PICKY щодо їх вводу.**Емоційки, символи, навіть числа можуть спантеличити їх.
  • **Він не призначений для будь-якого навантаження.**Дивіться вище.
  • **Вона ніколи не була створена.**Він не призначений для оновлення своїх моделей.
  • **або бути (легко) побудований з вбудованими моделями.**Його речовий матеріал GPU CUDA давній
  • **Так повільніше, ніж має бути.**Ти нічого не можеш полагодити.
  • Код Python на експропріаторі, але зновуне чудовий

**Ніяких відштовхувань чи чергування.**Надсилайте забагато запитів, і він просто з'являється.MODEL_FAMILYНіякої упертості.

# Opus-MT (default, best quality)
MODEL_FAMILY=opus-mt

# mBART50 (50 languages, single model)
MODEL_FAMILY=mbart50

# M2M100 (100 languages, broadest coverage)
MODEL_FAMILY=m2m100

Когда всё идет не так, ты летаешь слепой.

Вирішення: здебільшогоLucid-NMTТому... я вирішив побудувати новий та покращений THENMT, заразumcid-nmt


  1. Це не просто латка робота; це повний перепис з використанням виробництва.MODEL_FAMILYОсь що робить це кращим:opus-mtБагатомодерна підтримка сім'ї
  2. Зараз підтримується здебільшого Lucid- NMT
  3. три сім' ї моделей перекладу
  4. , даючи вам гнучкість, що базується на ваших потребах:

Opus- MT (Helsinki- NLP) - типовий

# Set primary to Opus-MT (best quality)
MODEL_FAMILY=opus-mt
AUTO_MODEL_FALLBACK=1
MODEL_FALLBACK_ORDER=opus-mt,mbart50,m2m100

# Request Ukrainian → French
# 1. Try Opus-MT first (not available)
# 2. Automatically fall back to mBART50 (available!)
# 3. Translation succeeds with mBART50

Обкладинка:

  • 1200+пари перекладів для 150+ мовАрхітектура:
  • Розділити модель на напрямок перекладуЯкість:
  • Найкраща якість перекладуВипадок використання:
  • Виготовлення перекладів, де якість має значенняРозмір моделі:

300- 500 Мб на напрямок

# Enable auto-fallback (default: enabled)
AUTO_MODEL_FALLBACK=1

# Set fallback priority (default: opus-mt → mbart50 → m2m100)
MODEL_FALLBACK_ORDER="opus-mt,mbart50,m2m100"

# Disable for strict single-family mode
AUTO_MODEL_FALLBACK=0

Приклад:

Англійська → Німецька - інша модель, ніж німецька → English

  1. **mBART50 (лицем)**Обкладинка:
  2. 50 мов, повний перекладАрхітектура:
  3. Одна багатомовна модельЯкість:
  4. **Добра якість, особливо для головних мов.**Випадок використання:
  5. Конструкція простору або багато пар мовРозмір моделі:
  6. **~2. 4GB (single модель для всіх 50 мов)**Переваги:
  7. Одна модель керує 2 450 парами перекладівM2M100 (лицем)
  8. **Обкладинка:**100 мов, повний переклад
  9. **Архітектура:**Одна багатомовна модель
  10. **Якість:**Добра якість з найширшим покриттям мови
  11. **Випадок використання:**Максимальна обкладинка мови-minРозмір моделі:

~2. 2GB (single модель для всіх 100 мов)

Переваги:

Одна модель керує 9 900 парами перекладів

Перемикання просте

    • Просто наведите.
  • змінна середовища:
  • Автомодельована сім'я - нове!

Однією з найсильніших нових рис є

  • автоматичний спад між моделями сімей
  • Це забезпечує максимальну оцінку пари мов під час приготувань до перекладу.

**Як це працює:**Ви встановили основний

  • **(e.g.,**для найліпшої якості)
  • **Коли ви хочете мати пару, яка б перекладала, якої немає в головній сім'ї.**Система автоматично перевіряє наступну сім'ю у порядку повернення
  • Це продовжується до того часу, доки не буде знайдено відповідну модельСкрипт прикладу:

Користі:

Максимальне покриття:

Підтримка 100+ мов без керування декількома розповсюдженнями

  • Пріоритет якості:
  • Завжди використовуйте найкращу досяжну модель для кожної пари
  • Нульове налаштування:
  • Працює автоматично, не потрібно втручання вручну

Прозоре ведення журналу:

  • Дивіться, яку модель сім'ї було використано для кожного перекладу
  • Налаштування:
  • Ця можливість ідеально пасує до середовища виробництва, у якому ви бажаєте максимального покриття без втрати якості!
  • Вдосконалення ключів

Багатомодельована підтримка сім' ї

# NMT: Fits on a USB stick
du -sh model-cache/
2.5G    model-cache/

# LLM: Needs serious storage
du -sh llama-models/
140G    llama-models/

- Оберіть варіант Opus- MT (1200+пари), mBART50 (50 мов), або M2M100 (100 мов).

Кінцеві точки відкриття моделі

    • Динамічні запити для кожної сім'ї.
  • Обробка обробки вхідних даних
    • Емоджі?
  • Числа?

Символи?

  • Давай.
  • До служби тепер включено повнофункціональну вимову та маску символів.
  • Запит щодо черги завдань і зворотного друку
    • Побудовано на основі семафри чергуються з розумними оцінками щодо повторних спроб.

Кечування моделей LRU

  • Автоматично керує VRAM, виганяючи старі моделі, якщо кеш повний. |--------|------|------| Сучасна підтримка CUDA
  • Використовує PyTorch з CUDA 12. 6, підтримує покращення швидкості 2x для FP16/BF16. Виробництво-готове узгоджування
  • Перевірка здоров'я, зонди Очищення, стан кешу, вирубка лісозаготівель. Милосердне завершення роботи

- Ніяких осиротілих запитів чи зіпсованих станів.

Сумісний з EasyNMT API

    • Заміна існуючих інтеграцій.
  • Повернення перекладу Pivot
    • Якщо пара мов недоступна, автоматично прокладає шлях через англійську (або обраний вами поворот).
  • Мінімальний об' єм зображень
    • Нову

Варіанти з кешем на основі об' єму для менших значень.

  • ⚠️ Sometimes adds interpretations not in original
  • ⚠️ Quality varies with prompt phrasing
  • ⚠️ Can be "creative" with technical terms
  • ⚠️ Needs careful prompt engineering
  • ⚠️ Unpredictable with edge cases

Чому НМТ над LLMs для перекладу?

Input: "The API returns a 429 status code when rate limited."

NMT (Opus-MT): "Die API gibt einen 429-Statuscode zurück, wenn sie ratenbegrenzt ist."
(Accurate, preserves technical terms)

LLM (might do): "Die API sendet den Fehlercode 429, wenn zu viele Anfragen gestellt werden."
(Interprets rather than translates, adds context not in original)

Ви можете запитати: "Навіщо використовувати віддану службу NMT, коли LLMs на зразок GPT-4, Claude або Llama може перекладати?" Чудове питання.

Ось реальна перевірка на основі використання виробництва:

  • Швидкість: швидкість 10- 100x швидче
  • NMT (здебільшого вимірюваного- nmt):
  • ЦП: ~0. 3- 1. 0 секунд на речення
  • GPU (FP16): ~0.05- 0. 2 секунд на речення
  • Пакетна обробка: 50+ речення/секунда у GPU
  • LLMs:

GPT- 4: 3- 10 секунд на запит (покоління латок + створення)

  • Llama 3 70B: 5- 15 секунд на речення (локальне)
  • Claude 3: 2- 8 seconds на запит (permission)
  • Справжній приклад:
  • Переклад допис блогу 1000 слів:
  • threecid-nmt (GPU)

: 5- 10 секунд

GPT-4 API**: 30- 60 секунд**Локальна Llama 70B

  • : 2- 5 хвилин
  • Коли ви автоматично перекладаєте сотні блогів на 12+нонгів, то різниця у швидкості - MASSIVE.
  • Розмір моделі: 500MБ проти 140GB
  • Моделі NMT:

Opus- MT (у напрямку): 300- 500MB

mBART50 (всі 50 мов): 2. 4GBM2M100 (всі 100 мов): 2. 2GB

Загалом для 100+ мов: ~2. 2GB

flowchart LR
    A[HTTP Client] --> B[API Gateway]
    B --> C[Translation Endpoint]
    C --> D{Has Capacity?}
    D -->|Yes| E[Translation Service]
    D -->|No| F[Queue with 429]
    F --> E
    E --> G[Process Pipeline]
    G --> H[Get Model from Cache]
    H --> I[Translate]
    I --> J[Return Response]
    J --> A

LLMs:

  1. Llama 3 8B: ~16GBLlama 3 70B: ~140GB
  2. Mixtral 8x7B: ~90GBGPT- 4: недоступний для самопідтримання
  3. **Ефект зберігання:**Вимоги виконавців: Лептоп/ Ферма сервера
    • **Деляція процесора NMT:**Дуже добре працює: над двома ядрами процесора, 4GB RAM
    • Зображення Docker: 1,5- 2, 5GBПідсилення: лише процесор, не потрібен GPURetry-AfterВартість: 10- 20/ місячний VPS
  4. **Вимоги LLM:**Llama 3 70B: потребує 80GB+ VRAM (A100 GPU)
    • Менші моделі 7Б- 13Б: Мінімальний об' єм пам' яті 16- 32 ГБ
    • Вартість API: 0. 03- 0. 30 на 1000 марок (додається швидко!)
    • Самопідтримка: $ 1000+/місяця для серйозного GPU
    • Порівняння справжніх витрат для 10 000 перекладів блогу:
  5. Д_ д. д. д. д. д. д. д. д. д. д. д. д. д. д. здебільшого musicid-nmt (CPU)} $20/місяця VPS} 2/3 години}
    • meanslucid-nmt (GPU) сяє/місяця GPU VPS} 15-30 хвилин
    • +GPE-4 API} $50-300} 8-15 годин
    • +300 + 6-00 годин
  6. **♪ Local Llama 70B} $0+/місяцеве обладнання} 20-40 годин ♪**Якість: Purpose-Built vs General- Purpose

**Міць NMT:**Навчені спеціально для перекладуRetry-AfterВідповідна якість (те саме значення, що і вхід = той самий вивід)

Немає " галюцинацій" - чистого перекладу

Визначає технічний вміст, код, добре форматування

Не потрібно негайної інженерії

sequenceDiagram
    participant Client
    participant API
    participant Queue
    participant Translator
    participant Cache
    participant Model

    Client->>API: POST /translate
    API->>Queue: Acquire slot

    alt Queue has space
        Queue-->>API: Slot acquired
        API->>Translator: Process translation
        Translator->>Translator: Sanitize input
        Translator->>Translator: Split sentences
        Translator->>Translator: Chunk text
        Translator->>Translator: Mask symbols
        Translator->>Cache: Get model (en→de)

        alt Cache hit
            Cache-->>Translator: Return cached model
        else Cache miss
            Cache->>Model: Load from Hugging Face
            Model-->>Cache: Pipeline loaded
            Cache->>Cache: Evict old if at capacity
            Cache-->>Translator: Return model
        end

        Translator->>Model: Translate batches
        Model-->>Translator: Translations
        Translator->>Translator: Unmask symbols
        Translator->>Translator: Post-process
        Translator-->>API: Translations
        API->>Queue: Release slot
        API-->>Client: 200 OK + translations
    else Queue full
        Queue-->>API: Overflow error
        API-->>Client: 429 Too Many Requests\nRetry-After: X seconds
    end

Зусилля LLM:

Скрипт прикладу:

graph LR
    A[Raw Input] --> B{Sanitize?}
    B -->|Yes| C[Check Noise]
    B -->|No| D[Split Sentences]
    C -->|Is Noise| Z[Return Placeholder]
    C -->|Valid| D

    D --> E[Enforce Max Length]
    E --> F[Chunk for Batching]
    F --> G{Symbol Masking?}

    G -->|Yes| H[Mask Digits/Punct/Emoji]
    G -->|No| I[Translate]
    H --> I

    I --> J{Direct Model?}
    J -->|Available| K[Direct Translation]
    J -->|Not Available| L{Pivot Fallback?}

    L -->|Yes| M[src→en→tgt]
    L -->|No| Z
    K --> N[Unmask Syis robust input handling. Here's what happens:

**Noise Detection:**
- Strips control characters (except \t, \n, \r)
- Checks minimum character count (default: 1)
- Calculates alphanumeric ratio (default: must be ≥20%)
- Rejects pure emoji, pure punctuation, or pure whitespace

**Symbol Masking:**
Why mask symbols? Translation models are trained on text, not emoji or special symbols. These can confuse them or get mangled. So we:

1. Extract all digits, punctuation, and emoji as contiguous runs
2. Replace them with sentinel tokens: `⟪MSK0⟫`, `⟪MSK1⟫`, etc.
3. Translate the masked text
4. Restore the original symbols in their positions

Example:

Input: "Hello 👋 world! Price: $99.99" Коли використовувати кожен (👋) (!) (:) ($99.99)


**Post-Processing:**
After translation, we remove "symbol loops" - repeated symbols that weren't in the source:

Використовувати NMT (здебільшого вимірюваного- nmt), якщо: Вам потрібен послідовний, швидкий переклад у масштабі Бюджет має значення (збереження або високий об' єм)


### Sentence Splitting & Chunking

Long texts get split intelligently:

```mermaid
graph TD
    A[Long Text] --> B[Split on . ! ? …]
    B --> C{Sentence > 500 chars?}
    C -->|Yes| D[Split on word boundaries]
    C -->|No| E[Keep sentence]
    D --> E

    E --> F[Group into chunks ≤900 chars]
    F --> G[Translate each chunk]
    G --> H[Join with space]

Ви перекладаєте технічний вміст, код, структуровані дані

  • Вам потрібен детермінований вивід (те саме вхід = той самий вивід)
  • Ви хочете працювати на процесорі або на малому обладнанні
  • Ви будуєте автоматичні транспортні труби для перекладу

Використовувати LLM, якщо:

Вам потрібна творча адаптація, а не буквальний переклад

stateDiagram-v2
    [*] --> CheckCache
    CheckCache --> CacheHit: Model exists
    CheckCache --> CacheMiss: Model not loaded

    CacheHit --> MoveToEnd: Update LRU order
    MoveToEnd --> ReturnModel

    CacheMiss --> CheckCapacity
    CheckCapacity --> LoadModel: Space available
    CheckCapacity --> EvictOldest: Cache full

    EvictOldest --> MoveToCPU: Free VRAM
    MoveToCPU --> ClearCUDA: torch.cuda.empty_cache()
    ClearCUDA --> LoadModel

    LoadModel --> AddToCache
    AddToCache --> ReturnModel
    ReturnModel --> [*]

Контекстні та культурні нюанси важливіші, ніж швидкість

  • Ви робите переклади низької кількості, однократні
  • Вам слід перекласти + підсумувати + переписати на один крок
  • Ви в порядку зі змінними витратами і повільнішою обробкою
  • Підсумок
  • for

Автоматний переклад блогу

(мій випадок використання), NMT є ясним переможцем:

# Semaphore limits concurrent translations
MAX_INFLIGHT = 1  # On GPU, 1 at a time for efficiency
MAX_QUEUE_SIZE = 1000  # Up to 1000 waiting

# When full:
# - Returns 429 Too Many Requests
# - Includes Retry-After header
# - Estimates wait time based on average duration

Перекладає дописи 100+ блогів на 12 мов у ~30 хвилин (GPU)

avg_duration = 2.5 seconds (tracked with EMA)
waiters = 100
slots = 1
estimated_wait = (100 / 1) * 2.5 = 250 seconds
clamped = min(250, 120) = 120 seconds
Retry-After: 120

Запускається на $50/місяць VPSName

Послідовна якість для всіх дописів

graph LR
    A[Ukrainian Text] --> B{Direct uk→fr?}
    B -->|Exists| C[Translate Directly]
    B -->|Missing| D[Pivot via English]

    D --> E[uk→en]
    E --> F[en→fr]
    F --> G[French Result]
    C --> G

Загальне налаштування: один контейнер панелі

Спроба скористатися LLM коштувала б сотні доларів на місяць у платі за API або потребувала б сервер GPU на $1.

Лише різниця швидкості робить NMT єдиним практичним вибором для створення транспортних трубопроводів.

ТЛ; ДР:

NMT побудовано з метою перекладу, працює на звичайному апаратному забезпеченні, він є на 10- 100x швидшим за LLM. Якщо вам потрібно швидкий, послідовний, ефективних результатів перекладу на шкалі, NMT перехоплює руки.

# src/core/cache.py
from collections import OrderedDict
import torch

class LRUPipelineCache:
    """LRU cache that automatically cleans up GPU memory when evicting models."""

    def __init__(self, capacity: int):
        self.cache = OrderedDict()  # Maintains insertion order
        self.capacity = capacity

    def get(self, key: str):
        """Get model from cache, moves it to end (most recently used)."""
        if key not in self.cache:
            return None
        self.cache.move_to_end(key)  # Mark as recently used
        return self.cache[key]

    def put(self, key: str, value):
        """Add model to cache, evicting oldest if at capacity."""
        if key in self.cache:
            self.cache.move_to_end(key)
        else:
            self.cache[key] = value

        # If cache is full, evict the oldest model
        if len(self.cache) > self.capacity:
            oldest_key, oldest_pipeline = self.cache.popitem(last=False)

            # MAGIC: Move evicted model to CPU to free GPU memory
            try:
                oldest_pipeline.model.to("cpu")
                if torch.cuda.is_available():
                    torch.cuda.empty_cache()  # Tell GPU to release memory
                logger.info(f"Evicted {oldest_key}, freed GPU memory")
            except Exception as e:
                logger.warning(f"Failed to clean GPU memory: {e}")

Огляд архітектури

  • OrderedDictПотік запиту є простим:
  • Клієнтнадсилає запит на переклад до шлюзу API (Guni жолудів + працівників Uvichor)
  • Шлюз APIШлях до точки завершення перекладу
  • Перевірка місткості: Система перевіряє, чи може вона виконувати запит

Так.

→ Запит негайно відправляється до перекладацької служби

# src/services/model_manager.py
def get_pipeline(self, src: str, tgt: str):
    """Try to get translation model, with automatic fallback to other providers."""

    # Determine which model families support this language pair
    families_to_try = []

    if config.AUTO_MODEL_FALLBACK:
        # Try families in priority order: opus-mt → mbart50 → m2m100
        for family in config.MODEL_FALLBACK_ORDER.split(","):
            if self._is_pair_supported(src, tgt, family.strip()):
                families_to_try.append(family.strip())

    # Try each family until one succeeds
    last_error = None
    for family in families_to_try:
        try:
            model_name, src_lang, tgt_lang, _ = self._get_model_name_and_langs(src, tgt, family)

            if family != config.MODEL_FAMILY:
                logger.info(f"Using fallback '{family}' for {src}->{tgt}")

            # Load the model from HuggingFace
            pipeline = transformers.pipeline(
                "translation",
                model=model_name,
                device=device_manager.device_index,
                src_lang=src_lang,
                tgt_lang=tgt_lang
            )

            self.cache.put(f"{src}->{tgt}", pipeline)
            return pipeline

        except Exception as e:
            last_error = e
            logger.warning(f"Family '{family}' failed for {src}->{tgt}: {e}")
            continue  # Try next family

    # All families failed
    raise ModelLoadError(f"{src}->{tgt}", last_error)

Ні

  • → Запит до черги, клієнт отримує HTTP 429 ззаголовок
  • Служба перекладуобробити запит за допомогою трубопроводу:
  • Вхідне встановлення і розбиття реченьМаскування символів (emojis, спеціальні символи)
  • Переклад за допомогою кешованих моделейСимвол, який розмасшує і остаточно обробляє

Кеш моделей

(LRU) постачає моделі перекладу:

# src/services/queue_manager.py
import asyncio
from contextlib import asynccontextmanager

class QueueManager:
    """Manages request queuing and backpressure."""

    def __init__(self, max_inflight: int, max_queue: int):
        self.semaphore = asyncio.Semaphore(max_inflight)  # Limit concurrent translations
        self.max_queue_size = max_queue
        self.waiting_count = 0
        self.inflight_count = 0
        self.avg_duration_sec = 5.0  # Exponential moving average

    @asynccontextmanager
    async def acquire_slot(self):
        """Try to get a translation slot, track metrics, handle queueing."""

        # Check if queue is too full
        if self.waiting_count >= self.max_queue_size:
            # Calculate how long client should wait before retrying
            retry_after = self._estimate_retry_after()
            raise QueueOverflowError(self.waiting_count, retry_after)

        self.waiting_count += 1
        try:
            # Wait for available slot (this is the queue!)
            await self.semaphore.acquire()
            self.waiting_count -= 1
            self.inflight_count += 1

            start_time = time.time()
            yield  # Let the translation happen

            # Update average duration for retry-after estimates
            duration = time.time() - start_time
            alpha = config.RETRY_AFTER_ALPHA  # Smoothing factor (0.2)
            self.avg_duration_sec = alpha * duration + (1 - alpha) * self.avg_duration_sec

        finally:
            self.inflight_count -= 1
            self.semaphore.release()

    def _estimate_retry_after(self) -> int:
        """Smart calculation: how many waiting / how many slots * avg time per request."""
        if self.inflight_count == 0:
            return config.RETRY_AFTER_MIN_SEC

        # If 10 people waiting and 2 slots available, and each takes 5 seconds:
        # retry_after = (10 / 2) * 5 = 25 seconds
        retry_sec = (self.waiting_count / self.semaphore._value) * self.avg_duration_sec

        # Clamp between min and max
        return max(
            config.RETRY_AFTER_MIN_SEC,
            min(int(retry_sec), config.RETRY_AFTER_MAX_SEC)
        )

Удар кешу → Швидка відповідь

  • Не вистачає кешу → Завантаження з вузлаПовноцінний кеш → Автоматичні старі моделі, прозора пам' ять CUDAmax_inflight)
  • Відповідь (@asynccontextmanagerreturn to client
  • **Дизайн ключів:**Механізм зворотного друку (queue + HTTP 429) запобігає аварійним завершенням під час завантаження.
  • Якщо перевищено, запити з черги послуг замість того, щоб вмерти, надають клієнтам кмітливих спроб череззаголовки.
  • **Як це працює.**Запитувати потоку

Коли надходить запит на переклад, ось що станеться:

Вхідна лінія трубопроводу

# src/utils/symbol_masking.py
import re

def mask_symbols(text: str) -> tuple[str, dict[str, str]]:
    """Replace special symbols with placeholders before translation."""

    originals = {}
    masked_text = text
    placeholder_counter = 0

    # Pattern: Match emojis, symbols, special punctuation
    # \U0001F300-\U0001F9FF = emoji range
    # [\u2600-\u26FF\u2700-\u27BF] = misc symbols
    symbol_pattern = re.compile(
        r'[\U0001F300-\U0001F9FF\u2600-\u26FF\u2700-\u27BF'
        r'\u00A9\u00AE\u2122\u2139\u3030\u303D\u3297\u3299]+'
    )

    for match in symbol_pattern.finditer(text):
        symbol = match.group()
        placeholder = f"__SYMBOL_{placeholder_counter}__"
        originals[placeholder] = symbol
        masked_text = masked_text.replace(symbol, placeholder, 1)
        placeholder_counter += 1

    return masked_text, originals

def unmask_symbols(text: str, originals: dict[str, str]) -> str:
    """Restore original symbols after translation."""
    for placeholder, original in originals.items():
        text = text.replace(placeholder, original)
    return text

Служба використовує складний багатосмуговий трубопровод для обробки безладного тексту реального світу:

# Before translation:
text = "Hello! 👋 Check out this cool feature 🚀"

# Mask symbols:
masked, originals = mask_symbols(text)
# masked = "Hello! __SYMBOL_0__ Check out this cool feature __SYMBOL_1__"
# originals = {"__SYMBOL_0__": "👋", "__SYMBOL_1__": "🚀"}

# Translate the masked text:
translated = translate(masked, "de")  # → "Hallo! __SYMBOL_0__ Schau dir diese coole Funktion an __SYMBOL_1__"

# Unmask symbols:
final = unmask_symbols(translated, originals)
# final = "Hallo! 👋 Schau dir diese coole Funktion an 🚀"

ДЗ: "ось світ має значення MSK0}МСК1 +МСК2 +МСК3"

  • **Джерело: "Привіт світ."**Поганий переклад: "Hola mundo!!!!!!!!!
  • **Очищено: "Hola mundo" # Прибирає!!!**Забезпечення:👋Моделі не задушуються великими входами.__SYMBOL_0__Ми можемо пакетизувати ефективно
  • Контекст зберігається у межахКерування кешуванням і пам'яттю моделей

Кеш LRU є кмітливим щодо пам' яті GPU:

Чому це є важливим:

# src/utils/text_processing.py
def chunk_sentences(sentences: list[str], max_chars: int = 900) -> list[list[str]]:
    """Group sentences into chunks that fit within model's max input length."""

    chunks = []
    current_chunk = []
    current_length = 0

    for sentence in sentences:
        sentence_len = len(sentence)

        # If this sentence alone is too long, it goes in its own chunk
        if sentence_len > max_chars:
            if current_chunk:
                chunks.append(current_chunk)
                current_chunk = []
                current_length = 0
            chunks.append([sentence])
            continue

        # If adding this sentence exceeds limit, start new chunk
        if current_length + sentence_len + 1 > max_chars:
            chunks.append(current_chunk)
            current_chunk = [sentence]
            current_length = sentence_len
        else:
            current_chunk.append(sentence)
            current_length += sentence_len + 1  # +1 for space

    # Don't forget the last chunk!
    if current_chunk:
        chunks.append(current_chunk)

    return chunks

def split_sentences(text: str, max_sentence_chars: int = 500) -> list[str]:
    """Split text into sentences, enforcing max length."""

    # Split on common sentence terminators
    sentences = re.split(r'([.!?…]+\s+)', text)

    result = []
    for sentence in sentences:
        if not sentence or sentence.isspace():
            continue

        # If sentence is too long, split on word boundaries
        if len(sentence) > max_sentence_chars:
            words = sentence.split()
            current = []
            current_len = 0

            for word in words:
                if current_len + len(word) + 1 > max_sentence_chars:
                    result.append(' '.join(current))
                    current = [word]
                    current_len = len(word)
                else:
                    current.append(word)
                    current_len += len(word) + 1

            if current:
                result.append(' '.join(current))
        else:
            result.append(sentence.strip())

    return result

Пам' ять GPU є цінною

  • Моделі перекладу - 300- 500 МБ на коженЗавантаження моделей є повільним (1- 3 секунди).!?…Ми тримаємо 6 найсвіжіших моделей гарячими.
  • **Старі моделі автоматично виселяють.**Черга & зворотного друку
  • **Замість того, щоб завершувати роботу під навантаженням, черги служб просять:**Оцінка повторення є розумною:
  • Повернення до перекладу PivotНе всі пари мов мають прямі моделі гри на обличчі.

Разрешение?

Pivot через англійську:

# src/services/model_discovery.py
import httpx
from datetime import datetime, timedelta

class ModelDiscoveryService:
    """Discovers available translation models with 1-hour cache."""

    def __init__(self):
        self._cache = {}  # Cache results to avoid hammering HuggingFace API
        self._cache_ttl = timedelta(hours=1)
        self._hf_api_base = "https://huggingface.co/api/models"

    async def discover_opus_mt_pairs(self, force_refresh: bool = False):
        """Query HuggingFace for all Helsinki-NLP Opus-MT models."""

        cache_key = "opus-mt"

        # Check cache first
        if not force_refresh and cache_key in self._cache:
            cached_data, cached_time = self._cache[cache_key]
            if datetime.now() - cached_time < self._cache_ttl:
                return cached_data  # Cache hit!

        # Cache miss - query HuggingFace API
        async with httpx.AsyncClient() as client:
            response = await client.get(
                self._hf_api_base,
                params={
                    "author": "Helsinki-NLP",
                    "search": "opus-mt",
                    "limit": 1000
                },
                timeout=30.0
            )
            models = response.json()

        # Extract language pairs from model names
        # Example: "Helsinki-NLP/opus-mt-en-de" → ("en", "de")
        pairs = []
        for model in models:
            model_id = model.get("modelId", "")
            if model_id.startswith("Helsinki-NLP/opus-mt-"):
                # Extract the language codes after "opus-mt-"
                lang_part = model_id.replace("Helsinki-NLP/opus-mt-", "")
                if "-" in lang_part:
                    src, tgt = lang_part.split("-", 1)
                    pairs.append({"source": src, "target": tgt})

        # Cache the results
        self._cache[cache_key] = (pairs, datetime.now())

        return pairs

Це подвоює спізнення, але забезпечує покриття всіх пар мов, які підтримуються.

  • Глибокий об' єм коду: придатні для зміни можливості (httpxДавайте дослідимо деякі з найцікавіших частин бази коду!
  • **Це справжні виробничі моделі, які роблять службу стійкою і ефективною.**У кожному фрагменті містяться пояснення, що відповідають розробникам, що не належать до Python.
  • **1.**Кмітливий кеш LRU з керування пам'яттю GPUenОднією з найкрутіших можливостей є кеш з кмітливою моделлю, який знає як обробляти пам' ять GPU:deЩо тут відбувається?Helsinki-NLP/opus-mt-en-de
  • : Як звичайний словник, але пам'ятайте про порядок, який було доданоLRU (Найменш недавно використана)

: Коли кеш переповнений, викиньте модель, яка не використовується у найдовший час

Очищення GPU

# src/core/device.py
import torch

class DeviceManager:
    """Smart device selection with GPU auto-detection."""

    def __init__(self):
        self.use_gpu = self._should_use_gpu()
        self.device_index = self._resolve_device()
        self.device_str = "cpu" if self.device_index < 0 else f"cuda:{self.device_index}"

        # Auto-configure parallel translation slots based on device
        if self.device_index >= 0:
            # GPU: Run translations serially to avoid VRAM fragmentation
            self.max_inflight = 1
        else:
            # CPU: Can handle multiple translations in parallel
            self.max_inflight = config.MAX_WORKERS_BACKEND

        self._log_device_info()

    def _should_use_gpu(self) -> bool:
        """Check if GPU should be used."""
        if config.USE_GPU.lower() == "false":
            return False
        if config.USE_GPU.lower() == "true":
            return torch.cuda.is_available()
        # "auto" mode: use GPU if available
        return torch.cuda.is_available()

    def _resolve_device(self) -> int:
        """Returns device index: -1 for CPU, 0+ for CUDA."""
        if not self.use_gpu:
            return -1

        # Check if specific CUDA device requested
        if config.DEVICE and config.DEVICE.startswith("cuda:"):
            device_num = int(config.DEVICE.split(":")[1])
            return device_num

        return 0  # Use first GPU

    def _log_device_info(self):
        """Log device information at startup."""
        if self.device_index >= 0:
            gpu_name = torch.cuda.get_device_name(self.device_index)
            vram_gb = torch.cuda.get_device_properties(self.device_index).total_memory / 1e9
            logger.info(f"Using GPU: {gpu_name} ({vram_gb:.1f}GB VRAM)")
            logger.info(f"Max inflight translations: {self.max_inflight} (GPU mode)")
        else:
            cpu_count = os.cpu_count()
            logger.info(f"Using CPU ({cpu_count} cores)")
            logger.info(f"Max inflight translations: {self.max_inflight} (CPU mode)")

# Global singleton instance
device_manager = DeviceManager()

: Виселяючи модель, ми явно переносимо її до процесорної пам' яті і наказуємо GPU випускати свої ресурси

  • Чому це важливо: Без цього, пам'ять GPU заповнювалась б і заповнилась б після завантаження 2-3 моделей!
  • **2.**Повернення до автоматичної моделі сім' їmax_inflight=1Ця кмітлива можливість автоматично перевіряє декілька постачальників комп' ютерної моделі, якщо перша пара не має потрібної пари мов:max_inflight=4Що тут відбувається?
  • Ланцюжок зворотного зв' язку: Якщо Opus-MT не має українською → французькою, спробуйте автоматично mBART50, то M2M100DEVICE=cuda:1
  • Без втручання вручну: Користувачі просто вимагають перекладу і отримують найкращу модель
  • Обробка помилок: Якщо всі сім'ї зазнають невдачі, ми помиляємося з останньою причиною невдачі.

Кмітливе кешування

: Успішні моделі захаращуються ключем до мови

# Snippet from QueueManager showing EMA calculation
def update_avg_duration(self, new_duration: float):
    """Update average duration using exponential moving average."""

    # EMA formula: new_avg = α × new_value + (1 - α) × old_avg
    # α = smoothing factor (0.0 to 1.0)
    #   - Higher α = more weight to recent values (faster adaptation)
    #   - Lower α = more weight to historical values (more stable)

    alpha = 0.2  # 20% weight to new value, 80% to historical

    self.avg_duration_sec = (
        alpha * new_duration +
        (1 - alpha) * self.avg_duration_sec
    )

3.

# Initial average: 5.0 seconds
# New request takes: 10.0 seconds

# EMA calculation:
new_avg = 0.2 * 10.0 + 0.8 * 5.0
        = 2.0 + 4.0
        = 6.0 seconds

# Next request takes: 3.0 seconds
new_avg = 0.2 * 3.0 + 0.8 * 6.0
        = 0.6 + 4.8
        = 5.4 seconds

Запит у чергу з Burpressure (HTTP 429)

  • **Програма для виконання завдань, які запобігають аварійному завершенню роботи сервера під важким навантаженням:**Що тут відбувається?
  • Semaphore: Як каскадер у клубі, тільки дозволяє N людям увійти одночасно (N =)
  • Менеджер контексту): Автоматично стежити за вимірами і очистити
  • Кмітлива повторна спроба: Повідомляє клієнтам "приходьте через 25 секунд" на основі глибини черги і середньої кількості запитівRetry-AfterЕкспоненціальний рух середньостатистичний

: Згладжує шипи у час запиту

  • Чому це важливо: Під важким навантаженням повертає HTTP 429 замість аварійного аварійного завершення або нескінченної черги
  • **4.**Магія маскування символів
  • **Зберігати спеціальні символи (емоджіс, символи), які можуть зіпсувати моделі перекладу:**Використання прикладу:
  • **Що тут відбувається?**Шаблон формального виразу
  • : Порівнює emoji і особливого символу діапазону UnicodeСистема заповнювача
  • : Поміняти місцямина

тимчасово

Чому це важливо

: Моделі перекладу деколи руйнують або усувають емоджі - це зберігає їх у досконалому стані!

5.

# Prefer GPU if available (default)
USE_GPU=auto

# Force GPU
USE_GPU=true

# Force CPU
USE_GPU=false

# Explicit device override
DEVICE=cuda:0
DEVICE=cpu

Інтелектуальна текстова розшифровка

# Model family selection (NEW in v2.0!)
MODEL_FAMILY=opus-mt   # Best quality (default)
MODEL_FAMILY=mbart50   # 50 languages, single model
MODEL_FAMILY=m2m100    # 100 languages, maximum coverage

# Auto-fallback between model families (NEW in v2.0!)
AUTO_MODEL_FALLBACK=1  # Enabled by default
MODEL_FALLBACK_ORDER="opus-mt,mbart50,m2m100"  # Priority order

# Volume-mapped model cache (NEW in v2.0!)
MODEL_CACHE_DIR=/models  # Persistent cache directory

# Model arguments passed to transformers.pipeline
EASYNMT_MODEL_ARGS='{"torch_dtype":"fp16"}'
EASYNMT_MODEL_ARGS='{"torch_dtype":"bf16","cache_dir":"/models"}'

# Preload models at startup (reduces first-request latency)
PRELOAD_MODELS="en->de,de->en,fr->en"

# LRU cache capacity
MAX_CACHED_MODELS=6

Розбиває довгі тексти на шматки, які відповідають моделяційним обмеженням під час збереження меж речень:

  • **Що тут відбувається?**Розбиття речень

    • opus-mt: Застосовує regex для поділу на
    • mbart50під час збереження пунктуації
    • m2m100Жадібний кусень
  • : пакує якомога більше речень до кожного шматка без перевищення обмеженняПоділ на межі слова

    • 1: Якщо одне речення задовге, розбиття на пробіли замість скорочення середнього слова
    • 0Чому це важливо
  • **: Моделі перекладу мають вхідні обмеження (зазвичай, 512- 1024 маркерів).**Це гарантує, що ми ніколи не перевищимо їх, зберігаючи контекст непошкодженим.

    • 6."opus-mt,mbart50,m2m100"Асинхронне відкриття моделі з кешуванням
    • Динамічне виявлення доступних моделей перекладу за допомогою Hraging Face:"m2m100,mbart50,opus-mt"Що тут відбувається?
  • Асинхронний клієнт HTTP): Робить неблоковані запити HTTP до обрізування лисиці

    • Кечування, засноване на часі/models: зберігає результати протягом однієї години, щоб уникнути обмеження швидкості-v ./model-cache:/models
    • Обробка назв моделей
    • : Видобування

і

  • fp16від
  • bf16Чому це важливо
  • fp32: У Hacking Face є 1200+ Моделі Operus-MT.

Обыскать их все займет 10 секунд.

# Batch size for translation (higher = faster but more VRAM)
EASYNMT_BATCH_SIZE=16  # CPU: 8-16, GPU: 32-64

# Maximum text length per item
EASYNMT_MAX_TEXT_LEN=1000

# Maximum beam size (higher = better quality but slower)
EASYNMT_MAX_BEAM_SIZE=5

# Worker thread pools
MAX_WORKERS_BACKEND=1    # Translation workers
MAX_WORKERS_FRONTEND=2   # Language detection workers

Качування робить це миттєво!

# Enable request queueing (highly recommended)
ENABLE_QUEUE=1

# Max concurrent translations
# Auto: 1 on GPU, MAX_WORKERS_BACKEND on CPU
MAX_INFLIGHT_TRANSLATIONS=1

# Max queued requests before 429
MAX_QUEUE_SIZE=1000

# Per-request timeout (0 = disabled)
TRANSLATE_TIMEOUT_SEC=180

# Retry-After estimation
RETRY_AFTER_MIN_SEC=1      # Floor
RETRY_AFTER_MAX_SEC=120    # Ceiling
RETRY_AFTER_ALPHA=0.2      # EMA smoothing factor

7.

# Enable input filtering
INPUT_SANITIZE=1

# Minimum alphanumeric ratio (0.2 = 20%)
INPUT_MIN_ALNUM_RATIO=0.2

# Minimum character count
INPUT_MIN_CHARS=1

# Language code for undetermined/noise
UNDETERMINED_LANG_CODE=und

Автоматичне визначення пристрою

# Default sentence splitting behavior
PERFORM_SENTENCE_SPLITTING_DEFAULT=1

# Max chars per sentence before word-boundary split
MAX_SENTENCE_CHARS=500

# Max chars per chunk for batching
MAX_CHUNK_CHARS=900

# Sentence joiner
JOIN_SENTENCES_WITH=" "

Автоматично виявляти і використовувати GPU, якщо це можливо:

# Enable symbol masking
SYMBOL_MASKING=1

# What to mask
MASK_DIGITS=1    # Mask 0-9
MASK_PUNCT=1     # Mask .,!? etc.
MASK_EMOJI=1     # Mask 😀🎉 etc.

Що тут відбувається?

# Align response array length to input
ALIGN_RESPONSES=1

# Placeholder for failed items (when aligned)
SANITIZE_PLACEHOLDER=""

# Response format
EASYNMT_RESPONSE_MODE=strings    # ["translation1", "translation2"]
EASYNMT_RESPONSE_MODE=objects    # [{"text":"translation1"}, ...]

Визначення GPU

# Enable two-hop translation via pivot
PIVOT_FALLBACK=1

# Pivot language (usually English)
PIVOT_LANG=en

: Використовуйте PyTorch для перевірки наявності CUDA

# Log level
LOG_LEVEL=INFO

# Per-request logging (verbose)
REQUEST_LOG=1

# Format
LOG_FORMAT=plain    # Human-readable
LOG_FORMAT=json     # Structured JSON

# File logging with rotation
LOG_TO_FILE=1
LOG_FILE_PATH=/var/log/marian-translator/app.log
LOG_FILE_MAX_BYTES=10485760    # 10MB
LOG_FILE_BACKUP_COUNT=5

# Include raw text in logs (privacy risk!)
LOG_INCLUDE_TEXT=0

Автоматичне налаштування

# Periodically clear CUDA cache (seconds, 0=disabled)
CUDA_CACHE_CLEAR_INTERVAL_SEC=0

: Набори

# Worker count (use 1 for single GPU)
WEB_CONCURRENCY=1

# Request timeout
TIMEOUT=60

# Graceful shutdown timeout
GRACEFUL_TIMEOUT=20

# Keep-alive timeout
KEEP_ALIVE=5

на GPU (обмежена фрагментація VRAM) проти

на процесорі (максичний паралелізм)

# GET request
curl "http://localhost:8000/translate?target_lang=de&text=Hello%20world&source_lang=en"

# Response
{
  "translations": ["Hallo Welt"]
}

Вибір пристрою

# POST request
curl -X POST http://localhost:8000/translate \
  -H 'Content-Type: application/json' \
  -d '{
    "text": [
      "Hello world",
      "This is a test",
      "Machine translation is amazing"
    ],
    "target_lang": "de",
    "source_lang": "en",
    "beam_size": 1,
    "perform_sentence_splitting": true
  }'

# Response
{
  "target_lang": "de",
  "source_lang": "en",
  "translated": [
    "Hallo Welt",
    "Das ist ein Test",
    "Maschinenübersetzung ist erstaunlich"
  ],
  "translation_time": 0.342
}

: Може бути специфічна GPU за допомогою

# Omit source_lang for auto-detection
curl -X POST http://localhost:8000/translate \
  -H 'Content-Type: application/json' \
  -d '{
    "text": ["Bonjour le monde"],
    "target_lang": "en"
  }'

# Response
{
  "target_lang": "en",
  "source_lang": "fr",  # Detected
  "translated": ["Hello world"],
  "translation_time": 0.156
}

Журналювання

# GET
curl "http://localhost:8000/language_detection?text=Hola%20mundo"
# {"language": "es"}

# POST with batch
curl -X POST http://localhost:8000/language_detection \
  -H 'Content-Type: application/json' \
  -d '{"text": ["Hello", "Bonjour", "Hola"]}'
# {"languages": ["en", "fr", "es"]}

: Показує назву GPU і VRAM під час запуску для зневаджування

# Health check
curl http://localhost:8000/healthz
# {"status": "ok"}

# Readiness
curl http://localhost:8000/readyz
# {
#   "status": "ready",
#   "device": "cuda:0",
#   "queue_enabled": true,
#   "max_inflight": 1
# }

# Cache status
curl http://localhost:8000/cache
# {
#   "capacity": 6,
#   "size": 3,
#   "keys": ["en->de", "de->en", "fr->en"],
#   "device": "cuda:0",
#   "inflight": 1,
#   "queue_enabled": true
# }

# Model info
curl http://localhost:8000/model_name | jq

Шаблон Sington

# When queue is full, you get 429
curl -X POST http://localhost:8000/translate \
  -H 'Content-Type: application/json' \
  -d '{"text": ["test"], "target_lang": "de"}'

# Response: 429 Too Many Requests
# Headers: Retry-After: 45
# Body:
{
  "message": "Too many requests; queue full",
  "retry_after_sec": 45
}

# Proper client behavior:
# 1. Read Retry-After header
# 2. Wait that long + jitter
# 3. Retry request

: Один приклад, що був поділений на всю програму

Експонентне рухоме середнє для повторень після

Плавна повторна оцінка, яка пристосовується до поточної тривалості запиту:

Приклад:

.\build-all.ps1

Що тут відбувається?

chmod +x build-all.sh
./build-all.sh

EMA (Expential рухове середнє)

: Подібно до середньої ваги, яка надає більшої ваги недавнім цінностям.Коефіцієнт згладжування (⇩):

  1. : Керує тим, як швидко ми пристосовуємося до змін (latest, min, gpu, gpu-minЧому це не є тільки середньостатистичний?
  2. : EMA швидше адаптується до змін під час фільтрування шипівЧому це важливо20250108.143022: Надає клієнтам реалістичну інформацію

час, який слід застосувати до поточного навантаження на систему

# Always get the latest version
docker pull scottgal/mostlylucid-nmt:cpu
# Or use the :latest alias
docker pull scottgal/mostlylucid-nmt:latest

# Pin to a specific version for reproducibility
docker pull scottgal/mostlylucid-nmt:cpu-20250108.143022
docker pull scottgal/mostlylucid-nmt:cpu-min-20250108.143022

Ці шаблони коду демонструють методи виробництва Python:

Керування виконавцями

  • : Явне очищення пам' яті GPUМилосердна деградація
  • : Автоматичне повернення між постачальниками моделейРобота з компенсацією
  • : Черга + HTTP 429 замість аварійного завершенняЦілісність даних
  • : Маскування символів зберігає спеціальні символиОптимізація швидкодії

: Кмітливий кеш, кусочок і паралельна обробка

docker inspect scottgal/mostlylucid-nmt:cpu | jq '.[0].Config.Labels'

Спостереження: Детальне стеження за лісозаготівлею і вимірами.

Кожна з цих можливостей вирішує справжню проблему виробництва, яка могла б спричинити катастрофи, помилки або поганий досвід користувача без них!

Довідник з налаштування

# Using pre-built image from Docker Hub (recommended)
docker run -d \
  --name translator \
  -p 8000:8000 \
  -e ENABLE_QUEUE=1 \
  -e MAX_QUEUE_SIZE=500 \
  -e EASYNMT_BATCH_SIZE=16 \
  -e TIMEOUT=180 \
  -e LOG_LEVEL=INFO \
  -e REQUEST_LOG=0 \
  scottgal/mostlylucid-nmt

# Or build locally
docker build -t mostlylucid-nmt .
docker run -d --name translator -p 8000:8000 mostlylucid-nmt

# Check logs
docker logs -f translator

Службу можна налаштувати за допомогою змінних середовища.

# Using pre-built GPU image from Docker Hub (recommended)
docker run -d \
  --name translator-gpu \
  --gpus all \
  -p 8000:8000 \
  -e USE_GPU=true \
  -e DEVICE=cuda:0 \
  -e PRELOAD_MODELS="en->de,de->en,en->fr,fr->en,en->es,es->en" \
  -e EASYNMT_MODEL_ARGS='{"torch_dtype":"fp16"}' \
  -e EASYNMT_BATCH_SIZE=64 \
  -e MAX_CACHED_MODELS=8 \
  -e ENABLE_QUEUE=1 \
  -e MAX_QUEUE_SIZE=2000 \
  -e WEB_CONCURRENCY=1 \
  -e TIMEOUT=180 \
  -e GRACEFUL_TIMEOUT=30 \
  -e LOG_FORMAT=json \
  -e LOG_TO_FILE=1 \
  -v /var/log/translator:/var/log/marian-translator \
  scottgal/mostlylucid-nmt:gpu

# Or build locally
docker build -f Dockerfile.gpu -t mostlylucid-nmt:gpu .
docker run -d --name translator-gpu --gpus all -p 8000:8000 mostlylucid-nmt:gpu

# Monitor cache and performance
watch -n 5 "curl -s http://localhost:8000/cache | jq"

Ось повний провідник:

version: '3.8'

services:
  translator:
    image: scottgal/mostlylucid-nmt:gpu  # Use pre-built image
    container_name: translator
    restart: unless-stopped

    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

    ports:
      - "8000:8000"

    environment:
      USE_GPU: "true"
      DEVICE: "cuda:0"
      PRELOAD_MODELS: "en->de,de->en,en->fr,fr->en"
      EASYNMT_MODEL_ARGS: '{"torch_dtype":"fp16"}'
      EASYNMT_BATCH_SIZE: "64"
      MAX_CACHED_MODELS: "8"
      ENABLE_QUEUE: "1"
      MAX_QUEUE_SIZE: "2000"
      WEB_CONCURRENCY: "1"
      TIMEOUT: "180"
      LOG_FORMAT: "json"
      LOG_TO_FILE: "1"

    volumes:
      - translator-logs:/var/log/marian-translator
      - translator-cache:/root/.cache/huggingface

    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

volumes:
  translator-logs:
  translator-cache:

Вибір пристрою

apiVersion: apps/v1
kind: Deployment
metadata:
  name: translator
spec:
  replicas: 2  # Scale horizontally for CPU, use 1 per GPU
  selector:
    matchLabels:
      app: translator
  template:
    metadata:
      labels:
        app: translator
    spec:
      containers:
      - name: translator
        image: scottgal/mostlylucid-nmt:gpu
        ports:
        - containerPort: 8000
        env:
        - name: USE_GPU
          value: "true"
        - name: EASYNMT_MODEL_ARGS
          value: '{"torch_dtype":"fp16"}'
        - name: PRELOAD_MODELS
          value: "en->de,de->en"
        - name: ENABLE_QUEUE
          value: "1"
        - name: MAX_QUEUE_SIZE
          value: "2000"

        resources:
          requests:
            memory: "4Gi"
            cpu: "2"
            nvidia.com/gpu: 1
          limits:
            memory: "8Gi"
            cpu: "4"
            nvidia.com/gpu: 1

        livenessProbe:
          httpGet:
            path: /healthz
            port: 8000
          initialDelaySeconds: 30
          periodSeconds: 10

        readinessProbe:
          httpGet:
            path: /readyz
            port: 8000
          initialDelaySeconds: 20
          periodSeconds: 5

---
apiVersion: v1
kind: Service
metadata:
  name: translator
spec:
  selector:
    app: translator
  ports:
  - port: 80
    targetPort: 8000
  type: LoadBalancer

Налаштування моделі

Пояснення нових налаштувань:

  1. MODEL_ FAMILY

    EASYNMT_MODEL_ARGS='{"torch_dtype":"fp16"}'
    
    • : Виберіть модель сім'ї, яку слід використовувати як основну
    • : Найкраща якість, 1200+параметрів, окремі моделі
    • : хороша якість, 50 мовами, єдина модель 2.4GB
  2. : хороша якість, 100 мов, єдина модель 2.2 ГБ

    # Start high, reduce if you get OOM
    EASYNMT_BATCH_SIZE=64  # Try 128 on large GPUs
    
  3. AUTO_ MODEL_ FALLBACK

    PRELOAD_MODELS="en->de,de->en,en->fr,fr->en,en->es,es->en"
    
  4. : Автоматично випробовувати інші сім' ї, якщо пара недоступна

    WEB_CONCURRENCY=1
    MAX_INFLIGHT_TRANSLATIONS=1
    
  5. (типовий): увімкнено - максимальна обкладинка

    MAX_CACHED_MODELS=10  # Keep more models in VRAM
    
  6. : Непрацездатний - строгий режим однієї сім'ї

    # beam_size=1 is 3-5x faster than beam_size=5
    # Quality difference is often minimal
    curl -X POST ... -d '{"beam_size": 1, ...}'
    

MODEL_ FALLBACK_ ORDER

  1. : Порядок пріоритету для повернення назад

    EASYNMT_BATCH_SIZE=8
    
  2. Типове значення:

    MAX_WORKERS_BACKEND=4
    MAX_INFLIGHT_TRANSLATIONS=4
    WEB_CONCURRENCY=2
    
  3. (перший якість)

    PERFORM_SENTENCE_SPLITTING_DEFAULT=0
    

Альтернативний:

  1. (перший захист)

    // Bad: 100 separate requests
    for (const text of texts) {
      await translate(text);
    }
    
    // Good: 1 batch request
    await translate(texts);
    
  2. MODEL_ CCHE_ DIR

    async function translateWithRetry(texts) {
      try {
        return await translate(texts);
      } catch (err) {
        if (err.status === 429) {
          const retryAfter = err.headers['retry-after'];
          const jitter = Math.random() * 5;
          await sleep((retryAfter + jitter) * 1000);
          return translateWithRetry(texts);
        }
        throw err;
      }
    }
    
  3. : Постійне взірцеве сховище на основі томів докерів.

    // Reuse HTTP connections
    const agent = new https.Agent({ keepAlive: true });
    
  4. Встановити до

    // Bad: mixed language pairs in one request
    translate([
      { text: "Hello", sourceLang: "en", targetLang: "de" },
      { text: "Bonjour", sourceLang: "fr", targetLang: "de" }
    ]);
    
    // Good: group by language pair
    translateBatch(enToDe, "en", "de");
    translateBatch(frToDe, "fr", "de");
    

і об' єм карти:

Модели, що продовжуються через перезапуск контейнера

  1. Спільний кеш між декількома контейнерамипараметри flash_ dtype:
  2. (float16): 2x швидше на GPU, половина пам'яті, незначна втрата якості(bfloat16): Краща числова стабільність за fp16, потребує сучасні GPU
  3. (float32): Повна точність, найповільніша, але найточнішаПараметри перекладів
  4. & Швидкодія у черзіЗасновування вхідних даних
  5. Обробка реченняМаскування символів
  6. Поведінка відповідіПовернення Pivot
  7. ЖурналюванняСупровід

Gunicorn (Docker)

Приклади використання

translation_requests_total{lang_pair="en->de",status="success"} 1523
translation_requests_total{lang_pair="en->de",status="error"} 7
translation_duration_seconds{lang_pair="en->de",quantile="0.5"} 0.342
translation_duration_seconds{lang_pair="en->de",quantile="0.95"} 1.234
translation_queue_depth 23
translation_cache_size 6
translation_cache_hits_total 8234
translation_cache_misses_total 142

Основний переклад

# Enable JSON logging
LOG_FORMAT=json REQUEST_LOG=1

# Output example
{
  "ts": "2025-01-08T15:30:45+0000",
  "level": "INFO",
  "name": "app",
  "message": "translate_post done items=5 dt=0.342s",
  "req_id": "a3d2f5b1-c4e6-4f7a-9d8c-1e2f3a4b5c6d",
  "endpoint": "/translate",
  "src": "en",
  "tgt": "de",
  "items": 5,
  "duration_ms": 342
}

Пакетний переклад (рекомендовано)

Автовиявлення мови

Лише виявлення мови |---------|---------|-----------------| | Точка завершення спостереженняЯк справлятися з придушенням | Будівництво і перекладТепер у всіх зображеннях Docker міститься відповідна версія і метадані для стеження. | Швидке збиранняЗібрати всі 4 варіанти з автоматичною версією дати: | **Вікна:**Linux/Mac: | Стратегія перекладуСтворення кожної збірки | два міткиМітка з назвою | ) - завжди вказує на останніМітка версії | (e.g.,) - незмінний знімок | **Приклади:**Мітки OCI | **Кожне зображення містить метадані:**Версія | **: Часовий штамп збирання (РРРРМРРД. ГГМСС)**Дата збирання | : ISO 8601 Часовий штампGit- внески

: Коротка SHA

Варіант

: cpu- full, cpu- min, gpu- full або gpu- minПеревірка міток:

Докладніші настанови щодо збирання і інтеграції CI/CD можна знайти у розділі

  • BUILD. mdMAX_QUEUE_SIZE
  • Впровадження
  • Впровадження процесораMAX_INFLIGHT_TRANSLATIONSВпровадження GPU
  • Докер Композитний

Взаємозв'язок Kubernetes

Оптимізація швидкодіїСписок перевірок Оптимізації GPU

Використовувати точність FP16

  • 2x швидких підрахунківENABLE_QUEUE=1
  • Половина використання VRAM

Нелегальна втрата якості для перекладу

Пакетний розмірЗаздалегідь завантажувати гарячі моделі

Один працівник на GPU

  • Збільшити розмір кешуEASYNMT_BATCH_SIZE
  • Нижній розмір променя для протокиMAX_CACHED_MODELS
  • Оптимізація ЦПEASYNMT_MODEL_ARGS='{"torch_dtype":"fp16"}'
  • Нижній розмір пакетаWEB_CONCURRENCY=1Збільшує паралелізмMAX_INFLIGHT_TRANSLATIONS=1

Вимкнути розбиття речень для коротких текстів

Найкращі вправи клієнтаПакетні запити

Повага до повторних спроб

PRELOAD_MODELS="en->de,de->en"

Використовувати набір з' єднань

Група за парою мов Helsinki-NLP/opus-mt-{src}-{tgt}Спостереження за і спостереженням

Метрика клавіш для стеження

  • Перекласти через сітківкуPIVOT_FALLBACK=1(запити/ сек)
  • Середня спізненняcurl http://localhost:8000/lang_pairs

(p50, p95, p99)

Глибина черги(поточний рахунок очікування)

Частота влучання у кеш

  • (% від запитів до кешу)MASK_EMOJI=0Частота помилокMASK_PUNCT=0
  • (5xx відповідей)SYMBOL_MASKING=0

Програма GPU

(якщо можна застосувати)

public class MostlyLucidNmtClient
{
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl;

    public MostlyLucidNmtClient(HttpClient httpClient, string baseUrl)
    {
        _httpClient = httpClient;
        _baseUrl = baseUrl;
    }

    public async Task<TranslationResponse> TranslateAsync(
        List<string> texts,
        string targetLang,
        string sourceLang = "",
        int beamSize = 1,
        bool performSentenceSplitting = true,
        CancellationToken cancellationToken = default)
    {
        var request = new TranslationRequest
        {
            Text = texts,
            TargetLang = targetLang,
            SourceLang = sourceLang,
            BeamSize = beamSize,
            PerformSentenceSplitting = performSentenceSplitting
        };

        var response = await _httpClient.PostAsJsonAsync(
            $"{_baseUrl}/translate",
            request,
            cancellationToken);

        if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
        {
            // Read Retry-After header
            var retryAfter = response.Headers.RetryAfter?.Delta?.TotalSeconds ?? 30;
            var jitter = Random.Shared.Next(0, 5);
            await Task.Delay(TimeSpan.FromSeconds(retryAfter + jitter), cancellationToken);

            // Retry
            return await TranslateAsync(texts, targetLang, sourceLang, beamSize,
                performSentenceSplitting, cancellationToken);
        }

        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<TranslationResponse>(cancellationToken);
    }
}

public class TranslationRequest
{
    [JsonPropertyName("text")]
    public List<string> Text { get; set; }

    [JsonPropertyName("target_lang")]
    public string TargetLang { get; set; }

    [JsonPropertyName("source_lang")]
    public string SourceLang { get; set; }

    [JsonPropertyName("beam_size")]
    public int BeamSize { get; set; }

    [JsonPropertyName("perform_sentence_splitting")]
    public bool PerformSentenceSplitting { get; set; }
}

public class TranslationResponse
{
    [JsonPropertyName("target_lang")]
    public string TargetLang { get; set; }

    [JsonPropertyName("source_lang")]
    public string SourceLang { get; set; }

    [JsonPropertyName("translated")]
    public List<string> Translated { get; set; }

    [JsonPropertyName("translation_time")]
    public double TranslationTime { get; set; }
}

Використання пам' яті

services.AddHttpClient<MostlyLucidNmtClient>(client =>
{
    client.BaseAddress = new Uri("http://translator:8000");
    client.Timeout = TimeSpan.FromMinutes(3);
});

(VRAM для GPU, RAM для процесора)

Приклад Метриці Prometheus**Якщо ви інтегруєте Prometheus (не вбудовано, але просто додати):**Приклад структурованого журналу

Ви можете передавати цю інформацію до Elatisicalsearch, HavyWatch, або до будь - якого лісозаготівельного агресора.

Порівняння: EasyNMT vs Mis Lucid- NMT

  • Ті-Мт- д'Івуар- НМТ*
  • Стабільність
  • Переваги. Часті помилки.

Обробка вхідних даних

  • Має значення seoji/ symbens ® Roust saentifiation + charching}
  • Пригнічення
  • ♪ None, OOMs під завантаженням ♪ Semaphore + queue with reep-

Спостереження

  • Дівчата/Райка/Вашний кінцевий пункт, структура цілих дробів
  • Підтримка GPU
  • Керування моделями

, без cashine LRU cache with auto- evicce}

  • Робота з реченнями
  • ♪ Кмітливо}*
  • Переклад Pivot
  • Ні - автоматичне повернення назад через англійську #
  • Милосердне вимикання

♪ Ні ♪ Так, з'являється ♪

Налаштування** 40 + env vars для тонкої тиші**Сумісність API

♪ TYNMT кінцеві пункти} 100% сумісні + розширення ♪

  • Якість кодуДзвінок, Моношка, няня, випробуваний
  • Вирішення проблем429 забагато запитів
  • **Причина:**Черга повна.
  • **Вирішення:**Збільшити
  • **Додати більше копій (горизонтальне масштабування)**Збільшити
  • **(якщо у вас є універмаг)**Зменшити розмір пакетів від клієнтів
  • 503 Служба недоступнаПричина:
  • **Чергування вимкнене і всі слоти зайняті.**Вирішення:

Увімкнути чергування:

# Maximum coverage with auto-fallback (recommended!)
docker run -d -p 8000:8000 \
  -v ./model-cache:/models \
  -e MODEL_CACHE_DIR=/models \
  -e AUTO_MODEL_FALLBACK=1 \
  -e MODEL_FALLBACK_ORDER="opus-mt,mbart50,m2m100" \
  scottgal/mostlylucid-nmt:cpu-min

# GPU with best quality
docker run -d --gpus all -p 8000:8000 \
  -e USE_GPU=true \
  -e MODEL_FAMILY=opus-mt \
  -e EASYNMT_MODEL_ARGS='{"torch_dtype":"fp16"}' \
  scottgal/mostlylucid-nmt:gpu

# Test it
curl -X POST http://localhost:8000/translate \
  -H 'Content-Type: application/json' \
  -d '{"text": ["Hello world"], "target_lang": "de"}'

Підвищити обмеження inflight, якщо у вас є ресурси

OOM (Не пам' ять) на GPU

Причина:

Пакетний розмір занадто високий або забагато моделей збережено.


Вирішення:

і

Повільне перше прохання[Причина:

Модель не попередньо завантажено.

Translation NMT Neural Machine Translation Python FastAPI Docker CUDA PyTorch Transformers Helsinki-NLP Production Microservices API

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.