Agent_V3 #3

Merged
Kevin merged 12 commits from Agent_V3 into master 2026-02-12 15:24:11 +01:00
4 changed files with 119 additions and 22 deletions
Showing only changes of commit f1caea0323 - Show all commits

View File

@@ -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 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""" """Noeud qui s'occupe de gérer les appels au LLM"""
# Initialisation du LLM # Initialisation du LLM
model = llm.bind_tools(getTools()) 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 # Appel du LLM
return {"messages": [model.invoke(state["messages"])]} return {"messages": [model.invoke(state["messages"])]}
@@ -142,7 +149,7 @@ def should_shorten(state: CustomState)->str:
return 'réduire contexte' return 'réduire contexte'
# fonction de routage : Après reponse_question, si le LLM veut appeler un outil, on va au tool_node # 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 Vérifier s'il y a un appel aux outils dans le dernier message
""" """

View File

@@ -1,5 +1,8 @@
from langchain.tools import tool from langchain.tools import tool
from langgraph.prebuilt import InjectedState 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 tavily import TavilyClient
from pathlib import Path from pathlib import Path
from typing import List, Dict, Annotated 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)}" return f"Erreur lors de l'écriture: {str(e)}"
@tool @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) Modifier l'état d'une tâche (TODO)
Args: Args:
index (int): Index de la tâche à modifier, en commançant à 0 pour la première tâche. 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é" 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: if len(state["todo"]) <= index:
# Erreur, l'index est trop grand # 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 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 break
if not found: state["todo"] = [] # Toutes les tâches terminées, je peux clear la TODO list du state 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 @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 Ajouter une nouvelle tâche/TODO
Args: Args:
name (str): Nom de cette tâche name (str): Nom de cette tâche
description (str): Une ou deux phrases pour décrire le travail à effectuer dans ce TODO 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)) 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 @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 Retirer une tâche/TODO de la liste des tâches
Args: Args:
index (int): Position de la tâche dans la liste, commence à 0 pour le premier TODO 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: if len(state["todo"]) <= index:
# Erreur, l'index est trop grand # 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) 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 @tool
def read_file(file_path: str) -> str: def read_file(file_path: str) -> str: