Negozi e schema

Questa pagina presenta le astrazioni dell'area di memorizzazione principale e i controlli dello schema utilizzati dall'SDK di memoria dell'agente Oracle.

API negozio

Semantica scrittura negozio

Le scritture dell'area di memorizzazione mantengono una chiara separazione tra il testo memorizzato da un'applicazione e il payload utilizzato dall'area di memorizzazione per il recupero. La maggior parte delle applicazioni può utilizzare le API a livello di memoria e thread e lasciare che l'area di memorizzazione prepari le righe di ricerca necessarie per il recupero vettoriale, di parole chiave o ibrido. Le API di memorizzazione di livello inferiore espongono index_texts, index_text, embeddings e embedding per integrazioni avanzate che sanno già quale testo o vettori devono essere utilizzati per il recupero.

Pensa a ogni scrittura come a due pezzi correlati:

Se non viene fornita alcuna sostituzione di ricerca o incorporamento esplicito, l'area di memorizzazione utilizza il testo memorizzato risolto come testo di recupero. Il testo non vuoto viene messo in chunk dal negozio durante la configurazione del chunk. Testo vuoto memorizza il testo del record, ma non fornisce alcun testo di recupero.

Nella tabella seguente viene descritto come viene scelto il testo di recupero prima di considerare i payload vettoriali espliciti.

Payload di recupero a livello di negozio

Input Aggiungi() update()
index_texts o index_text omesso Ogni record utilizza il valore contents risolto per il recupero. Per il recupero viene utilizzato un valore text sostitutivo. Se viene omesso anche text, gli aggiornamenti di solo incorporamento riutilizzano le righe di testo di recupero esistenti del record.
Voce stringa index_texts o stringa index_text La stringa sostituisce il testo di recupero per il record. Il negozio può eseguire il chunk prima di scrivere le righe di recupero. La stringa sostituisce il testo di recupero per il record. Il negozio può eseguire il chunk prima di scrivere le righe di recupero.
list[str] index_texts voce o list[str] index_text L'elenco viene considerato come blocchi di proprietà del chiamante. Ogni stringa non vuota viene scritta come una riga di recupero e il negozio non la raggruppa di nuovo. L'elenco viene considerato come blocchi di proprietà del chiamante. Ogni stringa non vuota viene scritta come una riga di recupero e il negozio non la raggruppa di nuovo.
None index_texts voce o index_text=None None nell'elenco esterno index_texts significa "utilizzare il contenuto memorizzato per questo record". index_text=None cancella le righe di recupero lasciando invariato il testo memorizzato, a meno che non venga fornito anche text.
Stringa vuota o elenco chunk vuoto Memorizza il testo del record e non fornisce alcun testo di recupero per tale record. Aggiorna il testo del record quando viene fornito text e cancella il testo di recupero per tale record.

Le integrazioni esplicite sono facoltative. Quando vengono omessi, l'area di memorizzazione ricava vettori locali dal testo di recupero quando è configurata la memorizzazione vettoriale locale; le aree di memorizzazione per parola chiave o ibride possono anche utilizzare righe di recupero solo testo. Quando vengono forniti valori embeddings o embedding espliciti, l'area di memorizzazione scrive tali vettori direttamente e non ne chiama l'incorporatore per tali vettori.

In add(), embeddings=None si comporta come se omettesse embeddings. In update(), embedding=None è esplicito: l'archivio conserva o riscrive il testo di recupero secondo text e index_text, ma memorizza tali righe senza vettori locali. Se text e index_text vengono omessi entrambi, i vettori vengono cancellati dalle righe di recupero esistenti.

La forma vettoriale indica la quantità di proprietà del chunk che il chiamante sta assumendo:

Alcune combinazioni vengono rifiutate in modo che il testo memorizzato, il testo di recupero e i vettori non si separino. Il passaggio di text=None cancella il testo memorizzato e le righe di recupero, pertanto non può essere combinato con valori index_text o embedding non nulli. I record del profilo attore non supportano text=None. Il passaggio di index_text=None in update() significa "Cancella righe di recupero", pertanto non sono consentite incorporamenti espliciti non vuoti nella stessa chiamata. Più vettori espliciti richiedono testo chunk esplicito, a meno che l'aggiornamento non sia di sola incorporazione e le righe di recupero esistenti non forniscano già il testo chunk.

