Traductions_mistralai

2024

博客翻译脚本的演进:整合 Mistral AI

在本文中,我将与您分享使用人工智能的博客翻译脚本的演进,并整合了 Mistral AI 技术。要在所有语言中查看结果,请访问此页面:使用 Mistral AI 进行翻译

为什么要这个脚本?

我的翻译脚本的目标是使我的博客文章能够在多种语言中获得,通过自动化其翻译。想象一下一个智能翻译器,能够阅读法语文章并忠实地将其还原为英语、西班牙语或其他语言,同时保留原始格式。这就是我的脚本所做的,它利用了最新的人工智能进步。

初始脚本的主要功能

  1. 自动翻译:使用 OpenAI 或 Mistral AI API 进行精确翻译。
  2. 保留格式:脚本保留了原始格式,包括代码块和链接。
  3. 多语言:能够翻译成多种语言。
  4. 支持 Markdown:适用于常用于博客中的 Markdown 文件。
  5. 自动化:通过单个命令翻译多篇文章。

整合 Mistral AI 的新功能

Mistral AI 整合

Mistral AI 是一个提供自然语言处理服务的先进人工智能平台。通过整合 Mistral AI,我可以扩大我的脚本的翻译和自动化能力,充分利用另一个强大的人工智能资源。此外,Mistral AI 是一家法国公司!

智能文本分段

脚本现在可以将长文本分段,以便更好地适应 AI 模型的令牌限制,从而更有效地管理大量文本的翻译。

添加翻译说明

新功能可以在翻译后的文档末尾添加翻译说明,告知读者翻译过程。

选择 OpenAI 和 Mistral AI

脚本现在提供了选择 OpenAI 和 Mistral AI 进行翻译的灵活性,根据用户的具体需求和首选项。

文件和目录管理

改进了文件和目录的管理,允许在必要时排除某些部分的翻译过程。

脚本代码

更新后的脚本可以在 我的 GitLab 上查找。

您还可以在此处找到它的当前版本:

#!/usr/bin/env python3

import os
import argparse
import time
from openai import OpenAI
import re
from mistralai.client import MistralClient
from mistralai.models.chat_completion import ChatMessage

EXCLUDE_PATTERNS = ["traductions_"]

# Initialisation de la configuration avec les valeurs par défaut
DEFAULT_OPENAI_API_KEY = "votre-clé-api-openai-par-défaut"
DEFAULT_MISTRAL_API_KEY = "votre-clé-api-mistral-par-défaut"
DEFAULT_MODEL_OPENAI = "gpt-4-1106-preview"
DEFAULT_MODEL_MISTRAL = "mistral-medium"
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,
}


def segment_text(text, max_length):
    """
    Divise un texte Markdown en segments ne dépassant pas la longueur maximale spécifiée,
    en essayant de conserver des points de coupure naturels.

    Args:
        text (str): Texte Markdown à diviser.
        max_length (int): Longueur maximale de chaque segment.

    Returns:
        list[str]: Liste des segments de texte Markdown.
    """
    segments = []
    while text:
        if len(text) <= max_length:
            segments.append(text)
            break
        segment = text[:max_length]
        next_index = max_length

        # Recherche de points de coupure naturels (fin de phrase, fin de paragraphe, fin de titre)
        last_good_break = max(
            segment.rfind(". "), segment.rfind("\n\n"), segment.rfind("\n#")
        )
        if last_good_break != -1:
            next_index = last_good_break + 1

        segments.append(text[:next_index])
        text = text[next_index:]

    return segments


