Creazione di un agente di ragionamento ReWOO utilizzando IBM Granite

Autore

Jobit Varughese

Technical Content Writer

IBM

I modelli linguistici di grandi dimensioni (LLM) e le loro varianti avanzate, i modelli linguistici aumentati (ALM), sono diventati la spina dorsale dei moderni sistemi di intelligenza artificiale. Combinando una potente generazione di linguaggio con tecniche esterne di recupero della conoscenza come la retrieval-augmented generation (RAG), consentono il ragionamento avanzato, la risposta alle domande e l'automazione delle attività in diversi domini. Tuttavia, nonostante le loro notevoli capacità, questi modelli devono spesso affrontare sfide come la robustezza incoerente tra i sistemi, l'elevato utilizzo di token, i tempi di risposta lenti e le inefficienze causate da prompt ripetitivi e da un contesto ridondante, quando affrontano attività complesse. Tali limitazioni aumentano i costi operativi e ostacolano la scalabilità e le prestazioni in tempo reale.

Per superare questi problemi, il framework ReWOO (ragionamento senza osservazione) offre un nuovo approccio che si concentra sul disaccoppiamento del ragionamento dal recupero di conoscenze esterne. Invece di far sì che un solo LLM cerchi di ragionare, agire e osservare in modo interlacciato, ReWOO separa queste preoccupazioni in moduli distinti, ciascuno potenzialmente alimentato da un LLM ma con un ruolo specifico. Modularizzando il processo in fasi distinte di pianificazione, raccolta delle prove e sintesi, ReWOO migliora l'efficienza e la precisione dei token. Inoltre, semplifica il debug del sistema e consente workflow AI più snelli ed efficaci.

La metodologia alla base di ReWOO

Il flusso di lavoro di ReWOO ruota attorno a tre componenti chiave: ragionamento graduale, tool calling e riassunto. Questi componenti sono implementati in una struttura modulare composta da tre parti: il pianificatore, il lavoratore e il risolutore.

Pianificatore

Il pianificatore suddivide l'attività principale in una sequenza di domande secondarie mirate, creando un blueprint. Invece di chiedere all'LLM di rispondere contemporaneamente a una domanda complessa che può portare a un uso eccessivo di token e a risposte confuse, il pianificatore crea un blueprint o un roadmap. Questa suddivisione graduale guida il workflow e mantiene strutturato il processo di ragionamento.

Lavoratore

Il lavoratore chiama strumenti esterni come motori di ricerca o database per recuperare informazioni e prove pertinenti necessarie per rispondere alle domande secondarie. Utilizza l'LLM per formulare risposte chiare e concise basate esclusivamente su queste informazioni recuperate. Questa fase di osservazione esterna è tenuta separata dal processo di ragionamento per evitare inutili ripetizioni di prompt e ridurre il consumo di token.

Risolutore

Il risolutore sintetizza tutti gli insight raccolti per generare una risposta finale fresca e ben strutturata. Questa separazione modulare aiuta a garantire un ragionamento efficiente, accurato e scalabile con modelli linguistici di grandi dimensioni.

Framework come LangChain e LangGraph forniscono potenti strumenti per implementare l'architettura ReWOO utilizzando modelli di OpenAI, IBM Granite o strumenti specializzati come Serper e Tavily per la ricerca.

In questo tutorial, esplorerai come creare un agente ReWOO che esegua il compito di riassumere i contenuti. Questo agente può:

  • Suddividere un compito di alto livello in domande secondarie
  • Utilizzare la ricerca web per raccogliere il contesto pertinente per ogni domanda secondaria
  • Generare risposte utilizzando IBM Granite
  • Riassumere i risultati in una risposta finale

Questa architettura è utile per:

  • Attività di riassunto
  • Risposte a domande su conoscenze esterne
  • Ragionamento dinamico e potenziato da strumenti

Tecnologie utilizzate

Questo tutorial passo passo sfrutta tecnologie AI all'avanguardia, tra cui:

  1. IBM Granite Instruct: un potente LLM per l'insegnamento generale, ideale per gli assistenti AI in ambito aziendale e in altri settori.
  2. Transformers: una libreria Python ampiamente utilizzata che fornisce strumenti per caricare, tokenizzare ed eseguire modelli linguistici come IBM Granite. Consente l'elaborazione efficiente degli input di testo e la generazione degli output del modello.

Passaggi

Passaggio 1: configura il tuo ambiente