classe oracleagentmemory.core.OracleMemoryStore

Basi: IMemoryStore

Interfaccia di memorizzazione comune utilizzata da OracleAgentMemory.

Un'implementazione del negozio è responsabile della persistenza dei record di testo e dell'esecuzione di ricerche di somiglianza su di essi. Entrambi i punti di accesso sincrono e asincrono sono definiti in modo che le API di livello superiore possano esporre le superfici di sincronizzazione/asincroni corrispondenti senza duplicare la logica specifica dell'area di memorizzazione.

metodo add

Aggiungere record al negozio.

Note

Utilizzare add_batches() quando il chiamante dispone già di uno o più oggetti PendingRecordBatch.

metodo add_agent (abstract)

Aggiungere un record profilo agente.

metodo add_async (asincrono)

Aggiungere in modo asincrono record orientati alle righe al negozio.

Accetta gli stessi argomenti e restituisce gli stessi identificativi di add().

metodo add_batches

Aggiungere batch logici preparati dal chiamante all'area di memorizzazione.

Esempi

store.add_batches(
    [
        PendingRecordBatch(
            texts=["pizza batch"],
            record_type="memory",
            record_ids="mem-batch-docs",
        )
    ]
)
['mem-batch-docs']

metodo add_batches_async (asincrono)

Aggiungere in modo asincrono batch logici preparati dal chiamante all'area di memorizzazione.

Accetta gli stessi argomenti e restituisce gli stessi identificativi di add_batches().

metodo add_user (abstract)

Aggiungere un record profilo utente.

metodo delete (abstract)

Eliminare un record memorizzato in base all'identificativo.

metodo delete_thread (abstract)

Eliminare un thread e i dati memorizzati associati.

Note

Operazione a livello di negozio per la rimozione di un thread e dei record con ambito thread gestiti dal negozio. Preferire l'eliminazione dei thread quando i requisiti di conservazione richiedono l'eliminazione sia dei messaggi di origine che dei dati di memoria con ambito thread derivato, poiché le eliminazioni a livello di messaggio non implicano la rimozione di record derivati con persistenza separata.

metodo get (abstract)

Recupera un record memorizzato per tipo e identificativo.

metodo list (abstract)

Elenca i record memorizzati per un tipo di record.

metodo list_thread_messages (abstract)

Elenca la cronologia dei messaggi memorizzata per una discussione.

metodo search (abstract)

Cerca i record per somiglianza.

Esempi

store.add(
    ["Searchable abstract memory"],
    record_type="memory",
    record_ids="mem-search-abstract-docs",
)
['mem-search-abstract-docs']
store.search("Searchable", 1, record_types={"memory"})[0][0].id
'mem-search-abstract-docs'

Filtra in base a un valore di metadati scalare:

store.add(
    ["pizza release"],
    record_type="memory",
    record_ids="mem-search-meta-source-docs",
    metadata={"source": "slack"},
)
['mem-search-meta-source-docs']
any(
    record.id == "mem-search-meta-source-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"source": "slack"},
    )
)
True

Filtra in base ai metadati nidificati:

store.add(
    ["pizza review"],
    record_type="memory",
    record_ids="mem-search-meta-review-docs",
    metadata={"review": {"status": "open"}},
)
['mem-search-meta-review-docs']
any(
    record.id == "mem-search-meta-review-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"review": {"status": "open"}},
    )
)
True

Corrisponde esattamente a un valore di elenco, incluso l'ordine:

store.add(
    ["pizza tags"],
    record_type="memory",
    record_ids="mem-search-meta-tags-docs",
    metadata={"tags": ["prod", "urgent"]},
)
['mem-search-meta-tags-docs']
any(
    record.id == "mem-search-meta-tags-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"tags": ["prod", "urgent"]},
    )
)
True

Filtra quando un array di metadati contiene un valore:

any(
    record.id == "mem-search-meta-tags-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"tags": {"$array_contains": "prod"}},
    )
)
True

Combina più condizioni metadati. Un record deve soddisfare ogni chiave:

