Files
companion-assistant/backend/app/api/chat.py
T

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="已删除")