Spaces:
Sleeping
Sleeping
File size: 7,522 Bytes
c9fb3f2 f7021ae 01e9c30 f7021ae 01e9c30 f7021ae 01e9c30 f7021ae 01e9c30 f7021ae | 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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | ---
title: "Data Analysis Agent"
emoji: "💬"
colorFrom: "indigo"
colorTo: "pink"
sdk: "streamlit"
sdk_version: "1.36.0"
app_file: "streamlit_app.py"
pinned: false
---
# Data Analysis Agent (Streamlit + LangGraph ReAct Agent)
A lightweight Streamlit application that ingests **Excel (.xlsx)** files into a local **DuckDB** database and lets you **chat with your data**. It uses a **LangGraph ReAct-style agent** to generate DuckDB SQL from natural language, refine on errors, and optionally render plots. Answers stream live, are aware of chat history, and show the generated SQL in an expander for transparency.
---
## Highlights
- **One‑click ingestion**: Excel → DuckDB using `excel_to_duckdb.py` (keeps ingestion logs).
- **Overview & preview**: Human‑friendly overview and quick table previews before chatting.
- **Chat with your dataset**: Natural‑language questions → SQL → answer (+ optional chart).
- **Streaming**: Answers appear token‑by‑token (“Answer pending…” shows immediately).
- **History‑aware**: Follow‑ups consider prior Q&A context for better intent & filters.
- **Conservative plotting**: Only plots when useful (trends/many rows or explicitly asked).
- **Clean UI**: Chart appears **below** the answer and **before** the generated SQL.
- **Session isolation**: Uploading a new file **clears** overview, previews, and chat.
- **Local by default**: DuckDB DB & plots are saved locally (`./dbs`, `./plots`).
---
## Repo Structure
```
streamlit_app.py # Streamlit app (UI, flow, chat)
duckdb_react_agent.py # LangGraph ReAct agent (SQL generation, refine, answer, plots)
excel_to_duckdb.py # Excel → DuckDB ingestion script (unchanged behavior)
uploads/ # Uploaded Excel files (created at runtime)
dbs/ # DuckDB files per upload (created at runtime)
plots/ # Charts generated by the agent (created at runtime)
```
> **Note:** The app intentionally skips internal tables (e.g., `__excel_*`) when discovering “user tables.” Those tables hold ingestion metadata and previews.
---
## Requirements
- Python 3.10+
- Recommended packages:
```bash
pip install streamlit duckdb pandas matplotlib python-dotenv langgraph langchain langchain-openai
```
- **OpenAI** API key in environment or `.env` file:
```dotenv
OPENAI_API_KEY=sk-...
# optional: model override (defaults to gpt-4o-mini in app; gpt-4o in CLI agent)
OPENAI_MODEL=gpt-4o-mini
```
If your ingestion or preview relies on Excel parsing features, make sure you have:
```bash
pip install openpyxl
```
---
## Quick Start
1. Place the three files side‑by‑side:
```
streamlit_app.py
duckdb_react_agent.py
excel_to_duckdb.py
```
2. Set your API key (env var or `.env`):
```bash
export OPENAI_API_KEY=sk-... # macOS/Linux
setx OPENAI_API_KEY "sk-..." # Windows PowerShell (new sessions)
```
3. Run the app:
```bash
streamlit run streamlit_app.py
```
4. In the UI:
- **Upload** an `.xlsx` file → watch the **Processing logs**.
- Once ingestion finishes, you’ll see the **overview** and **quick previews**.
- Scroll down to **Chat with your dataset** and start asking questions.
- Each bot reply shows: **answer text**, optional **chart**, and an expander for **SQL**.
> **New upload behavior:** As soon as you upload a different file, the app **clears** the previous overview, table previews, and chat, then ingests the new file.
---
## How It Works
### 1) Ingestion (Excel → DuckDB)
- The app shells out to `excel_to_duckdb.py`:
- Detects multiple tables per sheet (using blank rows as separators), handles merged headers, ignores pivot/chart‑like blocks, and writes one DuckDB table per block.
- Creates helpful metadata tables (e.g., `__excel_tables`, `__excel_schema`).
- The app then opens the DuckDB file and builds a **schema snapshot** for the agent.
- **User tables**: The app queries `information_schema` to list the “real” user tables (skips internals like `__excel_*`).
### 2) LangGraph ReAct Agent (DuckDB Q&A)
- **ReAct loop**: Draft a SELECT query → run → if error, **refine up to 3×** with the error and prior SQL.
- **Safety**: Only **SELECT** queries are permitted.
- **Streaming answers**: Final natural‑language answer streams to the UI.
- **History awareness**: Recent Q&A is summarized and fed to the LLM for better follow‑ups.
- **Plotting (optional)**: If the result truly benefits from visuals (or you ask for one), a chart is generated and saved to `./plots`; the app then displays it **below** the answer.
> The agent avoids revealing plot file names or paths. Answers refer generically to “the chart” and the UI renders the image inline.
---
## Configuration & Tweaks
- **Models**: Set `OPENAI_MODEL` in your env to change the LLM (`gpt-4o-mini`, `gpt-4o`, etc.).
- **Plot policy**: The agent is conservative by default. To make it more/less eager to chart, tune the **viz prompt** or the **row‑count threshold** in `duckdb_react_agent.py` (`many_rows = df.shape[0] > 20`).
- **Chart size**: In `streamlit_app.py`, the plot width is ~**560px** for answers and ~**320‑360px** in history; adjust to taste.
- **Schemas**: The schema summary focuses on `main`. To include more schemas, extend the `allowed_schemas` list where `get_schema_summary()` is called.
---
## Troubleshooting
**“No user tables were discovered. Showing ingestion metadata…”**
- Your Excel may not have recognizable data blocks under the current heuristics. Check the **Processing logs** and the `__excel_tables` preview to verify what got detected.
- If it’s a header/merged‑cell issue, revisit your spreadsheet (ensure at least one empty row between blocks).
**Agent errors / SQL fails repeatedly**
- The agent refines up to 3×. If it still fails, it returns the error. Try asking the question more explicitly (table names, time ranges, filters).
**Streamlit cache / stale code**
- If updates don’t show up, restart Streamlit or clear cache:
```bash
streamlit cache clear
```
**Windows console encoding warnings**
- The app sets `PYTHONIOENCODING=utf-8` for ingestion logs. If you still see encoding issues, ensure system locale supports UTF‑8.
---
## Security & Privacy Notes
- **Local files**: DuckDB files and plots are stored locally by default (`./dbs`, `./plots`).
- **What goes to the LLM**: The agent sends the **schema snapshot** and a **small result preview** (first rows) along with your **question** and a compact **history summary**—not the full dataset. For stricter controls, reduce or strip the preview passed to the LLM in `duckdb_react_agent.py`.
---
## Extending the App
- **CSV support**: Add a CSV branch next to the Excel ingest that writes to the same DuckDB.
- **Persisted chat**: Save `chat_history` to a file keyed by DB name to restore on reload.
- **Role‑specific prompts**: Swap in system prompts for financial analysis, marketing analytics, etc.
- **Auth & multi‑user**: Gate uploads and route per‑user databases under a workspace prefix.
---
## CLI (Agent Only)
You can also run the agent from the command line for ad‑hoc Q&A:
```bash
python duckdb_react_agent.py --duckdb ./dbs/mydata.duckdb --stream
```
Type your question; the agent prints streaming answers and shows where charts were saved (the Streamlit app displays them inline).
---
## License
Proprietary / internal. Adapt as needed for your environment.
|