cryogenic22 commited on
Commit
274299c
·
verified ·
1 Parent(s): 604238b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +161 -86
app.py CHANGED
@@ -1,112 +1,178 @@
1
- from fastapi import FastAPI, UploadFile, File
2
- from fastapi.responses import HTMLResponse
 
3
  import pandas as pd
4
  from sentence_transformers import SentenceTransformer
5
  import numpy as np
6
- from typing import List
 
7
  import os
8
 
9
  app = FastAPI()
10
  model = SentenceTransformer('all-MiniLM-L6-v2')
11
 
 
 
 
 
12
  @app.get("/", response_class=HTMLResponse)
13
  async def root():
14
  return """
15
  <!DOCTYPE html>
16
- <html lang="en">
17
  <head>
18
- <meta charset="UTF-8">
19
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
20
  <title>Analytics Dashboard</title>
21
- <script src="https://cdn.tailwindcss.com"></script>
22
- <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
23
- <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
24
- <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
25
  <script src="https://unpkg.com/recharts@2.1.9/umd/Recharts.js"></script>
 
 
 
 
 
26
  <script type="text/babel">
27
- const { useState } = React;
28
- const { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer } = Recharts;
29
-
30
  function App() {
31
- const [data, setData] = useState(null);
32
- const [query, setQuery] = useState('');
33
- const [insights, setInsights] = useState([]);
 
 
34
 
35
  const handleFileUpload = async (event) => {
36
  const file = event.target.files[0];
 
 
 
 
37
  const formData = new FormData();
38
  formData.append('file', file);
39
 
40
- const response = await fetch('/api/process-file', {
41
- method: 'POST',
42
- body: formData,
43
- });
44
- const result = await response.json();
45
- setData(result);
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  };
47
 
48
  const handleQuery = async () => {
49
  if (!data || !query) return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
- const response = await fetch('/api/query', {
52
- method: 'POST',
53
- headers: { 'Content-Type': 'application/json' },
54
- body: JSON.stringify({
55
- query,
56
- embeddings: data.embeddings
57
- }),
58
- });
59
-
60
- const result = await response.json();
61
- const newInsights = result.similar_indices.map(idx => data.raw_data[idx]);
62
- setInsights(newInsights);
 
 
63
  };
64
 
65
  return (
66
  <div className="p-6 max-w-6xl mx-auto">
67
- <h1 className="text-2xl font-bold mb-6">Data Analytics Dashboard</h1>
68
- <div className="mb-6">
69
- <label className="block mb-2 text-sm font-medium">Upload Data File</label>
 
 
 
 
 
 
 
 
 
70
  <input
71
  type="file"
72
  onChange={handleFileUpload}
73
  accept=".csv,.xlsx,.xls"
74
  className="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100"
 
75
  />
76
  </div>
77
 
78
  {data && (
79
  <div className="space-y-6">
80
- <div>
81
  <input
82
  type="text"
83
  value={query}
84
  onChange={(e) => setQuery(e.target.value)}
85
  placeholder="Ask a question about your data..."
86
- className="w-full p-2 border rounded"
 
87
  />
88
  <button
89
  onClick={handleQuery}
90
- className="mt-2 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
 
91
  >
92
- Search
93
  </button>
94
  </div>
95
 
96
  {insights.length > 0 && (
97
- <div className="mt-6">
98
- <h3 className="text-lg font-semibold mb-4">Related Insights</h3>
99
- <div className="h-64">
100
- <ResponsiveContainer width="100%" height="100%">
101
- <BarChart data={insights}>
102
- {Object.keys(insights[0] || {}).map((key) => (
103
- <Bar key={key} dataKey={key} fill="#8884d8" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  ))}
105
- <XAxis />
106
- <YAxis />
107
- <Tooltip />
108
- </BarChart>
109
- </ResponsiveContainer>
110
  </div>
111
  </div>
112
  )}
@@ -118,44 +184,53 @@ async def root():
118
 
119
  ReactDOM.render(<App />, document.getElementById('root'));
120
  </script>
121
- </head>
122
- <body>
123
- <div id="root"></div>
124
  </body>
125
  </html>
126
  """
127
 
128
  @app.post("/api/process-file")
129
  async def process_file(file: UploadFile = File(...)):
