Back to "Κτίριο ως επί το πλείστον διαυγή-nmt: A Production-Ready (EasyNMT συμβατό) Translation Service"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

API CUDA Docker EasyNMT FastAPI Helsinki-NLP mostlylucid-nmt Neural Machine Translation Python PyTorch Transformers

Κτίριο ως επί το πλείστον διαυγή-nmt: A Production-Ready (EasyNMT συμβατό) Translation Service

Saturday, 08 November 2025

Εισαγωγή

Μια εφαρμογή FastAPI EXACTly αντιγραφή του API του EasyNMT (https://github.com/UKPLab/EasyNMT) ένα εξαιρετικό αλλά εγκαταλελειμμένο έργο νευρικής-μετάφρασης.

Αλλά έχω προσθέσει τόσο πολλά ωραία χαρακτηριστικά για να αυξήσει την αξιοπιστία και να το κάνει έτοιμο για χρήση σε ένα σύστημα παραγωγής.Σκέψου γρήγορα τη μετάφραση που φιλοξενείς...).

Από την αρχή αυτού του blog, ένα μεγάλο πάθος είναι η αυτόματη μετάφραση άρθρων blog.

ΝΑΙ Ξέρω ότι το "google κάνει αυτό" σε browsers κλπ... κλπ...αλλά δεν είναι αυτό το θέμα.mostlylucid-nmtΉθελα να μάθω πώς να το κάνω!

Επιπλέον είναι ωραίο να καλωσορίζουμε ανθρώπους που δεν διαβάζουν Αγγλικά (ακόμα και αν διαβάζουν Αγγλικά ως δεύτερη γλώσσα, είναι πιο δύσκολο να αναπαραχθούν).Έτσι σκέφτηκα πώς να το κάνω · καθώς και να μοιράζομαι πώς να φτιάχνω αυτό το είδος συστήματος.Ω και μου έδωσε ιδέες για το πώς να το χρησιμοποιήσετε στο ASP.NET για αυτόματη εντόπιση του κειμένου (συμπεριλαμβανομένου του δυναμικού κειμένου) χρησιμοποιώντας το σύστημα SignalR & ένα slick realtime ενημέρωση. (

Μείνετε συντονισμένοιOh and I've made a demo available here; https://nmtdemo.mostlyclearning.net/demo/ it's only running in an old laptop with no GPU but give you the idea (and let me test lengevity).Ουσιαστικά, οι άνθρωποι γράφουν σκατά κείμενο που είναι SUPER θορυβώδες για τις μηχανές να χειριστεί αποτελεσματικά.

Έτσι, πολλά ήταν η εύρεση πώς να λειτουργήσει γύρω από τα θέματα με EasyNMT (ήταν πραγματικά ποτέ ένα ερευνητικό έργο).

Τώρα.

έχει σχεδιαστεί για να είναι μια μάχη δοκιμαστεί (καλά μεταφράζοντας τις δεκάδες χιλιάδες λέξεις εδώ!) χρήσιμο σύστημα για οποιαδήποτε μετάφραση. Κάτι σαν BabelFish API. Έχει επίσης όλες τις γνώσεις που έχω από τρεις δεκαετίες κατασκευής διακομιστών παραγωγής & συστημάτων. Ranging από 429 κώδικες για να πω στον πελάτη να κάνει πίσω, επιστρέφοντας μεταδεδομένα σχετικά με μεταφράσεις για να βοηθήσει τους πελάτες, επιπλέον τελικά σημεία για να πάρει περισσότερα δεδομένα και OF COURSE μια σελίδα επίδειξης

Που με αφήνει και τους δύο ενώ αναπτύσσομαι, όπως κι εσύ, έναν τρόπο να έχουμε ένα έργο.

Ιέγραψε ένα ολόκληρο σύστημαhttp://<server>:<port>/demoγια να γίνει αυτό με ένα καταπληκτικό έργο που ονομάζεται EasyNMT.

Demo

[TOC]

Τέλος πάντων, αν έλεγξες τη συμφωνία ξέρεις ότι υπάρχει ένα θέμα... δεν έχει αγγίξει εδώ και χρόνια.

Είναι ένας απλός, γρήγορος τρόπος για να πάρετε μια μετάφραση API χωρίς την ανάγκη να πληρώσετε για κάποια υπηρεσία ή να εκτελέσετε ένα πλήρες μέγεθος LLM για να πάρετε μετάφραση (αργά).

Σε προηγούμενες δημοσιεύσεις μας, συζητήσαμε πώς να ενσωματώσουμε το EasyNMT με τις εφαρμογές ASP.NET για τη μετάφραση υποβάθρου.

**Αλλά όσο περνούσε ο καιρός, οι ρωγμές άρχισαν να εμφανίζονται.**Ήταν ώρα για κάτι καλύτερο.

**Ως συνήθως είναι όλα στο GitHub και όλα δωρεάν για χρήση κλπ...**Τραβάει ο Ντόκερ

  • cpuCity name (optional, probably does not need a translation): 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)
  • **gpuCity name (optional, probably does not need a translation)**gpu- min
  • **Demo...δείτε αργότερα για το demo σελίδα!**Μια ολοκληρωμένη (κυρίως) διαδραστική σελίδα επίδειξης
  • (σεή μόνο η ρίζα)
  • **Τι είναι το "Νιού";**Πριν βουτήξουμε στο γρήγορο ξεκίνημα, εδώ είναι τι κάνει αυτή την έκδοση-αλλαγή παιχνιδιού:

Σημαντικές ενημερώσεις (v3.1) - Νοημοσύνη & ΟρατότηταΝέο σε v3.1:

  • **Η τελευταία έκδοση φέρνει τεράστιες βελτιώσεις στην αξιοπιστία, την προβολή των επιδόσεων, και έξυπνη επιλογή μοντέλων!**1.
  • Smart Model Caching με ορατότητα- Να δούμε τι ακριβώς συμβαίνει.
  • Καταγραφή Cache HITΚαταγραφή MISS Cache
  • Ανίχνευση κατάστασης μνήμης: Εμφανίζει ποσοστό χρήσης και φορτωμένα μοντέλα
  • Προειδοποιήσεις έξωσης: Καθαρίστε τις ειδοποιήσεις όταν η κρύπτη είναι γεμάτη και τα μοντέλα είναι έξωση
  • Αύξηση της παραγωγικής ικανότητας:
    ====================================================================================================
      🚀 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 GB")**Καταμέτρηση αρχείων
  • : Εμφανίζει τον αριθμό των αρχείων για λήψηΟθόνη συσκευής

