Suchen

infrastructureblogia

Die Übersetzung von Blogartikeln mit KI revolutionieren

Die Übersetzung von Blogartikeln mit KI revolutionieren

In diesem Artikel teile ich ein als Proof of Concept (POC) entwickeltes Python-Skript, um die Übersetzung der Beiträge meines Blogs zu automatisieren, unter Verwendung des Sprachmodells GPT-4 von OpenAI. Dieses Skript ist speziell dafür ausgelegt, Markdown-Dateien zu verarbeiten und erleichtert so die mehrsprachige Verwaltung meiner Artikel. Die Übersetzungen sind über den Sprachwahlschalter oben auf der Seite verfügbar.

Projektbeginn: KI und Automatisierung für meinen Blog vereinen

Dieses Übersetzungsautomatisierungsprojekt für meine Blogartikel entstand aus meiner wachsenden Faszination für künstliche Intelligenz. Inspiriert durch meine ersten Erfahrungen mit den OpenAI GPT-4-APIs und Mistral AI, wollte ich diese Technologien in einem praktischen Projekt umsetzen, das meinem Blog echten Mehrwert bietet. Es ging nicht nur darum, die Werkzeuge der KI zu beherrschen, sondern auch darum, Automatisierung und Innovation zu verbinden, um meine digitale Präsenz zu bereichern.

Das Projekt wurde zu einem Abenteuer, bei dem die KI nicht nur ein Thema zum Schreiben war, sondern ein aktiver Partner in der Entwicklung. Die Idee, meine Artikel einfach und effizient mit KI zu übersetzen und dabei die Automatisierungsmöglichkeiten auszuloten, eröffnete faszinierende Perspektiven. Es war eine Chance, Sprachbarrieren zu überwinden und meine Inhalte einem breiteren Publikum zugänglich zu machen, während ich mich im ständig wandelnden Feld der künstlichen Intelligenz bewegte.

Die Herausforderung

Die Hauptaufgabe bestand darin, ein Skript zu erstellen, das präzise übersetzt und dabei die ursprüngliche Formatierung der Artikel beibehält, insbesondere Codeblöcke, Links und Bilder. Eine weitere Herausforderung war sicherzustellen, dass das Skript leicht an unterschiedliche Sprachen angepasst werden kann. Es sollte auch in der Lage sein, diese Struktur zu berücksichtigen :

├── content
   ├── about
   └── a-propos-du-blog-jls42.md
   ├── mentions
   └── mentions-legales.md
   ├── posts
   ├── blog
   └── nouveau-theme-logo.md
   ├── ia
   ├── poc-mistral-ai-mixtral.md
   ├── poc-openai-api-gpt4.md
   └── stable-difusion-aws-ec2.md
   ├── infrastructure
   └── infrastruture-as-code-serverless-ha-jls42-org.md
   └── raspberry-pi
       ├── glusterfs_distribue_replique_sur_raspberry_pi_via_ansible.md
       ├── initialisation-auto-de-raspbian-sur-raspberry-pi.md
       ├── installation-de-docker-sur-raspberry-pi-via-ansible.md
       └── installation-de-kubernetes-sur-raspberry-pi-via-ansible.md

Die Lösung: Ein innovatives Skript

Ich habe ein Python-Skript entwickelt, das die OpenAI GPT-4-API zur Übersetzung des Textes nutzt und dabei nicht-textliche Elemente bewahrt. Durch eine Reihe von Verarbeitungsregeln und den Einsatz von Platzhaltern kann das Skript Codeblöcke und andere nicht übersetzbare Elemente identifizieren und ausschließen, sodass der übersetzte Inhalt dem Original treu bleibt.

Wichtige Funktionen

  1. Präzise Übersetzung mit GPT-4: Das Skript verwendet das GPT-4-Modell von OpenAI, um den Text vom Französischen ins Englische zu übersetzen und dabei Qualität und Nuancen des Originals zu wahren.
  2. Erhaltung der Formatierung: Codeblöcke, URLs und Bildpfade werden erkannt und während der Übersetzung intakt gelassen, wodurch die ursprüngliche Formatierung erhalten bleibt.
  3. Mehrsprachige Flexibilität: Das Skript ist so konzipiert, dass es leicht an verschiedene Quell- und Zielsprachen angepasst werden kann und somit vielfältige mehrsprachige Anwendungen ermöglicht.
  4. Unterstützung für Markdown-Dateien: Fähigkeit, in Markdown verfasste Dokumente zu übersetzen und deren Struktur und Formatierung beizubehalten.
  5. Automatisierte Übersetzung von Verzeichnissen: Automatische Übersetzung der in einem angegebenen Verzeichnis und dessen Unterverzeichnissen gefundenen Markdown-Dateien, was die Verwaltung großer Inhaltsmengen erleichtert.
  6. Einfügung einer Übersetzungsnotiz: Fügt automatisch eine Übersetzungsnotiz am Ende der übersetzten Dokumente ein, die das für die Übersetzung verwendete GPT-Modell angibt.
  7. Einfache Konfiguration und Anpassung: Anpassbare Standardeinstellungen für den API-Schlüssel, das GPT-Modell, Quell- und Zielsprache sowie Dateiverzeichnisse, die große Flexibilität bieten.
  8. Leistungsbericht: Das Skript gibt Rückmeldungen zur benötigten Zeit für die Übersetzung jeder Datei, sodass die Performance überwacht werden kann.

