Portfolio-Projekt · AWS Serverless

Ein Datei-Upload reicht - der Rest läuft vollautomatisch auf AWS.

Du lädst ein beliebiges Dokument hoch - eine Rechnung, eine Visitenkarte, ein Vertragsschnipsel. Die Pipeline erkennt automatisch den Dokumenttyp und extrahiert die relevanten Felder per Claude, komplett ohne dass vorher festgelegt wurde, welcher Typ hochgeladen wird. Kein Server, den man selbst am Laufen halten muss - event-getrieben, serverlos, auf AWS.

Läuft live gegen eine echte, deployte AWS-Pipeline (S3 → Lambda → Claude → DynamoDB → API Gateway). Free-Tier-App schläft nach Inaktivität ein, erster Aufruf kann ein paar Sekunden zum Aufwachen brauchen.

Was das Tool macht

Fünf Schritte von der hochgeladenen Datei bis zum angezeigten Ergebnis - vollständig event-getrieben, kein Polling.

1

Presigned Upload

Das Frontend fragt beim API Gateway eine Presigned-URL an und lädt die Datei direkt nach S3 hoch - ohne eigene AWS-Zugangsschlüssel.

2

Automatischer Trigger

Das S3-ObjectCreated-Event startet automatisch die process_document-Lambda - kein manueller Trigger.

3

Klassifikation + Extraktion

Ein einziger Claude-Call klassifiziert den Dokumenttyp und extrahiert gleichzeitig die typ-spezifischen Felder.

4

Validierung + Ablage

Die Antwort wird gegen das passende Pydantic-Schema geprüft und als Datensatz in DynamoDB abgelegt - inklusive Fehlerfällen.

5

Live-Anzeige

Streamlit fragt die Ergebnisliste per HTTP ab und zeigt erfolgreiche wie fehlgeschlagene Verarbeitungen live an.

Use Cases

Drei synthetische Dokumenttypen, jeweils mit eigenem Pydantic-Schema, damit die LLM-Ausgabe validierbar ist - nicht nur "hoffentlich JSON".

TypBeispiel-InhaltExtrahierte Felder
invoice generierte Rechnungen (Fantasie-Firmen/-Beträge) vendor, date, amount, currency, line_items[]
business_card generierte Visitenkarten-Texte (Fantasie-Namen/-Firmen) name, company, email, phone
contract_snippet generierte Vertragsklausel-Ausschnitte (Fantasie-Parteien) parties[], clause_type, effective_date, summary

Alle Testdokumente unter sample_documents/ sind komplett selbst generiert - kein Bezug zu echten Kundendaten.

Wie es funktioniert

Ein kombinierter Call statt zwei getrennter

Klassifikation und Extraktion laufen in einem Claude-Aufruf: der Prompt kennt alle drei Schemas und liefert direkt {"doc_type": ..., "fields": {...}} zurück - spart einen kompletten Roundtrip gegenüber getrennten Calls. Das Routing (welches Schema validiert?) passiert danach im Python-Code.

Kein OCR/Textract

Die Testdokumente sind maschinenlesbarer Text/PDF, kein gescanntes Bildmaterial. Die Lambda liest den Text direkt aus S3 bzw. extrahiert ihn aus dem PDF - eine Bild-zu-Text-Stufe wäre hier zusätzlicher Aufwand ohne Mehrwert.

Fehlerfälle sind sichtbar, nicht stumm

Schlägt der Claude-Call fehl, passt die Antwort nicht ins Schema oder ist doc_type: "unknown", schreibt die Lambda trotzdem einen Datensatz mit status: "failed" statt abzustürzen. Das Dashboard zeigt das genauso an wie Erfolge.

Architektur

Ein S3-Upload triggert automatisch die Verarbeitung - das ist der serverlose, event-getriebene Kern.

Streamlit-Appfragt Presigned-URL an
API Gateway+ Lambda get_upload_url
S3 BucketDatei-Upload (PUT direkt)
Lambda process_documentObjectCreated-Event-Trigger
Claude APIklassifizieren + extrahieren
DynamoDBErgebnis inkl. Fehlerfälle

Rückweg: Die Streamlit-App fragt die Ergebnisliste über API Gateway → Lambda list_documents → DynamoDB per HTTP ab und zeigt sie live an.

infra/ # Terraform: s3, dynamodb, lambda, api_gateway, variables, outputs
src/pipeline/lambdas/process_document.py # S3-Event-Handler: laden -> Claude-Call -> validieren -> DynamoDB
src/pipeline/lambdas/get_upload_url.py # Presigned-URL erzeugen
src/pipeline/lambdas/list_documents.py # DynamoDB scannen/zurückgeben
src/pipeline/schemas.py # Pydantic: Invoice, BusinessCard, ContractSnippet
src/pipeline/prompts.py # Klassifikations-/Extraktions-Prompt
streamlit_app/app.py # Upload-UI + Ergebnisliste
sample_documents/ # synthetische Testdokumente (3 Typen)
tests/ # moto-/Mock-basiert, kein AWS/API-Key nötig

Tech-Stack

Cloud-ComputeAWS Lambda (Python 3.12) - serverlose Ausführung, kein eigener Server
StorageAWS S3 - Dokumenten-Upload, Event-Trigger
DatenbankAWS DynamoDB - strukturierte Ablage der Extraktionsergebnisse
APIAWS API Gateway (HTTP API) - öffentliche Endpunkte für Upload-URL + Ergebnisliste
IaCTerraform - reproduzierbares, versioniertes Infrastruktur-Setup
LLMAnthropic Claude (Haiku) - Dokumenttyp-Klassifikation + Feldextraktion
ValidierungPydantic v2 - Schema-Validierung der LLM-Ausgabe pro Dokumenttyp
FrontendStreamlit - Upload-UI + Ergebnis-Dashboard
Testspytest + moto - AWS-Verhalten ohne echtes AWS-Konto testbar (35 Tests)
Projektseiten-HostingGitHub Pages (diese Seite - self-contained, kein CDN)

Kostenschätzung

Kein dauerhaft laufender Server, keine Grundgebühr - Kosten entstehen nur pro Nutzung.

≈ 0 €
Lambda / DynamoDB / API Gateway
Cent-Bereich
Claude-API-Call pro Dokument (Haiku)
vernachlässigbar
S3-Speicher (wenige MB Testdokumente)

Zum Aufräumen nach dem Ausprobieren: terraform destroy im infra/-Verzeichnis entfernt alle angelegten AWS-Ressourcen wieder vollständig.

Weiterführende Dokumentation

Limitierungen