Menu

ReAct prompting: il ciclo ragiona e agisci

Il ReAct prompting fa alternare a un modello il ragionamento su un compito e la chiamata a uno strumento, leggendo ogni risultato prima di decidere il passo successivo. È il ciclo dietro la maggior parte degli agenti IA.

Ogni prompt qui sotto è modificabile: cambialo, poi aprilo in ChatGPT, Claude o un'altra app di AI.

Il ReAct prompting è uno schema in cui un modello linguistico alterna ragionamento e azione: scrive un pensiero su cosa fare, compie un'azione come una ricerca o la chiamata a uno strumento, legge il risultato e solo allora decide il passo successivo. Il nome è l'abbreviazione di Reason + Act (ragiona e agisci) e viene da Yao et al. 2022, "ReAct: Synergizing Reasoning and Acting in Language Models". Non ha legami con React, la libreria JavaScript per costruire interfacce utente.

La maggior parte degli agenti IA che navigano, eseguono codice o modificano file usa una qualche versione di questo ciclo. Una volta che l'hai percorso a mano, il comportamento di un agente diventa molto più facile da prevedere e da debuggare.

Il ciclo Thought, Action, Observation

Un prompt ReAct chiede al modello di scrivere tre tipi di righe.

  • Thought (pensiero): il ragionamento sulla situazione attuale e sulle informazioni che mancano.
  • Action (azione): una chiamata a uno strumento in un formato fisso, come search[query], read_file[path] o finish[answer].
  • Observation (osservazione): il risultato di quell'azione. Il modello non scrive questa riga. Il tuo programma (o tu) esegue l'azione e aggiunge l'output reale alla trascrizione.

Poi l'intera trascrizione torna al modello, che scrive il Thought successivo. Il ciclo finisce quando il modello sceglie l'azione di chiusura. Il modello non esegue mai uno strumento da solo; si limita a chiederlo, e il codice intorno a lui decide se soddisfare la richiesta.

Perché ragionare e agire batte ciascuna delle due cose da sola

L'articolo ha confrontato ReAct con prompt che ragionano soltanto (chain of thought) e prompt che agiscono soltanto (chiamate a strumenti senza ragionamento scritto). Nella risposta a domande e nella verifica dei fatti con uno strumento di ricerca su Wikipedia, il solo ragionamento spesso costruiva un argomento sicuro di sé su un fatto che il modello si era inventato, mentre ReAct poteva andare a cercare il fatto, e i risultati migliori nella risposta a domande sono arrivati combinando ReAct con il chain of thought, passando dall'uno all'altro quando il primo non dava una risposta sicura. Il solo agire faticava a scomporre l'obiettivo e a mettere insieme ciò che trovava in una risposta; i pensieri scritti tenevano il piano in vista. In due compiti interattivi, un gioco testuale di faccende domestiche e un sito di shopping simulato, ReAct con uno o due esempi nel prompt ha fatto meglio dei sistemi addestrati con cui gli autori l'hanno confrontato.

La lezione generale: il chain of thought aiuta un modello a pianificare, gli strumenti gli danno i fatti, e nessuno dei due basta per un compito che richiede entrambe le cose.

Un agente ReAct, turno per turno

Il blocco qui sotto è un piccolo agente di programmazione con due strumenti. Ogni scheda è la stessa conversazione un passo dopo: le righe Observation sono ciò che il programma ha incollato dopo aver eseguito l'azione precedente. Le etichette Thought, Action e Observation restano in inglese perché sono il formato che cerca il codice in fondo alla pagina. Leggi le risposte in ordine.

System prompt
Risolvi il compito ripetendo Thought, Action e Observation. Thought: ragiona su ciò che sai e su cosa fare dopo. Action: esattamente una tra run_tests[path] esegue pytest su un file e restituisce l'output read_file[path] restituisce il contenuto di un file finish[answer] chiude il compito con la tua risposta Scrivi un Thought e un'Action, poi fermati. L'Observation ti verrà fornita.
Compito: tests/test_cart.py ha iniziato a fallire dopo il merge di ieri. Trova la causa.
Try it
Chat apps receive the system prompt as the start of your message, so this tries its wording, not its priority. To test it as standing instructions, put it in the app's custom instructions or the API's system field.
Example replyReplies vary between models and runs.

