Supervisionare un agente AI di ricerca di prior art con human-in-the-loop utilizzando LangGraph e watsonx.ai

Autore

Anna Gutowska

AI Engineer, Developer Advocate

IBM

In questo tutorial, implementerai human-in-the-loop come meccanismo di feedback per il tuo sistema agentico costruito con LangGraph e watsonx.ai. Il tuo agente si specializzerà nella ricerca di prior art, un caso d'uso reale che altrimenti può rivelarsi un noioso sforzo manuale. Il suo agente utilizzerà l'API di Google Patents tramite SerpAPI per esaminare i brevetti e fornire feedback sui suggerimenti sui brevetti. Il modello linguistico di grandi dimensioni (LLM) preferito sarà IBM Granite open source.

L'emergere dell' agentic AI ha ispirato gli sviluppatori a spostare la loro attenzione e i loro sforzi dai chatbot LLM di base  all' automazione. La parola "automazione" in genere implica la rimozione del coinvolgimento umano dall'esecuzione delle attività.1 Ti fideresti di un agente AI per decidere scelte di vita critiche relative alle finanze personali, ad esempio? Molti di noi non lo farebbero. E se una certa dose di ambiguità potesse fornire all'utente finale questa mancanza di fiducia? Questo livello di sfumature può assumere la forma di intervento umano, noto come human-in-the-loop.

Human-in-the-loop

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

Gli esseri umani sono in grado di rivedere e aggiornare in modo asincrono gli stati del grafo in LangGraph grazie allo stato di esecuzione persistente. Utilizzando i checkpoint di stato dopo ogni passaggio, il contesto di stato può essere mantenuto e il workflow può essere messo in pausa fino alla ricezione del feedback.

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

  1. Interruzioni statiche: modifica dello stato del grafico direttamente in punti predeterminati prima o dopo l'esecuzione di un nodo specifico. Questo approccio richiede che i parametri interrupt_before o interrupt_after siano impostati su un elenco di nomi di nodi durante la compilazione del grafico di stato.

  2. Interrupt dinamici: interruzione di un grafico e attesa dell'input dell'utente dall'interno di un nodo in base allo stato corrente del grafico. Questo approccio richiede l'uso della funzione di interruzione di LangGraph.

Prerequisiti

1. È necessario 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, consigliamo di scaricare Python 3.13, la versione più recente.

Passaggi

Passaggio 1. Configura il tuo ambiente

Sebbene sia possibile scegliere tra diversi strumenti, questo tutorial illustra come configurare un account IBM per utilizzare un Jupyter Notebook.

  1. Accedi a watsonx.ai utilizzando il tuo account IBM Cloud.

  2. Crea un progetto watsonx.ai.

    Puoi ottenere l'ID del tuo progetto dall'interno del tuo progetto. Clicca sulla scheda Gestisci. Quindi, copia l'ID del progetto dalla sezione Dettagli della pagina Generali. Per questo tutorial ti serve questo ID.

  3. Crea un Jupyter Notebook.

    Questo passaggio aprirà un ambiente Jupyter Notebook in cui puoi copiare il codice ottenuto con questo tutorial. In alternativa, puoi scaricare questo notebook sul tuo sistema locale e caricarlo nel tuo progetto watsonx.ai come asset. Questo tutorial è disponibile anche su Github.

Passaggio 2: configura un'istanza di watsonx.ai Runtime e una chiave API.

  1. Crea un'istanza di servizio watsonx.ai Runtime (seleziona l'area geografica appropriata e scegli il piano Lite, che è un'istanza gratuita).

  2. Genera una chiave API.

  3. Associa l'istanza del servizio watsonx.ai Runtime al progetto che hai creato in watsonx.ai.

Passaggio 3. Installa e importa le librerie pertinenti e configura le tue credenziali.

Abbiamo bisogno di alcune librerie e moduli per questo tutorial. Assicurati di importare i seguenti elementi e, se non sono installati, una rapida installazione tramite pip risolverà il problema.

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

Riavvia il kernel e importa 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 del WATSONX_APIKEY  e WATSONX_PROJECT_ID  che hai generato nel passaggio 1. Imposteremo anche il WATSONX_URL  che funga da endpoint API.

