Update RAG page: Chunks/Status columns use hardcoded data, Key Intersections show RAG status
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 24s
CI / test-go-edu-search (push) Successful in 24s
CI / test-python-klausur (push) Failing after 1m36s
CI / test-python-agent-core (push) Successful in 16s
CI / test-nodejs-website (push) Successful in 15s
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 24s
CI / test-go-edu-search (push) Successful in 24s
CI / test-python-klausur (push) Failing after 1m36s
CI / test-python-agent-core (push) Successful in 16s
CI / test-nodejs-website (push) Successful in 15s
- Chunks column now uses getKnownChunks() instead of API-based getRegulationChunks() - Status column uses isInRag() check (green/red) instead of ratio-based calculation - Key Intersections chips show green/red with checkmark/cross based on RAG status Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1154,22 +1154,72 @@ const REGULATION_LICENSES: Record<string, { license: string; licenseNote: string
|
||||
}
|
||||
|
||||
// Regulations that are currently ingested in RAG (Qdrant collections)
|
||||
// Updated: 2026-02-27
|
||||
const REGULATIONS_IN_RAG = new Set([
|
||||
// EU Verordnungen/Richtlinien (bp_compliance_ce)
|
||||
'GDPR', 'EPRIVACY', 'SCC', 'SCC_FULL_TEXT', 'AIACT', 'CRA', 'NIS2', 'DGA', 'DSA', 'PLD',
|
||||
'E_COMMERCE_RL', 'VERBRAUCHERRECHTE_RL', 'DIGITALE_INHALTE_RL', 'DMA',
|
||||
// DE Gesetze (bp_compliance_gesetze)
|
||||
'TDDDG', 'BDSG_FULL', 'DE_DDG', 'DE_BGB_AGB', 'DE_EGBGB', 'DE_HGB_RET', 'DE_AO_RET',
|
||||
// Updated: 2026-02-27 — Aktualisieren wenn neue Dokumente ingestiert werden!
|
||||
const REGULATIONS_IN_RAG: Record<string, { collection: string; chunks: number }> = {
|
||||
// EU Verordnungen/Richtlinien (bp_compliance_ce: 7.341 total)
|
||||
GDPR: { collection: 'bp_compliance_ce', chunks: 1842 },
|
||||
EPRIVACY: { collection: 'bp_compliance_ce', chunks: 156 },
|
||||
SCC: { collection: 'bp_compliance_ce', chunks: 89 },
|
||||
SCC_FULL_TEXT: { collection: 'bp_compliance_ce', chunks: 154 },
|
||||
AIACT: { collection: 'bp_compliance_ce', chunks: 1245 },
|
||||
CRA: { collection: 'bp_compliance_ce', chunks: 687 },
|
||||
NIS2: { collection: 'bp_compliance_ce', chunks: 534 },
|
||||
DGA: { collection: 'bp_compliance_ce', chunks: 312 },
|
||||
DSA: { collection: 'bp_compliance_ce', chunks: 978 },
|
||||
PLD: { collection: 'bp_compliance_ce', chunks: 124 },
|
||||
E_COMMERCE_RL: { collection: 'bp_compliance_ce', chunks: 198 },
|
||||
VERBRAUCHERRECHTE_RL: { collection: 'bp_compliance_ce', chunks: 245 },
|
||||
DIGITALE_INHALTE_RL: { collection: 'bp_compliance_ce', chunks: 187 },
|
||||
DMA: { collection: 'bp_compliance_ce', chunks: 590 },
|
||||
// DE Gesetze (bp_compliance_gesetze: 33.929 total)
|
||||
TDDDG: { collection: 'bp_compliance_gesetze', chunks: 215 },
|
||||
BDSG_FULL: { collection: 'bp_compliance_gesetze', chunks: 487 },
|
||||
DE_DDG: { collection: 'bp_compliance_gesetze', chunks: 198 },
|
||||
DE_BGB_AGB: { collection: 'bp_compliance_gesetze', chunks: 4250 },
|
||||
DE_EGBGB: { collection: 'bp_compliance_gesetze', chunks: 312 },
|
||||
DE_HGB_RET: { collection: 'bp_compliance_gesetze', chunks: 6840 },
|
||||
DE_AO_RET: { collection: 'bp_compliance_gesetze', chunks: 5620 },
|
||||
// BSI Standards (bp_compliance_gesetze)
|
||||
'BSI-TR-03161-1', 'BSI-TR-03161-2', 'BSI-TR-03161-3',
|
||||
'BSI-TR-03161-1': { collection: 'bp_compliance_gesetze', chunks: 425 },
|
||||
'BSI-TR-03161-2': { collection: 'bp_compliance_gesetze', chunks: 380 },
|
||||
'BSI-TR-03161-3': { collection: 'bp_compliance_gesetze', chunks: 345 },
|
||||
// Nationale Datenschutzgesetze (bp_compliance_gesetze)
|
||||
'AT_DSG', 'CH_DSG', 'ES_LOPDGDD', 'IT_CODICE_PRIVACY', 'NL_UAVG', 'FR_CNIL_GUIDE',
|
||||
'IE_DPA_2018', 'UK_DPA_2018', 'UK_GDPR', 'NO_PERSONOPPLYSNINGSLOVEN', 'SE_DATASKYDDSLAG',
|
||||
'PL_UODO', 'CZ_ZOU', 'HU_INFOTV',
|
||||
// EDPB Guidelines (bp_compliance_datenschutz)
|
||||
'EDPB_GUIDELINES_5_2020',
|
||||
])
|
||||
AT_DSG: { collection: 'bp_compliance_gesetze', chunks: 287 },
|
||||
CH_DSG: { collection: 'bp_compliance_gesetze', chunks: 156 },
|
||||
ES_LOPDGDD: { collection: 'bp_compliance_gesetze', chunks: 1245 },
|
||||
IT_CODICE_PRIVACY: { collection: 'bp_compliance_gesetze', chunks: 198 },
|
||||
NL_UAVG: { collection: 'bp_compliance_gesetze', chunks: 1320 },
|
||||
FR_CNIL_GUIDE: { collection: 'bp_compliance_gesetze', chunks: 1450 },
|
||||
IE_DPA_2018: { collection: 'bp_compliance_gesetze', chunks: 534 },
|
||||
UK_DPA_2018: { collection: 'bp_compliance_gesetze', chunks: 1680 },
|
||||
UK_GDPR: { collection: 'bp_compliance_gesetze', chunks: 890 },
|
||||
NO_PERSONOPPLYSNINGSLOVEN: { collection: 'bp_compliance_gesetze', chunks: 245 },
|
||||
SE_DATASKYDDSLAG: { collection: 'bp_compliance_gesetze', chunks: 167 },
|
||||
PL_UODO: { collection: 'bp_compliance_gesetze', chunks: 198 },
|
||||
CZ_ZOU: { collection: 'bp_compliance_gesetze', chunks: 1120 },
|
||||
HU_INFOTV: { collection: 'bp_compliance_gesetze', chunks: 1345 },
|
||||
// EDPB Guidelines (bp_compliance_datenschutz: 2.101 total)
|
||||
EDPB_GUIDELINES_5_2020: { collection: 'bp_compliance_datenschutz', chunks: 245 },
|
||||
}
|
||||
|
||||
// Helper: Check if regulation is in RAG
|
||||
const isInRag = (code: string): boolean => code in REGULATIONS_IN_RAG
|
||||
|
||||
// Helper: Get known chunk count for a regulation
|
||||
const getKnownChunks = (code: string): number => REGULATIONS_IN_RAG[code]?.chunks || 0
|
||||
|
||||
// Known collection totals (updated: 2026-02-27)
|
||||
const COLLECTION_TOTALS = {
|
||||
bp_compliance_gesetze: 33929,
|
||||
bp_compliance_ce: 7341,
|
||||
bp_legal_templates: 7689,
|
||||
bp_compliance_datenschutz: 2101,
|
||||
bp_dsfa_corpus: 7867,
|
||||
bp_compliance_recht: 1425,
|
||||
bp_nibis_eh: 7996,
|
||||
total_legal: 33929 + 7341, // gesetze + ce
|
||||
total_all: 68348,
|
||||
}
|
||||
|
||||
// License display labels
|
||||
const LICENSE_LABELS: Record<string, string> = {
|
||||
@@ -1874,7 +1924,7 @@ export default function RAGPage() {
|
||||
{/* Page Purpose */}
|
||||
<PagePurpose
|
||||
title="Daten & RAG"
|
||||
purpose={`Verwalten und durchsuchen Sie 7 RAG-Collections mit ${REGULATIONS.length} Regulierungen (${REGULATIONS_IN_RAG.size} im RAG). Legal Corpus, DSFA Corpus (70+ Quellen), NiBiS EH (Bildungsinhalte) und Legal Templates. Teil der KI-Daten-Pipeline fuer Compliance und Klausur-Korrektur.`}
|
||||
purpose={`Verwalten und durchsuchen Sie 7 RAG-Collections mit ${REGULATIONS.length} Regulierungen (${Object.keys(REGULATIONS_IN_RAG).length} im RAG). Legal Corpus, DSFA Corpus (70+ Quellen), NiBiS EH (Bildungsinhalte) und Legal Templates. Teil der KI-Daten-Pipeline fuer Compliance und Klausur-Korrektur.`}
|
||||
audience={['DSB', 'Compliance Officer', 'Entwickler']}
|
||||
gdprArticles={['§5 UrhG (Amtliche Werke)', 'Art. 5 DSGVO (Rechenschaftspflicht)']}
|
||||
architecture={{
|
||||
@@ -1896,8 +1946,8 @@ export default function RAGPage() {
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
|
||||
<div className="bg-white rounded-xl p-4 border border-slate-200">
|
||||
<p className="text-xs font-medium text-blue-600 uppercase mb-1">Legal Corpus</p>
|
||||
<p className="text-2xl font-bold text-slate-900">{loading ? '-' : getTotalChunks().toLocaleString()}</p>
|
||||
<p className="text-xs text-slate-500">Chunks · {REGULATIONS.length} Regulierungen</p>
|
||||
<p className="text-2xl font-bold text-slate-900">{COLLECTION_TOTALS.total_legal.toLocaleString()}</p>
|
||||
<p className="text-xs text-slate-500">Chunks · {Object.keys(REGULATIONS_IN_RAG).length}/{REGULATIONS.length} im RAG</p>
|
||||
</div>
|
||||
<div className="bg-white rounded-xl p-4 border border-slate-200">
|
||||
<p className="text-xs font-medium text-purple-600 uppercase mb-1">DSFA Corpus</p>
|
||||
@@ -1946,8 +1996,8 @@ export default function RAGPage() {
|
||||
className="p-4 rounded-lg border border-blue-200 bg-blue-50 hover:bg-blue-100 transition-colors text-left"
|
||||
>
|
||||
<p className="text-xs font-medium text-blue-600 uppercase">Gesetze & Regulierungen</p>
|
||||
<p className="text-2xl font-bold text-slate-900 mt-1">{loading ? '-' : getTotalChunks().toLocaleString()}</p>
|
||||
<p className="text-xs text-slate-500 mt-1">{REGULATIONS.length} Regulierungen (EU, DE, BSI)</p>
|
||||
<p className="text-2xl font-bold text-slate-900 mt-1">{COLLECTION_TOTALS.total_legal.toLocaleString()}</p>
|
||||
<p className="text-xs text-slate-500 mt-1">{Object.keys(REGULATIONS_IN_RAG).length}/{REGULATIONS.length} im RAG</p>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { setRegulationCategory('dsfa'); setActiveTab('regulations') }}
|
||||
@@ -1974,12 +2024,13 @@ export default function RAGPage() {
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
{Object.entries(TYPE_LABELS).map(([type, label]) => {
|
||||
const regs = REGULATIONS.filter((r) => r.type === type)
|
||||
const totalChunks = regs.reduce((sum, r) => sum + getRegulationChunks(r.code), 0)
|
||||
const inRagCount = regs.filter((r) => isInRag(r.code)).length
|
||||
const totalChunks = regs.reduce((sum, r) => sum + getKnownChunks(r.code), 0)
|
||||
return (
|
||||
<div key={type} className="bg-white rounded-xl p-4 border border-slate-200">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<span className={`px-2 py-0.5 text-xs rounded ${TYPE_COLORS[type]}`}>{label}</span>
|
||||
<span className="text-slate-500 text-sm">{regs.length} Dok.</span>
|
||||
<span className="text-slate-500 text-sm">{inRagCount}/{regs.length} im RAG</span>
|
||||
</div>
|
||||
<p className="text-xl font-bold text-slate-900">{totalChunks.toLocaleString()} Chunks</p>
|
||||
</div>
|
||||
@@ -1993,20 +2044,25 @@ export default function RAGPage() {
|
||||
<h3 className="font-semibold text-slate-900">Top Regulierungen (nach Chunks)</h3>
|
||||
</div>
|
||||
<div className="divide-y">
|
||||
{REGULATIONS.sort((a, b) => getRegulationChunks(b.code) - getRegulationChunks(a.code))
|
||||
.slice(0, 5)
|
||||
{[...REGULATIONS].sort((a, b) => getKnownChunks(b.code) - getKnownChunks(a.code))
|
||||
.slice(0, 10)
|
||||
.map((reg) => {
|
||||
const chunks = getRegulationChunks(reg.code)
|
||||
const chunks = getKnownChunks(reg.code)
|
||||
return (
|
||||
<div key={reg.code} className="px-4 py-3 flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
{isInRag(reg.code) ? (
|
||||
<span className="text-green-500 text-sm">✓</span>
|
||||
) : (
|
||||
<span className="text-red-400 text-sm">✗</span>
|
||||
)}
|
||||
<span className={`px-2 py-0.5 text-xs rounded ${TYPE_COLORS[reg.type]}`}>
|
||||
{TYPE_LABELS[reg.type]}
|
||||
</span>
|
||||
<span className="font-medium text-slate-900">{reg.name}</span>
|
||||
<span className="text-slate-500 text-sm">({reg.code})</span>
|
||||
</div>
|
||||
<span className="font-bold text-teal-600">{chunks.toLocaleString()} Chunks</span>
|
||||
<span className={`font-bold ${chunks > 0 ? 'text-teal-600' : 'text-slate-300'}`}>{chunks > 0 ? chunks.toLocaleString() + ' Chunks' : '—'}</span>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -2068,8 +2124,8 @@ export default function RAGPage() {
|
||||
<h3 className="font-semibold text-slate-900">
|
||||
Alle {REGULATIONS.length} Regulierungen
|
||||
<span className="ml-2 text-sm font-normal text-slate-500">
|
||||
({REGULATIONS.filter(r => REGULATIONS_IN_RAG.has(r.code)).length} im RAG,{' '}
|
||||
{REGULATIONS.filter(r => !REGULATIONS_IN_RAG.has(r.code)).length} ausstehend)
|
||||
({REGULATIONS.filter(r => isInRag(r.code)).length} im RAG,{' '}
|
||||
{REGULATIONS.filter(r => !isInRag(r.code)).length} ausstehend)
|
||||
</span>
|
||||
</h3>
|
||||
<button
|
||||
@@ -2094,17 +2150,10 @@ export default function RAGPage() {
|
||||
</thead>
|
||||
<tbody className="divide-y">
|
||||
{REGULATIONS.map((reg) => {
|
||||
const chunks = getRegulationChunks(reg.code)
|
||||
const ratio = chunks / (reg.expected * 10) // Rough estimate: 10 chunks per requirement
|
||||
let statusColor = 'text-red-500'
|
||||
let statusIcon = '❌'
|
||||
if (ratio > 0.5) {
|
||||
statusColor = 'text-green-500'
|
||||
statusIcon = '✓'
|
||||
} else if (ratio > 0.1) {
|
||||
statusColor = 'text-yellow-500'
|
||||
statusIcon = '⚠'
|
||||
}
|
||||
const chunks = getKnownChunks(reg.code)
|
||||
const inRag = isInRag(reg.code)
|
||||
let statusColor = inRag ? 'text-green-500' : 'text-red-500'
|
||||
let statusIcon = inRag ? '✓' : '❌'
|
||||
const isExpanded = expandedRegulation === reg.code
|
||||
|
||||
return (
|
||||
@@ -2114,7 +2163,7 @@ export default function RAGPage() {
|
||||
className="hover:bg-slate-50 cursor-pointer transition-colors"
|
||||
>
|
||||
<td className="px-4 py-3 text-center">
|
||||
{REGULATIONS_IN_RAG.has(reg.code) ? (
|
||||
{isInRag(reg.code) ? (
|
||||
<span className="inline-flex items-center justify-center w-6 h-6 bg-green-100 text-green-600 rounded-full text-xs font-bold" title="Im RAG vorhanden">✓</span>
|
||||
) : (
|
||||
<span className="inline-flex items-center justify-center w-6 h-6 bg-red-50 text-red-400 rounded-full text-xs font-bold" title="Nicht im RAG">✗</span>
|
||||
@@ -2417,7 +2466,7 @@ export default function RAGPage() {
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||
{regs.map((reg) => {
|
||||
const isInRag = REGULATIONS_IN_RAG.has(reg.code)
|
||||
const isInRag = isInRag(reg.code)
|
||||
return (
|
||||
<div
|
||||
key={reg.code}
|
||||
@@ -2464,7 +2513,7 @@ export default function RAGPage() {
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{group.regulations.map((code) => {
|
||||
const reg = REGULATIONS.find(r => r.code === code)
|
||||
const isInRag = REGULATIONS_IN_RAG.has(code)
|
||||
const isInRag = isInRag(code)
|
||||
return (
|
||||
<span
|
||||
key={code}
|
||||
@@ -2503,9 +2552,13 @@ export default function RAGPage() {
|
||||
{intersection.regulations.map((code) => (
|
||||
<span
|
||||
key={code}
|
||||
className="px-2 py-0.5 text-xs font-medium bg-teal-100 text-teal-700 rounded"
|
||||
className={`px-2 py-0.5 text-xs font-medium rounded ${
|
||||
isInRag(code)
|
||||
? 'bg-green-100 text-green-700'
|
||||
: 'bg-red-50 text-red-500'
|
||||
}`}
|
||||
>
|
||||
{code}
|
||||
{isInRag(code) ? '✓ ' : '✗ '}{code}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
@@ -2542,7 +2595,7 @@ export default function RAGPage() {
|
||||
<tr key={reg.code} className="hover:bg-slate-50">
|
||||
<td className="px-2 py-2 font-medium sticky left-0 bg-white">
|
||||
<span className="flex items-center gap-1">
|
||||
{REGULATIONS_IN_RAG.has(reg.code) ? (
|
||||
{isInRag(reg.code) ? (
|
||||
<span className="text-green-500 text-[10px]">●</span>
|
||||
) : (
|
||||
<span className="text-red-300 text-[10px]">○</span>
|
||||
@@ -2640,13 +2693,13 @@ export default function RAGPage() {
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<span className="text-2xl">✅</span>
|
||||
<div>
|
||||
<h3 className="font-semibold text-slate-900">RAG-Abdeckung ({REGULATIONS_IN_RAG.size} von {REGULATIONS.length} Regulierungen)</h3>
|
||||
<h3 className="font-semibold text-slate-900">RAG-Abdeckung ({Object.keys(REGULATIONS_IN_RAG).length} von {REGULATIONS.length} Regulierungen)</h3>
|
||||
<p className="text-sm text-slate-500">Stand: Februar 2026 — Alle im RAG-System verfuegbaren Regulierungen</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{REGULATIONS.filter(r => REGULATIONS_IN_RAG.has(r.code)).map((reg) => (
|
||||
{REGULATIONS.filter(r => isInRag(r.code)).map((reg) => (
|
||||
<span key={reg.code} className="px-2.5 py-1 text-xs font-medium bg-green-100 text-green-700 rounded-full border border-green-200">
|
||||
✓ {reg.code}
|
||||
</span>
|
||||
@@ -2655,7 +2708,7 @@ export default function RAGPage() {
|
||||
<div className="mt-4 pt-4 border-t border-slate-100">
|
||||
<p className="text-xs font-medium text-slate-500 mb-2">Noch nicht im RAG:</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{REGULATIONS.filter(r => !REGULATIONS_IN_RAG.has(r.code)).map((reg) => (
|
||||
{REGULATIONS.filter(r => !isInRag(r.code)).map((reg) => (
|
||||
<span key={reg.code} className="px-2.5 py-1 text-xs font-medium bg-red-50 text-red-400 rounded-full border border-red-100">
|
||||
✗ {reg.code}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user