File size: 3,522 Bytes
afd56bc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# ruff: noqa: E402
from dotenv import load_dotenv

load_dotenv()
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver

from agents.supervisor import supervisor_node
from agents.profiler import profiler_node
from agents.researcher import researcher_node
from agents.matcher import matcher_node
from agents.verifier import verifier_node
from agents.timeline import timeline_node
from agents.wizard import wizard_node
from agents.planner import planner_node
from agents.critic import critic_node
from agents.risk_scoring import risk_scoring_node
from agents.document_gap_analyzer import document_gap_analyzer_node
from agents.compliance_guardian import compliance_guardian_node
from schemas import AgentState

# W 2026 roku celujemy w Postgres dla subgraf贸w, tymczasowo bazowy memory_saver.
memory_saver = MemorySaver()


def create_app():
    workflow = StateGraph(AgentState)

    # Rejestracja wszystkich w臋z艂贸w (Agent贸w)
    workflow.add_node("supervisor", supervisor_node)
    workflow.add_node("profiler", profiler_node)
    workflow.add_node("researcher", researcher_node)
    workflow.add_node("matcher", matcher_node)
    workflow.add_node("verifier", verifier_node)
    workflow.add_node("timeline", timeline_node)
    workflow.add_node("wizard", wizard_node)
    workflow.add_node("planner", planner_node)
    workflow.add_node("critic", critic_node)
    workflow.add_node("risk_scoring", risk_scoring_node)
    workflow.add_node("document_gap_analyzer", document_gap_analyzer_node)
    workflow.add_node("compliance_guardian", compliance_guardian_node)

    # Definicja kraw臋dzi wej艣ciowych
    workflow.add_edge(START, "supervisor")

    # Logika warunkowa supervisora jako Global Router
    workflow.add_conditional_edges(
        "supervisor",
        lambda state: state.current_agent,
        {
            "profiler": "profiler",
            "researcher": "researcher",
            "matcher": "matcher",
            "verifier": "verifier",
            "timeline": "timeline",
            "wizard": "wizard",
            "planner": "planner",
            "risk_scoring": "risk_scoring",
            "document_gap_analyzer": "document_gap_analyzer",
            "compliance_guardian": "compliance_guardian",
            "end": END,
        },
    )

    # Conditional routing po Critic (idziemy do wizard je艣li is_approved=False, chyba 偶e przekroczono limit)
    workflow.add_conditional_edges(
        "critic",
        lambda state: "approve"
        if (state.critic_evaluation and state.critic_evaluation.is_approved)
        or state.critic_iterations >= state.max_critic_iterations
        else "wizard",
        {"approve": END, "wizard": "wizard"},
    )

    # W architekturze 2026, Wizard idzie zawsze do Critica (Recenzenta)
    workflow.add_edge("wizard", "critic")

    # Powrotne kraw臋dzie do Supervisora
    workflow.add_edge("profiler", "supervisor")
    workflow.add_edge("researcher", "supervisor")
    workflow.add_edge("matcher", "supervisor")
    workflow.add_edge("verifier", "supervisor")
    workflow.add_edge("timeline", "supervisor")
    workflow.add_edge("planner", "supervisor")
    workflow.add_edge("risk_scoring", "supervisor")
    workflow.add_edge("document_gap_analyzer", "supervisor")
    workflow.add_edge("compliance_guardian", "supervisor")

    # Kompilacja z systemem checkpoint贸w dla Human-in-the-Loop
    return workflow.compile(checkpointer=memory_saver, interrupt_before=["critic"])


app = create_app()