Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 28s
CI / test-go-edu-search (push) Successful in 28s
CI / test-python-klausur (push) Failing after 2m22s
CI / test-python-agent-core (push) Successful in 21s
CI / test-nodejs-website (push) Successful in 23s
korrektur/ zeugnis/ admin/ compliance/ worksheet/ training/ metrics/ 52 shims, relative imports, RAG untouched. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
134 lines
3.8 KiB
Python
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
|