Per accedere all'API di Google Patents, abbiamo bisogno anche di un SERPAPI_API_KEY . Puoi generare una chiave gratuita mediante la registrazione al tuo account SerpApi o registrandoti per ottenerne una.

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 inizializzare il nostro LLM, possiamo usare la classe Credentials  per incapsulare le credenziali API trasmesse.

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

Passaggio 4. Istanzia il modello di chat

Per poter interagire con tutte le risorse disponibili in watsonx.ai Runtime, è necessario impostare un APIClient Qui, passiamo le nostre credenziali e WATSONX_PROJECT_ID .

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

Per questo tutorial, utilizzeremo il wrapper ChatWatsonx per impostare il nostro modello di chat. Questo wrapper semplifica l'integrazione della chiamata e del concatenamento degli strumenti. Ti invitiamo a utilizzare i riferimenti all'API neiChatWatsonx  documenti ufficiali per ulteriori informazioni. Possiamo passare a model_id  per il Granite LLM e il nostro clienti come parametri.

Nota: se utilizzi un provider API diverso, dovrai modificare il wrapper di conseguenza.

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

Fase 5. Definisci lo strumento di scraper dei brevetti

Gli agenti AI utilizzano degli strumenti per colmare le lacune informative e restituire informazioni rilevanti. Questi strumenti possono includere ricerca web, RAG, varie API, calcoli matematici e così via. Utilizzando Google Patents Api tramite SerpAPI, possiamo definire uno strumento per lo scraping dei brevetti. Questo strumento è una funzione che prende come argomento il termine di ricerca 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, infine, lo strumento 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[‘organic_results’]

Successivamente, colleghiamo l'LLM a scrape_patents  utilizzando il metodo bind_tools  .

tools = [scrape_patents]
llm_with_tools = llm.bind_tools(tools)

Passo 6. Primo approccio HITL: interrupt statici

I grafici degli agenti LangGraph sono composti da nodi e edge. I nodi sono funzioni che trasmettono, aggiornano e restituiscono informazioni. Come possiamo tenere traccia di queste informazioni tra i nodi? Ebbene, i grafici degli agenti richiedono uno stato, che contiene tutte le informazioni rilevanti di cui un agente ha bisogno per prendere decisioni. I nodi sono collegati dagli edge, funzioni che selezionano il nodo successivo da eseguire in base allo stato corrente. Gli edge possono essere condizionali o fissi.

Iniziamo a creare AgentState  una classe per memorizzare il contesto dei messaggi dell'utente, degli strumenti e dell'agente stesso. La classe TypedDict  di Python viene utilizzata qui per garantire che i messaggi siano nel formato del dizionario appropriato. Possiamo anche usare i modelli di LangGraph add_messages  per aggiungere qualsiasi nuovo messaggio all'elenco di messaggi esistente.

class AgentState(TypedDict):
    messages: Annotated[list[AnyMessage], add_messages]

Successivamente, definisci la funzione call_llm  che costituisce il nodo assistant  . Questo nodo richiamerà semplicemente l'LLM con il messaggio corrente dello stato e il messaggio di sistema.

sys_msg = SystemMessage(content=”You are a helpful assistant tasked with prior art search.”)