130
- content = await file.read()
131
- with open(f"temp_{file.filename}", "wb") as f:
132
- f.write(content)
133
-
134
- df = pd.read_excel(f"temp_{file.filename}") if file.filename.endswith('.xlsx') else pd.read_csv(f"temp_{file.filename}")
135
-
136
- text_reps = []
137
- for _, row in df.iterrows():
138
- text_rep = " ".join([f"{col}: {val}" for col, val in row.items()])
139
- text_reps.append(text_rep)
140
-
141
- embeddings = model.encode(text_reps)
142
- metadata = {
143
- 'columns': list(df.columns),
144
- 'row_count': len(df),
145
- 'numerical_cols': list(df.select_dtypes(include=[np.number]).columns),
146
- 'categorical_cols': list(df.select_dtypes(include=['object']).columns)
147
- }
148
-
149
- os.remove(f"temp_{file.filename}")
150
- return {
151
- 'embeddings': embeddings.tolist(),
152
- 'metadata': metadata,
153
- 'raw_data': df.to_dict('records')
154
- }
 
 
 
 
 
 
155
 
156
  @app.post("/api/query")
157
- async def query_data(query: str, embeddings: List[List[float]], k: int = 5):
158
- query_embedding = model.encode([query])[0]
159
- similarities = np.dot(embeddings, query_embedding)
160
- indices = np.argsort(similarities)[-k:][::-1].tolist()
161
- return {"similar_indices": indices}
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, UploadFile, File, Request
2
+ from fastapi.responses import HTMLResponse, JSONResponse
3
+ from pydantic import BaseModel
4
  import pandas as pd
5
  from sentence_transformers import SentenceTransformer
6
  import numpy as np
7
+ from typing import List, Dict
8
+ import json
9
  import os
10
 
11
  app = FastAPI()
12
  model = SentenceTransformer('all-MiniLM-L6-v2')
13
 
14
+ class QueryRequest(BaseModel):
15
+ query: str
16
+ embeddings: List[List[float]]
17
+
18
  @app.get("/", response_class=HTMLResponse)
19
  async def root():
20
  return """
21
  <!DOCTYPE html>
22
+ <html>
23
  <head>
 
 
24
  <title>Analytics Dashboard</title>
25
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
26
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
 
 
27
  <script src="https://unpkg.com/recharts@2.1.9/umd/Recharts.js"></script>
28
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
29
+ <script src="https://cdn.tailwindcss.com"></script>
30
+ </head>
31
+ <body>
32
+ <div id="root"></div>
33
  <script type="text/babel">
 
 
 
34
  function App() {
35
+ const [data, setData] = React.useState(null);
36
+ const [query, setQuery] = React.useState('');
37
+ const [insights, setInsights] = React.useState([]);
38
+ const [loading, setLoading] = React.useState(false);
39
+ const [error, setError] = React.useState(null);
40
 
41
  const handleFileUpload = async (event) => {
42
  const file = event.target.files[0];
43
+ if (!file) return;
44
+
45
+ setLoading(true);
46
+ setError(null);
47
  const formData = new FormData();
48
  formData.append('file', file);
49
 
50
+ try {
51
+ const response = await fetch('/api/process-file', {
52
+ method: 'POST',
53
+ body: formData,
54
+ });
55
+
56
+ if (!response.ok) {
57
+ throw new Error('Upload failed');
58
+ }
59
+
60
+ const result = await response.json();
61
+ console.log('Upload result:', result);
62
+ setData(result);
63
+ } catch (err) {
64
+ console.error('Upload error:', err);
65
+ setError('Failed to upload file');
66
+ } finally {
67
+ setLoading(false);
68
+ }
69
  };
70
 
71
  const handleQuery = async () => {
72
  if (!data || !query) return;
73
+ setLoading(true);
74
+ setError(null);
75
+
76
+ try {
77
+ const response = await fetch('/api/query', {
78
+ method: 'POST',
79
+ headers: {
80
+ 'Content-Type': 'application/json',
81
+ },
82
+ body: JSON.stringify({
83
+ query: query,
84
+ embeddings: data.embeddings
85
+ })
86
+ });
87
 
88
+ if (!response.ok) {
89
+ throw new Error('Query failed');
90
+ }
91
+
92
+ const result = await response.json();
93
+ console.log('Query result:', result);
94
+ const newInsights = result.similar_indices.map(idx => data.raw_data[idx]);
95
+ setInsights(newInsights);
96
+ } catch (err) {
97
+ console.error('Query error:', err);
98
+ setError('Failed to process query');
99
+ } finally {
100
+ setLoading(false);
101
+ }
102
  };
103
 
104
  return (
105
  <div className="p-6 max-w-6xl mx-auto">
106
+ <h1 className="text-3xl font-bold mb-8">Data Analytics Dashboard</h1>
107
+
108
+ {error && (
109
+ <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
110
+ {error}
111
+ </div>
112
+ )}
113
+
114
+ <div className="mb-8">
115
+ <label className="block text-sm font-medium mb-2">
116
+ Upload Data File (.csv, .xlsx)
117
+ </label>
118
  <input
119
  type="file"
120
  onChange={handleFileUpload}
121
  accept=".csv,.xlsx,.xls"
122
  className="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100"
123
+ disabled={loading}
124
  />
125
  </div>
126
 
127
  {data && (
128
  <div className="space-y-6">
129
+ <div className="flex gap-2">
130
  <input
131
  type="text"
132
  value={query}
133
  onChange={(e) => setQuery(e.target.value)}
134
  placeholder="Ask a question about your data..."
135
+ className="flex-1 p-2 border rounded"
136
+ disabled={loading}
137
  />
138
  <button
139
  onClick={handleQuery}
140
+ className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50"
141
+ disabled={loading || !query}
142
  >
143
+ {loading ? 'Processing...' : 'Search'}
144
  </button>
145
  </div>
146
 
147
  {insights.length > 0 && (
148
+ <div className="mt-8">
149
+ <h3 className="text-xl font-semibold mb-4">Related Insights</h3>
150
+ <div className="h-96 mb-8">
151
+ <Recharts.ResponsiveContainer width="100%" height="100%">
152
+ <Recharts.BarChart data={insights}>
153
+ {Object.keys(insights[0] || {})
154
+ .filter(key => typeof insights[0][key] === 'number')
155
+ .map((key) => (
156
+ <Recharts.Bar key={key} dataKey={key} fill="#8884d8" />
157
+ ))}
158
+ <Recharts.XAxis />
159
+ <Recharts.YAxis />
160
+ <Recharts.Tooltip />
161
+ <Recharts.Legend />
162
+ </Recharts.BarChart>
163
+ </Recharts.ResponsiveContainer>
164
+ </div>
165
+ <div className="grid gap-4">
166
+ {insights.map((insight, idx) => (
167
+ <div key={idx} className="p-4 bg-gray-50 rounded shadow">
168
+ {Object.entries(insight).map(([key, value]) => (
169
+ <div key={key} className="mb-1">
170
+ <span className="font-medium">{key}:</span>{' '}
171
+ {typeof value === 'number' ? value.toFixed(2) : value}
172
+ </div>
173
  ))}
174
+ </div>
175
+ ))}
 
 
 
176
  </div>
177
  </div>
178
  )}
 
184
 
185
  ReactDOM.render(<App />, document.getElementById('root'));
186
  </script>
 
 
 
187
  </body>
188
  </html>
189
  """
