File size: 4,063 Bytes
32d4a86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Image Caption Generator - Flask Application
Production-ready application with model caching and security.
"""

from flask import Flask
import os
import logging

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


def create_app(config=None):
    """
    Application factory pattern.
    Creates and configures the Flask application.
    """
    # Get base directory (project root)
    import os
    from pathlib import Path
    base_dir = Path(__file__).resolve().parent.parent
    
    app = Flask(__name__, 
                template_folder=str(base_dir / 'templates'),
                static_folder=str(base_dir / 'static'))
    
    # Load configuration
    app.secret_key = os.environ.get("SESSION_SECRET")
    if not app.secret_key or app.secret_key == "default-secret-key":
        if os.environ.get("FLASK_ENV") == "production":
            raise ValueError("SESSION_SECRET must be set in production environment!")
        else:
            logger.warning("Using default secret key. Set SESSION_SECRET in production!")
            app.secret_key = "default-secret-key"
    
    # Configuration
    app.config['UPLOAD_FOLDER'] = os.environ.get('UPLOAD_FOLDER', 'uploads')
    app.config['MAX_CONTENT_LENGTH'] = int(os.environ.get('MAX_FILE_SIZE', 10 * 1024 * 1024))
    app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg'}
    
    # Create uploads directory
    if not os.path.exists(app.config['UPLOAD_FOLDER']):
        os.makedirs(app.config['UPLOAD_FOLDER'])
    
    # Register blueprints/routes
    from app.routes import bp
    app.register_blueprint(bp)
    
    # Download model if needed (before loading)
    # Try HF Hub first, then download URL
    if os.environ.get("FLASK_ENV") == "production" or os.environ.get("LOAD_MODELS", "true").lower() == "true":
        try:
            # Try downloading from Hugging Face Hub first
            model_repo = os.environ.get("HF_MODEL_REPO")
            if model_repo:
                try:
                    from huggingface_hub import hf_hub_download
                    logger.info(f"Downloading model from HF Hub: {model_repo}")
                    model_path = hf_hub_download(
                        repo_id=model_repo,
                        filename="efficientnet_efficient_best_model_quantized.pth",
                        cache_dir=str(base_dir / "models" / "optimized_models")
                    )
                    logger.info(f"Model downloaded from HF Hub: {model_path}")
                except Exception as e:
                    logger.warning(f"Could not download from HF Hub: {e}. Trying download URL...")
                    import sys
                    sys.path.insert(0, str(base_dir))
                    from scripts.download_model import download_efficientnet_model
                    download_efficientnet_model()
            else:
                # Fallback to download URL method
                import sys
                sys.path.insert(0, str(base_dir))
                from scripts.download_model import download_efficientnet_model
                download_efficientnet_model()
        except Exception as e:
            logger.warning(f"Could not download model: {e}. Will try to use existing model if available.")
    
    # Initialize models at startup (production)
    if os.environ.get("FLASK_ENV") == "production" or os.environ.get("LOAD_MODELS", "true").lower() == "true":
        logger.info("Initializing models...")
        try:
            from app.utils.model_cache import model_cache
            # Only load EfficientNet model
            model_cache.load_efficientnet_model_only(use_optimized=True)
            logger.info("EfficientNet model loaded successfully")
        except Exception as e:
            logger.error(f"Failed to load models: {e}", exc_info=True)
            # Don't raise here - let the app start and handle errors gracefully
    
    return app


# For backward compatibility
app = create_app()