Questa esercitazione illustra la configurazione dell'ambiente di sviluppo locale per eseguire una pipeline di ragionamento in stile ReWOO usando Jupyter Notebook. Utilizzerai il modello linguistico IBM Granite e Serper.dev per il recupero delle ricerche web in tempo reale.

Nota: Non è richiesta alcuna GPU, ma l'esecuzione può essere più lenta nei sistemi basati su CPU. Questo passaggio apre un ambiente notebook in cui potrai incollare il codice da questo tutorial. Questo tutorial è disponibile anche su GitHub.

Passaggio 2: installa le dipendenze necessarie

Queste librerie sono necessarie per eseguire la pipeline ReWOO e interagire con strumenti esterni:

transformers: carica ed esegue il modello linguistico di grandi dimensioni IBM Granite.

torch: un framework di deep learning necessario per eseguire il modello in modo efficiente.

accelerate: ottimizza le prestazioni del modello su tutto l'hardware (opzionale).

requests: invia richieste HTTP POST ad API esterne (come Serper).

!pip install transformers accelerate torch requests

Passaggio 3: importa le librerie necessarie

In questo passaggio, importa le librerie Python necessarie per creare i componenti principali della pipeline ReWOO.

transformers.AutoTokenizer: carica il tokenizer che converte il testo in token compatibili con il modello linguistico.

transformers.AutoModelForCausalLM: carica il modello linguistico preaddestrato IBM Granite per la generazione di risposte.

transformers.pipeline: fornisce un'interfaccia di alto livello per creare rapidamente una pipeline di generazione di testo utilizzando il tokenizer e il modello.

import requests
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline

Passaggio 4: carica il modello IBM Granite e crea una pipeline di generazione del testo

In questa fase, carichiamo il modello linguistico IBM Granite e inizializziamo una pipeline di generazione di testo utilizzando la libreria transformers di Hugging Face. Esplora il modello Granite 3.2 2B Instruct su Hugging Face qui.

model_id = "ibm-granite/granite-3.2-2b-instruct": Specifica il nome del checkpoint del modello IBM Granite ospitato su Hugging Face. Questo modello è ottimizzato per attività che richiedono l'esecuzione di istruzioni.

AutoTokenizer.from_pretrained(model_id): carica il tokenizer associato al modello specificato. È responsabile della conversione del testo di input in token e della decodifica dei token di output in testo.

AutoModelForCausalLM.from_pretrained(model_id): carica il modello linguistico (Granite 3.2 2B instruct) per attività di generazione di testo quali la risposta a domande o la sintesi.

pipeline("text-generation", model=model, tokenizer=tokenizer): crea una pipeline di generazione di testo di alto livello che combina il modello e il tokenizer, facilitando la generazione di risposte dai prompt.

model_id = "ibm-granite/granite-3.2-2b-instruct"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id)
generator = pipeline("text-generation", model=model, tokenizer=tokenizer)

Passaggio 5: configura l'API Serper per il recupero delle ricerche web

In questo passaggio, definiamo una funzione che funge da lavoratore nell'architettura ReWOO. Questo lavoratore utilizza uno strumento di ricerca web, Serper.dev, per recuperare informazioni pertinenti e aggiornate da Internet per supportare il ragionamento e la generazione di risposte. Serper.dev è un'API veloce e leggera che fornisce i risultati della ricerca Google in un formato strutturato, rendendola ideale per il recupero di informazioni in tempo reale nei workflow AI.

Questa configurazione consente al sistema ReWOO di "osservare" il mondo reale interrogando fonti di conoscenza esterne prima che l'LLM prenda le decisioni finali.

Per utilizzare Serper nella pipeline ReWOO:

  1. Visita https://serper.dev e crea un account gratuito.
  2. Dopo la registrazione, accedi alla Dashboard e copia la chiave API.
  3. Nel codice, memorizza la chiave API in modo sicuro. Per ora, assegnala direttamente come mostrato di seguito:

SERPER_API_KEY = "<YOUR_API_KEY>" # Sostituisci con la chiave effettiva

Nota: non caricare mai la chiave API su archivi pubblici. Per le impostazioni di produzione o di team, usa file .env o variabili d'ambiente per mantenerla sicura.

Schermata di ReWOO

def query_serper(question, num_results=3): Definisce una funzione che accetta una domanda di ricerca e restituisce frammenti pertinenti dai primi risultati di ricerca.

payload = {"q": question, "num": num_results}: prepara il payload della query con il termine di ricerca e il numero di risultati da restituire.

