Skip to content
> 💻 🧠 Codice 1001 > 📑 Schede Riassuntive > > LangChain e LangGraph

LangChain e LangGraph

Lo sviluppo con i modelli linguistici di grandi dimensioni (LLM) inizia tipicamente con un semplice ciclo di richiesta-risposta. Ma non appena il compito va oltre quello di un semplice chatbot e richiede al modello di eseguire azioni reali — come integrare tools esterni, lavorare con database o accedere al file system — ci si scontra con una sfida fondamentale. L’API standard di un modello è intrinsecamente stateless (senza stato) e manca di meccanismi integrati per la gestione di logiche complesse.

Un compito apparentemente semplice come “analizza questo file, trova dati pertinenti online e genera un report” si trasforma in una complessa sfida di orchestrazione:

  • Come si gestisce lo stato e si passa il contesto tra molteplici chiamate al LLM?
  • Come si implementa una logica ciclica, in cui un agente interagisce ripetutamente con gli strumenti finché non raggiunge un obiettivo?
  • Come si standardizzano le connessioni a diversi modelli (OpenAI, Gemini, locali) e strumenti senza dover riscrivere il codice ogni volta?

LangChain e LangGraph sono stati creati per semplificare lo sviluppo di tali sistemi e fornire agli sviluppatori un approccio standardizzato a questa sfida di orchestrazione:

  • LangChain fornisce un toolkit unificato: interfacce standardizzate per i modelli, componenti per i prompt e gli strumenti.
  • LangGraph è un framework costruito su LangChain che permette di costruire la logica decisionale dell’agente come un grafo di stati, risolvendo elegantemente il problema dei cicli e delle biforcazioni.

Per comprendere meglio i loro ruoli, usiamo un’analogia.

Immagina di costruire qualcosa con i LEGO. Hai i singoli mattoncini (motori, ruote, blocchi), ma da soli sono solo pezzi. Per assemblare una macchina funzionante, hai bisogno di istruzioni e di capire come collegare questi pezzi tra loro.

Nel mondo degli agenti IA:

  • LangChain è il tuo set di mattoncini LEGO high-tech.
  • LangGraph è il manuale di istruzioni avanzato che ti permette di assemblare questi mattoncini non solo in modelli statici, ma in meccanismi dinamici e “intelligenti” capaci di prendere decisioni.

…

Analizziamo ciascuno di questi strumenti separatamente.

Parte 1: LangChain — Il toolkit per lavorare con i LLM

L’obiettivo principale di LangChain: semplificare e standardizzare l’interazione tra il tuo codice e i Modelli Linguistici di Grandi Dimensioni (LLM). Fornisce componenti pronti all’uso (“mattoncini”) per risolvere compiti comuni.

Componenti chiave di LangChain (I nostri “mattoncini”):

1. Modelli (Models)
Sono dei “wrapper” per l’interazione diretta con le reti neurali. LangChain li divide in due tipi:

  • LLMs: L’interfaccia più vecchia. Prende in input una stringa e restituisce una stringa.
    • Esempio: llm.invoke("Di che colore è il cielo?") → "Il cielo è blu."
  • ChatModels: L’interfaccia moderna e più potente. Lavora con una lista di messaggi (HumanMessage, AIMessage, SystemMessage). Questo permette al modello di comprendere meglio il contesto di una conversazione.
    • Esempio: chat.invoke([HumanMessage(content="Di che colore è il cielo?")]) → AIMessage(content="Il cielo è generalmente blu...")

LangChain unifica l’API. Non hai bisogno di imparare a lavorare separatamente con OpenAI, Gemini o un Ollama locale. Sostituisci semplicemente un oggetto come ChatOpenAI con ChatGoogleGenerativeAI o ChatOllama, e il resto del tuo codice continuerà a funzionare.

2. Prompt
Sono dei template per le tue richieste al modello. Invece di comporre manualmente il testo della richiesta ogni volta, crei un template con delle variabili.

from langchain_core.prompts import ChatPromptTemplate

template = ChatPromptTemplate.from_messages([
    ("system", "Sei un assistente utile che traduce il testo in {output_language}."),
    ("human", "{text_to_translate}")
])

prompt_value = template.invoke({"output_language": "francese", "text_to_translate": "Amo programmare."})

I prompt rendono le tue richieste riproducibili, sicure e facilmente modificabili. Separi la logica di formattazione della richiesta dalla logica di chiamata del modello.

3. Catene (Chains e il linguaggio LCEL)
Questo è il cuore del primo LangChain. Una catena è una connessione sequenziale di più componenti. Oggi, per questo si usa il LangChain Expression Language (LCEL), che assomiglia a una pipeline (|).

La catena più semplice: prompt | modello.

chain = template | get_gemini_llm()
response = chain.invoke({"output_language": "tedesco", "text_to_translate": "Ciao, mondo!"})
# response.content conterrà "Hallo, Welt!"

Le catene ti permettono di creare flussi di lavoro semplici. Ad esempio, prima ottenere dati dall’utente, poi formattare un prompt, inviarlo al modello e, infine, elaborare la risposta.

4. Parser di output (Output Parsers)
I modelli restituiscono testo, ma nelle applicazioni spesso abbiamo bisogno di dati strutturati (JSON, una lista, un numero). I parser convertono la risposta testuale “grezza” del modello nel formato desiderato.

from langchain_core.output_parsers import JsonOutputParser

