În acest articol, împărtășesc un script Python dezvoltat ca un Proof of Concept (POC) pentru a automatiza traducerea postărilor de pe blogul meu, folosind modelul de limbaj GPT-4 de la OpenAI. Acest script este conceput special pentru a procesa fișiere Markdown, facilitând gestionarea multilingvă a articolelor mele. Traducerile sunt disponibile prin selectorul de limbă din partea de sus a paginii.
Inițierea proiectului: Îmbinarea IA și automatizării pentru blogul meu
Acest proiect de automatizare a traducerii articolelor mele de blog a fost declanșat de fascinația mea tot mai mare pentru inteligența artificială. Inspirat de experiențele mele preliminare cu API-urile OpenAI GPT-4 și Mistral AI, am fost atras de ideea de a concretiza aceste tehnologii într-un proiect practic, oferind o valoare tangibilă blogului meu. Nu a fost doar o căutare pentru a stăpâni instrumentele AI, ci și o dorință de a îmbina automatizarea și inovația pentru a îmbogăți spațiul meu digital.
Proiectul s-a transformat într-o aventură în care AI-ul nu era doar un subiect de scris, ci un partener activ în dezvoltare. Ideea de a traduce articolele într-un mod simplu și eficient cu ajutorul AI-ului, explorând totodată capabilitățile sale de automatizare, deschidea perspective fascinante. A fost o oportunitate de a transcende barierele lingvistice, făcând conținutul meu accesibil unui public mai larg, în timp ce navigam domeniul în continuă evoluție al inteligenței artificiale.
Provocarea
Provocarea principală a fost să creez un script capabil să traducă cu precizie și să păstreze formatul original al articolelor, în special blocurile de cod, linkurile și imaginile. O altă provocare a fost să mă asigur că scriptul poate fi ușor adaptat pentru a suporta diferite limbi. De asemenea, trebuia să poată ține cont de această structură :
├── 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
Soluția: Un script inovator
Am conceput un script Python care se bazează pe API-ul OpenAI GPT-4 pentru a traduce textul în timp ce păstrează elementele non-textuale. Datorită unei serii de reguli de procesare și utilizării de placeholders, scriptul poate identifica și exclude blocurile de cod și alte elemente netraductibile, garantând astfel că conținutul tradus rămâne fidel originalului.
Funcționalități cheie
- Traducere precisă cu GPT-4 : Scriptul folosește modelul GPT-4 de la OpenAI pentru a traduce textul din franceză în engleză, asigurând păstrarea calității și nuanței conținutului original.
- Păstrarea formatării : Blocurile de cod, URL-urile și căile imaginilor sunt identificate și lăsate intacte în timpul traducerii, garantând că formatul original este păstrat.
- Flexibilitate multilingvă : Scriptul este proiectat pentru a fi ușor adaptabil la diferite limbi sursă și țintă, permițând o mare varietate de aplicații multilingve.
- Suport pentru fișiere Markdown : Capacitatea de a traduce documente scrise în Markdown, păstrând structura și formatarea specifice.
- Automatizarea traducerii directoarelor : Traducerea automată a fișierelor Markdown găsite într-un director dat și în subdirectoarele sale, facilitând gestionarea unui volum mare de conținut.
- Adăugarea unei note de traducere : Adaugă automat o notă de traducere la sfârșitul documentelor traduse, indicând modelul GPT folosit pentru traducere.
- Configurare și personalizare ușoare : Setări implicite personalizabile pentru cheia API, modelul GPT, limbile sursă și țintă și directoarele de fișiere, oferind o mare flexibilitate de utilizare.
- Raport de performanță : Scriptul oferă feedback asupra timpului necesar pentru a traduce fiecare fișier, permițând monitorizarea performanței.
Codul scriptului
Codul este disponibil și aici : Traducător Markdown alimentat de IA
#!/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()
Privire asupra scriptului
Importuri de module
În primul rând, avem câteva importuri de module necesare, cum ar fi os, argparse, time și re. Aceste module sunt folosite pentru a efectua operații asupra sistemului de fișiere, pentru a analiza argumentele din linia de comandă, pentru a măsura timpul de execuție și pentru a efectua operații de căutare și înlocuire a textului.
Constante
Apoi, avem constante definite, cum ar fi DEFAULT_API_KEY, DEFAULT_MODEL, DEFAULT_SOURCE_LANG, DEFAULT_TARGET_LANG, DEFAULT_SOURCE_DIR și DEFAULT_TARGET_DIR. Aceste constante reprezintă valorile implicite utilizate în script, dar ele pot fi modificate prin specificarea argumentelor în linia de comandă.
Funcția translate_with_openai
Următorul este funcția translate_with_openai. Această funcție primește un text, un obiect client OpenAI și argumente ca parametri. Folosește API-ul OpenAI pentru a traduce textul din limba sursă în limba țintă. Iată cum funcționează:
- Funcția utilizează o expresie regulată pentru a detecta și stoca blocurile de cod din text. Aceste blocuri de cod sunt delimitate de triple backticks (
). Les blocs de code sont stockés dans une liste appeléecode_blocks`. - Apoi, funcția înlocuiește blocurile de cod cu placeholders în text. Placeholders sunt șiruri de forma
#CODEBLOCK{index}#, undeindexeste indexul blocului de cod corespunzător din listacode_blocks. - Funcția creează un mesaj pentru API-ul OpenAI. Acest mesaj conține două părți: un mesaj de sistem care indică API-ului să traducă textul din limba sursă în limba țintă lăsând elementele precum URL-urile, căile imaginilor și blocurile de cod neschimbate, și un mesaj utilizator care conține textul de tradus.
- Funcția trimite cererea de traducere către API folosind metoda
client.chat.completions.create(). Specifică modelul de utilizat și mesajele de tradus. - Răspunsul API conține textul tradus. Funcția preia textul tradus și înlocuiește placeholders cu blocurile de cod originale.
- În final, funcția returnează textul tradus.
Funcția add_translation_note
Apoi, avem funcția add_translation_note. Această funcție adaugă o notă de traducere unui document. Primește un obiect client OpenAI și argumente ca parametri. Iată cum funcționează:
- Funcția creează o notă de traducere în limba franceză folosind variabila
translation_note_fr. - Apoi, funcția folosește funcția
translate_with_openaipentru a traduce nota de traducere utilizând API-ul OpenAI. Argumentele transmise latranslate_with_openaiinclud nota de traducere în franceză și celelalte argumente. - Funcția formatează nota de traducere tradusă adăugând caractere de formatare.
- În final, funcția returnează nota de traducere formatată.
Funcția translate_markdown_file
Următoarea este funcția translate_markdown_file. Această funcție primește calea unui fișier Markdown de intrare, calea unui fișier de ieșire, un obiect client OpenAI și argumente ca parametri. Traduce conținutul fișierului Markdown folosind API-ul de traducere OpenAI și scrie conținutul tradus în fișierul de ieșire.
Acest script nu doar că a îmbunătățit accesibilitatea articolelor mele de blog, dar a și deschis calea către noi posibilități de automatizare în domeniul creării de conținut multilingv. Este un pas înainte către o răspândire mai largă și mai incluzivă a cunoștințelor.
Experiența de utilizare și timpii de procesare
Exemple de utilizare
# 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é.
Timp de procesare
- Engleză : Aproximativ 4 minute (248.70 secunde)
- Spaniolă : Aproximativ 4,7 minute (284.05 secunde)
- Total cumulat : Aproximativ 8,7 minute (532.75 secunde) Acești timpi demonstrează eficiența și rapiditatea scriptului.
Rezultate
Notă : Acest exemplu ilustrează funcționarea scriptului pe vechea structură Hugo a blogului. Blogul a fost între timp migrat către Astro cu o nouă arhitectură multilingvă. Traducerile sunt acum accesibile prin selectorul de limbă integrat.
Această postare pe blog este un condens al experienței mele în automatizarea traducerii cu IA. Este o dovadă că, atunci când combini programarea cu inteligența artificială, posibilitățile sunt aproape nelimitate, deschizând orizonturi noi și captivante în domeniul distribuirii cunoștințelor și accesibilității conținutului.
Acest document a fost tradus din versiunea fr în limba ro folosind modelul gpt-5-mini. Pentru mai multe informații despre procesul de traducere, consultați https://gitlab.com/jls42/ai-powered-markdown-translator