Skriptcode

Der Code ist auch hier verfügbar : KI-gestützter Markdown-Übersetzer

#!/usr/bin/env python3

import os
import argparse
import time
from openai import OpenAI
import re

# Initialisation de la configuration avec les valeurs par défaut
DEFAULT_API_KEY = 'votre-clé-api-par-défaut'
DEFAULT_MODEL = "gpt-4-1106-preview"
DEFAULT_SOURCE_LANG = 'fr'
DEFAULT_TARGET_LANG = 'en'
DEFAULT_SOURCE_DIR = 'content/posts'
DEFAULT_TARGET_DIR = 'traductions_en'

MODEL_TOKEN_LIMITS = {
    "gpt-4-1106-preview": 4096,
    "gpt-4-vision-preview": 4096,
    "gpt-4": 8192,
    "gpt-4-32k": 32768,
    "gpt-4-0613": 8192,
    "gpt-4-32k-0613": 32768
}

# Fonction de traduction
def translate_with_openai(text, client, args):
    """
    Traduit le texte donné du langage source au langage cible en utilisant l'API OpenAI.

    Args:
        text (str) : Le texte à traduire.
        client : L'objet client OpenAI.
        args : Les arguments contenant les informations sur le langage source, le langage cible et le modèle.

    Returns:
        str : Le texte traduit.
    """
    # Détecter et stocker les blocs de code
    code_blocks = re.findall(r'(^```[a-zA-Z]*\n.*?\n^```)', text, flags=re.MULTILINE | re.DOTALL)
    placeholders = [f"#CODEBLOCK{index}#" for index, _ in enumerate(code_blocks)]

    # Remplacer les blocs de code par des placeholders
    for placeholder, code_block in zip(placeholders, code_blocks):
        text = text.replace(code_block, placeholder)

    # Création du message pour l'API
    messages = [
        {"role": "system", "content": f"Translate the following text from {args.source_lang} to {args.target_lang}, ensuring that elements such as URLs, image paths, and code blocks (delimited by ```) are not translated. Leave these elements unchanged."},
        {"role": "user", "content": text}
    ]

    # Envoi de la demande de traduction
    response = client.chat.completions.create(
        model=args.model,
        messages=messages
    )

    # Obtenir le texte traduit et remplacer les placeholders par les blocs de code originaux
    translated_text = response.choices[0].message.content.strip()
    for placeholder, code_block in zip(placeholders, code_blocks):
        translated_text = translated_text.replace(placeholder, code_block)

    return translated_text

def add_translation_note(client, args):
    """
    Ajoute une note de traduction à un document.

    Args:
        client : Le client de traduction.
        args : Arguments supplémentaires.

    Returns:
        La note de traduction formatée.
    """
    # Note de traduction en français
    translation_note_fr = "Ce document a été traduit de la version française du blog par le modèle "
    # Traduire la note en langue cible
    translated_note = translate_with_openai(translation_note_fr + args.model, client, args)
    # Formatage de la note de traduction
    return f"\n\n**{translated_note}**\n\n"

# Traitement des fichiers Markdown
def translate_markdown_file(file_path, output_path, client, args):
    """
    Traduit le contenu d'un fichier markdown en utilisant l'API de traduction OpenAI et écrit le contenu traduit dans un nouveau fichier.

    Args:
        file_path (str): Chemin vers le fichier markdown d'entrée.
        output_path (str): Chemin vers le fichier de sortie où le contenu traduit sera écrit.
        client: Client de traduction OpenAI.
        args: Arguments supplémentaires pour le processus de traduction.

    Returns:
        None
    """
    print(f"Traitement du fichier : {file_path}")
    start_time = time.time()

    with open(file_path, 'r', encoding='utf-8') as f:
        content = f.read()

    translated_content = translate_with_openai(content, client, args)

    # Ajouter la note de traduction à la fin du contenu traduit
    translation_note = add_translation_note(client, args)
    translated_content_with_note = translated_content + translation_note

    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(translated_content_with_note)

    end_time = time.time()
    print(f"Traduction terminée en {end_time - start_time:.2f} secondes.")

