interuption

This commit is contained in:
2026-04-10 22:16:27 +00:00
parent 38e993c1d6
commit b6803c4957

86
agent_interupt.py Normal file
View File

@@ -0,0 +1,86 @@
import sys
import asyncio
from dotenv import load_dotenv
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_mcp_adapters.client import MultiServerMCPClient
# ✅ LE BON IMPORT POUR LANGGRAPH V1.0+ (et futur v2.0)
from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
from langchain_core.messages import HumanMessage
from langchain_core.messages import ToolMessage
load_dotenv()
async def lancer_agent_moderne():
llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash")
# Notre configuration MCP habituelle
client = MultiServerMCPClient({
"serveur_taches": {
"command": sys.executable,
"args": ["serveur_mcp.py"],
"transport": "stdio"
}
})
outils = await client.get_tools()
async with AsyncSqliteSaver.from_conn_string("memoire_agent.db") as checkpointer:
# 🚀 L'approche moderne :
# On définit l'agent directement via le constructeur de LangGraph.
# Plus besoin de 'AgentExecutor', LangGraph gère la boucle lui-même.
agent = create_react_agent(
llm,
tools=outils,
checkpointer=checkpointer,
interrupt_before=["tools"] # Notre garde-fou
)
config = {"configurable": {"thread_id": "session_moderne_001"}}
# --- ÉTAPE 1 : L'Agent propose une action ---
consigne = "Ajoute la tâche 'Apprendre LangGraph' à ma liste."
print(f"\n🗣️ ORDRE : {consigne}")
async for etape in agent.astream(
{"messages": [HumanMessage(content=consigne)]},
config=config,
stream_mode="values"
):
etape["messages"][-1].pretty_print()
# --- ÉTAPE 2 : Vérification de l'état ---
etat_actuel = await agent.aget_state(config)
if etat_actuel.next:
print(f"\n⚠️ ACTION EN ATTENTE : L'agent veut utiliser l'outil : {etat_actuel.next}")
confirmation = input("👉 Voulez-vous autoriser cette action ? (oui/non) : ")
if confirmation.lower() == "oui":
# --- ÉTAPE 3 : On relance l'agent là où il s'est arrêté ---
print("🚀 Validation reçue. Exécution en cours...")
async for etape in agent.astream(None, config=config, stream_mode="values"):
etape["messages"][-1].pretty_print()
else:
print("❌ Action annulée par l'utilisateur.")
# On crée un message de résultat d'outil manuel pour clore la boucle
outil_id = etape["messages"][-1].tool_calls[0]["id"]
message_annulation = ToolMessage(
tool_call_id=outil_id,
content="L'utilisateur a refusé cette action. Propose une alternative ou arrête-toi là."
)
# On met à jour l'état de l'agent avec ce message de "faux" résultat
await agent.aupdate_state(config, {"messages": [message_annulation]})
# On relance pour que l'IA réagisse à l'annulation
async for etape in agent.astream(None, config=config, stream_mode="values"):
etape["messages"][-1].pretty_print()
else:
print("\n✅ L'agent a terminé sans avoir besoin de validation.")
if __name__ == "__main__":
asyncio.run(lancer_agent_moderne())