File size: 4,365 Bytes
a38f710
 
 
76ca861
a38f710
0d87629
a38f710
830be50
a38f710
348e214
a38f710
 
 
348e214
830be50
a38f710
 
 
 
348e214
830be50
 
 
0d87629
a38f710
 
88d625f
 
0d87629
88d625f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d87629
88d625f
 
a38f710
0d87629
 
348e214
a38f710
 
 
 
 
 
 
830be50
 
 
 
 
 
0d87629
830be50
 
 
 
 
 
 
 
0d87629
830be50
 
 
 
a38f710
 
 
 
 
1788936
 
 
 
a38f710
 
 
 
 
 
 
 
 
 
 
76ca861
f6e3d73
a38f710
 
 
 
 
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
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from .api.v1.endpoints import generate, download, health, auth
from .core.config import settings
from .core.model_loader import get_generator  # Import get_generator
from contextlib import asynccontextmanager
from pathlib import Path
import logging

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Ensure all required directories exist
settings.resolved_generated_path.mkdir(parents=True, exist_ok=True)
settings.resolved_base_path.mkdir(parents=True, exist_ok=True)
settings.resolved_symbols_path.mkdir(parents=True, exist_ok=True)
settings.resolved_qr_code_path.mkdir(parents=True, exist_ok=True)

# Ensure the static mount directory exists
settings.resolved_static_files_mount_dir.mkdir(parents=True, exist_ok=True)

# Lifecycle management for the model
@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup: Preload the model (non-blocking)
    logger.info("Anwendung startet... Starte LLM-Modell-Loading im Hintergrund.")
    try:
        # Start model loading in background to avoid blocking app startup
        import asyncio
        import threading
        
        def load_model_background():
            try:
                logger.info("Hintergrund-Loading des LLM-Modells gestartet...")
                get_generator()  # Calls get_generator to load and cache the model
                logger.info("✅ LLM-Modell erfolgreich vorab geladen und Pipeline initialisiert.")
            except Exception as e:
                logger.error(f"❌ Fehler beim Hintergrund-Loading des LLM-Modells: {e}", exc_info=True)
        
        # Start model loading in a separate thread
        model_thread = threading.Thread(target=load_model_background, daemon=True)
        model_thread.start()
        logger.info("🚀 Anwendung gestartet - Modell lädt im Hintergrund...")
        
    except Exception as e:
        logger.error(f"Fehler beim Starten des Hintergrund-Loadings: {e}", exc_info=True)
    
    yield
    # Shutdown: Cleanup actions could go here (not currently needed for the model)
    logger.info("Anwendung wird heruntergefahren.")

app = FastAPI(
    title=settings.PROJECT_NAME,  
    description="Ein Service zur Generierung personalisierter Horoskopkarten mit LoRa und FastAPI.",
    version=settings.APP_VERSION, 
    lifespan=lifespan
)

# Mount static files with error handling
try:
    static_dir = settings.resolved_static_files_mount_dir
    logger.info(f"Attempting to mount static directory: {static_dir}")
    logger.info(f"Static directory exists: {static_dir.exists()}")
    if static_dir.exists():
        app.mount(f"{settings.API_PREFIX}/static", StaticFiles(directory=static_dir), name="static")
        logger.info("Static files mounted successfully")
    else:
        logger.warning(f"Static directory does not exist: {static_dir}")
        logger.info("Creating static directory structure...")
        static_dir.mkdir(parents=True, exist_ok=True)
        # Create basic subdirectories
        (static_dir / "images").mkdir(exist_ok=True)
        (static_dir / "fonts").mkdir(exist_ok=True)
        app.mount(f"{settings.API_PREFIX}/static", StaticFiles(directory=static_dir), name="static")
        logger.info("Static files mounted with created directory")
except Exception as e:
    logger.error(f"Failed to mount static files: {e}")
    # Continue without static files mounting in case of error


origins = [
    "http://localhost",
    "http://localhost:3000",  
    "https://huggingface.co",
    "https://ch404-cardserver.hf.space",
    "https://huggingface.co/spaces/ch404/cardserver",
    "*",  # Allow all origins for debugging
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(health.router, prefix=settings.API_PREFIX, tags=["Health"])
app.include_router(auth.router, prefix=settings.API_PREFIX, tags=["Authentication"])
app.include_router(generate.router, prefix=settings.API_PREFIX, tags=["Generate Card"])
app.include_router(download.router, prefix=settings.API_PREFIX, tags=["Download Card"])

@app.get("/")
async def root():
    return {"message": f"Welcome to the {settings.PROJECT_NAME} API."}