diff --git a/app/models.py b/app/models.py new file mode 100644 index 0000000..c399487 --- /dev/null +++ b/app/models.py @@ -0,0 +1,135 @@ +"""数据模型""" +from __future__ import annotations +import uuid +from datetime import datetime +from sqlalchemy import Column, String, Text, Float, Integer, DateTime, ForeignKey, JSON, Boolean +from sqlalchemy.orm import relationship +from .database import Base + + +class Agent(Base): + """Agent 定义""" + __tablename__ = "agents" + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + name = Column(String(255), nullable=False) + description = Column(Text, nullable=True) + system_prompt = Column(Text, nullable=True) + llm_provider = Column(String(100), nullable=True) + temperature = Column(Float, default=0.7) + max_tokens = Column(Integer, default=2048) + created_at = Column(DateTime, default=datetime.utcnow) + updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) + + tools = relationship("AgentTool", back_populates="agent", cascade="all, delete-orphan") + conversations = relationship("Conversation", back_populates="agent", cascade="all, delete-orphan") + + def __repr__(self) -> str: + return f"" + + +class AgentTool(Base): + """Agent 绑定的工具""" + __tablename__ = "agent_tools" + + id = Column(Integer, primary_key=True, autoincrement=True) + agent_id = Column(String(36), ForeignKey("agents.id", ondelete="CASCADE"), nullable=False) + tool_name = Column(String(255), nullable=False) + enabled = Column(Boolean, default=True) + + agent = relationship("Agent", back_populates="tools") + + def __repr__(self) -> str: + return f"" + + +class Conversation(Base): + """对话会话""" + __tablename__ = "conversations" + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + agent_id = Column(String(36), ForeignKey("agents.id", ondelete="CASCADE"), nullable=False) + title = Column(String(255), nullable=True) + created_at = Column(DateTime, default=datetime.utcnow) + updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) + + agent = relationship("Agent", back_populates="conversations") + messages = relationship("Message", back_populates="conversation", cascade="all, delete-orphan") + + def __repr__(self) -> str: + return f"" + + +class Message(Base): + """消息记录""" + __tablename__ = "messages" + + id = Column(Integer, primary_key=True, autoincrement=True) + conversation_id = Column(String(36), ForeignKey("conversations.id", ondelete="CASCADE"), nullable=False) + role = Column(String(20), nullable=False) # user / assistant / system / tool + content = Column(Text, nullable=True) + tool_calls = Column(JSON, nullable=True) + created_at = Column(DateTime, default=datetime.utcnow) + + conversation = relationship("Conversation", back_populates="messages") + + def __repr__(self) -> str: + return f"" + + +class Workflow(Base): + """工作流定义""" + __tablename__ = "workflows" + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + name = Column(String(255), nullable=False) + description = Column(Text, nullable=True) + definition = Column(JSON, nullable=True) + status = Column(String(50), default="draft") # draft / active / archived + created_at = Column(DateTime, default=datetime.utcnow) + updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) + + runs = relationship("WorkflowRun", back_populates="workflow", cascade="all, delete-orphan") + + def __repr__(self) -> str: + return f"" + + +class WorkflowRun(Base): + """工作流执行实例""" + __tablename__ = "workflow_runs" + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + workflow_id = Column(String(36), ForeignKey("workflows.id", ondelete="CASCADE"), nullable=False) + status = Column(String(50), default="pending") # pending / running / completed / failed + results = Column(JSON, nullable=True) + error = Column(Text, nullable=True) + started_at = Column(DateTime, default=datetime.utcnow) + completed_at = Column(DateTime, nullable=True) + + workflow = relationship("Workflow", back_populates="runs") + steps = relationship("WorkflowStep", back_populates="run", cascade="all, delete-orphan") + + def __repr__(self) -> str: + return f"" + + +class WorkflowStep(Base): + """工作流步骤""" + __tablename__ = "workflow_steps" + + id = Column(Integer, primary_key=True, autoincrement=True) + run_id = Column(String(36), ForeignKey("workflow_runs.id", ondelete="CASCADE"), nullable=False) + step_name = Column(String(255), nullable=False) + agent_id = Column(String(36), ForeignKey("agents.id"), nullable=True) + status = Column(String(50), default="pending") # pending / running / completed / failed + input_data = Column(JSON, nullable=True) + output_data = Column(JSON, nullable=True) + started_at = Column(DateTime, default=datetime.utcnow) + completed_at = Column(DateTime, nullable=True) + + run = relationship("WorkflowRun", back_populates="steps") + agent = relationship("Agent") + + def __repr__(self) -> str: + return f""