Machine Translation: Машинный перевод с LLM

nlpmachine-translationllmopensourcemultilingual
← Back to Blog

Введение

Machine Translation (MT) — одна из старейших задач NLP. LLM произвели революцию в машинном переводе, сделав его значительно качественнее классических нейронных моделей.


Эволюция машинного перевода

1. Rule-based (RBMT)

Правила на основе лингвистики:
  "The cat sits on the mat" → "Кот сидит на коврике"
  
  Правила:
  - The → Кот (определённый артикль → им. падеж)
  - cat → кот
  - sits → сидит (3л, ед.ч.)
  - on → на (предлог)
  - the → на (определённый артикль опускается)
  - mat → коврик

2. Statistical (SMT)

Statistical Machine Translation:
  P(translation|source) ∝ P(source|translation) × P(translation)
  
  P(source|translation) — модель перевода
  P(translation) — языковая модель
  
  Пример:
  "hello world" → "привет мир" (0.85)
  "hello world" → "здравствуйте мир" (0.10)
  "hello world" → "привет мир" (0.05)

3. Neural (NMT)

Neural Machine Translation:
  P(target|source) = ∏ P(word_i | source, words_1...i-1)
  
  Encoder: [hello] [world] → [вектор контекста]
  Decoder: [BOS] → "привет" → "мир" → [EOS]

4. LLM-based Translation

Large Language Models:
  P(target|source, prompt, context)
  
  Преимущества:
  - Zero-shot перевод
  - Контекстуальная осведомлённость
  - Стиль и регистр
  - Множествен варианты перевода

Zero-shot перевод с LLM

Базовый перевод

from openai import OpenAI

client = OpenAI()

def translate(text, source_lang, target_lang):
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "system",
                "content": f"Перведи текст с {source_lang} на {target_lang}.
Верни только перевод, без объяснений."
            },
            {"role": "user", "content": text}
        ]
    )
    return response.choices[0].message.content

# Использование
print(translate("Hello, world!", "English", "Russian"))
# → "Привет, мир!"

print(translate("Привет, мир!", "Russian", "Japanese"))
# → "こんにちは、世界!"

Перевод с учётом контекста

def translate_with_context(text, source_lang, target_lang, context=None):
    system_prompt = f"Перведи с {source_lang} на {target_lang}."
    
    if context:
        system_prompt += f"\n\nКонтекст: {context}"
    
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": text}
        ]
    )
    return response.choices[0].message.content

Перевод с выбором стиля

def translate_with_style(text, source_lang, target_lang, style="formal"):
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "system",
                "content": f"Перведи с {source_lang} на {target_lang}.
Стиль: {style}."
            },
            {"role": "user", "content": text}
        ]
    )
    return response.choices[0].message.content

# Формальный
print(translate_with_style(
    "Hey, what's up?", "English", "Russian", "formal"
))
# → "Здравствуйте, как ваши дела?"

# Неформальный
print(translate_with_style(
    "Hey, what's up?", "English", "Russian", "informal"
))
# → "Привет, как дела?"

Перевод с few-shot examples

Few-shot translation

def few_shot_translate(text, source_lang, target_lang, examples):
    """Перевод с примерами"""
    
    examples_str = "\n".join([
        f"{src}\n{tgt}" for src, tgt in examples
    ])
    
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "system",
                "content": f"Перведи с {source_lang} на {target_lang}.
Следуй формату примеров."
            },
            {"role": "user", "content": f"Примеры:\n{examples_str}\n\nПереведи:\n{text}"}
        ]
    )
    return response.choices[0].message.content

# Использование
examples = [
    ("Hello, how are you?", "Привет, как дела?"),
    ("I'm fine, thanks.", "Всё хорошо, спасибо."),
    ("See you later.", "Увидимся позже.")
]

print(few_shot_translate(
    "Good morning!", "English", "Russian", examples
))
# → "Доброе утро!"

Перевод с локальными моделями

NLLB (No Language Left Behind)

from transformers import AutoTokenizer, AutoModelForSeq2SeqLM

# Meta NLLB — 200+ языков
model_name = "facebook/nllb-200-distilled-600M"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSeq2SeqLM.from_pretrained(model_name)

def translate_nllb(text, src_lang, tgt_lang):
    # NLLB использует коды языков
    langs = {
        "eng_Latn": "English",
        "rus_Cyrl": "Russian",
        "zho_Hans": "Chinese",
        "jpn_Jpan": "Japanese",
        "deu_Latn": "German",
        "fra_Latn": "French"
    }
    
    src_code = langs[src_lang]
    tgt_code = langs[tgt_lang]
    
    prefix = f"{tgt_code} "
    inputs = tokenizer(
        prefix + text,
        return_tensors="pt",
        truncation=True,
        max_length=512
    )
    
    outputs = model.generate(**inputs, max_length=512)
    return tokenizer.decode(outputs[0], skip_special_tokens=True)

