In questo articolo, condivido uno script Python sviluppato come Proof of Concept (POC) per automatizzare la traduzione dei post del mio blog, utilizzando il modello di linguaggio GPT-4 di OpenAI. Questo script è specificamente progettato per trattare file Markdown nella struttura del mio blog Hugo, facilitando la gestione multilingue dei miei articoli. Sono disponibili in Inglese, Spagnolo e Cinese.

Inizio del Progetto: Fondere l’IA e l’Automazione per il Mio Blog

Questo progetto di automazione della traduzione dei miei articoli di blog è stato avviato dalla mia crescente fascinazione per l’intelligenza artificiale. Ispirato dalle mie esperienze preliminari con le API OpenAI GPT-4 e Mistral AI, sono stato attratto dall’idea di concretizzare queste tecnologie in un progetto pratico, offrendo un valore tangibile al mio blog. Non era solo una ricerca per padroneggiare gli strumenti dell’IA, ma anche il desiderio di fondere l’automazione e l’innovazione per arricchire il mio spazio digitale.

Questo progetto si è trasformato in un’avventura in cui l’IA non era solo un argomento di scrittura, ma un partner attivo nello sviluppo. L’idea di tradurre i miei articoli in modo semplice ed efficace con l’IA, esplorando al tempo stesso le sue capacità di automazione, apriva prospettive affascinanti. Si trattava di un’opportunità per trascendere le barriere linguistiche, rendendo il mio contenuto accessibile a un pubblico più ampio, navigando nel campo in continua evoluzione dell’intelligenza artificiale.

La Sfida

La sfida principale era creare uno script in grado di tradurre con precisione e conservare la formattazione originale degli articoli, inclusi blocchi di codice, link e immagini. Un’altra sfida era assicurarsi che lo script potesse essere facilmente adattato per supportare diverse lingue. Doveva anche essere in grado di tenere conto di questa struttura:

├── 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

La Soluzione: Uno Script Innovativo

Ho progettato uno script Python che si basa sull’API OpenAI GPT-4 per tradurre il testo mantenendo intatti gli elementi non testuali. Grazie a una serie di regole di elaborazione e all’uso di segnaposti, lo script può identificare ed escludere blocchi di codice e altri elementi non traducibili, garantendo che il contenuto tradotto rimanga fedele all’originale.

Caratteristiche Chiave

  1. Traduzione Precisa con GPT-4: Lo script utilizza il modello GPT-4 di OpenAI per tradurre il testo dal francese all’inglese, assicurandosi di mantenere la qualità e la sfumatura del contenuto originale.
  2. Preservazione della Formattazione: I blocchi di codice, gli URL e i percorsi delle immagini vengono identificati e lasciati intatti durante la traduzione, garantendo che la formattazione originale venga mantenuta.
  3. Flessibilità Multilingue: Lo script è progettato per essere facilmente adattabile a diverse lingue di origine e destinazione, permettendo una grande varietà di applicazioni multilingue.
  4. Supporto per i File Markdown: Capacità di tradurre documenti scritti in Markdown, mantenendo la loro struttura e formattazione specifiche.
  5. Automazione della Traduzione delle Directory: Traduzione automatica dei file Markdown trovati in una determinata directory e nelle sue sottodirectory, facilitando la gestione di grandi volumi di contenuti.
  6. Integrazione della Nota di Traduzione: Aggiunge automaticamente una nota di traduzione alla fine dei documenti tradotti, indicando il modello GPT utilizzato per la traduzione.
  7. Configurazione e Personalizzazione Facili: Impostazioni predefinite personalizzabili per la chiave API, il modello GPT, le lingue di origine e destinazione, e le directory dei file, offrendo grande flessibilità d’uso.
  8. Rapporto sulla Performance : Lo script fornisce un feedback sul tempo necessario per tradurre ogni file, permettendo di monitorare la sua performance.

Codice dello script

Il codice è disponibile anche qui: AI-Powered Markdown Translator

#!/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()

Focus sullo script

Importazione dei moduli

Per prima cosa, abbiamo alcune importazioni di moduli necessari, come os, argparse, time e re. Questi moduli vengono utilizzati per eseguire operazioni sul file system, analizzare gli argomenti della riga di comando, misurare il tempo di esecuzione ed eseguire operazioni di ricerca e sostituzione testo.

Costanti

