File size: 3,344 Bytes
ca7a2c2
 
 
 
 
 
 
 
 
 
 
 
 
d7a7993
 
9882d96
ca7a2c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d7a7993
ca7a2c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d7a7993
 
9882d96
d7a7993
 
 
 
ca7a2c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
108
109
110
111
112
"""
LocalMate Da Nang V2 - Multi-Modal Contextual Agent API.

FastAPI application entry point with /chat endpoint for testing.
"""

from contextlib import asynccontextmanager

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app.api.router import router as api_router
from app.planner.router import router as planner_router
from app.users.router import router as users_router
from app.itineraries.router import router as itineraries_router
from app.auth.router import router as auth_router
from app.shared.db.session import engine
from app.shared.integrations.neo4j_client import neo4j_client


@asynccontextmanager
async def lifespan(app: FastAPI):
    """Application lifespan handler for startup/shutdown."""
    # Startup - preload SigLIP model
    try:
        from app.shared.integrations.siglip_client import get_siglip_client
        siglip = get_siglip_client()
        print(f"✅ SigLIP ready: {siglip.is_loaded}")
    except Exception as e:
        print(f"⚠️ SigLIP not loaded (image search disabled): {e}")
    
    yield
    
    # Shutdown
    await neo4j_client.close()
    await engine.dispose()


app = FastAPI(
    title="LocalMate Da Nang V2",
    description="""
## Multi-Modal Contextual Agent (MMCA) API

Intelligent travel assistant for Da Nang with 3 MCP tools + Trip Planner:

### Tools Available:
1. **retrieve_context_text** - Semantic search in text descriptions (reviews, menus)
2. **retrieve_similar_visuals** - Image similarity search (find similar vibes)
3. **find_nearby_places** - Spatial search (find places near a location)

### Trip Planner:
- Create plans and add places
- Optimize route with TSP algorithm
- Reorder, replace, and manage places

### Examples:
- "Tìm quán cafe gần bãi biển Mỹ Khê"
- "Nhà hàng hải sản nào được review tốt?"
- "Quán nào có không gian xanh mát?" (with image_url)
""",
    version="0.3.0",
    lifespan=lifespan,
)

# CORS middleware - allow all for demo
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Include API routers
app.include_router(api_router, prefix="/api/v1", tags=["Chat"])
app.include_router(planner_router, prefix="/api/v1", tags=["Trip Planner"])
app.include_router(users_router, prefix="/api/v1", tags=["Users"])
app.include_router(itineraries_router, prefix="/api/v1", tags=["Itineraries"])
app.include_router(auth_router, prefix="/api/v1", tags=["Authentication"])

# Upload router
from app.upload import router as upload_router
app.include_router(upload_router, prefix="/api/v1", tags=["Upload"])


@app.get("/health", tags=["System"])
async def health_check():
    """
    Health check endpoint.

    Returns status of the application and connected services.
    """
    neo4j_ok = await neo4j_client.verify_connectivity()
    return {
        "status": "healthy",
        "version": "0.2.0",
        "services": {
            "neo4j": "connected" if neo4j_ok else "disconnected",
        },
    }


@app.get("/", tags=["System"])
async def root():
    """Root endpoint with API info."""
    return {
        "name": "LocalMate Da Nang V2 - MMCA API",
        "version": "0.2.0",
        "docs": "/docs",
        "description": "Multi-Modal Contextual Agent for Da Nang Tourism",
    }