# Использование
print(translate_nllb(
    "Hello, world!", "eng_Latn", "rus_Cyrl"
))
# → "Привет, мир!"

MarianMT для конкретных пар языков

from transformers import MarianMTModel, MarianTokenizer

# Специализированная модель для пары языков
model_name = "Helsinki-NLP/opus-mt-en-ru"
tokenizer = MarianTokenizer.from_pretrained(model_name)
model = MarianMTModel.from_pretrained(model_name)

def translate_en_ru(text):
    inputs = tokenizer(
        text, return_tensors="pt",
        truncation=True, max_length=512
    )
    
    translated = model.generate(**inputs, max_length=512)
    return tokenizer.decode(translated[0], skip_special_tokens=True)

# Использование
print(translate_en_ru("The quick brown fox jumps over the lazy dog."))
# → "Быстрая коричневая лиса перепрыгивает через ленивую собаку."

llama.cpp для перевода

import requests

def translate_with_llama(text, source_lang, target_lang):
    prompt = f"""Перведи с {source_lang} на {target_lang}.

{source_lang}: {text}
{target_lang}:"""

    response = requests.post(
        "http://localhost:8080/completion",
        json={
            "prompt": prompt,
            "max_tokens": 500,
            "temperature": 0.3
        }
    )
    return response.json()["response"].strip()

Batch translation

Перевод документов

import tiktoken

def split_document(text, max_tokens=1000):
    """Разбиение документа на части для перевода"""
    encoding = tiktoken.get_encoding("cl100k_base")
    tokens = encoding.encode(text)
    
    chunks = []
    for i in range(0, len(tokens), max_tokens):
        chunks.append(encoding.decode(tokens[i:i+max_tokens]))
    
    return chunks

def translate_document(text, source_lang, target_lang):
    chunks = split_document(text)
    translated_chunks = []
    
    for chunk in chunks:
        translated = translate(chunk, source_lang, target_lang)
        translated_chunks.append(translated)
    
    return '\n'.join(translated_chunks)

Перевод с сохранением формата

import re

def translate_preserving_format(text, source_lang, target_lang):
    """Перевод с сохранением форматирования"""
    
    # Извлекаем теги и форматирование
    tags = re.findall(r'<[^>]+>', text)
    clean_text = re.sub(r'<[^>]+>', '', text)
    
    # Переводим
    translated = translate(clean_text, source_lang, target_lang)
    
    # Восстанавливаем теги
    for tag in tags:
        translated = translated.replace(tag, tag)
    
    return translated

Multilingual LLMs

Поддержка языков в LLM

GPT-4o:
  ✅ English, Chinese, Spanish, French, German, Japanese, Korean
  ✅ Arabic, Hindi, Portuguese, Russian, Italian
  ✅ 50+ языков с высоким качеством

Llama 3:
  ✅ English, German, French, Spanish, Italian, Portuguese
  ✅ Hindi, Arabic, Dutch, Polish, Turkish, Chinese, Japanese, Korean

Multilingual BERT:
  ✅ 104 языков
  ✅ Коды: eng_Latn, rus_Cyrl, zho_Hans, jpn_Jpan

Коды языков NLLB

LANGUAGES = {
    "English": "eng_Latn",
    "Russian": "rus_Cyrl",
    "Chinese": "zho_Hans",
    "Japanese": "jpn_Jpan",
    "Korean": "kor_Hang",
    "German": "deu_Latn",
    "French": "fra_Latn",
    "Spanish": "spa_Latn",
    "Arabic": "arb_Arab",
    "Hindi": "hin_Deva",
    "Portuguese": "por_Latn",
    "Italian": "ita_Latn",
    "Dutch": "nld_Latn",
    "Polish": "pol_Latn",
    "Turkish": "tur_Latn",
    "Swahili": "swa_Latn",
    "Thai": "tha_Thai"
}

Translation quality assessment

Метрики качества

BLEU (Bilingual Evaluation Understudy):
  n-gram precision с penalty за короткие переводы
  
  BLEU = BP × exp(∑ w_n × log(p_n))
  
  Пример:
  Reference: "The cat sits on the mat"
  Hypothesis: "The cat is on the mat"
  BLEU: 0.45

BLEU ranges:
  0.0-0.2: Poor
  0.2-0.4: Fair
  0.4-0.6: Good
  0.6-0.8: Very Good
  0.8-1.0: Excellent

METEOR:
  Учитывает синонимы и стемминг
  
TER (Translation Edit Rate):
  Минимальное количество правок
  
chrF:
  n-gram precision по character level

Оценка качества

