Generatore di Storie con NLP
L’obiettivo è creare un sistema che, a partire da una matrice di analisi semantica (come quella proposta), possa generare una narrazione coerente e coinvolgente.
1. Analisi della Matrice
La matrice fornita è un ottimo punto di partenza. Rappresenta un’ampia gamma di elementi narrativi. Per renderla ancora più efficace per la generazione automatica, possiamo considerare alcuni miglioramenti:
- Struttura più rigida per alcuni elementi: Per elementi come “Struttura della Trama” e “Stile Narrativo”, potremmo definire un set predefinito di opzioni (come hai fatto in parte) per guidare meglio la generazione.
- Relazioni tra elementi: Aggiungere informazioni sulle relazioni tra gli elementi (ad esempio, quali temi sono più adatti a certi stili narrativi, quali ruoli dei personaggi sono tipicamente associati a certi conflitti).
- Ontologie: Utilizzare ontologie esistenti (come DBpedia o schema.org) per arricchire la matrice con informazioni sul mondo reale (ad esempio, associare un “TipoDiAmbientazione” come “Fantasy medievale” a concetti come “castello”, “cavaliere”, “magia”).
2. Componenti del Sistema
Il sistema potrebbe essere composto dai seguenti componenti:
- Modulo di Input:
- Permette all’utente di specificare i parametri della storia (selezionando valori dalla matrice o inserendo input personalizzati).
- Potrebbe includere un’interfaccia utente grafica (GUI) per facilitare l’interazione.
- Modulo di Elaborazione del Linguaggio Naturale (NLP):
- Analisi del testo: Se il sistema deve generare storie a partire da un testo esistente, questo modulo si occupa di analizzarlo per estrarre le informazioni rilevanti e popolare la matrice.
-
- Estrazione di entità nominate (NER): Per identificare personaggi, luoghi, oggetti.
-
- Analisi del sentiment: Per determinare il “TipoDiSentimentiPresentiNelRacconto” e la “IntensitàEmotivaMedia”.
- Riconoscimento delle relazioni: Per capire come i personaggi interagiscono tra loro.
-
- Generazione del testo: Il cuore del sistema. Utilizza le informazioni della matrice per creare la narrazione.
-
- Modelli linguistici pre-addestrati: Modelli come GPT-3, T5 o simili possono essere utilizzati per generare il testo vero e proprio.
-
- Regole e vincoli: Il sistema deve includere regole per garantire la coerenza della storia (ad esempio, assicurarsi che le azioni dei personaggi siano coerenti con i loro ruoli e la loro evoluzione).
- Tecniche di generazione creativa: Tecniche come la variazione tematica, la generazione di dialoghi e la descrizione di scene possono essere impiegate.
-
- Analisi del testo: Se il sistema deve generare storie a partire da un testo esistente, questo modulo si occupa di analizzarlo per estrarre le informazioni rilevanti e popolare la matrice.
- Modulo di Output:
- Presenta la storia generata all’utente in un formato leggibile (testo, HTML, ecc.).
- Potrebbe includere opzioni per esportare la storia in diversi formati (PDF, ePub, ecc.).
3. Esempio di Flusso di Lavoro
- Input: L’utente seleziona dalla matrice:
- Personaggi: 3
- Ruoli: “Eroe”, “Antagonista”, “Aiutante”
- Ambientazione: “Fantasy epico”
- Struttura della trama: “Lineare classica”
- Temi: “Coraggio”, “Tradimento”, “Redenzione”
- Elaborazione:
- Il sistema recupera descrizioni di personaggi archetipici per “Eroe”, “Antagonista” e “Aiutante” da un database.
- Utilizza l’ontologia per ottenere dettagli sull’ambientazione “Fantasy epico” (castelli, foreste, creature magiche).
- Il modello linguistico genera una trama lineare che coinvolge i personaggi selezionati e i temi specificati.
- Output: Il sistema produce un racconto che inizia con l’Eroe che intraprende un viaggio, affronta il tradimento dell’Aiutante, combatte l’Antagonista e alla fine trova la redenzione.
4. Tecnologie e Strumenti
- Linguaggi di programmazione: Python (per la sua ricca libreria di NLP).
- Librerie NLP:
- spaCy o NLTK per l’analisi del testo.
- Transformers (Hugging Face) per l’utilizzo di modelli linguistici pre-addestrati.
- Framework per GUI: PyQt o Tkinter (se si desidera un’interfaccia grafica).
- Database: Per archiviare informazioni sui personaggi, ambientazioni, temi, ecc.
- Ontologie: DBpedia, schema.org.
5. Sfide e Considerazioni
- Coerenza: Garantire che la storia sia coerente a livello di trama, personaggi e tono.
- Creatività: Bilanciare la generazione automatica con elementi di originalità e creatività.
- Controllo: Fornire all’utente un controllo sufficiente sul processo di generazione.
- Valutazione: Definire metriche per valutare la qualità delle storie generate (coerenza, coinvolgimento, originalità).
Questo è un progetto ambizioso, ma con le giuste tecniche e risorse, è possibile creare un generatore di storie potente e versatile.
Le applicazioni principali del software di generazione e gestione di tensori narrativi come quello descritto sono:
-
: aiuta autori, sceneggiatori e creativi a sviluppare trame, personaggi e stili narrativi in modo strutturato e guidato, facilitando la prototipazione di storie complesse e coerenti.
-
: consente di rappresentare e comprendere le componenti tematiche, emotive e strutturali di un testo narrativo attraverso tensori multidimensionali, utili per studi letterari, didattica e ricerca.
-
: può essere usato per insegnare tecniche di narrazione, analisi testuale e composizione poetica, offrendo feedback visivi e quantitativi sulle scelte stilistiche e tematiche.
-
: integrabile in videogiochi, app interattive o piattaforme di narrazione digitale per generare contenuti dinamici e personalizzati in base alle scelte dell’utente.
-
: come banco di prova per modelli di NLP avanzati, machine learning e AI generativa, per migliorare la coerenza e la creatività automatica nei testi.
In sintesi, il software è un software applicativo orizzontale che trova impiego in ambiti creativi, educativi, di ricerca e intrattenimento, offrendo funzionalità innovative per la gestione e la generazione automatica di narrazioni complesse
import tkinter as tk from tkinter import filedialog, messagebox, ttk, simpledialog from docx import Document from docx.shared import Pt from datetime import datetime import json import os import random import subprocess import numpy as np import spacy from transformers import pipeline # =============================== # Configurazione Globale e Inizializzazione # =============================== # Modello NLP per analisi linguistica (spacy) nlp = spacy.load("it_core_news_sm") # Modello per generazione di testo (transformers) generator = pipeline("text-generation", model="gpt2-medium") # =============================== # Parametri di Default e Strutture Dati # =============================== lingue = ["italiano", "inglese", "spagnolo", "francese", "tedesco"] generi = ["fantasy", "thriller", "romanzo storico", "fantascienza", "horror", "avventura", "drammatico", "mistero"] pubblico_target = ["ragazzi", "giovani adulti", "adulti"] stili_linguistici = ["sognante", "semplice", "descrittivo", "immersivo", "intenso", "ricercato"] titoli_base = ["L'eredità perduta", "Ombre nel passato", "Il segreto degli antichi", "Nel cuore della tempesta", "La via verso l'ignoto", "Custodi del destino", "L'ultimo codice", "Misteri sotto la luna", "La chiave del tempo", "Un mondo oltre il velo"] trame_base = [ "Un archeologo scopre un manoscritto che parla di una civiltà perduta. Il viaggio lo porterà a scoperte incredibili e a sfide pericolose.", "Una giovane hacker scopre un complotto segreto che potrebbe cambiare il mondo. Dovrà decidere se rivelare la verità o salvarsi.", "Un cavaliere senza macchia deve proteggere un artefatto magico dalle forze del male.", "In un futuro distopico, un ribelle si erge contro il sistema oppressivo per reclamare la libertà.", "Un gruppo di amici si avventura in una casa infestata, affrontando i loro peggiori incubi.", "Un detective con un passato oscuro indaga su una serie di omicidi misteriosi.", "Una famiglia si trasferisce in una nuova città, scoprendo che la loro casa nasconde segreti inquietanti.", "Un viaggio alla ricerca di un tesoro leggendario si trasforma in una lotta per la sopravvivenza.", "La scoperta di un portale dimensionale apre le porte a mondi sconosciuti e pericoli inimmaginabili.", "Un artista maledetto scopre che le sue opere hanno un potere oscuro e deve trovare un modo per fermarlo." ] ambientazioni = ["Un'oscura foresta avvolta nella nebbia, dove misteriose creature si nascondono.", "Le rovine di un'antica città perduta, illuminate dalla luce tremolante di torce.", "Una caverna sotterranea piena di cristalli luminescenti e strani simboli incisi sulle pareti."] azioni_personaggi = ["Il protagonista trova un vecchio manoscritto e inizia a decifrarne i segreti.", "Una figura misteriosa si avvicina e sussurra una rivelazione sconvolgente.", "Un'esplosione improvvisa scuote l'ambiente, costringendo i personaggi a fuggire.", "Il protagonista si confronta con il suo nemico giurato in un duello epico.", "Un messaggio criptico conduce il gruppo verso un luogo nascosto.", "La scoperta di un passaggio segreto rivela una verità sconcertante.", "Un sacrificio inaspettato cambia il corso degli eventi.", "Un tradimento inatteso spezza la fiducia tra i protagonisti.", "Un oggetto magico conferisce al protagonista un potere straordinario.", "La profezia si avvera, rivelando il destino del mondo."] dialoghi = [ "\"Non avrei mai creduto che saremmo arrivati a questo punto.\"", "\"Dobbiamo trovare un modo per fermarli, prima che sia troppo tardi.\"", "\"C'è qualcosa di strano in questo posto, lo sento.\"", "\"Non fidarti di nessuno, tutti hanno qualcosa da nascondere.\"", "\"La verità è più complessa di quanto sembri.\"", "\"Siamo legati da un destino che va oltre la nostra comprensione.\"", "\"Il passato ritorna sempre a perseguitarci.\"", "\"La speranza è l'ultima a morire.\"", "\"A volte, le scelte più difficili sono quelle giuste.\"", "\"Non siamo soli in questo mondo, ci sono forze che non possiamo controllare.\"" ] fasi = ['inizio', 'sviluppo', 'climax', 'fine'] livelli = ['trama', 'personaggi', 'atmosfera', 'dialoghi'] attributi = ['intensità_emotiva', 'tensione', 'crescita'] # =============================== # Funzioni Utilità # =============================== def trova_nome_libero(base_nome, estensione): """Trova un nome file disponibile incrementando numeri progressivi.""" numero = 1 nuovo_nome = f"{base_nome}{estensione}" while os.path.exists(nuovo_nome): nuovo_nome = f"{base_nome}_{numero}{estensione}" numero += 1 return nuovo_nome def carica_parametri(nome_file="parametri_libro.json"): """Carica i parametri del libro da un file JSON.""" try: with open(nome_file, "r", encoding="utf-8") as file: return json.load(file) except FileNotFoundError: print(f"?? Errore: Il file dei parametri '{nome_file}' non è stato trovato. Esegui prima 'raccolta_parametri.py'.") return None except json.JSONDecodeError: print(f"?? Errore: Il file dei parametri '{nome_file}' non è un JSON valido.") return None def salva_parametri(parametri, nome_file="parametri_libro.json"): """Salva i parametri del libro in un file JSON.""" try: with open(nome_file, "w", encoding="utf-8") as file: json.dump(parametri, file, indent=4) print(f"? Parametri salvati con successo in '{nome_file}'.") except Exception as e: print(f"?? Errore durante il salvataggio dei parametri: {e}") return False return True def carica_contenuto(nome_file="contenuto_libro.txt"): """Legge e verifica il contenuto generato.""" try: with open(nome_file, "r", encoding="utf-8") as file: contenuto = file.read() if len(contenuto) < 500: print("⚠️ Avviso: Il contenuto sembra troppo corto. Controlla 'generazione.py'.") return contenuto except FileNotFoundError: print(f"⚠️ Errore: Il file dei contenuti '{nome_file}' non è stato trovato. Esegui prima 'generazione.py'.") return None except Exception as e: print(f"?? Errore durante il caricamento del contenuto: {e}") return None def salva_contenuto(contenuto, nome_file="contenuto_libro.txt"): """Salva il contenuto in un file .txt.""" try: with open(nome_file, "w", encoding="utf-8") as file: file.write(contenuto) print(f"? Contenuto salvato in '{nome_file}'!") except Exception as e: print(f"?? Errore durante il salvataggio del contenuto: {e}") return False return True # =============================== # Funzioni di Generazione Contenuto # =============================== def genera_trama(): """Genera una trama casuale.""" genere = random.choice(generi) ambientazione = random.choice(ambientazioni) conflitto = random.choice(azioni_personaggi) protagonista = random.choice(dialoghi) trama = f"In un mondo di genere {genere}, ambientato in {ambientazione}, {protagonista} deve affrontare {conflitto}..." return trama def genera_parametri_casuali(numero_opere=1): """Genera parametri casuali per la creazione di opere.""" parametri_list = [] for _ in range(numero_opere): parametri = { "titolo": random.choice(titoli_base), "lingua": random.choice(lingue), "genere": random.choice(generi), "stile_linguistico": random.choice(stili_linguistici), "pubblico_target": random.choice(pubblico_target), "lunghezza": f"{random.randint(150, 400)} pagine", "numero_capitoli": f"{random.randint(10, 30)}", "tema_principale": random.choice(trame_base), "difficolta_linguistica": random.choice(["facile", "media", "complessa"]), "formato_output": random.choice(["docx", "pdf", "epub"]) } parametri_list.append(parametri) return parametri_list def genera_contenuto(parametri): """Genera il contenuto del libro basandosi sui parametri.""" num_capitoli = int(parametri.get("numero_capitoli", 10)) contenuto = [] contenuto.append(f"# {parametri['titolo']}\\n") contenuto.append(f"## {parametri['pubblico_target']} - {parametri['genere']}\\n") contenuto.append(f"### Scritto in {parametri['lingua']}\\n\\n") for i in range(1, num_capitoli + 1): contenuto.append(f"## Capitolo {i}: Titolo provvisorio\\n") contenuto.append(f"Ambientazione: {random.choice(ambientazioni)}\\n") contenuto.append(f"Sviluppo della trama:\\n") for _ in range(5): contenuto.append(f"- {random.choice(azioni_personaggi)} ") contenuto.append(f"- {random.choice(dialoghi)} ") contenuto.append("\\n") return "\\n".join(contenuto) # =============================== # Funzioni Tensore Narrativo # =============================== def crea_tensore_da_testo(testo): """ Analizza un testo e restituisce un tensore narrativo (numpy array) con supporto per più attributi. Args: testo (str): Il testo da analizzare. Returns: numpy.ndarray: Un tensore 3D che rappresenta il testo analizzato. Le dimensioni sono: [fase, livello, attributo]. """ doc = nlp(testo) insights = { "ricchezza_lessicale": len(set([token.text for token in doc if token.is_alpha])) / len(doc), "lunghezza_media_frasi": np.mean([len(sent) for sent in doc.sents]), "variabilita_sintattica": len(list(doc.sents)), "emozione_media": 0.5, # Placeholder } # Creazione di un tensore 3D tensore = np.zeros((len(fasi), len(livelli), len(attributi))) # Popolamento del tensore con i valori calcolati # Esempio: Popola il tensore con i valori di 'inizio' tensore[0, 0, :] = [insights["ricchezza_lessicale"], insights["lunghezza_media_frasi"], insights["variabilita_sintattica"]] #trama tensore[0, 1, :] = [insights["emozione_media"], 0.6, 0.5] #personaggi tensore[0, 2, :] = [0.7, 0.4, 0.6] #atmosfera tensore[0, 3, :] = [0.5, 0.7, 0.4] #dialoghi # Per le fasi successive, potremmo voler calcolare valori diversi o usare una logica più complessa. tensore[1, 0, :] = [0.8, 0.7, 0.6] # Sviluppo - Trama tensore[1, 1, :] = [0.6, 0.5, 0.7] # Sviluppo - Personaggi tensore[1, 2, :] = [0.5, 0.6, 0.5] tensore[1, 3, :] = [0.4,0.5,0.6] tensore[2, 0, :] = [0.2, 0.9, 0.8] # Climax - Trama tensore[2, 1, :] = [0.9, 0.8, 0.2] # Climax - Personaggi tensore[2, 2, :] = [0.9, 0.2, 0.9] tensore[2, 3, :] = [0.7,0.9,0.2] tensore[3, 0, :] = [0.5, 0.4, 0.3] # Fine - Trama tensore[3, 1, :] = [0.3, 0.2, 0.4] # Fine - Personaggi tensore[3, 2, :] = [0.4, 0.3, 0.2] tensore[3, 3, :] = [0.2,0.4,0.3] return tensore def costruisci_prompt(fase_idx, tensore): """ Costruisce un prompt di generazione del testo a partire da una fase e un tensore, includendo tutti gli attributi. Args: fase_idx (int): L'indice della fase narrativa. tensore (numpy.ndarray): Il tensore narrativo 3D. Returns: str: Il prompt di generazione del testo. """ prompt = f"In questa fase {fasi[fase_idx]}, sviluppa una scena con:\n" for liv_idx, livello in enumerate(livelli): for attr_idx, attributo in enumerate(attributi): valore = tensore[fase_idx, liv_idx, attr_idx] prompt += f" - {livello} - {attributo}: {valore:.2f}\n" return prompt def genera_narrazione(tensore): """ Genera una narrazione basata su un tensore narrativo 3D. Args: tensore (numpy.ndarray): Il tensore narrativo 3D. Returns: str: La narrazione generata. """ fase_idx = np.random.randint(len(fasi)) prompt = costruisci_prompt(fase_idx, tensore) output = generator(prompt, max_length=200, do_sample=True)[0]['generated_text'] return output # =============================== # Funzioni di Formattazione e Esportazione # =============================== def formatta_documento(contenuto, parametri): """Genera un file .docx formattato con titolo, capitoli e stile.""" documento = Document() documento.add_heading(parametri["titolo"], level=1) documento.add_paragraph(f"Autore: {parametri.get('autore', 'Anonimo')}") documento.add_paragraph(f"Data di generazione: {datetime.now().strftime('%Y-%m-%d')}") documento.add_page_break() for linea in contenuto.split("\n"): if linea.startswith("## "): documento.add_heading(linea.replace("## ", ""), level=2) else: paragrafo = documento.add_paragraph(linea) if paragrafo.runs: paragrafo.runs[0].font.size = Pt(12) nome_file = trova_nome_libero("libro_formattato", ".docx") try: documento.save(nome_file) print(f"? Documento '{nome_file}' generato con successo!") return nome_file except PermissionError: print("?? Errore: Il file è aperto, creando un nuovo nome...") nome_file = trova_nome_libero("libro_formattato_backup", ".docx") documento.save(nome_file) print(f"? Documento '{nome_file}' generato con successo!") return nome_file except Exception as e: print(f"?? Errore durante la formattazione del documento: {e}") return None def converti_in_pdf(nome_file_docx): """Converte il file .docx in PDF.""" nome_file_pdf = nome_file_docx.replace(".docx", ".pdf") try: convert(nome_file_docx, nome_file_pdf) print(f"? Conversione completata! File PDF salvato come '{nome_file_pdf}'.") return nome_file_pdf except Exception as e: print(f"?? Errore nella conversione in PDF: {e}") return None def converti_in_epub(nome_file_docx): """Converte il file .docx in EPUB.""" nome_file_epub = nome_file_docx.replace(".docx", ".epub") try: pypandoc.convert_file(nome_file_docx, "epub", outputfile=nome_file_epub) print(f"? Conversione completata! File EPUB salvato come '{nome_file_epub}'.") return nome_file_epub except Exception as e: print(f"?? Errore nella conversione in EPUB: {e}") return None # =============================== # Interfaccia Grafica (Tkinter) # =============================== def avvia_generazione(): """Esegue la pipeline completa per la creazione del libro.""" try: # 1. Raccolta parametri parametri = raccogli_parametri_libro() if parametri is None: return # 2. Validazione parametri # ... # 3. Generazione contenuto contenuto = genera_contenuto(parametri) if contenuto is None: messagebox.showerror("Errore", "Errore durante la generazione del contenuto.") return # 4. Creazione del tensore narrativo tensore = crea_tensore_da_testo(contenuto) # 5. Generazione della narrazione basata sul tensore narrazione_generata = genera_narrazione(tensore) contenuto += "\n\n" + narrazione_generata #aggiunge la narrazione generata al contenuto esistente # 6. Salvataggio contenuto if not salva_contenuto(contenuto): messagebox.showerror("Errore", "Errore durante il salvataggio del contenuto.") return # 7. Formattazione documento nome_file_docx = formatta_documento(contenuto, parametri) if nome_file_docx is None: messagebox.showerror("Errore", "Errore durante la formattazione del documento.") return # 8. Esportazione (opzionale) if parametri['formato_output'] in ('pdf', 'epub', 'entrambi'): if parametri['formato_output'] in ('pdf', 'entrambi'): converti_in_pdf(nome_file_docx) if parametri['formato_output'] in ('epub', 'entrambi'): converti_in_epub(nome_file_docx) messagebox.showinfo("Successo", "Libro generato e formattato correttamente!") except Exception as e: messagebox.showerror("Errore", f"Si è verificato un problema: {e}") def esporta_pdf_epub(): """Avvia la conversione nei formati PDF ed EPUB.""" nome_file_docx = filedialog.askopenfilename(title="Seleziona il file .docx da convertire", filetypes=[("Word Documents", "*.docx")]) if nome_file_docx: if converti_in_pdf(nome_file_docx): messagebox.showinfo("Esportazione", "Conversione in PDF completata.") else: messagebox.showerror("Errore", "Conversione in PDF fallita.") if converti_in_epub(nome_file_docx): messagebox.showinfo("Esportazione", "Conversione in EPUB completata.") else: messagebox.showerror("Errore", "Conversione in EPUB fallita.") def genera_opere(): """Genera più opere editoriali in modo automatico.""" numero_opere = simpledialog.askinteger("Generatore Opere", "Quante opere vuoi generare?", minvalue=1, maxvalue=100) if numero_opere is None: return parametri_list = genera_parametri_casuali(numero_opere) for i, parametri in enumerate(parametri_list): print(f"\nGenerando opera {i + 1} di {numero_opere}...") contenuto = genera_contenuto(parametri) if not salva_contenuto(contenuto, f"contenuto_libro_{i+1}.txt"): print(f"Errore nel salvare il contenuto dell'opera {i+1}") continue # Creazione del tensore per ogni opera tensore = crea_tensore_da_testo(contenuto) narrazione_generata = genera_narrazione(tensore) contenuto += "\n\n" + narrazione_generata nome_file_docx = formatta_documento(contenuto, parametri) if nome_file_docx is None: print(f"Errore nella formattazione dell'opera {i+1}") continue if parametri['formato_output'] in ('pdf', 'epub', 'entrambi'): if parametri['formato_output'] in ('pdf', 'entrambi'): converti_in_pdf(nome_file_docx) if parametri['formato_output'] in ('epub', 'entrambi'): converti_in_epub(nome_file_docx) messagebox.showinfo("Generazione Opere", f"Generazione di {numero_opere} opere completata!") def avvia_revisione(): """Avvia il processo di revisione del testo (bozza).""" try: subprocess.run(["python", "revisione.py"]) except Exception as e: messagebox.showerror("Errore", f"Errore durante l'avvio della revisione: {e}") def raccogli_parametri_libro(): """Richiede all'utente di inserire i parametri del libro e li restituisce.""" parametri = { "titolo": simpledialog.askstring("Parametri Libro", "Titolo del libro:"), "lingua": simpledialog.askstring("Parametri Libro", "Lingua del libro:", initialvalue="italiano"), "genere": simpledialog.askstring("Parametri Libro", "Genere:", initialvalue="fantasy"), "stile_linguistico": simpledialog.askstring("Parametri Libro", "Stile linguistico:", initialvalue="descrittivo"), "pubblico_target": simpledialog.askstring("Parametri Libro", "Pubblico target:", initialvalue="adulti"), "lunghezza": simpledialog.askstring("Parametri Libro", "Lunghezza (parole/pagine):", initialvalue="300 pagine"), "numero_capitoli": simpledialog.askstring("Parametri Libro", "Numero di capitoli (o 'auto'):", initialvalue="15"), "tema_principale": simpledialog.askstring("Parametri Libro", "Tema/Trama centrale:", initialvalue=genera_trama()), "difficolta_linguistica": simpledialog.askstring("Parametri Libro", "Difficoltà linguistica:", initialvalue="media"), "formato_output": simpledialog.askstring("Parametri Libro", "Formato di output (docx, pdf, epub, entrambi):", initialvalue="docx"), "autore": simpledialog.askstring("Parametri Libro", "Autore:", initialvalue="Anonimo"), } if parametri["numero_capitoli"].lower() != "auto": try: int(parametri["numero_capitoli"]) except ValueError: messagebox.showerror("Errore", "Il numero di capitoli deve essere un numero intero o 'auto'.") return None return parametri # =============================== # Funzione Principale (Main) # =============================== def main