# 30-in-15 · #12 — CSV → Insights Analyst (plan) **Rung focus:** code execution + a data agent (vs. #11's long-running service). **One-liner:** Upload a CSV → get auto-generated charts + plain-English findings you can trust. ## Core principle (honest by construction) The LLM **never invents numbers.** A deterministic profiling pass (pandas) computes every stat and chart; the model only *narrates* the already-computed summary. Numbers in the writeup are grounded in the computed profile, not hallucinated. (Mirrors the #10 RAG "honest, cited" discipline.) ## v1 scope (lean) 1. **Upload** a CSV (size-capped, typed sniff). 2. **Profile** (pandas): shape, dtypes, missing %, numeric describe, top categoricals, correlations, simple outlier + trend flags. 3. **Auto-charts** (matplotlib, GritAI design-system palette): distributions, top categories, correlation heatmap, and a time trend if a date column is detected. 4. **Narrative**: LLM turns the computed profile into a plain-English "what's interesting here" — grounded in the numbers, flags data-quality issues, suggests next questions. 5. **Ask-a-question** (stretch): natural-language question → constrained pandas op executed on the dataframe → answer + the exact numbers (the "data agent / code execution" angle). ## Stack - Flask + the canonical GritAI design system (`docs/gritai_design_system.css`), same as the Flask rungs. - pandas + matplotlib (stdlib-adjacent, no heavy deps). - Backend LLM: local Ollama (free) by default; Claude optional — same env-var pattern as the bot. - Deploy: HF docker Space per [[hf-spaces-deploy-playbook]] → `insights.gritai.solutions` on the hub. - Two-tier: free demo (funnel) / paid "GritAI Studio" full stack. ## Validate on REAL data (Rob's rule) Build + tune against a real CSV Rob provides so the demo isn't synthetic. Fallback: a solid public dataset, swap Rob's in later. ## Safety Same secrets hygiene (env-only keys, log exception TYPE only). Uploaded data stays local/ephemeral; never logged, never sent anywhere except the chosen LLM backend (local by default).