GraphRag / processingPdf /extractor.py
ValerioBotto's picture
Initial clean commit without secrets
aabd32c
#Questo documento incapsula la logica per l'estrazione delle NE e del testo strutturato
from gliner import GLiNER
import torch
import logging
from processingPdf.loader import get_layout_extractor, load_pdf_from_bytes
from processingPdf.logicSections import extract_logical_sections
logger = logging.getLogger(__name__)
class PDFExtractor:
def __init__(self):
self.layout_extractor = get_layout_extractor()
def extract_sections(self, file_path: str):
# Legge il file in bytes per spaCyLayout
with open(file_path, "rb") as f:
pdf_bytes = f.read()
# Carica il documento ed estrae il layout
doc = load_pdf_from_bytes(pdf_bytes, self.layout_extractor)
# Suddivide in sezioni logiche
if doc:
return extract_logical_sections(doc)
return {}
class EntityExtractor:
_model = None
@staticmethod
def get_model():
if EntityExtractor._model is None:
logger.info("Caricamento del modello GLiNER...")
device = "cuda" if torch.cuda.is_available() else "cpu"
EntityExtractor._model = GLiNER.from_pretrained("urchade/gliner_medium-v2.1").to(device)
return EntityExtractor._model
@staticmethod
def extract_ne(text: str):
model = EntityExtractor.get_model()
labels = [
# --- GENERAL & IDENTIFIERS ---
"Person", "Organization", "Location", "Date", "Time",
"Product", "Event", "Nationality", "Language",
# --- BUROCRATICO, NORMATIVO & BANDI ---
"Normative Reference", # Articoli di legge, decreti, commi
"Public Body", # Enti pubblici (es. Ministero, Commissione Europea)
"Deadline", # Scadenze per bandi, domande o pagamenti
"Requirement", # Requisiti di partecipazione o criteri di accesso
"Amount", # Cifre monetarie, borse di studio, tasse
"Evaluation Criteria", # Criteri di punteggio o valutazione
"Document Type", # Es. ISEE, Marca da bollo, Certificato di laurea
# --- TECNICO & MANUALE DI ISTRUZIONI ---
"Component", # Parti di macchinari o componenti hardware
"Technical Specification", # Es. 220V, 50Hz, risoluzione 4K, velocità rotazione
"Error Code", # Codici errore (es. E04, 404, Fault-01)
"Safety Instruction", # Avvertenze di sicurezza o pericoli
"Tool", # Strumenti necessari (es. chiave inglese, cacciavite)
"Operation Mode", # Modalità operative (es. Standby, Manuale, Eco)
# --- SCIENTIFICO, CHIMICO & FISICO ---
"Scientific Term", # Termini tecnici generali
"Chemical Compound", # Formule e nomi di sostanze (es. H2O, Glucosio)
"Theory/Law", # Leggi fisiche o teorie (es. Legge di Ohm, Relatività)
"Measurement Unit", # Unità di misura (es. Joule, Watt, Nanometri)
"Phenomenon", # Fenomeni naturali o reazioni (es. Ossidazione, Gravità)
# --- MEDICO & CLINICO ---
"Clinical Condition", # Malattie, patologie o sintomi
"Medical Parameter", # Es. Glicemia, Pressione Arteriosa, Frequenza Cardiaca
"Anatomical Structure", # Organi, ossa, muscoli o tessuti
"Drug/Medication", # Nomi di farmaci o principi attivi
"Diagnostic Test", # Es. Risonanza Magnetica, Analisi del sangue
# --- ACCADEMICO & SCOLASTICO ---
"Academic Subject", # Materie (es. Storia Moderna, Fisica Quantistica)
"Exam/Test Name", # Titoli di esami o test (es. Test TOLC, Prova Scritta)
"Degree Course", # Corsi di laurea o diplomi
"Bibliographic Source", # Citazioni, autori o titoli di testi universitari
# --- STORICO & NARRATIVO (FANTASCIENZA) ---
"Historical Period", # Ere, secoli o movimenti (es. Illuminismo, Paleolitico)
"Fictional Species", # Es. Androidi, Alieni, Specie di fantasia
"Technological Concept", # Tecnologie immaginarie o concetti futuristici
# --- QUANTITATIVO ---
"Percentage", # Percentuali e tassi
"Quantity", # Quantità generiche non monetarie
"Distance" # Distanze e lunghezze
]
entities_found = model.predict_entities(text, labels, threshold=0.5)
entities = []
seen = set() # Per tracciare i duplicati nello stesso chunk
for ent in entities_found:
text_clean = ent["text"].strip().lower()
label_clean = ent["label"].upper().replace(" ", "_")
# Creiamo una chiave univoca per il set
entity_key = (text_clean, label_clean)
if entity_key not in seen:
entities.append({
"text": text_clean,
"label": label_clean
})
seen.add(entity_key)
return entities