generated from john/python-template
82 lines
2.8 KiB
Python
82 lines
2.8 KiB
Python
"""SQLModel domain models for the transcription system.
|
|
|
|
Three models capture the MVP lifecycle:
|
|
Document -> one-to-many -> Job -> one-to-many -> Transcript
|
|
"""
|
|
|
|
from datetime import UTC
|
|
from datetime import datetime
|
|
from enum import StrEnum
|
|
from uuid import UUID
|
|
from uuid import uuid4
|
|
|
|
from sqlalchemy import UniqueConstraint
|
|
from sqlmodel import Field
|
|
from sqlmodel import Relationship
|
|
from sqlmodel import SQLModel
|
|
|
|
|
|
class JobStatus(StrEnum):
|
|
QUEUED = "queued"
|
|
PROCESSING = "processing"
|
|
TRANSCRIBED = "transcribed"
|
|
FAILED = "failed"
|
|
|
|
|
|
class Document(SQLModel, table=True):
|
|
"""An uploaded document image."""
|
|
|
|
id: UUID = Field(default_factory=uuid4, primary_key=True)
|
|
filename: str
|
|
file_path: str
|
|
uploaded_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
|
|
|
|
# --- relationships ---
|
|
jobs: list["Job"] = Relationship(back_populates="document")
|
|
|
|
|
|
class Job(SQLModel, table=True):
|
|
"""A transcription job tied to a single document."""
|
|
|
|
id: UUID = Field(default_factory=uuid4, primary_key=True)
|
|
document_id: UUID = Field(foreign_key="document.id")
|
|
status: JobStatus = Field(default=JobStatus.QUEUED)
|
|
retry_count: int = Field(default=0, ge=0)
|
|
created_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
|
|
updated_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
|
|
|
|
# --- relationships ---
|
|
document: Document = Relationship(back_populates="jobs")
|
|
transcripts: list["Transcript"] = Relationship(back_populates="job")
|
|
|
|
@property
|
|
def filename(self) -> str:
|
|
"""Return the filename of the associated document."""
|
|
return self.document.filename if self.document else "unknown"
|
|
|
|
|
|
class Transcript(SQLModel, table=True):
|
|
"""The output of a transcription job."""
|
|
|
|
id: UUID = Field(default_factory=uuid4, primary_key=True)
|
|
job_id: UUID = Field(foreign_key="job.id")
|
|
"""ID for the associated job."""
|
|
revision: int = Field(default=0, ge=0)
|
|
"""Revision number for this job's transcript history, starting at 0."""
|
|
provider: str
|
|
"""Name of the transcription provider used to generate this transcript."""
|
|
model: str
|
|
"""Model identifier used to generate this transcript revision."""
|
|
prompt_name: str
|
|
"""Name of the prompt used to generate this transcript."""
|
|
text: str | None = None
|
|
"""The transcribed text. This may be None if the job failed or is still in progress."""
|
|
error_detail: str | None = None
|
|
"""Details of any error that occurred during transcription."""
|
|
created_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
|
|
|
|
__table_args__ = (UniqueConstraint("job_id", "revision", name="uq_transcript_job_revision"),)
|
|
|
|
# --- relationships ---
|
|
job: Job = Relationship(back_populates="transcripts")
|