Files
moss-ai/app/backend-python/api/config.py
雷雨 8635b84b2d init
2025-12-15 22:05:56 +08:00

511 lines
16 KiB
Python

"""
配置管理 API
提供系统配置、AI模型、Agent、设备等配置的管理接口
"""
import logging
from typing import List, Optional
from fastapi import APIRouter, HTTPException, status
from pydantic import BaseModel, Field
import database
from services.config_service import ConfigService
logger = logging.getLogger(__name__)
router = APIRouter()
def get_config_service() -> ConfigService:
"""获取配置服务实例(每次请求时动态创建)"""
if database.db is None:
raise HTTPException(
status_code=500,
detail="数据库未初始化,请确保服务已正确启动"
)
return ConfigService(database.db)
# ==================== 数据模型 ====================
class AIModelResponse(BaseModel):
"""AI模型响应模型"""
id: int
model_name: str
provider: str
api_key: str
api_base: str
model_type: str = "chat"
temperature: float = 0.7
max_tokens: int = 2048
is_default: bool = False
is_active: bool = True
class AIModelUpdate(BaseModel):
"""AI模型更新模型"""
model_name: Optional[str] = None
provider: Optional[str] = None
api_key: Optional[str] = None
api_base: Optional[str] = None
model_type: Optional[str] = None
temperature: Optional[float] = None
max_tokens: Optional[int] = None
is_default: Optional[bool] = None
is_active: Optional[bool] = None
class AIModelCreate(BaseModel):
"""AI模型创建模型"""
model_name: str
provider: str
api_key: str
api_base: str
model_type: str = "chat"
temperature: float = 0.7
max_tokens: int = 2048
is_default: bool = False
is_active: bool = True
class AgentResponse(BaseModel):
"""Agent响应模型"""
id: int
agent_code: str
agent_name: str
host: str = "localhost"
port: int
description: Optional[str] = None
is_enabled: bool = True
class AgentUpdate(BaseModel):
"""Agent更新模型"""
agent_name: Optional[str] = None
host: Optional[str] = None
port: Optional[int] = None
description: Optional[str] = None
is_enabled: Optional[bool] = None
class AgentPromptResponse(BaseModel):
"""Agent提示词响应模型"""
agent_code: str
prompt_text: str
class AgentPromptUpdate(BaseModel):
"""Agent提示词更新模型"""
prompt_text: str
version: str = "v1.0"
class DeviceResponse(BaseModel):
"""设备响应模型"""
id: int
device_code: str
device_name: str
device_type: str
agent_code: str
ip_address: Optional[str] = None
token: Optional[str] = None
model: Optional[str] = None
extra_config: Optional[str] = None
is_active: bool = True
class DeviceUpdate(BaseModel):
"""设备更新模型"""
device_name: Optional[str] = None
ip_address: Optional[str] = None
token: Optional[str] = None
model: Optional[str] = None
extra_config: Optional[str] = None
is_active: Optional[bool] = None
class DeviceCreate(BaseModel):
"""设备创建模型"""
device_code: str
device_name: str
device_type: str
agent_code: str
ip_address: Optional[str] = None
token: Optional[str] = None
model: Optional[str] = None
extra_config: Optional[str] = None
is_active: bool = True
class XiaomiAccountResponse(BaseModel):
"""小米账号响应模型"""
id: int
username: str
password: str
region: str = "cn"
is_default: bool = True
is_active: bool = True
class XiaomiAccountUpdate(BaseModel):
"""小米账号更新模型"""
username: Optional[str] = None
password: Optional[str] = None
region: Optional[str] = None
is_default: Optional[bool] = None
is_active: Optional[bool] = None
class XiaomiAccountCreate(BaseModel):
"""小米账号创建模型"""
username: str
password: str
region: str = "cn"
is_default: bool = True
is_active: bool = True
class SystemConfigResponse(BaseModel):
"""系统配置响应模型"""
id: int
config_key: str
config_value: str
config_type: str
category: str
description: Optional[str] = None
is_active: bool = True
class SystemConfigUpdate(BaseModel):
"""系统配置更新模型"""
config_value: str
# ==================== AI 模型管理 ====================
@router.get("/ai-models", response_model=List[AIModelResponse])
async def get_ai_models(is_active: Optional[bool] = None):
"""获取AI模型配置列表"""
try:
config_service = get_config_service()
models = config_service.get_ai_models(is_active)
return models
except Exception as e:
logger.error(f"获取AI模型配置失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/ai-models/default", response_model=AIModelResponse)
async def get_default_ai_model():
"""获取默认AI模型配置"""
try:
config_service = get_config_service()
model = config_service.get_default_ai_model()
if not model:
raise HTTPException(status_code=404, detail="未找到默认AI模型")
return model
except HTTPException:
raise
except Exception as e:
logger.error(f"获取默认AI模型失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/ai-models/{model_id}", response_model=AIModelResponse)
async def get_ai_model(model_id: int):
"""根据ID获取AI模型配置"""
try:
config_service = get_config_service()
model = config_service.get_ai_model_by_id(model_id)
if not model:
raise HTTPException(status_code=404, detail="未找到该AI模型")
return model
except HTTPException:
raise
except Exception as e:
logger.error(f"获取AI模型失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.put("/ai-models/{model_id}")
async def update_ai_model(model_id: int, data: AIModelUpdate):
"""更新AI模型配置"""
try:
config_service = get_config_service()
update_data = data.model_dump(exclude_unset=True)
success = config_service.update_ai_model(model_id, update_data)
if not success:
raise HTTPException(status_code=404, detail="更新失败或未找到该模型")
return {"message": "更新成功", "model_id": model_id}
except HTTPException:
raise
except Exception as e:
logger.error(f"更新AI模型失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/ai-models", status_code=status.HTTP_201_CREATED)
async def create_ai_model(data: AIModelCreate):
"""创建新的AI模型配置"""
try:
config_service = get_config_service()
model_id = config_service.create_ai_model(data.model_dump())
return {"message": "创建成功", "model_id": model_id}
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"创建AI模型失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
# ==================== Agent 管理 ====================
@router.get("/agents", response_model=List[AgentResponse])
async def get_agents(is_enabled: Optional[bool] = None):
"""获取Agent配置列表"""
try:
config_service = get_config_service()
agents = config_service.get_agents(is_enabled)
return agents
except Exception as e:
logger.error(f"获取Agent配置失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/agents/{agent_code}", response_model=AgentResponse)
async def get_agent(agent_code: str):
"""根据代码获取Agent配置"""
try:
config_service = get_config_service()
agent = config_service.get_agent_by_code(agent_code)
if not agent:
raise HTTPException(status_code=404, detail="未找到该Agent")
return agent
except HTTPException:
raise
except Exception as e:
logger.error(f"获取Agent配置失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.put("/agents/{agent_id}")
async def update_agent(agent_id: int, data: AgentUpdate):
"""更新Agent配置"""
try:
config_service = get_config_service()
update_data = data.model_dump(exclude_unset=True)
success = config_service.update_agent(agent_id, update_data)
if not success:
raise HTTPException(status_code=404, detail="更新失败或未找到该Agent")
return {"message": "更新成功", "agent_id": agent_id}
except HTTPException:
raise
except Exception as e:
logger.error(f"更新Agent配置失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/agents/{agent_code}/prompt", response_model=AgentPromptResponse)
async def get_agent_prompt(agent_code: str):
"""获取Agent的系统提示词"""
try:
config_service = get_config_service()
prompt = config_service.get_agent_prompt(agent_code)
if not prompt:
raise HTTPException(status_code=404, detail="未找到该Agent的提示词")
return {"agent_code": agent_code, "prompt_text": prompt}
except HTTPException:
raise
except Exception as e:
logger.error(f"获取Agent提示词失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.put("/agents/{agent_code}/prompt")
async def update_agent_prompt(agent_code: str, data: AgentPromptUpdate):
"""更新Agent的系统提示词"""
try:
config_service = get_config_service()
success = config_service.update_agent_prompt(
agent_code, data.prompt_text, data.version
)
if not success:
raise HTTPException(status_code=404, detail="更新失败")
return {"message": "提示词更新成功", "agent_code": agent_code}
except HTTPException:
raise
except Exception as e:
logger.error(f"更新Agent提示词失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
# ==================== 设备管理 ====================
@router.get("/devices", response_model=List[DeviceResponse])
async def get_devices(
device_type: Optional[str] = None,
is_active: Optional[bool] = None
):
"""获取设备配置列表"""
try:
config_service = get_config_service()
devices = config_service.get_devices(device_type, is_active)
return devices
except Exception as e:
logger.error(f"获取设备配置失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/devices/{device_code}", response_model=DeviceResponse)
async def get_device(device_code: str):
"""根据代码获取设备配置"""
try:
config_service = get_config_service()
device = config_service.get_device_by_code(device_code)
if not device:
raise HTTPException(status_code=404, detail="未找到该设备")
return device
except HTTPException:
raise
except Exception as e:
logger.error(f"获取设备配置失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.put("/devices/{device_id}")
async def update_device(device_id: int, data: DeviceUpdate):
"""更新设备配置"""
try:
config_service = get_config_service()
update_data = data.model_dump(exclude_unset=True)
success = config_service.update_device(device_id, update_data)
if not success:
raise HTTPException(status_code=404, detail="更新失败或未找到该设备")
return {"message": "更新成功", "device_id": device_id}
except HTTPException:
raise
except Exception as e:
logger.error(f"更新设备配置失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/devices", status_code=status.HTTP_201_CREATED)
async def create_device(data: DeviceCreate):
"""创建新设备配置"""
try:
config_service = get_config_service()
device_id = config_service.create_device(data.model_dump())
return {"message": "创建成功", "device_id": device_id}
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"创建设备配置失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
# ==================== 小米账号管理 ====================
@router.get("/xiaomi-accounts", response_model=List[XiaomiAccountResponse])
async def get_xiaomi_accounts(is_active: Optional[bool] = None):
"""获取小米账号配置列表"""
try:
config_service = get_config_service()
accounts = config_service.get_xiaomi_accounts(is_active)
return accounts
except Exception as e:
logger.error(f"获取小米账号配置失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/xiaomi-accounts/default", response_model=XiaomiAccountResponse)
async def get_default_xiaomi_account():
"""获取默认小米账号"""
try:
config_service = get_config_service()
account = config_service.get_default_xiaomi_account()
if not account:
raise HTTPException(status_code=404, detail="未找到默认小米账号")
return account
except HTTPException:
raise
except Exception as e:
logger.error(f"获取默认小米账号失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.put("/xiaomi-accounts/{account_id}")
async def update_xiaomi_account(account_id: int, data: XiaomiAccountUpdate):
"""更新小米账号配置"""
try:
config_service = get_config_service()
update_data = data.model_dump(exclude_unset=True)
success = config_service.update_xiaomi_account(account_id, update_data)
if not success:
raise HTTPException(status_code=404, detail="更新失败或未找到该账号")
return {"message": "更新成功", "account_id": account_id}
except HTTPException:
raise
except Exception as e:
logger.error(f"更新小米账号失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/xiaomi-accounts", status_code=status.HTTP_201_CREATED)
async def create_xiaomi_account(data: XiaomiAccountCreate):
"""创建新小米账号"""
try:
config_service = get_config_service()
account_id = config_service.create_xiaomi_account(data.model_dump())
return {"message": "创建成功", "account_id": account_id}
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"创建小米账号失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
# ==================== 系统配置管理 ====================
@router.get("/system-config", response_model=List[SystemConfigResponse])
async def get_system_configs(category: Optional[str] = None):
"""获取系统配置列表"""
try:
config_service = get_config_service()
configs = config_service.get_system_configs(category)
return configs
except Exception as e:
logger.error(f"获取系统配置失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/system-config/{config_key}")
async def get_system_config(config_key: str):
"""根据键获取系统配置值"""
try:
config_service = get_config_service()
value = config_service.get_system_config(config_key)
if value is None:
raise HTTPException(status_code=404, detail="未找到该配置项")
return {"config_key": config_key, "config_value": value}
except HTTPException:
raise
except Exception as e:
logger.error(f"获取系统配置失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.put("/system-config/{config_key}")
async def update_system_config(config_key: str, data: SystemConfigUpdate):
"""更新系统配置"""
try:
config_service = get_config_service()
success = config_service.update_system_config(config_key, data.config_value)
if not success:
raise HTTPException(status_code=404, detail="更新失败或未找到该配置项")
return {"message": "更新成功", "config_key": config_key}
except HTTPException:
raise
except Exception as e:
logger.error(f"更新系统配置失败: {e}")
raise HTTPException(status_code=500, detail=str(e))