Python (6 files in klausur-service): - rbac.py (1,132 → 4), admin_api.py (1,012 → 4) - routes/eh.py (1,111 → 4), ocr_pipeline_geometry.py (1,105 → 5) Python (2 files in backend-lehrer): - unit_api.py (1,226 → 6), game_api.py (1,129 → 5) Website (6 page files): - 4x klausur-korrektur pages (1,249-1,328 LOC each) → shared components in website/components/klausur-korrektur/ (17 shared files) - companion (1,057 → 10), magic-help (1,017 → 8) All re-export barrels preserve backward compatibility. Zero import errors verified. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
144 lines
9.0 KiB
TypeScript
144 lines
9.0 KiB
TypeScript
'use client'
|
|
|
|
const ARCHITECTURE_DIAGRAM = `┌─────────────────────────────────────────────────────────────────────────────┐
|
|
│ MAGIC HELP ARCHITEKTUR │
|
|
├─────────────────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌───────────────┐ ┌──────────────────┐ ┌───────────────┐ │
|
|
│ │ FRONTEND │ │ BACKEND │ │ STORAGE │ │
|
|
│ │ (Next.js) │ │ (FastAPI) │ │ │ │
|
|
│ │ │ │ │ │ │ │
|
|
│ │ ┌─────────┐ │ REST │ ┌────────────┐ │ │ ┌─────────┐ │ │
|
|
│ │ │ Admin │──┼─────────┼──│ TrOCR │ │ │ │ Models │ │ │
|
|
│ │ │ Panel │ │ │ │ Service │──┼─────────┼──│ (ONNX) │ │ │
|
|
│ │ └─────────┘ │ │ └────────────┘ │ │ └─────────┘ │ │
|
|
│ │ │ │ │ │ │ │ │
|
|
│ │ ┌─────────┐ │ WebSocket│ ┌────────────┐ │ │ ┌─────────┐ │ │
|
|
│ │ │ Lehrer │──┼─────────┼──│ Klausur │ │ │ │ LoRA │ │ │
|
|
│ │ │ Portal │ │ │ │ Processor │──┼─────────┼──│ Adapter │ │ │
|
|
│ │ └─────────┘ │ │ └────────────┘ │ │ └─────────┘ │ │
|
|
│ │ │ │ │ │ │ │ │
|
|
│ └───────────────┘ │ ┌────────────┐ │ │ ┌─────────┐ │ │
|
|
│ │ │ Pseudo- │ │ │ │Training │ │ │
|
|
│ │ │ nymizer │──┼─────────┼──│ Data │ │ │
|
|
│ │ └────────────┘ │ │ └─────────┘ │ │
|
|
│ │ │ │ │ │
|
|
│ └──────────────────┘ └───────────────┘ │
|
|
│ │ │
|
|
│ │ (nur pseudonymisiert) │
|
|
│ ▼ │
|
|
│ ┌──────────────────┐ │
|
|
│ │ CLOUD LLM │ │
|
|
│ │ (SysEleven) │ │
|
|
│ │ Namespace- │ │
|
|
│ │ Isolation │ │
|
|
│ └──────────────────┘ │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────────────────┘`
|
|
|
|
const COMPONENTS = [
|
|
{
|
|
icon: '🔍',
|
|
title: 'TrOCR Service',
|
|
details: [
|
|
{ label: 'Modell', value: 'microsoft/trocr-base-handwritten' },
|
|
{ label: 'Größe', value: '~350 MB' },
|
|
{ label: 'Lizenz', value: 'MIT' },
|
|
{ label: 'Framework', value: 'PyTorch / Transformers' },
|
|
],
|
|
description: 'Das TrOCR-Modell von Microsoft ist speziell für Handschrifterkennung trainiert. Es verwendet eine Vision-Transformer (ViT) Architektur für Bildverarbeitung und einen Text-Decoder für die Textgenerierung.',
|
|
},
|
|
{
|
|
icon: '🎯',
|
|
title: 'LoRA Fine-Tuning',
|
|
details: [
|
|
{ label: 'Methode', value: 'Low-Rank Adaptation' },
|
|
{ label: 'Adapter-Größe', value: '~10 MB' },
|
|
{ label: 'Trainingszeit', value: '5-15 Min (CPU)' },
|
|
{ label: 'Min. Beispiele', value: '10' },
|
|
],
|
|
description: 'LoRA fügt kleine, trainierbare Matrizen zu bestimmten Schichten hinzu, ohne das Basismodell zu verändern. Dies ermöglicht effizientes Fine-Tuning mit minimaler Speichernutzung.',
|
|
},
|
|
{
|
|
icon: '🔒',
|
|
title: 'Pseudonymisierung',
|
|
details: [
|
|
{ label: 'Methode', value: 'QR-Code Tokens' },
|
|
{ label: 'Token-Format', value: 'UUID v4' },
|
|
{ label: 'Mapping', value: 'Lokal beim Lehrer' },
|
|
{ label: 'Cloud-Daten', value: 'Nur Tokens + Text' },
|
|
],
|
|
description: 'Schülernamen werden durch anonyme Tokens ersetzt, bevor Daten die lokale Umgebung verlassen. Das Mapping wird ausschließlich lokal gespeichert.',
|
|
},
|
|
{
|
|
icon: '☁️',
|
|
title: 'Cloud LLM',
|
|
details: [
|
|
{ label: 'Provider', value: 'SysEleven (DE)' },
|
|
{ label: 'Standort', value: 'Deutschland' },
|
|
{ label: 'Isolation', value: 'Namespace pro Schule' },
|
|
{ label: 'Datenverarbeitung', value: 'Nur pseudonymisiert' },
|
|
],
|
|
description: 'Die KI-Korrektur erfolgt auf deutschen Servern mit strikter Mandantentrennung. Es werden keine Klarnamen oder identifizierenden Informationen übertragen.',
|
|
},
|
|
]
|
|
|
|
const DATA_FLOW_STEPS = [
|
|
{ color: 'blue', num: 1, title: 'Lokale Header-Extraktion', desc: 'TrOCR erkennt Schülernamen, Klasse und Fach direkt im Browser/PWA (offline-fähig)' },
|
|
{ color: 'purple', num: 2, title: 'Pseudonymisierung', desc: 'Namen werden durch QR-Code Tokens ersetzt, Mapping bleibt lokal' },
|
|
{ color: 'green', num: 3, title: 'Cloud-Korrektur', desc: 'Nur pseudonymisierte Dokument-Tokens werden an die KI gesendet' },
|
|
{ color: 'yellow', num: 4, title: 'Re-Identifikation', desc: 'Ergebnisse werden lokal mit dem Mapping wieder den echten Namen zugeordnet' },
|
|
]
|
|
|
|
export default function ArchitectureTab() {
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Architecture Diagram */}
|
|
<div className="bg-gray-800/50 border border-gray-700 rounded-xl p-6">
|
|
<h2 className="text-lg font-semibold text-white mb-6">Systemarchitektur</h2>
|
|
<div className="bg-gray-900 rounded-lg p-6 font-mono text-xs overflow-x-auto">
|
|
<pre className="text-gray-300">{ARCHITECTURE_DIAGRAM}</pre>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Components */}
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
{COMPONENTS.map(comp => (
|
|
<div key={comp.title} className="bg-gray-800/50 border border-gray-700 rounded-xl p-6">
|
|
<h3 className="text-lg font-semibold text-white mb-4 flex items-center gap-2">
|
|
<span>{comp.icon}</span> {comp.title}
|
|
</h3>
|
|
<div className="space-y-3 text-sm">
|
|
{comp.details.map(d => (
|
|
<div key={d.label} className="flex justify-between">
|
|
<span className="text-gray-400">{d.label}</span>
|
|
<span className="text-white">{d.value}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
<p className="text-gray-400 text-sm mt-4">{comp.description}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Data Flow */}
|
|
<div className="bg-gray-800/50 border border-gray-700 rounded-xl p-6">
|
|
<h2 className="text-lg font-semibold text-white mb-4">Datenfluss</h2>
|
|
<div className="space-y-4">
|
|
{DATA_FLOW_STEPS.map(step => (
|
|
<div key={step.num} className="flex items-start gap-4 bg-gray-900/50 rounded-lg p-4">
|
|
<div className={`w-8 h-8 rounded-full bg-${step.color}-500/20 flex items-center justify-center text-${step.color}-400 font-bold`}>
|
|
{step.num}
|
|
</div>
|
|
<div>
|
|
<div className="font-medium text-white">{step.title}</div>
|
|
<div className="text-sm text-gray-400">{step.desc}</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|