| from __future__ import annotations |
|
|
| from backend.agents.analysis import AnalysisAgent |
| from backend.agents.planner import PlannerAgent |
| from backend.agents.reflection_agent import ReflectionAgent |
| from backend.agents.sql_agent import SQLAgent |
| from backend.agents.visulaization_agent import VisualizationAgent |
| from graph.state import BIState |
|
|
|
|
| class WorkflowNodes: |
| def __init__( |
| self, |
| planner: PlannerAgent, |
| sql_agent: SQLAgent, |
| analysis_agent: AnalysisAgent, |
| reflection_agent: ReflectionAgent, |
| visualization_agent: VisualizationAgent, |
| ) -> None: |
| self.planner = planner |
| self.sql_agent = sql_agent |
| self.analysis_agent = analysis_agent |
| self.reflection_agent = reflection_agent |
| self.visualization_agent = visualization_agent |
|
|
| def run_planner(self, state: BIState) -> BIState: |
| plan = self.planner.run(state["question"]) |
| return { |
| **state, |
| "plan": plan.to_dict(), |
| "next_step": "sql" if plan.needs_database else "analysis", |
| } |
|
|
| def run_sql(self, state: BIState) -> BIState: |
| plan = self.planner.run(state["question"]) |
| sql_output = self.sql_agent.run(state["question"], plan) |
| return { |
| **state, |
| "plan": state.get("plan") or plan.to_dict(), |
| "sql": sql_output.to_dict(), |
| "next_step": "analysis", |
| } |
|
|
| def run_analysis(self, state: BIState) -> BIState: |
| plan = self.planner.run(state["question"]) |
| sql_output = self.sql_agent.run(state["question"], plan) if not state.get("sql") else None |
| sql_payload = state.get("sql") or sql_output.to_dict() |
| analysis_output = self.analysis_agent.run( |
| state["question"], |
| plan, |
| sql_output if sql_output else self._sql_output_from_dict(sql_payload), |
| ) |
| return { |
| **state, |
| "plan": state.get("plan") or plan.to_dict(), |
| "sql": sql_payload, |
| "analysis": analysis_output.to_dict(), |
| "next_step": "reflection", |
| } |
|
|
| def run_reflection(self, state: BIState) -> BIState: |
| sql_output = self._sql_output_from_dict(state["sql"]) |
| analysis_output = self._analysis_output_from_dict(state["analysis"]) |
| reflection = self.reflection_agent.run(sql_output, analysis_output) |
| return { |
| **state, |
| "reflection": reflection.to_dict(), |
| "next_step": "visualization", |
| } |
|
|
| def run_visualization(self, state: BIState) -> BIState: |
| sql_result = state.get("sql", {}).get("result", {}) |
| visualization = self.visualization_agent.run(state["question"], sql_result) |
| return { |
| **state, |
| "visualization": visualization.to_dict(), |
| "next_step": "end", |
| } |
|
|
| @staticmethod |
| def _sql_output_from_dict(payload: dict): |
| from backend.agents.sql_agent import SQLAgentOutput |
|
|
| return SQLAgentOutput( |
| sql=payload.get("sql", ""), |
| rationale=payload.get("rationale", ""), |
| selected_tables=payload.get("selected_tables", []), |
| selected_columns=payload.get("selected_columns", []), |
| result=payload.get("result", {}), |
| warnings=payload.get("warnings", []), |
| error=payload.get("error"), |
| ) |
|
|
| @staticmethod |
| def _analysis_output_from_dict(payload: dict): |
| from backend.agents.analysis import AnalysisOutput |
|
|
| return AnalysisOutput( |
| summary=payload.get("summary", ""), |
| insights=payload.get("insights", []), |
| follow_ups=payload.get("follow_ups", []), |
| confidence=payload.get("confidence", "medium"), |
| ) |
|
|