def translate_directory(input_dir, output_dir, client, args):
    """
    Traduit tous les fichiers markdown dans le répertoire d'entrée et ses sous-répertoires.

    Args:
        input_dir (str): Chemin vers le répertoire d'entrée.
        output_dir (str): Chemin vers le répertoire de sortie.
        client: Objet client de traduction.
        args: Arguments supplémentaires pour la traduction.

    Returns:
        None
    """
    for root, dirs, files in os.walk(input_dir, topdown=True):
        # Exclure les dossiers qui commencent par "traductions_"
        dirs[:] = [d for d in dirs if not d.startswith("traductions_")]

        for file in files:
            if file.endswith('.md'):
                file_path = os.path.join(root, file)
                base, _ = os.path.splitext(file)
                # Ajouter le nom du modèle utilisé dans le nom du fichier de sortie
                output_file = f"{base}-{args.model}-{args.target_lang}.md"
                relative_path = os.path.relpath(root, input_dir)
                output_path = os.path.join(output_dir, relative_path, output_file)

                os.makedirs(os.path.dirname(output_path), exist_ok=True)

                if not os.path.exists(output_path):
                    translate_markdown_file(file_path, output_path, client, args)
                    print(f"Fichier '{file}' traité.")


def main():
    """
    Fonction principale pour traduire les fichiers Markdown.

    Args:
        --source_dir (str): Répertoire source contenant les fichiers Markdown.
        --target_dir (str): Répertoire cible pour sauvegarder les traductions.
        --model (str): Modèle GPT à utiliser.
        --target_lang (str): Langue cible pour la traduction.
        --source_lang (str): Langue source pour la traduction.
    """
    parser = argparse.ArgumentParser(description="Traduit les fichiers Markdown.")
    parser.add_argument('--source_dir', type=str, default=DEFAULT_SOURCE_DIR, help='Répertoire source contenant les fichiers Markdown')
    parser.add_argument('--target_dir', type=str, default=DEFAULT_TARGET_DIR, help='Répertoire cible pour sauvegarder les traductions')
    parser.add_argument('--model', type=str, default=DEFAULT_MODEL, help='Modèle GPT à utiliser')
    parser.add_argument('--target_lang', type=str, default=DEFAULT_TARGET_LANG, help='Langue cible pour la traduction')
    parser.add_argument('--source_lang', type=str, default=DEFAULT_SOURCE_LANG, help='Langue source pour la traduction')

    args = parser.parse_args()

    openai_api_key = os.getenv('OPENAI_API_KEY', DEFAULT_API_KEY)
    with OpenAI(api_key=openai_api_key) as client:
        translate_directory(args.source_dir, args.target_dir, client, args)

if __name__ == "__main__":
    main()

Blick auf das Skript

Modulimporte

Zunächst haben wir einige notwendige Modulimporte wie os, argparse, time und re. Diese Module werden verwendet, um Operationen auf dem Dateisystem auszuführen, Kommandozeilenargumente zu parsen, die Ausführungszeit zu messen und Such- und Ersetzungsoperationen im Text durchzuführen.

Konstanten

Anschließend gibt es definierte Konstanten wie DEFAULT_API_KEY, DEFAULT_MODEL, DEFAULT_SOURCE_LANG, DEFAULT_TARGET_LANG, DEFAULT_SOURCE_DIR und DEFAULT_TARGET_DIR. Diese Konstanten repräsentieren die Standardwerte, die im Skript verwendet werden, können aber durch Angabe von Kommandozeilenargumenten geändert werden.

Funktion translate_with_openai