store.add(
    ["pizza rollout"],
    record_type="memory",
    record_ids="mem-search-meta-combined-docs",
    metadata={
        "source": "slack",
        "review": {"status": "open"},
        "tags": ["prod", "urgent"],
    },
)
['mem-search-meta-combined-docs']
any(
    record.id == "mem-search-meta-combined-docs"
    for record, _ in store.search(
        "pizza",
        k=5,
        metadata_filter={
            "source": "slack",
            "review": {"status": "open"},
            "tags": ["prod", "urgent"],
        },
    )
)
True

metodo search_async (asincrono)

Cercare i record in modo asincrono in base alla somiglianza semantica.

metodo update (abstract)

Aggiorna il contenuto dei record memorizzati, incorporando dati, metadati, indicatore orario o scadenza.

Area di memorizzazione Oracle DB

classe oracleagentmemory.core.OracleDBMemoryStore

Basi: OracleMemoryStore

Persistenza supportata dal database per messaggi, memorie e profili degli attori.

Creare un'area di memorizzazione Oracle DB.

Avvertenza: SchemaPolicy.CREATE_IF_NECESSARY può essere più costoso del normale avvio dell'area di memorizzazione perché potrebbe applicare DDL dello schema gestito e riscritture dei dati con il massimo sforzo prima che l'inizializzazione abbia esito positivo. Pianificare la prima apertura di uno schema gestito meno recente come operazione di migrazione o manutenzione quando tale schema può contenere più righe.

Se l'impostazione dello schema deve creare il job di rimozione dei record scaduti gestiti, ma l'utente del database non dispone del privilegio scheduler-job, l'inizializzazione avverte e continua. I messaggi e le memorie scaduti rimangono nascosti dalle letture e dalle ricerche, ma non vengono rimossi fisicamente fino a quando il job non viene creato da un utente con CREATE JOB o un privilegio scheduler equivalente.

Quando SchemaPolicy.CREATE_IF_NECESSARY crea per la prima volta un indice ibrido gestito su uno schema esistente, Oracle analizza il testo di ricerca memorizzato e crea lo stato dell'indice ibrido gestito dal modello in-database configurato. L'inizializzazione dell'area di memorizzazione attende il completamento di tale DDL, pertanto pianifica il primo upgrade ibrido come operazione di migrazione o manutenzione per schemi di grandi dimensioni. SearchIndexSyncMode controlla la manutenzione in corso dopo che l'indice esiste; non rende la prima build dell'indice asincrona.

La creazione di tale indice ibrido gestito crea anche una preferenza vectorizer DBMS_VECTOR_CHAIN denominata dallo schema gestito. La preferenza memorizza i metadati di configurazione del vectorizer leggero dal modello OracleDBEmbedder configurato. Può essere ispezionato con viste delle preferenze di Oracle Text, ad esempio CTX_USER_PREFERENCES e CTX_USER_PREFERENCE_VALUES.

metodo add

Aggiungere record all'area di memorizzazione di Oracle DB.

Esempi

store.add(
    ["Index this stored text"],
    record_type="memory",
    record_ids="mem-db-add-docs",
)
['mem-db-add-docs']
store.add(
    ["Stored text"],
    record_type="memory",
    index_texts=["Search this text"],
    record_ids="mem-db-index-text-docs",
)
['mem-db-index-text-docs']
store.add(
    ["Short-lived event"],
    record_type="memory",
    record_ids="mem-db-ttl-docs",
    timestamps="2026-01-01T12:00:00+00:00",
    ttl_days=7,
    ttl_anchor=TimeToLiveAnchor.TIMESTAMP,
)
['mem-db-ttl-docs']

metodo add_agent

Aggiungere un record profilo agente.

Note

I record profilo agente non hanno ambito. L'identificativo di record pubblico inserito è lo stesso valore passato come agent_id.

Esempi

store.add_agent("a-docs-agent", "Support assistant")
'a-docs-agent'

metodo add_async (asincrono)

Aggiungere in modo asincrono record orientati alle righe al negozio.

Accetta gli stessi argomenti e restituisce gli stessi identificativi di add().

metodo add_batches

Aggiungere batch logici preparati dal chiamante all'area di memorizzazione.

