• Sab. Giu 14th, 2025

Atlantis is real: Official discovery of Atlantis, language and migrations

Atlantis is the Sardo Corso Graben Horst underwater continental block submerged by the Meltwater Pulses and destroyed by a subduction zone, Capital is Sulcis

Analizzatore di testo in base a Greimas, di Luigi Usai

Spread the love
import spacy
from transformers import pipeline
import numpy as np
from collections import Counter

# Luigi Usai - https://colab.research.google.com/drive/1c9ksr1ZfaL35dAZM4GooQ_u7DvbeCeLY

# Caricamento del modello NLP di Spacy
nlp = spacy.load("it_core_news_sm")

def analyze_attanzial_roles(text):
    """
    Analizza i ruoli attanziali (Soggetto, Oggetto, Aiutante, Oppositore, Destinante, Destinatario) in un testo.

    Args:
        text (str): Il testo da analizzare.

    Returns:
        dict: Un dizionario che mappa gli elementi del testo ai ruoli attanziali.
              Esempio: {"personaggio1": "Soggetto", "obiettivo": "Oggetto", ...}
    """
    doc = nlp(text)
    # Questa è una semplificazione.  L'analisi attanziale completa è complessa e
    # richiederebbe regole euristiche o modelli di IA addestrati.
    # Qui, implementiamo una logica molto basica basata su identificazione di
    # alcuni tipi di entità e relazioni.

    attanzial_mapping = {}
    for ent in doc.ents:
        if ent.label_ in ["PER", "PERSON"]:
            if "vuole" in ent.sent.text:  # Molto semplificato: cerca "vuole" nella frase
                attanzial_mapping[ent.text] = "Soggetto"
            elif "aiuta" in ent.sent.text: # Cerca "aiuta"
                attanzial_mapping[ent.text] = "Aiutante"
            elif "ostacola" in ent.sent.text: # Cerca "ostacola"
                attanzial_mapping[ent.text] = "Oppositore"
            else:
                attanzial_mapping[ent.text] = "Personaggio"  # Ruolo di default
        elif ent.label_ in ["ORG", "PRODUCT", "EVENT"]:
            attanzial_mapping[ent.text] = "Oggetto" # Obiettivo della narrazione

    # Identificazione Destinante/Destinatario (esempio ancora più semplice)
    if "ordina" in text or "chiede" in text:
        for ent in doc.ents:
            if ent.label_ in ["PER", "PERSON"]:
                attanzial_mapping[ent.text] = "Destinante"
                break #mi fermo al primo che trovo
    if "ottiene" in text or "riceve" in text:
        for ent in doc.ents:
             if ent.label_ in ["PER", "PERSON"]:
                attanzial_mapping[ent.text] = "Destinatario"
                break
    return attanzial_mapping



def analyze_semiotic_square(text):
    """
    Analizza le opposizioni semantiche in un testo usando il Quadrato Semiotico di Greimas.

    Args:
        text (str): Il testo da analizzare.

    Returns:
        dict: Un dizionario che rappresenta l'intensità delle opposizioni semantiche.
              Esempio: {"vita_morte": 0.8, "verita_menzogna": 0.5, ...}
    """
    doc = nlp(text)
    # Anche questa è una grande semplificazione.  Il Quadrato Semiotico richiede
    # un'analisi interpretativa profonda.  Qui usiamo solo una semplice
    # analisi di frequenza di parole chiave.

    oppositions = {
        "vita_morte": 0,
        "verita_menzogna": 0,
        "ordine_disordine": 0,
    }
    keywords = {
        "vita": ["vita", "vivere", "esistenza", "nascite"],
        "morte": ["morte", "morire", "decesso", "fine"],
        "verita": ["verità", "vero", "realtà", "autentico"],
        "menzogna": ["menzogna", "falso", "bugia", "inganno"],
        "ordine": ["ordine", "regola", "struttura", "sistema"],
        "disordine": ["disordine", "caos", "anarchia", "confusione"],
    }

    for token in doc:
        for key, values in keywords.items():
            if token.lemma_ in values:
                oppositions[key] += 1

    # Normalizza i valori (esempio)
    max_count = max(oppositions.values())
    if max_count > 0:
        for key in oppositions:
            oppositions[key] /= max_count
    return oppositions



def generate_narrative(attanzial_roles, semiotic_square, lunghezza_desiderata=20):
    """
    Genera una breve narrazione basata sui ruoli attanziali e le opposizioni semantiche.

    Args:
        attanzial_roles (dict): I ruoli attanziali identificati.
        semiotic_square (dict): Le opposizioni semantiche analizzate.
        lunghezza_desiderata: Il numero di frasi desiderato (circa).

    Returns:
        str: Una narrazione generata.
    """
    # Anche questa è una semplificazione estrema.  La generazione di storie coerenti
    # richiede modelli di linguaggio ampiamente addestrati e una comprensione
    # profonda della narratologia.  Qui, implementiamo una logica molto basica
    # per dimostrare il concetto.

    personaggi = list(attanzial_roles.keys())
    if not personaggi:
        return "Non sono stati identificati personaggi sufficienti per generare una storia."

    soggetto = ""
    oggetto = ""
    destinante = ""
    destinatario = ""

    for personaggio, ruolo in attanzial_roles.items():
        if ruolo == "Soggetto":
            soggetto = personaggio
        elif ruolo == "Oggetto":
            oggetto = personaggio  # Potrebbe essere un oggetto o un obiettivo
        elif ruolo == "Destinante":
            destinante = personaggio
        elif ruolo == "Destinatario":
            destinatario = personaggio

    storia = ""
    if destinante:
        storia += f"{destinante} ha chiesto a {soggetto} di ottenere {oggetto}. "
    elif soggetto and oggetto:
        storia += f"{soggetto} voleva ottenere {oggetto}. "
    else:
        storia += f"C'era una volta, in un mondo lontano. "

    # Crea una struttura di base della storia
    azioni = ["ha viaggiato", "ha combattuto", "ha cercato", "ha scoperto"]
    ostacoli = ["un mostro", "un traditore", "una tempesta", "un enigma"]
    aiutanti = ["un amico", "un saggio", "un artefatto magico", "la fortuna"]

    for i in range(lunghezza_desiderata):
        azione = np.random.choice(azioni)
        ostacolo = np.random.choice(ostacoli)
        aiutante = np.random.choice(aiutanti)

        # Inserisci elementi basati sul quadrato semiotico
        if semiotic_square["vita_morte"] > 0.5:
            storia += "La vita era in pericolo. "
        if semiotic_square["verita_menzogna"] > 0.5:
            storia += "La verità era nascosta. "

        storia += f"{soggetto} {azione} e ha incontrato {ostacolo}. "
        storia += f"Per fortuna, {soggetto} ha trovato {aiutante}. "

    if destinatario:
        storia += f"Alla fine, {soggetto} ha dato {oggetto} a {destinatario}. "
    else:
        storia += f"Alla fine, {soggetto} ha raggiunto il suo obiettivo. "
    return storia