def translate(text, client, args, use_mistral=False, is_translation_note=False):
    """
    Traduit un texte en utilisant les services de traduction d'OpenAI ou Mistral AI.
    Cette fonction segmente d'abord le texte pour s'assurer qu'il respecte la limite de tokens du modèle.
    Elle utilise un argument optionnel 'is_translation_note' pour gérer différemment les notes de traduction.

    Args:
        text (str): Texte à traduire.
        client: Client de l'API de traduction (OpenAI ou Mistral AI).
        args: Arguments contenant les informations de configuration.
        use_mistral (bool): Indique si l'API Mistral AI doit être utilisée (True) ou l'API OpenAI (False).
        is_translation_note (bool): Indique si le texte est une note de traduction, ce qui nécessite un traitement spécial.

    Returns:
        str: Texte traduit.
    """
    model_limit = MODEL_TOKEN_LIMITS.get(args.model, 4096)

    segments = segment_text(text, model_limit)
    translated_segments = []

    for segment in segments:
        try:
            prompt_message = ""
            if is_translation_note:
                prompt_message = f"Translate this exact sentence to {args.target_lang}, without any additions or explanations: '{segment}'"
            else:
                prompt_message = f"Please translate this text from {args.source_lang} to {args.target_lang}, and do not translate or change URLs, image paths, and code blocks (delimited by ```) : {segment}"

            if use_mistral:
                messages = [ChatMessage(role="user", content=prompt_message)]
                response = client.chat(model=args.model, messages=messages)
            else:
                messages = [
                    {"role": "system", "content": prompt_message},
                    {"role": "user", "content": segment},
                ]
                response = client.chat.completions.create(
                    model=args.model, messages=messages
                )
            translated_text = response.choices[0].message.content.strip()
        except Exception as e:
            raise RuntimeError(f"Erreur lors de la traduction : {e}")

        translated_segments.append(translated_text)

    return " ".join(translated_segments)


def add_translation_note(client, args, use_mistral):
    """
    Génère et traduit une note de traduction.

    Args:
        client: Objet client de traduction.
        args: Arguments contenant les informations de langue source et cible, et le modèle utilisé.
        use_mistral (bool): Indique si l'API Mistral AI doit être utilisée pour la traduction.

    Returns:
        str: Note de traduction traduite.
    """
    translation_note_src = f"Ce document a été traduit de la version {args.source_lang} par le modèle {args.model}."
    try:
        # Utiliser un prompt très spécifique pour Mistral AI
        if use_mistral:
            prompt_message = f"Translate this exact sentence to {args.target_lang}, without any additions or explanations: '{translation_note_src}'"
            messages = [ChatMessage(role="user", content=prompt_message)]
            response = client.chat(model=args.model, messages=messages)
            translated_note = response.choices[0].message.content.strip()
        else:
            # Pour OpenAI
            messages = [
                {
                    "role": "system",
                    "content": f"Translate this exact sentence to {args.target_lang}, without any additions or explanations: '{translation_note_src}'",
                },
                {"role": "user", "content": translation_note_src},
            ]
            response = client.chat.completions.create(
                model=args.model, messages=messages
            )
            translated_note = response.choices[0].essage.content.strip()

        return f"\n\n**{translated_note}**\n\n"
    except Exception as e:
        raise RuntimeError(f"Erreur lors de l'ajout de la note de traduction : {e}")


