cryogenic22 commited on
Commit
cfff021
·
verified ·
1 Parent(s): bd1d92a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +169 -6
app.py CHANGED
@@ -1,6 +1,8 @@
 
1
  from fastapi import FastAPI, UploadFile, File
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from fastapi.staticfiles import StaticFiles
 
4
  import pandas as pd
5
  from sentence_transformers import SentenceTransformer
6
  import numpy as np
@@ -20,24 +22,24 @@ app.add_middleware(
20
  allow_headers=["*"],
21
  )
22
 
 
 
 
 
23
  @app.post("/api/process-file")
24
  async def process_file(file: UploadFile = File(...)):
25
  content = await file.read()
26
 
27
- # Save temporarily
28
  with open(f"temp_{file.filename}", "wb") as f:
29
  f.write(content)
30
 
31
- # Read file
32
  df = pd.read_excel(f"temp_{file.filename}") if file.filename.endswith('.xlsx') else pd.read_csv(f"temp_{file.filename}")
33
 
34
- # Create text representations
35
  text_reps = []
36
  for _, row in df.iterrows():
37
  text_rep = " ".join([f"{col}: {val}" for col, val in row.items()])
38
  text_reps.append(text_rep)
39
 
40
- # Generate embeddings
41
  embeddings = model.encode(text_reps)
42
 
43
  metadata = {
@@ -62,5 +64,166 @@ async def query_data(query: str, embeddings: List[List[float]], k: int = 5):
62
  indices = np.argsort(similarities)[-k:][::-1].tolist()
63
  return {"similar_indices": indices}
64
 
65
- # Mount static files at root
66
- app.mount("/", StaticFiles(directory="static", html=True), name="static")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
  from fastapi import FastAPI, UploadFile, File
3
  from fastapi.middleware.cors import CORSMiddleware
4
  from fastapi.staticfiles import StaticFiles
5
+ from fastapi.responses import FileResponse
6
  import pandas as pd
7
  from sentence_transformers import SentenceTransformer
8
  import numpy as np
 
22
  allow_headers=["*"],
23
  )
24
 
25
+ @app.get("/")
26
+ async def read_root():
27
+ return FileResponse('static/index.html')
28
+
29
  @app.post("/api/process-file")
30
  async def process_file(file: UploadFile = File(...)):
31
  content = await file.read()
32
 
 
33
  with open(f"temp_{file.filename}", "wb") as f:
34
  f.write(content)
35
 
 
36
  df = pd.read_excel(f"temp_{file.filename}") if file.filename.endswith('.xlsx') else pd.read_csv(f"temp_{file.filename}")
37
 
 
38
  text_reps = []
39
  for _, row in df.iterrows():
40
  text_rep = " ".join([f"{col}: {val}" for col, val in row.items()])
41
  text_reps.append(text_rep)
42
 
 
43
  embeddings = model.encode(text_reps)
44
 
