Utiliser un agent LangGraph

Avant de commencer

Ce tutoriel suppose que vous avez lu et suivi les instructions de :

Obtenir une instance d'un agent

Pour interroger un LanggraphAgent, vous devez d'abord créer une instance ou obtenir une instance existante.

Pour obtenir le LanggraphAgent correspondant à un ID de ressource spécifique :

SDK Vertex AI pour Python

Exécutez le code suivant :

import vertexai

client = vertexai.Client(  # For service interactions via client.agent_engines
    project="PROJECT_ID",
    location="LOCATION",
)

agent = client.agent_engines.get(name="projects/PROJECT_ID/locations/LOCATION/reasoningEngines/RESOURCE_ID")

print(agent)

Où :

Bibliothèque de requêtes Python

Exécutez le code suivant :

from google import auth as google_auth
from google.auth.transport import requests as google_requests
import requests

def get_identity_token():
    credentials, _ = google_auth.default()
    auth_request = google_requests.Request()
    credentials.refresh(auth_request)
    return credentials.token

response = requests.get(
f"https://LOCATION-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/reasoningEngines/RESOURCE_ID",
    headers={
        "Content-Type": "application/json; charset=utf-8",
        "Authorization": f"Bearer {get_identity_token()}",
    },
)

API REST

curl \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://LOCATION-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/reasoningEngines/RESOURCE_ID

Lorsque vous utilisez le SDK Vertex AI pour Python, l'objet agent correspond à une classe AgentEngine qui contient les éléments suivants :

  • un agent.api_resource contenant des informations sur l'agent déployé. Vous pouvez également appeler agent.operation_schemas() pour renvoyer la liste des opérations compatibles avec l'agent. Pour en savoir plus, consultez Opérations compatibles.
  • un agent.api_client qui permet des interactions de service synchrones.
  • un agent.async_api_client qui permet des interactions de service asynchrones.

Le reste de cette section suppose que vous disposez d'une instance AgentEngine nommée agent.

Opérations compatibles

Les opérations suivantes sont acceptées pour LanggraphAgent :

  • query : pour obtenir une réponse à une requête de manière synchrone.
  • stream_query : pour diffuser une réponse à une requête.
  • get_state : pour obtenir un point de contrôle spécifique.
  • get_state_history : pour lister les points de contrôle d'un thread.
  • update_state : pour créer des branches correspondant à différents scénarios.

Diffuser une réponse à une requête

LangGraph est compatible avec plusieurs modes de streaming. Voici les principaux :

  • values : ce mode diffuse l'état complet du graphique après chaque appel de nœud.
  • updates : ce mode diffuse les mises à jour de l'état du graphique après l'appel de chaque nœud.

