Passa al contenuto principale

Tipologie di nodi

I nodi sono i mattoni che compongono il grafo del Tree Agent.

informazioni

Ogni volta che si compila con successo un grafo tramite build o update, questo viene convertito in un file pronto per l'esecuzione. Durante questo processo, alcuni nodi, detti virtuali, vengono eliminati e le informazioni in essi contenute trasferite nel file finale. I nodi virtuali sono quelli di tipo: root, component, head, tail.

warning

Nessun nodo può mai essere figlio di più nodi, e tutti i nodi, ad eccezione di quelli virtuali root, head e tail devono sempre avere un genitore!

Per offrire la massima flessibilità, esistono diverse tipologie di nodi, ognuno dotato di un differente set di callback e di proprietà, e con una funzione di esecuzione distinta. Indipendentemente dalla loro tipologia, tutti i nodi non virtuali condividono questo set di proprietà e callback:

  • name (str): è il nome del nodo;
  • instruction (str | None): è una stringa richiamabile in fase di creazione del prompt;
  • context (str | None): è una stringa richiamabile in fase di creazione del prompt;
  • before (Callable | None): la callback before;
  • after (Callable | None): la callback after;
  • is_blocking (bool): è True se il nodo è bloccante (fase 1 dello step explore), False altrimenti (a livello grafico si ha l'icona 🔒 attiva quando la proprietà è True);
  • is_anchor (bool): è True se il nodo è un anchor (fase 2 dello step explore explore), False altrimenti (a livello grafico si ha l'icona ⚓ attiva quando la proprietà è True);
  • similarity_threshold (float | None): se specificato sovrascrive la similarità minima che si deve raggiungere in fase di explore per scendere su un nodo figlio. In caso di un query node specifica invece la similarità minima che si deve raggiungere per estrarre i chunk dal vector store.
warning

Seppure le proprietà sopra indicate siano comuni, alcune di queste potrebbero avere dei valori predefiniti per alcune tipologie di nodi, e pertanto apparire nascoste a livello di interfaccia grafica.

Root node

Callback disponibili: before_run after_run

Questo nodo virtuale viene aggiunto automaticamente durante la creazione di un nuovo albero, e non può: nè essere duplicato nè essere cancellato. Il root node è utile per specificare alcune proprietà associate all'intero albero che, come tali, non appartengono ad alcun nodo specifico.

Nell'interfaccia, tramite il nodo root è possibile specificare:

  • init (Callable | None): funzione di inizializzazione del self disponibile a tutti i nodi definiti allo stesso livello della root, quindi al di fuori di ogni componente;
  • before_run (Callable | None): callback before_run;
  • after_run (Callable | None): callback after_run;
  • default_models: dove è possibile definire il modello LLM da impiegare di default per ciascuna tipologia di nodo;
  • default_similarity_threshold: dove è possibile definire la similarità minima da raggiungere per scendere in un nodo figlio durante lo step explore;
  • memory_agent_props: le proprietà richieste dal Memory Agent.
suggerimento

Tutte le proprietà di default possono essere sovrascritte nodo per nodo tramite apposite proprietà

informazioni

L'argomento special della callback extend_message contiene:

class SimpleNamespace:
topics: str | None # i topics eventualmente inseriti tramite interfaccia grafica
conversation_goal: str | None # il conversation goal eventualmente inserito tramite interfaccia grafica
informazioni

L'argomento special della callback before_run contiene:

class SimpleNamespace:
has_state_reset: bool # diventa True quando lo stato è stato resettato rispetto all'ultima interazione per via di un avanzamento di versione con reset abilitato
informazioni

L'argomento special della callback after_run contiene le seguenti informazioni:

class SpecialLlmNodeContext:
agent_output: AgentOutput # l'oggetto di risposta del TreeAgent
run_events: List[dict] # la catena di eventi che ha portato alla risposta {node_id, type}
warning

Il root può avere solo nodi figli di tipo agent

Agent node

Callback disponibili: fallback

Tramite i nodi di tipo agent è possibile definire più agenti distinti.

warning

L'agent node deve avere come genitore il root node e avere sempre e solo un nodo figlio.

Il nodo agent ha le seguenti proprietà extra:

  • is_primary (bool): se True allora in caso di primo messaggio, in mancanza di una callback before_run che specifica un nodo da eseguire, lo step di explore sarà avviato dall'agente composto dai nodi appartenenti al sottoalbero di questo nodo;
  • role (str) è il ruolo dell'agente. Questa informazione di default sarà accessibile tramite gli argomenti delle callback prompt di tutti i nodi appartenenti all'agente;
  • fallback (Callable) funzione di fallback associata.
informazioni

Sempre e solo un nodo agent ha la proprietà is_primary = True. A livello grafico è possibile riconoscerlo perchè ha l'icona ☆ attiva

informazioni

L'argomento special delle callback fallback contiene le seguenti informazioni:

class SpecialLlmNodeContext:
error: Exception # l'errore che ha provocato l'esecuzione della fallback
node_id: int # l'id del nodo dove è avvenuto l'errore

LLM node

Callback disponibili: before after prompt response_format

Il nodo di tipo llm è utile quando si vuole richiamare un LLM per fare dei ragionamenti guidati.

Il nodo llm ha le seguenti proprietà extra:

  • model (str | None): se specificato, sovrascrive il modello LLM utilizzato di default;
  • prompt (Callable): è la callback prompt;
  • response_format (Callable | None): è la callback response_format.
informazioni

L'argomento special delle callback after e prompt nel nodo di tipo llm contiene le seguenti informazioni:

class SpecialLlmNodeContext:
prompt_obj: dict | None # l'insieme di informazioni utili per la composizione del prompt
llm_response: str # la risposta prodotta dal LLM
fail_response_format: bool | None # diventa True se è stato impostato un response_format ed il LLM ha fallito la sua applicazione per attempts volte

con prompt_obj:

{
"role": str # il ruolo definito dentro l'agent node a capo del nodo attuale
"context": List[str] # una lista che contiene, concatenati uno dopo l'altro, i contesti definiti nella catena di nodi che parte dal nodo agente e finisce nel nodo corrente
"instructions": str # le istruzioni eventualmente inserite nel nodo attuale
}

Il prompt_obj è disponibile solo quando la callback è prompt. La llm_response è disponibile solo quando la callback è after.

La fail_response_format è disponibile solo quando la callback è after e il nodo ha specificato un response_format, in caso contrario è None.

Switch node

Callback disponibili: before

Il nodo di tipo switch è una versione più specifica e ottimizzata del llm node da utilizzare in quei casi in cui si ha bisogno di eseguire un LLM per individuare il corretto nodo da eseguire.

Il nodo switch ha le seguenti proprietà extra:

  • model (str | None): se specificato, sovrascrive il modello LLM utilizzato di default;
  • alternatives: permette di indicare quali nodi eseguire in base alle descrizioni associate;

In particolare le alternatives permettono di specificare i possibili nodi da eseguire in base a delle condizioni indicate via testo. Ogni alternatives richiede le seguenti informazioni:

  • keyword: una parola chiave che descrive la condizione che attiva l'alternativa;
  • node_target: il nodo da raggiungere quando la condizione si verifica secondo la descrizione fornita;
  • step: lo step da settare quando si verifica la condizione;
  • description: condizione che il LLM deve verificare per attivare o meno quell'alternativa;
informazioni

Seguendo alternatives il framework imposta automaticamente il response_format, il prompt e la callback after.

informazioni

Oltre alle alternative personalizzate, ogni nodo switch richiede obbligatoriamente la configurazione dell'alternativa speciale FALLBACK. Questa viene attivata quando nessuna delle condizioni definite è soddisfatta, garantendo che l'esecuzione continui sempre su un nodo valido.

warning

Il sistema verifica che la risposta fornita dall'LLM rispetti il response_format indicato. Nel caso in cui:

  • il LLM seleziona la condizione associata a FALLBACK;
  • oppure il response_format viene ignorato per 2 volte consecutive;
  • oppure il LLM seleziona 0 o più di 1 opzione;

il sistema attiverà comunque l'alternativa associata a FALLBACK. È quindi importante che le alternative siano mutualmente esclusive: alternative sovrapposte aumentano il rischio di atterrare in FALLBACK.

suggerimento

Più alternatives vengono aggiunte maggiore è il rischio che il LLM fallisca nel riconoscimento di quella corretta. In caso di più di 5-6 alternative, considerare di annidarle su più livelli con 2 o più nodi in serie.

Emit node

Callback disponibili: before after prompt emit

Il nodo di tipo emit serve quando si vuole inviare un contentuo all'utente.

Un nodo di tipo emit ha le seguenti proprietà extra:

  • model (str | None): se specificato, sovrascrive il modello LLM utilizzato di default;
  • emit (Callable) callback emit;
  • prompt (Callable) callback prompt;
  • translate (bool) se abilitato traduce il testo dentro message alla lingua dell'ultimo messaggio inviato dall'utente;
warning

Il translate si applica solo quando il message è di tipo STATIC.

informazioni

L'argomento special delle callback prompt e after nel nodo di tipo emit contiene le seguenti informazioni:

class SpecialEmitNodeContext:
prompt_obj: dict | None # l'insieme di informazioni utili per la composizione del prompt (disponibile solo nella callback prompt)
original_options: List[str] # le opzioni specificate tramite callback options sempre nella lingua originale (disponibile solo nella callback after)
options: List[str] # le opzioni specificate tramite callback options o eventualmente tradotte tramite callback translate (disponibile solo nella callback after)
selected_option: str | None # l'opzione selezionata dall'utente sempre nella lingua originale (disponibile solo nella callback after)

Il campo selected_option è popolato solo dentro la callback after

informazioni

L'opzione selezionata viene automaticamente individuata facendo un controllo tra stringhe non rigido (se c'è un piccolo errore di battitura comunque viene individuata la risposta più simile). selected_option, se definito è sempre un elemento di original_options, quindi riporta la voce selezionata dall'utente in lingua originale.

warning

Visto che comunque l'utente può evitare di cliccare un'opzione e scrivere liberamente, nel caso in cui nessuna opzione sia individuata, la proprietà selected_option sarà None

Query node

Callback disponibili: before after query

Il nodo di tipo query è l'unico che permette di immagazzinare e cercare tra i chunk definiti al suo interno. Questo nodo, infatti, oltre ai chunk con proprietà for_rag = False che vengono utilizzati durante lo step explore per individuare il prossimo nodo da eseguire, può contenere i chunk con proprietà for_rag = True.

Un nodo di tipo query ha le seguenti proprietà extra:

  • query (Callable) callback query;
informazioni

L'argomento special della callback after nel nodo di tipo query contiene le seguenti informazioni:

class SpecialQueryNodeContext:
chunks: List[Chunk] # i chunk estratti dal vector store
assets: List[FileMetadata] # tutti i file presenti dentro i chunk estratti
offset: str | None # l'offset restituito in caso di scroll per richiedere la pagina successiva, è None anche quando si è raggiunto l'ultima pagina #TODO

con Chunk descritto in seguito nella sezione dedicata ai chunk e FileMetadata descritto in seguito nella sezione dedicata al File Agent:

warning

Durante lo step explore vengono considerati sia i chunk con proprietà for_rag = True che quelli con for_rag = False

Guardrail node

Callback disponibili: before after

Il nodo di tipo guardrail è un nodo privo di proprietà specifiche. L'esecuzione di questo nodo comporta l'eliminazione immediata dal database dell'ultimo messaggio dell'utente, e mostra a quest'ultimo un avviso predefinito. Il testo dell'avviso è configurabile tramite gli aspect, un meccanismo di personalizzazione della piattaforma CAITY esterno al Tree Agent.

Empty node

Callback disponibili: before after

Il nodo di tipo empty è un nodo privo di proprietà specifiche. Lo scopo di questo nodo è quello di consentire l'esecuzione delle sue callback before e after senza che venga lanciata alcun altra funzione.


Di seguito sono riportati i nodi relativi alla logica a componenti:

Component node

Il nodo virtuale di tipo component rappresenta un componente dall'esterno. Come per i nodi non virtuali, anche il nodo componente deve sempre avere un genitore.

Un nodo di tipo component ha le seguenti proprietà:

  • name (str): il nome del nodo;
  • icon (str): l'icona che si vuole associare al componente recuperata da Lucid;
informazioni

Per cambiare l'icona del nodo è sufficiente scegliere nel catalogo di lucid e copiare il nome in kebab-case

Head node

Il nodo virtuale di tipo head rappresenta sempre il primo nodo dentro un componente, di conseguenza NON ha mai alcun nodo genitore.

Un nodo di tipo head ha le seguenti proprietà:

  • init (Callable | None): funzione di inizializzazione del self disponibile a tutti i nodi definiti allo stesso livello della head, quindi all'interno del componente;
warning

Se il componente contiene altri componenti, i nodi in essi contenuti avranno un loro self distinto ed isolato.

Tail node

Il nodo virtuale di tipo tail può essere considerato come l'ultimo nodo del componente. Questo è l'unico nodo che può essere sia collegato che non; infatti la conseguenza di collegare questo nodo è quello di permettere all'esterno di associare dei nodi figli al rispettivo nodo componente. In tal caso, i nodi figli all'esterno saranno da considerarsi come collegati direttamente al genitore del nodo tail.