45
  metadata = {
 
64
  indices = np.argsort(similarities)[-k:][::-1].tolist()
65
  return {"similar_indices": indices}
66
 
67
+ app.mount("/static", StaticFiles(directory="static"), name="static")
68
+
69
+ # Dockerfile
70
+ FROM python:3.9-slim
71
+
72
+ WORKDIR /code
73
+
74
+ RUN mkdir -p /cache && chmod 777 /cache
75
+ ENV HF_HOME=/cache
76
+
77
+ COPY requirements.txt .
78
+ RUN pip install -r requirements.txt
79
+
80
+ COPY . .
81
+
82
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
83
+
84
+ # requirements.txt
85
+ fastapi==0.104.1
86
+ uvicorn==0.24.0
87
+ anthropic==0.5.0
88
+ python-multipart==0.0.6
89
+ sentence-transformers==2.2.2
90
+ pandas==2.1.3
91
+ numpy==1.26.2
92
+
93
+ # static/index.html
94
+ <!DOCTYPE html>
95
+ <html lang="en">
96
+ <head>
97
+ <meta charset="UTF-8">
98
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
99
+ <title>Analytics Dashboard</title>
100
+ <script src="https://cdn.tailwindcss.com"></script>
101
+ <script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
102
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
103
+ <script src="https://unpkg.com/recharts/umd/Recharts.min.js"></script>
104
+ <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
105
+ </head>
106
+ <body>
107
+ <div id="root"></div>
108
+ <script type="text/babel" src="/static/app.js"></script>
109
+ </body>
110
+ </html>
111
+
112
+ # static/app.js
113
+ const { useState } = React;
114
+ const { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer } = Recharts;
115
+
116
+ function App() {
117
+ const [data, setData] = useState(null);
118
+ const [query, setQuery] = useState('');
119
+ const [insights, setInsights] = useState([]);
120
+
121
+ const handleFileUpload = async (event) => {
122
+ const file = event.target.files[0];
123
+ const formData = new FormData();
124
+ formData.append('file', file);
125
+
126
+ const response = await fetch('/api/process-file', {
127
+ method: 'POST',
128
+ body: formData,
129
+ });
130
+ const result = await response.json();
131
+ setData(result);
132
+ };
133
+
134
+ const handleQuery = async () => {
135
+ if (!data || !query) return;
136
+
137
+ const response = await fetch('/api/query', {
138
+ method: 'POST',
139
+ headers: { 'Content-Type': 'application/json' },
140
+ body: JSON.stringify({
141
+ query,
142
+ embeddings: data.embeddings
143
+ }),
144
+ });
145
+
146
+ const result = await response.json();
147
+ const newInsights = result.similar_indices.map(idx => data.raw_data[idx]);
148
+ setInsights(newInsights);
149
+ };
150
+
151
+ return (
152
+ <div className="p-6 max-w-6xl mx-auto">
153
+ <div className="mb-6">
154
+ <label className="block mb-2 text-sm font-medium">
155
+ Upload Data File
156
+ </label>
157
+ <div className="flex items-center justify-center w-full">
158
+ <label className="flex flex-col items-center justify-center w-full h-32 border-2 border-dashed rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100">
159
+ <div className="flex flex-col items-center justify-center pt-5 pb-6">
160
+ <svg className="w-8 h-8 mb-4 text-gray-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 16">
161
+ <path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2"/>
162
+ </svg>
163
+ <p className="mb-2 text-sm text-gray-500">
164
+ <span className="font-semibold">Click to upload</span> or drag and drop
165
+ </p>
166
+ </div>
167
+ <input
168
+ type="file"
169
+ className="hidden"
170
+ onChange={handleFileUpload}
171
+ accept=".csv,.xlsx,.xls"
172
+ />
173
+ </label>
174
+ </div>
175
+ </div>
176
+
177
+ {data && (
178
+ <div className="space-y-6">
179
+ <div>
180
+ <input
181
+ type="text"
182
+ value={query}
183
+ onChange={(e) => setQuery(e.target.value)}
184
+ placeholder="Ask a question about your data..."
185
+ className="w-full p-2 border rounded"
186
+ />
187
+ <button
188
+ onClick={handleQuery}
189
+ className="mt-2 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
190
+ >
191
+ Search
192
+ </button>
193
+ </div>
194
+
195
+ {insights.length > 0 && (
196
+ <div className="mt-6">
197
+ <h3 className="text-lg font-semibold mb-4">Related Insights</h3>
198
+ <div className="h-64">
199
+ <ResponsiveContainer width="100%" height="100%">
200
+ <BarChart data={insights}>
201
+ {Object.keys(insights[0] || {}).map((key) => (
202
+ <Bar key={key} dataKey={key} fill="#8884d8" />
203
+ ))}
204
+ <XAxis />
205
+ <YAxis />
206
+ <Tooltip />
207
+ </BarChart>
208
+ </ResponsiveContainer>
209
+ </div>
210
+ <div className="mt-4 space-y-2">
211
+ {insights.map((insight, idx) => (
212
+ <div key={idx} className="p-4 bg-gray-50 rounded">
213
+ {Object.entries(insight).map(([key, value]) => (
214
+ <div key={key}>
215
+ <span className="font-medium">{key}:</span> {value}
216
+ </div>
217
+ ))}
218
+ </div>
219
+ ))}
220
+ </div>
221
+ </div>
222
+ )}
223
+ </div>
224
+ )}
225
+ </div>
226
+ );
227
+ }
228
+
229
+ ReactDOM.render(<App />, document.getElementById('root'));