94 lines
3.1 KiB
Python
94 lines
3.1 KiB
Python
import logging
|
|
from fastapi import FastAPI, HTTPException, BackgroundTasks
|
|
from pydantic import BaseModel
|
|
from typing import List, Optional, Dict, Any
|
|
import uvicorn
|
|
import sys
|
|
import os
|
|
|
|
# Thêm thư mục gốc vào PYTHONPATH để tìm thấy các module chat, search, ingestion...
|
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from chat.rag_engine import RAGEngine
|
|
from core.config import settings
|
|
|
|
# Cấu hình Logging
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
|
logger = logging.getLogger("API")
|
|
|
|
app = FastAPI(
|
|
title="PoC SharePoint RAG API",
|
|
description="Hệ thống hỏi đáp nội bộ dựa trên SharePoint và Distributed VLM",
|
|
version="1.0.0"
|
|
)
|
|
|
|
# Khởi tạo RAG Engine (Singleton)
|
|
# Khi API khởi động, nó sẽ nạp sẵn Embedding Model vào RAM để phản hồi cực nhanh
|
|
try:
|
|
if settings.opensearch_host == "opensearch":
|
|
settings.opensearch_host = "localhost" # Fallback cho Local Dev
|
|
rag_engine = RAGEngine()
|
|
except Exception as e:
|
|
logger.error(f"Không thể khởi động RAG Engine: {e}")
|
|
rag_engine = None
|
|
|
|
# --- MODELS ---
|
|
class ChatRequest(BaseModel):
|
|
query: str
|
|
history: Optional[List[Dict[str, str]]] = []
|
|
|
|
class ChatResponse(BaseModel):
|
|
answer: str
|
|
sources: List[Dict[str, Any]] = []
|
|
|
|
# --- ENDPOINTS ---
|
|
|
|
@app.get("/health")
|
|
def health_check():
|
|
"""Kiểm tra sức khỏe hệ thống"""
|
|
return {
|
|
"status": "healthy",
|
|
"llm_provider": settings.llm_provider,
|
|
"opensearch_host": settings.opensearch_host
|
|
}
|
|
|
|
@app.post("/chat", response_model=ChatResponse)
|
|
async def chat_endpoint(request: ChatRequest):
|
|
"""
|
|
Điểm cuối để thực hiện hỏi đáp (RAG).
|
|
"""
|
|
if not rag_engine:
|
|
raise HTTPException(status_code=503, detail="RAG Engine chưa được khởi tạo thành công.")
|
|
|
|
try:
|
|
logger.info(f"Nhận câu hỏi: {request.query}")
|
|
result = rag_engine.chat(request.query, history=request.history)
|
|
|
|
return ChatResponse(
|
|
answer=result["answer"],
|
|
sources=result["sources"]
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Lỗi xử lý chat: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
@app.post("/ingest")
|
|
async def start_ingestion(background_tasks: BackgroundTasks):
|
|
"""
|
|
Kích hoạt quá trình quét SharePoint và nạp dữ liệu vào OpenSearch.
|
|
Chạy dưới dạng Background Task để không làm treo API.
|
|
"""
|
|
# TODO: Kết nối với script sync.py và quy trình extraction
|
|
# Ở đây chúng ta sẽ gọi một function xử lý bất đồng bộ
|
|
background_tasks.add_task(dummy_ingest_task)
|
|
return {"message": "Quá trình đồng bộ dữ liệu đã bắt đầu chạy ngầm."}
|
|
|
|
async def dummy_ingest_task():
|
|
logger.info("Bắt đầu Ingestion task...")
|
|
# Sẽ tích hợp logic từ test_rag_pipeline.py vào đây
|
|
pass
|
|
|
|
if __name__ == "__main__":
|
|
# Chạy server tại cổng 8000
|
|
uvicorn.run(app, host="0.0.0.0", port=8000)
|