190
 
191
  @app.post("/api/process-file")
192
  async def process_file(file: UploadFile = File(...)):
193
+ try:
194
+ content = await file.read()
195
+ with open(f"temp_{file.filename}", "wb") as f:
196
+ f.write(content)
197
+
198
+ df = pd.read_excel(f"temp_{file.filename}") if file.filename.endswith('.xlsx') else pd.read_csv(f"temp_{file.filename}")
199
+
200
+ text_reps = []
201
+ for _, row in df.iterrows():
202
+ text_rep = " ".join([f"{col}: {val}" for col, val in row.items()])
203
+ text_reps.append(text_rep)
204
+
205
+ embeddings = model.encode(text_reps)
206
+ metadata = {
207
+ 'columns': list(df.columns),
208
+ 'row_count': len(df),
209
+ 'numerical_cols': list(df.select_dtypes(include=[np.number]).columns),
210
+ 'categorical_cols': list(df.select_dtypes(include=['object']).columns)
211
+ }
212
+
213
+ os.remove(f"temp_{file.filename}")
214
+ return JSONResponse({
215
+ 'embeddings': embeddings.tolist(),
216
+ 'metadata': metadata,
217
+ 'raw_data': df.to_dict('records')
218
+ })
219
+ except Exception as e:
220
+ return JSONResponse(
221
+ status_code=500,
222
+ content={"error": str(e)}
223
+ )
224
 
225
  @app.post("/api/query")
226
+ async def query_data(request: QueryRequest):
227
+ try:
228
+ query_embedding = model.encode([request.query])[0]
229
+ similarities = np.dot(request.embeddings, query_embedding)
230
+ indices = np.argsort(similarities)[-5:][::-1].tolist()
231
+ return JSONResponse({"similar_indices": indices})
232
+ except Exception as e:
233
+ return JSONResponse(
234
+ status_code=500,
235
+ content={"error": str(e)}
236
+ )