In dit artikel deel ik een Python-script dat is ontwikkeld als een Proof of Concept (POC) om de vertaling van de posts op mijn blog te automatiseren met behulp van het taalmodel GPT-4 van OpenAI. Dit script is specifiek ontworpen om Markdown-bestanden te verwerken, waardoor het beheer van meertalige artikelen eenvoudiger wordt. De vertalingen zijn beschikbaar via de taalselector bovenaan de pagina.
Projectintroductie : IA en Automatisering voor Mijn Blog
Dit project voor het automatiseren van de vertaling van mijn blogartikelen is voortgekomen uit mijn groeiende fascinatie voor kunstmatige intelligentie. Geïnspireerd door mijn vroege ervaringen met de OpenAI GPT-4- en Mistral AI-API’s, wilde ik deze technologieën in een praktisch project concretiseren dat echte waarde biedt voor mijn blog. Het ging niet alleen om het onder de knie krijgen van AI-tools, maar ook om automatisering en innovatie te combineren om mijn digitale ruimte te verrijken.
Het project werd een avontuur waarbij AI niet alleen een schrijfontje was, maar een actieve partner in de ontwikkeling. Het idee om mijn artikelen eenvoudig en efficiënt te vertalen met AI, terwijl ik zijn automatiseringsmogelijkheden onderzocht, opende fascinerende perspectieven. Het was een kans om taalbarrières te overstijgen en mijn inhoud toegankelijk te maken voor een breder publiek, terwijl ik navigeerde door het voortdurend veranderende domein van kunstmatige intelligentie.
De Uitdaging
De hoofduitdaging was het creëren van een script dat nauwkeurig kan vertalen en tegelijkertijd de oorspronkelijke opmaak van de artikelen behoudt, met name codeblokken, links en afbeeldingen. Een andere uitdaging was ervoor te zorgen dat het script eenvoudig aanpasbaar is om verschillende talen te ondersteunen. Het moest ook rekening kunnen houden met deze structuur :
├── 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
De Oplossing : Een Innovatief Script
Ik heb een Python-script ontworpen dat gebruikmaakt van de OpenAI GPT-4 API om tekst te vertalen en niet-tekstuele elementen te behouden. Door een reeks verwerkingsregels en het gebruik van placeholders kan het script codeblokken en andere niet-vertalende elementen identificeren en uitsluiten, waardoor de vertaalde inhoud trouw blijft aan het origineel.
Belangrijkste Functies
- Nauwkeurige vertaling met GPT-4 : Het script gebruikt het GPT-4-model van OpenAI om tekst van Frans naar Engels te vertalen, waarbij de kwaliteit en nuance van de originele inhoud behouden blijven.
- Behoud van opmaak : Codeblokken, URL’s en afbeeldingspaden worden geïdentificeerd en onaangeroerd gelaten tijdens de vertaling, zodat de oorspronkelijke opmaak behouden blijft.
- Multiculturele flexibiliteit : Het script is ontworpen om eenvoudig aan te passen aan verschillende bron- en doeltalen, waardoor het geschikt is voor diverse meertalige toepassingen.
- Ondersteuning voor Markdown-bestanden : Mogelijkheid om documenten geschreven in Markdown te vertalen, waarbij hun structuur en opmaak behouden blijven.
- Automatisering van vertaling in mappen : Automatische vertaling van Markdown-bestanden die in een opgegeven map en de submappen worden gevonden, wat het beheer van grote hoeveelheden inhoud vergemakkelijkt.
- Invoegen van vertaalkop : Voegt automatisch een vertaalkop toe aan het einde van vertaalde documenten, waarin het gebruikte GPT-model voor de vertaling wordt vermeld.
- Eenvoudige configuratie en personalisatie : Standaardinstellingen die aanpasbaar zijn voor de API-sleutel, het GPT-model, bron- en doeltaal, en bestandsmappen, wat veel flexibiliteit biedt.
- Prestatieoverzicht : Het script geeft feedback over de tijd die nodig is om elk bestand te vertalen, zodat je de prestaties kunt monitoren.
Code van het script
De code is ook hier beschikbaar : AI-gestuurde Markdown-vertaler
#!/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()
Diepgaande blik op het script
Geïmporteerde modules
Allereerst importeren we enkele benodigde modules, zoals os, argparse, time en re. Deze modules worden gebruikt voor bestandsstysteemoperaties, het parsen van commandoregelargumenten, het meten van uitvoeringstijd en voor zoek- en vervangoperaties in tekst.
Constanten
Vervolgens hebben we een aantal gedefinieerde constanten, zoals DEFAULT_API_KEY, DEFAULT_MODEL, DEFAULT_SOURCE_LANG, DEFAULT_TARGET_LANG, DEFAULT_SOURCE_DIR en DEFAULT_TARGET_DIR. Deze constanten vertegenwoordigen de standaardwaarden die in het script worden gebruikt, maar ze kunnen worden gewijzigd door commandoregelargumenten mee te geven.
Functie translate_with_openai
Daarna bespreken we de functie translate_with_openai. Deze functie neemt een tekst, een OpenAI-clientobject en argumenten als parameters. Ze gebruikt de OpenAI-API om de tekst van de brontaal naar de doeltaal te vertalen. Zo werkt het:
- De functie gebruikt een reguliere expressie om codeblokken in de tekst te detecteren en op te slaan. Deze codeblokken worden afgebakend door triple backticks (
). Les blocs de code sont stockés dans une liste appeléecode_blocks`. - Vervolgens vervangt de functie de codeblokken door placeholders in de tekst. De placeholders zijn strings van de vorm
#CODEBLOCK{index}#, waarbijindexde index is van het betreffende codeblok in de lijstcode_blocks. - De functie maakt een bericht voor de OpenAI-API. Dit bericht bevat twee delen: een systeembericht dat de API instrueert om de tekst van de brontaal naar de doeltaal te vertalen en elementen zoals URL’s, afbeeldingspaden en codeblokken onaangeroerd te laten, en een gebruikersbericht dat de te vertalen tekst bevat.
- De functie stuurt de vertaalverzoek naar de API met behulp van de methode
client.chat.completions.create(). Ze specificeert het model en de berichten. - De API-respons bevat de vertaalde tekst. De functie haalt deze tekst op en vervangt de placeholders door de originele codeblokken.
- Tot slot geeft de functie de vertaalde tekst terug.
Functie add_translation_note
Vervolgens hebben we de functie add_translation_note. Deze functie voegt een vertaalkop toe aan een document. Ze neemt een OpenAI-client en argumenten als parameters. Zo werkt het:
- De functie maakt een vertaalkop in het Frans met behulp van de variabele
translation_note_fr. - Daarna gebruikt de functie
translate_with_openaiom de vertaalkop te vertalen via de OpenAI-API. De argumenten die aantranslate_with_openaiworden doorgegeven omvatten de Franse vertaalkop en andere parameters. - De functie formatteert de vertaalde vertaalkop door opmaaktekens toe te voegen.
- Ten slotte retourneert de functie de geformatteerde vertaalkop.
Functie translate_markdown_file
Daarna bespreken we de functie translate_markdown_file. Deze functie neemt het pad van een invoer-Markdownbestand, het pad van een uitvoerbestand, een OpenAI-client en argumenten als parameters. Ze vertaalt de inhoud van het Markdown-bestand met behulp van de OpenAI-vertalings-API en schrijft de vertaalde inhoud naar het uitvoerbestand.
Dit script heeft niet alleen de toegankelijkheid van mijn blogartikelen verbeterd, maar heeft ook de deur geopend naar nieuwe mogelijkheden voor automatisering op het gebied van meertalige contentcreatie. Het is een stap in de richting van bredere en inclusievere kennisdeling.
Gebruikerservaring en verwerkingstijd
Gebruiksvoorbeelden
# 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é.
Verwerkingstijd
- Engels : Ongeveer 4 minuten (248.70 seconden)
- Spaans : Ongeveer 4.7 minuten (284.05 seconden)
- Totaal opgeteld : Ongeveer 8.7 minuten (532.75 seconden) Deze tijden tonen de efficiëntie en snelheid van het script aan.
Resultaten
Opmerking : Dit voorbeeld illustreert hoe het script werkte op de oude Hugo-structuur van de blog. De blog is sindsdien gemigreerd naar Astro met een nieuwe meertalige architectuur. De vertalingen zijn nu toegankelijk via de ingebouwde taalselector.
Deze blogpost is een samenvatting van mijn ervaring met het automatiseren van vertalingen met AI. Het bewijst dat wanneer je programmeren combineert met kunstmatige intelligentie, de mogelijkheden bijna eindeloos zijn, en dat het nieuwe en opwindende wegen opent voor kennisdeling en toegankelijke content.
Dit document is vertaald van de Franse versie naar het Nederlands met behulp van het model gpt-5-mini. Voor meer informatie over het vertaalproces, raadpleeg https://gitlab.com/jls42/ai-powered-markdown-translator