: Εμφανίζει τη συσκευή-στόχο (GPU/CPU) στο bannerΓραμμές προόδου

  • **: Όμορφη πρόοδος 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)
    

Ευφυής επιλογή Pivot Data-Driven- Όχι άλλες τυφλές προσπάθειες.

  • Έξυπνη λογική τομήςLoading mbart50 model on GPU (cuda:0)
  • : Βρίσκει γλώσσες όπου υπάρχουν και τα δύο πόδια περιστροφήςModel loaded on device: cuda:0
  • Αποφεύγει τις αποτυχημένες προσπάθειεςSuccessfully loaded... on GPU (cuda:0)

: Won't try en→es→bn if es→bn doesn't thereΠαράδειγμα για en→bn

  • Προτεραιότητα fallbacken->hi, hi->bn
  • : Αγγλικά → Ισπανικά → Γαλλικά → Γερμανικά → Κινέζικα → Ρωσικά
  • Διαφανής καταγραφή[Pivot] Both legs loaded and cached. Ready to translate.

: Δείτε ακριβώς γιατί κάθε περιστροφή επιλέχθηκε ή παραλείψτηκε4.

  • Σταθερό αυτόματο fallback
    • Τέρμα οι διπλοτραγωδίες.model_familyΠάντα προσπαθεί να υποχωρήσει
  • : Ακόμα και αν προτιμάται οικογένεια "πρέπει" υποστηρίζει το ζεύγος

Ενιαία προσπάθεια ανά οικογένεια

: Δεν ξαναδοκιμάζουμε το ίδιο μοντέλο δύο φορέςΠαράδειγμα ροής

  • Διαύγεια GPU
    • Πάντα να ξέρετε πού είναι τα μοντέλα σας:
  • Κάθε μοντέλο φορτίου δείχνει:
  • Μετά το φορτίο επιβεβαιώνει:

**Το μήνυμα επιτυχίας περιλαμβάνει:**6.

  • Pivot Model Caching- Αποτελεσματική επαναχρησιμοποίηση περιστροφής:
  • **Και τα δύο άκρα της περιστροφής αποκολλημένα χωριστά:**Την επόμενη φορά en→hi ή hi→bn χρειάζεται, άμεση κρύπτη χτύπημα!
  • **Καθαρισμός καταγραφής:**7.
  • Αναζήτηση επιλογής μοντέλου

**- Δουλεύει ήδη στο ντέμο:**Demo πτώση επιτρέπει την επιλογή opus-mt, mbart50, ή m2m100

  • Τα σέβη του συστήματος υποστήριξης
  • παράμετρος ανά αίτηση
  • Μοντέλα που συγκρατούνται χωριστά από την οικογένεια για άμεση αλλαγή
  • Σημαντικές ενημερώσεις (v3.0)
  • 1.requirements-prod.txtΕνισχυμένη σελίδα επίδειξηςName

**- Διαδραστική διεπαφή παραγωγής-έτοιμη:**Πλήρης διάταξη προβολής (100vw/100vh) για βυθιστική εμπειρία μετάφρασης

  • **Κατάλληλη θεματική επιλογή dropdows (όχι πλέον clunky input/datalist)**Live model family switching (Opus-MT, mBART50, M2M100)
  • Δυναμική φόρτωση γλώσσας βάσει επιλεγμένου μοντέλουΠεριστρεφόμενες περιοχές εξόδου για μεγάλες μεταφράσεις
  • **2.**Επιδόσεις-Optimized Προκαθορισμένα
    • "Γρήγορη όσο το δυνατόν" έξω από το κουτί:
  • GPU

**: FP16 enabled, ΠΑΡΤΙ∆Α_ SIZE=64, MAX_INFLIGHT=1 (default for single GPU)**CPU

  • : WEB_CONCURRENCY=4, MAX_INFLIGHT=4, ΠΑΡΤΙ∆Α_SIZE=16 (χρησιμοποίησε όλους τους πυρήνες)
  • Γρήγορη παύση λειτουργίας
  • : 5-δευτερόλεπτο χαριτωμένο timeout (όχι περισσότερα 20-δευτερόλεπτο κρέμονται)
  • Τα εμπορευματοκιβώτια σταματούν καθαρά χωρίς τρομακτικά μηνύματα SIGKILL
  • Βελτιστοποίηση Κατασκευής Παραγωγής

**- Μικρότερες, γρηγορότερες εικόνες:**Απομακρύνθηκαν εξαρτήσεις δοκιμής (πυρετός, πυρετός-κοφ) από τις κατασκευές παραγωγής

  • Αποθηκεύει ~200MB ανά εικόναΕικόνες CPU: ~8-10GB (πλήρης), ~3-4GB (ελάχ.)
  • **Εικόνες GPU: ~12-15GB (πλήρης), ~6-8GB (ελάχ.)**Όλη η χρήση
  • για ελάχιστο αποτύπωμα4.

Πλήρης δοκιμή και δοκιμή φορτίου- Επικυρώστε τα πάντα:

  • Ζωντανή δοκιμαστική σουίτα API
  • (30+ δοκιμές) για την υγεία, τη μετάφραση, την ανίχνευση, την ανακάλυψη
  • k6 δοκιμή φορτίου

με ρεαλιστικά μοτίβα κυκλοφορίαςΣενάρια επικύρωσης Cross-platform

  • /discover/opus-mt(PowerShell + Bash)
  • /discover/mbart50Δοκιμές για λήψεις μοντέλων και περιστροφή μετάφρασης fallback
  • /discover/m2m100Αυτόματες δοκιμές καπνού για γρήγορη επικύρωση

**5.**Τεκμηρίωση για την ανάπτυξη

    • Η παραγωγή είναι έτοιμη από την πρώτη μέρα:
  • 4 σενάρια ρύθμισης: Max Thrubput, Low Latency, High Concurrency, Memory-Constrated
  • Docker Compose παραδείγματα με τις ρυθμίσεις GPU/CPU

Kubernetes εκδηλώνει με PVC, όρια πόρων, υγειονομικούς ελέγχουςΠαραδείγματα εμπορευματοκιβωτίων Azure

  • scottgal/mostlylucid-nmt:cpuΚαθοδήγηση δοκιμών φορτίου και συστάσεις παρακολούθησης:latestΗ Concurrency vs throughput trade-offs εξήγησε
  • 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 ζεύγη

