Autore:
Anna Gutowska
Ingegnere AI, Developer Advocate
IBM

In questo tutorial, implementerete il concetto di Human-in-the-Loop come meccanismo di feedback per il vostro sistema di agenti AI, creato con LangGraph e watsonx.ai. Il vostro agente sarà specializzato nella ricerca dello stato dell'arte, un caso d'uso pratico che altrimenti richiederebbe un lavoro manuale noioso. Il vostro agente utilizzerà l'API di Google Patents tramite SerpAPI per esaminare i brevetti e fornire feedback sui suggerimenti di brevetti. Il modello linguistico di grandi dimensioni (LLM) scelto sarà l'open source IBM Granite.

L'avvento dell'IA agentica ha ispirato gli sviluppatori a spostare il loro focus e i loro sforzi da semplici chatbot LLM all'automazione. La parola "automazione" di solito implica la rimozione della partecipazione umana dall'esecuzione delle attività.

Vi fidereste di un agente AI per prendere decisioni critiche per la vita, ad esempio quelle che riguardano le vostre finanze personali? Molti di noi non lo farebbero. E se un certo livello di ambiguità potesse dare all'utente finale quella fiducia mancante? Questo livello di sfumatura può presentarsi sotto forma di intervento umano, il cosiddetto Human-in-the-Loop.

Human-in-the-Loop

Human-in-the-Loop (HITL) è un modello architettonico in cui il feedback umano è richiesto per guidare il processo decisionale di un'applicazione LLM e fornire supervisione. Nel campo dell'intelligenza artificiale, HITL rappresenta la presenza di un intervento umano in una fase del flusso di lavoro AI. Questo metodo garantisce precisione, sicurezza e responsabilità.

Grazie allo stato di esecuzione persistente, gli esseri umani sono in grado di controllare e aggiornare in modo asincrono lo stato del grafo in LangGraph. Utilizzando i checkpoint di stato dopo ogni passaggio, il contesto dello stato può essere mantenuto e il flusso di lavoro messo in pausa fino alla ricezione del feedback umano.

In questo tutorial, sperimenteremo i due approcci HITL in LangGraph:

  • Interruzioni statiche: Modifica dello stato del grafo direttamente in punti predefiniti prima o dopo l'esecuzione di un nodo specifico. Questo approccio richiede che il parametro interrupt_before o interrupt_after sia impostato su un elenco di nomi di nodi durante la compilazione del grafo di stato.
  • Interruzioni dinamiche: Interruzione di un grafo e attesa di un input utente all'interno di un nodo in base allo stato attuale del grafo. Questo approccio richiede l'uso della funzione interrupt di LangGraph.

Prerequisiti

  1. Avrete bisogno di un account IBM Cloud per creare un progetto watsonx.ai.
  2. Per questo tutorial, possono essere utilizzate diverse versioni di Python. Al momento della pubblicazione, raccomandiamo di scaricare Python 3.13 come versione più recente.

Passaggi

Passaggio 1. Configurazione dell'ambiente

Anche se potete scegliere tra diversi strumenti, questo tutorial vi guiderà attraverso la configurazione di un account IBM per l'utilizzo di un Jupyter Notebook.

  • Accedete a watsonx.ai con il vostro account IBM Cloud.
  • Create un progetto watsonx.ai.
  • Potete recuperare l'ID del vostro progetto all'interno del progetto stesso. Fate clic sulla scheda Gestisci. Copiate quindi l'ID del progetto dalla sezione Dettagli della pagina Generale. Avrete bisogno di questo ID per questo tutorial.
  • Create un Jupyter Notebook.

Questo passaggio apre un ambiente Jupyter Notebook in cui potete copiare il codice da questo tutorial. In alternativa, potete scaricare questo notebook sul vostro sistema locale e caricarlo come asset nel vostro progetto watsonx.ai. Questo tutorial è disponibile anche su Github.

Passaggio 2. Configurazione di un'istanza di runtime watsonx.ai e di una chiave API.

  • Create un'istanza del servizio runtime watsonx.ai (selezionate la regione appropriata e scegliete il piano Lite, che è un'istanza gratuita).
  • Generate una chiave API.
  • Collegate l'istanza del servizio runtime watsonx.ai al progetto che avete creato in watsonx.ai.

