Spaces:
Running
Running
File size: 3,413 Bytes
4b380de | 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 __future__ import annotations
import os
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from src.api.routes import chat, chat_stream, health, metrics
from src.common.env_loader import load_project_env
API_VERSION = "0.1.0"
load_project_env()
import sys
if sys.stdout and sys.stdout.encoding.lower() != "utf-8":
sys.stdout.reconfigure(encoding="utf-8")
from contextlib import asynccontextmanager
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Quản lý vòng đời của ứng dụng FastAPI, bao gồm việc tải trước các mô hình.
Hàm này được gọi khi ứng dụng FastAPI khởi động và tắt.
Khi ứng dụng khởi động, nó sẽ tải trước các mô hình học máy nặng
như dịch vụ trả lời và bộ truy xuất BM25
để đảm bảo các yêu cầu đầu tiên không bị chậm do quá trình khởi tạo mô hình.
Điều này giúp tránh hiện tượng "cold start" (khởi động lạnh).
Args:
app: Đối tượng ứng dụng FastAPI hiện tại.
Yields:
Không có giá trị cụ thể nào được trả về, nhưng nó cho phép ứng dụng chạy
trong khi các tài nguyên đã được chuẩn bị.
"""
print("🚀 [FastAPI] Preloading heavy models to prevent Cold Start...")
from src.api.deps import get_answer_service
from src.retrieval.core.bm25_retriever import get_bm25_retriever
# Kích hoạt Singleton ngay từ lúc server khởi động
get_answer_service()
get_bm25_retriever()
print("✅ [FastAPI] All models preloaded successfully!")
yield
app = FastAPI(
title="Student Handbook RAG API",
version=API_VERSION,
lifespan=lifespan,
)
cors_origins = [
origin.strip()
for origin in os.getenv("STUDENT_RAG_CORS_ORIGINS", "").split(",")
if origin.strip()
]
if cors_origins:
app.add_middleware(
CORSMiddleware,
allow_origins=cors_origins,
allow_credentials=False,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(health.router)
app.include_router(metrics.router)
app.include_router(chat.router)
app.include_router(chat_stream.router)
@app.get("/")
def root() -> dict[str, str]:
"""Trả về thông tin cơ bản về API.
Khi người dùng truy cập đường dẫn gốc của API ("/"), hàm này sẽ được gọi
và trả về một dictionary chứa các thông tin hữu ích về dịch vụ,
như tên, phiên bản, và các đường dẫn đến tài liệu API hoặc kiểm tra sức khỏe.
Returns:
Một dictionary chứa các cặp khóa-giá trị mô tả dịch vụ:
- 'service': Tên định danh của dịch vụ.
- 'name': Tên đầy đủ của API.
- 'version': Phiên bản hiện tại của API.
- 'health': Đường dẫn để kiểm tra trạng thái sức khỏe của API.
- 'docs': Đường dẫn đến tài liệu API (Swagger UI/Redoc).
"""
return {
"service": "student_handbook_rag",
"name": "Student Handbook RAG API",
"version": API_VERSION,
"health": "/health",
"docs": "/docs",
}
if __name__ == "__main__":
import uvicorn
uvicorn.run("src.api.main:app", host="127.0.0.1", port=8000, reload=True)
|