Auto- Fallback- Ευφυώς επιλέγει το καλύτερο διαθέσιμο μοντέλο:

  • **Ορισμός πρωτογενούς οικογένειας (π.χ. Opus-MT για ποιότητα)**Αυτόματη δοκιμή mBART50/M2M100 εάν το ζεύγος δεν είναι διαθέσιμο
  • Μέγιστη κάλυψη χωρίς θυσία ποιότητας8.
  • Μοντέλο Discovery- Δυναμικά διαθέσιμα μοντέλα ερωτήσεων:
    • Όλα τα 1200+ ζευγάρια από το πρόσωπο αγκαλιάσματος

- Όλα τα ζευγάρια mBART50- Όλα τα ζεύγη M2M100

  • Ελάχιστες εικόνες

- Μικρότερες, ευέλικτες εφαρμογές:

Κανένα προφορτωμένο μοντέλο (κατέβασμα κατά παραγγελία)

Ογκομετρούμενη επίμονη κρύπτη

Οικογένειες μοντέλων Switch χωρίς ανοικοδόμηση**10.**Single Docker Repository

  • Όλες οι παραλλαγές σε ένα μέρος: |-----|-----------------|------|-------------|----------| | cpulatest) | scottgal/mostlylucid-nmt:cpu) - ΚΜΕ | cpu-min | scottgal/mostlylucid-nmt:cpu-min- ΚΜΕ minimal | gpu | scottgal/mostlylucid-nmt:gpu- GPU με CUDA 12.6 | gpu-min | scottgal/mostlylucid-nmt:gpu-min- GPU minimal

**11.**Ορθή μετάφραση

    • Όλες οι εικόνες περιλαμβάνουν την έκδοση ημερομηνίας:
  • Ονόματα ετικετών (
  • ) πάντα δείχνουν την πιο πρόσφατη κατασκευή
  • Αμετάβλητες ετικέτες έκδοσης (π.χ.

) για pinning special builds

Πλήρης ετικέτα 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

για εικόνες CPU (διεύθυνση Python 3.11 ευπάθεια)

CUDA 12.6