Passaggio 3. Installazione e importazione delle librerie pertinenti e configurazione delle credenziali.

Per questo tutorial, avremo bisogno di alcune librerie e moduli. Assicuratevi di importare i seguenti pacchetti. Se non sono installati, una rapida installazione con Pip può risolvere il problema.

%pip install --quiet -U langgraph langchain-ibm langgraph_sdk langgraph-prebuilt google-search-results

Riavviate il kernel e importate i seguenti pacchetti.

import getpass
import uuid
from ibm_watsonx_ai import APIClient, Credentials
from ibm_watsonx_ai.foundation_models.moderations import Guardian
from IPython.display import Image, display
from langchain_core.messages import AnyMessage, SystemMessage, HumanMessage, AIMessage
from langchain_ibm import ChatWatsonx
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import START, END, StateGraph
from langgraph.graph.message import add_messages
from langgraph.prebuilt import tools_condition, ToolNode
from langgraph.types import interrupt, Command
from serpapi.google_search import GoogleSearch
from typing_extensions import TypedDict
from typing import Annotated

Per impostare le nostre credenziali, abbiamo bisogno di WATSONX_APIKEY e WATSONX_PROJECT_ID che avete generato nel Passaggio 1. Imposteremo anche WATSONX_URL per utilizzarlo come endpoint API.

Per accedere all'API di Google Patents, abbiamo anche bisogno di una SERPAPI_API_KEY. Potete generare una chiave gratuita accedendo al vostro account SerpApi o registrandovi.

WATSONX_APIKEY = getpass.getpass(“Please enter your watsonx.ai Runtime API key (hit enter): “)
WATSONX_PROJECT_ID = getpass.getpass(“Please enter your project ID (hit enter): “)
WATSONX_URL = getpass.getpass(“Please enter your watsonx.ai API endpoint (hit enter): “)
SERPAPI_API_KEY = getpass.getpass(“Please enter your SerpAPI API key (hit enter): “)

Prima di poter inizializzare il nostro LLM, possiamo usare la classe Credentials per incapsulare le nostre credenziali API fornite.

credentials = Credentials(url=WATSONX_URL, api_key=WATSONX_APIKEY)

Passaggio 4. Istanziazione del modello di chat

Per poter interagire con tutte le risorse disponibili nel runtime di watsonx.ai, è necessario configurare un APIClient. Qui inseriamo le nostre credenziali e il WATSONX_PROJECT_ID.

client = APIClient(credentials=credentials, project_id=WATSONX_PROJECT_ID)

In questo tutorial, utilizzeremo il wrapper ChatWatsonx per configurare il nostro modello di chat. Questo wrapper semplifica l'integrazione della chiamata agli strumenti e del concatenamento. Vi consigliamo di consultare i riferimenti API nella documentazione ufficiale di ChatWatsonx per ulteriori informazioni. Possiamo passare il nostro model_id per Granite LLM e il nostro client come parametri.

Si noti che è necessario modificare il wrapper di conseguenza se si utilizza un altro fornitore di API.

model_id = “ibm/granite-3-3-8b-instruct”
llm = ChatWatsonx(model_id=model_id, watsonx_client=client)

Passaggio 5. Definizione dello strumento di scraping dei brevetti

Gli agenti AI utilizzano strumenti per colmare le lacune informative e restituire informazioni pertinenti. Questi strumenti possono includere la ricerca web, RAG, varie API, calcoli matematici, ecc. Con l'API di Google Patents tramite SerpAPI, definiamo uno strumento per lo scraping dei brevetti. Questo strumento è una funzione che prende il termine di ricerca come argomento e restituisce i risultati di ricerca organici per i brevetti correlati. Il wrapper GoogleSearch richiede parametri come il motore di ricerca, che nel nostro caso è google_patents, il termine di ricerca e successivamente la SERPAPI_API_KEY.

def scrape_patents(search_term: str):
    """Search for patents about the topic.
    Args:
        search_term: topic to search for
    """
    params = {
        "engine": "google_patents",
        "q": search_term,
        "api_key": SERPAPI_API_KEY
    }
    search = GoogleSearch(params)
    results = search.get_dict()
    return results