Files
fquiz/api/app/models/ai_chat.py
T
chengkai3 21f9839dd6 feat: [FL-166] 实现AI问答功能
- 后端实现:
  - 添加 ai_chat_conversations 和 ai_chat_messages 数据模型
  - 创建 AI 问答 API 路由(/api/v1/ai-chat)
  - 实现对话管理和消息发送服务
  - 集成 OpenAI API 进行对话交互
  - 支持流式对话历史和上下文管理

- 前端实现:
  - 创建 ChatGPT 风格的聊天界面(/admin/ai-chat)
  - 支持新建、选择、删除对话
  - 实现消息发送和实时显示
  - 使用 Ant Design 组件构建响应式 UI

- 系统参数配置:
  - ai_chat.openai_api_key: OpenAI API 密钥
  - ai_chat.model: 使用的 AI 模型(默认 gpt-3.5-turbo)
  - ai_chat.base_url: API 基础 URL(支持第三方兼容接口)

- 数据库迁移:
  - 002_add_ai_chat.sql: 创建对话和消息表
  - 003_add_ai_chat_params.sql: 添加系统参数默认配置

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-20 23:20:26 +08:00

60 lines
1.8 KiB
Python

from __future__ import annotations
from datetime import datetime
from typing import TYPE_CHECKING
from sqlalchemy import DateTime, ForeignKey, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship
from ..core.database import Base
from .base import utcnow
if TYPE_CHECKING:
from .user import User
class AiChatConversation(Base):
__tablename__ = "ai_chat_conversations"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
title: Mapped[str] = mapped_column(String(256), default="新对话")
user_id: Mapped[str] = mapped_column(
String(36),
ForeignKey("users.user_id", ondelete="CASCADE"),
index=True,
)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utcnow)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=utcnow,
onupdate=utcnow,
)
user: Mapped[User] = relationship("User", foreign_keys=[user_id], lazy="selectin")
messages: Mapped[list[AiChatMessage]] = relationship(
"AiChatMessage",
back_populates="conversation",
cascade="all, delete-orphan",
lazy="select",
)
class AiChatMessage(Base):
__tablename__ = "ai_chat_messages"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
conversation_id: Mapped[int] = mapped_column(
Integer,
ForeignKey("ai_chat_conversations.id", ondelete="CASCADE"),
index=True,
)
role: Mapped[str] = mapped_column(String(16), index=True)
content: Mapped[str] = mapped_column(Text())
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utcnow)
conversation: Mapped[AiChatConversation] = relationship(
"AiChatConversation",
back_populates="messages",
lazy="selectin",
)