feat: 初始化考培练系统项目

- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
111
2026-01-24 19:33:28 +08:00
commit 998211c483
1197 changed files with 228429 additions and 0 deletions

View File

@@ -0,0 +1,199 @@
"""
Coze AI对话服务
"""
import logging
from typing import Optional
from cozepy import Coze, COZE_CN_BASE_URL, Message
from cozepy.exception import CozeError, CozeAPIError
from app.core.config import settings
from app.services.ai.coze.client import get_auth_manager
# 注意:不再直接使用 TokenAuth统一通过 get_auth_manager() 管理认证
logger = logging.getLogger(__name__)
class CozeService:
"""Coze对话服务"""
def __init__(self):
"""初始化Coze客户端"""
if not settings.COZE_PRACTICE_BOT_ID:
raise ValueError("COZE_PRACTICE_BOT_ID 未配置")
self.bot_id = settings.COZE_PRACTICE_BOT_ID
self._auth_manager = get_auth_manager()
logger.info(
f"CozeService初始化成功Bot ID={self.bot_id}, "
f"Base URL={COZE_CN_BASE_URL}"
)
@property
def client(self) -> Coze:
"""获取Coze客户端每次获取确保OAuth token有效"""
return self._auth_manager.get_client(force_new=True)
def build_scene_prompt(
self,
scene_name: str,
scene_background: str,
scene_ai_role: str,
scene_objectives: list,
scene_keywords: Optional[list] = None,
scene_description: Optional[str] = None,
user_message: str = ""
) -> str:
"""
构建场景提示词Markdown格式
参数:
scene_name: 场景名称
scene_background: 场景背景
scene_ai_role: AI角色描述
scene_objectives: 练习目标列表
scene_keywords: 关键词列表
scene_description: 场景描述(可选)
user_message: 用户第一句话
返回:
完整的场景提示词Markdown格式
"""
# 构建练习目标
objectives_text = "\n".join(
f"{i+1}. {obj}" for i, obj in enumerate(scene_objectives)
)
# 构建关键词
keywords_text = ", ".join(scene_keywords) if scene_keywords else ""
# 构建完整提示词
prompt = f"""# 陪练场景设定
## 场景名称
{scene_name}
"""
# 添加场景描述(如果有)
if scene_description:
prompt += f"""
## 场景描述
{scene_description}
"""
prompt += f"""
## 场景背景
{scene_background}
## AI角色要求
{scene_ai_role}
## 练习目标
{objectives_text}
"""
# 添加关键词(如果有)
if keywords_text:
prompt += f"""
## 关键词
{keywords_text}
"""
prompt += f"""
---
现在开始陪练对话。请你严格按照上述场景设定扮演角色,与学员进行实战对话练习。
不要提及"场景设定""角色扮演"等元信息,直接进入角色开始对话。
学员的第一句话:{user_message}
"""
return prompt
def create_stream_chat(
self,
user_id: str,
message: str,
conversation_id: Optional[str] = None
):
"""
创建流式对话
参数:
user_id: 用户ID
message: 消息内容
conversation_id: 对话ID续接对话时使用
返回:
Coze流式对话迭代器
"""
try:
logger.info(
f"创建Coze流式对话user_id={user_id}, "
f"conversation_id={conversation_id}, "
f"message_length={len(message)}"
)
stream = self.client.chat.stream(
bot_id=self.bot_id,
user_id=user_id,
additional_messages=[Message.build_user_question_text(message)],
conversation_id=conversation_id
)
# 记录LogID用于排查问题
if hasattr(stream, 'response') and hasattr(stream.response, 'logid'):
logger.info(f"Coze对话创建成功logid={stream.response.logid}")
return stream
except (CozeError, CozeAPIError) as e:
logger.error(f"Coze API调用失败: {e}")
raise
except Exception as e:
logger.error(f"创建Coze对话失败: {e}")
raise
def cancel_chat(self, conversation_id: str, chat_id: str):
"""
中断对话
参数:
conversation_id: 对话ID
chat_id: 聊天ID
"""
try:
logger.info(f"中断Coze对话conversation_id={conversation_id}, chat_id={chat_id}")
result = self.client.chat.cancel(
conversation_id=conversation_id,
chat_id=chat_id
)
logger.info(f"对话中断成功")
return result
except (CozeError, CozeAPIError) as e:
logger.error(f"中断对话失败: {e}")
raise
except Exception as e:
logger.error(f"中断对话异常: {e}")
raise
# 单例模式
_coze_service: Optional[CozeService] = None
def get_coze_service() -> CozeService:
"""
获取CozeService单例
用于FastAPI依赖注入
"""
global _coze_service
if _coze_service is None:
_coze_service = CozeService()
return _coze_service