def translate_markdown_file(
    file_path, output_path, client, args, use_mistral, add_translation_note=False
):
    """
    Traduit un fichier Markdown en utilisant les modèles de traitement du langage naturel de OpenAI ou Mistral AI.

    Args:
        file_path (str): Chemin complet vers le fichier d'entrée.
        output_path (str): Chemin complet vers le fichier de sortie.
        client: Objet client de traduction.
        args: Arguments supplémentaires pour la traduction.
        use_mistral (bool): Indique si l'API Mistral AI doit être utilisée pour la traduction.
        add_translation_note (bool): Indique si une note de traduction doit être ajoutée.

    Returns:
        None
    """
    try:
        # Calcul des chemins relatifs pour un affichage plus lisible
        relative_file_path = os.path.join(
            args.source_dir, os.path.relpath(file_path, start=args.source_dir)
        )
        relative_output_path = os.path.join(
            args.target_dir, os.path.relpath(output_path, start=args.target_dir)
        )

        print(f"Traitement du fichier : {relative_file_path}")
        start_time = time.time()

        # Lecture du contenu du fichier
        with open(file_path, "r", encoding="utf-8") as f:
            content = f.read()

        # Extraction et remplacement temporaire des blocs de code pour éviter leur traduction
        code_blocks = re.findall(
            r"(^```[a-zA-Z]*\n.*?\n^```)", content, flags=re.MULTILINE | re.DOTALL
        )
        placeholders = [f"#CODEBLOCK{index}#" for index, _ in enumerate(code_blocks)]
        for placeholder, code_block in zip(placeholders, code_blocks):
            content = content.replace(code_block, placeholder)

        # Traduction du contenu
        translated_content = translate(content, client, args, use_mistral)

        # Restauration des blocs de code dans le contenu traduit
        for placeholder, code_block in zip(placeholders, code_blocks):
            translated_content = translated_content.replace(placeholder, code_block)

        # Ajout de la note de traduction si nécessaire
        if add_translation_note:
            translation_note = translate(
                "Ce document a été traduit de la version "
                + args.source_lang
                + " par le modèle "
                + args.model
                + ".",
                client,
                args,
                use_mistral,
                True,
            )
            translated_content += "\n\n**" + translation_note + "**\n\n"

        # Écriture du contenu traduit dans le fichier de sortie
        clean_output_path = os.path.normpath(output_path)
        with open(clean_output_path, "w", encoding="utf-8") as f:
            f.write(translated_content)

        end_time = time.time()
        print(
            f"Fichier '{relative_file_path}' traduit en {end_time - start_time:.2f} secondes et enregistré sous : {relative_output_path}"
        )
    except IOError as e:
        print(f"Erreur lors du traitement du fichier '{relative_file_path}': {e}")
    except Exception as e:
        print(
            f"Une erreur inattendue est survenue lors de la traduction du fichier '{relative_file_path}': {e}"
        )


def is_excluded(path):
    """
    Vérifie si le chemin donné correspond à l'un des motifs d'exclusion.

    Cette fonction parcourt la liste des motifs d'exclusion définis dans EXCLUDE_PATTERNS.
    Si l'un de ces motifs est trouvé dans le chemin fourni, la fonction renvoie True,
    indiquant que le chemin doit être exclu du processus de traduction.

    Args:
        path (str): Le chemin du fichier ou du répertoire à vérifier.

    Returns:
        bool: True si le chemin correspond à l'un des motifs d'exclusion, False sinon.
    """
    for pattern in EXCLUDE_PATTERNS:
        if pattern in path:
            return True
    return False


def translate_directory(
    input_dir, output_dir, client, args, use_mistral, add_translation_note
):
    """
    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.
        use_mistral (bool): Indique si l'API Mistral AI doit être utilisée pour la traduction.
        add_translation_note (bool): Indique si une note de traduction doit être ajoutée.

    Returns:
        None
    """
    input_dir = os.path.abspath(input_dir)
    output_dir = os.path.abspath(output_dir)

    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    output_base_dir = os.path.basename(output_dir)

    for root, dirs, files in os.walk(input_dir, topdown=True):
        if is_excluded(root) or root.startswith(output_dir):
            continue

        if (
            os.path.basename(root) == output_base_dir
            and os.path.abspath(os.path.join(root, "..")) == input_dir
        ):
            continue

        for file in files:
            if file.endswith(".md") and not is_excluded(file):
                file_path = os.path.join(root, file)
                base, _ = os.path.splitext(file)
                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,
                        use_mistral,
                        add_translation_note,
                    )
                    print(f"Fichier '{file}' traité.")


