diff --git a/backend/api/admin_router.py b/backend/api/admin_router.py index 2a2caa0..b928566 100644 --- a/backend/api/admin_router.py +++ b/backend/api/admin_router.py @@ -14,6 +14,7 @@ from utils.database import get_db from utils.security import get_current_admin_user, get_current_user from models.database import User, Pet, Background, ChatLog, UserWallet, UserBackgroundRelation, BackgroundPetConfig from services.token_service import TokenService +from config.settings import get_chat_context_rounds, set_chat_context_rounds logger = logging.getLogger(__name__) admin_router = APIRouter() @@ -890,7 +891,8 @@ async def get_system_config(current_admin: Dict = Depends(get_current_admin_user "default_model": "gpt-4", "temperature": 0.7, "max_tokens": 2000, - "top_p": 0.9 + "top_p": 0.9, + "chat_context_rounds": get_chat_context_rounds() }, "voice": { "default_tts_provider": "volcengine", @@ -913,10 +915,30 @@ async def update_system_config( ): """Update system configuration (admin only)""" logger.info(f"Admin {current_admin.get('id')} updating system config") - # TODO: 实现配置更新逻辑 + + ai_config = config_data.get("ai") if isinstance(config_data, dict) else None + if isinstance(ai_config, dict) and "chat_context_rounds" in ai_config: + rounds = ai_config.get("chat_context_rounds", 0) + try: + rounds = int(rounds) + except (TypeError, ValueError): + raise HTTPException(status_code=400, detail="chat_context_rounds 必须是整数") + + if rounds < 0: + raise HTTPException(status_code=400, detail="chat_context_rounds 不能小于0") + if rounds > 50: + raise HTTPException(status_code=400, detail="chat_context_rounds 不能大于50") + + set_chat_context_rounds(rounds) + return { "success": True, - "message": "System configuration updated successfully" + "message": "System configuration updated successfully", + "data": { + "ai": { + "chat_context_rounds": get_chat_context_rounds() + } + } } @admin_router.patch("/users/{user_id}/status") diff --git a/backend/config/settings.py b/backend/config/settings.py index 1e3b1c7..4e7f5c1 100644 --- a/backend/config/settings.py +++ b/backend/config/settings.py @@ -93,6 +93,20 @@ class Settings(BaseSettings): DEFAULT_BACKGROUND_ID: int = int(os.getenv("DEFAULT_BACKGROUND_ID", "1")) DEFAULT_DAILY_QUOTA: int = int(os.getenv("DEFAULT_DAILY_QUOTA", "20")) + # 聊天上下文轮数(1轮=一组用户+AI),0表示不带历史上下文 + CHAT_CONTEXT_ROUNDS: int = int(os.getenv("CHAT_CONTEXT_ROUNDS", "0")) settings = Settings() + +# 运行时可动态更新(用于后台系统配置即时生效) +_runtime_chat_context_rounds = max(0, int(getattr(settings, "CHAT_CONTEXT_ROUNDS", 0) or 0)) + + +def get_chat_context_rounds() -> int: + return max(0, int(_runtime_chat_context_rounds)) + + +def set_chat_context_rounds(rounds: int) -> None: + global _runtime_chat_context_rounds + _runtime_chat_context_rounds = max(0, int(rounds)) diff --git a/backend/services/chat_service.py b/backend/services/chat_service.py index 1049f97..374a319 100644 --- a/backend/services/chat_service.py +++ b/backend/services/chat_service.py @@ -14,6 +14,7 @@ import asyncio from models.database import Pet, Background, BackgroundPetConfig, ChatLog from services.doubao_service import doubao_service +from config.settings import get_chat_context_rounds logger = logging.getLogger(__name__) @@ -52,18 +53,22 @@ async def send_message(db_session: AsyncSession, user_id: int, message: str, pet if not background: raise ValueError(f"Background with id {background_id} not found") - history_result = await db_session.execute( - sa_select(ChatLog).where( - ChatLog.user_id == user_id, - ChatLog.pet_id == pet_id, - ChatLog.bg_id == background_id - ).order_by(ChatLog.created_at.desc()).limit(10) - ) - history_logs = history_result.scalars().all() - history = [ - {"is_user": True, "content": log.user_msg, "created_at": log.created_at} - for log in reversed(history_logs) - ] + context_rounds = get_chat_context_rounds() + history = [] + if context_rounds > 0: + history_result = await db_session.execute( + sa_select(ChatLog).where( + ChatLog.user_id == user_id, + ChatLog.pet_id == pet_id, + ChatLog.bg_id == background_id + ).order_by(ChatLog.created_at.desc()).limit(context_rounds) + ) + history_logs = history_result.scalars().all() + for log in reversed(history_logs): + if log.user_msg: + history.append({"is_user": True, "content": log.user_msg, "created_at": log.created_at}) + if log.ai_msg: + history.append({"is_user": False, "content": log.ai_msg, "created_at": log.created_at}) messages = doubao_service.build_messages( system_prompt=pet.global_prompt, @@ -233,18 +238,22 @@ async def send_message_stream(db_session: AsyncSession, user_id: int, message: s yield f"错误:找不到ID为{background_id}的背景" return - history_result = await db_session.execute( - sa_select(ChatLog).where( - ChatLog.user_id == user_id, - ChatLog.pet_id == pet_id, - ChatLog.bg_id == background_id - ).order_by(ChatLog.created_at.desc()).limit(10) - ) - history_logs = history_result.scalars().all() - history = [ - {"is_user": True, "content": log.user_msg, "created_at": log.created_at} - for log in reversed(history_logs) - ] + context_rounds = get_chat_context_rounds() + history = [] + if context_rounds > 0: + history_result = await db_session.execute( + sa_select(ChatLog).where( + ChatLog.user_id == user_id, + ChatLog.pet_id == pet_id, + ChatLog.bg_id == background_id + ).order_by(ChatLog.created_at.desc()).limit(context_rounds) + ) + history_logs = history_result.scalars().all() + for log in reversed(history_logs): + if log.user_msg: + history.append({"is_user": True, "content": log.user_msg, "created_at": log.created_at}) + if log.ai_msg: + history.append({"is_user": False, "content": log.ai_msg, "created_at": log.created_at}) messages = doubao_service.build_messages( system_prompt=pet.global_prompt, diff --git a/frontend/src/api/index.js b/frontend/src/api/index.js index 31e8278..0742f4a 100644 --- a/frontend/src/api/index.js +++ b/frontend/src/api/index.js @@ -141,7 +141,9 @@ export const adminAPI = { savePet: (petData) => apiClient.post('/api/v1/admin/pets', petData), getBackgroundPetBindings: (backgroundId) => apiClient.get(`/api/v1/admin/backgrounds/${backgroundId}/pet-bindings`), saveBackgroundPetBindings: (backgroundId, bindings) => apiClient.post(`/api/v1/admin/backgrounds/${backgroundId}/pet-bindings`, { bindings }), - deleteBackgroundPetBinding: (backgroundId, bindingId) => apiClient.delete(`/api/v1/admin/backgrounds/${backgroundId}/pet-bindings/${bindingId}`) + deleteBackgroundPetBinding: (backgroundId, bindingId) => apiClient.delete(`/api/v1/admin/backgrounds/${backgroundId}/pet-bindings/${bindingId}`), + getSystemConfig: () => apiClient.get('/api/v1/admin/config'), + updateSystemConfig: (data) => apiClient.patch('/api/v1/admin/config', data) } export const adminApi = adminAPI diff --git a/frontend/src/views/components/admin/DefaultPolicy.vue b/frontend/src/views/components/admin/DefaultPolicy.vue index 2dec461..ec117cf 100644 --- a/frontend/src/views/components/admin/DefaultPolicy.vue +++ b/frontend/src/views/components/admin/DefaultPolicy.vue @@ -48,6 +48,23 @@ 系统限制 + + + + 关闭后每次聊天互相独立,不携带上次对话 + + + + + + 轮(1轮=用户+AI) + +