[split-required] Split remaining Python monoliths (Phase 1 continued)
klausur-service (7 monoliths): - grid_editor_helpers.py (1,737 → 5 files: columns, filters, headers, zones) - cv_cell_grid.py (1,675 → 7 files: build, legacy, streaming, merge, vocab) - worksheet_editor_api.py (1,305 → 4 files: models, AI, reconstruct, routes) - legal_corpus_ingestion.py (1,280 → 3 files: registry, chunking, ingestion) - cv_review.py (1,248 → 4 files: pipeline, spell, LLM, barrel) - cv_preprocessing.py (1,166 → 3 files: deskew, dewarp, barrel) - rbac.py, admin_api.py, routes/eh.py remain (next batch) backend-lehrer (1 monolith): - classroom_engine/repository.py (1,705 → 7 files by domain) All re-export barrels preserve backward compatibility. Zero import errors verified. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
133
klausur-service/backend/worksheet_editor_models.py
Normal file
133
klausur-service/backend/worksheet_editor_models.py
Normal file
@@ -0,0 +1,133 @@
|
||||
"""
|
||||
Worksheet Editor Models — Enums, Pydantic models, and configuration.
|
||||
"""
|
||||
|
||||
import os
|
||||
import logging
|
||||
from typing import Optional, List, Dict
|
||||
from enum import Enum
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# =============================================
|
||||
# CONFIGURATION
|
||||
# =============================================
|
||||
|
||||
OLLAMA_URL = os.getenv("OLLAMA_URL", "http://host.docker.internal:11434")
|
||||
SD_MODEL = os.getenv("SD_MODEL", "stable-diffusion") # or specific SD model
|
||||
WORKSHEET_STORAGE_DIR = os.getenv("WORKSHEET_STORAGE_DIR",
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), "worksheet-storage"))
|
||||
|
||||
# Ensure storage directory exists
|
||||
os.makedirs(WORKSHEET_STORAGE_DIR, exist_ok=True)
|
||||
|
||||
# =============================================
|
||||
# ENUMS & MODELS
|
||||
# =============================================
|
||||
|
||||
class AIImageStyle(str, Enum):
|
||||
REALISTIC = "realistic"
|
||||
CARTOON = "cartoon"
|
||||
SKETCH = "sketch"
|
||||
CLIPART = "clipart"
|
||||
EDUCATIONAL = "educational"
|
||||
|
||||
class WorksheetStatus(str, Enum):
|
||||
DRAFT = "draft"
|
||||
PUBLISHED = "published"
|
||||
ARCHIVED = "archived"
|
||||
|
||||
# Style prompt modifiers
|
||||
STYLE_PROMPTS = {
|
||||
AIImageStyle.REALISTIC: "photorealistic, high detail, professional photography",
|
||||
AIImageStyle.CARTOON: "cartoon style, colorful, child-friendly, simple shapes",
|
||||
AIImageStyle.SKETCH: "pencil sketch, hand-drawn, black and white, artistic",
|
||||
AIImageStyle.CLIPART: "clipart style, flat design, simple, vector-like",
|
||||
AIImageStyle.EDUCATIONAL: "educational illustration, clear, informative, textbook style"
|
||||
}
|
||||
|
||||
# =============================================
|
||||
# REQUEST/RESPONSE MODELS
|
||||
# =============================================
|
||||
|
||||
class AIImageRequest(BaseModel):
|
||||
prompt: str = Field(..., min_length=3, max_length=500)
|
||||
style: AIImageStyle = AIImageStyle.EDUCATIONAL
|
||||
width: int = Field(512, ge=256, le=1024)
|
||||
height: int = Field(512, ge=256, le=1024)
|
||||
|
||||
class AIImageResponse(BaseModel):
|
||||
image_base64: str
|
||||
prompt_used: str
|
||||
error: Optional[str] = None
|
||||
|
||||
class PageData(BaseModel):
|
||||
id: str
|
||||
index: int
|
||||
canvasJSON: str
|
||||
|
||||
class PageFormat(BaseModel):
|
||||
width: float = 210
|
||||
height: float = 297
|
||||
orientation: str = "portrait"
|
||||
margins: Dict[str, float] = {"top": 15, "right": 15, "bottom": 15, "left": 15}
|
||||
|
||||
class WorksheetSaveRequest(BaseModel):
|
||||
id: Optional[str] = None
|
||||
title: str
|
||||
description: Optional[str] = None
|
||||
pages: List[PageData]
|
||||
pageFormat: Optional[PageFormat] = None
|
||||
|
||||
class WorksheetResponse(BaseModel):
|
||||
id: str
|
||||
title: str
|
||||
description: Optional[str]
|
||||
pages: List[PageData]
|
||||
pageFormat: PageFormat
|
||||
createdAt: str
|
||||
updatedAt: str
|
||||
|
||||
class AIModifyRequest(BaseModel):
|
||||
prompt: str = Field(..., min_length=3, max_length=1000)
|
||||
canvas_json: str
|
||||
model: str = "qwen2.5vl:32b"
|
||||
|
||||
class AIModifyResponse(BaseModel):
|
||||
modified_canvas_json: Optional[str] = None
|
||||
message: str
|
||||
error: Optional[str] = None
|
||||
|
||||
class ReconstructRequest(BaseModel):
|
||||
session_id: str
|
||||
page_number: int = 1
|
||||
include_images: bool = True
|
||||
regenerate_graphics: bool = False
|
||||
|
||||
class ReconstructResponse(BaseModel):
|
||||
canvas_json: str
|
||||
page_width: int
|
||||
page_height: int
|
||||
elements_count: int
|
||||
vocabulary_matched: int
|
||||
message: str
|
||||
error: Optional[str] = None
|
||||
|
||||
# =============================================
|
||||
# IN-MEMORY STORAGE (Development)
|
||||
# =============================================
|
||||
|
||||
worksheets_db: Dict[str, Dict] = {}
|
||||
|
||||
# PDF Generation availability
|
||||
try:
|
||||
from reportlab.lib import colors # noqa: F401
|
||||
from reportlab.lib.pagesizes import A4 # noqa: F401
|
||||
from reportlab.lib.units import mm # noqa: F401
|
||||
from reportlab.pdfgen import canvas # noqa: F401
|
||||
from reportlab.lib.styles import getSampleStyleSheet # noqa: F401
|
||||
REPORTLAB_AVAILABLE = True
|
||||
except ImportError:
|
||||
REPORTLAB_AVAILABLE = False
|
||||
Reference in New Issue
Block a user