Esempi

store.add_batches(
    [
        PendingRecordBatch(
            texts=["pizza batch"],
            record_type="memory",
            record_ids="mem-batch-docs",
        )
    ]
)
['mem-batch-docs']

metodo add_batches_async (asincrono)

Aggiungere in modo asincrono batch logici preparati dal chiamante all'area di memorizzazione.

Accetta gli stessi argomenti e restituisce gli stessi identificativi di add_batches().

metodo add_user

Aggiungere un record profilo utente.

Note

I record profilo utente non hanno ambito. L'identificativo di record pubblico inserito è lo stesso valore passato come user_id.

Esempi

store.add_user("u-docs-profile", "Prefers concise answers.")
'u-docs-profile'

metodo delete

Eliminare una riga gestita e le relative righe chunk in base all'identificativo.

Note

L'operazione viene eseguita all'interno di una transazione. Quando cascade è abilitato per una destinazione di livello superiore supportata, l'eliminazione del profilo e tutte le eliminazioni figlio con ambito vengono sottoposte a commit o sottoposte a rollback insieme.

Esempi

store.add(["Delete me"], record_type="memory", record_ids="mem-delete-docs")
['mem-delete-docs']
store.delete("memory", "mem-delete-docs")
1

metodo delete_thread

Eliminare un thread e le relative righe memorizzate associate.

Note

Utilizzare questa operazione quando è necessario eseguire il cleanup a cascata con ambito thread. Nell'area di memorizzazione supportata dal database, l'eliminazione del thread rimuove la riga del thread gestito insieme alle righe di messaggio e memoria associate, oltre ai dati di ricerca gestiti per il recupero. Questa operazione è più ampia di un'eliminazione a livello di messaggio, che rimuove solo la riga del messaggio raw. L'eliminazione dei thread rimuove le righe di messaggi e memoria dipendenti insieme ai dati di recupero associati nella stessa transazione.

Esempi

store.delete_thread("c1")
0

metodo get

Recupera un record memorizzato in base all'identificativo.

Esempi

store.add(["Remember this"], record_type="memory", record_ids="mem-get-docs")
['mem-get-docs']
store.get("memory", "mem-get-docs").id
'mem-get-docs'

metodo list

Enumerare i record persistenti per un tipo di record.

Note

"user_profile" e "agent_profile" sono tipi di record senza ambito. Per questi tipi di record, thread_id, user_id e agent_id vengono ignorati e l'identità dell'attore rimane in record.id.

Esempi

store.add(
    ["First listed", "Second listed"],
    record_type="memory",
    record_ids=["mem-list-docs-1", "mem-list-docs-2"],
)
['mem-list-docs-1', 'mem-list-docs-2']
[record.id for record in store.list("memory", limit=2)]
['mem-list-docs-1', 'mem-list-docs-2']
store.add_user("u-list-docs", "Prefers concise answers.")
'u-list-docs'
any(
    record.id == "u-list-docs"
    for record in store.list("user_profile", user_id=None, limit=10)
)
True

metodo list_thread_messages

Restituisci messaggi persistenti per un thread.

Esempi

store.list_thread_messages("c1")
[]

Cerca i record per somiglianza.

Il backend di ricerca attivo dipende dal valore SearchStrategy configurato dell'area di memorizzazione. SearchStrategy.VECTOR classifica il vettore di query rispetto ai vettori di record memorizzati. SearchStrategy.HYBRID esegue query sull'indice ibrido gestito di Oracle sul testo di ricerca memorizzato e sul relativo stato dell'indice gestito. SearchStrategy.KEYWORD si classifica solo in base al testo corrispondente sul testo di ricerca memorizzato.

Esempi

store.add(
    ["pizza preference"],
    record_type="memory",
    record_ids="mem-search-docs",
    thread_ids="c-search-docs",
)
['mem-search-docs']
results = store.search(
    "pizza",
    1,
    thread_id="c-search-docs",
    exact_thread_match=True,
    record_types={"memory"},
)
results[0][0].id
'mem-search-docs'

Filtra in base a un valore di metadati scalare:

