opencode/backend/app/schemas.py
Кирилл Блинов f37c477a0a Add FastAPI backend with DZI viewer and feedback system
- 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
2026-06-01 12:29:41 +03:00

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