Pour diffuser values (qui correspond à l'état complet du graphique) :

for state_values in agent.stream_query(
    input=inputs,
    stream_mode="values",
    config={"configurable": {"thread_id": "streaming-thread-values"}},
):
    print(state_values)

Pour diffuser updates (correspondant aux mises à jour de l'état du graphique) :

for state_updates in agent.stream_query(
    input=inputs,
    stream_mode="updates",
    config={"configurable": {"thread_id": "streaming-thread-updates"}},
):
    print(state_updates)

Human-in-the-loop (avec intervention humaine)

Dans LangGraph, un aspect courant de l'approche "humain dans la boucle" consiste à ajouter des points d'arrêt pour interrompre la séquence d'actions de l'agent et permettre à un humain de reprendre le flux ultérieurement.

Récapitulatif

Vous pouvez définir des points d'arrêt à l'aide des arguments interrupt_before= ou interrupt_after= lorsque vous appelez .query ou .stream_query :

from langchain.load import load as langchain_load

response = agent.query(
    input=inputs,
    interrupt_before=["tools"], # after generating the function call, before invoking the function
    interrupt_after=["tools"], # after getting a function response, before moving on
    config={"configurable": {"thread_id": "human-in-the-loop-deepdive"}},
)

langchain_load(response['messages'][-1]).pretty_print()

Le résultat ressemblera à ce qui suit :

================================== Ai Message ==================================
Tool Calls:
  get_exchange_rate (12610c50-4465-4296-b1f3-d751ec959fd5)
 Call ID: 12610c50-4465-4296-b1f3-d751ec959fd5
  Args:
    currency_from: USD
    currency_to: SEK

Approbation

Pour approuver l'appel d'outil généré et reprendre l'exécution, transmettez None à l'entrée et spécifiez le thread ou le point de contrôle dans config :

from langchain.load import load as langchain_load

response = agent.query(
    input=None,  # Continue with the function call
    interrupt_before=["tools"], # after generating the function call, before invoking the function
    interrupt_after=["tools"], # after getting a function response, before moving on
    config={"configurable": {"thread_id": "human-in-the-loop-deepdive"}},
)

langchain_load(response['messages'][-1]).pretty_print()

Le résultat ressemblera à ce qui suit :

================================= Tool Message =================================
Name: get_exchange_rate

{"amount": 1.0, "base": "USD", "date": "2024-11-14", "rates": {"SEK": 11.0159}}

Historique

Pour lister tous les points de contrôle d'un thread donné, utilisez la méthode .get_state_history :

for state_snapshot in agent.get_state_history(
    config={"configurable": {"thread_id": "human-in-the-loop-deepdive"}},
):
    if state_snapshot["metadata"]["step"] >= 0:
        print(f'step {state_snapshot["metadata"]["step"]}: {state_snapshot["config"]}')
        state_snapshot["values"]["messages"][-1].pretty_print()
        print("\n")

La réponse sera semblable à la séquence de résultats suivante :

step 3: {'configurable': {'thread_id': 'human-in-the-loop-deepdive', 'checkpoint_ns': '', 'checkpoint_id': '1efa2e95-ded5-67e0-8003-2d34e04507f5'}}
================================== Ai Message ==================================

The exchange rate from US dollars to Swedish krona is 1 USD to 11.0159 SEK.
step 2: {'configurable': {'thread_id': 'human-in-the-loop-deepdive', 'checkpoint_ns': '', 'checkpoint_id': '1efa2e95-d189-6a77-8002-5dbe79e2ce58'}}
================================= Tool Message =================================
Name: get_exchange_rate

{"amount": 1.0, "base": "USD", "date": "2024-11-14", "rates": {"SEK": 11.0159}}
step 1: {'configurable': {'thread_id': 'human-in-the-loop-deepdive', 'checkpoint_ns': '', 'checkpoint_id': '1efa2e95-cc7f-6d68-8001-1f6b5e57c456'}}
================================== Ai Message ==================================
Tool Calls:
  get_exchange_rate (12610c50-4465-4296-b1f3-d751ec959fd5)
 Call ID: 12610c50-4465-4296-b1f3-d751ec959fd5
  Args:
    currency_from: USD
    currency_to: SEK
step 0: {'configurable': {'thread_id': 'human-in-the-loop-deepdive', 'checkpoint_ns': '', 'checkpoint_id': '1efa2e95-c2e4-6f3c-8000-477fd654cb53'}}
================================ Human Message =================================

What is the exchange rate from US dollars to Swedish currency?

Obtenir la configuration d'une étape

Pour obtenir un point de contrôle antérieur, spécifiez checkpoint_id (et checkpoint_ns). Tout d'abord, revenez à l'étape 1, lorsque l'appel d'outil a été généré :

snapshot_config = {}
for state_snapshot in agent.get_state_history(
    config={"configurable": {"thread_id": "human-in-the-loop-deepdive"}},
):
    if state_snapshot["metadata"]["step"] == 1:
        snapshot_config = state_snapshot["config"]
        break

print(snapshot_config)

Le résultat ressemblera à ce qui suit :

{'configurable': {'thread_id': 'human-in-the-loop-deepdive',
  'checkpoint_ns': '',
  'checkpoint_id': '1efa2e95-cc7f-6d68-8001-1f6b5e57c456'}}

Fonctionnalité temporelle

Pour obtenir un point de contrôle, vous pouvez utiliser la méthode .get_state :

# By default, it gets the latest state [unless (checkpoint_ns, checkpoint_id) is specified]
state = agent.get_state(config={"configurable": {
    "thread_id": "human-in-the-loop-deepdive",
}})

print(f'step {state["metadata"]["step"]}: {state["config"]}')
state["values"]["messages"][-1].pretty_print()

Par défaut, il obtient le dernier point de contrôle (par code temporel). Le résultat devrait être semblable à ce qui suit :

step 3: {'configurable': {'thread_id': 'human-in-the-loop-deepdive', 'checkpoint_ns': '', 'checkpoint_id': '1efa2e95-ded5-67e0-8003-2d34e04507f5'}}
================================== Ai Message ==================================

The exchange rate from US dollars to Swedish krona is 1 USD to 11.0159 SEK.

Obtenir le point de contrôle d'une configuration

Pour une configuration donnée (par exemple, snapshot_config à partir de la configuration d'une étape), vous pouvez obtenir le point de contrôle correspondant :

state = agent.get_state(config=snapshot_config)
print(f'step {state["metadata"]["step"]}: {state["config"]}')
state["values"]["messages"][-1].pretty_print()

Le résultat ressemblera à ce qui suit :

step 1: {'configurable': {'thread_id': 'human-in-the-loop-deepdive', 'checkpoint_ns': '', 'checkpoint_id': '1efa2e95-cc7f-6d68-8001-1f6b5e57c456'}}
================================== Ai Message ==================================
Tool Calls:
  get_exchange_rate (12610c50-4465-4296-b1f3-d751ec959fd5)
 Call ID: 12610c50-4465-4296-b1f3-d751ec959fd5
  Args:
    currency_from: USD
    currency_to: SEK

Revoir

Pour rejouer à partir d'un état donné, transmettez la configuration de l'état (c'est-à-dire state["config"]) à l'agent. La configuration de l'état est un dictionnaire qui se présente comme suit :

{'configurable': {'thread_id': 'human-in-the-loop-deepdive',
  'checkpoint_ns': '',
  'checkpoint_id': '1efa2e95-cc7f-6d68-8001-1f6b5e57c456'}}

Pour relire à partir de state["config"] (où un appel d'outil a été généré), spécifiez None dans l'entrée :

from langchain.load import load as langchain_load

for state_values in agent.stream_query(
    input=None, # resume
    stream_mode="values",
    config=state["config"],
):
    langchain_load(state_values["messages"][-1]).pretty_print()

Vous obtiendrez un résultat semblable à la séquence de sorties suivante :

================================== Ai Message ==================================
Tool Calls:
  get_exchange_rate (12610c50-4465-4296-b1f3-d751ec959fd5)
 Call ID: 12610c50-4465-4296-b1f3-d751ec959fd5
  Args:
    currency_from: USD
    currency_to: SEK
================================= Tool Message =================================
Name: get_exchange_rate

{"amount": 1.0, "base": "USD", "date": "2024-11-14", "rates": {"SEK": 11.0159}}
================================== Ai Message ==================================

The exchange rate from US dollars to Swedish krona is 1 USD to 11.0159 SEK.

Branchement

Vous pouvez créer des branches à partir de points de contrôle précédents pour essayer d'autres scénarios à l'aide de la méthode .update_state :

branch_config = agent.update_state(
    config=state["config"],
    values={"messages": [last_message]}, # the update we want to make
)

print(branch_config)

Le résultat ressemblera à ce qui suit :

{'configurable': {'thread_id': 'human-in-the-loop-deepdive',
  'checkpoint_ns': '',
  'checkpoint_id': '1efa2e96-0560-62ce-8002-d1bb48a337bc'}}

Nous pouvons interroger l'agent avec branch_config pour reprendre à partir du point de contrôle avec l'état mis à jour :

from langchain.load import load as langchain_load

for state_values in agent.stream_query(
    input=None, # resume
    stream_mode="values",
    config=branch_config,
):
    langchain_load(state_values["messages"][-1]).pretty_print()

Vous obtiendrez un résultat semblable à la séquence de sorties suivante :

================================== Ai Message ==================================
Tool Calls:
  get_exchange_rate (12610c50-4465-4296-b1f3-d751ec959fd5)
 Call ID: 12610c50-4465-4296-b1f3-d751ec959fd5
  Args:
    currency_date: 2024-09-01
    currency_from: USD
    currency_to: SEK
================================= Tool Message =================================
Name: get_exchange_rate

{"amount": 1.0, "base": "USD", "date": "2024-08-30", "rates": {"SEK": 10.2241}}
================================== Ai Message ==================================

The exchange rate from US dollars to Swedish krona on 2024-08-30 was 1 USD to 10.2241 SEK.

Étapes suivantes