Icking AI-Pipeline — Audit-Report & Verdict

Stand: 2026-05-14. Drei parallele Sub-Agent-Audits + eigene Validierung. Repos lokal: ~/source/a-icking, ~/source/gaeb_converter.

Kurzfassung

Marvin’s drei Beschwerden gegen die Realität:

BeschwerdeRealitätQuelle
”Qualität passt nicht”Teils richtig. Domain-Modell stimmt (Recall@1 49→85% nach Fine-Tuning, Feb 2026), aber Architektur drumrum ist Over-Engineering. SQL-Injection-Risiko in pg_client.py, drei verschiedene DB-Connection-Patterns, kein CI, ~400 LOC toter Hybrid-Codearchitektur-audit
”Dauert zu lange” (12s)Bestätigt — aber nicht aus den Gründen die im BENCHMARK.md stehen. Hauptursachen: Retry-After: 5 zwingt Client zu 5s Wartezeit + Pipeline-Lambda hat nur 512MB (Cold-Start 2.5-4s) + SQS+Polling-Overhead. Modell-Lambdas sind provisioned, also NICHT Cold-Start-Problemperformance-audit
”Kostet Geld im Monat”AWS-Kosten zahlt Icking selbst (Account 063507503859, eigene Org). Marvin’s Belastung ist Maintenance-Zeit. Tatsächliche AWS-Idle-Kosten ~119 EUR/Monat, davon ~100 EUR für Provisioned Concurrency auf 2 Modell-Lambdas 24/7cost-audit + eigene Recherche

Verdict: Refactor (2-3 Tage), kein Rewrite. Begründung unten.

Was da ist (Inventur)

Repo a-icking ist ~12k LOC Python, aber produktiver Kern ist nur ~1.500 LOC:

  • search_pipeline/ (1.500 LOC) — Pipeline, DB-Client, Lambda-Handler, async-Rerank
  • lambdas/ (320 LOC) — API-Handler, Auth-Handler, Status-Handler
  • models/embedding + models/reranking (~150 LOC + Dockerfiles) — Container-Lambdas mit BGE-M3 + BGE-Reranker
  • db/migrations/ — 6 SQL-Files, sauber (pgvector + HNSW)

Der Rest ist Datascience-Material:

  • fine-tuning/ (2.700 LOC) — SageMaker, GAEB-Extractor, Labeling-CLI
  • Eval-Scripts im Root (2.500 LOC) — evaluate_baseline.py, evaluate_pipeline_local.py, generate_training_data.py, etc.
  • terraform/ mit Modulen + 4 Envs (dev1/prod/shared/global) — Struktur ist solide

Toter Code im Production-Pfad: run_batch, postgres_hybrid_search, SearchMode.HYBRID, build_keyword_boost_query — werden nur in Eval-Scripts aufgerufen, nicht vom Production-Handler. ~350-400 LOC.

Architektur — was wirklich falsch ist

  1. SQS+Jobs+Polling für 10s-Workload (handler.py:75-83). Komplette Async-Maschinerie für eine Operation die in 30s-API-Gateway-Timeout passt. Kosten: 3 zusätzliche Hops + Retry-After: 5 = ~5-7s zusätzliche Wahrnehmungs-Latenz. Reason für die Architektur war wohl Erwartung dass Pipeline länger braucht — die Erwartung war falsch.

  2. Drei Lambdas wo eine reicht — Embedding-Lambda, Rerank-Lambda und Pipeline-Lambda sind getrennte Container. Beide Modell-Lambdas laden PyTorch+SentenceTransformers (~500MB Boot). Zusammen in einer Container-Lambda: ein Cold-Start statt zwei, ein boto3-Hop weniger.

  3. Pipeline-Lambda nutzt run() statt run_batch()cli.py hat eine fertige optimierte Batch-Methode mit async-Rerank. Der Production-Handler ignoriert sie und feuert für jeden Query separat im ThreadPool. Toter Optimierungs-Pfad neben der echten Bahn.

  4. Drei DB-Connection-Patternspg_client.py mit psycopg3+Pool, pg_jobs.py greift auf denselben Pool zu aber ruft trotz autocommit ein conn.commit(), status_handler/handler.py benutzt psycopg2 ohne Pool und ohne sslmode=require. Inkonsistent.

  5. Kein CI.github/workflows/ fehlt in a-icking (in gaeb_converter vorhanden). Tests existieren (1.770 LOC), laufen aber niemand automatisch. Erklärt warum keiner mehr weiß was funktioniert.

