triflix commited on
Commit
b1aea0a
·
verified ·
1 Parent(s): 6ef03c1

Upload 7 files

Browse files
Files changed (7) hide show
  1. .gitattributes +35 -35
  2. Dockerfile +12 -0
  3. README.md +10 -10
  4. main.py +100 -0
  5. requirements.txt +6 -0
  6. static/tailwind.css +1 -0
  7. templates/index.html +45 -0
.gitattributes CHANGED
@@ -1,35 +1,35 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.12-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install --no-cache-dir -r requirements.txt
7
+
8
+ COPY . .
9
+
10
+ EXPOSE 7860
11
+
12
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,10 +1,10 @@
1
- ---
2
- title: Chatplot
3
- emoji: ⚡
4
- colorFrom: red
5
- colorTo: indigo
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ ---
2
+ title: Chatplot
3
+ emoji: ⚡
4
+ colorFrom: red
5
+ colorTo: indigo
6
+ sdk: docker
7
+ pinned: false
8
+ ---
9
+
10
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
main.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, Request
2
+ from fastapi.responses import HTMLResponse, JSONResponse
3
+ from fastapi.staticfiles import StaticFiles
4
+ from fastapi.templating import Jinja2Templates
5
+ from io import BytesIO
6
+ import base64
7
+ import matplotlib.pyplot as plt
8
+ import pandas as pd
9
+ from google import genai
10
+ from google.genai import types
11
+ import os
12
+
13
+ # ---- User configuration ----
14
+ API_KEY = os.getenv("GEMINI_API_KEY", "YOUR_API_KEY")
15
+ EXCEL_FILE = "/content/heart_failure_clinical_records_dashboard.xlsx"
16
+
17
+ client = genai.Client(api_key=API_KEY)
18
+ MODEL = "gemini-2.5-flash-lite"
19
+
20
+ # FastAPI setup
21
+ app = FastAPI()
22
+ app.mount("/static", StaticFiles(directory="static"), name="static")
23
+ templates = Jinja2Templates(directory="templates")
24
+
25
+ # Load dataset
26
+ df = pd.read_excel(EXCEL_FILE)
27
+
28
+ def get_metadata(df):
29
+ return {
30
+ "columns": list(df.columns),
31
+ "dtypes": df.dtypes.apply(lambda x: str(x)).to_dict(),
32
+ "num_rows": df.shape[0],
33
+ "num_cols": df.shape[1],
34
+ "null_counts": df.isnull().sum().to_dict(),
35
+ "unique_counts": df.nunique().to_dict(),
36
+ "sample_rows": df.head(3).to_dict(orient="records")
37
+ }
38
+
39
+ def generate_plot_code(user_query, metadata):
40
+ system_prompt = f"""
41
+ You are a Python plotting assistant.
42
+ Use the existing DataFrame named df.
43
+ Do NOT load any files.
44
+ Use only matplotlib or pandas plotting.
45
+ Use only the following columns: {metadata['columns']}.
46
+ Do NOT explain, do NOT add extra text.
47
+ Only produce executable code for plotting the requested chart.
48
+ """
49
+ user_prompt = f"""
50
+ Dataset metadata:
51
+ Columns: {metadata['columns']}
52
+ Data types: {metadata['dtypes']}
53
+ Null counts: {metadata['null_counts']}
54
+ Unique counts: {metadata['unique_counts']}
55
+ Sample rows: {metadata['sample_rows']}
56
+
57
+ User request: {user_query}
58
+ """
59
+ contents = [types.Content(role="user", parts=[types.Part.from_text(text=user_prompt)])]
60
+ config = types.GenerateContentConfig(
61
+ temperature=0,
62
+ max_output_tokens=1000,
63
+ thinking_config=types.ThinkingConfig(thinking_budget=0),
64
+ system_instruction=[types.Part.from_text(text=system_prompt)]
65
+ )
66
+
67
+ code = ""
68
+ for chunk in client.models.generate_content_stream(model=MODEL, contents=contents, config=config):
69
+ code += chunk.text
70
+ return code.replace("```python", "").replace("```", "").strip()
71
+
72
+ @app.get("/", response_class=HTMLResponse)
73
+ async def home(request: Request):
74
+ return templates.TemplateResponse("index.html", {"request": request})
75
+
76
+ @app.post("/generate_plot")
77
+ async def generate_plot(request: Request):
78
+ data = await request.json()
79
+ user_query = data.get("query", "")
80
+ metadata = get_metadata(df)
81
+
82
+ # Generate code
83
+ code = generate_plot_code(user_query, metadata)
84
+
85
+ # Execute code and generate plot
86
+ try:
87
+ exec_globals = {"df": df, "plt": plt}
88
+ exec(code, exec_globals)
89
+ buf = BytesIO()
90
+ plt.savefig(buf, format="png")
91
+ plt.close()
92
+ buf.seek(0)
93
+ img_base64 = base64.b64encode(buf.read()).decode("utf-8")
94
+ success = True
95
+ except Exception as e:
96
+ img_base64 = ""
97
+ success = False
98
+ code += f"\n\n# ERROR: {str(e)}"
99
+
100
+ return JSONResponse({"success": success, "plot": img_base64, "code": code})
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ jinja2
4
+ pandas
5
+ matplotlib
6
+ google-genai
static/tailwind.css ADDED
@@ -0,0 +1 @@
 
 
1
+ @import url('https://cdn.jsdelivr.net/npm/tailwindcss@3.3.3/dist/tailwind.min.css');
templates/index.html ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AI Plotting App</title>
7
+ <link href="/static/tailwind.css" rel="stylesheet">
8
+ </head>
9
+ <body class="bg-gray-100 min-h-screen flex flex-col items-center p-4">
10
+
11
+ <h1 class="text-2xl font-bold mb-4">AI Plotting App</h1>
12
+
13
+ <div class="w-full max-w-2xl bg-white p-4 rounded shadow mb-4">
14
+ <input id="userQuery" type="text" placeholder="Enter plot request..." class="w-full border p-2 rounded mb-2">
15
+ <button onclick="generatePlot()" class="bg-blue-600 text-white px-4 py-2 rounded">Generate Plot</button>
16
+ </div>
17
+
18
+ <div class="w-full max-w-2xl bg-white p-4 rounded shadow mb-4">
19
+ <h2 class="font-bold mb-2">Plot Output</h2>
20
+ <img id="plotImg" class="w-full" />
21
+ </div>
22
+
23
+ <div class="w-full max-w-2xl bg-white p-4 rounded shadow">
24
+ <h2 class="font-bold mb-2">Generated Code & Console</h2>
25
+ <pre id="consoleOutput" class="overflow-x-auto"></pre>
26
+ </div>
27
+
28
+ <script>
29
+ async function generatePlot() {
30
+ const query = document.getElementById("userQuery").value;
31
+ const response = await fetch("/generate_plot", {
32
+ method: "POST",
33
+ headers: {"Content-Type": "application/json"},
34
+ body: JSON.stringify({query})
35
+ });
36
+ const data = await response.json();
37
+ if(data.success){
38
+ document.getElementById("plotImg").src = "data:image/png;base64," + data.plot;
39
+ }
40
+ document.getElementById("consoleOutput").textContent = data.code;
41
+ }
42
+ </script>
43
+
44
+ </body>
45
+ </html>