File size: 2,924 Bytes
c6706bd
a7942ef
c6706bd
 
6365287
1006fab
a7942ef
c6706bd
4d4fccb
c6706bd
6365287
a7942ef
c6706bd
 
1006fab
c6706bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4d4fccb
c6706bd
6365287
 
 
 
 
 
c6706bd
 
 
 
 
 
 
 
 
 
 
 
 
 
4d4fccb
c6706bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""FastAPI application entry point"""
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
from fastapi.staticfiles import StaticFiles
from dotenv import load_dotenv

from cloudzy.database import create_db_and_tables
from cloudzy.routes import upload, photo, search, generate
from cloudzy.search_engine import SearchEngine
import os

# Initialize search engine at startup
search_engine = None
load_dotenv()

@asynccontextmanager
async def lifespan(app: FastAPI):
    """Manage app lifecycle - startup and shutdown"""
    # Startup
    print("πŸš€ Starting Cloudzy AI service...")
    create_db_and_tables()
    
    # Initialize search engine
    global search_engine
    search_engine = SearchEngine()
    stats = search_engine.get_stats()
    print(f"πŸ“Š FAISS Index loaded: {stats}")
    print("βœ… Application ready!")
    
    yield
    
    # Shutdown
    print("πŸ›‘ Shutting down Cloudzy AI service...")


# Create FastAPI app
app = FastAPI(
    title="Cloudzy AI",
    description="Cloud photo management with AI tagging, captioning, and semantic search",
    version="1.0.0",
    lifespan=lifespan,
)

# Add CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Include routers
app.include_router(upload.router)
app.include_router(photo.router)
app.include_router(search.router)
app.include_router(generate.router)

UPLOAD_DIR = os.path.join(os.getcwd(), "uploads")
os.makedirs(UPLOAD_DIR, exist_ok=True)

# Mount static file serving
app.mount("/uploads", StaticFiles(directory=UPLOAD_DIR), name="uploads")


@app.get("/", tags=["info"])
async def root():
    """Root endpoint - API info"""
    return {
        "service": "Cloudzy AI",
        "version": "1.0.0",
        "description": "Cloud photo management with AI tagging, captioning, and semantic search",
        "endpoints": {
            "upload": "POST /upload - Upload a photo",
            "get_photo": "GET /photo/{id} - Get photo metadata",
            "list_photos": "GET /photos - List all photos",
            "search": "GET /search?q=... - Semantic search",
            "image_to_image": "POST /search/image-to-image - Similar images",
            "generate_similar": "POST /generate-similar-image - Generate image from description",
            "docs": "/docs - Interactive API documentation",
        }
    }


@app.get("/health", tags=["info"])
async def health_check():
    """Health check endpoint"""
    global search_engine
    stats = search_engine.get_stats() if search_engine else {}
    
    return {
        "status": "healthy",
        "service": "Cloudzy AI",
        "search_engine": stats,
    }


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(
        "app:app",
        host="0.0.0.0",
        port=8000,
        reload=True,
    )