Initial commit: AI Interview System

This commit is contained in:
111
2026-01-23 13:57:48 +08:00
commit 95770afe21
127 changed files with 24686 additions and 0 deletions

129
backend/app/routers/room.py Normal file
View File

@@ -0,0 +1,129 @@
"""
房间相关接口
"""
import time
import uuid
from fastapi import APIRouter, HTTPException
from loguru import logger
from app.schemas import ApiResponse, CreateRoomRequest, CreateRoomResponse
from app.services.coze_service import coze_service
from app.config import settings
router = APIRouter()
def generate_user_id() -> str:
"""生成用户 ID"""
return f"user_{uuid.uuid4().hex[:12]}"
def generate_session_id() -> str:
"""生成会话 ID"""
timestamp = int(time.time())
random_code = uuid.uuid4().hex[:6]
return f"SESS_{timestamp}_{random_code}"
@router.post("/rooms", response_model=ApiResponse)
async def create_room(request: CreateRoomRequest):
"""
创建语音房间
方案A前端不预先收集姓名和简历
- sessionId 和 fileId 都是可选的
- 如果没有传入 sessionId后端自动生成
- 姓名和简历由 Coze 工作流在对话中收集
"""
try:
# 生成用户 ID
user_id = generate_user_id()
# 如果没有传入 sessionId自动生成
session_id = request.sessionId or generate_session_id()
# 调用 Coze API 创建语音房间
# Coze 会自动让 Bot 加入房间,并返回 RTC 连接信息
room_data = await coze_service.create_audio_room(
user_id=user_id,
file_id=request.fileId, # 可能是 None
session_id=session_id,
)
# Coze 返回的字段映射
# Coze: app_id, room_id, token, uid
# 前端期望: appId, roomId, token, userId, sessionId
response_data = CreateRoomResponse(
appId=room_data.get("app_id", ""),
roomId=room_data.get("room_id", ""),
token=room_data.get("token", ""),
userId=room_data.get("uid", user_id),
sessionId=session_id, # 返回 sessionId 给前端
debugInfo=room_data.get("debug_info"), # 调试信息
)
logger.info(f"Room created: session_id={session_id}, room_id={response_data.roomId}")
return ApiResponse(
code=0,
message="success",
data=response_data
)
except Exception as e:
logger.error(f"Create room error: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/interviews/{session_id}/end", response_model=ApiResponse)
async def end_interview(session_id: str):
"""
结束面试
- 通知后端面试已结束
- 可以在这里添加后续处理逻辑
"""
try:
logger.info(f"Interview ended: session_id={session_id}")
# TODO: 可以在这里添加后续处理逻辑
# 例如:更新状态、发送通知等
return ApiResponse(
code=0,
message="success",
data={"success": True}
)
except Exception as e:
logger.error(f"End interview error: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/coze-config", response_model=ApiResponse)
async def get_coze_config():
"""
获取 Coze Realtime SDK 配置
返回前端需要的配置信息,用于直接连接 Coze Realtime
注意:这种方式会暴露 PAT Token 到浏览器,仅用于开发/测试
"""
try:
config = {
"accessToken": settings.COZE_PAT_TOKEN,
"botId": settings.COZE_BOT_ID,
"voiceId": settings.COZE_VOICE_ID,
"connectorId": "1024", # 固定值
}
logger.info(f"Coze config requested: bot_id={settings.COZE_BOT_ID}")
return ApiResponse(
code=0,
message="success",
data=config
)
except Exception as e:
logger.error(f"Get coze config error: {e}")
raise HTTPException(status_code=500, detail=str(e))