修复主角回复聊天气泡问题,加入聊天轮数引用机制
This commit is contained in:
parent
23e3e68fa9
commit
47fc227d59
@ -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")
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -48,6 +48,23 @@
|
||||
|
||||
<el-divider>系统限制</el-divider>
|
||||
|
||||
<el-form-item label="连续对话上下文">
|
||||
<el-switch v-model="policy.enable_chat_context" />
|
||||
<span style="margin-left: 12px; color: #909399;">
|
||||
关闭后每次聊天互相独立,不携带上次对话
|
||||
</span>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="上下文轮数">
|
||||
<el-input-number
|
||||
v-model="policy.chat_context_rounds"
|
||||
:min="0"
|
||||
:max="50"
|
||||
:disabled="!policy.enable_chat_context"
|
||||
/>
|
||||
<span style="margin-left: 12px; color: #909399;">轮(1轮=用户+AI)</span>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="单次对话Token限制">
|
||||
<el-input-number
|
||||
v-model="policy.max_tokens_per_chat"
|
||||
@ -101,9 +118,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { Check, Refresh } from '@element-plus/icons-vue'
|
||||
import { adminAPI } from '@/api/index'
|
||||
|
||||
export default {
|
||||
name: 'DefaultPolicy',
|
||||
@ -122,6 +140,8 @@ export default {
|
||||
max_tokens_per_chat: 2000,
|
||||
max_daily_chats: 20,
|
||||
max_conversation_rounds: 20,
|
||||
enable_chat_context: false,
|
||||
chat_context_rounds: 0,
|
||||
enable_content_moderation: true,
|
||||
enable_keyword_filter: true
|
||||
})
|
||||
@ -134,12 +154,33 @@ export default {
|
||||
ElMessage.info('选择主角功能开发中...')
|
||||
}
|
||||
|
||||
const effectiveChatContextRounds = computed(() => {
|
||||
return policy.enable_chat_context ? Number(policy.chat_context_rounds || 0) : 0
|
||||
})
|
||||
|
||||
const loadPolicy = async () => {
|
||||
try {
|
||||
const res = await adminAPI.getSystemConfig()
|
||||
const rounds = Number(res?.data?.data?.ai?.chat_context_rounds ?? 0)
|
||||
policy.chat_context_rounds = Number.isNaN(rounds) ? 0 : Math.max(0, Math.min(50, rounds))
|
||||
policy.enable_chat_context = policy.chat_context_rounds > 0
|
||||
} catch (error) {
|
||||
console.error('加载系统配置失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const savePolicy = async () => {
|
||||
try {
|
||||
saving.value = true
|
||||
await adminAPI.updateSystemConfig({
|
||||
ai: {
|
||||
chat_context_rounds: effectiveChatContextRounds.value
|
||||
}
|
||||
})
|
||||
ElMessage.success('策略保存成功')
|
||||
} catch (error) {
|
||||
ElMessage.error('保存失败')
|
||||
console.error('保存策略失败:', error)
|
||||
ElMessage.error(error?.response?.data?.detail || '保存失败')
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
@ -154,19 +195,22 @@ export default {
|
||||
max_tokens_per_chat: 2000,
|
||||
max_daily_chats: 20,
|
||||
max_conversation_rounds: 20,
|
||||
enable_chat_context: false,
|
||||
chat_context_rounds: 0,
|
||||
enable_content_moderation: true,
|
||||
enable_keyword_filter: true
|
||||
})
|
||||
ElMessage.success('已重置为默认策略')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 加载策略配置
|
||||
onMounted(async () => {
|
||||
await loadPolicy()
|
||||
})
|
||||
|
||||
return {
|
||||
saving,
|
||||
policy,
|
||||
effectiveChatContextRounds,
|
||||
selectBackground,
|
||||
selectPet,
|
||||
savePolicy,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user