Dans cet article, je partage un script Python développé comme un Proof of Concept (POC) pour automatiser la traduction des posts de mon blog, en utilisant le modèle de langage GPT-4 d’OpenAI. Ce script est spécifiquement conçu pour traiter des fichiers Markdown dans la structure de mon blog Hugo, facilitant la gestion multilingue de mes articles. Ils sont disponibles en Anglais, Espagnol et Chinois.
Initiation au Projet : Fusionner IA et Automatisation pour Mon Blog
Ce projet d’automatisation de la traduction de mes articles de blog a été initié par ma fascination croissante pour l’intelligence artificielle. Inspiré par mes expériences préliminaires avec les APIs OpenAI GPT-4 et Mistral AI, j’ai été attiré par l’idée de concrétiser ces technologies dans un projet pratique, offrant une valeur tangible à mon blog. Ce n’était pas seulement une quête de maîtriser les outils d’IA, mais aussi un désir de fusionner l’automatisation et l’innovation pour enrichir mon espace numérique.
Ce projet s’est transformé en une aventure où l’IA n’était pas seulement un sujet d’écriture, mais un partenaire actif dans le développement. L’idée de traduire mes articles de manière simple et efficace avec l’IA, tout en explorant ses capacités d’automatisation, ouvrait des perspectives fascinantes. Il s’agissait d’une opportunité de transcender les barrières linguistiques, rendant mon contenu accessible à un public plus large, tout en naviguant dans le domaine en constante évolution de l’intelligence artificielle.
Le Défi
Le défi principal était de créer un script capable de traduire avec précision et de conserver la mise en forme originale des articles, notamment les blocs de code, les liens et les images. Un autre défi était de s’assurer que le script puisse être facilement adapté pour prendre en charge différentes langues. Il devait aussi être capable de prendre en compte cette structure :
├── 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 Solution : Un Script Innovant
J’ai conçu un script Python qui s’appuie sur l’API OpenAI GPT-4 pour traduire le texte tout en préservant les éléments non-textuels. Grâce à une série de règles de traitement et à l’utilisation de placeholders, le script peut identifier et exclure les blocs de code et autres éléments non traduisibles, garantissant ainsi que le contenu traduit reste fidèle à l’original.
Fonctionnalités Clés
- Traduction Précise avec GPT-4 : Le script utilise le modèle GPT-4 d’OpenAI pour traduire le texte du français à l’anglais, en s’assurant de conserver la qualité et la nuance du contenu original.
- Préservation de la Mise en Forme : Les blocs de code, les URL et les chemins d’image sont identifiés et laissés intacts pendant la traduction, garantissant que la mise en forme originale est préservée.
- Flexibilité Multilingue : Le script est conçu pour être facilement adaptable à différentes langues source et cible, permettant une grande variété d’applications multilingues.
- Prise en Charge des Fichiers Markdown : Capacité de traduire des documents écrits en Markdown, en conservant leur structure et formatage spécifiques.
- Automatisation de la Traduction de Répertoires : Traduction automatique des fichiers Markdown trouvés dans un répertoire donné et de ses sous-répertoires, facilitant la gestion de gros volumes de contenu.
- Intégration de Note de Traduction : Ajoute automatiquement une note de traduction à la fin des documents traduits, indiquant le modèle GPT utilisé pour la traduction.
- Configuration et Personnalisation Faciles : Paramètres par défaut personnalisables pour la clé API, le modèle GPT, les langues source et cible, et les répertoires de fichiers, offrant une grande souplesse d’utilisation.
- Rapport de Performance : Le script fournit un retour d’information sur le temps nécessaire pour traduire chaque fichier, permettant de surveiller sa performance.
Code du script
Le code est disponible aussi ici : 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()
Zoom sur le script
Importations de modules
Tout d’abord, nous avons quelques importations de modules nécessaires, tels que os
, argparse
, time
et re
. Ces modules sont utilisés pour effectuer des opérations sur le système de fichiers, analyser les arguments de ligne de commande, mesurer le temps d’exécution et effectuer des opérations de recherche et de remplacement de texte.
Constantes
Ensuite, nous avons des constantes définies, telles que DEFAULT_API_KEY
, DEFAULT_MODEL
, DEFAULT_SOURCE_LANG
, DEFAULT_TARGET_LANG
, DEFAULT_SOURCE_DIR
et DEFAULT_TARGET_DIR
. Ces constantes représentent les valeurs par défaut utilisées dans le script, mais elles peuvent être modifiées en spécifiant des arguments de ligne de commande.
Fonction translate_with_openai
Ensuite, nous avons la fonction translate_with_openai
. Cette fonction prend un texte, un objet client OpenAI et des arguments en tant que paramètres. Elle utilise l’API OpenAI pour traduire le texte de la langue source à la langue cible. Voici comment cela fonctionne :
- La fonction utilise une expression régulière pour détecter et stocker les blocs de code dans le texte. Ces blocs de code sont délimités par des triple backticks (
). Les blocs de code sont stockés dans une liste appelée
code_blocks`. - Ensuite, la fonction remplace les blocs de code par des placeholders dans le texte. Les placeholders sont des chaînes de la forme
#CODEBLOCK{index}#
, oùindex
est l’indice du bloc de code correspondant dans la listecode_blocks
. - La fonction crée un message pour l’API OpenAI. Ce message contient deux parties : un message système qui indique à l’API de traduire le texte de la langue source à la langue cible en laissant les éléments tels que les URL, les chemins d’image et les blocs de code inchangés, et un message utilisateur qui contient le texte à traduire.
- La fonction envoie la demande de traduction à l’API en utilisant la méthode
client.chat.completions.create()
. Elle spécifie le modèle à utiliser et les messages à traduire. - La réponse de l’API contient le texte traduit. La fonction récupère le texte traduit et remplace les placeholders par les blocs de code originaux.
- Enfin, la fonction renvoie le texte traduit.
Fonction add_translation_note
Ensuite, nous avons la fonction add_translation_note
. Cette fonction ajoute une note de traduction à un document. Elle prend un objet client OpenAI et des arguments en tant que paramètres. Voici comment cela fonctionne :
- La fonction crée une note de traduction en français en utilisant la variable
translation_note_fr
. - Ensuite, la fonction utilise la fonction
translate_with_openai
pour traduire la note de traduction en utilisant l’API OpenAI. Les arguments passés àtranslate_with_openai
incluent la note de traduction en français et les autres arguments. - La fonction formate la note de traduction traduite en ajoutant des caractères de mise en forme.
- Enfin, la fonction renvoie la note de traduction formatée.
Fonction translate_markdown_file
Ensuite, nous avons la fonction translate_markdown_file
. Cette fonction prend le chemin d’un fichier Markdown d’entrée, le chemin d’un fichier de sortie, un objet client OpenAI et des arguments en tant que paramètres. Elle traduit le contenu du fichier Markdown en utilisant l’API de traduction OpenAI et écrit le contenu traduit dans le fichier de sortie.
Ce script a non seulement amélioré l’accessibilité de mes articles de blog, mais a également ouvert la voie à de nouvelles possibilités d’automatisation dans le domaine de la création de contenu multilingue. C’est un pas en avant vers un partage plus large et plus inclusif des connaissances.
Expérience d’Utilisation et Temps de Traitement
Exemples d’Usage
# 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é.
Temps de Traitement
- Anglais : Environ 4 minutes (248.70 secondes)
- Espagnol : Environ 4.7 minutes (284.05 secondes)
- Total cumulé : Environ 8.7 minutes (532.75 secondes) Ces temps démontrent l’efficacité et la rapidité du script.
Résulats
Vous pouvez dès à présent accéder aux résultats de ces générations de contenu traduit sur ces liens :
Ce post de blog est un condensé de mon expérience en automatisation de traduction avec l’IA. C’est une preuve que, quand on associe la programmation à l’intelligence artificielle, les possibilités sont presque illimitées, ouvrant des horizons nouveaux et passionnants dans le domaine du partage de connaissances et de l’accessibilité du contenu.