86 lines
3.3 KiB
Python
86 lines
3.3 KiB
Python
"""对话路由:会话管理 + REST 非流式对话。"""
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.orm import Session
|
|
|
|
from ..core.deps import get_current_user
|
|
from ..core.response import ok
|
|
from ..database import get_db
|
|
from ..models import Agent, ChatMessage, ChatSession, User
|
|
from ..schemas.chat import ChatRequest, ChatSessionCreate
|
|
from ..services import chat_service
|
|
|
|
router = APIRouter(prefix="/chat", tags=["对话"])
|
|
|
|
|
|
def _session_out(s: ChatSession) -> dict:
|
|
return {
|
|
"id": s.id, "title": s.title, "agent_id": s.agent_id, "model": s.model,
|
|
"created_at": s.created_at.isoformat(), "updated_at": s.updated_at.isoformat(),
|
|
}
|
|
|
|
|
|
def _message_out(m: ChatMessage) -> dict:
|
|
return {"id": m.id, "session_id": m.session_id, "role": m.role, "content": m.content,
|
|
"model": m.model, "created_at": m.created_at.isoformat()}
|
|
|
|
|
|
def _get_owned_session(db: Session, user: User, session_id: int) -> ChatSession:
|
|
s = db.get(ChatSession, session_id)
|
|
if not s or s.user_id != user.id:
|
|
raise HTTPException(status_code=404, detail="会话不存在")
|
|
return s
|
|
|
|
|
|
@router.get("/sessions")
|
|
def list_sessions(user: User = Depends(get_current_user), db: Session = Depends(get_db)):
|
|
sessions = (
|
|
db.query(ChatSession).filter(ChatSession.user_id == user.id)
|
|
.order_by(ChatSession.updated_at.desc()).all()
|
|
)
|
|
return ok([_session_out(s) for s in sessions])
|
|
|
|
|
|
@router.post("/sessions")
|
|
def create_session(body: ChatSessionCreate, user: User = Depends(get_current_user), db: Session = Depends(get_db)):
|
|
if body.agent_id:
|
|
agent = db.get(Agent, body.agent_id)
|
|
if not agent or (agent.user_id and agent.user_id != user.id and not agent.is_public):
|
|
raise HTTPException(status_code=404, detail="智能体不存在")
|
|
s = ChatSession(user_id=user.id, title=body.title, agent_id=body.agent_id, model=body.model)
|
|
db.add(s)
|
|
db.commit()
|
|
db.refresh(s)
|
|
return ok(_session_out(s))
|
|
|
|
|
|
@router.get("/sessions/{session_id}/messages")
|
|
def list_messages(session_id: int, user: User = Depends(get_current_user), db: Session = Depends(get_db)):
|
|
s = _get_owned_session(db, user, session_id)
|
|
messages = db.query(ChatMessage).filter(ChatMessage.session_id == s.id).order_by(ChatMessage.id).all()
|
|
return ok([_message_out(m) for m in messages])
|
|
|
|
|
|
@router.post("/sessions/{session_id}/messages")
|
|
async def send_message(session_id: int, body: ChatRequest,
|
|
user: User = Depends(get_current_user), db: Session = Depends(get_db)):
|
|
s = _get_owned_session(db, user, session_id)
|
|
try:
|
|
reply = await chat_service.chat_once(db, user, s, body.content, body.agent_id, body.model)
|
|
except LookupError as e:
|
|
raise HTTPException(status_code=404, detail=str(e))
|
|
except Exception as e:
|
|
raise HTTPException(status_code=502, detail=f"模型调用失败:{e}")
|
|
# 自动生成会话标题
|
|
if s.title == "新对话" and len(body.content) <= 40:
|
|
s.title = body.content[:20]
|
|
db.commit()
|
|
return ok(_message_out(reply))
|
|
|
|
|
|
@router.delete("/sessions/{session_id}")
|
|
def delete_session(session_id: int, user: User = Depends(get_current_user), db: Session = Depends(get_db)):
|
|
s = _get_owned_session(db, user, session_id)
|
|
db.delete(s)
|
|
db.commit()
|
|
return ok(message="已删除")
|