feat: KI-Bewertungs-Versionierung — alte Versionen behalten
Backend: - DELETE vor INSERT entfernt — neue Bewertungen werden hinzugefügt - erstellt_at Timestamp bei jeder Neubewertung - API liefert ki_versionen[] (ältere Versionen, neueste zuerst) Frontend (Explorer + Vorlagen-Detail): - Neueste Version als Hauptanzeige (wie bisher) - Button 'X vorherige Versionen' → aufklappbar - Jede Version mit Zeitstempel + prompt_version
This commit is contained in:
parent
df917725e2
commit
3fd1bc5bd7
@ -85,6 +85,7 @@ class VorlageDetail(BaseModel):
|
|||||||
kette_id: int | None = None
|
kette_id: int | None = None
|
||||||
umsetzungsbewertungen: list[UmsetzungsBewertung] = []
|
umsetzungsbewertungen: list[UmsetzungsBewertung] = []
|
||||||
ampel: dict | None = None
|
ampel: dict | None = None
|
||||||
|
ki_versionen: list[dict] | None = None
|
||||||
|
|
||||||
|
|
||||||
class KettenGliedOut(BaseModel):
|
class KettenGliedOut(BaseModel):
|
||||||
|
|||||||
@ -162,12 +162,12 @@ def _run_zusammenfassung(vorlage_id: int, anmerkung: str, job_id: str):
|
|||||||
_jobs[job_id] = {"status": "error", "error": str(result)}
|
_jobs[job_id] = {"status": "error", "error": str(result)}
|
||||||
return
|
return
|
||||||
|
|
||||||
# Delete old, insert new
|
# Keep old versions, insert new
|
||||||
conn.execute("DELETE FROM ki_bewertungen WHERE vorlage_id = ? AND typ = 'zusammenfassung'", (vorlage_id,))
|
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"""INSERT INTO ki_bewertungen (vorlage_id, typ, begruendung, anmerkungen, modell, prompt_version)
|
"""INSERT INTO ki_bewertungen (vorlage_id, typ, begruendung, anmerkungen, modell, prompt_version, erstellt_at)
|
||||||
VALUES (?, 'zusammenfassung', ?, ?, 'qwen-plus-latest', 'v2-reeval')""",
|
VALUES (?, 'zusammenfassung', ?, ?, 'qwen-plus-latest', 'v2-reeval', ?)""",
|
||||||
(vorlage_id, result.get("zusammenfassung"), json.dumps(result, ensure_ascii=False)),
|
(vorlage_id, result.get("zusammenfassung"), json.dumps(result, ensure_ascii=False),
|
||||||
|
datetime.now().isoformat()),
|
||||||
)
|
)
|
||||||
if result.get("kernforderung"):
|
if result.get("kernforderung"):
|
||||||
conn.execute("UPDATE vorlagen SET thema_kurz = ? WHERE id = ?", (result["kernforderung"][:200], vorlage_id))
|
conn.execute("UPDATE vorlagen SET thema_kurz = ? WHERE id = ?", (result["kernforderung"][:200], vorlage_id))
|
||||||
@ -249,19 +249,16 @@ def _run_ketten_bewertung(kette_id: int, anmerkung: str, job_id: str):
|
|||||||
_jobs[job_id] = {"status": "error", "error": str(result)}
|
_jobs[job_id] = {"status": "error", "error": str(result)}
|
||||||
return
|
return
|
||||||
|
|
||||||
# Delete old umsetzung_match, insert new
|
# Keep old versions, insert new
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"DELETE FROM ki_bewertungen WHERE vorlage_id = ? AND typ = 'umsetzung_match'",
|
"""INSERT INTO ki_bewertungen (vorlage_id, typ, score, begruendung, anmerkungen, modell, prompt_version, erstellt_at)
|
||||||
(kette["ursprung_id"],),
|
VALUES (?, 'umsetzung_match', ?, ?, ?, 'qwen-plus-latest', 'v2-reeval', ?)""",
|
||||||
)
|
|
||||||
conn.execute(
|
|
||||||
"""INSERT INTO ki_bewertungen (vorlage_id, typ, score, begruendung, anmerkungen, modell, prompt_version)
|
|
||||||
VALUES (?, 'umsetzung_match', ?, ?, ?, 'qwen-plus-latest', 'v2-reeval')""",
|
|
||||||
(
|
(
|
||||||
kette["ursprung_id"],
|
kette["ursprung_id"],
|
||||||
result.get("score"),
|
result.get("score"),
|
||||||
result.get("begruendung"),
|
result.get("begruendung"),
|
||||||
json.dumps(result, ensure_ascii=False),
|
json.dumps(result, ensure_ascii=False),
|
||||||
|
datetime.now().isoformat(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -297,16 +297,28 @@ def get_vorlage(vorlage_id: int, conn=Depends(_db)):
|
|||||||
if kette_info and kette_info["strang"]:
|
if kette_info and kette_info["strang"]:
|
||||||
kette_ampel = get_ampel(kette_info["strang"], kette_info["status"] or "")
|
kette_ampel = get_ampel(kette_info["strang"], kette_info["status"] or "")
|
||||||
|
|
||||||
# KI-Zusammenfassung
|
# KI-Zusammenfassung (alle Versionen, neueste zuerst)
|
||||||
ki_row = conn.execute(
|
ki_rows = conn.execute(
|
||||||
"SELECT anmerkungen FROM ki_bewertungen WHERE vorlage_id = ? AND typ = 'zusammenfassung' LIMIT 1",
|
"SELECT anmerkungen, erstellt_at, prompt_version FROM ki_bewertungen WHERE vorlage_id = ? AND typ = 'zusammenfassung' ORDER BY id DESC",
|
||||||
(vorlage_id,),
|
(vorlage_id,),
|
||||||
).fetchone()
|
).fetchall()
|
||||||
ki_zusammenfassung = None
|
ki_zusammenfassung = None
|
||||||
if ki_row and ki_row["anmerkungen"]:
|
ki_versionen = []
|
||||||
|
for i, ki_row in enumerate(ki_rows):
|
||||||
|
if ki_row["anmerkungen"]:
|
||||||
try:
|
try:
|
||||||
ki_data = json.loads(ki_row["anmerkungen"])
|
ki_data = json.loads(ki_row["anmerkungen"])
|
||||||
|
if i == 0:
|
||||||
ki_zusammenfassung = KiZusammenfassung(**ki_data)
|
ki_zusammenfassung = KiZusammenfassung(**ki_data)
|
||||||
|
else:
|
||||||
|
ki_versionen.append({
|
||||||
|
"zusammenfassung": ki_data.get("zusammenfassung", ""),
|
||||||
|
"kernforderung": ki_data.get("kernforderung", ""),
|
||||||
|
"begruendung": ki_data.get("begruendung", ""),
|
||||||
|
"thema": ki_data.get("thema", ""),
|
||||||
|
"erstellt_at": ki_row["erstellt_at"],
|
||||||
|
"prompt_version": ki_row["prompt_version"],
|
||||||
|
})
|
||||||
except (json.JSONDecodeError, TypeError):
|
except (json.JSONDecodeError, TypeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -351,4 +363,5 @@ def get_vorlage(vorlage_id: int, conn=Depends(_db)):
|
|||||||
ki_zusammenfassung=ki_zusammenfassung,
|
ki_zusammenfassung=ki_zusammenfassung,
|
||||||
umsetzungsbewertungen=umsetzungsbewertungen,
|
umsetzungsbewertungen=umsetzungsbewertungen,
|
||||||
ampel=kette_ampel,
|
ampel=kette_ampel,
|
||||||
|
ki_versionen=ki_versionen if ki_versionen else None,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
// Mobile tab
|
// Mobile tab
|
||||||
let mobileTab = $state<'liste' | 'kette' | 'detail'>('liste');
|
let mobileTab = $state<'liste' | 'kette' | 'detail'>('liste');
|
||||||
let showVolltext = $state(false);
|
let showVolltext = $state(false);
|
||||||
|
let showVersionen = $state(false);
|
||||||
|
|
||||||
const STRANG_TABS = [
|
const STRANG_TABS = [
|
||||||
{ value: '', label: 'Alle' },
|
{ value: '', label: 'Alle' },
|
||||||
@ -438,6 +439,33 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<!-- Vorherige KI-Versionen -->
|
||||||
|
{#if selectedVorlage.ki_versionen?.length}
|
||||||
|
<div>
|
||||||
|
<button onclick={() => showVersionen = !showVersionen}
|
||||||
|
class="text-xs text-gray-500 hover:text-gray-700 flex items-center gap-1">
|
||||||
|
<span>{showVersionen ? '▼' : '▶'}</span>
|
||||||
|
{selectedVorlage.ki_versionen.length} vorherige Version{selectedVorlage.ki_versionen.length > 1 ? 'en' : ''}
|
||||||
|
</button>
|
||||||
|
{#if showVersionen}
|
||||||
|
<div class="mt-2 space-y-3">
|
||||||
|
{#each selectedVorlage.ki_versionen as v, i}
|
||||||
|
<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
|
||||||
|
<div class="flex items-center justify-between mb-2">
|
||||||
|
<span class="text-xs text-gray-400">Version {selectedVorlage.ki_versionen.length - i} · {v.erstellt_at || 'unbekannt'}</span>
|
||||||
|
<span class="text-[10px] px-1.5 py-0.5 rounded bg-gray-200 text-gray-500">{v.prompt_version || ''}</span>
|
||||||
|
</div>
|
||||||
|
<p class="text-sm text-gray-600">{v.zusammenfassung}</p>
|
||||||
|
{#if v.kernforderung}
|
||||||
|
<p class="text-xs text-gray-500 mt-1"><strong>Kernforderung:</strong> {v.kernforderung}</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<!-- Umsetzungsbewertung -->
|
<!-- Umsetzungsbewertung -->
|
||||||
{#if selectedVorlage.umsetzungsbewertungen?.length}
|
{#if selectedVorlage.umsetzungsbewertungen?.length}
|
||||||
<div class="rounded-xl border border-gray-200 p-5">
|
<div class="rounded-xl border border-gray-200 p-5">
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
let error: string | null = $state(null);
|
let error: string | null = $state(null);
|
||||||
let showVolltext = $state(false);
|
let showVolltext = $state(false);
|
||||||
let showReeval = $state(false);
|
let showReeval = $state(false);
|
||||||
|
let showVersionen = $state(false);
|
||||||
let reevalAnmerkung = $state('');
|
let reevalAnmerkung = $state('');
|
||||||
let reevalStatus = $state<'idle' | 'running' | 'done' | 'error'>('idle');
|
let reevalStatus = $state<'idle' | 'running' | 'done' | 'error'>('idle');
|
||||||
let reevalError = $state('');
|
let reevalError = $state('');
|
||||||
@ -201,6 +202,33 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<!-- Vorherige KI-Versionen -->
|
||||||
|
{#if vorlage.ki_versionen?.length}
|
||||||
|
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
||||||
|
<button onclick={() => showVersionen = !showVersionen}
|
||||||
|
class="text-sm text-gray-500 hover:text-gray-700 flex items-center gap-1.5">
|
||||||
|
<span>{showVersionen ? '▼' : '▶'}</span>
|
||||||
|
{vorlage.ki_versionen.length} vorherige KI-Version{vorlage.ki_versionen.length > 1 ? 'en' : ''}
|
||||||
|
</button>
|
||||||
|
{#if showVersionen}
|
||||||
|
<div class="mt-3 space-y-3">
|
||||||
|
{#each vorlage.ki_versionen as v, i}
|
||||||
|
<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
|
||||||
|
<div class="flex items-center justify-between mb-2">
|
||||||
|
<span class="text-xs text-gray-400">Version {vorlage.ki_versionen.length - i} · {v.erstellt_at || 'unbekannt'}</span>
|
||||||
|
<span class="text-[10px] px-1.5 py-0.5 rounded bg-gray-200 text-gray-500">{v.prompt_version || ''}</span>
|
||||||
|
</div>
|
||||||
|
<p class="text-sm text-gray-600">{v.zusammenfassung}</p>
|
||||||
|
{#if v.kernforderung}
|
||||||
|
<p class="text-xs text-gray-500 mt-1"><strong>Kernforderung:</strong> {v.kernforderung}</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<!-- Umsetzungsbewertung -->
|
<!-- Umsetzungsbewertung -->
|
||||||
{#if vorlage.umsetzungsbewertungen?.length}
|
{#if vorlage.umsetzungsbewertungen?.length}
|
||||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user