Agent_V2 #2
@@ -22,21 +22,28 @@ def getGraph()->CompiledStateGraph:
|
|||||||
workflow.add_node(inject_preparation_prompt)
|
workflow.add_node(inject_preparation_prompt)
|
||||||
workflow.add_node("tool_node", tool_node)# BasicToolNode(tools=getTools())) # N'est pas une fonction, mais une classe instanciée, je dois précisier le nom du node
|
workflow.add_node("tool_node", tool_node)# BasicToolNode(tools=getTools())) # N'est pas une fonction, mais une classe instanciée, je dois précisier le nom du node
|
||||||
workflow.add_node("weekly_report_tools", weekly_report_tools)
|
workflow.add_node("weekly_report_tools", weekly_report_tools)
|
||||||
|
workflow.add_node(context_shortener) # Réduit la taille du contexte
|
||||||
|
workflow.add_node("context_shortener_2", context_shortener) # Le même, sous un autre nom pour le différencier dans le graphe
|
||||||
|
|
||||||
# Arrêtes
|
# Arrêtes
|
||||||
workflow.set_conditional_entry_point(is_resumes_reports_already_initialised, {
|
workflow.set_conditional_entry_point(is_resumes_reports_already_initialised, {
|
||||||
"résumés non disponibles": "inject_preparation_prompt",
|
"résumés non disponibles": "inject_preparation_prompt", # Résumés non générés
|
||||||
"résumés déjà générés": "user_prompt"
|
"résumés déjà générés": "user_prompt" # Résumés déjà prêts, je peux aller direct à la partie principale
|
||||||
})
|
})
|
||||||
workflow.add_edge("inject_preparation_prompt", "preparation_docs")
|
workflow.add_edge("inject_preparation_prompt", "preparation_docs")
|
||||||
workflow.add_conditional_edges("preparation_docs", should_continue, {
|
workflow.add_conditional_edges("preparation_docs", should_continue, {
|
||||||
"tools":"weekly_report_tools",
|
"tools":"weekly_report_tools",
|
||||||
"no_tools":"user_prompt"
|
"no_tools":"context_shortener" # FIN de la préparation, on réduit le contexte avant de passer à la suite
|
||||||
})
|
})
|
||||||
|
workflow.add_edge("context_shortener", "user_prompt") # Et ici, je rejoins la partie principale qui rédigera le rapport
|
||||||
workflow.add_edge("user_prompt", "LLM_central")
|
workflow.add_edge("user_prompt", "LLM_central")
|
||||||
|
|
||||||
workflow.add_edge("weekly_report_tools", "preparation_docs")
|
workflow.add_edge("weekly_report_tools", "preparation_docs")
|
||||||
workflow.add_edge("tool_node", "LLM_central")
|
workflow.add_conditional_edges("tool_node", should_shorten, {
|
||||||
|
'sous la limite': "LLM_central",
|
||||||
|
'réduire contexte': "context_shortener_2"
|
||||||
|
})
|
||||||
|
workflow.add_edge("context_shortener_2", "LLM_central")
|
||||||
workflow.add_conditional_edges("LLM_central", should_continue, {
|
workflow.add_conditional_edges("LLM_central", should_continue, {
|
||||||
"tools":"tool_node",
|
"tools":"tool_node",
|
||||||
"no_tools":END
|
"no_tools":END
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ from langgraph.graph import MessagesState
|
|||||||
from langgraph.prebuilt import ToolNode
|
from langgraph.prebuilt import ToolNode
|
||||||
from langchain.chat_models import init_chat_model
|
from langchain.chat_models import init_chat_model
|
||||||
from langgraph.graph import START, END
|
from langgraph.graph import START, END
|
||||||
from langchain.messages import HumanMessage, AIMessage, SystemMessage
|
from langchain.messages import HumanMessage, AIMessage, SystemMessage, ToolMessage
|
||||||
from langgraph.types import interrupt
|
from langgraph.types import interrupt
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import json
|
||||||
|
|
||||||
from .tools import getTools, getWeeklyReportTools
|
from .tools import getTools, getWeeklyReportTools
|
||||||
from .state import CustomState
|
from .state import CustomState
|
||||||
@@ -66,6 +67,30 @@ def LLM_central(state: MessagesState):
|
|||||||
# Appel du LLM
|
# Appel du LLM
|
||||||
return {"messages": [model.invoke(state["messages"])]}
|
return {"messages": [model.invoke(state["messages"])]}
|
||||||
|
|
||||||
|
def context_shortener(state: CustomState):
|
||||||
|
""" Noeud visant à réduire la taille du contexte pour éviter une explosion de la taille de la mémoire court-terme/contexte """
|
||||||
|
raise NotImplementedError('TODO, faut que je le fasse')
|
||||||
|
|
||||||
|
# fonction de routage
|
||||||
|
def should_shorten(state: CustomState)->str:
|
||||||
|
"""
|
||||||
|
Fonction de routage, permet de savoir s'il est temps de résumer la contexte de la conversation
|
||||||
|
|
||||||
|
Args:
|
||||||
|
state (CustomState): Le State actuel
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Faut-il réduire le contexte ?
|
||||||
|
"""
|
||||||
|
TAILLE_CONTEXTE_MAX = 20000 #charactères
|
||||||
|
count = 0
|
||||||
|
for msg in state['messages']: count += len(msg.content) # Compter le nombre total de caractères dans le contexte
|
||||||
|
|
||||||
|
if count < TAILLE_CONTEXTE_MAX:
|
||||||
|
# OK
|
||||||
|
return 'sous la limite'
|
||||||
|
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: MessagesState):
|
||||||
"""
|
"""
|
||||||
@@ -82,21 +107,6 @@ def should_continue(state: MessagesState):
|
|||||||
return "tools"
|
return "tools"
|
||||||
return "no_tools"
|
return "no_tools"
|
||||||
|
|
||||||
def task_ended(state: MessagesState):
|
|
||||||
"""
|
|
||||||
Vérifier si l'agent a terminé son cycle, ou s'il faut le relancer
|
|
||||||
"""
|
|
||||||
if isinstance(state, list):
|
|
||||||
ai_message = state[-1]
|
|
||||||
elif messages := state.get("messages", []):
|
|
||||||
ai_message = messages[-1]
|
|
||||||
else:
|
|
||||||
raise ValueError(f"No messages found in input state to tool_edge: {state}")
|
|
||||||
|
|
||||||
if "terminé" in ai_message.content.lower():
|
|
||||||
return END
|
|
||||||
return "continue"
|
|
||||||
|
|
||||||
weekly_report_tools = ToolNode(tools=getWeeklyReportTools())
|
weekly_report_tools = ToolNode(tools=getWeeklyReportTools())
|
||||||
tool_node = ToolNode(tools=getTools())
|
tool_node = ToolNode(tools=getTools())
|
||||||
|
|
||||||
@@ -127,8 +137,7 @@ class BasicToolNode: # De mon ancien projet, https://github.com/LJ5O/Assistant/b
|
|||||||
)
|
)
|
||||||
return {"messages": outputs}
|
return {"messages": outputs}
|
||||||
|
|
||||||
# UTILS
|
# fonction de routage
|
||||||
|
|
||||||
def is_resumes_reports_already_initialised(state: CustomState)->str:
|
def is_resumes_reports_already_initialised(state: CustomState)->str:
|
||||||
"""Permet de savoirr si les résumés de comptes-rendu ont déjà été générés.
|
"""Permet de savoirr si les résumés de comptes-rendu ont déjà été générés.
|
||||||
S'ils le sont, inutile de recréer ce dossier.
|
S'ils le sont, inutile de recréer ce dossier.
|
||||||
|
|||||||
BIN
imgs/agent.png
BIN
imgs/agent.png
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
@@ -22,6 +22,7 @@
|
|||||||
## Amélioration de l'agent
|
## Amélioration de l'agent
|
||||||
- [ ] Cross-encoding sur la sortie du **RAG**
|
- [ ] Cross-encoding sur la sortie du **RAG**
|
||||||
- [ ] Sauvegarde de l'état de l'agent
|
- [ ] Sauvegarde de l'état de l'agent
|
||||||
|
- [ ] Lecture d'un `skills.md`
|
||||||
- [ ] Système de redémarrage après un arrêt
|
- [ ] Système de redémarrage après un arrêt
|
||||||
- [ ] Détection de *prompt injection*
|
- [ ] Détection de *prompt injection*
|
||||||
- [ ] Génération d'un PDF en sortie du système
|
- [ ] Génération d'un PDF en sortie du système
|
||||||
|
|||||||
Reference in New Issue
Block a user