store.add(
    ["pizza release"],
    record_type="memory",
    record_ids="mem-search-meta-source-docs",
    metadata={"source": "slack"},
)
['mem-search-meta-source-docs']
any(
    record.id == "mem-search-meta-source-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"source": "slack"},
    )
)
True

Filtra in base ai metadati nidificati:

store.add(
    ["pizza review"],
    record_type="memory",
    record_ids="mem-search-meta-review-docs",
    metadata={"review": {"status": "open"}},
)
['mem-search-meta-review-docs']
any(
    record.id == "mem-search-meta-review-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"review": {"status": "open"}},
    )
)
True

Corrisponde esattamente a un valore di elenco, incluso l'ordine:

store.add(
    ["pizza tags"],
    record_type="memory",
    record_ids="mem-search-meta-tags-docs",
    metadata={"tags": ["prod", "urgent"]},
)
['mem-search-meta-tags-docs']
any(
    record.id == "mem-search-meta-tags-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"tags": ["prod", "urgent"]},
    )
)
True

Filtra quando un array di metadati contiene un valore:

any(
    record.id == "mem-search-meta-tags-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"tags": {"$array_contains": "prod"}},
    )
)
True

Combina più condizioni metadati. Un record deve soddisfare ogni chiave:

store.add(
    ["pizza rollout"],
    record_type="memory",
    record_ids="mem-search-meta-combined-docs",
    metadata={
        "source": "slack",
        "review": {"status": "open"},
        "tags": ["prod", "urgent"],
    },
)
['mem-search-meta-combined-docs']
any(
    record.id == "mem-search-meta-combined-docs"
    for record, _ in store.search(
        "pizza",
        k=5,
        metadata_filter={
            "source": "slack",
            "review": {"status": "open"},
            "tags": ["prod", "urgent"],
        },
    )
)
True

metodo search_async (asincrono)

Cercare i record in modo asincrono in base alla somiglianza semantica.

metodo update

Aggiorna il contenuto del record memorizzato, lo stato della ricerca, i metadati e i valori dell'indicatore orario.

Esempi

store.add(["Original note"], record_type="memory", record_ids="mem-update-docs")
['mem-update-docs']
store.update("memory", "mem-update-docs", text="Updated note")
1
store.get("memory", "mem-update-docs").content
'Updated note'

Strategia di ricerca

classe oracleagentmemory.core.dbsearch.SearchStrategy

Basi: Enum

Funzionamento della ricerca per le aree di memorizzazione di Oracle DB.

L'inizializzazione dell'area di memorizzazione DB utilizza la strategia selezionata per scegliere la funzionalità di ricerca dello schema gestito. La ricerca VECTOR memorizza gli incorporamenti locali. La ricerca KEYWORD memorizza il testo ricercabile e un indice di testo. HYBRID memorizza il testo ricercabile più lo stato dell'indice vettoriale ibrido gestito da Oracle. L'area di memorizzazione DB convalida questa funzionalità di schema all'avvio in modo che una strategia incompatibile non restituisca in silenzio risultati incompleti.

VECTOR
Cerca solo per somiglianza vettoriale. L'area di memorizzazione incorpora la query con l'incorporatore configurato oppure utilizza un query_vector fornito dal chiamante e classifica i record in base alla distanza dai vettori memorizzati. Utilizzare questa opzione con uno schema DB configurato per la ricerca vettoriale.
HYBRID
Cerca con l'indice ibrido gestito di Oracle. Oracle combina la corrispondenza di testo rispetto al testo di ricerca memorizzato con la classificazione vettoriale dell'indice ibrido nel database. Utilizzare questa opzione quando gli utenti possono eseguire ricerche in base al linguaggio naturale, nonché agli identificatori esatti, agli alias o ai nomi dei prodotti. Questa strategia richiede che l'embedder principale dell'area di memorizzazione sia un OracleDBEmbedder in modo che l'indice gestito e l'area di memorizzazione condividano un modello nel database.
KEYWORD
Cerca solo per parola chiave/testo corrispondente rispetto al testo di ricerca memorizzato. Questa modalità non crea incorporamenti di query locali e non richiede un incorporamento di Oracle DB. Se aperto rispetto a uno schema ibrido esistente, può utilizzare il ramo di testo di tale indice ibrido senza creare un nuovo indice ibrido. Utilizzare questa opzione quando identificatori esatti, alias, nomi di prodotti o frasi brevi devono guidare il recupero senza fusione vettoriale.

IBRIDO = "ibrido"

KEYWORD = parola chiave

VECTOR = 'vettore'

Modalità di sincronizzazione indice di ricerca

classe oracleagentmemory.core.dbsearch.SearchIndexSyncMode

Basi: Enum

Funzionamento di aggiornamento per gli indici di ricerca DB gestiti.

Questa impostazione controlla quando Oracle rende visibile il testo di ricerca nuovo o modificato per la ricerca basata sul testo supportata dal database. SearchStrategy.HYBRID utilizza l'indice vettoriale ibrido gestito di Oracle. SearchStrategy.KEYWORD utilizza un indice Oracle Text. SearchStrategy.VECTOR non utilizza questa impostazione.

ON_COMMIT
Aggiornare l'indice quando viene eseguito il commit della transazione di scrittura. Questa è la scelta predefinita e più semplice per la maggior parte delle applicazioni perché i record possono essere cercati immediatamente dopo una scrittura riuscita. Può aggiungere lavoro per scrivere transazioni perché l'indice viene mantenuto aggiornato immediatamente.
MANUAL
Non aggiornare l'indice automaticamente. È possibile che i record nuovi o aggiornati non vengano visualizzati nella ricerca per parola chiave o ibrida finché non si esegue l'operazione di sincronizzazione dell'indice lato database. Ciò è utile per i caricamenti di massa o le finestre di manutenzione in cui si desidera controllare quando vengono eseguiti i lavori di aggiornamento.
AUTO
Consenti a Oracle di aggiornare l'indice ibrido gestito in modo asincrono. Le scritture possono evitare il costo di aggiornamento immediato, ma i risultati della ricerca potrebbero rimanere in ritardo rispetto alle scritture recenti fino al completamento dell'aggiornamento in background da parte di Oracle. Questa modalità è supportata solo con SearchStrategy.HYBRID.

Avvertenza: questa impostazione controlla la manutenzione continua dopo l'esistenza dell'indice di ricerca gestito. Non rende la prima build dell'indice asincrona. La creazione di un indice ibrido gestito sul testo di ricerca memorizzata esistente può essere a esecuzione prolungata perché Oracle crea lo stato dell'indice ibrido gestito da tale testo.

AUTO = 'AUTO'

MANUAL = 'manuale'

ON_COMMIT = 'ON_COMMIT'

Time To Live

classe oracleagentmemory.core.retention.MemoryRetentionConfig

Basi: object

Impostazioni di conservazione a livello di schema per i record supportati da Oracle DB.

classe oracleagentmemory.apis.ttl.TimeToLiveAnchor

Basi: Enum

Ancoraggio utilizzato per calcolare un indicatore orario di scadenza da una durata Time To Live.

CREATED_AT
Scadenza del calcolo dall'indicatore orario di creazione del database del record. Questa è l'impostazione predefinita quando i chiamanti omettono ttl_anchor.
TIMESTAMP
Calcola la scadenza dall'indicatore orario dell'evento memorizzato del record. Utilizzare questa opzione quando un messaggio o una memoria rappresenta un evento meno recente e deve scadere in relazione all'ora dell'evento anziché all'ora di inserimento.

CREATED_AT = 'CREATED_AT'

TIMESTAMP = 'Indicatore orario'

Criterio schema

classe oracleagentmemory.core.SchemaPolicy

Basi: str, Enum

Criterio di creazione schema per le aree di memorizzazione di Oracle DB.

RICHIEDI_ESISTENTE

Verificare che lo schema gestito completo esista già e sia aggiornato. Non creare o modificare oggetti DB.

CREA_SE_EMPTY

Se non esistono oggetti gestiti, lo schema di bootstrap. Se gli oggetti esistono già, è necessario uno schema gestito completo e aggiornato.

CREA_SE_NECESSARIO

Creare gli oggetti gestiti mancanti e applicare gli aggiornamenti dello schema gestito supportati.

RICREA

Eliminare e ricreare tutti gli oggetti schema gestiti. Questo è distruttivo.