În acest articol, împărtășesc un script Python dezvoltat ca un Proof of Concept (POC) pentru automatizarea traducerii postărilor de pe blogul meu, folosind modelul de limbaj GPT-4 de la OpenAI. Acest script este special conceput pentru a procesa fișiere Markdown în structura blogului meu Hugo, facilitând gestionarea multilingvă a articolelor mele. Ele sunt disponibile în Engleză, Spaniolă și Chineză.
Inițierea Proiectului: Îmbinarea IA și Automatizării pentru Blogul Meu
Acest proiect de automatizare a traducerii articolelor mele de blog a fost inițiat din fascinația mea în creștere 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 era doar o căutare de a stăpâni uneltele IA, ci și o dorință de a îmbina automatizarea și inovația pentru a îmbogăți spațiul meu digital.
Acest proiect s-a transformat într-o aventură unde IA nu era doar un subiect de scris, ci un partener activ în dezvoltare. Ideea de a traduce articolele mele într-un mod simplu și eficient cu IA, explorând în același timp capacitățile sale de automatizare, deschidea perspective fascinante. Era vorba despre o oportunitate de a transcende barierele lingvistice, făcând conținutul meu accesibil unui public mai larg, navigând totodată în domeniul în continuă evoluție al inteligenței artificiale.
Provocarea
Provocarea principală era de a crea un script capabil să traducă cu precizie și să păstreze formatarea originală a articolelor, inclusiv blocurile de cod, link-urile și imaginile. O altă provocare era să se asigure că scriptul poate fi ușor adaptat pentru a suporta diferite limbi. El trebuia de asemenea să poată lua în considerare 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 păstrând în același timp elementele non-textuale. Printr-o serie de reguli de procesare și utilizarea de elemente placeholder, scriptul poate identifica și exclude blocurile de cod și alte elemente non-traductibile, asigurându-se astfel că textul 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 a nuanțelor 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 păstrarea formatei originale.
- Flexibilitate Multilingvă: Scriptul este conceput pentru a fi ușor de adaptat pentru 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 specifică.
- Automatizarea Traducerii Directoarelor: Traducerea automată a fișierelor Markdown găsite într-un director dat și în subdirectoarele acestuia, facilitând gestionarea unui volum mare de conținut.
- Adăugarea Automată a Notei de Traducere: Adaugă automat o notă de traducere la sfârșitul documentelor traduse, indicând modelul GPT utilizat pentru traducere.
- Configurare și Personalizare Ușoară: Setări implicite personalizabile pentru cheia API, modelul GPT, limbile sursă și țintă, și directoarele de fișiere, oferind o mare flexibilitate în utilizare.
- Raport de Performanță : Scriptul oferă feedback despre timpul necesar pentru a traduce fiecare fișier, permițând monitorizarea performanței acestuia.
Codul scriptului
Codul este disponibil și aici: 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()
Detalii despre script
Importarea modulelor
Mai întâi, avem câteva importuri de module necesare, cum ar fi os
, argparse
, time
și re
. Aceste module sunt utilizate pentru a efectua operațiuni pe sistemul de fișiere, analiza argumentele din linia de comandă, măsura timpul de execuție și efectua operațiuni 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 pot fi modificate specificând argumente din linia de comandă.
Funcția translate_with_openai
Apoi, avem funcția translate_with_openai
. Această funcție ia 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 folosește o expresie regulată pentru a detecta și stoca blocurile de cod în text. Aceste blocuri de cod sunt delimitate de trei backtick-uri (
). Blocurile de cod sunt stocate într-o listă numită
code_blocks`. - Apoi, funcția înlocuiește blocurile de cod cu substituenți în text. Substituenții sunt șiruri de caractere de forma
#CODEBLOCK{index}#
, undeindex
este indicele 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 elemente precum URL-urile, căile imaginilor și blocurile de cod neschimbate, și un mesaj de utilizator care conține textul de tradus.
- Funcția trimite cererea de traducere la API folosind metoda
client.chat.completions.create()
. Specifică modelul de utilizat și mesajele de tradus. - Răspunsul API-ului conține textul tradus. Funcția recuperează textul tradus și înlocuiește substituenții 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 într-un document. Ia un obiect client OpenAI și argumente ca parametri. Iată cum funcționează:
- Funcția creează o notă de traducere în franceză folosind variabila
translation_note_fr
. - Apoi, funcția folosește funcția
translate_with_openai
pentru a traduce nota de traducere utilizând API-ul OpenAI. Argumentele trecute latranslate_with_openai
includ nota de traducere în franceză și celelalte argumente. - Funcția formatează nota de traducere tradusă prin adăugarea de caractere de formatare.
- În final, funcția returnează nota de traducere formatată.
Funcția translate_markdown_file
Apoi, avem funcția translate_markdown_file
. Această funcție ia calea unui fișier Markdown de intrare, calea unui fișier de ieșire, un obiect client OpenAI și argumente ca parametri. Ea 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 deschis și calea către noi posibilități de automatizare în domeniul creării de conținut multilingv. Este un pas înainte către un schimb mai larg și mai inclusiv al cunoștințelor. ## Experiență de Utilizare și Timp 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) Aceste timpuri demonstrează eficiența și rapiditatea scriptului.
Rezultate
Puteți accesa acum rezultatele acestor generații de conținut tradus pe aceste linkuri:
Acest post de blog este un condens al experienței mele în automatizarea traducerilor cu AI. Este o dovadă că, atunci când asociem programarea cu inteligența artificială, posibilitățile sunt aproape nelimitate, deschizând orizonturi noi și incitante în domeniul împărtășirii cunoștințelor și accesibilității conținutului.
Acest document a fost tradus din versiunea fr în limba ro folosind modelul gpt-4o. Pentru mai multe informații despre procesul de traducere, consultați https://gitlab.com/jls42/ai-powered-markdown-translator