Code-Qualität — Blocker

  • SQL-Injection via f-strings (pg_client.py:124,138,158,312,349,407). Aktuell betroffen sind nur Vector + numerische Werte → praktisch unkritisch. Aber: postgres_hybrid_search nimmt User-Text mit halbgarem replace("'", "''"). Wenn Hybrid scharfgeschaltet wird: Injection-Vektor.
  • Nebeneffekt: Vector als f-string (1024 Floats ~10-20KB Query-Text) macht Postgres’ Prepared-Statement-Cache nutzlos. Jede Query ist neuer Parse+Plan → ~30-100ms unnötig.
  • pg_jobs.py nebenan macht es korrekt mit psycopg.sql — das Muster existiert im Repo, wurde nur nicht angewendet.

Kosten — was wirklich abfließt

Account 063507503859 gehört Icking selbst (separate AWS-Org). Marvin zahlt nichts direkt. Aber Icking zahlt aktuell:

PostenEUR/MonatAbschaltbar?
Provisioned Concurrency Embedding (2 × 3GB, 24/7)~33Ja, 1-Zeilen-Fix
Provisioned Concurrency Reranking (2 × 6GB, 24/7)~67Ja, 1-Zeilen-Fix
RDS db.t4g.micro Single-AZ + 20GB~16Nur durch Pause
Secrets/ECR/CloudWatch/Rest~3Egal
Idle-Summe~119

Top-Quick-Win: models_concurrency = -1 in app.tf:21. Spart 100 EUR/Monat. Cold-Start kommt zurück bei seltenen Requests — für Pilot-Phase akzeptabel.

Bei 50+ EUR/Monat Ersparnis könnte das ein gutes Argument an Icking sein wenn Marvin ein Phase-2-Festpreis-Angebot für den Refactor macht.

Performance — wo die 12s herkommen

Realer Breakdown (Annahme: Modell-Lambdas warm via Provisioned Concurrency, Pipeline-Lambda kalt):

Phasems
Retry-After: 5 zwingt Client zu 5s Wartezeit vor erstem Poll5.000
Pipeline-Lambda Cold-Start (512MB, VPC)2.500-4.000
Polling-Round-Trips (Client → Status-Handler)1.000-2.000
SQS-Hop + Init500-1.000
Embedding+Search+Rerank warm zusammen800-1.500

Wenn Retry-After: 5 raus, Pipeline-Memory auf 2GB, Models eager im Init geladen → realistisch 3-5s ohne Architektur-Refactor. Bei Refactor (sync Path, kombinierte Modell-Lambda): 500-900ms.

Phasen-Empfehlung

Phase 0 — Quick-Win-PR (1-2h, heute machbar)

Wirkung: 12s → 3-5s, Kosten 119 → 18 EUR/Monat. Ein einzelner PR.

  • handler.py:79: Retry-After: 5Retry-After: 1
  • app.tf:21: models_concurrency = -1 (Provisioned Concurrency aus, Lambda-Warmer übernimmt)
  • app.py:15-28: _get_model() in Modul-Top-Level ziehen (eager Load in Lambda-Init-Phase, gratis)
  • app.py:30-35: dito
  • main.tf: Pipeline-Lambda-Memory 512 → 2048 MB
  • HNSW Query-Time-Recall: SET hnsw.ef_search = 100 in pg_client.py setzen (bessere Recall-Qualität, ~0ms Latenz-Cost)

Phase 1 — Architektur-Refactor (2-3 Tage)

Wirkung: 3-5s → 500-900ms, Code-Komplexität halbiert, debuggbar in 5min.

  • SQS + Jobs-Tabelle + Status-Handler + Polling raus. Sync Path: API Gateway → Pipeline-Lambda → Response. Bei Bedarf später WebSocket — aber nicht prophylaktisch.
  • Embedding + Rerank in eine Container-Lambda mergen (~8GB Memory, 1 Cold-Start statt 2)
  • pg_client.py neu mit psycopg.sql + Parameter-Binding (SQL-Injection + Prepared-Statement-Cache)
  • Toten Hybrid-Code + run_batch löschen (~400 LOC weg)
  • status_handler auf psycopg3 + Pool umstellen, sslmode=require überall
  • GitHub Actions: pytest auf PR, Terraform-plan auf main, Container-Build via CodeBuild bleibt

Phase 2 — Operations (1 Tag)

Wirkung: Pipeline ist in 5min debuggbar.

  • X-Ray-Tracing über alle Lambdas
  • Structured Logging mit job_id (eigentlich request_id nach Sync-Umbau) als Correlation-ID
  • Health-Endpoint prüft Embedding-Lambda + DB + (falls noch da) SQS, nicht nur DB
  • CloudWatch-Alarms im Terraform: p99-Latenz > 3s, Error-Rate > 1%, RDS-Connections > 80%
  • ONBOARDING.md im Repo: ein 1h-Einstieg für neue Augen

Was NICHT zu tun ist

  • Kein Rewrite from Scratch. Schema, Container-Modelle, Terraform-Module, query_preprocessor (Maß-Extraktion DN/mm/m²), auth_handler sind keep-worthy. Rewrite kostet 2-3 Wochen statt 3-4 Tage Refactor.
  • Nicht das Fine-Tuned-Modell wegwerfen. Recall@1 49→85% ist real (docs/fine-tuning-guide.md, Commits 1669bb5). Daten + Training-Loop neu aufzubauen kostet Tage. ABER: prüfen ob das deployte Lambda-Image-Tag wirklich das fine-tuned Modell verwendet — Env-Variable in models/embedding/app.py:11 zeigt hardcoded BAAI/bge-m3, fine-tuned kann nur über CodeBuild-Bake-Step im Image gelandet sein.
  • Nicht Mistral-Lambda als Judge einbauen (so im Vault als Phase 1 geplant). Die Pipeline braucht keinen LLM-Judge — der Cross-Encoder-Reranker macht das schon, und ein LLM-Call würde Latenz um 1-3s erhöhen. Falls Icking expliziten Wunsch hat: separates Feature, nicht in Phase 1.

Wirtschaftliche Einordnung

Im Vault stand die AI-Pipeline als Festpreis-Projekt 5.500 EUR in 2 Phasen (Phase 1: 3.000 EUR MVP, Phase 2: 2.500 EUR Tuning). MVP ist offensichtlich längst gebaut — Phase 2 wäre genau der Refactor oben. Phase-Status im Vault muss korrigiert werden (projekte/icking-heyjulia/_index.md + kunden/icking.md).

Realistisches Vorgehen: Phase 0 als Vertrauens-Beweis (1-2h, kostenlos im Rahmen), dann Phase 2 für 2.500 EUR mit konkretem Plan (siehe Phase 1+2 oben). Oder Phase 2 in zwei Hälften aufteilen — Phase-1-Notausgang-Pattern (siehe festpreis-phase1-notausgang) anwenden.

Open Questions (für Marvin zu klären)

  1. Ist die Pipeline aktuell überhaupt im aktiven Einsatz? Letzter Commit 12.02.2026, kein CI, keiner schaut drauf. Wenn niemand sie nutzt: Quick-Win-PR überflüssig, alles abschalten bis Smart Dach Next live ist.
  2. Was hat Florian für eine Position dazu? Er ist der einzige technische Ansprech bei Icking. Refactor-Plan muss er mit-tragen oder zumindest verstehen.
  3. Wer hat Image-Build-Rechte und wie wird neu deployed? CodeBuild läuft, aber Trigger ist unklar. Vor Phase 0 muss klar sein: wie kommt der Code nach Production?
  4. Vertragslage Phase 2: Existiert ein Festpreis-Angebot oder müsste das neu gemacht werden? Vault sagt nicht eindeutig ob versendet/akzeptiert.

Referenzen