Thought: Non so quale test fallisce né come. Eseguire i test mi mostrerà l'asserzione esatta prima di leggere qualsiasi codice. Action: run_tests[tests/test_cart.py]

Nota due cose. La prima azione è un'esecuzione dei test, non un'ipotesi: il modello ha raccolto prove prima di leggere il codice. E ogni pensiero si riferisce all'ultima osservazione, che è proprio ciò che il chain of thought non può fare.

Prova ReAct in un'app di chat

Non ti serve codice per vedere il ciclo. In ChatGPT, Claude o Gemini puoi fare tu da strumento: il modello chiede un'azione, tu la esegui e incolli il risultato.

Fai da strumenti per il modello
Fill in
Voglio rispondere a questa domanda: Perché la ventola del mio portatile fa tanto rumore anche quando non sto facendo niente? Aiutami lavorando in un ciclo. Ogni risposta contiene esattamente un Pensiero (cosa sai finora e cosa manca) e un'Azione: una cosa precisa che devo controllare, eseguire o cercare, con i passaggi esatti. Poi fermati e aspetta. Ti risponderò con il risultato come "Osservazione: ...". Quando hai prove sufficienti, rispondi con "Risposta:" e la tua conclusione. Non tirare a indovinare una risposta prima di avere delle prove.
Try it
Example replyReplies vary between models and runs.