Successivamente, abbiamo delle costanti definite, come DEFAULT_API_KEY, DEFAULT_MODEL, DEFAULT_SOURCE_LANG, DEFAULT_TARGET_LANG, DEFAULT_SOURCE_DIR e DEFAULT_TARGET_DIR. Queste costanti rappresentano i valori predefiniti utilizzati nello script, ma possono essere modificate specificando degli argomenti della riga di comando.

Funzione translate_with_openai

Successivamente, abbiamo la funzione translate_with_openai. Questa funzione prende un testo, un oggetto client OpenAI e degli argomenti come parametri. Utilizza l’API OpenAI per tradurre il testo dalla lingua di origine alla lingua di destinazione. Ecco come funziona:

  1. La funzione utilizza un’espressione regolare per rilevare e memorizzare i blocchi di codice nel testo. Questi blocchi di codice sono delimitati da triple backtick (```). I blocchi di codice sono memorizzati in una lista chiamata code_blocks.
  2. Successivamente, la funzione sostituisce i blocchi di codice con dei segnaposto nel testo. I segnaposto sono stringhe del tipo #CODEBLOCK{index}#, dove index è l’indice del blocco di codice corrispondente nella lista code_blocks.
  3. La funzione crea un messaggio per l’API OpenAI. Questo messaggio contiene due parti: un messaggio di sistema che indica all’API di tradurre il testo dalla lingua di origine a quella di destinazione lasciando invariati elementi come URL, percorsi di immagini e blocchi di codice, e un messaggio utente che contiene il testo da tradurre.
  4. La funzione invia la richiesta di traduzione all’API utilizzando il metodo client.chat.completions.create(). Specifica il modello da utilizzare e i messaggi da tradurre.
  5. La risposta dell’API contiene il testo tradotto. La funzione recupera il testo tradotto e sostituisce i segnaposto con i blocchi di codice originali.
  6. Infine, la funzione restituisce il testo tradotto.

Funzione add_translation_note

Successivamente, abbiamo la funzione add_translation_note. Questa funzione aggiunge una nota di traduzione a un documento. Prende un oggetto client OpenAI e degli argomenti come parametri. Ecco come funziona:

  1. La funzione crea una nota di traduzione in francese utilizzando la variabile translation_note_fr.
  2. Successivamente, la funzione utilizza la funzione translate_with_openai per tradurre la nota di traduzione utilizzando l’API OpenAI. Gli argomenti passati a translate_with_openai includono la nota di traduzione in francese e gli altri argomenti.
  3. La funzione formatta la nota di traduzione tradotta aggiungendo caratteri di formattazione.
  4. Infine, la funzione restituisce la nota di traduzione formattata.

Funzione translate_markdown_file

Successivamente, abbiamo la funzione translate_markdown_file. Questa funzione prende il percorso di un file Markdown di input, il percorso di un file di output, un oggetto client OpenAI e degli argomenti come parametri. Traduce il contenuto del file Markdown utilizzando l’API di traduzione OpenAI e scrive il contenuto tradotto nel file di output.

Questo script non solo ha migliorato l’accessibilità dei miei articoli del blog, ma ha aperto anche la strada a nuove possibilità di automazione nel campo della creazione di contenuti multilingue. È un passo avanti verso una condivisione più ampia e inclusiva delle conoscenze. ## Esperienza d’Uso e Tempo di Elaborazione

Esempi di Utilizzo

# 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é.

Tempo di Elaborazione

  • Inglese: Circa 4 minuti (248,70 secondi)
  • Spagnolo: Circa 4,7 minuti (284,05 secondi)
  • Totale accumulato: Circa 8,7 minuti (532,75 secondi) Questi tempi dimostrano l’efficacia e la rapidità dello script.

Risultati

Potete accedere ai risultati di queste generazioni di contenuti tradotti ai seguenti link:

Questo post del blog è un riassunto della mia esperienza nell’automatizzazione della traduzione con l’IA. È una prova che, quando si combina la programmazione con l’intelligenza artificiale, le possibilità sono quasi illimitate, aprendo nuovi e affascinanti orizzonti nel campo della condivisione della conoscenza e dell’accessibilità dei contenuti.

Questo documento è stato tradotto dalla versione fr alla lingua it utilizzando il modello gpt-4o. Per maggiori informazioni sul processo di traduzione, consultare https://gitlab.com/jls42/ai-powered-markdown-translator