92 lines
2.6 KiB
Python
92 lines
2.6 KiB
Python
import warnings
|
|
from langchain_core._api.deprecation import LangChainPendingDeprecationWarning
|
|
warnings.filterwarnings("ignore", category=LangChainPendingDeprecationWarning)
|
|
|
|
from langgraph.graph import StateGraph, END
|
|
from app.graph.state import WorkflowState
|
|
from app.graph.nodes import (
|
|
pm_node,
|
|
retrieval_node,
|
|
dev_node,
|
|
qa_node,
|
|
human_review_node,
|
|
)
|
|
|
|
# --- Fonctions de Routage (Conditional Edges) ---
|
|
|
|
def route_after_retrieval(state: WorkflowState):
|
|
# Si un projet existe, on demande d'abord à l'humain (via le nœud de review)
|
|
if state.get("existing_project"):
|
|
return "human_review"
|
|
return "dev"
|
|
|
|
def route_after_qa(state: WorkflowState):
|
|
qa_res = state.get("qa_result", {})
|
|
|
|
# Loop 1 : Si échec des tests ET qu'on a pas dépassé 3 essais -> On renvoie chez le Dev
|
|
if not qa_res.get("success") and state.get("loop_count", 0) < 3:
|
|
return "dev"
|
|
|
|
# Si c'est vert (ou trop d'échecs), on présente le résultat à l'utilisateur
|
|
# EXTENSION FUTURE : si trop d'échecs, on pourrait envoyer à une IA plus puissante
|
|
return "human_review"
|
|
|
|
def route_after_human(state: WorkflowState):
|
|
# Cas d'un projet existant proposé
|
|
if state.get("existing_project") and not state.get("generated_code"):
|
|
if state.get("existing_project_approved") == True:
|
|
return END # L'utilisateur est satisfait du projet existant
|
|
return "dev" # L'utilisateur refuse l'existant, on génère du neuf
|
|
|
|
# Cas du code généré
|
|
if state.get("is_completed") == True:
|
|
return END
|
|
|
|
# Si l'utilisateur a refusé le code -> Retour à la case PM avec ses commentaires
|
|
return "pm"
|
|
|
|
# --- Assemblage du Graphe ---
|
|
|
|
graph = StateGraph(WorkflowState)
|
|
|
|
graph.add_node("pm", pm_node)
|
|
graph.add_node("retrieval", retrieval_node)
|
|
graph.add_node("dev", dev_node)
|
|
graph.add_node("qa", qa_node)
|
|
graph.add_node("human_review", human_review_node)
|
|
|
|
graph.set_entry_point("pm")
|
|
graph.add_edge("pm", "retrieval")
|
|
|
|
# Étape 1 : Choix après recherche vectorielle
|
|
graph.add_conditional_edges(
|
|
"retrieval",
|
|
route_after_retrieval,
|
|
{
|
|
"dev": "dev",
|
|
"human_review": "human_review",
|
|
},
|
|
)
|
|
|
|
# Étape 2 & 3 : Boucle Dev <-> QA (Loop 1)
|
|
graph.add_edge("dev", "qa")
|
|
graph.add_conditional_edges(
|
|
"qa",
|
|
route_after_qa,
|
|
{
|
|
"dev": "dev",
|
|
"human_review": "human_review",
|
|
},
|
|
)
|
|
|
|
# Étape 4 : Boucle de Feedback Humain (Loop 2) ou Clôture
|
|
graph.add_conditional_edges(
|
|
"human_review",
|
|
route_after_human,
|
|
{
|
|
"pm": "pm",
|
|
"dev": "dev",
|
|
END: END,
|
|
},
|
|
)
|
|
compiled_graph = graph.compile() |