Files
breakpilot-lehrer/klausur-service/backend/worksheet_editor_models.py
Benjamin Admin b2a0126f14 [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>
2026-04-24 22:47:59 +02:00

134 lines
3.8 KiB
Python

"""
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