Prep_my_data / app.py
lsottani's picture
Update app.py
4cc0fc9 verified
#!/usr/bin/env python
import os
import re
import tempfile
from pathlib import Path
import pdfplumber
import docx
import gradio as gr
def clean_text_for_rag(text: str) -> str:
"""Normalise et nettoie le texte pour un usage RAG."""
# Normalisation des caractères typographiques
text = re.sub(
r"[’‘“”«»–—\u00A0\u202F…œŒæÆ©®™§°±×÷]",
lambda m: {
"’": "'", "‘": "'", "“": '"', "”": '"',
"«": '"', "»": '"', "–": "-", "—": "-",
"…": "...", "œ": "oe", "Œ": "OE",
"æ": "ae", "Æ": "AE", "©": "(c)", "®": "(R)",
"™": "TM", "§": "§", "°": "°", "±": "+/-",
"×": "x", "÷": "/"
}.get(m.group(0), m.group(0)),
text,
)
# Conserver uniquement les caractères suivants
text = re.sub(r'[^a-zA-ZÀ-ÿæ-œ0-9\s\.\,\:\;\!\?\-\_\'\"\\\(\)]', '', text)
# Réduire les espaces multiples
return re.sub(r'\s+', ' ', text).strip()
def extract_and_clean_pdf(pdf_path: str) -> str:
"""Ouvre le PDF, récupère le texte et le nettoie."""
print(f"[+] Extraction du PDF : {pdf_path}")
all_pages = []
with pdfplumber.open(pdf_path) as pdf:
for page in pdf.pages:
txt = page.extract_text()
if txt:
all_pages.append(txt)
return clean_text_for_rag(" ".join(all_pages))
def extract_and_clean_docx(docx_path: str) -> str:
"""Lit un fichier DOCX et le nettoie."""
print(f"[+] Extraction du DOCX : {docx_path}")
doc = docx.Document(docx_path)
paragraphs = []
for para in doc.paragraphs:
text = para.text.strip()
if text:
paragraphs.append(text)
return clean_text_for_rag(" ".join(paragraphs))
def extract_and_clean_txt(txt_path: str) -> str:
"""Lit un fichier texte (txt, md, …) et le nettoie."""
print(f"[+] Lecture du fichier texte : {txt_path}")
with open(txt_path, "r", encoding="utf-8") as f:
lines = f.readlines()
cleaned = [
clean_text_for_rag(line.strip())
for line in lines
if line.strip()
]
return "\n".join(cleaned)
def process_file(input_file, output_name):
"""
- Detecte le type (PDF ou texte)
- Effectue l'extraction + nettoyage
- Crée un fichier temporaire **avec le nom choisi** (output_name)
- Retourne le chemin du fichier temporaire (Gradio le propose en téléchargement)
"""
if input_file is None:
return None
if hasattr(input_file, "read"):
data = input_file.read()
filename = input_file.name
elif isinstance(input_file, str):
filename = input_file
with open(input_file, "rb") as f:
data = f.read()
else:
filename = input_file[0].name
data = input_file[0].read()
# écrire dans /tmp (important sur HF Spaces)
suffix = os.path.splitext(filename)[1]
tmp_path = os.path.join(tempfile.gettempdir(), "upload" + suffix)
with open(tmp_path, "wb") as f:
f.write(data)
ext = suffix.lower()
if ext == ".pdf":
cleaned_text = extract_and_clean_pdf(tmp_path)
elif ext == ".docx":
cleaned_text = extract_and_clean_docx(tmp_path)
else:
cleaned_text = extract_and_clean_txt(tmp_path)
if not output_name.lower().endswith(".md"):
output_name += ".md"
out_path = os.path.join(tempfile.gettempdir(), output_name)
with open(out_path, "w", encoding="utf-8") as f:
f.write(cleaned_text)
return out_path
with gr.Blocks(title="Nettoyage de texte pour RAG") as demo:
gr.Markdown("# 📄 Nettoyage d'un fichier pour optimisation de vos pipelines RAG")
gr.Markdown(
"Déposez simplement votre fichier : nous nous chargeons d’extraire son contenu textuel, de le nettoyer "
"puis de vous le restituer en format markdown **sous le nom que vous choisissez.**"
)
with gr.Row():
with gr.Column(scale=1):
input_file = gr.File(
label="Déposez votre fichier ici",
file_types=[".pdf", ".txt", ".md", ".docx"],
file_count="single",
)
output_name = gr.Textbox(
value="output.md",
label="Nom du fichier de sortie (en .md)",
placeholder="exemple.md",
interactive=True,
)
submit_btn = gr.Button("Traiter le fichier", variant="primary")
with gr.Column(scale=1):
output_file = gr.File(
label="Fichier nettoyé (.md)",
file_types=["md"],
)
submit_btn.click(
fn=process_file,
inputs=[input_file, output_name],
outputs=output_file,
)
gr.Markdown(
"""
---
**Prétraitements effectués :**
- Suppression des symboles non imprimables et des caractères parasites
- Conservation des lettres (y compris accentuées), chiffres, espaces et ponctuation simple
- Normalisation des espaces pour un texte harmonieux
- Export automatique au format **`.md`**
"""
)
if __name__ == "__main__":
demo.launch()