All checks were successful
CI / test-bqas (push) Successful in 32s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 46s
CI / test-python-voice (push) Successful in 38s
- Install Gitleaks, Trivy, Grype, Syft, Semgrep, Bandit in backend-core Dockerfile - Add Woodpecker SQLite proxy API (fallback without API token) - Mount woodpecker_data volume read-only to backend-core - Add backend proxy fallback in admin-core Woodpecker route - Add Vault file-based persistent storage (config.hcl, init-vault.sh) - Auto-init, unseal and root-token persistence for Vault - Add 6 pitch-deck annex slides (Assumptions, Architecture, GTM, Regulatory, Engineering, AI Pipeline) - Dynamic margin/amortization KPIs in BusinessModelSlide - Market sources modal with citations in MarketSlide - Redesign nginx landing page to 3-column layout (Lehrer/Compliance/Core) - Extend MkDocs nav with Services and SDK documentation sections - Add SDK Protection architecture doc Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
330 lines
17 KiB
TypeScript
330 lines
17 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { Language } from '@/lib/types'
|
|
import { t } from '@/lib/i18n'
|
|
import GradientText from '../ui/GradientText'
|
|
import FadeInView from '../ui/FadeInView'
|
|
import GlassCard from '../ui/GlassCard'
|
|
import {
|
|
Brain,
|
|
Search,
|
|
Database,
|
|
FileText,
|
|
Bot,
|
|
Zap,
|
|
Layers,
|
|
ArrowRight,
|
|
Activity,
|
|
Shield,
|
|
Cpu,
|
|
MessageSquare,
|
|
Eye,
|
|
Gauge,
|
|
Network,
|
|
Sparkles,
|
|
} from 'lucide-react'
|
|
|
|
interface AIPipelineSlideProps {
|
|
lang: Language
|
|
}
|
|
|
|
type PipelineTab = 'rag' | 'agents' | 'quality'
|
|
|
|
export default function AIPipelineSlide({ lang }: AIPipelineSlideProps) {
|
|
const i = t(lang)
|
|
const de = lang === 'de'
|
|
const [activeTab, setActiveTab] = useState<PipelineTab>('rag')
|
|
|
|
const heroStats = [
|
|
{ value: '19', label: de ? 'Indexierte Verordnungen' : 'Indexed Regulations', sub: 'DSGVO · AI Act · NIS2 · CRA · ePrivacy · ...', color: 'text-indigo-400' },
|
|
{ value: '7', label: de ? 'Autonome Agenten' : 'Autonomous Agents', sub: de ? 'SOUL-basiert · Orchestriert' : 'SOUL-based · Orchestrated', color: 'text-purple-400' },
|
|
{ value: '5', label: de ? 'KI-Modelle lokal' : 'Local AI Models', sub: 'Llama 3.2 · Qwen 2.5 · BGE-M3 · TrOCR · CrossEncoder', color: 'text-emerald-400' },
|
|
{ value: '97', label: de ? 'Golden-Suite Tests' : 'Golden Suite Tests', sub: de ? 'Automatische Qualitaetssicherung' : 'Automatic Quality Assurance', color: 'text-amber-400' },
|
|
]
|
|
|
|
const tabs: { id: PipelineTab; label: string; icon: typeof Brain }[] = [
|
|
{ id: 'rag', label: de ? 'RAG-Pipeline' : 'RAG Pipeline', icon: Search },
|
|
{ id: 'agents', label: de ? 'Multi-Agent-System' : 'Multi-Agent System', icon: Bot },
|
|
{ id: 'quality', label: de ? 'Qualitaetssicherung' : 'Quality Assurance', icon: Gauge },
|
|
]
|
|
|
|
// RAG Pipeline content
|
|
const ragPipelineSteps = [
|
|
{
|
|
icon: FileText,
|
|
color: 'text-blue-400',
|
|
bg: 'bg-blue-500/10 border-blue-500/20',
|
|
title: de ? '1. Ingestion' : '1. Ingestion',
|
|
items: de
|
|
? ['PDF-Upload, URL-Crawling, API-Import', 'Automatische Spracherkennung (DE/EN)', 'Semantisches Chunking (rekursiv, 512 Tokens)', 'Metadaten-Extraktion (Verordnung, Artikel, Absatz)']
|
|
: ['PDF upload, URL crawling, API import', 'Automatic language detection (DE/EN)', 'Semantic chunking (recursive, 512 tokens)', 'Metadata extraction (regulation, article, paragraph)'],
|
|
},
|
|
{
|
|
icon: Cpu,
|
|
color: 'text-purple-400',
|
|
bg: 'bg-purple-500/10 border-purple-500/20',
|
|
title: de ? '2. Embedding' : '2. Embedding',
|
|
items: de
|
|
? ['BGE-M3 Multilingual Embeddings (lokal)', 'CrossEncoder Re-Ranking (lokal)', 'HyDE: Hypothetical Document Embeddings', 'Lazy Model Loading (Speicher-optimiert)']
|
|
: ['BGE-M3 multilingual embeddings (local)', 'CrossEncoder re-ranking (local)', 'HyDE: Hypothetical Document Embeddings', 'Lazy model loading (memory-optimized)'],
|
|
},
|
|
{
|
|
icon: Database,
|
|
color: 'text-emerald-400',
|
|
bg: 'bg-emerald-500/10 border-emerald-500/20',
|
|
title: de ? '3. Vektorspeicher' : '3. Vector Store',
|
|
items: de
|
|
? ['Qdrant Vector DB (Self-hosted)', '5 Collections: Legal Corpus, DSFA, Compliance, Dokumente, Agenten-Wissen', 'MinIO Object Storage fuer Quelldokumente', 'Automatische Re-Indexierung bei Updates']
|
|
: ['Qdrant Vector DB (self-hosted)', '5 Collections: Legal Corpus, DSFA, Compliance, Documents, Agent Knowledge', 'MinIO object storage for source documents', 'Automatic re-indexing on updates'],
|
|
},
|
|
{
|
|
icon: Search,
|
|
color: 'text-indigo-400',
|
|
bg: 'bg-indigo-500/10 border-indigo-500/20',
|
|
title: de ? '4. Hybrid Search' : '4. Hybrid Search',
|
|
items: de
|
|
? ['Dense Retrieval (70%) + BM25 Keyword (30%)', 'Deutsche Komposita-Zerlegung', 'Cross-Encoder Re-Ranking der Top-K Ergebnisse', 'Quellen-Attribution mit Artikel-Referenz']
|
|
: ['Dense retrieval (70%) + BM25 keyword (30%)', 'German compound word decomposition', 'Cross-encoder re-ranking of top-K results', 'Source attribution with article reference'],
|
|
},
|
|
]
|
|
|
|
// Multi-Agent System content
|
|
const agents = [
|
|
{ name: de ? 'Compliance-Berater' : 'Compliance Advisor', soul: 'compliance-advisor.soul.md', desc: de ? 'Beantwortet Compliance-Fragen mit RAG-Kontext' : 'Answers compliance questions with RAG context', color: 'text-indigo-400' },
|
|
{ name: de ? 'Audit-Agent' : 'Audit Agent', soul: 'quality-judge.soul.md', desc: de ? 'Prueft Dokumente gegen regulatorische Anforderungen' : 'Checks documents against regulatory requirements', color: 'text-emerald-400' },
|
|
{ name: de ? 'Dokument-Agent' : 'Drafting Agent', soul: 'drafting-agent.soul.md', desc: de ? 'Erstellt Compliance-Dokumente und Policies' : 'Creates compliance documents and policies', color: 'text-purple-400' },
|
|
{ name: 'Orchestrator', soul: 'orchestrator.soul.md', desc: de ? 'Task-Routing und Koordination aller Agenten' : 'Task routing and coordination of all agents', color: 'text-amber-400' },
|
|
{ name: de ? 'Alert-Agent' : 'Alert Agent', soul: 'alert-agent.soul.md', desc: de ? 'Monitoring, Fristen und Benachrichtigungen' : 'Monitoring, deadlines and notifications', color: 'text-red-400' },
|
|
{ name: de ? 'Tutor-Agent' : 'Tutor Agent', soul: 'tutor-agent.soul.md', desc: de ? 'Interaktive Compliance-Schulungen' : 'Interactive compliance training', color: 'text-blue-400' },
|
|
]
|
|
|
|
const agentInfra = [
|
|
{ icon: MessageSquare, label: 'SOUL Files', desc: de ? 'Deklarative Agenten-Persoenlichkeit in Markdown' : 'Declarative agent personality in Markdown' },
|
|
{ icon: Brain, label: 'Shared Brain', desc: de ? 'Gemeinsamer Wissensspeicher + Langzeitgedaechtnis' : 'Shared knowledge store + long-term memory' },
|
|
{ icon: Network, label: 'Message Bus', desc: de ? 'Valkey/Redis · Pub/Sub · Task Queue' : 'Valkey/Redis · Pub/Sub · Task Queue' },
|
|
{ icon: Activity, label: 'Session Manager', desc: de ? 'Heartbeat · Checkpoints · Recovery' : 'Heartbeat · Checkpoints · Recovery' },
|
|
]
|
|
|
|
// Quality Assurance content
|
|
const qaFeatures = [
|
|
{
|
|
icon: Shield,
|
|
color: 'text-emerald-400',
|
|
title: de ? 'BQAS — Quality Assurance System' : 'BQAS — Quality Assurance System',
|
|
items: de
|
|
? ['97 Golden-Suite-Referenztests fuer Regressionserkennung', 'Synthetische Testgenerierung per LLM', 'RAG-Retrieval-Accuracy und Correction-Tests', 'Precision, Recall, F1 Tracking ueber alle Releases']
|
|
: ['97 golden suite reference tests for regression detection', 'Synthetic test generation via LLM', 'RAG retrieval accuracy and correction tests', 'Precision, recall, F1 tracking across all releases'],
|
|
},
|
|
{
|
|
icon: Eye,
|
|
color: 'text-indigo-400',
|
|
title: de ? 'LLM Evaluation & Vergleich' : 'LLM Evaluation & Comparison',
|
|
items: de
|
|
? ['Side-by-Side-Vergleich: Ollama lokal vs. OpenAI vs. Claude', 'Latenz-, Token- und Qualitaets-Metriken pro Provider', 'Automatischer Fallback bei Provider-Ausfall', 'Self-RAG: Selbstreflektierende Antwortvalidierung']
|
|
: ['Side-by-side comparison: Ollama local vs. OpenAI vs. Claude', 'Latency, token and quality metrics per provider', 'Automatic fallback on provider failure', 'Self-RAG: Self-reflective answer validation'],
|
|
},
|
|
{
|
|
icon: Sparkles,
|
|
color: 'text-purple-400',
|
|
title: de ? 'Document Intelligence' : 'Document Intelligence',
|
|
items: de
|
|
? ['TrOCR Handschrifterkennung mit LoRA Fine-Tuning', 'Multi-OCR-Pipeline: 5 Methoden parallel (Vision LLM, Tesseract, OpenCV, ...)', 'Labeling-Interface fuer Trainingsdaten-Erstellung (DSGVO-konform, lokal)', 'OpenCV Document Reconstruction (Deskew, Dewarp, Binarisierung)']
|
|
: ['TrOCR handwriting recognition with LoRA fine-tuning', 'Multi-OCR pipeline: 5 methods in parallel (Vision LLM, Tesseract, OpenCV, ...)', 'Labeling interface for training data creation (GDPR-compliant, local)', 'OpenCV document reconstruction (deskew, dewarp, binarization)'],
|
|
},
|
|
{
|
|
icon: Zap,
|
|
color: 'text-amber-400',
|
|
title: de ? 'GPU & Training' : 'GPU & Training',
|
|
items: de
|
|
? ['Lokales Training auf Apple Silicon (M4 Max, 64 GB unified)', 'vast.ai Integration fuer Cloud-GPU bei Bedarf', 'LoRA/QLoRA Fine-Tuning mit konfigurierbaren Hyperparametern', 'SSE-Streaming fuer Echtzeit-Trainingsmetriken (Loss, Accuracy, F1)']
|
|
: ['Local training on Apple Silicon (M4 Max, 64 GB unified)', 'vast.ai integration for cloud GPU on demand', 'LoRA/QLoRA fine-tuning with configurable hyperparameters', 'SSE streaming for real-time training metrics (loss, accuracy, F1)'],
|
|
},
|
|
]
|
|
|
|
return (
|
|
<div>
|
|
<FadeInView className="text-center mb-5">
|
|
<p className="text-xs font-mono text-indigo-400/60 uppercase tracking-widest mb-2">
|
|
{de ? 'Anhang' : 'Appendix'}
|
|
</p>
|
|
<h2 className="text-4xl md:text-5xl font-bold mb-2">
|
|
<GradientText>{i.annex.aipipeline.title}</GradientText>
|
|
</h2>
|
|
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.annex.aipipeline.subtitle}</p>
|
|
</FadeInView>
|
|
|
|
{/* Hero Stats */}
|
|
<FadeInView delay={0.1}>
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-2 mb-4">
|
|
{heroStats.map((stat, idx) => (
|
|
<div key={idx} className="border border-white/[0.08] rounded-xl p-2.5 bg-white/[0.03] text-center">
|
|
<p className={`text-2xl font-black tracking-tight ${stat.color}`}>{stat.value}</p>
|
|
<p className="text-[11px] font-semibold text-white/70">{stat.label}</p>
|
|
<p className="text-[9px] text-white/30 mt-0.5 leading-tight">{stat.sub}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</FadeInView>
|
|
|
|
{/* Tab Navigation */}
|
|
<FadeInView delay={0.15}>
|
|
<div className="flex items-center justify-center gap-2 mb-4">
|
|
{tabs.map((tab) => {
|
|
const Icon = tab.icon
|
|
return (
|
|
<button
|
|
key={tab.id}
|
|
onClick={() => setActiveTab(tab.id)}
|
|
className={`flex items-center gap-2 px-4 py-2 rounded-xl text-sm transition-all
|
|
${activeTab === tab.id
|
|
? 'bg-indigo-500/20 text-indigo-300 border border-indigo-500/30'
|
|
: 'bg-white/[0.04] text-white/40 border border-transparent hover:text-white/60 hover:bg-white/[0.06]'
|
|
}`}
|
|
>
|
|
<Icon className="w-4 h-4" />
|
|
{tab.label}
|
|
</button>
|
|
)
|
|
})}
|
|
</div>
|
|
</FadeInView>
|
|
|
|
{/* Tab Content */}
|
|
<FadeInView delay={0.2} key={activeTab}>
|
|
{activeTab === 'rag' && (
|
|
<div>
|
|
{/* Pipeline Flow Visualization */}
|
|
<div className="flex items-center justify-center gap-1 mb-4 flex-wrap">
|
|
{[
|
|
{ icon: FileText, label: de ? 'Dokumente' : 'Documents' },
|
|
{ icon: Layers, label: 'Chunking' },
|
|
{ icon: Cpu, label: 'BGE-M3' },
|
|
{ icon: Database, label: 'Qdrant' },
|
|
{ icon: Search, label: 'Hybrid Search' },
|
|
{ icon: Brain, label: 'LLM' },
|
|
].map((step, idx, arr) => (
|
|
<div key={idx} className="flex items-center gap-1">
|
|
<div className="flex items-center gap-1 px-2 py-1 rounded-lg bg-white/[0.05] border border-white/[0.08]">
|
|
<step.icon className="w-3 h-3 text-indigo-400" />
|
|
<span className="text-[10px] text-white/50">{step.label}</span>
|
|
</div>
|
|
{idx < arr.length - 1 && <ArrowRight className="w-3 h-3 text-white/20" />}
|
|
</div>
|
|
))}
|
|
</div>
|
|
{/* Pipeline Steps */}
|
|
<div className="grid md:grid-cols-2 gap-3">
|
|
{ragPipelineSteps.map((step, idx) => {
|
|
const Icon = step.icon
|
|
return (
|
|
<div key={idx} className={`border rounded-xl p-3 ${step.bg}`}>
|
|
<div className="flex items-center gap-2 mb-2">
|
|
<Icon className={`w-4 h-4 ${step.color}`} />
|
|
<h3 className="text-xs font-bold text-white">{step.title}</h3>
|
|
</div>
|
|
<ul className="space-y-1">
|
|
{step.items.map((item, iidx) => (
|
|
<li key={iidx} className="flex items-start gap-1.5 text-[11px] text-white/50">
|
|
<span className={`w-1 h-1 rounded-full mt-1.5 ${step.color} bg-current shrink-0`} />
|
|
{item}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'agents' && (
|
|
<div className="grid md:grid-cols-12 gap-4">
|
|
{/* Agent List */}
|
|
<div className="md:col-span-7">
|
|
<GlassCard hover={false} className="p-4">
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Bot className="w-4 h-4 text-white/40" />
|
|
<p className="text-xs font-semibold text-white/40 uppercase tracking-wider">
|
|
{de ? 'Agenten-Fleet' : 'Agent Fleet'}
|
|
</p>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-2">
|
|
{agents.map((agent, idx) => (
|
|
<div key={idx} className="p-2 rounded-lg bg-white/[0.03] border border-white/5">
|
|
<div className="flex items-center gap-1.5 mb-1">
|
|
<div className={`w-1.5 h-1.5 rounded-full ${agent.color} bg-current`} />
|
|
<p className="text-xs font-bold text-white/80">{agent.name}</p>
|
|
</div>
|
|
<p className="text-[10px] text-white/40 leading-tight">{agent.desc}</p>
|
|
<p className="text-[9px] font-mono text-white/20 mt-1">{agent.soul}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</GlassCard>
|
|
</div>
|
|
{/* Agent Infrastructure */}
|
|
<div className="md:col-span-5">
|
|
<GlassCard hover={false} className="p-4 h-full">
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Network className="w-4 h-4 text-white/40" />
|
|
<p className="text-xs font-semibold text-white/40 uppercase tracking-wider">
|
|
{de ? 'Infrastruktur' : 'Infrastructure'}
|
|
</p>
|
|
</div>
|
|
<div className="space-y-2.5">
|
|
{agentInfra.map((inf, idx) => {
|
|
const Icon = inf.icon
|
|
return (
|
|
<div key={idx} className="flex items-start gap-2.5">
|
|
<div className="w-7 h-7 rounded-lg bg-purple-500/10 border border-purple-500/20 flex items-center justify-center shrink-0">
|
|
<Icon className="w-3.5 h-3.5 text-purple-400" />
|
|
</div>
|
|
<div>
|
|
<p className="text-xs font-semibold text-white/70">{inf.label}</p>
|
|
<p className="text-[10px] text-white/40">{inf.desc}</p>
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
<div className="mt-3 pt-3 border-t border-white/5">
|
|
<p className="text-[10px] text-white/20">
|
|
{de
|
|
? 'Alle Agenten laufen lokal · Kein API-Schluessel erforderlich · DSGVO-konform'
|
|
: 'All agents run locally · No API key required · GDPR-compliant'}
|
|
</p>
|
|
</div>
|
|
</GlassCard>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'quality' && (
|
|
<div className="grid md:grid-cols-2 gap-3">
|
|
{qaFeatures.map((feat, idx) => {
|
|
const Icon = feat.icon
|
|
return (
|
|
<GlassCard key={idx} hover={false} className="p-3">
|
|
<div className="flex items-center gap-2 mb-2">
|
|
<Icon className={`w-4 h-4 ${feat.color}`} />
|
|
<h3 className="text-xs font-bold text-white">{feat.title}</h3>
|
|
</div>
|
|
<ul className="space-y-1">
|
|
{feat.items.map((item, iidx) => (
|
|
<li key={iidx} className="flex items-start gap-1.5 text-[11px] text-white/50">
|
|
<span className={`w-1 h-1 rounded-full mt-1.5 ${feat.color} bg-current shrink-0`} />
|
|
{item}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</GlassCard>
|
|
)
|
|
})}
|
|
</div>
|
|
)}
|
|
</FadeInView>
|
|
</div>
|
|
)
|
|
}
|