diff --git a/AgentReact/utils/nodes.py b/AgentReact/utils/nodes.py index 0763de2..f34d116 100644 --- a/AgentReact/utils/nodes.py +++ b/AgentReact/utils/nodes.py @@ -66,10 +66,17 @@ def user_prompt(state: CustomState): return {'messages': messages}# Je passe unen liste, devrait écraser tous les messages précédent au lieu d'ajouter à la liste du State -def LLM_central(state: MessagesState): +def LLM_central(state: CustomState): """Noeud qui s'occupe de gérer les appels au LLM""" # Initialisation du LLM model = llm.bind_tools(getTools()) + #print(state) + + if "todo" in state.keys(): # S'il y a des TODO, je l'ajoute avant le prompt au LLM + if len(state['todo'])>0: + sysmsg = SystemMessage(f"Voici la liste des tâches en cours : {str([f"{i}: {str(todo)}\n" for i,todo in enumerate(state['todo'])])}") + print(sysmsg.content) + return {"messages": [model.invoke(state["messages"] + [AIMessage('.'), sysmsg])]} # AIMessage pour que Msitrail ne refuse pas la requête avec un 400 # Appel du LLM return {"messages": [model.invoke(state["messages"])]} @@ -142,7 +149,7 @@ def should_shorten(state: CustomState)->str: return 'réduire contexte' # fonction de routage : Après reponse_question, si le LLM veut appeler un outil, on va au tool_node -def should_continue(state: MessagesState): +def should_continue(state: CustomState): """ Vérifier s'il y a un appel aux outils dans le dernier message """ diff --git a/AgentReact/utils/tools.py b/AgentReact/utils/tools.py index a1bc51e..97ee9f9 100644 --- a/AgentReact/utils/tools.py +++ b/AgentReact/utils/tools.py @@ -1,5 +1,8 @@ from langchain.tools import tool from langgraph.prebuilt import InjectedState +from langchain_core.tools import InjectedToolCallId +from langchain_core.messages import ToolMessage +from langgraph.types import Command from tavily import TavilyClient from pathlib import Path from typing import List, Dict, Annotated @@ -60,20 +63,18 @@ def write_file(file_path:str, content: str, append:bool=True) -> str: return f"Erreur lors de l'écriture: {str(e)}" @tool -def editTodo(index:int, todoState:int, state: Annotated[dict, InjectedState])->bool: # https://stackoverflow.com/a/79525434 +def editTodo(index:int, todoState:int, state: Annotated[dict, InjectedState], tool_call_id: Annotated[str, InjectedToolCallId])->Command: # https://stackoverflow.com/a/79525434 """ Modifier l'état d'une tâche (TODO) Args: index (int): Index de la tâche à modifier, en commançant à 0 pour la première tâche. todoState (int): Nouvel état. 0 pour "non commencé, 1 pour "en cours", 2 pour "complété" - - Returns: - bool: Réussite de l'opération, ou non. """ + if "todo" not in state.keys(): return Command(update={"messages": [ToolMessage(content="Echec!", tool_call_id=tool_call_id)]}) if len(state["todo"]) <= index: # Erreur, l'index est trop grand - return False + return Command(update={"messages": [ToolMessage(content="Index en dehors de la liste, echec!", tool_call_id=tool_call_id)]}) state["todo"][index].state = todoState # Modification de l'état de cette tâche @@ -85,42 +86,46 @@ def editTodo(index:int, todoState:int, state: Annotated[dict, InjectedState])->b break if not found: state["todo"] = [] # Toutes les tâches terminées, je peux clear la TODO list du state - return True + return Command(update={ + "messages": [ToolMessage(content="Réussite!", tool_call_id=tool_call_id)], + "todo": [x for x in state["todo"]] # Update du state, # medium.com/@o39joey/a-comprehensive-guide-to-langgraph-managing-agent-state-with-tools-ae932206c7d7 + }) @tool -def addTodo(name:str, description:str, state: Annotated[dict, InjectedState])->bool: +def addTodo(name:str, description:str, state: Annotated[dict, InjectedState], tool_call_id: Annotated[str, InjectedToolCallId])->Command: """ Ajouter une nouvelle tâche/TODO Args: name (str): Nom de cette tâche description (str): Une ou deux phrases pour décrire le travail à effectuer dans ce TODO - - Returns: - bool: Réussite de l'opération, ou non """ - if state["todo"] is None: state["todo"] = [] + if "todo" not in state.keys(): state["todo"] = [] state["todo"].append(TodoElement(name, description)) - return True + return Command(update={ + "messages": [ToolMessage(content="Réussite!", tool_call_id=tool_call_id)], + "todo": [x for x in state["todo"]] # Update du state, # medium.com/@o39joey/a-comprehensive-guide-to-langgraph-managing-agent-state-with-tools-ae932206c7d7 + }) @tool -def removeTodo(index:int, state: Annotated[dict, InjectedState])->bool: +def removeTodo(index:int, state: Annotated[dict, InjectedState], tool_call_id: Annotated[str, InjectedToolCallId])->Command: """ Retirer une tâche/TODO de la liste des tâches Args: index (int): Position de la tâche dans la liste, commence à 0 pour le premier TODO - - Returns: - bool: Réussite de l'opération, ou non """ + if "todo" not in state.keys(): return Command(update={"messages": [ToolMessage(content="Echec!", tool_call_id=tool_call_id)]}) if len(state["todo"]) <= index: # Erreur, l'index est trop grand - return False + return Command(update={"messages": [ToolMessage(content="Index en dehors de la liste, echec!", tool_call_id=tool_call_id)]}) state['todo'].pop(index) - return True + return Command(update={ + "messages": [ToolMessage(content="Réussite!", tool_call_id=tool_call_id)], + "todo": [x for x in state["todo"]] # Update du state, # medium.com/@o39joey/a-comprehensive-guide-to-langgraph-managing-agent-state-with-tools-ae932206c7d7 + }) @tool def read_file(file_path: str) -> str: