DevForML commited on
Commit
6b40452
Β·
verified Β·
1 Parent(s): 9187863

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +347 -337
app.py CHANGED
@@ -1,337 +1,347 @@
1
- # app.py
2
-
3
- import eventlet
4
- eventlet.monkey_patch()
5
-
6
- from flask import Flask, render_template, request, redirect, url_for, flash, session, send_from_directory
7
- from flask_socketio import SocketIO
8
- import traceback
9
- import os
10
- from werkzeug.utils import secure_filename
11
- import json
12
- import logging
13
- import agent # your agent.py module
14
- from agent import refresh_memory
15
- from agent import run_stream
16
- from typing import List, Dict
17
- import markdown2
18
- import re
19
- import time
20
-
21
-
22
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
23
- # ─────────────────────────────────────────────── Inialized VAR & FS ───────────────────────────────────────────────────────────────────
24
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
25
- BASE_DIR = os.path.abspath(os.path.dirname(__file__))
26
-
27
- UPLOAD_FOLDER = os.path.join(BASE_DIR, "uploads")
28
- os.makedirs(UPLOAD_FOLDER, exist_ok=True)
29
-
30
- CHAT_FOLDER = os.path.join(BASE_DIR, "chats")
31
- os.makedirs(CHAT_FOLDER, exist_ok=True)
32
-
33
- app = Flask(__name__, template_folder="templates")
34
-
35
- # For storing the processed files
36
- app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
37
- # For storing the Chat history and other files
38
- app.config["CHAT_FOLDER"] = CHAT_FOLDER
39
-
40
- app.secret_key = os.getenv("FLASK_SECRET", "supersecret")
41
-
42
- # Use eventlet for async SocketIO
43
- socketio = SocketIO(app, cors_allowed_origins="*", async_mode="eventlet")
44
-
45
- # Allowed file extensions
46
- ALLOWED_EXTENSIONS = {
47
- ".db", ".sqlite", # SQLite databases
48
- ".pdf", ".txt", ".doc", ".docx", # Documents
49
- ".png", ".jpg", ".jpeg", ".gif" # Images
50
- }
51
-
52
- import config
53
- DB_PATH = None # will be set when a .db is uploaded
54
- DOC_PATH = None # will be set when a document is uploaded
55
- IMG_PATH = None # will be set when an image is uploaded
56
- OTH_PATH = None # will be set when an other file is uploaded
57
-
58
- # import config
59
- # IMG_PATH = "path/to/user_uploaded_file.jpg"
60
- # DOC_PATH = "path/to/user_uploaded_file.pdf"
61
- # DB_PATH = "path/to/user_uploaded_file.db"
62
- # OTH_PATH = "path/to/user_uploaded_file.txt"
63
-
64
- def allowed_file(filename: str) -> bool:
65
- ext = os.path.splitext(filename.lower())[1]
66
- return ext in ALLOWED_EXTENSIONS
67
-
68
- #text cleaning function
69
- def clean_html_chunk(text):
70
- """
71
- Removes outer <p>...</p> tags and trims extra backticks or 'json' words.
72
- Similar to your 'format:' cleaning logic.
73
- """
74
- text = text.strip()
75
-
76
- # Pattern to match single <p>...</p> wrapping
77
- pattern = r'^<p>(.*?)</p>$'
78
- match = re.match(pattern, text, re.DOTALL)
79
- if match:
80
- text = match.group(1).strip()
81
-
82
- # Extra clean-up (optional, like your example)
83
- text = text.strip('`').strip('json').strip()
84
-
85
- return text
86
-
87
-
88
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
89
- # ─────────────────────────────────────────────── AGENT Defination ────────────────────────────────────────────────────────────────────────────
90
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
91
-
92
- def run_agent_thread(
93
- prompt: str,
94
- user_id: str,
95
- chat_history: List[Dict], # ← new parameter
96
- ):
97
- """
98
- Launches the agent in a background thread, streaming results back over SocketIO.
99
- `data` is the uploaded file path (image, document, or DB) that will be injected
100
- into config before the agent runs.
101
- """
102
- global DB_PATH, DOC_PATH, IMG_PATH, OTH_PATH # force re-initializing agent
103
-
104
- # Build the list of all paths, skipping None or empty
105
- data_paths = [DB_PATH, DOC_PATH, IMG_PATH, OTH_PATH]
106
- data_paths = [p for p in data_paths if p]
107
- print(f"Data paths----------------->: {data_paths}")
108
- text_accum = ""
109
- try:
110
- # Stream using run_stream (which will also pick up the same globals)
111
- for piece in run_stream(prompt, data_paths):
112
- html_chunk = markdown2.markdown(piece, extras=["fenced-code-blocks", "tables", "strike", "task_list", "break-on-newline"])
113
- print(f"HTML chunk: {html_chunk}") # Debugging output
114
- html_chunk = clean_html_chunk(html_chunk)
115
- text_accum += html_chunk # accumulate HTML
116
- socketio.emit("final_stream", {"message": html_chunk})
117
- print(f"Streaming chunk: {html_chunk}") # Debugging output
118
- except Exception as e:
119
- socketio.emit("error", {"message": f"Streaming error: {e}"})
120
- traceback.print_exc()
121
- return
122
-
123
- # Fallback / finalize
124
- try:
125
- if not text_accum:
126
- text_accum = markdown2.markdown(agent.agent.executor.run(prompt), extras=["fenced-code-blocks", "tables", "strike", "task_list", "break-on-newline"])
127
- print(f"Final HTML chunk: {text_accum}") # Debugging output
128
- text_accum = clean_html_chunk(text_accum)
129
- print(f"Final text: {text_accum}") # Debugging output
130
-
131
- socketio.emit("stream_complete", {"message": text_accum})
132
- socketio.emit("final", {"message": text_accum})
133
- chat_history.append({"user": prompt, "assistant": text_accum})
134
-
135
- output_path = os.path.join(
136
- app.config["CHAT_FOLDER"],
137
- f"user_chat_no_{user_id}.json"
138
- )
139
- with open(output_path, "w", encoding="utf-8") as f:
140
- json.dump(chat_history, f, ensure_ascii=False, indent=4)
141
-
142
- except Exception as e:
143
- socketio.emit("error", {"message": f"Final generation error: {e}"})
144
- traceback.print_exc()
145
-
146
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
147
- # ─────────────────────────────────────────────── Main Page ────────────────────────────────────────────────────────────────────────────────
148
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
149
-
150
- @app.route("/")
151
- def index():
152
- if "user_id" not in session:
153
- session["user_id"] = os.urandom(16).hex()
154
- session["uploads"] = []
155
- session["chat_history"] = []
156
- refresh_memory()
157
- else:
158
- # Load previous chat history from JSON file if exists
159
- user_id = session["user_id"]
160
- chat_file = os.path.join(app.config.get("CHAT_FOLDER", "chat_history"), f"user_chat_no_{user_id}.json")
161
- if os.path.exists(chat_file):
162
- with open(chat_file, "r", encoding="utf-8") as f:
163
- session["chat_history"] = json.load(f)
164
-
165
- return render_template("index.html", chat_history=session.get("chat_history", []))
166
-
167
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
168
- # ─────────────────────────────────────────────── Upload section ──────────────────────────────────────────────────────���───────────────────
169
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
170
-
171
- @app.route("/upload", methods=["GET", "POST"])
172
- def upload():
173
- global DB_PATH, DOC_PATH, IMG_PATH, OTH_PATH # force re-initializing agent
174
-
175
- if request.method == "POST":
176
- f = request.files.get("file")
177
- if not f or f.filename == "":
178
- flash("No file selected", "error")
179
- return render_template("upload.html")
180
-
181
- filename = secure_filename(f.filename)
182
- if not allowed_file(filename):
183
- flash("File type not supported", "error")
184
- return render_template("upload.html")
185
-
186
- ext = os.path.splitext(filename.lower())[1]
187
-
188
- if ext in (".db", ".sqlite"):
189
- save_path = os.path.join(app.config["UPLOAD_FOLDER"], "databases", filename)
190
- os.makedirs(os.path.dirname(save_path), exist_ok=True)
191
- global DB_PATH
192
- DB_PATH = save_path
193
- # DB_PATH = f"http://127.0.0.1:5000/uploads/databases/{filename}"
194
- print(f"Database path: {save_path}")
195
- f.save(save_path)
196
- elif ext in (".pdf", ".txt", ".doc", ".docx"):
197
- save_path = os.path.join(app.config["UPLOAD_FOLDER"], "documents", filename)
198
- os.makedirs(os.path.dirname(save_path), exist_ok=True)
199
- global DOC_PATH
200
- DOC_PATH = save_path
201
- # DOC_PATH = f"http://127.0.0.1:5000/uploads/documents/{filename}"
202
- print(f"Document path: {save_path}")
203
- f.save(save_path)
204
- elif ext in (".png", ".jpg", ".jpeg", ".gif"):
205
- save_path = os.path.join(app.config["UPLOAD_FOLDER"], "images", filename)
206
- os.makedirs(os.path.dirname(save_path), exist_ok=True)
207
- global IMG_PATH
208
- IMG_PATH = save_path
209
- # IMG_PATH = f"http://127.0.0.1:5000/uploads/images/{filename}"
210
- print(f"Image path: {save_path}")
211
- f.save(save_path)
212
- else:
213
- save_path = os.path.join(app.config["UPLOAD_FOLDER"], "others", filename)
214
- os.makedirs(os.path.dirname(save_path), exist_ok=True)
215
- global OTH_PATH
216
- OTH_PATH = save_path
217
- # OTH_PATH = f"http://127.0.0.1:5000/uploads/others/{filename}"
218
- print(f"Other file path: {save_path}")
219
- f.save(save_path)
220
-
221
- #f.save(save_path)
222
-
223
- # Add the uploaded file to the session
224
- session["uploads"].append(filename)
225
-
226
- # β€” Database files β€”
227
- if ext in (".db", ".sqlite"):
228
- DB_PATH = save_path
229
- agent.GLOBAL_DB_PATH = DB_PATH
230
- flash(f"Database uploaded and set: {filename}", "success")
231
-
232
- # β€” Documents for RAG indexing β€”
233
- elif ext in (".pdf", ".txt", ".doc", ".docx"):
234
- agent.rag_index_document(save_path)
235
- flash(f"Document indexed for RAG: {filename}", "success")
236
-
237
- # β€” Images or other files β€”
238
- else:
239
- flash(f"File uploaded: {filename}", "success")
240
-
241
- return redirect(url_for("index"))
242
-
243
- # GET
244
- return render_template("upload.html")
245
-
246
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
247
- # ─────────────────────────────────────────────── Static Upload ───────────────────────────────────────────────────────────────────────────
248
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
249
-
250
- @app.route('/uploads/databases/<filename>')
251
- def serve_database(filename):
252
- """
253
- Serve an database file from the uploads/databases folder.
254
- """
255
- return send_from_directory(os.path.join(app.root_path, 'uploads', 'databases'), filename)
256
-
257
- @app.route('/uploads/images/<filename>')
258
- def serve_image(filename):
259
- """
260
- Serve an document file from the uploads/images folder.
261
- """
262
- return send_from_directory(os.path.join(app.root_path, 'uploads', 'images'), filename)
263
-
264
- @app.route('/uploads/documents/<filename>')
265
- def serve_document(filename):
266
- """
267
- Serve an image file from the uploads/documents folder.
268
- """
269
- return send_from_directory(os.path.join(app.root_path, 'uploads', 'documents'), filename)
270
-
271
- @app.route('/uploads/others/<filename>')
272
- def serve_other(filename):
273
- """
274
- Serve an other file from the uploads/others folder.
275
- """
276
- return send_from_directory(os.path.join(app.root_path, 'uploads', 'others'), filename)
277
-
278
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
279
- # ─────────────────────────────────────────────── AGENT calling ───────────────────────────────────────────────────────────────────────────
280
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
281
-
282
- @app.route("/generate", methods=["POST"])
283
- def generate():
284
- prompt = request.json.get("prompt", "").strip()
285
- if not prompt:
286
- return "No prompt provided", 400
287
-
288
- socketio.start_background_task(
289
- run_agent_thread,
290
- prompt,
291
- session["user_id"],
292
- session["chat_history"]
293
- # ← pass it here
294
- )
295
- return "OK", 200
296
-
297
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
298
- # ─────────────────────────────────────────────── SESSION handling ───────────────────────────────────────────────────────────────────────
299
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
300
-
301
- @app.route("/session-info")
302
- def session_info():
303
- # Endpoint to view session details (for debugging purposes)
304
- return {
305
- "user_id": session.get("user_id"),
306
- "uploads": session.get("uploads", [])
307
- }
308
-
309
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
310
- # ─────────────────────────────────────────────── SESSION clearing ───────────────────────────────────────────────────────────────────────
311
- # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
312
-
313
- @app.route("/clear_chat", methods=["POST"])
314
- def clear_chat():
315
- user_id = session.get("user_id")
316
-
317
- # Remove saved JSON chat file
318
- if user_id:
319
- chat_file = os.path.join(app.config["CHAT_FOLDER"], f"user_chat_no_{user_id}.json")
320
- if os.path.exists(chat_file):
321
- os.remove(chat_file)
322
-
323
- # Reset session
324
- session.clear()
325
-
326
- # Generate new session id and chat history
327
- session["user_id"] = os.urandom(16).hex()
328
- session["uploads"] = []
329
- session["chat_history"] = []
330
-
331
- # Refresh agent memory
332
- refresh_memory()
333
-
334
- return {"message": "Chat history and session cleared!"}, 200
335
-
336
- if __name__ == "__main__":
337
- socketio.run(app, debug=True, port=5000)
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+
3
+ import eventlet
4
+ eventlet.monkey_patch()
5
+
6
+ from flask import Flask, render_template, request, redirect, url_for, flash, session, send_from_directory
7
+ from flask_socketio import SocketIO
8
+ import traceback
9
+ import os
10
+ from werkzeug.utils import secure_filename
11
+ import json
12
+ import logging
13
+ import agent # your agent.py module
14
+ from agent import refresh_memory
15
+ from agent import run_stream
16
+ from typing import List, Dict
17
+ import markdown2
18
+ import re
19
+ import time
20
+
21
+
22
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
23
+ # ─────────────────────────────────────────────── Inialized VAR & FS ───────────────────────────────────────────────────────────────────
24
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
25
+ BASE_DIR = os.path.abspath(os.path.dirname(__file__))
26
+
27
+ UPLOAD_FOLDER = os.path.join(BASE_DIR, "uploads")
28
+ os.makedirs(UPLOAD_FOLDER, exist_ok=True)
29
+
30
+ CHAT_FOLDER = os.path.join(BASE_DIR, "chats")
31
+ os.makedirs(CHAT_FOLDER, exist_ok=True)
32
+
33
+ app = Flask(__name__, template_folder="templates")
34
+
35
+ # For storing the processed files
36
+ app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
37
+ # For storing the Chat history and other files
38
+ app.config["CHAT_FOLDER"] = CHAT_FOLDER
39
+
40
+ app.secret_key = os.getenv("FLASK_SECRET", "supersecret")
41
+
42
+ # Use eventlet for async SocketIO
43
+ socketio = SocketIO(app, cors_allowed_origins="*", async_mode="eventlet")
44
+
45
+ # Allowed file extensions
46
+ ALLOWED_EXTENSIONS = {
47
+ ".db", ".sqlite", # SQLite databases
48
+ ".pdf", ".txt", ".doc", ".docx", # Documents
49
+ ".png", ".jpg", ".jpeg", ".gif" # Images
50
+ }
51
+
52
+ import config
53
+ DB_PATH = None # will be set when a .db is uploaded
54
+ DOC_PATH = None # will be set when a document is uploaded
55
+ IMG_PATH = None # will be set when an image is uploaded
56
+ OTH_PATH = None # will be set when an other file is uploaded
57
+
58
+ # import config
59
+ # IMG_PATH = "path/to/user_uploaded_file.jpg"
60
+ # DOC_PATH = "path/to/user_uploaded_file.pdf"
61
+ # DB_PATH = "path/to/user_uploaded_file.db"
62
+ # OTH_PATH = "path/to/user_uploaded_file.txt"
63
+
64
+ def allowed_file(filename: str) -> bool:
65
+ ext = os.path.splitext(filename.lower())[1]
66
+ return ext in ALLOWED_EXTENSIONS
67
+
68
+ def ensure_user_session():
69
+ if "user_id" not in session:
70
+ session["user_id"] = os.urandom(16).hex()
71
+ session["uploads"] = []
72
+ session["chat_history"] = []
73
+ refresh_memory()
74
+
75
+ #text cleaning function
76
+ def clean_html_chunk(text):
77
+ """
78
+ Removes outer <p>...</p> tags and trims extra backticks or 'json' words.
79
+ Similar to your 'format:' cleaning logic.
80
+ """
81
+ text = text.strip()
82
+
83
+ # Pattern to match single <p>...</p> wrapping
84
+ pattern = r'^<p>(.*?)</p>$'
85
+ match = re.match(pattern, text, re.DOTALL)
86
+ if match:
87
+ text = match.group(1).strip()
88
+
89
+ # Extra clean-up (optional, like your example)
90
+ text = text.strip('`').strip('json').strip()
91
+
92
+ return text
93
+
94
+
95
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
96
+ # ──────────────────────────────────��──────────── AGENT Defination ────────────────────────────────────────────────────────────────────────────
97
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
98
+
99
+ def run_agent_thread(
100
+ prompt: str,
101
+ user_id: str,
102
+ chat_history: List[Dict], # ← new parameter
103
+ ):
104
+ """
105
+ Launches the agent in a background thread, streaming results back over SocketIO.
106
+ `data` is the uploaded file path (image, document, or DB) that will be injected
107
+ into config before the agent runs.
108
+ """
109
+ global DB_PATH, DOC_PATH, IMG_PATH, OTH_PATH # force re-initializing agent
110
+
111
+ # Build the list of all paths, skipping None or empty
112
+ data_paths = [DB_PATH, DOC_PATH, IMG_PATH, OTH_PATH]
113
+ data_paths = [p for p in data_paths if p]
114
+ print(f"Data paths----------------->: {data_paths}")
115
+ text_accum = ""
116
+ try:
117
+ # Stream using run_stream (which will also pick up the same globals)
118
+ for piece in run_stream(prompt, data_paths):
119
+ html_chunk = markdown2.markdown(piece, extras=["fenced-code-blocks", "tables", "strike", "task_list", "break-on-newline"])
120
+ print(f"HTML chunk: {html_chunk}") # Debugging output
121
+ html_chunk = clean_html_chunk(html_chunk)
122
+ text_accum += html_chunk # accumulate HTML
123
+ socketio.emit("final_stream", {"message": html_chunk})
124
+ print(f"Streaming chunk: {html_chunk}") # Debugging output
125
+ except Exception as e:
126
+ socketio.emit("error", {"message": f"Streaming error: {e}"})
127
+ traceback.print_exc()
128
+ return
129
+
130
+ # Fallback / finalize
131
+ try:
132
+ if not text_accum:
133
+ text_accum = markdown2.markdown(agent.agent.executor.run(prompt), extras=["fenced-code-blocks", "tables", "strike", "task_list", "break-on-newline"])
134
+ print(f"Final HTML chunk: {text_accum}") # Debugging output
135
+ text_accum = clean_html_chunk(text_accum)
136
+ print(f"Final text: {text_accum}") # Debugging output
137
+
138
+ socketio.emit("stream_complete", {"message": text_accum})
139
+ socketio.emit("final", {"message": text_accum})
140
+ chat_history.append({"user": prompt, "assistant": text_accum})
141
+
142
+ output_path = os.path.join(
143
+ app.config["CHAT_FOLDER"],
144
+ f"user_chat_no_{user_id}.json"
145
+ )
146
+ with open(output_path, "w", encoding="utf-8") as f:
147
+ json.dump(chat_history, f, ensure_ascii=False, indent=4)
148
+
149
+ except Exception as e:
150
+ socketio.emit("error", {"message": f"Final generation error: {e}"})
151
+ traceback.print_exc()
152
+
153
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
154
+ # ─────────────────────────────────────────────── Main Page ────────────────────────────────────────────────────────────────────────────────
155
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
156
+
157
+ @app.route("/")
158
+ def index():
159
+ if "user_id" not in session:
160
+ session["user_id"] = os.urandom(16).hex()
161
+ session["uploads"] = []
162
+ session["chat_history"] = []
163
+ refresh_memory()
164
+ else:
165
+ # Load previous chat history from JSON file if exists
166
+ user_id = session["user_id"]
167
+ chat_file = os.path.join(app.config.get("CHAT_FOLDER", "chat_history"), f"user_chat_no_{user_id}.json")
168
+ if os.path.exists(chat_file):
169
+ with open(chat_file, "r", encoding="utf-8") as f:
170
+ session["chat_history"] = json.load(f)
171
+
172
+ return render_template("index.html", chat_history=session.get("chat_history", []))
173
+
174
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
175
+ # ─────────────────────────────────────────────── Upload section ──────────────────────────────────────────────────────────────────────────
176
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
177
+
178
+ @app.route("/upload", methods=["GET", "POST"])
179
+ def upload():
180
+ ensure_user_session()
181
+ global DB_PATH, DOC_PATH, IMG_PATH, OTH_PATH # force re-initializing agent
182
+
183
+ if request.method == "POST":
184
+ f = request.files.get("file")
185
+ if not f or f.filename == "":
186
+ flash("No file selected", "error")
187
+ return render_template("upload.html")
188
+
189
+ filename = secure_filename(f.filename)
190
+ if not allowed_file(filename):
191
+ flash("File type not supported", "error")
192
+ return render_template("upload.html")
193
+
194
+ ext = os.path.splitext(filename.lower())[1]
195
+
196
+ if ext in (".db", ".sqlite"):
197
+ save_path = os.path.join(app.config["UPLOAD_FOLDER"], "databases", filename)
198
+ os.makedirs(os.path.dirname(save_path), exist_ok=True)
199
+ global DB_PATH
200
+ DB_PATH = save_path
201
+ # DB_PATH = f"http://127.0.0.1:5000/uploads/databases/{filename}"
202
+ print(f"Database path: {save_path}")
203
+ f.save(save_path)
204
+ elif ext in (".pdf", ".txt", ".doc", ".docx"):
205
+ save_path = os.path.join(app.config["UPLOAD_FOLDER"], "documents", filename)
206
+ os.makedirs(os.path.dirname(save_path), exist_ok=True)
207
+ global DOC_PATH
208
+ DOC_PATH = save_path
209
+ # DOC_PATH = f"http://127.0.0.1:5000/uploads/documents/{filename}"
210
+ print(f"Document path: {save_path}")
211
+ f.save(save_path)
212
+ elif ext in (".png", ".jpg", ".jpeg", ".gif"):
213
+ save_path = os.path.join(app.config["UPLOAD_FOLDER"], "images", filename)
214
+ os.makedirs(os.path.dirname(save_path), exist_ok=True)
215
+ global IMG_PATH
216
+ IMG_PATH = save_path
217
+ # IMG_PATH = f"http://127.0.0.1:5000/uploads/images/{filename}"
218
+ print(f"Image path: {save_path}")
219
+ f.save(save_path)
220
+ else:
221
+ save_path = os.path.join(app.config["UPLOAD_FOLDER"], "others", filename)
222
+ os.makedirs(os.path.dirname(save_path), exist_ok=True)
223
+ global OTH_PATH
224
+ OTH_PATH = save_path
225
+ # OTH_PATH = f"http://127.0.0.1:5000/uploads/others/{filename}"
226
+ print(f"Other file path: {save_path}")
227
+ f.save(save_path)
228
+
229
+ #f.save(save_path)
230
+
231
+ # Add the uploaded file to the session
232
+ session["uploads"].append(filename)
233
+
234
+ # β€” Database files β€”
235
+ if ext in (".db", ".sqlite"):
236
+ DB_PATH = save_path
237
+ agent.GLOBAL_DB_PATH = DB_PATH
238
+ flash(f"Database uploaded and set: {filename}", "success")
239
+
240
+ # β€” Documents for RAG indexing β€”
241
+ elif ext in (".pdf", ".txt", ".doc", ".docx"):
242
+ agent.rag_index_document(save_path)
243
+ flash(f"Document indexed for RAG: {filename}", "success")
244
+
245
+ # β€” Images or other files β€”
246
+ else:
247
+ flash(f"File uploaded: {filename}", "success")
248
+
249
+ return redirect(url_for("index"))
250
+
251
+ # GET
252
+ return render_template("upload.html")
253
+
254
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
255
+ # ─────────────────────────────────────────────── Static Upload ───────────────────────────────────────────────────────────────────────────
256
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
257
+
258
+ @app.route('/uploads/databases/<filename>')
259
+ def serve_database(filename):
260
+ """
261
+ Serve an database file from the uploads/databases folder.
262
+ """
263
+ return send_from_directory(os.path.join(app.root_path, 'uploads', 'databases'), filename)
264
+
265
+ @app.route('/uploads/images/<filename>')
266
+ def serve_image(filename):
267
+ """
268
+ Serve an document file from the uploads/images folder.
269
+ """
270
+ return send_from_directory(os.path.join(app.root_path, 'uploads', 'images'), filename)
271
+
272
+ @app.route('/uploads/documents/<filename>')
273
+ def serve_document(filename):
274
+ """
275
+ Serve an image file from the uploads/documents folder.
276
+ """
277
+ return send_from_directory(os.path.join(app.root_path, 'uploads', 'documents'), filename)
278
+
279
+ @app.route('/uploads/others/<filename>')
280
+ def serve_other(filename):
281
+ """
282
+ Serve an other file from the uploads/others folder.
283
+ """
284
+ return send_from_directory(os.path.join(app.root_path, 'uploads', 'others'), filename)
285
+
286
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
287
+ # ─────────────────────────────────────────────── AGENT calling ───────────────────────────────────────────────────────────────────────────
288
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
289
+
290
+ @app.route("/generate", methods=["POST"])
291
+ def generate():
292
+ prompt = request.json.get("prompt", "").strip()
293
+ ensure_user_session()
294
+ if not prompt:
295
+ return "No prompt provided", 400
296
+
297
+ socketio.start_background_task(
298
+ run_agent_thread,
299
+ prompt,
300
+ session["user_id"],
301
+ session["chat_history"]
302
+ # ← pass it here
303
+ )
304
+ return "OK", 200
305
+
306
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
307
+ # ─────────────────────────────────────────────── SESSION handling ───────────────────────────────────────────────────────────────────────
308
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
309
+
310
+ @app.route("/session-info")
311
+ def session_info():
312
+ # Endpoint to view session details (for debugging purposes)
313
+ return {
314
+ "user_id": session.get("user_id"),
315
+ "uploads": session.get("uploads", [])
316
+ }
317
+
318
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
319
+ # ─────────────────────────────────────────────── SESSION clearing ────────���──────────────────────────────────────────────────────────────
320
+ # ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
321
+
322
+ @app.route("/clear_chat", methods=["POST"])
323
+ def clear_chat():
324
+ ensure_user_session()
325
+ user_id = session.get("user_id")
326
+
327
+ # Remove saved JSON chat file
328
+ if user_id:
329
+ chat_file = os.path.join(app.config["CHAT_FOLDER"], f"user_chat_no_{user_id}.json")
330
+ if os.path.exists(chat_file):
331
+ os.remove(chat_file)
332
+
333
+ # Reset session
334
+ session.clear()
335
+
336
+ # Generate new session id and chat history
337
+ session["user_id"] = os.urandom(16).hex()
338
+ session["uploads"] = []
339
+ session["chat_history"] = []
340
+
341
+ # Refresh agent memory
342
+ refresh_memory()
343
+
344
+ return {"message": "Chat history and session cleared!"}, 200
345
+
346
+ if __name__ == "__main__":
347
+ socketio.run(app, debug=True, port=5000)