Spaces:
Sleeping
Sleeping
| # from fastapi import FastAPI | |
| # from pydantic import BaseModel | |
| # from model_loader import ModelLoader | |
| # from services.text_filter import TextFilterService | |
| # from services.image_ocr import ImageOCRService | |
| # from typing import Optional | |
| # from fastapi.responses import JSONResponse | |
| # import logging | |
| # logging.basicConfig( | |
| # level=logging.INFO, | |
| # format="%(asctime)s [%(levelname)s] %(message)s", | |
| # handlers=[ | |
| # logging.StreamHandler() | |
| # ] | |
| # ) | |
| # logger = logging.getLogger(__name__) | |
| # app = FastAPI() | |
| # logger.info("Starting FastAPI app...") | |
| # model_loader = ModelLoader() | |
| # logger.info("ModelLoader initialized.") | |
| # text_filter_service = TextFilterService(model_loader) | |
| # logger.info("TextFilterService initialized.") | |
| # image_ocr_service = ImageOCRService() | |
| # logger.info("Image OCR image initialized") | |
| # class InputData(BaseModel): | |
| # text: Optional[str] = None | |
| # image_url: Optional[str] = None | |
| # @app.post("/filtercomment") | |
| # async def filter_comment(input_data: InputData): | |
| # logger.info("Received request: %s", input_data) | |
| # final_text = "" | |
| # # Case 1: Extract text from image | |
| # if input_data.image_url: | |
| # logger.info("Image URL provided: %s", input_data.image_url) | |
| # try: | |
| # logger.info("Fetching image from URL...") | |
| # final_text = image_ocr_service.extract_text(input_data.image_url) | |
| # logger.info("Generated text: %s", final_text) | |
| # except Exception as e: | |
| # logger.error("Image processing failed: %s", str(e)) | |
| # return JSONResponse(status_code=400, content={"error": f"Image processing failed: {str(e)}"}) | |
| # # Case 2: Use provided text | |
| # elif input_data.text: | |
| # logger.info("Text input provided.") | |
| # final_text = input_data.text | |
| # else: | |
| # logger.warning("No input provided.") | |
| # return JSONResponse(status_code=400, content={"error": "Either 'text' or 'image_url' must be provided."}) | |
| # try: | |
| # logger.info("Processing text through TextFilterService...") | |
| # results = text_filter_service.process_text(final_text) | |
| # results["extracted_text"] = final_text | |
| # logger.info("Text filtering complete. Results: %s", results) | |
| # return results | |
| # except Exception as e: | |
| # logger.exception("Text filtering failed.") | |
| # return JSONResponse(status_code=500, content={"error": f"Text filtering failed: {str(e)}"}) | |
| # if __name__ == "__main__": | |
| # import uvicorn | |
| # logger.info("Starting Uvicorn server...") | |
| # uvicorn.run(app, host="0.0.0.0", port=3000) | |
| from flask import Flask, request, jsonify | |
| from model_loader import ModelLoader | |
| from services.text_filter import TextFilterService | |
| from services.llm_text_filter import ArticleClassifier | |
| from services.image_ocr import ImageClassifier | |
| from typing import Optional | |
| from PIL import Image | |
| import logging | |
| import io | |
| import cv2 | |
| import numpy as np | |
| import base64 | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format="%(asctime)s [%(levelname)s] %(message)s", | |
| handlers=[ | |
| logging.StreamHandler() | |
| ] | |
| ) | |
| logger = logging.getLogger(__name__) | |
| app = Flask(__name__) | |
| logger.info("Starting Flask app...") | |
| model_loader = ModelLoader() | |
| logger.info("ModelLoader initialized.") | |
| text_filter_service = TextFilterService(model_loader) | |
| logger.info("TextFilterService initialized.") | |
| image_classifier = ImageClassifier() | |
| logger.info("ImageClassifier initialized.") | |
| def blur_image(pil_image: Image.Image) -> Image.Image: | |
| """Convert PIL image to OpenCV, apply Gaussian blur, and return as PIL.""" | |
| cv_image = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR) | |
| blurred_cv = cv2.GaussianBlur(cv_image, (25, 25), 0) | |
| blurred_pil = Image.fromarray(cv2.cvtColor(blurred_cv, cv2.COLOR_BGR2RGB)) | |
| return blurred_pil | |
| def filter_comment(): | |
| text = request.form.get("text") | |
| image_url = request.form.get("image_url") | |
| article = request.form.get("article", "false").lower() == "true" | |
| image_file = request.files.get("image_file") | |
| logger.info("Received request: text=%s, image_url=%s, article=%s, image_file=%s", text, image_url, article, image_file.filename if image_file else None) | |
| final_text = "" | |
| # Case 1: Image file upload | |
| if image_file: | |
| try: | |
| logger.info("Processing uploaded image file: %s", image_file.filename) | |
| image_bytes = image_file.read() | |
| image = Image.open(io.BytesIO(image_bytes)).convert("RGB") | |
| result = image_classifier.classify(image) | |
| if result.get("text"): | |
| result['toxic_result'] = text_filter_service.process_text(result.get("text")) | |
| logger.info("Image classification result: %s", result) | |
| # Check if content is toxic or unsafe | |
| is_toxic = result.get("toxic") is True or not result.get("toxic_result", {}).get("safe", True) | |
| if is_toxic: | |
| logger.info("Toxic content detected. Blurring image.") | |
| blurred_image = blur_image(image) | |
| # Compose annotation message | |
| if not result.get("text"): | |
| message = "The image contains some toxic content" | |
| else: | |
| toxic_result = result.get("toxic_result", {}) | |
| exclude_keys = {"safe", "identity_hate_custom", "not_identity_hate_custom"} | |
| filtered = {k: v for k, v in toxic_result.items() if k not in exclude_keys} | |
| if filtered: | |
| max_label = max(filtered, key=filtered.get) | |
| message = "The image contains some toxic content" | |
| else: | |
| message = "The image contains some toxic content" | |
| # Encode blurred image to base64 | |
| buffer = io.BytesIO() | |
| blurred_image.save(buffer, format="JPEG") | |
| encoded_image = base64.b64encode(buffer.getvalue()).decode("utf-8") | |
| result["blurred_image_base64"] = encoded_image | |
| result["blurred"] = True | |
| result["alert_message"] = message | |
| else: | |
| result["blurred"] = False | |
| return jsonify(content={"image_classification": result}) | |
| except Exception as e: | |
| logger.error("Image file processing failed: %s", str(e)) | |
| return jsonify(status_code=400, content={"error": f"Image file processing failed: {str(e)}"}) | |
| # Case 2: Extract text from image URL | |
| if image_url: | |
| logger.info("Image URL provided: %s", image_url) | |
| try: | |
| logger.info("Fetching image from URL...") | |
| # You need to implement image_ocr_service.extract_text or use image_classifier if that's your OCR | |
| final_text = image_classifier.extract_text(image_url) | |
| logger.info("Generated text: %s", final_text) | |
| except Exception as e: | |
| logger.error("Image processing failed: %s", str(e)) | |
| return jsonify({"error": f"Image processing failed: {str(e)}"}), 400 | |
| # Case 3: Use provided text | |
| elif text: | |
| logger.info("Text input provided.") | |
| final_text = text | |
| else: | |
| logger.warning("No input provided.") | |
| return jsonify({"error": "Either 'text', 'image_url', or 'image_file' must be provided."}), 400 | |
| try: | |
| logger.info("Processing text through TextFilterService...") | |
| if article: | |
| logger.info("Classifying article...") | |
| classifier = ArticleClassifier(final_text) | |
| result = classifier.classify() | |
| logger.info("Article classification complete: %s", final_text) | |
| return jsonify(result) | |
| else: | |
| results = text_filter_service.process_text(final_text) | |
| results["extracted_text"] = final_text | |
| logger.info("Text filtering complete. Results: %s", results) | |
| return jsonify(results) | |
| except Exception as e: | |
| logger.exception("Text filtering failed.") | |
| return jsonify({"error": f"Text filtering failed: {str(e)}"}), 500 | |
| if __name__ == "__main__": | |
| logger.info("Starting Flask server...") | |
| app.run(host="0.0.0.0", port=7860) | |