from sacrebleu import corpus_bleu, sentence_bleu

def evaluate_translation(hypothesis, references):
    """Оценка перевода с помощью sacrebleu"""
    
    # Corpus BLEU
    bleu_score = corpus_bleu(
        [hypothesis],
        [references]
    ).score
    
    # Детальный разбор
    details = corpus_bleu(
        [hypothesis],
        [references],
        smooth_method="exp",
        force=True,
        lowercase=True,
        use_effective_order=True
    )
    
    return {
        "bleu_score": bleu_score,
        "bleu_details": details,
        "quality_estimate": "good" if bleu_score > 30 else "poor"
    }

# Использование
hypothesis = "Привет, мир!"
references = ["Привет, мир!", "Здравствуйте, мир!"]

print(evaluate_translation(hypothesis, references))

Human evaluation simulation

def simulate_human_evaluation(translation, reference):
    """Симуляция человеческой оценки"""
    
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "system",
                "content": """Оцени перевод по шкале 1-5:
1 - Неправильный перевод
2 - Грубая ошибка смысла
3 - Понятно, но с ошибками
4 - Хороший перевод, мелкие недочёты
5 - Идеальный перевод"""
            },
            {"role": "user", "content": f"Reference: {reference}\nTranslation: {translation}"}
        ]
    )
    return int(response.choices[0].message.content)

Back-translation

Улучшение переводов

Back-translation:
  1. Translate source → target
  2. Translate target → source (back)
  3. Compare back-translation with original
  
  Если back-translation ≈ original → перевод качественный
def back_translate(text, source_lang, target_lang):
    """Back-translation для проверки качества"""
    
    # Прямой перевод
    translation = translate(text, source_lang, target_lang)
    
    # Обратный перевод
    back_translation = translate(
        translation, target_lang, source_lang
    )
    
    # Сравнение
    similarity = check_similarity(text, back_translation)
    
    return {
        "original": text,
        "translation": translation,
        "back_translation": back_translation,
        "quality_score": similarity,
        "is_reliable": similarity > 0.85
    }

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

1. Локализация приложений

def localize_app(strings, target_lang):
    """Локализация интерфейса приложения"""
    localized = {}
    
    for key, value in strings.items():
        # Перевод с учётом контекста
        translation = translate_with_context(
            value, "English", target_lang,
            context=f"UI string for key: {key}"
        )
        localized[key] = translation
    
    return localized

2. Перевод документов

def translate_document(doc_path, target_lang):
    """Перевод целого документа"""
    
    # Чтение документа
    content = read_document(doc_path)
    
    # Разбиение на параграфы
    paragraphs = content.split('\n\n')
    
    # Перевод
    translated = []
    for p in paragraphs:
        if p.strip():
            translated.append(translate(p, "English", target_lang))
        else:
            translated.append('')
    
    # Сохранение
    save_translated_document('\n\n'.join(translated), target_lang)

3. Real-time translation

from fastapi import FastAPI
import asyncio

app = FastAPI()

@app.post("/translate")
async def translate_endpoint(request: TranslationRequest):
    """API для перевода в реальном времени"""
    
    translation = await asyncio.to_thread(
        translate,
        request.text,
        request.source_lang,
        request.target_lang
    )
    
    return {"translation": translation}

4. Субтитры

def translate_subtitles(srt_path, target_lang):
    """Перевод субтитров"""
    
    subtitles = parse_srt(srt_path)
    
    for subtitle in subtitles:
        # Перевод с сохранением таймингов
        subtitle["text"] = translate(
            subtitle["text"], "English", target_lang
        )
    
    save_srt(subtitles, f"translated_{target_lang}.srt")

Open Source инструменты

Модели:
  ✅ NLLB (Meta) — 200+ языков
  ✅ MarianMT — специализированные модели
  ✅ mBART (multilingual)
  ✅ T5-multilingual
  ✅ M2M100 (Meta) — 100+ языков

Библиотеки:
  ✅ fairseq (Meta)
  ✅ OpenNMT
  ✅ Apertium
  ✅ sacrebleu (оценка)

Бенчмарки:
  ✅ WMT (Workshop on Machine Translation)
  ✅ BLEU, METEOR, TER
  ✅ COMET (нейросетевая метрика)

Итоги

Machine Translation с LLM стала значительно качественнее. Zero-shot перевод работает для большинства языковых пар, а fine-tuned модели дают лучший результат для специфичных доменов.

Ключевые выводы:

  • Zero-shot перевод с GPT-4o точен для большинства языков
  • NLLB — лучший open-source для 200+ языков
  • MarianMT — быстрый для конкретных пар языков
  • Back-translation для проверки качества
  • BLEU — основной метрик, но COMET точнее
  • Локальные модели для приватных данных