Passa al contenuto principale

Step

Il ciclo di vita dell'esecuzione dell'albero si articola sempre in 4 step principali:

Step di esecuzione dell'albero

Explore

Lo step explore ha il compito di determinare automaticamente il prossimo nodo da eseguire. Si attiva in due specifiche casistiche: quando l'ultimo nodo eseguto non ha nessuna callback after associata, oppure quando tale funzione restituisce un oggetto BaseAfterOutput privo di node_target.

I chunk nei nodi

I chunk svolgono un ruolo centrale durante lo step explore. Durante questa fase, la navigazione si sposta verso il nodo discendente (rispetto all'ultimo eseguito) che contiene il chunk con similarità maggiore rispetto alla direction.

informazioni

Di default, la direzione, accessibile tramite l'explore_strategy corrisponde alla richiesta dell'utente.

Per questo motivo, i chunk non sono limitati ai soli nodi query, ma possono essere inseriti in tutte le altre tipologie di nodi impostando la proprietà for_rag = False. A differenza dei chunk con for_rag = True (riservati ai soli nodi query per essere aggiunti al prompt da passare al LLM), tutti gli altri chunk fungono da veri e propri "cartelli stradali" per guidare la direzione dell'esplorazione.

Step di esecuzione dell'albero

Questo meccaniscmo permette di esplorare l'albero sfruttando la correlazione semantica tra la query dell'utente ed i chunk, senza dover puntare esplicitamente a un nodo tramite la callback after. Sostituire il routing semantico con l'abuso di riferimenti espliciti ottentui tramite l'esecuzione di un LLM comporta due grandi svantaggi:

  • prestazioni: ogni chiamata ad un LLM ha un costo, e richiede tempo;
  • affidabilità: l'affidabilità di una soluzione che si basa su LLM si abbassa tanti più nodi muti vengono concatenati prima di arrivare ed eseguire il nodo effettivo. Spesso in questi casi si ha un problema di propagaizone dell'errore!

Funzionamento

In questa fase emerge il criterio di collegamento tra i nodi che compone il grafo, infatti la ricerca si articola in questo modo:

  1. Si verifica la proprietà is_blocking del nodo corrente:

    1. Se uguale a True si rimane nel nodo attuale e si passa allo step before, quindi la ricerca è conclusa;
    2. Se uguale a False la ricerca prosegue con la fase successiva;
  2. Se il nodo corrente non ha figli, allora:

    1. Se il nodo attuale è anche l'ultimo ad essere stato eseguito, allora si incrementa il fail_counter di 1 e si raggiunge il nodo ascendente con proprietà is_anchor = True più prossimo;
    2. Altrimenti si rimane nel nodo attuale e si passa allo step before, quindi la ricerca è conclusa;
  3. Viene recuperato il chunk appartenente all'albero sottostante al nodo corrente con la maggiore similarity rispetto all'embedding della stringa inserita dentro l'explore_strategy:

    1. Se la similarity è maggiore della similarity_threshold specificata nelle proprietà del nodo, allora ci si sposta nel nodo figlio il cui sottoalbero contiene il chunk individuato e si lascia lo step explore, il flusso di ricerca si ripete;
    2. Se la similarity è minore della soglia allora:
      1. Se il nodo attuale è anche l'ultimo ad essere stato eseguito, allora si incrementa il fail_counter di 1 e si raggiunge il nodo ascendente con proprietà is_anchor = True più prossimo. Viene anche aggiunto automaticamente il nodo attuale nella black_list dell'explore_strategy:;
      2. Altrimenti si rimane nel nodo attuale e si passa allo step before, quindi la ricerca è conclusa;;
informazioni

Il punto 1 si salta all'inizio dello step, altrimenti un nodo bloccante appena eseguito interromperebbe subito la ricerca.

informazioni

La similarity è un numero calcolato confrontando l'embedding della query con l'embedding di un singolo chunk. Nell'albero, come misura si utilizza la cosine similarity.

informazioni

L'explore_strategy permette di personalizzare la logica con cui viene individuato il nodo da eseguire durante lo step explore. Questo oggetto, accessibile tramite il context, contiene sia la direction ovvero il testo che viene embeddato per calcolare la similarity sia dei vincoli che possono escludere dei chunk del grafo.

Before

Lo step before segue sempre explore, oppure può essere manualmente impostato a seguito di una callback after. Lo scopo di questo step è quello di consentire l'esecuzione dell'omonima callback eventualmente associata al nodo corrente.

Execute

Durante questo step viene eseguita la funzione execute del nodo individuato tramite esplorazione, oppure esplicitamente richiesto tramite la proprietà node_target nell'output della callback after. Durante questo step, in base alla tipologia del nodo corrente posso essere eseguite azioni distinte: ad esempio nel nodo query viene fatta una ricerca nel vector store associato, oppure nel nodo llm viene fatta una richiesta al modello indicato, oppure nel nodo empty non viene fatto nulla!

informazioni

A differenza delle callback, l'esecuzione del nodo non è direttamente personalizzabile. In particolare, durante lo step execute vengono eseguite la maggior parte delle callback associate al nodo, ma l'ordine di esecuzione, ed il modo con cui vengono utilizzati i relativi output non può essere modificato.

After

Lo step after può essere eseguito a seguito di tre eventi distinti:

  • immediatamente dopo l'esecuzione dello stesso nodo, se questo ha la proprietà is_mute = True ovvero non invia alcun messaggio all'utente;
  • a seguito della risposta dell'utente se il nodo corrente ha inviato un messaggio all'utente;
  • a seguito di un altro step after se quest'ultimo ha specificato nell'output la proprietà step = Step.AFTER

Duarante questo step viene solamente lanciata la callback after del nodo se definita.

warning

Se il nodo appena eseguito ha la proprità is_mute = True, allora la funzione execute non produce alcun output per l'utente, di conseguenze non si deve attendere la risposta di quest'ultimo prima di avviare lo step after con l'esecuzione della callback associata.