def main():
    """
    Point d'entrée principal du script de traduction de fichiers Markdown.

    Ce script traduit des fichiers Markdown d'une langue source à une langue cible en utilisant
    les services de traduction de l'API OpenAI ou Mistral AI. Il prend en charge la segmentation
    des textes longs et peut également ajouter une note de traduction en fin de document.

    Arguments du script:
    --source_dir: Répertoire contenant les fichiers Markdown à traduire.
    --target_dir: Répertoire de destination pour les fichiers traduits.
    --model: Modèle de traduction GPT à utiliser.
    --target_lang: Langue cible pour la traduction.
    --source_lang: Langue source des documents.
    --use_mistral: Indicateur pour utiliser l'API Mistral AI pour la traduction.
    --add_translation_note: Indicateur pour ajouter une note de traduction au contenu traduit.
    """
    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, help="Modèle GPT à utiliser pour la traduction"
    )
    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",
    )
    parser.add_argument(
        "--use_mistral",
        action="store_true",
        help="Utiliser l'API Mistral AI pour la traduction",
    )
    parser.add_argument(
        "--add_translation_note",
        action="store_true",
        help="Ajouter une note de traduction au contenu traduit",
    )

    args = parser.parse_args()

    if not os.path.isdir(args.source_dir):
        raise ValueError(
            f"Le répertoire source spécifié n'existe pas : {args.source_dir}"
        )
    if not os.path.exists(args.target_dir):
        os.makedirs(args.target_dir)

    if args.use_mistral:
        args.model = args.model if args.model else DEFAULT_MODEL_MISTRAL
        api_key = os.getenv("MISTRAL_API_KEY", DEFAULT_MISTRAL_API_KEY)
        if not api_key:
            raise ValueError("Clé API Mistral non spécifiée.")
        client = MistralClient(api_key=api_key)
    else:
        args.model = args.model if args.model else DEFAULT_MODEL_OPENAI
        openai_api_key = os.getenv("OPENAI_API_KEY", DEFAULT_OPENAI_API_KEY)
        if not openai_api_key:
            raise ValueError("Clé API OpenAI non spécifiée.")
        client = OpenAI(api_key=openai_api_key)

    translate_directory(
        args.source_dir,
        args.target_dir,
        client,
        args,
        args.use_mistral,
        args.add_translation_note,
    )

    if args.use_mistral:
        try:
            del client
        except TypeError:
            pass


if __name__ == "__main__":
    main()

请继续关注更多关于人工智能有趣世界的更新和创新!

Lire la suite →

Evolution of my Blog Translation Script: Integration of Mistral AI

In this article, I will talk to you about the evolution of my blog translation script using artificial intelligence, with the integration of Mistral AI technology. To discover the results in all languages, I invite you to visit this page: Translations with Mistral AI.

Why this Script?

The goal of my translation script is to make my blog articles accessible in several languages, by automating their translation. Imagine an intelligent translator capable of reading an article in French and restoring it faithfully in English, Spanish or other languages, while preserving the original format. That’s what my script does, by leveraging the latest advances in AI.

Lire la suite →

Evolución de mi Script de Traducción de Blog: Integración de Mistral AI

En este artículo, te hablaré sobre la evolución de mi script de traducción de blog utilizando la inteligencia artificial, con la integración de la tecnología Mistral AI. Para descubrir los resultados en todos los idiomas, te invito a visitar esta página: Traducciones con Mistral AI.

Por qué este Script?

El objetivo de mi script de traducción es hacer que mis artículos de blog sean accesibles en varios idiomas, automatizando su traducción. Imagina un traductor inteligente capaz de leer un artículo en francés y devolverlo fielmente en inglés, español u otros idiomas, manteniendo el formato original. Eso es lo que hace mi script, aprovechando los últimos avances de la IA.

Lire la suite →

用IA革新博客文章翻译

在这篇文章中,我分享了一个作为概念证明(POC)开发的Python脚本,用于自动化翻译我的博客文章,使用OpenAI的GPT-4语言模型。这个脚本专门设计用于处理Hugo博客的Markdown文件结构,便于管理多语言文章。它们可以在英文西班牙文中文中获得。

Lire la suite →

