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 è progettato specificamente per elaborare file Markdown, facilitando la gestione multilingue dei miei articoli. Le traduzioni sono disponibili tramite il selettore di lingua in alto alla pagina.
Avvio del progetto: unire IA e automazione per il mio blog
Questo progetto di automazione della traduzione dei miei articoli del blog è nato 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 si trattava solo di imparare a usare gli strumenti di IA, ma anche del desiderio di coniugare automazione e innovazione per arricchire il mio spazio digitale.
Il 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, esplorandone al contempo le capacità di automazione, apriva prospettive affascinanti. Era un’opportunità per superare le barriere linguistiche, rendendo i miei contenuti accessibili a un pubblico più ampio, pur muovendosi nel campo in continua evoluzione dell’intelligenza artificiale.
La sfida
La sfida principale era creare uno script in grado di tradurre con precisione e di mantenere la formattazione originale degli articoli, in particolare blocchi di codice, link e immagini. Un’altra sfida era assicurarsi che lo script potesse essere facilmente adattato per supportare lingue diverse. Doveva anche essere in grado di prendere in considerazione 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.mdLa soluzione: uno script innovativo
Ho progettato uno script Python che si appoggia all’API OpenAI GPT-4 per tradurre il testo mantenendo gli elementi non testuali. Grazie a una serie di regole di elaborazione e all’uso di segnaposto, lo script può identificare ed escludere i blocchi di codice e altri elementi non traducibili, garantendo così che il contenuto tradotto rimanga fedele all’originale.
Funzionalità principali
- 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 le sfumature del contenuto originale.
- Preservazione della formattazione : I blocchi di codice, le URL e i percorsi delle immagini vengono identificati e lasciati intatti durante la traduzione, garantendo che la formattazione originale sia preservata.
- Flessibilità multilingue : Lo script è progettato per essere facilmente adattabile a diverse lingue sorgente e di destinazione, permettendo una vasta gamma di applicazioni multilingue.
- Supporto per file Markdown : Capacità di tradurre documenti scritti in Markdown, mantenendone la struttura e il formato specifici.
- Automazione della traduzione di directory : Traduzione automatica dei file Markdown trovati in una directory e nelle sue sottodirectory, facilitando la gestione di grandi volumi di contenuto.
- Integrazione di nota di traduzione : Aggiunge automaticamente una nota di traduzione alla fine dei documenti tradotti, indicando il modello GPT utilizzato per la traduzione.
- Configurazione e personalizzazione facili : Parametri predefiniti personalizzabili per la chiave API, il modello GPT, le lingue sorgente e di destinazione e le directory dei file, offrendo grande flessibilità d’uso.
- Rapporto di performance : Lo script fornisce un feedback sui tempi necessari per tradurre ogni file, permettendo di monitorarne le prestazioni.
Codice dello script
Il codice è disponibile anche qui : Traduttore Markdown potenziato dall’IA
#!/usr/bin/env python3
import osimport argparseimport timefrom openai import OpenAIimport re
# Initialisation de la configuration avec les valeurs par défautDEFAULT_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 traductiondef 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 Markdowndef 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()Approfondimento sullo script
Importazioni dei moduli
Innanzitutto, abbiamo alcune importazioni di moduli necessarie, come os, argparse, time e re. Questi moduli sono utilizzati per eseguire operazioni sul file system, analizzare gli argomenti da linea di comando, misurare i tempi di esecuzione ed effettuare operazioni di ricerca e sostituzione del 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 usati nello script, ma possono essere modificati specificando argomenti da linea di comando.
Funzione translate_with_openai
Poi, abbiamo la funzione translate_with_openai. Questa funzione prende un testo, un oggetto client OpenAI e degli argomenti come parametri. Usa l’API OpenAI per tradurre il testo dalla lingua sorgente alla lingua di destinazione. Ecco come funziona :
- 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 (
). Les blocs de code sont stockés dans une liste appeléecode_blocks`. - Successivamente, la funzione sostituisce i blocchi di codice con dei segnaposto nel testo. I segnaposto sono stringhe della forma
#CODEBLOCK{index}#, doveindexè l’indice del blocco di codice corrispondente nella listacode_blocks. - 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 sorgente alla lingua di destinazione lasciando inalterati elementi come URL, percorsi delle immagini e blocchi di codice, e un messaggio utente che contiene il testo da tradurre.
- La funzione invia la richiesta di traduzione all’API usando il metodo
client.chat.completions.create(). Specifica il modello da utilizzare e i messaggi da tradurre. - La risposta dell’API contiene il testo tradotto. La funzione recupera il testo tradotto e sostituisce i segnaposto con i blocchi di codice originali.
- Infine, la funzione restituisce il testo tradotto.
Funzione add_translation_note
Poi, 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 :
- La funzione crea una nota di traduzione in francese usando la variabile
translation_note_fr. - Successivamente, la funzione utilizza la funzione
translate_with_openaiper tradurre la nota di traduzione con l’API OpenAI. Gli argomenti passati atranslate_with_openaiincludono la nota in francese e gli altri argomenti. - La funzione formatta la nota di traduzione tradotta aggiungendo dei caratteri di formattazione.
- Infine, la funzione restituisce la nota di traduzione formattata.
Funzione translate_markdown_file
Poi, 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 usando 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 anche aperto 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 tempi di elaborazione
Esempi d’uso
# Création des répertoires ciblesjls42@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_enTraitement du fichier : content/posts/ia/stable-difusion-aws-ec2.mdTraduction terminée en 21.57 secondes.Fichier 'stable-difusion-aws-ec2.md' traité.Traitement du fichier : content/posts/ia/poc-openai-api-gpt4.mdTraduction terminée en 34.87 secondes.Fichier 'poc-openai-api-gpt4.md' traité.Traitement du fichier : content/posts/ia/poc-mistral-ai-mixtral.mdTraduction 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.mdTraduction 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.mdTraduction 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.mdTraduction 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.mdTraduction 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.mdTraduction terminée en 12.64 secondes.Fichier 'infrastruture-as-code-serverless-ha-jls42-org.md' traité.Traitement du fichier : content/mentions/mentions-legales.mdTraduction terminée en 11.90 secondes.Fichier 'mentions-legales.md' traité.Traitement du fichier : content/about/a-propos-du-blog-jls42.mdTraduction 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 esTraitement du fichier : content/posts/ia/stable-difusion-aws-ec2.mdTraduction terminée en 33.19 secondes.Fichier 'stable-difusion-aws-ec2.md' traité.Traitement du fichier : content/posts/ia/poc-openai-api-gpt4.mdTraduction terminée en 25.24 secondes.Fichier 'poc-openai-api-gpt4.md' traité.Traitement du fichier : content/posts/ia/poc-mistral-ai-mixtral.mdTraduction 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.mdTraduction 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.mdTraduction 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.mdTraduction 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.mdTraduction 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.mdTraduction terminée en 30.73 secondes.Fichier 'infrastruture-as-code-serverless-ha-jls42-org.md' traité.Traitement du fichier : content/mentions/mentions-legales.mdTraduction terminée en 13.14 secondes.Fichier 'mentions-legales.md' traité.Traitement du fichier : content/about/a-propos-du-blog-jls42.mdTraduction terminée en 11.24 secondes.Fichier 'a-propos-du-blog-jls42.md' traité.Tempi di elaborazione
- Inglese : Circa 4 minuti (248.70 secondi)
- Spagnolo : Circa 4,7 minuti (284.05 secondi)
- Totale cumulato : Circa 8,7 minuti (532.75 secondi) Questi tempi dimostrano l’efficienza e la rapidità dello script.
Risultati
Nota : Questo esempio illustra il funzionamento dello script sulla vecchia struttura Hugo del blog. Il blog è stato successivamente migrato a Astro con una nuova architettura multilingue. Le traduzioni sono ora accessibili tramite il selettore di lingua integrato.
Questo post del blog è un condensato della mia esperienza nell’automazione della traduzione con l’IA. È la prova che, quando si combina la programmazione con l’intelligenza artificiale, le possibilità sono quasi illimitate, aprendo nuovi e appassionanti orizzonti nel campo della condivisione delle conoscenze e dell’accessibilità dei contenuti.
Questo documento è stato tradotto dalla versione fr alla lingua it utilizzando il modello gpt-5-mini. Per maggiori informazioni sul processo di traduzione, consultare https://gitlab.com/jls42/ai-powered-markdown-translator