Pensiero: Una ventola rumorosa a riposo di solito significa che qualcosa sta usando la CPU in background, oppure che la ventola fatica a raffreddare (polvere, prese d'aria ostruite). Controllare prima l'uso della CPU separa questi due casi.

Azione: Apri Gestione attività (Ctrl+Shift+Esc su Windows) o Monitoraggio Attività (Applicazioni > Utility su un Mac). Ordina i processi per CPU, aspetta 30 secondi e dimmi i primi tre processi con le loro percentuali di CPU.

Le stesse istruzioni, con una funzione reale dietro ogni azione, sono un agente.

Un ciclo ReAct minimo in Python

Nel codice, il programma invia la trascrizione, trova la riga Action nella risposta, esegue la funzione corrispondente, aggiunge l'Observation e ripete. Questo abbozzo usa l'SDK Python di OpenAI e il prompt di sistema dell'agente di programmazione qui sopra.

import re
import subprocess
from pathlib import Path
from openai import OpenAI

client = OpenAI()
MODEL = "your-model-id"  # e.g. from your provider's model list
PROJECT = Path.cwd().resolve()
READABLE = {".py", ".md", ".txt", ".toml", ".cfg"}

def inside_project(arg):
    # The model chooses arg: resolve it and refuse anything outside the project.
    path = (PROJECT / arg).resolve()
    if not path.is_relative_to(PROJECT):
        raise ValueError(f"{arg} is outside the project")
    return path

def run_tests(arg):
    path = inside_project(arg)
    if not (path.is_file() and path.name.startswith("test_") and path.suffix == ".py"):
        raise ValueError(f"{arg} is not a test file")
    result = subprocess.run(["pytest", str(path), "-q"], capture_output=True, text=True)
    return result.stdout[-2000:]

def read_file(arg):
    path = inside_project(arg)
    if not path.is_file() or path.suffix not in READABLE:
        raise ValueError(f"{arg} is not a file this agent may read")
    return path.read_text()[:20000]

TOOLS = {"run_tests": run_tests, "read_file": read_file}

def react(task, system_prompt, max_steps=8):
    transcript = f"Task: {task}\n"
    for _ in range(max_steps):
        response = client.chat.completions.create(
            model=MODEL,
            messages=[
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": transcript},
            ],
            temperature=0,
        )
        text = response.choices[0].message.content
        match = re.search(r"Action: (\w+)\[(.*)\]", text)
        if not match:
            return text
        transcript += text[: match.end()] + "\n"
        tool, arg = match.groups()
        if tool == "finish":
            return arg
        try:
            observation = TOOLS[tool](arg) if tool in TOOLS else f"Unknown tool: {tool}"
        except Exception as error:  # a missing file becomes an observation, not a crash
            observation = f"Error: {error}"
        transcript += f"Observation:\n{observation}\n"
    return "Stopped after max_steps without an answer."

Quattro dettagli contano. La trascrizione viene tagliata subito dopo l'Action, perché a volte i modelli continuano a scrivere e si inventano da soli un'Observation. Uno strumento che fallisce (un nome di file sbagliato, per esempio) diventa un'Observation a cui il modello può reagire, invece di far crollare il ciclo. Il limite di passi ferma un modello che gira in tondo all'infinito. E l'output dei test viene accorciato, perché un log di test enorme riempirebbe la finestra di contesto; decidere cosa entra in quella finestra è context engineering.

I due strumenti controllano anche il loro argomento prima di fare qualsiasi cosa. È il modello a scegliere quell'argomento, quindi i limiti vanno messi nello strumento: inside_project rifiuta qualsiasi percorso che finisca fuori dalla cartella del progetto (trucchi con ../ compresi), run_tests accetta solo file test_*.py e read_file apre solo pochi tipi di file di codice e di testo e restituisce al massimo 20.000 caratteri, così un file .env o una chiave SSH non arrivano mai alla richiesta successiva. Eseguire pytest esegue comunque il codice del tuo progetto, quindi fai girare un agente come questo in un container o in una copia usa e getta, mai su una macchina che contiene segreti.

Le API attuali di OpenAI, Anthropic e Google offrono anche il tool calling nativo: descrivi ogni strumento con un nome e uno schema JSON, e il modello restituisce una chiamata strutturata invece di una riga Action:. Il ciclo è identico; sparisce solo l'analisi del testo.

Sicurezza in un ciclo ReAct

Un agente legge testo che non ha scritto: pagine web, file, output degli strumenti. Uno qualsiasi di questi può contenere istruzioni rivolte al modello, ed è la prompt injection. Dai a ogni strumento l'accesso minimo che gli serve (sola lettura quando possibile), chiedi a una persona di confermare qualsiasi cosa che cancelli, invii o paghi, e tratta le azioni richieste dal modello come input non affidabile da controllare, non come comandi da eseguire alla cieca.

Domande frequenti

Cos'è il ReAct prompting?

ReAct (abbreviazione di Reason + Act, ragiona e agisci) è uno schema di prompting in cui un modello linguistico scrive un breve ragionamento, poi un'azione come una ricerca o la chiamata a uno strumento, e legge il risultato prima di ragionare di nuovo. Viene da Yao et al. 2022, "ReAct: Synergizing Reasoning and Acting in Language Models". Non ha niente a che fare con la libreria JavaScript React.

Cosa sono Thought, Action e Observation in ReAct?

Un Thought (pensiero) è il ragionamento del modello su cosa fare dopo. Un'Action (azione) è la chiamata a uno strumento in un formato fisso, per esempio search[python 3.13 release notes]. L'Observation (osservazione) è l'output dello strumento, che il tuo programma ottiene eseguendo l'azione e aggiunge al prompt. Il ciclo si ripete finché il modello esegue un'azione di chiusura con la sua risposta.

Che differenza c'è tra ReAct e chain of thought?

Il chain of thought ragiona a partire da ciò che il modello sa già, quindi un fatto sbagliato all'inizio della catena resta sbagliato. ReAct alterna il ragionamento ad azioni che recuperano informazioni reali, così il modello può verificare un fatto, vedere un test fallire o leggere un file prima di continuare. L'articolo su ReAct ha rilevato che ancorare il ragionamento ai risultati di ricerca riduceva i fatti inventati che il solo chain of thought produceva.

Gli agenti IA usano ancora ReAct?

Il ciclo sì. La maggior parte degli agenti di oggi ragiona, chiama uno strumento, legge il risultato e decide di nuovo, e questo è il ciclo ReAct. È cambiato il formato: invece di estrarre righe Action: dal testo, le API attuali hanno il tool calling nativo, in cui il modello restituisce una richiesta strutturata di uno strumento e il tuo codice rimanda indietro il risultato.

Posso usare ReAct in ChatGPT senza programmare?

Sì, facendo tu da strumento. Chiedi al modello di rispondere con un Thought e un'Action e poi fermarsi. Tu esegui l'azione (cerchi, apri un file, lanci un comando), incolli il risultato come Observation e ripeti. È lento, ma mostra esattamente come un agente decide cosa fare dopo.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA