Run — Icking Pipeline-Handoff 2026-05-18
Zweck
Drei Auslieferungen am gleichen Tag:
- Eval-Bilanz der neu aufgesetzten Pipeline auf 51 Architekten-Queries — PDF mit AV-Design, an Christoph + Nicole gegangen.
- Technische API-Doku für Florian Schubert (Smart Dach) — als PDF mit eingebettetem API-Key, ebenfalls AV-Design, separat per Mail.
- POST /batch-Endpoint im inference-service vorbereitet (committed, noch nicht deployed) — für Florians 10–20-Query-Workloads.
Stand danach
| Bereich | Resultat |
|---|---|
| Pipeline-Qualität (51 expandierte LV-Queries) | R@1 74,5 %, R@3 86,3 %, R@5 96,1 %, R@10 96,1 %, 0 HTTP-Fehler |
| Median-Latenz | 10,1 s (durch 3-RPM-Quota, Service wartet aktiv statt 500) |
| Quota-Anträge | Cohere Rerank 3→250 RPM, Amazon Rerank 2→200 RPM, Haiku 4.5 RPM 10→10.000 — Support-Case offen |
| Mails | An Florian gesendet, an Nicole + Christoph als Draft → Marvin sendet selbst |
| Code | /batch + Tests live als Task-Def Rev 10, Image :d81c9a8 (PR #6 nach main gemergt 19:35, Deploy 19:46) |
Deploy-Erweiterung 2026-05-18 19:33–19:46 (/batch-Release)
Nach Audit-Pass + Marvin-Greenlight wurde das /batch-Drift-Problem beseitigt:
| Schritt | Zeit | Ergebnis |
|---|---|---|
Commit 05d5589 (Phase-5-Prep + Retry-Wrapper + 5 untracked Files) | 19:31 | Branch in Sync mit live Container |
Merge origin/main → Branch (10ae88a, Konflikt in main.py trivial gelöst) | 19:33 | 252 Tests grün, ruff sauber |
| PR #6 geöffnet | 19:34 | CI test-job pass in 16s |
PR-Merge nach main (d81c9a8) | 19:35 | CI build+deploy startet |
| CI fertig (Run 26049775805) | 19:43 | ARM64-Image :d81c9a8 + Tags :main + :latest in ECR |
| Task-Def Rev 10 registriert | 19:45 | Image-Tag :d81c9a8 statt :phase4-final-retry |
| Service-Update + stable | 19:46 | Container läuft, alle Checks grün |
Smoke-Test /search + /batch | 19:47 | 200 OK, plausible Treffer |
CI-Workflow-Lücke aufgedeckt: Der GitHub-Actions-Workflow (inference-service.yml) macht nach ECR-Push nur aws ecs update-service --force-new-deployment. Das startet einen neuen Task — aber mit derselben Task-Def-Revision, die auf einen statischen Image-Tag zeigt. Wenn der CI-Build neue Tags pusht (:main, :latest, :<sha>), aber der Task-Def auf :phase4-final-retry (statischer Tag) zeigt, wird Force-Deploy genau dasselbe Image neu starten. Resultat heute: nach erfolgreichem Merge + CI-Build lief /batch noch nicht — manuelle Task-Def-Revision 10 mit :d81c9a8 war notwendig.
Backlog für später: CI-Workflow erweitern um automatische Task-Def-Revision mit Commit-SHA-Tag. Pattern wäre aws ecs register-task-definition + --task-definition flag im update-service. Alternativ: Task-Def auf :latest umstellen und force-new-deployment reicht. Für heute: Rev 10 statisch ist Audit-fester, aber dann braucht jeder Deploy manuell eine neue Task-Def. Beide Wege sind valide, aktuell ist Rev 10 ein Einzelfall.
Eval-Methodik — sehr wichtig zu wissen
Die 96,1 % wurden NICHT auf Florians Original-Stichwort-Set gemessen. Sondern auf einer LLM-expandierten Variante davon (florian_long.jsonl). Vergleich:
Florians Original (data/eval/eval_set.jsonl) | florian_long.jsonl (für diesen Run verwendet) | |
|---|---|---|
| Cases | 51 | 51 (gleiche lvp_ids) |
| Query Ø-Länge | 39 Zeichen | 107 Zeichen |
| Query #1 | "Baustelleneinrichtung" | "Pauschale für Baustelleneinrichtung, Vorhaltung von Maschinen, Geräten und notwendigen Absperrmaßnahmen" |
| Recall@10 (Phase-4-final) | 54,9 % | 96,1 % |
Die Long-Queries sind ausformulierte LV-Position-Texte, vermutlich via Haiku aus den Stichworten generiert (im Result-File ist query_original als Florians Stichwort plus query als Long-Variante hinterlegt). Die Long-Queries sind oft Paraphrasen des Ziel-Catalog-Eintrags — Beispiel: Long-Query #1 vs Catalog-Eintrag 83278 ("Baustelleneinrichtung: Pauschale für Baustelleneinrichtung") — was die hohe Recall-Zahl maßgeblich erklärt.
Was die 96,1 % korrekt messen: wenn ein Bauleiter einen kompletten LV-Position-Text in die Suche tippt, findet das System den richtigen Catalog-Eintrag mit hoher Wahrscheinlichkeit in den Top-5.
Was die 96,1 % NICHT messen: Florians eigentliches Stichwort-Use-Case-Pattern ("Baustelleneinrichtung" → Catalog). Auf Stichworten liegt die Pipeline laut Phase-4-Bilanz bei ~55 % R@10.
In der Mail an Nicole + Christoph wurde der Eval-Set-Hintergrund nicht explizit gemacht („51 realistische Architekten-Anfragen”). Das ist nicht falsch — Architekten arbeiten mit LV-Texten — aber der Unterschied zu Florians Original ist wichtig für die nächste Eval-Runde mit echtem Florian-Material.
Reproduzierbarkeit der 96,1 %
Der Bake-Off-Run am 18.05.2026 zwischen 10:43 und 10:48 UTC ist über CloudWatch nachweisbar (Log-Group /ecs/inference-service-prod/app, 51 Search-Audit-Events von key_id 7c0a5657, alle 200 OK). Vollständige Reproduktion über:
| Artefakt | Pfad |
|---|---|
| Eval-Runner-Script | assets/eval/pipeline_full.py |
| Eval-Set verwendet | assets/eval/florian_long.jsonl + S3: s3://av-production-terraform-state/inference-service/bootstrap/eval_set_long_florian.jsonl |
| Per-Query Ergebnisse | assets/eval/florian_long_results.jsonl (rank + latency + top1_id pro Case) |
| Run-Output mit Summary | assets/eval/full_run_retry.log |
| Charts (Quell-PNGs) | assets/eval/charts_v2/{1_recall,2_rank,3_latency}.png |
| Report-HTML (Quelle der PDF) | assets/eval/charts_v2/report.html |
| Live-Service zum Test-Zeitpunkt | inference.agenticventures.de, Task-Def Rev 9, Image :phase4-final-retry (seit 19:46: Rev 10, Image :d81c9a8, inhaltsgleich + /batch) |
Re-Run gegen Florians ORIGINAL-Stichwort-Set steht aus — wird die echte Stichwort-Recall-Zahl ergeben (~55 % R@10 erwartet).
Architektur-Entscheidung dieser Session
Sync /batch statt async Polling-API. Die alte Lambda-Pipeline akzeptierte {queries: [...]} und gab job_id plus Status-Endpoint zurück. Der Wiederaufbau dieses Patterns hätte Job-State in der DB, Background-Worker und Cleanup-Cron bedeutet — eine Woche Code für einen Workflow, der nach Quota-Lift in 1–10 Sekunden synchron durchläuft. Stattdessen:
/batchnimmt 1–50 Queries, läuft intern sequentiell durch, gibt Array zurück- Per-Query-Errors brechen den Batch nicht (jede Query hat eigenen
status: "ok"|"error"+ optionalretry_after) - Hard-Limit 50 schützt vor HTTP-Timeouts
- Progress baut Florian client-side via Chunks von 10–20 Queries — pro Chunk weiß er „20 von 200 fertig”
Detailbegründung im Mail-Verlauf der Session (Marvin-Vorschlag „Florian soll nur die URL ändern” → realisiert mit minimaler Code-Anpassung bei Florian: kein Polling mehr, Response-Shape direkt auspacken).
Artefakte
Alle Files in assets/ dieses Run-Verzeichnisses:
| Datei | Zweck |
|---|---|
assets/eval-report.html | HTML-Quelle der Eval-Auswertung |
assets/icking-pipeline-auswertung.pdf | Gerenderter Eval-Bericht (7 Seiten, weißer Hintergrund, transparente Wortmarke) |
assets/florian-api-doku.html | HTML-Quelle der API-Doku |
assets/florian-api-doku.pdf | Gerenderte API-Doku (9 Seiten, mit eingebettetem Bearer-Token) |
assets/eval/pipeline_full.py | Eval-Runner gegen Live-Service |
assets/eval/florian_long.jsonl | 51-Case Eval-Set (LLM-expandiert aus Florians Stichworten) |
assets/eval/florian_long_results.jsonl | Per-Query rank + latency + top1_id |
assets/eval/full_run_retry.log | Run-Output mit finaler Summary |
assets/eval/charts_v2/ | Charts + HTML-Report-Quelle + render_pdf.py |
next-session-prompt.md | Ursprünglicher Session-Brief (enthält Pfad-Drift, siehe Drift-Notiz unten) |
S3-Drift-Notiz: Der next-session-prompt.md referenziert s3://av-icking-eval-data/reports/2026-05-18/ als Parallel-Storage — dieser Bucket liegt im av-icking-Sub-Account, auf den Marvin aktuell keinen SSO-Zugriff hat. Die im Run verwendeten Files lagen daher ausschließlich in /tmp/ auf Marvins Maschine. Nach diesem Run wurden sie in assets/eval/ gesichert und florian_long.jsonl zusätzlich nach s3://av-production-terraform-state/inference-service/bootstrap/eval_set_long_florian.jsonl hochgeladen (av-production, nicht av-icking) — das ist die einzige reproduzierbare Quelle des Eval-Sets.
Mails
Beide aus hello@marvinkuehlmann.com versendet bzw. als Draft abgelegt:
- An Florian Schubert (
f.schubert@leistungen-dach.de) — gesendet. Inhalt: neue Pipeline-Version, Trefferquoten, Architektur-Hinweis (Lambda+APIGW → ECS), neue URL, API-Doku als Anhang, Quota-Lage erklärt. - An Nicole + Christoph Icking (
N.Icking@leistungen-dach.de, ccc.icking@leistungen-dach.de) — Draft, Marvin sendet selbst. Inhalt: Eval-Bilanz, Phase-5-Hinweis als Aufpreis-Ankündigung, Vorschlag Vertrieb-Feedback einzuholen, HeyJulia-Vertragsentwurf-Frage angetriggert.
Was noch offen ist — Findings + Status nach Kritik-Pass
Strukturiert nach Sprengkraft. Audit dieser Session am 2026-05-18 Abend gegen den Stand am Mittag.
Hoch — vor Florians erstem API-Test klären
GELÖST 2026-05-18 19:46. PR #6 gemergt, CI-Build durch (Run 26049775805, ~8min), Task-Def Rev 10 mit Image/batchist 404 in Production.:d81c9a8deployed. Smoke-Test grün:/healthz,/readyz,/search,/batch(2/2 succeeded) — alle OK. Florian-Doku stimmt jetzt mit Production überein.- Re-Run gegen Florians Original-Stichwort-Set (
data/eval/eval_set.jsonl) für eine ehrliche Stichwort-Recall-Zahl. Vor Florian-Feedback hinlegen damit du beide Zahlen bei der Hand hast: 96,1 % auf LV-Texten, ~55 % auf Stichworten. Branch-Drift im inference-service.GELÖST 2026-05-18 19:33. Untracked Files (_retry.py,query_understanding.py, Migration 005, enrich-Script, generate_long_eval-Script) + 11 uncommittete Diffs in einem Commit zusammengefasst (05d5589), Merge mit origin/main aufgelöst (10ae88a), via PR #6 nach main. Branch ist jetzt in Sync mit Production.
Mittel — strukturell, hat heute keinen externen Effekt
- AWS-Quota-Lift — Support-Case läuft (Cohere Rerank 3→250 RPM, Amazon Rerank 2→200 RPM, Haiku 4.5 10→10.000 RPM), 24–48 h erwartet. Bis dahin ist die in der API-Doku versprochene Latenz „<1 s” eine Annahme, gemessen 10,1 s p50.
- Score-Fusion-Gewicht
wgr_consistency_weight=0.04ist binär, nicht weight-tunable (Phase-4-Bilanz schreibt das selbst: identische Recall-Zahlen bei W=0.04 und W=0.08). Sollte als bool-Flag oder feste Konstante refactoriert werden, damit keiner versucht den Wert zu tunen. - L7-Hypothese „aktuellerer Catalog-Stand, kein Absorber” ist Eigeninspektion ohne Florian-Validierung. Wenn falsch, dann hat Production einen systematischen Bias zu VELUX/Roto-Detailpositionen. Beim ersten Florian-Telefonat verifizieren.
- Migration 004 (
catalog_cleanup_archived) ist lokal modifiziert + WIP, derarchived IS NOT TRUE-Filter inhybrid.pyist im aktuellen Branch aktiv. Klären ob Migration in Prod-DB läuft und welche Catalog-Cleanup-Diffs deployed sind. - Phase 5 (Catalog-Anreicherung mit strukturierten Attributen) vorbereitet, aber bewusst nicht aktiviert. Aktivierung erst nach Florian-Feedback aus realen LV-Texten — sonst optimieren wir am Büro-Tisch. ✓ richtig so.
Niedrig — wirtschaftlich + organisatorisch
- Pricing Pipeline noch offen — Audit hatte 2.500 EUR Festpreis für Refactor vorgeschlagen, Rebuild war deutlich mehr Aufwand. Mail an Nicole/Christoph nennt Phase-5-Aufpreis ohne dass Phase 1–4 vergütungsmäßig geklärt ist. Beim HeyJulia-Telefonat Mi/Do mit auf die Agenda, getrennt von HeyJulia.
- Alte Lambdas im Icking-Account laufen weiter — ~119 EUR/Monat idle, Cutover blockt auf SSO. Niemand weiß ob noch jemand auf die alte URL pointet. Sobald SSO frei → abschalten.
av-icking-Sub-Account ist im Vault nicht dokumentiert —next-session-prompt.mdreferenziert Account376761748837mit S3-Bucketav-icking-eval-data. Bestätigen, ob das tatsächlich angelegt wurde (laut Vault-Konvention erst bei konkretem Workload), und ggf.intern/capabilities/aws/accounts.mdnachziehen.- Two-Key-Rotation TTL=120s blockt Sofort-Revoke — bei API-Key-Compromise (Florian-Side) 2 min Wartezeit minimum. ce:review-Backlog-Eintrag, nicht heute wichtig.
- Latenz-Claim „p50 400–800ms nach Quota-Lift” ist Annahme, nicht gemessen. Nach Quota-Increase mit echter Last validieren.
- HeyJulia-Vertragsentwurf — telefonisches Follow-up Mi/Do mit Nicole + Christoph. Separat von Pipeline-Pricing halten.