με Ubuntu 24.04 για εικόνες GPU (τελευταία στοίβα 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 με 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

(συμβιβάσιμο με το CUDA 12.6 runtime)

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

Σταθερές προειδοποιήσεις αποσυμπίεσης

- Αδιάβροχο για το μέλλον:

Απομακρύνθηκε TRANSFORMERS_CACHE (τώρα χρησιμοποιώντας HF_HOME)Συμβατό με Transformers v5Γρήγορη εκκίνηση (5 λεπτά)

http://localhost:8000/demo/

Demo

### Θέλεις απλά να μεταφράσεις;

Εδώ είναι ο πιο απλός τρόπος για να τρέξει ως επί το πλείστον διαυγής-nmt:

Διαθέσιμες εικόνες Docker

  • Όλες οι παραλλαγές είναι διαθέσιμες από
  • ένα αποθετήριο
  • με διαφορετικές ετικέτες:

Ετικέτα Ετικέτα Ετικέτα Ετικέτα Πλήρες όνομα εικόνας Μέγεθος Περιγραφή Χρησιμοποίησε την υπόθεση

  • □ ~2.5GB ΚΜΕ με πηγαίο κωδικό □ Ανάπτυξη ΚΜΕ Παραγωγής
  • ~1.5GB CPU minimal, no preloaded models
  • □ ~5GB GPU με CUDA 12.6 + πηγή
  • ~4GB GPU minimal, no preloaded models ~ GPU with volume-mapped cache

Ελάχιστες εικόνες

  • συνιστάται για:
  • Εγκαταστάσεις παραγωγής με κρυπτογραφημένη μνήμη
  • Χρησιμοποιώντας mBART50 ή M2M100 (μονά μεγάλα μοντέλα)

Διατηρώντας μικρό μέγεθος δοχείου

  • Ευελιξία για αλλαγή οικογενειών μοντέλων χωρίς ανοικοδόμησηΑπλότερη εκκίνηση (Opus-MT CPU)
    • Τραβήξτε και τρέξτε:
  • **2.**Μετάφρασε κάποιο κείμενο:
    • Απάντηση:
    • GPU Επιταχύνεται (10x γρηγορότερα)

Απαιτεί NVIDIA Docker runtime:

  • Με μοντέρνα κρυψώνα μοντέλουΚατεβάστε τα μοντέλα μία φορά και κρατήστε τα σε όλο το δοχείο επανεκκινεί:
  • **Linux/Mac:**Παράθυρα (PowerShell):
  • **Παράθυρα (CMD):**Μοντέλα κατεβάστε αυτόματα σε πρώτη χρήση και επιμένετε στον τοπικό κατάλογο σας!

Υγειονομικός έλεγχος:

  • Αυτό είναι το 5λεπτο γρήγορο ξεκίνημα!
    • **Για την ανάπτυξη της παραγωγής, τη διαμόρφωση και τα προηγμένα χαρακτηριστικά, συνεχίστε να διαβάζετε.**Διαδραστική σελίδα επίδειξηςName
    • Η υπηρεσία περιλαμβάνει μια πλήρως εξοπλισμένηδιαδραστική σελίδα επίδειξης
    • **που καθιστά εύκολο να δοκιμάσετε μεταφράσεις χωρίς να γράψετε κανένα κώδικα.**Πρόσβαση σε:
  • Χαρακτηριστικά επίδειξηςName

Η σελίδα demo παρέχει ένα πλήρες περιβάλλον δοκιμών μετάφρασης με:

// 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

Επιλογή γλώσσας

Auto-populated language drops downloads from the live service

  • Ανταλλάξτε τις γλώσσες πηγής/στόχου με ένα κλικ
  • Υποστηρίζει όλες τις γλώσσες 100+ ρυθμισμένες στην υπηρεσία
  • Smart Text Chunking

Αυτόματη διαχείριση των μεγάλων εισροών κειμένου οποιουδήποτε μεγέθους

  • Διαιρεί έξυπνα τις παραγράφους, διατηρώντας τη δομή του εγγράφου
  • Πέφτει πίσω στη διαίρεση ποινής για πολύ μεγάλες παραγράφους
  • Δείχνει πρόοδο για πολλές μεταφράσεις ("Μετάφραση κομματιού 2/5...")
  • Χωρίς ραφή επανασυναρμολογεί κομμάτια με την κατάλληλη απόσταση

3.

  • Ανίχνευση γλώσσας
  • Ανιχνεύστε τη γλώσσα πηγής με ένα κλικ
  • Automaticly populate language dropdown
  • Λειτουργεί με κείμενο μέχρι 5000 χαρακτήρες

4.

  1. Προχωρημένες επιλογές:

    • Μέγεθος ακτίνας
    • : Ποιότητα μετάφρασης ελέγχου (1-10)
    • Υψηλότερες τιμές = καλύτερη ποιότητα αλλά πιο αργή
    • Χαμηλότερες τιμές = ταχύτερη μετάβαση
  2. Διαχωρισμός της ποινής:

    • : Εναλλαγή αυτόματης διαίρεσης πρότασης
    • Ενεργοποιημένο (προκαθορισμένο): Χωρίζει τα μεγάλα κείμενα σε προτάσεις για καλύτερη ποιότητα
    • Άτομα με ειδικές ανάγκες: Μεταφράζει ολόκληρο το κείμενο ως ένα μπλοκ (γρήγορο για σύντομα κείμενα)
  3. Στατιστικά Πραγματικού Χρόνου:

    • Χρόνος μετάφρασης
    • : Εμφανίζει πραγματική διάρκεια μετάφρασης server-side
    • Αριθμός χαρακτήρων
    • : Μετρήστε ζωντανά όπως πληκτρολογείτε

Δείκτης κατάστασης

: Idle → Translating → Done/Error

  • **6.**Μοντέλο Οικογενειακής Ανακάλυψης
  • **Εξερευνήστε τα διαθέσιμα ζεύγη μεταφράσεων για κάθε οικογένεια μοντέλου:**Opus-MT
  • : 1200+ ζεύγη γλωσσώνmBART50
  • : 50 γλώσσες, 2.450 ζεύγηM2M100

: 100 γλώσσες, 9.900 ζεύγη/demo/Δείτε ακριβώς ποια ζεύγη γλωσσών είναι διαθέσιμα πριν από τη μετάφραση

Πώς λειτουργεί το Τσάνκινγκ κειμένου

Το demo εφαρμόζει έξυπνο κείμενο που πετάει στην πλευρά του πελάτη:Γιατί Χρησιμοποίησε το Demo;Γρήγορη δοκιμήΔοκιμαστικές μεταφράσεις χωρίς κώδικα γραφήςΔιαθεσιμότητα ζεύγους γλωσσών

Σύγκριση ποιότητας μετάφρασης με διαφορετικά μεγέθη δέσμης

  1. **Θήκες άκρων δοκιμής (emoji, σύμβολα, ειδικοί χαρακτήρες)**Αναπτυξιακή ενίσχυση
  2. Δείτε ακριβή μορφή αίτησης/απάντησης APIΕπιβεβαίωση της υγείας των υπηρεσιών πριν από την ενσωμάτωση
  3. Επιδόσεις δοκιμής με διαφορετικά μεγέθη κειμένουΑνακαλύψτε τις διαθέσιμες οικογένειες μοντέλων
  4. Αναφορά πελάτηΕμφανίζει τα κατάλληλα πρότυπα χρήσης API
  5. **Διαδηλώνει τον χειρισμό λάθους (429, ανίχνευση γλώσσας)**Παράδειγμα εφαρμογής πνιγμού
  6. Αληθινής λογικής ανακατάταξης του κόσμουΠαράδειγμα χρήσηςΑπλή μετάφραση.
  7. **Επικόλληση κειμένου: "Γεια σας, πώς είστε σήμερα;"**Επιλογή στόχου: Γερμανικά
  8. **Κάντε κλικ στο "Μετάφραση"**Αποτέλεσμα: "Hello, wie geht es Ihnen hute?"

Μακροχρόνια Μετάφραση Εγγράφων

Επικόλληση ολόκληρου του blog post (5000+ words)Το demo το κόβει αυτόματα σε εύχρηστα κομμάτιαΔείχνει πρόοδο όπως κάθε κομμάτι μεταφράζει

Επιστρέφει πλήρως μεταφρασμένο έγγραφο

Ανίχνευση γλώσσαςΕπικόλληση κειμένου σε άγνωστη γλώσσαΚάντε κλικ στο "Ανίχνευση γλώσσας"

Το Demo προσδιορίζει τη γλώσσα και τις ενημερώσεις πτώσης

  • Έτοιμοι να μεταφράσετε αμέσωςΤεχνικές λεπτομέρειες
  • **Η σελίδα επίδειξης είναι:**Αυτοσυντηρούμενο
  • : Μονό αρχείο HTML με ενσωματωμένο JavaScriptΜηδέν εξαρτήσεις
  • : Δεν απαιτούνται εξωτερικές βιβλιοθήκεςMobile friendly
  • : Responsive έργα σχεδιασμού σε όλες τις συσκευέςΠαραγωγή έτοιμη
  • : Η ίδια λογική πνιγμού μπορεί να χρησιμοποιηθεί στις εφαρμογές σαςΠρόσβαση στο live demo στο

Στην υπόθεσή σας!

  • Τα Προβλήματα με το EasyNMTΤώρα αυτό δεν είναι ντάμπινγκ σε
  • EasyNMTΔεν έφτιαξε τίποτα άλλο και το έχτισα.
  • Πολλά έργα που το χρησιμοποιούν
  • **Έχει περάσει πολύς καιρός στο δόντι, οπότε... τι προβλήματα έχουμε;**Θεέ μου, υπάρχουν πολλά.
  • **Το EasyNMT χτίστηκε πριν από μια δεκαετία.**Η τεχνολογία προχώρησε... και δεν προοριζόταν ποτέ να είναι ένα σύστημα παραγωγής.
  • **Εδώ είναι μερικά από τα θέματα:**Καταρρέει... πολύ.

Δεν είναι σχεδιασμένο να αναρρώνει από θέματα τόσο συχνά απλά πέφτει πάνω.

  • **Είναι SUPER PICKY σχετικά με την εισαγωγή του.**Τα εικονίδια, τα σύμβολα, ακόμα και οι αριθμοί μπορούν να το μπερδέψουν.
  • **Δεν είναι σχεδιασμένο για φορτίο.**Βλέπε ανωτέρω.
  • **Ποτέ δεν σχεδιάστηκε για να είναι.**Δεν έχει σχεδιαστεί για να ενημερώνει τα μοντέλα του
  • **ή να είναι (εύκολα) φτιαγμένα με ενσωματωμένα μοντέλα.**Το υλικό του GPU CUDA είναι αρχαίο
  • **Τόσο πιο αργά από ό, τι χρειάζεται να είναι.**Δεν μπορείς να διορθώσεις τίποτα.
  • **Ο κώδικας του Πάιθον είναι στη συμφωνία, αλλά ξανά.**Όχι πολύ καλά.

**Δεν υπάρχει πίσω πίεση ή ουρά.**Στείλτε πάρα πολλά αιτήματα και απλά χτυπάει.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Έτσι... Αποφάσισα να χτίσω ένα νέο και βελτιωμένο EasyNMT, τώραως επί το πλείστον διαυγής - nmt


  1. Αυτό δεν είναι απλά μια δουλειά patch? Είναι μια πλήρης rewrite με τη χρήση της παραγωγής στο μυαλό.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-500MB ανά κατεύθυνση

# 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→ German is a different model than German→Greek

  1. **mBART50 (Facebook)**Κάλυψη:
  2. 50 γλώσσες, όλες-σε-όλες τις μεταφράσειςΑρχιτεκτονική:
  3. Μονόγλωσσο μοντέλοΠοιότητα:
  4. Καλή ποιότητα, ειδικά για τις μεγάλες γλώσσεςΧρήση περίπτωσης:
  5. Διαστημικές εφαρμογές ή πολλά ζευγάρια γλωσσώνΜέγεθος μοντέλου:
  6. **~2.4GB (μονό μοντέλο και για τις 50 γλώσσες)**Πλεονέκτημα:
  7. Ένα μοντέλο χειρίζεται 2.450 ζεύγη μεταφράσεωνM2M100 (Facebook)
  8. **Κάλυψη:**100 γλώσσες, όλες-σε-όλες τις μεταφράσεις
  9. **Αρχιτεκτονική:**Μονόγλωσσο μοντέλο
  10. **Ποιότητα:**Καλή ποιότητα με ευρύτερη γλωσσική κάλυψη
  11. **Χρήση περίπτωσης:**Μέγιστη γλωσσική κάλυψη-minΜέγεθος μοντέλου:

~2.2GB (μονό μοντέλο και για τις 100 γλώσσες)

Πλεονέκτημα:

Ένα μοντέλο χειρίζεται 9.900 ζεύγη μεταφράσεων

Η αλλαγή είναι εύκολη.

    • απλά βάλτε το
  • μεταβλητή περιβάλλοντος:
  • Automatic Model Family Fallback - ΝΕΟ!

Ένα από τα πιο ισχυρά νέα χαρακτηριστικά είναι

  • αυτόματη αναπήδηση μεταξύ των οικογενειών μοντέλων
  • Αυτό εξασφαλίζει μέγιστη κάλυψη ζεύγους γλωσσών ενώ δίνει προτεραιότητα στην ποιότητα μετάφρασης.

**Πώς λειτουργεί:**Εσύ έβαλες ένα κύριο

  • **(π.χ.,**για την καλύτερη ποιότητα)
  • Όταν ζητάτε ένα ζεύγος μεταφράσεων που δεν είναι διαθέσιμο στην κύρια οικογένειαΤο σύστημα δοκιμάζει αυτόματα την επόμενη οικογένεια στο fallback order
  • Αυτό συνεχίζεται μέχρι να βρεθεί ένα κατάλληλο μοντέλοΠαράδειγμα σεναρίου:

Παροχές:

Μέγιστη κάλυψη:

Υποστήριξη 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 γλώσσες).

