166 lines
8.4 KiB
Python
166 lines
8.4 KiB
Python
from datetime import datetime
|
|
from typing import List, Optional
|
|
from sqlalchemy import String, Integer, DateTime, Text, Float, ForeignKey, JSON
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from .db import Base
|
|
|
|
|
|
class User(Base):
|
|
__tablename__ = "users"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
|
|
email: Mapped[str] = mapped_column(String(255), unique=True, index=True, nullable=False)
|
|
password_hash: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
|
|
|
|
class Voice(Base):
|
|
__tablename__ = "voices"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
|
name: Mapped[str] = mapped_column(String(128), nullable=False)
|
|
vendor: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
gender: Mapped[str] = mapped_column(String(32), nullable=False)
|
|
language: Mapped[str] = mapped_column(String(16), nullable=False)
|
|
description: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
voice_params: Mapped[dict] = mapped_column(JSON, default=dict)
|
|
|
|
|
|
class Assistant(Base):
|
|
__tablename__ = "assistants"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
|
user_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"), index=True)
|
|
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
call_count: Mapped[int] = mapped_column(Integer, default=0)
|
|
opener: Mapped[str] = mapped_column(Text, default="")
|
|
prompt: Mapped[str] = mapped_column(Text, default="")
|
|
knowledge_base_id: Mapped[Optional[str]] = mapped_column(String(64), nullable=True)
|
|
language: Mapped[str] = mapped_column(String(16), default="zh")
|
|
voice: Mapped[Optional[str]] = mapped_column(String(64), nullable=True)
|
|
speed: Mapped[float] = mapped_column(Float, default=1.0)
|
|
hotwords: Mapped[dict] = mapped_column(JSON, default=list)
|
|
tools: Mapped[dict] = mapped_column(JSON, default=list)
|
|
interruption_sensitivity: Mapped[int] = mapped_column(Integer, default=500)
|
|
config_mode: Mapped[str] = mapped_column(String(32), default="platform")
|
|
api_url: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
|
|
api_key: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
|
|
user = relationship("User")
|
|
call_records = relationship("CallRecord", back_populates="assistant")
|
|
|
|
|
|
class KnowledgeBase(Base):
|
|
__tablename__ = "knowledge_bases"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
|
user_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"), index=True)
|
|
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
description: Mapped[str] = mapped_column(Text, default="")
|
|
embedding_model: Mapped[str] = mapped_column(String(64), default="text-embedding-3-small")
|
|
chunk_size: Mapped[int] = mapped_column(Integer, default=500)
|
|
chunk_overlap: Mapped[int] = mapped_column(Integer, default=50)
|
|
doc_count: Mapped[int] = mapped_column(Integer, default=0)
|
|
chunk_count: Mapped[int] = mapped_column(Integer, default=0)
|
|
status: Mapped[str] = mapped_column(String(32), default="active")
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
|
|
user = relationship("User")
|
|
documents = relationship("KnowledgeDocument", back_populates="kb")
|
|
|
|
|
|
class KnowledgeDocument(Base):
|
|
__tablename__ = "knowledge_documents"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
|
kb_id: Mapped[str] = mapped_column(String(64), ForeignKey("knowledge_bases.id"), index=True)
|
|
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
size: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
file_type: Mapped[str] = mapped_column(String(32), default="txt")
|
|
storage_url: Mapped[Optional[str]] = mapped_column(String(512), nullable=True)
|
|
status: Mapped[str] = mapped_column(String(32), default="pending") # pending/processing/completed/failed
|
|
chunk_count: Mapped[int] = mapped_column(Integer, default=0)
|
|
error_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
|
upload_date: Mapped[str] = mapped_column(String(32), nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
processed_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
|
|
|
|
kb = relationship("KnowledgeBase", back_populates="documents")
|
|
|
|
|
|
class Workflow(Base):
|
|
__tablename__ = "workflows"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
|
user_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"), index=True)
|
|
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
node_count: Mapped[int] = mapped_column(Integer, default=0)
|
|
created_at: Mapped[str] = mapped_column(String(32), default="")
|
|
updated_at: Mapped[str] = mapped_column(String(32), default="")
|
|
global_prompt: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
|
nodes: Mapped[dict] = mapped_column(JSON, default=list)
|
|
edges: Mapped[dict] = mapped_column(JSON, default=list)
|
|
|
|
user = relationship("User")
|
|
|
|
|
|
class CallRecord(Base):
|
|
__tablename__ = "call_records"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
|
user_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"), index=True)
|
|
assistant_id: Mapped[Optional[str]] = mapped_column(String(64), ForeignKey("assistants.id"), index=True)
|
|
source: Mapped[str] = mapped_column(String(32), default="debug")
|
|
status: Mapped[str] = mapped_column(String(32), default="connected")
|
|
started_at: Mapped[str] = mapped_column(String(32), nullable=False)
|
|
ended_at: Mapped[Optional[str]] = mapped_column(String(32), nullable=True)
|
|
duration_seconds: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
|
summary: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
|
cost: Mapped[float] = mapped_column(Float, default=0.0)
|
|
call_metadata: Mapped[dict] = mapped_column(JSON, default=dict)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
|
|
user = relationship("User")
|
|
assistant = relationship("Assistant", back_populates="call_records")
|
|
transcripts = relationship("CallTranscript", back_populates="call_record")
|
|
audio_segments = relationship("CallAudioSegment", back_populates="call_record")
|
|
|
|
|
|
class CallTranscript(Base):
|
|
__tablename__ = "call_transcripts"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
|
|
call_id: Mapped[str] = mapped_column(String(64), ForeignKey("call_records.id"), index=True)
|
|
turn_index: Mapped[int] = mapped_column(Integer, nullable=False)
|
|
speaker: Mapped[str] = mapped_column(String(16), nullable=False) # human/ai
|
|
content: Mapped[str] = mapped_column(Text, nullable=False)
|
|
confidence: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
|
|
start_ms: Mapped[int] = mapped_column(Integer, nullable=False)
|
|
end_ms: Mapped[int] = mapped_column(Integer, nullable=False)
|
|
duration_ms: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
|
emotion: Mapped[Optional[str]] = mapped_column(String(32), nullable=True)
|
|
|
|
call_record = relationship("CallRecord", back_populates="transcripts")
|
|
|
|
|
|
class CallAudioSegment(Base):
|
|
__tablename__ = "call_audio_segments"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
|
|
call_id: Mapped[str] = mapped_column(String(64), ForeignKey("call_records.id"), index=True)
|
|
transcript_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("call_transcripts.id"), nullable=True)
|
|
turn_index: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
|
audio_url: Mapped[str] = mapped_column(String(512), nullable=False)
|
|
audio_format: Mapped[str] = mapped_column(String(16), default="mp3")
|
|
file_size_bytes: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
|
start_ms: Mapped[int] = mapped_column(Integer, nullable=False)
|
|
end_ms: Mapped[int] = mapped_column(Integer, nullable=False)
|
|
duration_ms: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
|
|
call_record = relationship("CallRecord", back_populates="audio_segments")
|