# ... creiamo un prompt che chiede al modello di rispondere in formato JSON
parser = JsonOutputParser()
chain = template | get_openai_llm() | parser

# Ora chain.invoke(...) non restituirà un oggetto di testo, ma un dizionario Python (dict)

Affinché il tuo codice possa lavorare programmaticamente con il risultato. Invece di cercare di estrarre i dati necessari da una stringa, ottieni direttamente un oggetto pronto all’uso.

5. Strumenti (Tools)
Questo è ciò che dà “le mani” al modello. Uno strumento è una qualsiasi funzione che un agente può chiamare. Potrebbe essere:

  • Una ricerca su internet (TavilySearch, BraveSearch).
  • Una calcolatrice.
  • Una funzione per leggere un file dal disco.
  • Una chiamata alla tua API interna.

Un modello da solo non sa che tempo fa oggi o cosa c’è scritto nel tuo file report.docx. Gli strumenti sono l’unico modo per accedere a informazioni esterne ed eseguire azioni nel mondo reale.


Parte 2: LangGraph — L’orchestratore per creare agenti

Se LangChain è l’insieme dei pezzi, LangGraph è il sistema di controllo che decide quale pezzo usare e in quale momento.

Il problema che LangGraph risolve: Le catene classiche (chains) in LangChain sono lineari. Vanno da un punto A a un punto B. Ma i compiti reali non sono lineari. Richiedono cicli, biforcazioni e processi decisionali.

Ad esempio, un agente di ricerca deve:

  1. Comprendere la richiesta.
  2. Decidere: è necessaria una ricerca su internet?
  3. Se sì → usare lo strumento di ricerca.
  4. Analizzare i risultati.
  5. Decidere: le informazioni sono sufficienti?
  6. Se no → tornare al punto 3 con una query più precisa (questo è un ciclo).
  7. Se sì → generare la risposta finale.

Una logica così complessa non può essere descritta con una semplice catena.

L’idea centrale di LangGraph: rappresentare il lavoro di un agente come un grafo di stati (o un diagramma di flusso).

Componenti chiave di LangGraph (Elementi del diagramma di flusso):

1. Stato (State)
È la memoria centrale dell’intero processo. Di solito è un dizionario Python (TypedDict) che viene passato da un passo all’altro. Ogni passo può leggere dati da esso e scriverne di nuovi.

Esempio di stato: {"user_request": "...", "search_results": [], "final_answer": None}.

2. Nodi (Nodes)
Sono i blocchi di azione nel tuo diagramma di flusso. Ogni nodo è una funzione Python che:

  • Prende in input lo stato corrente.
  • Esegue un’azione (chiama un LLM, usa uno strumento).
  • Restituisce lo stato aggiornato.

Esempi di nodi: call_model_node, execute_tool_node, analyze_results_node.

3. Archi (Edges)
Sono le frecce che collegano i nodi. Determinano quale nodo verrà eseguito successivamente. Esistono due tipi di archi:

  • Archi normali: Collegano semplicemente il nodo A al nodo B. Dopo che A è terminato, B verrà sempre eseguito.
  • Archi condizionali (Conditional Edges): Questa è la parte più importante. Dopo il nodo A, viene eseguita una speciale funzione “router” che guarda lo stato corrente e decide dove andare dopo: al nodo B, C o D.

Esempio di arco condizionale:

  • Dopo aver chiamato il modello (il nodo agent_node), controlliamo lo stato.
  • Se nella risposta del modello c’è una chiamata a uno strumento → andiamo al nodo execute_tool_node.
  • Se non c’è una chiamata a uno strumento → andiamo al nodo finale END.

LangChain vs. LangGraph: Quando usare cosa?

CriterioLangChain (Catene LCEL)LangGraph
Caso d’uso principaleCompiti semplici e lineariCompiti complessi e ciclici (agenti)
StrutturaPipeline (A → B → C)Grafo (diagramma di flusso con biforcazioni e cicli)
Flusso di controlloDeterministico, predefinitoDinamico, determinato in fase di esecuzione
Esempio di compito1. Prendere un testo.
2. Riassumerlo.
3. Tradurlo in un’altra lingua.
1. Ricevere una domanda.
2. Cercare su internet finché non si trova una risposta.
3. Riassumere i risultati e rispondere.
AnalogiaUna catena di montaggio in una fabbricaUn team di persone che discute e prende decisioni

Mettiamo tutto insieme

  1. L’input dell’utente entra nello Stato iniziale di LangGraph.
  2. Il Nodo “Agente” riceve lo stato. All’interno di questo nodo c’è una catena LangChain (prompt | modello | parser). Il modello, usando gli Strumenti di LangChain, decide cosa fare dopo (es. “chiamare la ricerca”). La sua decisione viene scritta nello Stato.
  3. Un Arco Condizionale analizza lo stato e dirige il flusso verso il Nodo “Esecutore di Strumenti”.
  4. Questo nodo esegue la chiamata reale allo strumento (es. fa una ricerca web) e scrive il risultato di nuovo nello Stato.
  5. Il flusso torna al Nodo “Agente” (questo è un ciclo). Ora il modello vede il risultato della ricerca e prende una nuova decisione.
  6. Il ciclo si ripete finché il modello non decide che il compito è completato. A quel punto, l’Arco Condizionale dirigerà il flusso verso la fine.

Leave a Reply

Your email address will not be published. Required fields are marked *