Μοντέλα τελικών σημείων ανακάλυψης

    • Δυναμικά διαθέσιμα μοντέλα από το Hugging Face για κάθε οικογένεια.
  • Ανθεκτικός χειρισμός εισόδου
    • Emoji;
  • Αριθμοί;

Σύμβολα;

  • Φέρ' το.
  • Η υπηρεσία περιλαμβάνει τώρα πλήρη καθαρισμό εισόδου και κάλυψη συμβόλων.
  • Ζητήστε ουρά και πίσω πίεση
    • Ενσωματωμένο semaphore-based ουρά με έξυπνη retry-after εκτιμήσεις.

LRU μοντέλο caching

  • Αυτόματη διαχείριση VRAM με την έξωση παλιά μοντέλα όταν η κρύπτη είναι πλήρης. |--------|------|------| Σύγχρονη υποστήριξη CUDA
  • Χρησιμοποιεί PyTorch με CUDA 12.6, υποστηρίζει FP16/BF16 για 2x βελτιώσεις ταχύτητας. Παρατήρηση ετοιμότητας παραγωγής Ελέγχους υγείας, ανιχνευτές ετοιμότητας, κατάσταση κρύπτης, δομημένη καταγραφή. Χαριτωμένο κλείσιμο

- Όχι άλλα ορφανά αιτήματα ή διεφθαρμένη κατάσταση.

EasyNMT-συμβατό API

    • Ανταλλακτικό για τις υπάρχουσες ενοποιήσεις.
  • Pivot μετάφραση fallback
    • Εάν ένα ζεύγος άμεσης γλώσσας δεν είναι διαθέσιμο, αυτόματα διαδρομές μέσω της αγγλικής (ή της επιλεγμένης περιστροφής σας).
  • Minimal Docker εικόνες
    • Καινούργια.

παραλλαγές με κρύπτη με όγκο για μικρότερες εφαρμογές.

  • ⚠️ 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

Γιατί NMT Over LLMs for Translation;

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 μπορεί να μεταφράσει;" Μεγάλη ερώτηση.

Εδώ είναι ο έλεγχος πραγματικότητας με βάση τη χρήση της παραγωγής:

  • Ταχύτητα: 100-100x γρηγορότερα
  • NMT (κυρίως διαυγής-nmt):
  • CPU: ~0.3-1.0 δευτερόλεπτα ανά πρόταση
  • GPU (FP16): ~0.05-0,2 δευτερόλεπτα ανά πρόταση
  • Επεξεργασία παρτίδας: 50+ προτάσεις/δεύτερο σε GPU
  • LLMs:

GPT-4: 3-10 δευτερόλεπτα ανά αίτηση (API καθυστέρηση + γενιά)

  • Λάμα 3 70B: 5-15 δευτερόλεπτα ανά πρόταση (τοπική)
  • Claude 3: 2-8 δευτερόλεπτα ανά αίτημα (API καθυστέρηση)
  • Πραγματικό παράδειγμα:
  • Μεταφράζοντας ένα blog 1000 λέξεων:
  • ως επί το πλείστον διαυγής-nmt (GPU)

