|
|
@@ -3,23 +3,26 @@ import requests
|
|
|
|
import json
|
|
|
|
import json
|
|
|
|
from reportlab.lib.pagesizes import letter
|
|
|
|
from reportlab.lib.pagesizes import letter
|
|
|
|
from reportlab.lib.units import inch
|
|
|
|
from reportlab.lib.units import inch
|
|
|
|
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
|
|
|
|
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Flowable
|
|
|
|
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
|
|
|
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
|
|
|
from reportlab.lib.enums import TA_JUSTIFY
|
|
|
|
from reportlab.lib.enums import TA_JUSTIFY
|
|
|
|
from reportlab.pdfbase import pdfmetrics
|
|
|
|
from reportlab.pdfbase import pdfmetrics
|
|
|
|
from reportlab.pdfbase.ttfonts import TTFont
|
|
|
|
from reportlab.pdfbase.ttfonts import TTFont
|
|
|
|
import os
|
|
|
|
import os
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Configuration
|
|
|
|
# Configuration
|
|
|
|
|
|
|
|
DEBUG = True
|
|
|
|
PDF_PATH = "TaniaBorecMemoir(Ukr).pdf"
|
|
|
|
PDF_PATH = "TaniaBorecMemoir(Ukr).pdf"
|
|
|
|
OLLAMA_MODEL = "traductionUkrainienVersFrancais:latest"
|
|
|
|
OLLAMA_MODEL = "traductionUkrainienVersFrancais:latest"
|
|
|
|
OLLAMA_URL = "http://localhost:11434/api/generate"
|
|
|
|
OLLAMA_URL = "http://localhost:11434/api/generate"
|
|
|
|
TARGET_LANGUAGE = "français"
|
|
|
|
TARGET_LANGUAGE = "français"
|
|
|
|
CHECKPOINT_FILE = "checkpoint.json"
|
|
|
|
CHECKPOINT_FILE = "checkpoint.json"
|
|
|
|
TEMP_OUTPUT_TXT = "output_temp.txt"
|
|
|
|
TEMP_OUTPUT_TXT = "output_temp.txt"
|
|
|
|
FINAL_OUTPUT_PDF = PDF_PATH.replace(".pdf",f" ({TARGET_LANGUAGE.upper()[:2]})_V2.pdf")
|
|
|
|
FINAL_OUTPUT_PDF = PDF_PATH.replace(".pdf",f"({TARGET_LANGUAGE.upper()[:2]})_V6.pdf")
|
|
|
|
FINAL_OUTPUT_TXT = PDF_PATH.replace(".pdf",f" ({TARGET_LANGUAGE.upper()[:2]})_V2.txt")
|
|
|
|
FINAL_OUTPUT_TXT = PDF_PATH.replace(".pdf",f"({TARGET_LANGUAGE.upper()[:2]})_V6.txt")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DEBUG = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def extract_parameters_from_template(template_str):
|
|
|
|
def extract_parameters_from_template(template_str):
|
|
|
|
"""Extrait les paramètres du modèle à partir du template."""
|
|
|
|
"""Extrait les paramètres du modèle à partir du template."""
|
|
|
@@ -144,8 +147,8 @@ def display_llm_info():
|
|
|
|
return "Informations du modèle non disponibles"
|
|
|
|
return "Informations du modèle non disponibles"
|
|
|
|
|
|
|
|
|
|
|
|
def register_unicode_font():
|
|
|
|
def register_unicode_font():
|
|
|
|
"""Enregistre une police TrueType qui supporte le cyrilique."""
|
|
|
|
"""Enregistre une police TrueType qui supporte le cyrillique."""
|
|
|
|
# Recherche une police système qui supporte le cyrilique
|
|
|
|
# Recherche une police système qui supporte le cyrillique
|
|
|
|
font_paths = [
|
|
|
|
font_paths = [
|
|
|
|
r"C:\Windows\Fonts\DejaVuSans.ttf",
|
|
|
|
r"C:\Windows\Fonts\DejaVuSans.ttf",
|
|
|
|
r"C:\Windows\Fonts\Calibri.ttf",
|
|
|
|
r"C:\Windows\Fonts\Calibri.ttf",
|
|
|
@@ -171,10 +174,15 @@ def load_checkpoint():
|
|
|
|
return json.load(f)
|
|
|
|
return json.load(f)
|
|
|
|
return {"last_processed_index": -1, "results": {}}
|
|
|
|
return {"last_processed_index": -1, "results": {}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Sauvegarde le checkpoint
|
|
|
|
# Sauvegarde le checkpoint
|
|
|
|
# Sauvegarde le checkpoint
|
|
|
|
def save_checkpoint(last_index, results):
|
|
|
|
def save_checkpoint(last_index, results):
|
|
|
|
|
|
|
|
# Trier les clés du dictionnaire results
|
|
|
|
|
|
|
|
sorted_results = {key: results[key] for key in sorted(results.keys(), key=int)}
|
|
|
|
|
|
|
|
|
|
|
|
with open(CHECKPOINT_FILE, "w") as f:
|
|
|
|
with open(CHECKPOINT_FILE, "w") as f:
|
|
|
|
json.dump({"last_processed_index": last_index, "results": results}, f)
|
|
|
|
# Utiliser un espace d'indentation de 4 espaces pour rendre le JSON plus lisible
|
|
|
|
|
|
|
|
json.dump({"last_processed_index": last_index, "results": sorted_results}, f, indent=4)
|
|
|
|
|
|
|
|
|
|
|
|
# Sauvegarde les résultats temporaires dans un fichier TXT
|
|
|
|
# Sauvegarde les résultats temporaires dans un fichier TXT
|
|
|
|
def save_temp_results(results):
|
|
|
|
def save_temp_results(results):
|
|
|
@@ -211,16 +219,13 @@ def send_to_ollama(text, target_lang=TARGET_LANGUAGE, model=OLLAMA_MODEL):
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
raise Exception(f"Erreur Ollama: {response.text}")
|
|
|
|
raise Exception(f"Erreur Ollama: {response.text}")
|
|
|
|
|
|
|
|
|
|
|
|
# Création du PDF final (inchangée)
|
|
|
|
# Création du PDF final avec numéros de chapitres dans la marge
|
|
|
|
def create_pdf_from_results(results, output_path):
|
|
|
|
def create_pdf_from_results(results, output_path):
|
|
|
|
"""Crée un PDF à partir des résultats de traduction."""
|
|
|
|
"""Crée un PDF à partir des résultats de traduction, avec des notes dans la marge et un numéro de page."""
|
|
|
|
doc = SimpleDocTemplate(output_path, pagesize=letter, topMargin=inch, bottomMargin=inch)
|
|
|
|
|
|
|
|
story = []
|
|
|
|
story = []
|
|
|
|
|
|
|
|
|
|
|
|
# Enregistre une police qui supporte le cyrilique
|
|
|
|
|
|
|
|
font_name = register_unicode_font()
|
|
|
|
font_name = register_unicode_font()
|
|
|
|
|
|
|
|
|
|
|
|
# Style personnalisé
|
|
|
|
# Styles personnalisés
|
|
|
|
styles = getSampleStyleSheet()
|
|
|
|
styles = getSampleStyleSheet()
|
|
|
|
title_style = ParagraphStyle(
|
|
|
|
title_style = ParagraphStyle(
|
|
|
|
'CustomTitle',
|
|
|
|
'CustomTitle',
|
|
|
@@ -251,17 +256,34 @@ def create_pdf_from_results(results, output_path):
|
|
|
|
fontName=font_name
|
|
|
|
fontName=font_name
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
note_style = ParagraphStyle(
|
|
|
|
|
|
|
|
'CustomBody',
|
|
|
|
|
|
|
|
parent=styles['BodyText'],
|
|
|
|
|
|
|
|
fontSize=8,
|
|
|
|
|
|
|
|
alignment=TA_JUSTIFY,
|
|
|
|
|
|
|
|
spaceAfter=0,
|
|
|
|
|
|
|
|
fontName=font_name
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Création du document avec les callbacks pour les notes et le numéro de page
|
|
|
|
|
|
|
|
doc = SimpleDocTemplate(
|
|
|
|
|
|
|
|
output_path,
|
|
|
|
|
|
|
|
pagesize=letter,
|
|
|
|
|
|
|
|
topMargin=inch,
|
|
|
|
|
|
|
|
bottomMargin=inch,
|
|
|
|
|
|
|
|
)
|
|
|
|
# Titre avec la langue cible
|
|
|
|
# Titre avec la langue cible
|
|
|
|
story.append(Paragraph(f"Traduction - Ukrainien vers {TARGET_LANGUAGE.capitalize()}", title_style))
|
|
|
|
story.append(Paragraph(f"Traduction - Ukrainien vers {TARGET_LANGUAGE.capitalize()}", title_style))
|
|
|
|
story.append(Paragraph(f"Document : {PDF_PATH}", title_style))
|
|
|
|
story.append(Paragraph(f"Document : {PDF_PATH}", title_style))
|
|
|
|
story.append(Spacer(1, 0.2*inch))
|
|
|
|
story.append(Spacer(1, 0.2*inch))
|
|
|
|
|
|
|
|
|
|
|
|
# Contenu
|
|
|
|
# Contenu
|
|
|
|
for page_num, translation in results.items():
|
|
|
|
for paragraph_num, translation in results.items():
|
|
|
|
# Préserver la mise en page en convertissant les sauts de ligne
|
|
|
|
|
|
|
|
formatted_text = translation.replace("\n", "<br/>")
|
|
|
|
formatted_text = translation.replace("\n", "<br/>")
|
|
|
|
|
|
|
|
if DEBUG:
|
|
|
|
|
|
|
|
# Ajoute le paragraphe avec sa note
|
|
|
|
|
|
|
|
story.append(Paragraph(paragraph_num, note_style))
|
|
|
|
story.append(Paragraph(formatted_text, body_style))
|
|
|
|
story.append(Paragraph(formatted_text, body_style))
|
|
|
|
# story.append(Spacer(1, 0.1*inch))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Infos sur le LLM
|
|
|
|
# Infos sur le LLM
|
|
|
|
story.append(Spacer(1, 0.2*inch))
|
|
|
|
story.append(Spacer(1, 0.2*inch))
|
|
|
@@ -271,6 +293,7 @@ def create_pdf_from_results(results, output_path):
|
|
|
|
doc.build(story)
|
|
|
|
doc.build(story)
|
|
|
|
print(f"PDF généré avec succès : {output_path}")
|
|
|
|
print(f"PDF généré avec succès : {output_path}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_txt_from_results(results, output_path):
|
|
|
|
def create_txt_from_results(results, output_path):
|
|
|
|
"""Crée un fichier TXT à partir des résultats de traduction."""
|
|
|
|
"""Crée un fichier TXT à partir des résultats de traduction."""
|
|
|
|
OUTPUT_TXT_PATH = output_path.replace(".pdf", f".txt") # Chemin du fichier TXT de sortie
|
|
|
|
OUTPUT_TXT_PATH = output_path.replace(".pdf", f".txt") # Chemin du fichier TXT de sortie
|
|
|
@@ -281,7 +304,10 @@ def create_txt_from_results(results, output_path):
|
|
|
|
txt_file.write(title_text + "\n\n")
|
|
|
|
txt_file.write(title_text + "\n\n")
|
|
|
|
|
|
|
|
|
|
|
|
# Contenu
|
|
|
|
# Contenu
|
|
|
|
for page_num, translation in results.items():
|
|
|
|
for paragraph_num, translation in results.items():
|
|
|
|
|
|
|
|
# Ajoute les numéro de paragraphe et chapitre
|
|
|
|
|
|
|
|
if(DEBUG): txt_file.write(f"{paragraph_num}\n")
|
|
|
|
|
|
|
|
|
|
|
|
# Préserver la mise en page en convertissant les sauts de ligne
|
|
|
|
# Préserver la mise en page en convertissant les sauts de ligne
|
|
|
|
txt_file.write(translation + "\n\n")
|
|
|
|
txt_file.write(translation + "\n\n")
|
|
|
|
|
|
|
|
|
|
|
@@ -291,17 +317,46 @@ def create_txt_from_results(results, output_path):
|
|
|
|
|
|
|
|
|
|
|
|
# Fonction principale
|
|
|
|
# Fonction principale
|
|
|
|
def main():
|
|
|
|
def main():
|
|
|
|
# Charge le checkpoint
|
|
|
|
|
|
|
|
checkpoint = load_checkpoint()
|
|
|
|
checkpoint = load_checkpoint()
|
|
|
|
last_index = checkpoint["last_processed_index"]
|
|
|
|
last_index = checkpoint["last_processed_index"]
|
|
|
|
results = checkpoint["results"]
|
|
|
|
results = checkpoint["results"]
|
|
|
|
|
|
|
|
|
|
|
|
# Extraction des paragraphes
|
|
|
|
|
|
|
|
pages = extract_text_from_pdf(PDF_PATH)
|
|
|
|
pages = extract_text_from_pdf(PDF_PATH)
|
|
|
|
paragraphs = split_pages_in_paragraphs(pages)
|
|
|
|
paragraphs = split_pages_in_paragraphs(pages)
|
|
|
|
|
|
|
|
|
|
|
|
# Traitement des paragraphes
|
|
|
|
# Liste de tous les indices de batches attendus (par pas de batch_size)
|
|
|
|
batch_size = 3
|
|
|
|
batch_size = 5
|
|
|
|
|
|
|
|
expected_batch_indices = list(range(0, len(paragraphs), batch_size))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Liste des indices de batches déjà présents dans results
|
|
|
|
|
|
|
|
present_batch_indices = set()
|
|
|
|
|
|
|
|
for key in results.keys():
|
|
|
|
|
|
|
|
batch_start = int(int(key) // batch_size * batch_size) # Arrondit à l'indice de début de batch
|
|
|
|
|
|
|
|
present_batch_indices.add(batch_start)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Trouve les batches manquants
|
|
|
|
|
|
|
|
missing_batches = [i for i in expected_batch_indices if i not in present_batch_indices and i <= last_index]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Affichage des batches manquants (pour débogage)
|
|
|
|
|
|
|
|
print(f"Batches manquants détectés : {missing_batches}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Traduction des paragraphes manquants
|
|
|
|
|
|
|
|
for i in missing_batches:
|
|
|
|
|
|
|
|
batch = paragraphs[i:i + batch_size]
|
|
|
|
|
|
|
|
paragraph_cumul = "\n".join(batch)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print(f"{15 * '-'} Traduction des paragraphes manquants {i+1} à {min(i + batch_size, len(paragraphs))} / {len(paragraphs)}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
result = send_to_ollama(paragraph_cumul)
|
|
|
|
|
|
|
|
print(f"{result}")
|
|
|
|
|
|
|
|
results[str(i)] = result
|
|
|
|
|
|
|
|
save_checkpoint(len(paragraphs), results) # Met à jour le dernier indice du batch
|
|
|
|
|
|
|
|
save_temp_results(results)
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
|
|
print(f"Erreur lors de la traduction du paragraphe {i}: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Traitement des paragraphes suivants
|
|
|
|
for i in range(last_index + 1, len(paragraphs), batch_size):
|
|
|
|
for i in range(last_index + 1, len(paragraphs), batch_size):
|
|
|
|
batch = paragraphs[i:i + batch_size]
|
|
|
|
batch = paragraphs[i:i + batch_size]
|
|
|
|
paragraph_cumul = "\n".join(batch)
|
|
|
|
paragraph_cumul = "\n".join(batch)
|
|
|
@@ -311,18 +366,18 @@ def main():
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
result = send_to_ollama(paragraph_cumul)
|
|
|
|
result = send_to_ollama(paragraph_cumul)
|
|
|
|
print(f"{result}")
|
|
|
|
print(f"{result}")
|
|
|
|
results[i] = result
|
|
|
|
results[str(i)] = result
|
|
|
|
save_checkpoint(i, results) # Sauvegarde le checkpoint
|
|
|
|
save_checkpoint(i + batch_size - 1, results)
|
|
|
|
save_temp_results(results) # Sauvegarde les résultats temporaires
|
|
|
|
save_temp_results(results)
|
|
|
|
except Exception as e:
|
|
|
|
except Exception as e:
|
|
|
|
print(f"Erreur : {e}")
|
|
|
|
print(f"Erreur : {e}")
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
# Génération des fichiers finaux
|
|
|
|
|
|
|
|
save_temp_results(results)
|
|
|
|
save_temp_results(results)
|
|
|
|
create_pdf_from_results(results, FINAL_OUTPUT_PDF)
|
|
|
|
create_pdf_from_results(results, FINAL_OUTPUT_PDF)
|
|
|
|
create_txt_from_results(results, FINAL_OUTPUT_TXT)
|
|
|
|
create_txt_from_results(results, FINAL_OUTPUT_TXT)
|
|
|
|
print("Traduction terminée !")
|
|
|
|
print("Traduction terminée !")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|
|
|
|
main()
|