from builder.state import AgentState from datastore.db import conn from clients.llm import complete from utils.charts import df_to_pil_chart def decider(state: dict) -> dict: """Decide whether to use SQL flow or general LLM chat.""" history_text = "\n".join([ f"{h['role'].capitalize()}: {h['content']}" for h in state.get("history", []) ]) prompt = f""" You are a router. Decide whether the user question requires SQL/database analysis (tables: sales, marketing_spend, customers) OR if it can be answered directly as a general conversational reply. Chat history so far: {history_text} Current question: {state['question']} Answer ONLY with one word: "sql" or "chat". """ decision = complete(prompt).lower().strip() if "sql" in decision: return {"route": "sql"} return {"route": "chat"} def sql_generator(state: AgentState) -> dict: schema = """ Tables: sales(date, region, product, revenue, units_sold) marketing_spend(date, region, channel, spend) customers(customer_id, region, age, income) """ prompt = f"You are a helpful SQL expert. Schema: {schema}. Question: {state['question']}. Return only a SELECT SQL query and do not wrap it with ```sql tag." sql = complete(prompt) if not sql.lower().startswith("select"): sql = "SELECT region, SUM(revenue) as total_revenue FROM sales GROUP BY region" return {"sql": sql} def sql_executor(state: AgentState) -> dict: df = conn.execute(state["sql"]).df() return {"df": df} def chart_generator(state: AgentState) -> dict: pil_img = df_to_pil_chart(state["df"], state["question"]) return {"chart_pil": pil_img} def narrator(state: AgentState) -> dict: df_json = state["df"].to_dict(orient="records") prompt = f"Question: {state['question']}\nResult: {df_json}\nWrite 3-4 bullet point insights with one recommendation." narrative = complete(prompt) return {"narrative": narrative} def general_chat(state: dict) -> dict: """Handle general conversational queries with LLM.""" history_text = "\n".join([ f"{h['role'].capitalize()}: {h['content']}" for h in state.get("history", []) ]) prompt = f""" You are a helpful assistant. Continue the conversation naturally. Chat history so far: {history_text} User question: {state['question']} """ response = complete(prompt) return {"narrative": response}