risposta = requests.post(...): invia una richiesta POST all'API Serper con la query e le intestazioni.

response.raise_for_status(): genera un errore se la risposta dell'API non è valida o ha esito negativo.

snippets = [...]: estrae frammenti di testo dai risultati di ricerca organici.

return "\n".join(snippets): unisce e restituisce i frammenti come una singola stringa, che funge da contesto per il modello linguistico.

Nota: questa funzione costituisce la spina dorsale della fase di "osservazione" di ReWOO, in cui vengono raccolte prove esterne per ulteriori ragionamenti. Assicurati che la tua chiave API sia valida e non abbia limiti di velocità durante il test.

SERPER_API_KEY = "your_serper_api_key_here" # Replace with your actual key
def query_serper(question, num_results=3):
    url = "https://google.serper.dev/search"
    headers = {
            "X-API-KEY": SERPER_API_KEY,
            "Content-Type": "application/json"
}
    payload = {"q": question, "num": num_results}
    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()
    data = response.json()
    snippets = [item.get("snippet", "") for item in data.get("organic", [])]
    return "\n".join(snippets)

Passaggio 6: genera risposte informate utilizzando la funzione expert

In questo passaggio, definiamo la funzione expert(), che funge da risolutore nell'architettura ReWOO. Il risolutore sintetizza l'evidenza esterna recuperata e genera una risposta finale utilizzando il modello linguistico.

def expert(question: str) -> str: La funzione expert() accetta una domanda (stringa) e restituisce una risposta (stringa) generata dal modello Granite. Funziona effettuando ricerche sul web con Serper.dev, raccogliendo informazioni pertinenti e utilizzandole per generare una risposta chiara e completa.

context = query_serper(question): utilizza lo strumento di ricerca web Serper per recuperare informazioni pertinenti (lavoratore).

prompt = f"""...""": crea un prompt che indica al modello di rispondere utilizzando solo il contesto recuperato.

generator(...): chiama il modello Granite per generare una risposta in base al prompt di input.

for _ in range(5): questo ciclo consente al modello di generare una risposta in blocchi, fino a un massimo di 5 volte. È utile se la risposta è lunga e non può essere completata in una volta sola.

generated_text += new_text: aggiunge ogni nuovo pezzo di testo per formare la risposta completa.

if new_text.endswith(...): se la risposta sembra completa (termina con un punto, un punto interrogativo o un punto esclamativo) e contiene abbastanza parole (più di 50), interrompe il ciclo.

return generated_text.strip(): restituisce la risposta finale ripulita.

Nota: il formato del prompt è importante, poiché garantisce che il modello non produca "allucinazioni" o vada fuori tema. Deve attenersi a quanto indicato nel contesto. Limitiamo ogni blocco di generazione a 120 token per controllare la lunghezza dell'output e gestire l'utilizzo delle risorse in modo efficiente, prevenendo l'uso eccessivo dei token.

def expert(question: str) -> str:
    context = query_serper(question) # your retrieval function
    prompt = f"""You are a knowledgeable expert. Based ONLY on the context below, answer the question clearly and concisely in your own words.
Do NOT mention any sources or references.
Context:
{context}
Question: {question}
Answer:"""
    input_prompt = prompt
    generated_text = ""
    last_generated = ""
    for _ in range(5): # up to 5 chunks
        outputs = generator(
            input_prompt,
            max_new_tokens=120,
            do_sample=False,
            eos_token_id=tokenizer.eos_token_id,
            # no invalid flags like 'temperature' here
        )
        text = outputs[0]["generated_text"]
        new_text = text[len(input_prompt):].strip()
        # Stop if no new content
        if new_text == last_generated:
            break
        generated_text += new_text + " "
        input_prompt = prompt + generated_text
        last_generated = new_text
        if new_text.endswith(('.', '!', '?')) and len(generated_text.split()) > 50:
            break
    return generated_text.strip()

Passaggio 7: definisci il modulo di pianificazione

In questa fase, definiamo la funzione di pianificazione, che suddivide un ampio compito di input in domande secondarie più piccole e ben definite, un principio fondamentale del ragionamento graduale di ReWOO.

