Files

105 lines
4.1 KiB
Python

import json, os
from fastapi import APIRouter, HTTPException, Header, Depends
from pydantic import BaseModel
from typing import Optional, List, Dict, Any
import time
from app.core.auth import decode_token
from app.config import settings
router = APIRouter()
DATA_FILE = os.path.join(settings.PROCESSED_DIR, "user_configs.json")
def _load_all():
if not os.path.exists(DATA_FILE):
return {"ai_configs": {}, "preferences": {}}
try:
with open(DATA_FILE, "r") as f:
return json.load(f)
except: return {"ai_configs": {}, "preferences": {}}
def _save_all(ai_configs=None, preferences=None):
data = _load_all()
if ai_configs is not None: data["ai_configs"] = ai_configs
if preferences is not None: data["preferences"] = preferences
os.makedirs(os.path.dirname(DATA_FILE), exist_ok=True)
with open(DATA_FILE, "w") as f:
json.dump(data, f, indent=2)
def _get_user_id(authorization):
if not authorization or not authorization.startswith("Bearer "):
return "anonymous"
token = authorization.split(" ")[1]
payload = decode_token(token)
if not payload:
return "anonymous"
return payload.get("user_id", "anonymous")
def _load_ai_configs():
data = _load_all()
return data.get("ai_configs", {})
def _load_preferences():
data = _load_all()
return data.get("preferences", {})
def _get_default_providers():
return [
{"id": "openai_default", "name": "OpenAI Official", "provider_type": "openai", "api_base_url": "https://api.openai.com/v1", "api_key": "", "model_name": "gpt-4o", "temperature": 0.7, "is_active": True},
{"id": "openai_compat_default", "name": "OpenAI Compatible (Ollama/LocalAI/DeepSeek)", "provider_type": "openai_compatible", "api_base_url": "http://localhost:11434/v1", "api_key": "ollama", "model_name": "deepseek-r1", "temperature": 0.7, "is_active": False},
{"id": "anthropic_default", "name": "Anthropic Claude", "provider_type": "anthropic", "api_base_url": "https://api.anthropic.com/v1", "api_key": "", "model_name": "claude-3-5-sonnet", "temperature": 0.7, "is_active": False},
{"id": "gemini_default", "name": "Google Gemini", "provider_type": "gemini", "api_base_url": "https://generativelanguage.googleapis.com", "api_key": "", "model_name": "gemini-1.5-pro", "temperature": 0.7, "is_active": False}
]
class AIProviderSetting(BaseModel):
id: str
name: str
provider_type: str # 'openai', 'openai_compatible', 'anthropic', 'gemini'
api_base_url: Optional[str] = "https://api.openai.com/v1"
api_key: Optional[str] = ""
model_name: Optional[str] = "gpt-4o"
temperature: float = 0.7
is_active: bool = True
class SaveAIConfigRequest(BaseModel):
providers: List[AIProviderSetting]
class SavePreferencesRequest(BaseModel):
preferences: Dict[str, Any]
@router.get("/preferences")
async def get_user_preferences(authorization: Optional[str] = Header(None)):
uid = _get_user_id(authorization)
prefs = _load_preferences()
return {"success": True, "preferences": prefs.get(uid, {})}
@router.post("/preferences")
async def save_user_preferences(req: SavePreferencesRequest, authorization: Optional[str] = Header(None)):
uid = _get_user_id(authorization)
prefs = _load_preferences()
prefs[uid] = req.preferences
_save_all(preferences=prefs)
return {"success": True, "message": "Đã lưu cấu hình người dùng."}
@router.get("/config/ai")
async def get_user_ai_config(authorization: Optional[str] = Header(None)):
uid = _get_user_id(authorization)
configs = _load_ai_configs()
if uid not in configs:
configs[uid] = _get_default_providers()
return {
"success": True,
"providers": configs[uid]
}
@router.post("/config/ai")
async def save_user_ai_config(req: SaveAIConfigRequest, authorization: Optional[str] = Header(None)):
uid = _get_user_id(authorization)
configs = _load_ai_configs()
configs[uid] = [p.model_dump() for p in req.providers]
_save_all(ai_configs=configs)
return {
"success": True,
"message": "Đã lưu cấu hình AI Providers thành công!"
}