Revolutionizing Blog Post Translations with AI

In this article, I share a Python script developed as a Proof of Concept (POC) to automate the translation of my blog posts using OpenAI’s GPT-4 language model. This script is specifically designed to handle Markdown files in the structure of my Hugo blog, making it easy to manage multilingual articles. They are available in English, Spanish, and Chinese.

Lire la suite →

Revolucionar las Traducciones de Entradas de Blog con IA

En este artículo, comparto un script de Python desarrollado como una Prueba de Concepto (POC) para automatizar la traducción de las entradas de mi blog, utilizando el modelo de lenguaje GPT-4 de OpenAI. Este script está específicamente diseñado para procesar archivos Markdown en la estructura de mi blog Hugo, facilitando la gestión multilingüe de mis entradas. Están disponibles en Inglés, Español y Chino.

Lire la suite →

此博客有了新主题

博客以新的风格改变!

Lire la suite →

Un nuevo tema para este blog

El blog se transforma con estilo !

Lire la suite →

A new theme for this blog

The blog is transforming with style!

Lire la suite →

Stable Diffusion 的发现

在这篇文章中,我想与你分享一下我在“Stable Diffusion”方面的项目。

Lire la suite →

Discovery of Stable Diffusion

In this post, I would like to share with you my project on the discovery of “Stable Diffusion”.

Lire la suite →

Descubrimiento de Stable Diffusion

En este post, quiero compartir con ustedes mi proyecto sobre el descubrimiento de “Stable Diffusion”.

Lire la suite →

使用 Mistral AI API 的另一种 Python 实践方法

在 OpenAI 之后,对 Mistral AI 进行了 POC!

Lire la suite →

Otra aproximación práctica en Python pero con la API de Mistral AI

Después de OpenAI, POC en Mistral AI, el competidor francés!

Lire la suite →

Another Practical Approach in Python but with the Mistral AI API

After OpenAI, POC on Mistral AI the French competitor!

Lire la suite →

使用Python和OpenAI API的实践方法

本文介绍了一个脚本,该脚本已开发为一个概念验证(POC),用于探索和熟悉OpenAI API的能力。

Lire la suite →

Un enfoque práctico con Python y la API de OpenAI

Este artículo presenta un script que se desarrolló como una prueba de concepto (POC) para explorar y familiarizarse con las capacidades de la API OpenAI.

Lire la suite →

A Practical Approach with Python and OpenAI API

This article presents a script that was developed as a Proof of Concept (POC) to explore and familiarize with the capabilities of the OpenAI API.

Lire la suite →

2018

Serverless Infrastructure of the jls42.org blog

This article presents the general infrastructure of the jls42.org blog.

Lire la suite →

jls42.org博客的Serverless基础设施

本文介绍了jls42.org博客的总体基础设施。

Lire la suite →

Infraestructura Serverless del blog jls42.org

Este artículo presenta la infraestructura general del blog jls42.org.

Lire la suite →

使用Ansible在Raspberry Pi上自动安装Kubernetes 1.13

本文介绍如何使用Ansible和自制角色自动在Raspberry Pi上安装Kubernetes 1.13。

Lire la suite →

Instalación automática de Kubernetes 1.13 en Raspberry Pi con Ansible

Este artículo propone la automatización de la instalación de Kubernetes 1.13 en Raspberry Pi mediante Ansible con un rol hecho en casa.

Lire la suite →

Automatic installation of Kubernetes 1.13 on Raspberry Pi with Ansible

This article aims to automate the installation of Kubernetes 1.13 on Raspberry Pi using Ansible with a homemade role.

Lire la suite →

在 Raspberry Pi 上使用 Ansible 自动安装 Docker

本文提出了使用 Ansible 自动安装 Raspberry Pi 上的 Docker,并使用自制角色

Lire la suite →

Instalación automática con Ansible de Docker en Raspberry Pi

Este artículo propone automatizar la instalación de docker en Raspberry Pi mediante Ansible con un rol hecho en casa.