def planner(task: str): definisce una funzione denominata planner che accetta una singola attività di argomento (una stringa che descrive l'attività da eseguire).

topic = task.replace("Summarize", "").replace("the novella", "").strip(): Estrai l'argomento principale (ad esempio, il titolo o il tema) dall'attività. Pulisce l'input rimuovendo frasi di prompt comuni come "Summarize" e "the novella", quindi taglia gli spazi bianchi iniziali e finali per isolare l'argomento principale.

return [ ... ]: restituisce un elenco di domande specifiche che guidano il modulo lavoratore.

Nota: è possibile ampliare questo elenco con domande secondarie più specifiche a seconda della profondità e della natura dell'input.

def planner(task: str):
topic = task.replace("Summarize", "").replace("the novella", "").strip()
return [
f"What is the main plot related to {topic}?",
f"Who are the key characters in {topic}?",
f"What themes are explored in {topic}?"
]

Passaggio 8: definisci il riassunto finale (modulo risolutore)

In questo passaggio, definiamo la funzione final_summarizer, che funge da risolutore nella pipeline ReWOO. Questa funzione prende le risposte secondarie (prove) fornite dal lavoratore e genera un riassunto coerente appena scritto utilizzando il modello linguistico.

def final_summarizer(task: str, sub_answers: dict) -> str: definisce la funzione che riceve l'attività e le risposte secondarie originali e restituisce un riassunto conciso.

insights = "\n".join(sub_answers.values()): combina tutte le risposte in un'unica stringa separata da nuove righe da includere nel prompt.

base_prompt = f"""...""": costruisce il prompt che istruisce il modello a riassumere gli insight forniti. Guida il modello nella generazione di un nuovo riassunto basato esclusivamente sulle risposte secondarie.

max_total_tokens = 400: imposta un limite massimo per il numero di token generati per evitare output eccessivamente lunghi.

max_loops = 5: consente fino a 5 iterazioni di generazione per costruire progressivamente il riassunto.

for in range (maxloops): cicli per generare blocchi di testo utilizzando il modello linguistico.

response = generator(..., max_new_tokens=100, ...): utilizza il generatore (oggetto pipeline) per generare fino a 100 nuovi token in ogni ciclo. La modalità di campionamento (do_sample=True) consente variazioni e creatività nella risposta.

if summary.endswith(...) or total_tokens_used >= max_total_tokens: termina il ciclo se il riassunto si conclude con una punteggiatura corretta o raggiunge il limite massimo di token.

return summary.strip(): restituisce il riassunto finale rifinito, senza spazi finali.

def final_summarizer(task: str, sub_answers: dict) -> str:
    insights = "\n".join(sub_answers.values())
    base_prompt = f"""You are an expert summarizer. Based on the following insights, write a fresh, concise summary of the text. The summary must be newly written and must end in a complete sentence with proper punctuation.
Insights:
{insights}
Summary:"""
    summary = ""
    current_prompt = base_prompt
    max_total_tokens = 400
    total_tokens_used = 0
    max_loops = 5
    for _ in range(max_loops):
        response = generator(current_prompt, max_new_tokens=100, do_sample=True, top_p=0.9, eos_token_id=tokenizer.eos_token_id)
        chunk = response[0]["generated_text"][len(current_prompt):].strip()
        summary += " " + chunk
        summary = summary.strip()
        total_tokens_used += len(chunk.split())
        if summary.endswith(('.', '!', '?')) or total_tokens_used >= max_total_tokens:
            break
        # Prepare prompt for next loop
        current_prompt = base_prompt + summary
    return summary.strip()

Passaggio 9: orchestra l'agente ReWOO con la funzione risolutore

In questo passaggio, definiamo la funzione risolutore, che rappresenta la fase finale della pipeline ReWOO. Orchestra il processo completo utilizzando il pianificatore, chiamando l'esperto e generando un riassunto utilizzando final_summarizer (risolutore). L'architettura ReWOO consente il ragionamento in più fasi suddividendo l'attività principale in sottodomande utilizzando un pianificatore. Ogni domanda secondaria viene affrontata indipendentemente da un modulo expert e il riassunto finale sintetizza tutte le risposte in una risposta coerente. Questo approccio modulare consente al sistema di affrontare compiti complessi in modo più efficace.

def solver(task: str): definisce la funzione principale del controller per l'esecuzione dell'intero workflow ReWOO.

subquestions = planner(task): utilizza il pianificatore per suddividere l'attività di input in domande secondarie mirate.

ans = expert(q): per ogni domanda secondaria, chiama la funzione expert per recuperare prove basate sul web e generare una risposta pertinente. Ogni domanda secondaria generata dal pianificatore viene passata all'esperto come input dello strumento. Il modulo esperto elabora l'input utilizzando un modello linguistico. Ciò può essere visto come l'esecuzione di uno strumento per una sottoattività specifica.

answers[q] = ans: memorizza ogni risposta digitata dalla domanda corrispondente per un successivo riassunto.

final_summary = final_summarizer(task, answers): inserisce tutte le risposte raccolte nel final_summarizer per generare un riassunto chiaro e coerente.

print(final_summary) and return final_summary: visualizza e restituisce il riassunto completo dell'attività originale.

Nota: il tempo totale impiegato dalla funzione solver() può variare tra i sistemi a causa delle differenze nella velocità della CPU, nella RAM disponibile e nell'efficienza del modello su diverse configurazioni hardware. Poiché il codice utilizza una strategia di generazione in loop con un modello linguistico, i sistemi con potenza di elaborazione o memoria inferiori possono richiedere molto più tempo. Anche il recupero basato sulla rete e le grandi dimensioni dei prompt possono contribuire ai ritardi. Per migliorare le prestazioni, prendi in considerazione la possibilità di ridurre max_loops utilizzando un modello più piccolo o quantizzato, ottimizzando la pipeline del tokenizer e del generatore o eseguendo il codice in un ambiente abilitato per GPU come Google Colab o Kaggle Notebooks.

def solver(task: str):
    print(f"Planner: Breaking down '{task}' into sub-questions...\n")
    subquestions = planner(task)
    answers = {}
    for q in subquestions:
        print(f"🔎 Expert answering: {q}")
        ans = expert(q)
        print(f"➡ Answer: {ans}\n")
        answers[q] = ans
    print("=== Final Summary ===\n")
    final_summary = final_summarizer(task, answers)
    print(final_summary)
    return final_summary

Passaggio 10: esegui la pipeline ReWOO per generare il riassunto finale

In questo passaggio finale, eseguiamo l'intera pipeline ReWOO chiamando la funzione risolutore con un compito specifico.

risolutore ("Riassumi la novella La metamorfosi"): attiva l'intero processo ReWOO; pianificazione, recupero delle prove e generazione di un riassunto per l'attività di input: riassumere il set di dati di La metamorfosi.

Questo passaggio produce l'output finale e dimostra come i componenti ReWOO lavorano insieme end-to-end per un caso d'uso reale.

solver("Summarize the novella The Metamorphosis")

Risultati principali

  1. L'agente ReWOO ha scomposto con successo il compito ("Riassumi la novella La metamorfosi") in domande secondarie significative su trama, personaggi e temi, consentendo il recupero mirato delle informazioni.
  2. A ogni domanda secondaria è stata data risposta utilizzando la ricerca web in tempo reale (Serper.dev) e IBM Granite, producendo risposte pertinenti e ben strutturate che catturavano gli elementi principali del testo.
  3. La risposta finale è stata coerente, scritta sul momento e accurata, a dimostrazione di come la retrieval-augmented generation può produrre riassunti di alta qualità e simili a quelli umani per attività di analisi letteraria.

Nota: per migliorare le prestazioni e l'affidabilità della pipeline ReWOO, è importante migliorare le metriche di valutazione come la qualità del riassunto, la coerenza e la latenza di generazione. Queste metriche aiutano a valutare le prestazioni del sistema in diverse attività e configurazioni hardware. L'architettura può essere estesa integrando algoritmi intelligenti per suddividere le grandi domande in domande più piccole e ordinare le risposte più utili. Questi miglioramenti consentirebbero un ragionamento più accurato ed efficiente, ridurrebbero i tempi di generazione e migliorerebbero la qualità complessiva degli output.

Soluzioni correlate
Agenti AI per il Business

Crea, implementa e gestisci assistenti e agenti AI potenti che automatizzano workflow e processi con l'AI generativa.

    Scopri watsonx Orchestrate
    Soluzioni per agenti AI IBM

    Costruisci il futuro della tua azienda con soluzioni AI di cui puoi fidarti.

    Esplora le soluzioni basate su agenti AI
    Servizi AI di IBM Consulting

    I servizi di AI di IBM Consulting aiutano a reinventare il modo in cui le aziende lavorano con l'AI per la trasformazione.

    Esplora i servizi di intelligenza artificiale
    Prossimi passi

    Sia che tu scelga di personalizzare app e competenze precostituite o di creare e implementare servizi di agenti personalizzati utilizzando uno studio di AI, la piattaforma IBM watsonx è la soluzione che fa per te.

    Scopri watsonx Orchestrate Esplora watsonx.ai