: 5-10 δευτερόλεπτα

GPT-4 API**: 30-60 δευτερόλεπτα**Local Llama 70B

  • 2-5 λεπτά
  • Όταν μεταφράζετε αυτόματα εκατοντάδες αναρτήσεις blog σε 12+ γλώσσες, αυτή η διαφορά ταχύτητας είναι MASSIVE.
  • Μέγεθος μοντέλου: 500MB vs 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. Λάμα 3 8B: ~16GBΛάμα 3 70B: ~140GB
  2. Mixtral 8x7B: ~90GBGPT-4: Μη διαθέσιμο για αυτοξεπέραση
  3. **Αντίκτυπος αποθήκευσης:**Απαιτήσεις πόρων: Φορητός υπολογιστής vs Server Farm
    • **Ανάπτυξη επεξεργαστών NMT:**Λειτουργεί πρόστιμο σε: 2 πυρήνας CPU, 4GB RAM
    • Εικόνα Docker: 1.5-2.5GBΣυνέδρια: CPU μόνο, δεν απαιτείται GPURetry-AfterΚόστος: $10-20/μήνα VPS
  4. **Απαιτήσεις LLM:**Λάμα 3 70B: Χρειάζεται 80GB+ VRAM (A100 GPU)
    • Μικρότερα μοντέλα 7B-13B: Ακόμα 16-32GB RAM ελάχιστο
    • API κόστος: $0,03-0.30 ανά 1000 μάρκες (προσθέτει επάνω γρήγορα!)
    • Αυτοεξυπηρέτηση: $1000+/μήνα για σοβαρή GPU
    • Σύγκριση πραγματικού κόστους για 10.000 μεταφράσεις blog:
  5. Μεθόδους Χρόνου Χρόνου ΧρόνουΠερισσότερο διαυγή-nmt (CPU) ~ $20/μήνα VPS ~ 2-3 ώρες ~
    • Περισσότερο διαυγής-nmt (GPU) ~ $50/μήνα GPU VPS ~ 15-30 λεπτά ~
    • GPT-4 API $150-300 8-15 ώρες
    • Κλωντ API $200-400 6-12 ώρες
  6. Τοπικό υλικό Llama 70B $1000+/μήνας 20-40 ώρεςΠοιότητα: Σκοπός-Χτισμένο εναντίον Γενικά-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]

Μεταφράζετε τεχνικό περιεχόμενο, κώδικα, δομημένα δεδομένα

  • Χρειάζεστε καθορισμένη έξοδο (ίδια είσοδο = ίδια έξοδο)
  • Θέλετε να τρέξετε σε CPU ή σε μέτριο υλικό
  • Φτιάχνεις αυτοματοποιημένους αγωγούς μεταφράσεων.

Χρήση LLMs όταν:

Χρειάζεσαι δημιουργική προσαρμογή, όχι κυριολεκτικά μετάφραση.

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 --> [*]

Πλαίσιο και πολιτισμικές αποχρώσεις της ύλης περισσότερο από την ταχύτητα

  • Κάνεις χαμηλές μεταφράσεις.
  • Πρέπει να μεταφράσετε + συνοψίζοντας + ξαναγράψτε σε ένα βήμα
  • Είσαι εντάξει με το μεταβλητό κόστος και την αργή επεξεργασία
  • Η Κάτω Γραμμή
  • Για

αυτοματοποιημένη μετάφραση blog

(περίπτωση χρήσης μου), 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+ blog σε 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/μήνα VPS

Συνεπής ποιότητα σε όλες τις θέσεις

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

Συνολική εγκατάσταση: Ένα δοχείο Docker

Δοκιμάζοντας αυτό με LLMs θα κοστίσει εκατοντάδες δολάρια ανά μήνα σε API τέλη ή απαιτούν ένα διακομιστή $ 2000+ GPU για να αυτο-φιλοξενήσει.

Η διαφορά ταχύτητας και μόνο καθιστά την NMT τη μόνη πρακτική επιλογή για τους αγωγούς μετάφρασης παραγωγής.

TL; DR:

NMT είναι σκοπός-χτισμένο για τη μετάφραση, τρέχει σε μέτρια υλικό, και είναι 100-100x γρηγορότερα από LLMs. Αν χρειάζεστε γρήγορη, συνεπή, οικονομικά αποδοτική μετάφραση σε κλίμακα, 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 Gateway (Gunicorn + Uvicorn εργαζόμενοι)
  • Πύλη 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 μεκεφαλίδα
  • Translation Serviceεπεξεργάζεται το αίτημα μέσω του αγωγού:
  • Λύση εισόδου και διαίρεση πρότασηςΑποκρύψεις συμβόλων (emojis, ειδικά chars)
  • Μετάφραση με τη χρήση κλειστών μοντέλωνΑπομάκρυνση συμβόλων και μετά την επεξεργασία

Μοντέλο Cache

(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)
        )

