Spaces:
Running
Running
| from flask import Flask, request, jsonify | |
| from flask_cors import CORS | |
| import logging | |
| # Cấu hình logging cho app | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| from model import predict_sentiment_3sentiment, predict_sentiment_5sentiment | |
| import pandas as pd | |
| # Khởi tạo Flask app | |
| app = Flask(__name__) | |
| CORS(app) | |
| # Xử lý encoding cho tiếng Việt để hiển thị đúng trong response | |
| app.config['JSON_AS_ASCII'] = False | |
| def predict(): | |
| """ | |
| Dự đoán cảm xúc từ văn bản đầu vào. | |
| Request body phải là JSON có dạng: {"text": "nội dung bình luận"} | |
| """ | |
| # Lấy dữ liệu JSON từ request | |
| json_data = request.get_json() | |
| logger.info(f"Received predict request: {json_data}") | |
| # Kiểm tra xem key 'text' có tồn tại và không rỗng không | |
| if not json_data or 'text' not in json_data or not json_data.get('text', '').strip(): | |
| logger.warning("Missing 'text' in request") | |
| return jsonify({"error": "Vui lòng cung cấp trường 'text' trong request body."}), 400 | |
| # Kiểm tra xem key 'type' có tồn tại và không rỗng không | |
| if not json_data or 'type' not in json_data or not json_data.get('type', '').strip(): | |
| logger.warning("Missing 'type' in request") | |
| return jsonify({"error": "Vui lòng cung cấp trường 'type' trong request body."}), 400 | |
| # Lấy văn bản từ dữ liệu | |
| text_to_predict = json_data['text'] | |
| sentiment_type = json_data['type'] | |
| # Gọi hàm dự đoán từ model | |
| try: | |
| if sentiment_type == "3sentiment": | |
| sentiment, score = predict_sentiment_3sentiment(text_to_predict) | |
| elif sentiment_type == "5sentiment": | |
| sentiment, score = predict_sentiment_5sentiment(text_to_predict) | |
| except Exception as e: | |
| logger.error(f"Prediction error: {e}") | |
| return jsonify({"error": str(e)}), 500 | |
| # Tạo response | |
| response = { | |
| "comment": text_to_predict, | |
| "sentiment": sentiment, | |
| "confidence": score | |
| } | |
| return jsonify(response) | |
| def read_root(): | |
| return jsonify({"message": "Chào mừng đến với API Phân tích Cảm xúc sử dụng Flask!"}) | |
| def predict_batch(): | |
| """ | |
| Dự đoán cảm xúc cho một loạt bình luận từ file Excel. | |
| File Excel phải được gửi dưới dạng form-data với key là 'file'. | |
| Cột đầu tiên của file Excel sẽ được sử dụng làm cột chứa bình luận. | |
| """ | |
| # 1. Kiểm tra xem có file trong request không | |
| if 'file' not in request.files: | |
| logger.warning("No file part in request") | |
| return jsonify({"error": "Không tìm thấy file trong request (key phải là 'file')."}), 400 | |
| # Dữ liệu form đi kèm với file sẽ nằm trong request.form | |
| sentiment_type = request.form.get('type') | |
| logger.info(f"Received batch predict request for type: {sentiment_type}") | |
| # Kiểm tra xem key 'type' có tồn tại và không rỗng không | |
| if not sentiment_type or sentiment_type.strip() not in ["3sentiment", "5sentiment"]: | |
| logger.warning("Invalid or missing 'type'") | |
| return jsonify({"error": "Vui lòng cung cấp trường 'type' (3sentiment hoặc 5sentiment) trong form data."}), 400 | |
| file = request.files['file'] | |
| # 2. Kiểm tra xem người dùng có chọn file không | |
| if file.filename == '': | |
| logger.warning("No selected file") | |
| return jsonify({"error": "Chưa chọn file nào."}), 400 | |
| # 3. Kiểm tra định dạng file | |
| if not file.filename.endswith(('.xlsx', '.xls')): | |
| logger.warning(f"Invalid file format: {file.filename}") | |
| return jsonify({"error": "Định dạng file không hợp lệ. Vui lòng sử dụng file .xlsx hoặc .xls."}), 400 | |
| try: | |
| # 4. Đọc file Excel bằng pandas, sử dụng engine openpyxl | |
| df = pd.read_excel(file, engine='openpyxl') | |
| if df.empty: | |
| return jsonify({"error": "File Excel rỗng."}), 400 | |
| # Lấy tên cột đầu tiên để xử lý | |
| comments_column = df.columns[0] | |
| results = [] | |
| # 5. Lặp qua từng bình luận (bỏ qua các dòng rỗng) để dự đoán | |
| for comment in df[comments_column].dropna().astype(str): | |
| if sentiment_type == "3sentiment": | |
| sentiment, score = predict_sentiment_3sentiment(comment) | |
| elif sentiment_type == "5sentiment": | |
| sentiment, score = predict_sentiment_5sentiment(comment) | |
| results.append({"comment": comment, "sentiment": sentiment, "confidence": score}) | |
| return jsonify(results) | |
| except Exception as e: | |
| logger.error(f"Error processing batch file: {e}") | |
| return jsonify({"error": f"Đã xảy ra lỗi khi xử lý file: {str(e)}"}), 500 | |
| if __name__ == "__main__": | |
| # Chạy app ở chế độ debug để tự động reload khi có thay đổi | |
| # host='0.0.0.0' để có thể truy cập từ bên ngoài network | |
| # Lưu ý: Không sử dụng debug=True trong môi trường production | |
| app.run(host="0.0.0.0", port=8000, debug=True) |