Будівництво three lumcid-nmt: Production- ready (EasyNMT сумісне) Translation Service
Вступ
Реалізація FastAPI EXACT копіює чудовий, але покинутий проект роботи з нейронним апаратом. https: // gitub.com/UKPLAB/EasyNMT).
Але я додав БАГАТЬОХ гарних рис, щоб збільшити надійність і підготувати її до використання у виробничій системі.Думайте про те, що швидкий переклад сам підтримується...).
З самого початку цього блогу, великим захопленням стали статті у автотрансляційних блогах.
ТАК Я знаю, що "Google робить це в браузерах і т.д., але справа не в цьому.mostlylucid-nmtЯ хотіла знати, як це зробити!
Крім того, приємно вітати людей, які не читають англійською (навіть якщо вони читають англійську як другу мову, це важче опрацювати).Тож я вирішив, як це зробити, і поділився тим, як побудувати таку систему.О, і вона дала мені ідеї щодо того, як використовувати текст у ASP.NET для автоматичного локалізації тексту (включаючи динамічний текст) за допомогою SNR & хитрої системи оновлення реального часу. (
Залишайтеся на зв'язкуПо суті, люди пишуть нісенітниці текст, який є ДУЖЕ шумним для машин, щоб ефективно поводитися.
Отже, багато з них з'ясовували, як працювати з FasyNMT (це був справді дослідний проект).
що дозволяє мені обом розвиватися так само добре, як тобі піти на гру.
Iзаписано цілу системуhttp://<server>:<port>/demoщоб це сталося з чудовим проектом під назвою EasyNMT.
ЯК ЖЕ, якщо ви тільки-но перевірили, що експропріатор, ви знаєте, є проблема... вона не була зворушена протягом РОКІВ.
Це простий, швидкий спосіб отримати 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) - : знаходить мови, де існують ноги-поворотні лінії BOTH
Model 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+пари, найкраща якість (вимірювання моделей)
- mBART50
latest,min,gpu,gpu-min: 50 мов, єдина модель 2.4GB, 2.450 пар - M2M100
20250108.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/
Ось абсолютний найпростіший спосіб запуску 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- 10)
- Вищі значення = кращу якість, але повільніші
- Нижні значення = швидший прохід
Розділення речень:
- : увімкнути або вимкнути автоматичне розбиття речень
- Увімкнено (типовий): розділює довгі тексти на речення для кращої якості
- Вимкнено: перекладає весь текст як один блок (швидше для коротких текстів)
-
Статистика реального часу:
- Час перекладу
- : Показує поточну тривалість перекладу на стороні сервера
- Кількість символів
- : Підрахуйте скільки набираєте
Індикатор стану
: Бездіяльний → Трансляція → Виконано/ Помилка
- **6.**Знаходження моделі сім'ї
- **Використання пар перекладів для кожної зразкової сім' ї:**Opus-MT
- : 1200+пари мовmBART50
- : 50 мовами, 2.450 парM2M100
: 100 мовами, 9700 пар/demo/Визначити, які пари мов доступні перед перекладом
Як працює текстова розшифровка
Демонстрація реалізує інтелектуальний фрагмент тексту на стороні клієнта:Чому слід використовувати демонізм?Швидке тестуванняПеревіряти переклади без коду записуПеревірити доступність пари мов
Порівняти якість перекладу з різними розмірами променя
- **Тестові випадки ребер (емоджі, символи, спеціальні символи)**Допомога у розробці
- Див. точний формат запиту/ репонентів APIПеревіряти стан служби перед об'єднанням
- Перевірка швидкодії з різними розмірами текстуВідкрити наявні гарні сім'ї
- Довідка клієнтаПоказує відповідні шаблони використання API
- **Демонструє роботу з помилками (429, виявлення мови)**Приклад реалізації шматків
- Повторна логіка реального світуПриклад використанняПростий переклад.
- **Вставте текст: "Привіт, як справи сьогодні?"**Вибір мети: німецька
- **Натисніть " Транзиту "**Результат: "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
- Це не просто латка робота; це повний перепис з використанням виробництва.
MODEL_FAMILYОсь що робить це кращим:opus-mtБагатомодерна підтримка сім'ї - Зараз підтримується здебільшого Lucid- NMT
- три сім' ї моделей перекладу
- , даючи вам гнучкість, що базується на ваших потребах:
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
- **mBART50 (лицем)**Обкладинка:
- 50 мов, повний перекладАрхітектура:
- Одна багатомовна модельЯкість:
- **Добра якість, особливо для головних мов.**Випадок використання:
- Конструкція простору або багато пар мовРозмір моделі:
- **~2. 4GB (single модель для всіх 50 мов)**Переваги:
- Одна модель керує 2 450 парами перекладівM2M100 (лицем)
- **Обкладинка:**100 мов, повний переклад
- **Архітектура:**Одна багатомовна модель
- **Якість:**Добра якість з найширшим покриттям мови
- **Випадок використання:**Максимальна обкладинка мови
-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:
- Llama 3 8B: ~16GBLlama 3 70B: ~140GB
- Mixtral 8x7B: ~90GBGPT- 4: недоступний для самопідтримання
- **Ефект зберігання:**Вимоги виконавців: Лептоп/ Ферма сервера
- **Деляція процесора NMT:**Дуже добре працює: над двома ядрами процесора, 4GB RAM
- Зображення Docker: 1,5- 2, 5GBПідсилення: лише процесор, не потрібен GPU
Retry-AfterВартість: 10- 20/ місячний VPS
- **Вимоги LLM:**Llama 3 70B: потребує 80GB+ VRAM (A100 GPU)
- Менші моделі 7Б- 13Б: Мінімальний об' єм пам' яті 16- 32 ГБ
- Вартість API: 0. 03- 0. 30 на 1000 марок (додається швидко!)
- Самопідтримка: $ 1000+/місяця для серйозного GPU
- Порівняння справжніх витрат для 10 000 перекладів блогу:
- Д_ д. д. д. д. д. д. д. д. д. д. д. д. д. д. здебільшого musicid-nmt (CPU)} $20/місяця VPS} 2/3 години}
- meanslucid-nmt (GPU) сяє/місяця GPU VPS} 15-30 хвилин
- +GPE-4 API} $50-300} 8-15 годин
- +300 + 6-00 годин
- **♪ 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)
)
Удар кешу → Швидка відповідь
- Не вистачає кешу → Завантаження з вузлаПовноцінний кеш → Автоматичні старі моделі, прозора пам' ять CUDA
max_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 з керування пам'яттю GPU
enОднією з найкрутіших можливостей є кеш з кмітливою моделлю, який знає як обробляти пам' ять 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, то M2M100
DEVICE=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"Що тут відбувається?
- 6.
Асинхронний клієнт 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 рухове середнє)
: Подібно до середньої ваги, яка надає більшої ваги недавнім цінностям.Коефіцієнт згладжування (⇩):
- : Керує тим, як швидко ми пристосовуємося до змін (
latest,min,gpu,gpu-minЧому це не є тільки середньостатистичний? - : 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
Налаштування моделі
Пояснення нових налаштувань:
MODEL_ FAMILY
EASYNMT_MODEL_ARGS='{"torch_dtype":"fp16"}'- : Виберіть модель сім'ї, яку слід використовувати як основну
- : Найкраща якість, 1200+параметрів, окремі моделі
- : хороша якість, 50 мовами, єдина модель 2.4GB
: хороша якість, 100 мов, єдина модель 2.2 ГБ
# Start high, reduce if you get OOM EASYNMT_BATCH_SIZE=64 # Try 128 on large GPUsAUTO_ MODEL_ FALLBACK
PRELOAD_MODELS="en->de,de->en,en->fr,fr->en,en->es,es->en": Автоматично випробовувати інші сім' ї, якщо пара недоступна
WEB_CONCURRENCY=1 MAX_INFLIGHT_TRANSLATIONS=1(типовий): увімкнено - максимальна обкладинка
MAX_CACHED_MODELS=10 # Keep more models in VRAM: Непрацездатний - строгий режим однієї сім'ї
# 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
: Порядок пріоритету для повернення назад
EASYNMT_BATCH_SIZE=8Типове значення:
MAX_WORKERS_BACKEND=4 MAX_INFLIGHT_TRANSLATIONS=4 WEB_CONCURRENCY=2(перший якість)
PERFORM_SENTENCE_SPLITTING_DEFAULT=0
Альтернативний:
(перший захист)
// Bad: 100 separate requests for (const text of texts) { await translate(text); } // Good: 1 batch request await translate(texts);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; } }: Постійне взірцеве сховище на основі томів докерів.
// Reuse HTTP connections const agent = new https.Agent({ keepAlive: true });Встановити до
// 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");
і об' єм карти:
Модели, що продовжуються через перезапуск контейнера
- Спільний кеш між декількома контейнерамипараметри flash_ dtype:
- (float16): 2x швидше на GPU, половина пам'яті, незначна втрата якості(bfloat16): Краща числова стабільність за fp16, потребує сучасні GPU
- (float32): Повна точність, найповільніша, але найточнішаПараметри перекладів
- & Швидкодія у черзіЗасновування вхідних даних
- Обробка реченняМаскування символів
- Поведінка відповідіПовернення Pivot
- ЖурналюванняСупровід
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. md
MAX_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