Κέις χτύπησε → Γρήγορη απάντηση

  • Cache miss → Φόρτωση από HuggingFace HubΚρυφή πλήρης → Auto-exict παλιά μοντέλα, σαφής μνήμη CUDAmax_inflight)
  • Απάντηση (@asynccontextmanagerεπιστρέφει στον πελάτη
  • **Βασικός σχεδιασμός:**Ο μηχανισμός πίσω πίεσης (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 BAR Κόσμος _BAR_ΜΣΚ1

  • **Πηγή: "Hello world"**Κακή μετάφραση: "Hola mundo!!!!!"
  • **Καθαρίστηκε: "Hola mundo" # Αφαιρεί το !!!**Αυτό εξασφαλίζει:👋Τα μοντέλα δεν πνίγονται σε τεράστιες εισροές__SYMBOL_0__Μπορούμε να το κάνουμε αποτελεσματικά.
  • Το πλαίσιο διατηρείται εντός λογικών ορίωνModel Caching & Memory Management

Η μνήμη 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-500MB το καθέναΦόρτωση μοντέλων είναι αργή (1-3 δευτερόλεπτα).!?…Κρατάμε τα 6 πιο πρόσφατα μοντέλα ζεστά
  • Τα παλιά μοντέλα εκδιώχνονται αυτόματαΑναζήτηση & Πίεση οπισθοπορείας
  • **Αντί να καταρρεύσει υπό φορτίο, οι ουρές υπηρεσίας ζητούν:**Η επανεκτίμηση είναι έξυπνη:
  • Pivot Translation FallbackΔεν έχουν όλα τα ζεύγη γλωσσών απευθείας μοντέλα στο πρόσωπο αγκαλιάσματος.

Λύση;

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Ας εξερευνήσουμε μερικά από τα πιο ενδιαφέροντα μέρη της βάσης κώδικα!
  • **Αυτά είναι πραγματικά πρότυπα παραγωγής που καθιστούν την υπηρεσία ισχυρή και αποτελεσματική.**Κάθε snippet περιλαμβάνει εξηγήσεις κατάλληλες για προγραμματιστές μη-Python.
  • **1.**Smart LRU Cache με τη διαχείριση μνήμης GPUenΈνα από τα πιο cool χαρακτηριστικά είναι το έξυπνο μοντέλο cache που ξέρει πώς να χειριστεί τη μνήμη 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.**Automatic Model Family Fallbackmax_inflight=1Αυτή η έξυπνη λειτουργία δοκιμάζει αυτόματα πολλούς παρόχους μοντέλων AI εάν ο πρώτος δεν έχει το ζεύγος γλωσσών που χρειάζεστε:max_inflight=4Τι συμβαίνει εδώ;
  • Αλυσίδα Fallback: Εάν 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

Αίτημα Queue με Backpressure (HTTP 429)

  • **Παραγωγή-βαθμού queuing που αποτρέπει server καταρρεύσει υπό βαρύ φορτίο:**Τι συμβαίνει εδώ;
  • ΣεμαφόρCity name (optional, probably does not need a translation): Όπως ένας πορτιέρης σε ένα κλαμπ - επιτρέπει μόνο N ανθρώπους μέσα ταυτόχρονα (N =
  • Διαχειριστής πλαισίου): Αυτόματα κομμάτια μέτρησης και καθαρίζει
  • Έξυπνη επαναπροσπάθηση μετά: Tells clients "come back in 25 seconds" based on ουρές depth and medium request timeRetry-AfterΕπιφανειοδραστικός κινούμενος μέσος όρος

: Καταπραΰνει τα καρφιά σε διάρκεια αιτήματος

  • Γιατί έχει σημασία;: Υπό βαρύ φορτίο, επιστρέφει HTTP 429 αντί για συντριβή ή ουρά απείρως
  • **4.**Η Μαγεία της Μάσκας Σύμβολο
  • **Διατηρεί ειδικούς χαρακτήρες (emojis, σύμβολα) που τα μεταφραστικά μοντέλα μπορεί να χαλάσουν:**Παράδειγμα χρήσης:
  • **Τι συμβαίνει εδώ;**Σχήμα Regex
  • : Ταιριάζει emoji και ειδικό σύμβολο Unicode εύροςΣύστημα κατόχων
  • : Συμφωνίες ανταλλαγήςμε

προσωρινά

Γιατί έχει σημασία;

: Μεταφραστικά μοντέλα μερικές φορές διαφθείρουν ή να αφαιρέσουν emojis - αυτό τα διατηρεί τέλεια!

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

Έξυπνο Text Chunking

# 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"Async Model Discovery με Caching
    • Δυναμικά ανακαλύπτει τα διαθέσιμα μοντέλα μετάφρασης από HuggingFace:"m2m100,mbart50,opus-mt"Τι συμβαίνει εδώ;
  • Async HTTP client): Makes non-blocking HTTP requests to HuggingFace

    • Χρονο-βάση (caching)/models: Αποθηκεύει αποτελέσματα για 1 ώρα για να αποφευχθεί ο περιορισμός ποσοστού-v ./model-cache:/models
    • Μοντέλο ανάλυσης ονόματος
    • Εκχύλισμα

και

  • fp16από
  • bf16Γιατί έχει σημασία;
  • fp32: HuggingFace έχει 1200+ μοντέλα Opus-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

Το Caching το κάνει αμέσως!

# 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) vs

σε CPU (μέγιστος παραλληλισμός)

# 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

μοτίβο Singleton

# 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

: Μία περίπτωση που μοιράστηκε σε ολόκληρη την εφαρμογή

Exponential Moving Average for Retry-After

Ομαλή εκ νέου δοκιμή μετά την εκτίμηση που προσαρμόζεται στις πραγματικές διάρκεια της αίτησης:

Παράδειγμα:

.\build-all.ps1

Τι συμβαίνει εδώ;

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

EMA (Exponential Moving Average)

: Όπως ένας σταθμισμένος μέσος όρος που δίνει μεγαλύτερη σημασία στις πρόσφατες τιμέςΚαταπραϋντικός συντελεστής (α):

  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Ευχάριστη υποβάθμιση
  • : Αυτόματη αναπήδηση μεταξύ παρόχων μοντέλωνΧειρισμός οπίσθιας πίεσης
  • : Queeue + HTTP 429 αντί για καταρρεύσειςΑκεραιότητα δεδομένων
  • : Η κάλυψη συμβόλων διατηρεί ειδικούς χαρακτήρεςΒελτιστοποίηση των επιδόσεων

: Smart caching, chunking και παράλληλη επεξεργασία

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

Ρύθμιση μοντέλουName

Νέα διαμόρφωση Επεξηγήθηκε:

  1. ΥΠΟΔΕΙΓΜΑ_FAMILY

    EASYNMT_MODEL_ARGS='{"torch_dtype":"fp16"}'
    
    • : Επιλέξτε ποια οικογένεια μοντέλων να χρησιμοποιήσετε ως κύρια
    • : Καλύτερη ποιότητα, 1200+ ζεύγη, ξεχωριστά μοντέλα
    • : Καλή ποιότητα, 50 γλώσσες, μονό μοντέλο 2.4GB
  2. : Καλή ποιότητα, 100 γλώσσες, μονό μοντέλο 2.2GB

    # 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, ...}'
    

ΥΠΟΔΕΙΓΜΑ_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. ΜΟΝΤΕΛΟ_ΚΑΧΗ_ΔΙΟΡΙΣΜΟΣ

    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. : Διαρκής αποθήκευση μοντέλου μέσω όγκου Docker

    // 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. Κοινόχρηστη κρύπτη μεταξύ πολλαπλών εμπορευματοκιβωτίωνΕπιλογές τύπου torch_d:
  2. (επάνω16): 2x γρηγορότερα σε GPU, το ήμισυ της μνήμης, αμελητέα απώλεια ποιότητας(bfloat16): Καλύτερη αριθμητική σταθερότητα από fp16, απαιτεί σύγχρονες GPU
  3. (επάνω32): Πλήρης ακρίβεια, βραδύτερη αλλά πιο ακριβήςΡυθμίσεις μεταφράσεων
  4. Παρακολουθώντας & ΕπιδόσειςΕυαισθητοποίηση εισόδου
  5. Επεξεργασία ποινήςΜάσκα συμβόλωνName
  6. Συμπεριφορά ανταπόκρισηςPivot Fallback
  7. ΚαταγραφήΣυντήρηση

Γουνόκερως (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
}

Μετάφραση παρτίδας (συνιστάται)

Αυτόματη ανίχνευση γλώσσας

Ανίχνευση γλώσσας μόνο |---------|---------|-----------------| | Τελικά σημεία παρατήρησηςΧειρισμός Backpressure | Κτίριο και ΈκδοσηΌλες οι εικόνες Docker τώρα περιλαμβάνουν την κατάλληλη έκδοση και τα μεταδεδομένα για την παρακολούθηση. | Γρήγορη κατασκευήΦτιάξτε και τις 4 παραλλαγές με αυτόματη έκδοση ημερομηνίας: | **Παράθυρα:**Linux/Mac: | Στρατηγική έκδοσηςΚάθε κατασκευή δημιουργεί | δύο ετικέτεςΟνομάζεται ετικέτα | ) - πάντα δείχνει την πιο πρόσφατηΕτικέτα έκδοσης | (π.χ.,) - Αμετάβλητο στιγμιότυπο | **Παραδείγματα:**Ετικέτες OCI | **Κάθε εικόνα περιλαμβάνει μεταδεδομένα:**Έκδοση | **: Κατασκευή χρονοσφραγίδας (YYYYMMDD.HHMMSS)**Ημερομηνία κατασκευής | : ISO 8601 χρονοσφραγίδαΔώσε μου το χέρι σου.

