- FastAPI app with SQLite DB (projects, pages, issues, feedback) - OpenSeadragon DZI viewer with inline SVG overlays - Dashboard: upload, project list, tiling toggle, review mode - Pipeline integration: tiling OCR → layout → elements → rules QC → DZI → DB - Feedback collection: true_positive / false_positive / not_sure per issue
138 lines
3.7 KiB
Python
138 lines
3.7 KiB
Python
# app/schemas.py
|
|
from pydantic import BaseModel
|
|
from typing import List, Optional, Dict, Any
|
|
from datetime import datetime
|
|
|
|
|
|
# ---------- Project ----------
|
|
class ProjectBase(BaseModel):
|
|
name: Optional[str] = None
|
|
|
|
class ProjectCreate(ProjectBase):
|
|
pdf_filename: str
|
|
|
|
class ProjectResponse(ProjectBase):
|
|
id: int
|
|
pdf_filename: str
|
|
status: str
|
|
created_at: datetime
|
|
completed_at: Optional[datetime] = None
|
|
error_message: Optional[str] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class ProjectDetail(ProjectResponse):
|
|
pages: List["PageResponse"] = []
|
|
issues: List["IssueResponse"] = []
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ---------- Page ----------
|
|
class PageBase(BaseModel):
|
|
page_number: int
|
|
width: Optional[int] = None
|
|
height: Optional[int] = None
|
|
|
|
class PageResponse(PageBase):
|
|
id: int
|
|
png_path: Optional[str] = None
|
|
vlm_description: Optional[str] = None
|
|
ocr_data: Optional[Dict[str, Any]] = None
|
|
issue_count: int = 0
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ---------- Issue ----------
|
|
class IssueBase(BaseModel):
|
|
issue_type: str
|
|
severity: str
|
|
message: str
|
|
page_number: Optional[int] = None
|
|
|
|
class IssueCreate(IssueBase):
|
|
bbox_x1: Optional[float] = None
|
|
bbox_y1: Optional[float] = None
|
|
bbox_x2: Optional[float] = None
|
|
bbox_y2: Optional[float] = None
|
|
dimension_text: Optional[str] = None
|
|
confidence: Optional[float] = None
|
|
extra_data: Optional[Dict[str, Any]] = None
|
|
|
|
class IssueResponse(IssueBase):
|
|
id: int
|
|
project_id: int
|
|
bbox_x1: Optional[float] = None
|
|
bbox_y1: Optional[float] = None
|
|
bbox_x2: Optional[float] = None
|
|
bbox_y2: Optional[float] = None
|
|
dimension_text: Optional[str] = None
|
|
confidence: Optional[float] = None
|
|
source: Optional[str] = None
|
|
created_at: datetime
|
|
feedback: Optional["FeedbackResponse"] = None
|
|
page_id: Optional[int] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ---------- Feedback ----------
|
|
class FeedbackCreate(BaseModel):
|
|
issue_id: int
|
|
is_true_positive: Optional[bool] = None
|
|
comment: Optional[str] = None
|
|
action_taken: Optional[str] = None # fixed / ignored / not_sure
|
|
|
|
class FeedbackResponse(BaseModel):
|
|
id: int
|
|
issue_id: int
|
|
is_true_positive: Optional[bool] = None
|
|
comment: Optional[str] = None
|
|
action_taken: Optional[str] = None
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ---------- Stats ----------
|
|
class StatsResponse(BaseModel):
|
|
total_projects: int
|
|
total_issues: int
|
|
issues_by_type: Dict[str, int]
|
|
feedback_stats: Dict[str, int] # true_positive, false_positive, unreviewed
|
|
accuracy_estimate: Optional[float] = None # Доля правильных срабатываний
|
|
|
|
|
|
# ---------- Training Data ----------
|
|
class TrainingSample(BaseModel):
|
|
"""Один пример для обучения ML-модели."""
|
|
issue_id: int
|
|
issue_type: str
|
|
severity: str
|
|
message: str
|
|
bbox: Dict[str, float] # x1, y1, x2, y2
|
|
dimension_text: Optional[str] = None
|
|
confidence: Optional[float] = None
|
|
page_number: int
|
|
is_true_positive: Optional[bool] = None
|
|
|
|
# Для обучения детектора (YOLO)
|
|
image_path: Optional[str] = None # Путь к PNG страницы
|
|
crop_path: Optional[str] = None # Вырезанный фрагмент bbox
|
|
label: Optional[str] = None # "good_dimension" / "bad_placement" / etc.
|
|
|
|
class TrainingDataExport(BaseModel):
|
|
total_samples: int
|
|
labeled_samples: int # Есть is_true_positive
|
|
samples: List[TrainingSample]
|
|
export_format: str # json / yolo / csv
|
|
|
|
class Config:
|
|
from_attributes = True
|