File size: 8,784 Bytes
8fc132d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
"""
FastAPI backend for Bhagwad Gita RAG Chatbot
"""

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse
from pydantic import BaseModel
from typing import List, Optional
import uvicorn
import os
from pathlib import Path

from backend.services.rag_service import RAGService
from backend.models.schemas import (
    QueryRequest, QueryResponse, HealthResponse,
    TranslationRequest, TranslationResponse, SupportedLanguagesResponse
)

# Initialize FastAPI app
app = FastAPI(
    title="Bhagwad Gita RAG Chatbot API",
    description="API for querying Bhagwad Gita and Patanjali Yoga Sutras using RAG (Retrieval Augmented Generation)",
    version="1.0.0",
    docs_url="/docs",
    redoc_url="/redoc"
)

# Add CORS middleware
# Prefer regex-based origin allowlist so any Netlify/Render preview domains also work
cors_origins = os.getenv(
    "CORS_ORIGINS",
    "http://localhost:3000,http://localhost:8000,https://spiritual-rag-chatbot.netlify.app"
).split(",")
cors_regex = os.getenv(
    "CORS_ORIGIN_REGEX",
    r"^https?:\/\/(localhost(:\d+)?|.*\.netlify\.app|.*\.onrender\.com)$"
)

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

# Initialize RAG service
rag_service = None

@app.on_event("startup")
async def startup_event():
    """Initialize the RAG service on startup"""
    global rag_service
    try:
        # Use environment variable for data directory or default to relative path
        data_dir = os.getenv("DATA_DIR", str(Path(__file__).parent.parent / "dataset"))
        data_dir = Path(data_dir)
        
        print(f"Initializing RAG Service with data directory: {data_dir}")
        
        if not data_dir.exists():
            print(f"Warning: Data directory {data_dir} does not exist")
            # Try alternative paths for production
            alt_paths = [
                Path("/app/dataset"),
                Path("/opt/render/project/src/dataset"),
                Path("./dataset")
            ]
            for alt_path in alt_paths:
                if alt_path.exists():
                    data_dir = alt_path
                    print(f"Using alternative data directory: {data_dir}")
                    break
        
        rag_service = RAGService(data_dir)
        await rag_service.initialize()
        print("RAG Service initialized successfully")
    except Exception as e:
        print(f"Error initializing RAG service: {e}")
        # Don't raise in production, just log the error
        if os.getenv("ENVIRONMENT") != "production":
            raise

@app.get("/", response_class=HTMLResponse)
async def read_root():
    """Serve the main page"""
    return """
    <!DOCTYPE html>
    <html>
    <head>
        <title>Bhagwad Gita RAG Chatbot</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <style>
            body { font-family: Arial, sans-serif; margin: 40px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; }
            .container { max-width: 800px; margin: 0 auto; background: rgba(255,255,255,0.1); padding: 30px; border-radius: 15px; backdrop-filter: blur(10px); }
            h1 { text-align: center; margin-bottom: 30px; }
            .api-info { background: rgba(255,255,255,0.2); padding: 20px; border-radius: 10px; margin: 20px 0; }
            a { color: #FFD700; text-decoration: none; }
            a:hover { text-decoration: underline; }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>πŸ•‰οΈ Bhagwad Gita RAG Chatbot API</h1>
            <div class="api-info">
                <h3>Welcome to the Spiritual Wisdom API</h3>
                <p>This API provides access to verses and wisdom from the Bhagavad Gita and Patanjali Yoga Sutras using advanced RAG (Retrieval Augmented Generation) technology.</p>
                
                <h4>πŸ“š Features:</h4>
                <ul>
                    <li>Query-based verse retrieval from sacred texts</li>
                    <li>Intelligent matching using TF-IDF and cosine similarity</li>
                    <li>Automatic summary generation</li>
                    <li>Bilingual support (Sanskrit and English)</li>
                </ul>
                
                <h4>πŸ”— Quick Links:</h4>
                <ul>
                    <li><a href="/docs">πŸ“– Interactive API Documentation (Swagger)</a></li>
                    <li><a href="/redoc">πŸ“‹ Alternative API Documentation (ReDoc)</a></li>
                    <li><a href="/health">πŸ’š Health Check</a></li>
                    <li><a href="/frontend">🌐 Frontend Application</a></li>
                </ul>
                
                <h4>πŸš€ Quick Test:</h4>
                <p>Try a sample query: <code>POST /query</code> with body: <code>{"query": "How to control the mind?"}</code></p>
            </div>
        </div>
    </body>
    </html>
    """

@app.get("/health", response_model=HealthResponse)
async def health_check():
    """Health check endpoint"""
    return HealthResponse(
        status="healthy",
        message="Bhagwad Gita RAG Chatbot API is running",
        version="1.0.0"
    )

@app.get("/ready")
async def readiness_check():
    """Readiness endpoint that verifies the RAG service is initialized."""
    return {"ready": rag_service is not None}

@app.post("/query", response_model=QueryResponse)
async def process_query(request: QueryRequest):
    """
    Process a spiritual query and return relevant verses with summary
    """
    if not rag_service:
        raise HTTPException(status_code=503, detail="RAG service not initialized")
    
    try:
        # Validate query
        if not request.query.strip():
            raise HTTPException(status_code=400, detail="Query cannot be empty")
        
        # Process the query
        result = await rag_service.process_query(
            query=request.query,
            top_n=request.top_n,
            include_summary=request.include_summary
        )
        
        return result
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error processing query: {str(e)}")

@app.get("/sources")
async def get_available_sources():
    """Get information about available text sources"""
    if not rag_service:
        raise HTTPException(status_code=503, detail="RAG service not initialized")
    
    return await rag_service.get_sources_info()

@app.post("/translate", response_model=TranslationResponse)
async def translate_text(request: TranslationRequest):
    """Translate text to supported languages"""
    if rag_service is None:
        raise HTTPException(status_code=503, detail="RAG service not initialized")
    
    try:
        translated_text = await rag_service.translate_text(request.text, request.target_language)
        
        if translated_text.startswith("Language") or translated_text.startswith("Translation failed"):
            raise HTTPException(status_code=400, detail=translated_text)
        
        language_name = rag_service.supported_languages.get(request.target_language, "Unknown")
        
        return TranslationResponse(
            original_text=request.text,
            translated_text=translated_text,
            target_language=request.target_language,
            language_name=language_name
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Translation failed: {str(e)}")

@app.get("/supported-languages", response_model=SupportedLanguagesResponse)
async def get_supported_languages():
    """Get list of supported languages for translation"""
    if rag_service is None:
        raise HTTPException(status_code=503, detail="RAG service not initialized")
    
    return SupportedLanguagesResponse(languages=rag_service.supported_languages)

# Mount static files for frontend
static_path = Path(__file__).parent.parent / "frontend" / "build"
if static_path.exists():
    app.mount("/frontend", StaticFiles(directory=static_path, html=True), name="frontend")

if __name__ == "__main__":
    # Get configuration from environment variables
    host = os.getenv("API_HOST", "0.0.0.0")
    port = int(os.getenv("API_PORT", "8000"))
    
    print(f"Starting Bhagwad Gita RAG Chatbot API on {host}:{port}")
    print(f"CORS Origins: {cors_origins}")
    
    uvicorn.run(
        "main:app", 
        host=host, 
        port=port, 
        reload=os.getenv("ENVIRONMENT") != "production",
        log_level=os.getenv("LOG_LEVEL", "info")
    )