: Short SHA

Παραλλαγή

: cpu-full, cpu-min, gpu-full, ή gpu-minΕτικέτες επιθεώρησης:

Για λεπτομερείς οδηγίες κατασκευής και ενσωμάτωση CI/CD, βλ.

  • BUILD.mdMAX_QUEUE_SIZE
  • Αναπτύξεως
  • Ανάπτυξη ΚΜΕMAX_INFLIGHT_TRANSLATIONSΑνάπτυξη GPU
  • Docker Compose

Kubernetes Development

Βελτιστοποίηση των επιδόσεωνΛίστα ελέγχου βελτιστοποίησης GPU

Χρήση ακρίβειας FP16

  • 2x γρηγορότερο συμπέρασμαENABLE_QUEUE=1
  • Η μισή χρήση VRAM

Απαράδεκτη απώλεια ποιότητας για μετάφραση

Μέγεθος παρτίδας TuneΠροφόρτωση ζεστών μοντέλων

Ελεύθερος εργαζόμενος ανά GPU

  • Αύξηση μεγέθους κρύπτηςEASYNMT_BATCH_SIZE
  • Χαμηλότερο μέγεθος δέσμης για διόρθωσηMAX_CACHED_MODELS
  • Λίστα ελέγχου βελτιστοποίησης CPUEASYNMT_MODEL_ARGS='{"torch_dtype":"fp16"}'
  • Χαμηλότερο μέγεθος παρτίδαςWEB_CONCURRENCY=1Αύξηση παραλληλισμούMAX_INFLIGHT_TRANSLATIONS=1

Απενεργοποίηση διαίρεσης πρότασης για σύντομα κείμενα

Βέλτιστες Πρακτικές ΠελατώνΖήτημα παρτίδας

Σεβασμός - Μετά

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

Χρήση συγκέντρωσης σύνδεσης

Ομάδα ανά ζεύγος γλωσσών Helsinki-NLP/opus-mt-{src}-{tgt}Παρακολούθηση & Παρατήρηση

Μετρική κλειδί για την παρακολούθηση

  • Translation throughputPIVOT_FALLBACK=1(ζητήματα/δευτερόλεπτο)
  • Μέση καθυστέρησηcurl http://localhost:8000/lang_pairs

(p50, p95, p99)

Βάθος αναμονής(τρέχων αριθμός αναμονής)

Ρυθμός χτυπήματος CacheName

  • (% των αιτήσεων που χτυπούν την κρύπτη)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 για CPU)

Παράδειγμα Προμηθέας Μετρικός**Αν ενσωματώσετε τον Προμηθέα (όχι ενσωματωμένο, αλλά εύκολο να προσθέσετε):**Παράδειγμα δομημένης καταγραφής

Μπορείτε να το συνδέσετε με το Elasticsearch, CloudWatch, ή οποιοδήποτε αρχείο καταγραφής.

Σύγκριση: EasyNMT vs ΚυρίωςLucid-NMT

  • □ Χαρακτηριστικό του EasyNMT ~ ΚυρίωςLucid-NMT ~
  • Σταθερότητα
  • Συχνά συντρίβονται Η παραγωγή είναι έτοιμη, χαριτωμένος χειρισμός λάθους

Χειρισμός εισόδου

  • Αποτυγχάνει σε emoji/σύμβολα
  • Πίεση πλάτης
  • Κανένας, OOMs υπό φορτίο Semaphore + ουρά με retry-after

Παρατηρησιμότητα

  • Λίγα σημεία αναφοράς για την υγεία/έτοιμη/βάση, δομημένα αρχεία καταγραφής
  • Υποστήριξη GPU
  • CUDA 10x (αρχαίος) Υποστήριξη CUDA 12.6, FP16/BF16
  • Διαχείριση μοντέλων

**Εγχειρίδιο, δεν caching LRU cache με auto-eviction **

  • Χειρισμός ποινής
  • Βασική διαίρεση Έξυπνο πνιγμό + παρτίδα
  • Μετάφραση Pivot
  • Automatic fallback via English
  • Ευγενικό Κλείσιμο

Όχι, ναι, με το τάιμ-άουτ.

Ρύθμιση**□ Limited 40+ env vars for fine-tuning**Συμβατότητα API

Τα τελικά σημεία EasyNMT είναι 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"}'

Αύξηση ορίου πτήσης εάν έχετε πόρους

OOM (Out of Memory) on GPU

Αιτία:

Μέγεθος παρτίδας πολύ υψηλό ή πάρα πολλά μοντέλα cached.


Διάλυμα:

και

Αργή πρώτη αίτηση[Αιτία:

Το μοντέλο δεν προφορτώθηκε.

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

logo

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