Lire la suite →

Automatic Installation of Docker on Raspberry Pi using Ansible

This article proposes to automate the installation of Docker on Raspberry Pi via Ansible using a homemade role.

Lire la suite →

在 Raspberry Pi 上自动初始化和保护 Raspbian

本文提供了脚本,用于自动化:

Lire la suite →

Inicialización y seguridad automatizadas de Raspbian en Raspberry Pi

Este artículo propone scripts para automatizar:

Lire la suite →

Automated Initialization and Security of Raspbian on Raspberry Pi

This article proposes scripts to automate:

Lire la suite →

法律声明

该博客是2004年6月21日法律2004-575号第6条第III项中非职业性质的在线公共信息传播服务。根据该条文的规定,该网站的编辑者选择保持"匿名"。

如果您对本站内容、评论或文章有任何投诉,请发送电子邮件至 contact@jls42.org

法律允许您直接联系托管商:Amazon Web Services

(注:此处未翻译URL和邮件地址)

**这份文件已由模型 Mistral-medium 从法语版本翻译而来。

Note: This is a direct translation of the sentence without any additional context or explanations. It says “This document has been translated from the French version by the Mistral-medium model.”**

Lire la suite →

关于此博客

此法语博客涉及智能化、自动化和容器等主题。

此处使用了各种环境,如树莓派或亚马逊网络服务(AWS)。

没有夸张,这里提供了各种技术问题的自动化解决方案。

发布频率由我的剩余时间决定。

基础设施

以下是如何创建和更新此博客:

alt text

有关更多信息,请参阅此专用页面

引擎和许可

此博客使用Hugopoison主题创建。

除非另有说明,此博客文章采用创意共享署名-相同方式共享 4.0 国际许可。 alt text.

**这份文档已由模型 “Mistral-medium” 从法语版翻译。

Note: Please note that the original sentence is in French and states that the document has been translated from the French version by the Mistral-medium model. The Chinese translation provided here is a direct translation of that sentence.**

Lire la suite →

Menciones legales

Este blog es un servicio de comunicación al público en línea editado con fines no profesionales de acuerdo con el artículo 6, III, 2° de la ley 2004-575 del 21 de junio de 2004. De acuerdo con las disposiciones de este artículo, el editor ha decidido permanecer “anónimo”.

En caso de reclamación sobre el contenido de este sitio, comentario o artículo, gracias por dirigir un correo electrónico a contact@jls42.org.

La ley le permite dirigirse directamente al proveedor de alojamiento: Amazon Web Services

Lire la suite →

Legal Notices

This blog is an online public communication service edited on a non-professional basis in accordance with Article 6, III, 2° of the law 2004-575 of June 21, 2004. In accordance with the provisions of this article, the editor has chosen to remain “anonymous”.

In case of claim regarding the content of this site, comment or post, please send an electronic letter to contact@jls42.org.

The law allows you to contact the host directly: Amazon Web Services

Lire la suite →

Acerca de este blog

Este blog en francés trata temas como la inteligencia artificial, la automatización y los contenedores.

Esto en diferentes entornos utilizando Raspberry Pi o Amazon Web Services (AWS).

Sin pretensiones, se encuentran propuestas de soluciones automatizadas a diversos problemas técnicos.

La frecuencia de publicación varía según mi tiempo libre disponible.

Infraestructura

Este es el proceso de creación y actualización de este blog:

alt text

Más información a través de esta página dedicada

Lire la suite →

About this blog

This French blog covers topics such as artificial intelligence, automation, and containers.

This is done in various environments using Raspberry Pi or Amazon Web Services (AWS), among others.

Without pretension, it offers automated solutions to various technical issues.

The publication frequency varies depending on my available free time.

Infrastructure

Here’s how this blog is created and updated:

alt text

More information on this dedicated page

Engine and license

This blog is made using Hugo with the poison theme.

Lire la suite →