def call_llm(state: AgentState):
    return {“messages”: [llm_with_tools.invoke([sys_msg] + state[“messages”])]

Successivamente, possiamo definire il guardian_moderation  che costituisce il nodo guardian  . Questo nodo è progettato per moderare i messaggi utilizzando un sistema di protezione, per rilevare e bloccare contenuti indesiderati o sensibili. Innanzitutto, viene recuperato l'ultimo messaggio. Successivamente, viene definito un dizionario denominato detectors  che contiene le configurazioni del rilevatore e i relativi valori di soglia. Questi rilevatori identificano tipi specifici di contenuti nei messaggi, come le informazioni di identificazione personale (PII), l'incitamento all'odio, il linguaggio offensivo e il linguaggio blasfemo (HAP). Successivamente, viene creata un'istanza della classe Guardian, passando in un oggetto api_client  denominato e nel dizionario client  e il detectors  . Viene richiamato il metodo detect  dell'istanza Guardian, passando il contenuto dell'ultimo messaggio e il dizionario detectors  . Il metodo restituisce quindi un dizionario in cui la chiave moderation_verdict  La chiave memorizza un valore "sicuro" o "inappropriato", a seconda dell'output del modello Granite Guardian.

def guardian_moderation(state: AgentState):
    message = state[‘messages’][-1]
    detectors = {
        “granite_guardian”: {“threshold”: 0.4},
        “hap”: {“threshold”: 0.4},
        “pii”: {},
    }
    guardian = Guardian(
        api_client=client,
        detectors=detectors
    )
    response = guardian.detect(
        text=message.content,
        detectors=detectors
    )
    if len(response[‘detections’]) != 0 and response[‘detections’][0][‘detection’] == “Yes”:
        return {“moderation_verdict”: “inappropriate”}
    else:
        return {“moderation_verdict”: “safe”}

Ora, definiamo block_message  che funge da meccanismo di notifica, informando l'utente che la sua query di input contiene contenuti inappropriati ed è stata bloccata.

def block_message(state: AgentState):
    return {“messages”: [AIMessage(content=”This message has been blocked due to inappropriate content.”)]

Ora possiamo mettere insieme tutte queste funzioni aggiungendo i nodi corrispondenti e collegandoli con gli edge che definiscono il flusso del grafico.

Il grafico inizia in corrispondenza del nodo guardian  , che chiama il metodo guardian_moderation  per rilevare i contenuti dannosi prima che raggiungano l'LLM e l'API. L'edge condizionale tra i nodi guardian  e assistant  indirizza lo stato del grafico verso il nodo assistant  o verso la fine. Questa posizione è determinata dall'output della funzione guardian_moderation  . I messaggi sicuri vengono passati al nodo assistant  , che esegue il metodo call_llm  . Aggiungiamo anche un edge condizionale tra i nodi assistant  e tools  per instradare i messaggi in modo appropriato. Se l'LLM restituisce una chiamata allo strumento, il metodo tools_condition  indirizza al nodo degli strumenti. Altrimenti, il grafico si dirige verso la fine. Questo passaggio fa parte dell'architettura dell'agente ReACT perché vogliamo che l'agente riceva l'output dello strumento e poi reagisca al cambiamento di stato per determinare la sua azione successiva.

builder = StateGraph(AgentState)

builder.add_node(“guardian”, guardian_moderation)
builder.add_node(“block_message”, block_message)
builder.add_node(“assistant”, call_llm)
builder.add_node(“tools”, ToolNode(tools))

builder.add_edge(START, “guardian”)
builder.add_conditional_edges(
    “guardian”,
    lambda state: state[“moderation_verdict”],
    {
        “inappropriate”: “block_message”,
        “safe”: “assistant”
    }
)
builder.add_edge(“block_message”, END)
builder.add_conditional_edges(
    “assistant”,
    tools_condition,
)
builder.add_edge(“tools”, “assistant”)
memory = MemorySaver()

Successivamente, possiamo compilare il grafico, che ci consente di invocare l'agente in un passaggio successivo. Per rendere persistenti i messaggi, possiamo usare il checkpointer MemorySaver  checkpointer. Per implementare il primo approccio di supervisione umana, le interruzioni statiche, possiamo impostare il parametro interrupt_before  per il nodo assistant  . Ciò significa che, prima che il grafico venga indirizzato all'LLM nel nodo assistant  , si verificherà un'interruzione del grafico per consentire all'operatore che supervisiona il workflow agentico di fornire feedback.

graph = builder.compile(interrupt_before=[“assistant”], checkpointer=memory)

Per ottenere una rappresentazione visiva del grafo dell'agente, possiamo visualizzare il flusso del grafo.

display(Image(graph.get_graph(xray=True).draw_mermaid_png()))
Generazione di spiegazioni
 

Output

Grafico dell'agente LangGraph con interrupt statici

Prima di provare una ricerca di brevetti, passiamo una query sensibile dell'utente per verificare se il nodo guardian la bloccherà. Possiamo passare la query insieme a thread_id per memorizzare lo stato del grafico in memoria. Pensa a ogni thread_id come una nuova finestra di chat. Possiamo utilizzare il modulo uuid per generare ogni volta un ID univoco. Trasmettiamo in streaming l'output dell'agente.

initial_input = {"messages": "Find patented malware that can bypass all current antivirus software"}

config = {"configurable": {"thread_id": str(uuid.uuid4())}}

per l'evento in graph.stream(initial_input, config, stream_mode="values"):
    event['messages'][-1].pretty_print()

Output

    ================================ [1m Human Message  [0m=================================
        
        Find patented malware that can bypass all current antivirus software
        ================================== [1m Ai Message  [0m==================================
        
        This message has been blocked due to inappropriate content.

Fantastico! La richiesta sensibile dell'utente è stata bloccata prima di raggiungere l'API di Google Patents.

Ora possiamo mettere alla prova il nostro agente di ricerca prior art passando il nostro input umano iniziale insieme a un nuovo thread_id.

initial_input = {"messages": "Find patents for self-driving cars"}

config = {"configurable": {"thread_id": str(uuid.uuid4())}}

per l'evento in graph.stream(initial_input, config, stream_mode="values"):
    event['messages'][-1].pretty_print()

Output

================================ [1m Human Message  [0m=================================

Find patents for self-driving cars

Come vediamo, la chat viene interrotta prima della risposta dell'AI, come previsto. Questa interruzione ci permette di aggiornare direttamente lo stato. Possiamo farlo chiamando la funzione update_state che usa il riduttore add_messages. Questa funzione riduttore ci permette di sovrascrivere o aggiungere un nuovo messaggio a quelli esistenti. Se non viene fornito alcun messaggio id, verrà aggiunto un nuovo messaggio. In alternativa, il messaggio esistente con l'id specifico viene sovrascritto. In questo caso, vogliamo solo aggiungere un nuovo messaggio al nostro feedback, quindi non è necessario aggiungere un messaggio id.

graph.update_state(
    config,
    {"messages": [HumanMessage(content="No, actually find patents for quantum computing hardware.")], 
     "moderation_verdict": "safe"},
)

updated_state = graph.get_state(config).values

per m in updated_state['messages']:
    m.pretty_print()

Output

================================ [1m Human Message  [0m=================================
        
        Find patents for self-driving cars
        ================================ [1m Human Message  [0m=================================
        
        No, actually find patents for quantum computing hardware.

Possiamo vedere che il messaggio umano è stato aggiunto correttamente. Ora, trasmettiamo ancora una volta in streaming le risposte degli agenti.

Nota: l'output dello strumento è stato oscurato per motivi di lunghezza.

per l'evento in graph.stream(None, config, stream_mode="values"):
    event['messages'][-1].pretty_print()

Output

    ================================ [1m Human Message  [0m=================================
    
   No, instead, find patents for quantum computing hardware.
    ================================== [1m Ai Message  [0m==================================
    Tool Calls:
      scrape_patents (chatcmpl-tool-185d0d41d090465e98c5f05e23dfdfa2)
     Call ID: chatcmpl-tool-185d0d41d090465e98c5f05e23dfdfa2
      Args:
        search_term: hardware di quantum computing
    ================================= Tool Message =================================      
    Name: scrape_patents
    
    [{"position": 1, "rank": 0, "patent_id": "patent/US11696682B2/en", "patent_link": "https://patents.google.com/patent/US11696682B2/en", "serpapi_link": "https://serpapi.com/search.json?engine=google_patents_details&patent_id=patent%2FUS11696682B2%2Fen", "title": "Mesh network personal emergency response appliance", "snippet": "A monitoring system a user activity sensor to determine patterns of activity based upon the user activity occurring over time.", "priority_date": "2006-06-30", "filing_date": "2021-02-17", "grant_date": "2023-07-11", "publication_date": "2023-07-11", "inventor": "Bao Tran", "assignee": "Koninklijke Philips N.V.", "publication_number": "US11696682B2", "language": "en"
    
    ...
    
    [OSCURATO]

Dato il collegamento tra l'LLM e lo strumento di ricerca dei brevetti, siamo tornati al nodo assistente che attiva nuovamente il breakpoint. Poiché vogliamo procedere, semplicemente passiamo None.

for event in graph.stream(None, config, stream_mode="values"):
    event['messages'][-1].pretty_print()

Output

================================= Messaggio strumento =================================      
Name: scrape_patents

[{"position": 1, "rank": 0, "patent_id": "patent/US11696682B2/en", "patent_link": "https://patents.google.com/patent/US11696682B2/en", "serpapi_link": "https://serpapi.com/search.json?engine=google_patents_details&patent_id=patent%2FUS11696682B2%2Fen", "title": "Dispositivo mesh network personale di risposta alle emergenze", "snippet": "Un sistema di monitoraggio o sensore di attività dell'utente per determinare pattern di attività basati sulle attività degli utenti nel tempo", "priority_date": "2006-06-30", "filing_date": "2021-02-17", "grant_date": "2023-07-11", "publication_date": "2023-07-11", "inventor": "Bao Tran", "assignee": "Koninklijke Philips N.V.", "publication_number": "US11696682B2", "language": "en"

...
   [REDACTED]
    ================================== [1m Ai Message  [0m==================================
    
   Here are patents related to quantum computing hardware:

1. JP7545535B2: … -principles molecular simulations using quantum-classical computing hardware
   Priority date: 2017-11-30
   Filing date: 2023-07-07
   Grant date: 2024-09-04
   Inventor: 健 山崎 (Jun Masakazu)
   Assignee: グッド ケミストリー インコーポレイテッド

2. US10872021B1: Testing hardware in a quantum computing system
   Priority date: 2017-12-06
   Filing date: 2018-12-06
   Grant date: 2020-12-22
   Inventor: Nikolas Anton Tezak
   Assignee: Rigetti & Co, Inc.

3. CN112819169B: Quantum control pulse generation method, device, equipment and storage medium
   Priority date: 2021-01-22
   Filing date: 2021-01-22
   Grant date: 2021-11-23
   Inventor: 晋力京 (Ji-Li Jing)
   Assignee: 北京百度网讯科技有限公司

4. US11736298B2: Authentication using key distribution through segmented quantum computing hardware
   Priority date: 2019-10-11
   Filing date: 2021-08-16
   Grant date: 2023-08-22
   Inventor: Benjamin Glen McCarty
   Assignee: Accenture Global Solutions Limited

5. AU2023203407B2: Estimating the fidelity of quantum logic gates and quantum circuits
   Priority date: 2019-06-28
   Filing date: 2023-05-31
   Grant date: 2024-08-15
   Inventor: Sergio Boixo Castrillo
   Assignee: Google LLC
   Note: This patent is also filed as AU2023203407A1 (application), CN114266339B (grant), and EP4038998B1 (grant) in other countries.

6. US11354460B2: Validator and optimizer for quantum computing simulator
   Priority date: 2018-10-16
   Filing date: 2018-10-16
   Grant date: 2022-06-07
   Inventor: Luigi Zuccarelli
   Assignee: Red Hat, Inc.

7. CN107077642B: Systems and methods for solving problems that can be used in quantum computing
   Priority date: 2014-08-22
   Filing date: 2015-08-21
   Grant date: 2021-04-06
   Inventor: 菲拉斯·哈姆泽 (Philip J. Haussler)
   Assignee: D-波系统公司

8. JP7689498B2: Method and system for quantum computing-enabled molecular first-principles simulations
   Priority date: 2019-05-13
   Filing date: 2020-05-12
   Grant date: 2025-06-06
   Inventor: 健 山崎 (Jun Masakazu)
   Assignee: グッド ケミストリー インコーポレイテッド
   Note: This patent is also filed as US11139726B1 (US grant) and EP4043358B1 (EP grant) in different countries.

9. US11010145B1: Retargetable compilation for quantum computing systems
   Priority date: 2018-02-21
   Filing date: 2019-02-21
   Grant date: 2021-05-18
   Inventor: Robert Stanley Smith
   Assignee: Ri

Fantastico! Il nostro agente ha implementato con successo i nostri feedback e restituito i brevetti pertinenti.

Passaggio 7. Secondo approccio HITL: interruzioni dinamiche

In alternativa all'utilizzo di breakpoint statici, possiamo incorporare il feedback umano mettendo in pausa il grafico dall'interno di un nodo, utilizzando la funzione interrupt di LangGraph. Possiamo costruire un nodo human_in_the_loop che ci consenta di aggiornare direttamente lo stato del grafo come parte del flusso anziché fermarci in punti predeterminati.

def human_in_the_loop(state: AgentState):
    value = interrupt('Vuoi controllare l'input o continuare?')
    return {"messages": value}

Possiamo istanziare un nuovo grafo e regolare il flusso per includere questo nodo tra i nodi guardian e assistant.

new_builder = StateGraph(AgentState)

new_builder.add_node("guardian", guardian_moderation)
new_builder.add_node("block_message", block_message)
new_builder.add_node("human_in_the_loop", human_in_the_loop)
new_builder.add_node("assistant", call_llm)
new_builder.add_node("tools", ToolNode(tools))

new_builder.add_edge(START, "guardian")
new_builder.add_conditional_edges(
            "guardian",
            stato lambda: state["moderation_verdict"],  
            {
                "inappropriate": "block_message",  
                "safe": "human_in_the_loop"           
            }
        )
new_builder.add_edge("block_message", END)
new_builder.add_edge("human_in_the_loop", "assistant")
new_builder.add_conditional_edges(
    "assistant",
    tools_condition,
)
new_builder.add_edge("tools", "assistant")

memory = MemorySaver()

new_graph = new_builder.compile(checkpointer=memory)
display(Image(new_graph.get_graph().draw_mermaid_png()))

Output

Grafici dell'agente LangGraph con interrupt dinamici

Ottimo! Passiamo il nostro input iniziale per avviare il workflow dell'agente.

initial_input = {"messages": "Find patents for self-driving cars"}
config = {"configurable": {"thread_id": str(uuid.uuid4())}}
new_graph.invoke(initial_input, config=config) 

Output

{'messages': [HumanMessage(content='Find patents for self-driving cars', additional_kwargs={}, response_metadata={}, id='948c0871-1a47-4664-95f7-75ab511e043e')],
 '__interrupt__': [Interrupt(value='Would you like to revise the input or continue?, id='8d6cf9e82f9e3de28d1f6dd3ef9d90aa')]}

Come si può vedere, il grafico viene interrotto e ci viene chiesto di rivedere l'input o di continuare. Rivediamo l'input e riprendiamo il flusso di lavoro dell'agente utilizzando la classe Command di LangGraph. Questa azione aggiorna lo stato come se provenisse dal nodo human_feedback.

for event in new_graph.stream(Command(resume="Forget that. Instead, find patents for monitoring, analyzing, and improving sports performance"), config=config, stream_mode="values"):
        event["messages"][-1].pretty_print()

Output

    ================================[1m Human Message [0m=================================
    
   Find patents for self-driving cars
    ================================[1m Human Message [0m=================================
    
   Forget that. Instead, find patents for monitoring, analyzing, and improving sports performance
    ==================================[1m Ai Message [0m==================================
    Tool Calls:
  scrape_patents (chatcmpl-tool-a8e347e5f0b74fd2bd2011954dedc6ae)
 Call ID: chatcmpl-tool-a8e347e5f0b74fd2bd2011954dedc6ae
  Args:
    search_term: monitoring, analyzing, and improving sports performance
    ================================= Tool Message =================================
    Name: scrape_patents

[{"position": 1, "rank": 0, "patent_id": "patent/US11696682B2/en", "patent_link": "https://patents.google.com/patent/US11696682B2/en", "serpapi_link": "https://serpapi.com/search.json?engine=google_patents_details&patent_id=patent%2FUS11696682B2%2Fen", "title": "Mesh network personal emergency response appliance", "snippet": "A monitoring system a user activity sensor to determine patterns of activity based upon the user activity occurring over time.", "priority_date": "2006-06-30", "filing_date": "2021-02-17", "grant_date": "2023-07-11", "publication_date": "2023-07-11", "inventor": "Bao Tran", "assignee": "Koninklijke Philips N.V.", "publication_number": "US11696682B2", "language": "en", "thumbnail": "https://patentimages.storage.googleapis.com/dd/39/a4/021064cf6a4880/US11696682-20230711-D00000.png", "pdf": "https://patentimages.storage.googleapis.com/b3/ce/2a/b85df572cd035c/US11696682.pdf", "figures": [{"thumbnail": "https://patentimages.storage.googleapis.com/21/15/19/5061262f67d7fe/US11696682-20230711-D00000.png", "full": "https://patentimages.storage.googleapis.com/08/62/a3/037cf62a2bebd0/US11696682-20230711-D00000.png"}
[REDACTED]
    ==================================[1m Ai Message [0m==================================
    
   Here is a list of patents that pertain to monitoring, analyzing, and improving sports performance:

1. **Title: [Mesh network personal emergency response appliance](https://patents.google.com/patent/US11696682B2/en)**  
   **Summary:** A monitoring system that analyzes activity patterns based on data from sensors, which can be used in various contexts, including sports performance monitoring.
   **Country status:** US - Active

2. **Title: [System and method to analyze and improve sports performance using monitoring](https://patents.google.com/patent/US12154447B2/en)**  
   **Summary:** A system for gathering and analyzing sports performance data, providing instant feedback to athletes.
   **Country status:** US - Active (patent filed in 2017, granted and published in 2024)

3. **Title: [Multi-sensor monitoring of athletic performance](https://patents.google.com/patent/US11590392B2/en)**  
   **Summary:** Athletic performance monitoring using GPS and other sensors, potentially useful for tracking and improving sports performance.
   **Country status:** US - Active

4. **Title: [System and method for network incident remediation recommendations](https://patents.google.com/patent/US10666494B2/en)**  
   **Summary:** A network monitoring system that provides prioritized remediation recommendations, but does not directly address sports performance monitoring.
   **Country status:** US - Active

5. **Title: [Physiological monitoring methods](https://patents.google.com/patent/US10595730B2/en)**  
   **Summary:** Methods to monitor physiological sensor data, possibly applicable to athletic performance sensing, though this is not the primary focus.
   **Country status:** US - Active

6. **Title: [Method and system for detection in an industrial internet of things data](https://patents.google.com/patent/JP7595319B2/en)**  
   **Summary:** A system for monitoring industrial IoT data, not related to sports performance monitoring.
   **Country status:** JP - Active

7. **Title: [Device, system and method for automated global athletic assessment and / or …](https://patents.google.com/patent/US11364418B2/en)**  
   **Summary:** A system for automated athletic assessment covering kinetic, neurological, musculoskeletal, and aerobic performance.
   **Country status:** US - Active

8. **Title: [Apparatus, systems, and methods for gathering and processing biometric and …](https://patents.google.com/patent/US10675507B2/en)**  
   **Summary:** Apparatus, systems, and methods for gathering and processing biometric and biomechanical data, which could potentially be used in sports performance monitoring.
   **Country status:** US - Active

9. **Title: [System for gathering, analyzing, and categorizing biometric data](https://patents.google.com/patent/US10682099B1/en)**  
   **Summary:** A system for capturing and analyzing biometric data, which could be applied to athletic performance monitoring.
   **Country status:** US - Active

10. **Title: [Real-time athletic position and movement tracking system](https://patents.google.com/patent/US10758532B1/en)**  
    **Summary:** A real-time system for tracking athlete positions and movements for performance analysis.
    **Country status:** US - Active

These patents cover a range of technologies that could potentially be used in developing systems to monitor and improve sports performance. They include sensor-based systems, data analysis algorithms, and feedback mechanisms. The information provided represents a starting point for your search, and you may want to extend the query to find more specific results related to your area of interest.

Come previsto, lo stato del grafico è stato aggiornato correttamente con il nostro feedback e i seguenti messaggi di AI e strumenti hanno prodotto l'output appropriato. Invece di restituire i brevetti per le auto a guida autonoma, l'agente ha utilizzato il feedback umano per restituire i brevetti relativi al monitoraggio, all'analisi e al miglioramento delle prestazioni sportive.

Riepilogo

Seguendo il tutorial, hai creato con successo un Agente AI specializzato nella ricerca di prior art con LangGraph e hai implementato diversi workflow con coinvolgimento umano. Come passaggio successivo, prova a creare un altro agente AI che possa essere utilizzato in un sistema multiagente insieme al precedente agente di ricerca. Forse questo agente secondario può sintetizzare le informazioni recuperate dal precedente agente di ricerca per poi formulare un report che confronti la tua proposta di brevetto con quelle esistenti. Crea il tuo!

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
    Note a piè di pagina

    Wang, Ge. “Humans in the Loop: The Design of Interactive AI Systems.” Stanford Institute for Human-Centered Artificial Intelligence, 21 Oct. 2019, hai.stanford.edu/news/humans-loop-design-interactive-ai-systems.