Spaces:
Sleeping
Sleeping
File size: 4,590 Bytes
9439512 f3fd40f 9439512 f3fd40f 9439512 ea534aa 9439512 ea534aa 9439512 cb6c215 9439512 cb6c215 9439512 cb6c215 9439512 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | from flask import Flask, request, jsonify, send_from_directory
from flask_cors import CORS
from llm_agent import LLM_Agent
from data_processor import DataProcessor
import os
import logging
import time
from dotenv import load_dotenv
from werkzeug.utils import secure_filename
load_dotenv()
logging.basicConfig(level=logging.INFO)
logging.getLogger('matplotlib').setLevel(logging.WARNING)
logging.getLogger('PIL').setLevel(logging.WARNING)
logging.getLogger('plotly').setLevel(logging.WARNING)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
app = Flask(__name__, static_folder=os.path.join(BASE_DIR, 'static'))
CORS(app, origins=[
"https://llm-integrated-excel-plotter-app.vercel.app",
"http://localhost:8080",
"http://localhost:3000",
], supports_credentials=False)
agent = LLM_Agent()
UPLOAD_FOLDER = os.path.join(BASE_DIR, 'data', 'uploads')
ALLOWED_EXTENSIONS = {'csv', 'xls', 'xlsx'}
MAX_UPLOAD_BYTES = 10 * 1024 * 1024 # 10 MB
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = MAX_UPLOAD_BYTES
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
STARTED_AT = time.time()
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/')
def index():
return jsonify({
"status": "ok",
"message": "AI Data Visualization API",
"endpoints": ["/health", "/plot", "/upload", "/stats", "/models"]
})
@app.route('/health', methods=['GET'])
def health():
"""Lightweight endpoint used by frontend wake-up checks and cron pings."""
return jsonify({
"status": "ok",
"service": "llm-excel-plotter-agent",
"uptime_seconds": round(time.time() - STARTED_AT, 2),
"timestamp": int(time.time()),
})
@app.route('/models', methods=['GET'])
def models():
return jsonify({
"models": [
{"id": "qwen", "name": "Qwen2.5-Coder-0.5B", "provider": "Local (transformers)", "free": True},
{"id": "bart", "name": "BART (fine-tuned)", "provider": "Local (transformers)", "free": True},
{"id": "gemini", "name": "Gemini 2.0 Flash", "provider": "Google AI (API key)", "free": False},
{"id": "grok", "name": "Grok-3 Mini", "provider": "xAI (API key)", "free": False},
],
"default": "qwen"
})
@app.route('/plot', methods=['POST'])
def plot():
t0 = time.time()
data = request.get_json(force=True)
if not data or not data.get('query'):
return jsonify({'error': 'Missing required field: query'}), 400
logging.info(f"Plot request: model={data.get('model','qwen')} query={data.get('query')[:80]}")
result = agent.process_request(data)
logging.info(f"Plot completed in {time.time() - t0:.2f}s")
return jsonify(result)
@app.route('/static/<path:filename>')
def serve_static(filename):
resp = send_from_directory(app.static_folder, filename)
resp.headers['Access-Control-Allow-Origin'] = '*'
resp.headers['Cache-Control'] = 'public, max-age=300'
return resp
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
return jsonify({'error': 'No file part in request'}), 400
file = request.files['file']
if not file.filename:
return jsonify({'error': 'No file selected'}), 400
if not allowed_file(file.filename):
return jsonify({'error': 'File type not allowed. Use CSV, XLS, or XLSX'}), 400
filename = secure_filename(file.filename)
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(file_path)
dp = DataProcessor(file_path)
return jsonify({
'message': 'File uploaded successfully',
'columns': dp.get_columns(),
'dtypes': dp.get_dtypes(),
'preview': dp.preview(5),
'file_path': file_path,
'row_count': len(dp.data),
})
@app.route('/stats', methods=['POST'])
def stats():
data = request.get_json(force=True) or {}
file_path = data.get('file_path')
dp = DataProcessor(file_path) if file_path and os.path.exists(file_path) else agent.data_processor
return jsonify({
'columns': dp.get_columns(),
'dtypes': dp.get_dtypes(),
'stats': dp.get_stats(),
'row_count': len(dp.data),
})
@app.errorhandler(413)
def file_too_large(e):
return jsonify({'error': f'File too large. Maximum size is {MAX_UPLOAD_BYTES // (1024*1024)} MB'}), 413
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860) |