def integrate_greimas_into_tensor(text):
    """
    Integra l'analisi di Greimas (ruoli attanziali e quadrato semiotico) nel processo
    di creazione del Tensore Narrativo.

    Args:
        text (str): Il testo da analizzare.

    Returns:
        numpy.ndarray: Un tensore narrativo che include le dimensioni di Greimas.
    """
    doc = nlp(text)
    segments = [sent.text for sent in doc.sents]
    n_segments = len(segments)

    # Definiamo le dimensioni del tensore, includendo Greimas
    D_T = 5  # Temi
    D_L = 4  # Linguaggio e Stile
    D_Te = 3 # Tempo
    D_P = 3  # Personaggi
    D_E = 2  # Emozioni
    D_A = 6  # Ruoli Attanziali (Soggetto, Oggetto, ...)
    D_S = 3  # Quadrato Semiotico (Vita/Morte, Verità/Menzogna, ...)

    tensor_shape = (n_segments, D_T, D_L, D_Te, D_P, D_E, D_A, D_S)
    tensor = np.zeros(tensor_shape)

    sentiment_analyzer = pipeline("sentiment-analysis", model="cardiffnlp/twitter-roberta-base-sentiment-it")

    for i, segment in enumerate(segments):
        # Analisi Tematica
        themes = extract_themes(segment)
        for j, theme in enumerate(themes):
            if j < D_T:
                tensor[i, j, 0, 0, 0, 0, 0, 0] = theme

        # Analisi Linguaggio e Stile
        linguistic_features = analyze_linguistic_style(segment)
        for j, feature_value in enumerate(linguistic_features):
            if j < D_L:
                tensor[i, 0, j, 0, 0, 0, 0, 0] = feature_value

        # Analisi Temporale
        temporal_features = analyze_temporal_features(segment)
        for j, feature_value in enumerate(temporal_features):
            if j < D_Te:
                tensor[i, 0, 0, j, 0, 0, 0, 0] = feature_value

        # Analisi Personaggi
        character_features = analyze_character_evolution(segment, doc)
        for j, feature_value in enumerate(character_features):
            if j < D_P: tensor[i, 0, 0, 0, j, 0, 0, 0] = feature_value # Analisi Emozioni sentiment_result = sentiment_analyzer(segment)[0] polarity = 0 if sentiment_result["label"] == "POSITIVE": polarity = 1 elif sentiment_result["label"] == "NEGATIVE": polarity = -1 intensity = sentiment_result["score"] tensor[i, 0, 0, 0, 0, 0, 0, 0] = polarity tensor[i, 0, 0, 0, 0, 1, 0, 0] = intensity # Analisi di Greimas attanzial_roles = analyze_attanzial_roles(segment) for personaggio, ruolo in attanzial_roles.items(): # Mappa i ruoli a indici del tensore (esempio) if ruolo == "Soggetto": tensor[i, 0, 0, 0, 0, 0, 0, 0] = 1 elif ruolo == "Oggetto": tensor[i, 0, 0, 0, 0, 0, 1, 0] = 1 elif ruolo == "Aiutante": tensor[i, 0, 0, 0, 0, 0, 2, 0] = 1 elif ruolo == "Oppositore": tensor[i, 0, 0, 0, 0, 0, 3, 0] = 1 elif ruolo == "Destinante": tensor[i, 0, 0, 0, 0, 0, 4, 0] = 1 elif ruolo == "Destinatario": tensor[i, 0, 0, 0, 0, 0, 5, 0] = 1 semiotic_square = analyze_semiotic_square(segment) tensor[i, 0, 0, 0, 0, 0, 0, 0] = semiotic_square["vita_morte"] tensor[i, 0, 0, 0, 0, 0, 0, 1] = semiotic_square["verita_menzogna"] tensor[i, 0, 0, 0, 0, 0, 0, 2] = semiotic_square["ordine_disordine"] return tensor def extract_themes(text, top_n=5): """Estrae temi principali da un testo (semplificato).""" doc = nlp(text) keywords = [token.lemma_ for token in doc if not token.is_stop and token.pos_ in {"NOUN", "VERB", "ADJ"}] word_count = Counter(keywords) most_common_words = [word for word, count in word_count.most_common(top_n)] return [1/top_n] * len(most_common_words) def analyze_linguistic_style(text): """Analizza lo stile linguistico di un testo.""" doc = nlp(text) avg_sentence_length = sum(len(sent) for sent in doc.sents) / len(list(doc.sents)) if list(doc.sents) else 0 lexical_diversity = len(set(token.text for token in doc)) / len(doc) if len(doc) else 0 adj_count = sum(1 for token in doc if token.pos_ == "ADJ") / len(doc) if len(doc) else 0 passive_voice_count = sum(1 for sent in doc.sents for token in sent if token.dep_ == "auxpass") / len(list(doc.sents)) if list(doc.sents) else 0 return [avg_sentence_length, lexical_diversity, adj_count, passive_voice_count] def analyze_temporal_features(text): """Analizza le caratteristiche temporali di un testo.""" doc = nlp(text) temporal_keywords = ["poi", "dopo", "prima", "mentre", "giorno", "notte", "mattina", "sera", "anno", "mese", "settimana"] temporal_presence = sum(1 for token in doc if token.lemma_ in temporal_keywords) / len(doc) if len(doc) else 0 past_tense_count = sum(1 for token in doc if token.tag_.startswith("V")) / len(doc) if len(doc) else 0 return [temporal_presence, past_tense_count, 0] def analyze_character_evolution(text, doc): """Analizza l'evoluzione dei personaggi in un testo.""" characters = set() for token in doc.ents: if token.label_ in ["PER", "PERSON"]: characters.add(token.text) if not characters: return [0,0,0] first_character = list(characters)[0] first_char_mentions = sum(1 for token in doc if token.text == first_character) / len(doc) if len(doc) else 0 adj_near_char = 0 for i, token in enumerate(doc): if token.text == first_character: if i > 0 and doc[i-1].pos_ == "ADJ":
                adj_near_char +=1
            if i < len(doc) -1 and doc[i+1].pos_ == "ADJ":
                adj_near_char +=1
    adj_near_char = adj_near_char / len(doc) if len(doc) else 0
    return [first_char_mentions, adj_near_char, 0]



if __name__ == "__main__":
    test_text = """
    C'era una volta un re di nome Artù che governava un regno. Artù era un sovrano giusto, ma il suo regno era minacciato da un mago malvagio, Merlino, che voleva usurpare il trono.
    Merlino aveva molti seguaci e poteri oscuri. Artù, con l'aiuto dei suoi fedeli cavalieri, Lancillotto e Ginevra, cercò di fermare Merlino.
    La battaglia finale fu epica. Lancillotto combatté valorosamente, ma Merlino era troppo potente. Ginevra, con un atto di coraggio, distrusse la fonte del potere di Merlino.
    Alla fine, Artù sconfisse Merlino e il regno tornò alla pace. Artù e Ginevra si sposarono e vissero felici e contenti.
    """

    # Esempio di utilizzo delle funzioni
    attanzial_roles = analyze_attanzial_roles(test_text)
    print("Ruoli Attanziali:", attanzial_roles)

    semiotic_square = analyze_semiotic_square(test_text)
    print("Quadrato Semiotico:", semiotic_square)

    tensore_narrativo = integrate_greimas_into_tensor(test_text)
    print("Tensore Narrativo (shape):", tensore_narrativo.shape)
    print("Tensore Narrativo (esempio):", tensore_narrativo[0, :, :, 0, 0, 0, :, :]) #mostro una fetta

    generated_story = generate_narrative(attanzial_roles, semiotic_square)
    print("\nStoria Generata:\n", generated_story)