CoolFace
Apppublic

DevForML/Multi_Agent_System

sourceHugging Facemitupdated 1y agoView on Hugging Face
0likes
app.py353 linesDownload Raw Back to root
1# app.py2 3import eventlet4eventlet.monkey_patch()5 6from flask import Flask, render_template, request, redirect, url_for, flash, session, send_from_directory7from flask_socketio import SocketIO8import traceback9import os10from werkzeug.utils import secure_filename11import json12import logging13import agent # your agent.py module14from agent import refresh_memory15from agent import run_stream 16from typing import List, Dict17import markdown218import re19import time20 21 22# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────23# ─────────────────────────────────────────────── Inialized VAR & FS ───────────────────────────────────────────────────────────────────24# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────25BASE_DIR = os.path.abspath(os.path.dirname(__file__))26 27UPLOAD_FOLDER = os.path.join(BASE_DIR, "uploads")28os.makedirs(UPLOAD_FOLDER, exist_ok=True)29 30CHAT_FOLDER = os.path.join(BASE_DIR, "chats")31os.makedirs(CHAT_FOLDER, exist_ok=True)32 33try:34    os.chmod(CHAT_FOLDER, 0o777)35except Exception:36    pass37 38app = Flask(__name__, template_folder="templates")39 40# For storing the processed files41app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER42# For storing the Chat history and other files43app.config["CHAT_FOLDER"] = CHAT_FOLDER44 45app.secret_key = os.getenv("FLASK_SECRET", "supersecret")46 47# Use eventlet for async SocketIO48socketio = SocketIO(app, cors_allowed_origins="*", async_mode="eventlet")49 50# Allowed file extensions51ALLOWED_EXTENSIONS = {52    ".db", ".sqlite",              # SQLite databases53    ".pdf", ".txt", ".doc", ".docx",  # Documents54    ".png", ".jpg", ".jpeg", ".gif"    # Images55}56 57import config58DB_PATH = None  # will be set when a .db is uploaded59DOC_PATH = None  # will be set when a document is uploaded60IMG_PATH = None  # will be set when an image is uploaded61OTH_PATH = None  # will be set when an other file is uploaded62 63# import config64# IMG_PATH = "path/to/user_uploaded_file.jpg"65# DOC_PATH = "path/to/user_uploaded_file.pdf"66# DB_PATH = "path/to/user_uploaded_file.db"67# OTH_PATH = "path/to/user_uploaded_file.txt"68 69def allowed_file(filename: str) -> bool:70    ext = os.path.splitext(filename.lower())[1]71    return ext in ALLOWED_EXTENSIONS72 73def ensure_user_session():74    if "user_id" not in session:75        session["user_id"] = os.urandom(16).hex()76        session["uploads"] = []77        session["chat_history"] = []78        refresh_memory()79 80#text cleaning function81def clean_html_chunk(text):82    """83    Removes outer <p>...</p> tags and trims extra backticks or 'json' words.84    Similar to your 'format:' cleaning logic.85    """86    text = text.strip()87    88    # Pattern to match single <p>...</p> wrapping89    pattern = r'^<p>(.*?)</p>$'90    match = re.match(pattern, text, re.DOTALL)91    if match:92        text = match.group(1).strip()93 94    # Extra clean-up (optional, like your example)95    text = text.strip('`').strip('json').strip()96 97    return text98 99 100# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────101# ─────────────────────────────────────────────── AGENT Defination ────────────────────────────────────────────────────────────────────────────102# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────103 104def run_agent_thread(105    prompt: str,106    user_id: str,107    chat_history: List[Dict],           # ← new parameter108):109    """110    Launches the agent in a background thread, streaming results back over SocketIO.111    `data` is the uploaded file path (image, document, or DB) that will be injected112    into config before the agent runs.113    """114    global DB_PATH, DOC_PATH, IMG_PATH, OTH_PATH  # force re-initializing agent115           116    # Build the list of all paths, skipping None or empty117    data_paths = [DB_PATH, DOC_PATH, IMG_PATH, OTH_PATH]118    data_paths = [p for p in data_paths if p]119    print(f"Data paths----------------->: {data_paths}")120    text_accum = ""121    try:122        # Stream using run_stream (which will also pick up the same globals)123        for piece in run_stream(prompt, data_paths):124            html_chunk = markdown2.markdown(piece, extras=["fenced-code-blocks", "tables", "strike", "task_list", "break-on-newline"])125            print(f"HTML chunk: {html_chunk}")  # Debugging output126            html_chunk = clean_html_chunk(html_chunk)127            text_accum  += html_chunk            # accumulate HTML128            socketio.emit("final_stream", {"message": html_chunk})129            print(f"Streaming chunk: {html_chunk}")  # Debugging output130    except Exception as e:131        socketio.emit("error", {"message": f"Streaming error: {e}"})132        traceback.print_exc()133        return134 135    # Fallback / finalize136    try:137        if not text_accum:138            text_accum = markdown2.markdown(agent.agent.executor.run(prompt), extras=["fenced-code-blocks", "tables", "strike", "task_list", "break-on-newline"])139            print(f"Final HTML chunk: {text_accum}")  # Debugging output140            text_accum = clean_html_chunk(text_accum)141            print(f"Final text: {text_accum}")  # Debugging output142            143        socketio.emit("stream_complete", {"message": text_accum})144        socketio.emit("final", {"message": text_accum})145        chat_history.append({"user": prompt, "assistant": text_accum})146 147        output_path = os.path.join(148            app.config["CHAT_FOLDER"],149            f"user_chat_no_{user_id}.json"150        )151        with open(output_path, "w", encoding="utf-8") as f:152            json.dump(chat_history, f, ensure_ascii=False, indent=4)153 154    except Exception as e:155        socketio.emit("error", {"message": f"Final generation error: {e}"})156        traceback.print_exc()157        158# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────159# ─────────────────────────────────────────────── Main Page ────────────────────────────────────────────────────────────────────────────────160# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────161 162@app.route("/")163def index():164    if "user_id" not in session:165        session["user_id"] = os.urandom(16).hex()166        session["uploads"] = []167        session["chat_history"] = []168        refresh_memory()169    else:170        # Load previous chat history from JSON file if exists171        user_id = session["user_id"]172        chat_file = os.path.join(app.config.get("CHAT_FOLDER", "chat_history"), f"user_chat_no_{user_id}.json")173        if os.path.exists(chat_file):174            with open(chat_file, "r", encoding="utf-8") as f:175                session["chat_history"] = json.load(f)176 177    return render_template("index.html", chat_history=session.get("chat_history", []))178 179# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────180# ─────────────────────────────────────────────── Upload section  ──────────────────────────────────────────────────────────────────────────181# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────182 183@app.route("/upload", methods=["GET", "POST"])184def upload():185    ensure_user_session()186    global DB_PATH, DOC_PATH, IMG_PATH, OTH_PATH  # force re-initializing agent187 188    if request.method == "POST":189        f = request.files.get("file")190        if not f or f.filename == "":191            flash("No file selected", "error")192            return render_template("upload.html")193 194        filename = secure_filename(f.filename)195        if not allowed_file(filename):196            flash("File type not supported", "error")197            return render_template("upload.html")198 199        ext = os.path.splitext(filename.lower())[1]200 201        if ext in (".db", ".sqlite"):202            save_path = os.path.join(app.config["UPLOAD_FOLDER"], "databases", filename)203            os.makedirs(os.path.dirname(save_path), exist_ok=True)204            global DB_PATH205            DB_PATH = save_path206            # DB_PATH = f"http://127.0.0.1:5000/uploads/databases/{filename}"207            print(f"Database path: {save_path}")208            f.save(save_path)209        elif ext in (".pdf", ".txt", ".doc", ".docx"):210            save_path = os.path.join(app.config["UPLOAD_FOLDER"], "documents", filename)211            os.makedirs(os.path.dirname(save_path), exist_ok=True)212            global DOC_PATH213            DOC_PATH = save_path214            # DOC_PATH = f"http://127.0.0.1:5000/uploads/documents/{filename}"215            print(f"Document path: {save_path}")216            f.save(save_path)217        elif ext in (".png", ".jpg", ".jpeg", ".gif"):218            save_path = os.path.join(app.config["UPLOAD_FOLDER"], "images", filename)219            os.makedirs(os.path.dirname(save_path), exist_ok=True)220            global IMG_PATH221            IMG_PATH = save_path222            # IMG_PATH = f"http://127.0.0.1:5000/uploads/images/{filename}"223            print(f"Image path: {save_path}")224            f.save(save_path)225        else:226            save_path = os.path.join(app.config["UPLOAD_FOLDER"], "others", filename)227            os.makedirs(os.path.dirname(save_path), exist_ok=True)228            global OTH_PATH229            OTH_PATH = save_path230            # OTH_PATH = f"http://127.0.0.1:5000/uploads/others/{filename}"231            print(f"Other file path: {save_path}")232            f.save(save_path)233 234        #f.save(save_path)235        236        # Add the uploaded file to the session237        session["uploads"].append(filename)238 239        # — Database files —240        if ext in (".db", ".sqlite"):241            DB_PATH = save_path242            agent.GLOBAL_DB_PATH = DB_PATH243            flash(f"Database uploaded and set: {filename}", "success")244 245        # — Documents for RAG indexing —246        elif ext in (".pdf", ".txt", ".doc", ".docx"):247            agent.rag_index_document(save_path)248            flash(f"Document indexed for RAG: {filename}", "success")249 250        # — Images or other files —251        else:252            flash(f"File uploaded: {filename}", "success")253 254        return redirect(url_for("index"))255 256    # GET257    return render_template("upload.html")258 259# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────260# ─────────────────────────────────────────────── Static Upload  ───────────────────────────────────────────────────────────────────────────261# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────262 263@app.route('/uploads/databases/<filename>')264def serve_database(filename):265    """266    Serve an database file from the uploads/databases folder.267    """268    return send_from_directory(os.path.join(app.root_path, 'uploads', 'databases'), filename)269 270@app.route('/uploads/images/<filename>')271def serve_image(filename):272    """273    Serve an document file from the uploads/images folder.274    """275    return send_from_directory(os.path.join(app.root_path, 'uploads', 'images'), filename)276 277@app.route('/uploads/documents/<filename>')278def serve_document(filename):279    """280    Serve an image file from the uploads/documents folder.281    """282    return send_from_directory(os.path.join(app.root_path, 'uploads', 'documents'), filename)283 284@app.route('/uploads/others/<filename>')285def serve_other(filename):286    """287    Serve an other file from the uploads/others folder.288    """289    return send_from_directory(os.path.join(app.root_path, 'uploads', 'others'), filename)290 291# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────292# ─────────────────────────────────────────────── AGENT calling  ───────────────────────────────────────────────────────────────────────────293# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────294 295@app.route("/generate", methods=["POST"])296def generate():297    prompt = request.json.get("prompt", "").strip()298    ensure_user_session()299    if not prompt:300        return "No prompt provided", 400301 302    socketio.start_background_task(303        run_agent_thread,304        prompt,305        session["user_id"],306        session["chat_history"]307               # ← pass it here308    )309    return "OK", 200310 311# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────312# ───────────────────────────────────────────────  SESSION handling  ───────────────────────────────────────────────────────────────────────313# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────314 315@app.route("/session-info")316def session_info():317    # Endpoint to view session details (for debugging purposes)318    return {319        "user_id": session.get("user_id"),320        "uploads": session.get("uploads", [])321    }322 323# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────324# ───────────────────────────────────────────────  SESSION clearing  ───────────────────────────────────────────────────────────────────────325# ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────326 327@app.route("/clear_chat", methods=["POST"])328def clear_chat():329    ensure_user_session()330    user_id = session.get("user_id")331    332    # Remove saved JSON chat file333    if user_id:334        chat_file = os.path.join(app.config["CHAT_FOLDER"], f"user_chat_no_{user_id}.json")335        if os.path.exists(chat_file):336            os.remove(chat_file)337    338    # Reset session339    session.clear()340    341    # Generate new session id and chat history342    session["user_id"] = os.urandom(16).hex()343    session["uploads"] = []344    session["chat_history"] = []345 346    # Refresh agent memory347    refresh_memory()348    349    return {"message": "Chat history and session cleared!"}, 200350 351if __name__ == "__main__":352    socketio.run(app, debug=True, port=5000)353