Danach betrachten wir die Funktion translate_with_openai. Diese Funktion nimmt einen Text, ein OpenAI-Clientobjekt und Argumente als Parameter. Sie verwendet die OpenAI-API, um den Text von der Quellsprache in die Zielsprache zu übersetzen. So funktioniert sie:

  1. Die Funktion verwendet einen regulären Ausdruck, um Codeblöcke im Text zu erkennen und zu speichern. Diese Codeblöcke werden durch dreifache Backticks abgegrenzt (). Les blocs de code sont stockés dans une liste appelée code_blocks`.
  2. Anschließend ersetzt die Funktion die Codeblöcke durch Platzhalter im Text. Die Platzhalter sind Zeichenketten der Form #CODEBLOCK{index}#, wobei index der Index des entsprechenden Codeblocks in der Liste code_blocks ist.
  3. Die Funktion erstellt eine Nachricht für die OpenAI-API. Diese Nachricht besteht aus zwei Teilen: einer Systemnachricht, die die API anweist, den Text von der Quellsprache in die Zielsprache zu übersetzen und Elemente wie URLs, Bildpfade und Codeblöcke unverändert zu lassen, und einer Nutzernachricht, die den zu übersetzenden Text enthält.
  4. Die Funktion sendet die Übersetzungsanfrage an die API mithilfe der Methode client.chat.completions.create(). Dabei werden das zu verwendende Modell und die Nachrichten angegeben.
  5. Die Antwort der API enthält den übersetzten Text. Die Funktion holt den übersetzten Text und ersetzt die Platzhalter wieder durch die ursprünglichen Codeblöcke.
  6. Schließlich gibt die Funktion den übersetzten Text zurück.

Funktion add_translation_note

Als Nächstes haben wir die Funktion add_translation_note. Diese Funktion fügt einem Dokument eine Übersetzungsnotiz hinzu. Sie nimmt ein OpenAI-Clientobjekt und Argumente als Parameter. So funktioniert sie:

  1. Die Funktion erstellt eine Übersetzungsnotiz auf Französisch unter Verwendung der Variable translation_note_fr.
  2. Anschließend verwendet die Funktion die Funktion translate_with_openai, um die Übersetzungsnotiz mithilfe der OpenAI-API zu übersetzen. Zu den an translate_with_openai übergebenen Argumenten gehören die französische Übersetzungsnotiz und weitere Argumente.
  3. Die Funktion formatiert die übersetzte Notiz, indem sie Formatierungszeichen hinzufügt.
  4. Schließlich gibt die Funktion die formatierte Übersetzungsnotiz zurück.

Funktion translate_markdown_file

Dann haben wir die Funktion translate_markdown_file. Diese Funktion nimmt den Pfad einer Eingabe-Markdown-Datei, den Pfad einer Ausgabedatei, ein OpenAI-Clientobjekt und Argumente als Parameter. Sie übersetzt den Inhalt der Markdown-Datei mithilfe der OpenAI-Übersetzungs-API und schreibt den übersetzten Inhalt in die Ausgabedatei.

Dieses Skript hat nicht nur die Zugänglichkeit meiner Blogartikel verbessert, sondern auch den Weg für neue Automatisierungsmöglichkeiten im Bereich der mehrsprachigen Inhaltserstellung geebnet. Es ist ein Schritt in Richtung einer breiteren und inklusiveren Verbreitung von Wissen.

Benutzererfahrung und Verarbeitungszeit

Anwendungsbeispiele

# Création des répertoires cibles
jls42@Boo:~/blog/jls42$ mkdir content/traductions_en content/traductions_es

###############################################
# Demande de traduction à l'IA vers l'anglais #
###############################################
jls42@Boo:~/blog/jls42$ python3 translate.py --source_dir content/ --target_dir content/traductions_en
Traitement du fichier : content/posts/ia/stable-difusion-aws-ec2.md
Traduction terminée en 21.57 secondes.
Fichier 'stable-difusion-aws-ec2.md' traité.
Traitement du fichier : content/posts/ia/poc-openai-api-gpt4.md
Traduction terminée en 34.87 secondes.
Fichier 'poc-openai-api-gpt4.md' traité.
Traitement du fichier : content/posts/ia/poc-mistral-ai-mixtral.md
Traduction terminée en 62.47 secondes.
Fichier 'poc-mistral-ai-mixtral.md' traité.
Traitement du fichier : content/posts/raspberry-pi/installation-de-kubernetes-sur-raspberry-pi-via-ansible.md
Traduction terminée en 46.37 secondes.
Fichier 'installation-de-kubernetes-sur-raspberry-pi-via-ansible.md' traité.
Traitement du fichier : content/posts/raspberry-pi/installation-de-docker-sur-raspberry-pi-via-ansible.md
Traduction terminée en 10.08 secondes.
Fichier 'installation-de-docker-sur-raspberry-pi-via-ansible.md' traité.
Traitement du fichier : content/posts/raspberry-pi/initialisation-auto-de-raspbian-sur-raspberry-pi.md
Traduction terminée en 17.17 secondes.
Fichier 'initialisation-auto-de-raspbian-sur-raspberry-pi.md' traité.
Traitement du fichier : content/posts/blog/nouveau-theme-logo.md
Traduction terminée en 12.91 secondes.
Fichier 'nouveau-theme-logo.md' traité.
Traitement du fichier : content/posts/infrastructure/infrastruture-as-code-serverless-ha-jls42-org.md
Traduction terminée en 12.64 secondes.
Fichier 'infrastruture-as-code-serverless-ha-jls42-org.md' traité.
Traitement du fichier : content/mentions/mentions-legales.md
Traduction terminée en 11.90 secondes.
Fichier 'mentions-legales.md' traité.
Traitement du fichier : content/about/a-propos-du-blog-jls42.md
Traduction terminée en 18.72 secondes.
Fichier 'a-propos-du-blog-jls42.md' traité.

################################################
# Demande de traduction à l'IA vers l'espagnol #
################################################
jls42@Boo:~/blog/jls42$ python3 translate.py --source_dir content/ --target_dir content/traductions_es --target_lang es
Traitement du fichier : content/posts/ia/stable-difusion-aws-ec2.md
Traduction terminée en 33.19 secondes.
Fichier 'stable-difusion-aws-ec2.md' traité.
Traitement du fichier : content/posts/ia/poc-openai-api-gpt4.md
Traduction terminée en 25.24 secondes.
Fichier 'poc-openai-api-gpt4.md' traité.
Traitement du fichier : content/posts/ia/poc-mistral-ai-mixtral.md
Traduction terminée en 58.78 secondes.
Fichier 'poc-mistral-ai-mixtral.md' traité.
Traitement du fichier : content/posts/raspberry-pi/installation-de-kubernetes-sur-raspberry-pi-via-ansible.md
Traduction terminée en 17.64 secondes.
Fichier 'installation-de-kubernetes-sur-raspberry-pi-via-ansible.md' traité.
Traitement du fichier : content/posts/raspberry-pi/installation-de-docker-sur-raspberry-pi-via-ansible.md
Traduction terminée en 19.60 secondes.
Fichier 'installation-de-docker-sur-raspberry-pi-via-ansible.md' traité.
Traitement du fichier : content/posts/raspberry-pi/initialisation-auto-de-raspbian-sur-raspberry-pi.md
Traduction terminée en 37.12 secondes.
Fichier 'initialisation-auto-de-raspbian-sur-raspberry-pi.md' traité.
Traitement du fichier : content/posts/blog/nouveau-theme-logo.md
Traduction terminée en 18.91 secondes.
Fichier 'nouveau-theme-logo.md' traité.
Traitement du fichier : content/posts/infrastructure/infrastruture-as-code-serverless-ha-jls42-org.md
Traduction terminée en 30.73 secondes.
Fichier 'infrastruture-as-code-serverless-ha-jls42-org.md' traité.
Traitement du fichier : content/mentions/mentions-legales.md
Traduction terminée en 13.14 secondes.
Fichier 'mentions-legales.md' traité.
Traitement du fichier : content/about/a-propos-du-blog-jls42.md
Traduction terminée en 11.24 secondes.
Fichier 'a-propos-du-blog-jls42.md' traité.

Verarbeitungszeit

  • Englisch : Etwa 4 Minuten (248.70 Sekunden)
  • Spanisch : Etwa 4,7 Minuten (284.05 Sekunden)
  • Kumuliert : Etwa 8,7 Minuten (532.75 Sekunden) Diese Zeiten zeigen die Effizienz und Schnelligkeit des Skripts.

Ergebnisse

Hinweis : Dieses Beispiel veranschaulicht die Funktionsweise des Skripts auf der alten Hugo-Struktur des Blogs. Der Blog wurde inzwischen zu Astro migriert und verfügt über eine neue mehrsprachige Architektur. Die Übersetzungen sind jetzt über den integrierten Sprachwahlschalter zugänglich.

Dieser Blogbeitrag fasst meine Erfahrungen mit der automatisierten Übersetzung mittels KI zusammen. Er beweist, dass die Verbindung von Programmierung und künstlicher Intelligenz nahezu unbegrenzte Möglichkeiten eröffnet und neue, spannende Horizonte im Teilen von Wissen und der Zugänglichkeit von Inhalten erschließt.

Dieses Dokument wurde von der fr-Version in die Sprache en mit dem Modell gpt-5-mini übersetzt. Für weitere Informationen über den Übersetzungsprozess konsultieren Sie https://gitlab.com/jls42/ai-powered-markdown-translator