Spaces:
Paused
Paused
| """GovOn LangGraph StateGraph ๋น๋. | |
| v4 ์ํคํ ์ฒ: ReAct + ToolNode ๊ธฐ๋ฐ. | |
| LLM์ด ์์จ์ ์ผ๋ก ๋๊ตฌ ํธ์ถ์ ๊ฒฐ์ ํ๋ฉฐ, ์ ์ planner/executor๋ฅผ ์ ๊ฑฐํ๋ค. | |
| Graph topology: | |
| START โ session_load โ agent โ [route_agent] | |
| โโโ (no tool_calls) โ persist โ END | |
| โโโ (all Tier 0) โ tools โ agent โ ... | |
| โโโ (needs approval) โ approval_wait โ [route_after_approval] | |
| โโโ (approved) โ tools โ agent โ ... | |
| โโโ (cancelled) โ persist โ END | |
| โโโ (rejected) โ agent โ ... | |
| """ | |
| from __future__ import annotations | |
| from typing import TYPE_CHECKING, Optional | |
| from langgraph.graph import END, START, StateGraph | |
| from langgraph.prebuilt import ToolNode | |
| from .nodes import ( | |
| make_agent_node, | |
| make_approval_wait_node, | |
| make_persist_node, | |
| make_session_load_node, | |
| route_after_approval, | |
| ) | |
| from .state import ApprovalStatus, GovOnGraphState | |
| if TYPE_CHECKING: | |
| from langgraph.graph.state import CompiledStateGraph | |
| from src.inference.session_context import SessionStore | |
| def _make_route_agent(approval_map: dict[str, bool]): | |
| """agent ๋ ธ๋ ์ดํ ๋ผ์ฐํ ํจ์๋ฅผ ์์ฑํ๋ค. | |
| Parameters | |
| ---------- | |
| approval_map : dict[str, bool] | |
| {tool_name: requires_approval} ๋งคํ. | |
| Returns | |
| ------- | |
| Callable | |
| state๋ฅผ ๋ฐ์ ๋ค์ ๋ ธ๋ ์ด๋ฆ์ ๋ฐํํ๋ ๋ผ์ฐํ ํจ์. | |
| """ | |
| def route_agent(state: GovOnGraphState) -> str: | |
| messages = state.get("messages", []) | |
| if not messages: | |
| return "persist" | |
| last = messages[-1] | |
| tool_calls = getattr(last, "tool_calls", None) | |
| if not tool_calls: | |
| return "persist" | |
| needs_approval = any(approval_map.get(tc["name"], False) for tc in tool_calls) | |
| return "approval_wait" if needs_approval else "tools" | |
| return route_agent | |
| def build_govon_graph( | |
| *, | |
| llm, | |
| tools: list, | |
| session_store: "SessionStore", | |
| checkpointer: Optional[object] = None, | |
| ) -> "CompiledStateGraph": | |
| """GovOn ReAct StateGraph๋ฅผ ๊ตฌ์ฑํ๊ณ ์ปดํ์ผํ๋ค. | |
| Parameters | |
| ---------- | |
| llm : BaseChatModel | |
| ๋๊ตฌ ๋ฐ์ธ๋ฉ ๊ฐ๋ฅํ LLM ์ธ์คํด์ค (ChatOpenAI ๋ฑ). | |
| tools : list[StructuredTool] | |
| build_all_tools()๋ก ์์ฑ๋ ๋๊ตฌ ๋ชฉ๋ก. | |
| session_store : SessionStore | |
| ์ธ์ ์ ์ฅ์. session_load / persist ๋ ธ๋์์ ์ฌ์ฉ. | |
| checkpointer : optional | |
| LangGraph checkpoint ์ ์ฅ์. | |
| None์ด๋ฉด MemorySaver๋ฅผ ์ฌ์ฉํ๋ค. | |
| Returns | |
| ------- | |
| CompiledStateGraph | |
| ์ปดํ์ผ๋ LangGraph. | |
| """ | |
| from langgraph.checkpoint.memory import MemorySaver | |
| from .tools import get_tool_approval_map | |
| tool_node = ToolNode(tools) | |
| approval_map = get_tool_approval_map(tools) | |
| graph = StateGraph(GovOnGraphState) | |
| # --- ๋ ธ๋ ๋ฑ๋ก --- | |
| graph.add_node("session_load", make_session_load_node(session_store)) | |
| graph.add_node("agent", make_agent_node(llm, tools)) | |
| graph.add_node("approval_wait", make_approval_wait_node(approval_map)) | |
| graph.add_node("tools", tool_node) | |
| graph.add_node("persist", make_persist_node(session_store)) | |
| # --- ์ฃ์ง --- | |
| graph.add_edge(START, "session_load") | |
| graph.add_edge("session_load", "agent") | |
| graph.add_conditional_edges( | |
| "agent", | |
| _make_route_agent(approval_map), | |
| { | |
| "tools": "tools", | |
| "approval_wait": "approval_wait", | |
| "persist": "persist", | |
| }, | |
| ) | |
| graph.add_conditional_edges( | |
| "approval_wait", | |
| route_after_approval, | |
| { | |
| "tools": "tools", | |
| "agent": "agent", | |
| "persist": "persist", | |
| }, | |
| ) | |
| graph.add_edge("tools", "agent") | |
| graph.add_edge("persist", END) | |
| # --- ์ปดํ์ผ --- | |
| saver = checkpointer if checkpointer is not None else MemorySaver() | |
| return graph.compile(checkpointer=saver) | |