02 / Selected work
Applied AI · data platform
Intelligent collections agent
Master's thesis system combining an empathetic collections chat with a Bronze → Silver → Gold pipeline and a metrics dashboard. Runnable demo — not a client deployment.
Python · FastAPI · Azure OpenAI · PySpark · PostgreSQL · Streamlit · Docker · GitHub Actions

Context
This is my Trabajo de Fin de Máster for the Master’s in Big Data and Data Engineering at Universidad Complutense de Madrid (with Ntic Master), 2024–2025. The repository is public. It is a demonstration system, not a bank or client deployment.
The domain — digital collections, promises to pay, conversation outcomes — overlaps with later work in financial-services analytics. The thesis is independent of any employer.
Problem
Collections conversations are messy: people already paid, they need time, they refuse, they promise. A useful system has to (1) talk with context, (2) persist what happened, and (3) turn those traces into metrics someone can inspect. Chat without Gold leaves operations blind. A dashboard without a conversation leaves the numbers ungrounded.
Architecture
The recovered local run follows this loop:
- A WhatsApp-style chat UI talks to FastAPI.
- The agent uses Azure OpenAI when configured, otherwise a deterministic / heuristic fallback (that is how this capture was produced — no paid API).
- Events land in Bronze (JSONL). Demo scripts also fill Silver / Gold CSVs so Streamlit has a surface to read.
- Streamlit serves KPIs from Gold.
Serving is split: HTTP on :8000 (chat, /agent/reply, /docs, /health) and dashboard on :8501.

Data / inputs
Nothing here is a real debt book. scripts/generate_demo_data.py builds 200 synthetic conversations (seed 42) for Silver/Gold. scripts/generate_synthetic.py seeds a tiny debtor catalog. A live chat turn appends to data/bronze/events.jsonl.
PostgreSQL is in the documented stack; the recovered demo does not require it. Chat persistence to Postgres is best-effort and is swallowed if the database is down.
Demo environment · synthetic data

Engineering decisions
- Layered processing, not a single notebook. Bronze stays recoverable; Gold is what a human should stare at.
- API as the product surface. FastAPI owns conversation stages and intents; the LLM is optional. The recovered run proves the product still talks without Azure.
- PySpark is documented; the demo Gold path used here is pandas CSV. That is honest about what was actually executed for these screenshots.
- Docker + GitHub Actions exist in the repo. Compose currently ships the API image, not the full chat + Streamlit + Postgres stack.
- No bank or CRM integration in v1.

Implementation
Python 3.11 package: app/core, app/llm, app/routers, app/services, plus dashboard/ and scripts/. Local recovery used Python 3.12, requirements.txt, demo data scripts, uvicorn, and Streamlit — no source changes.
Challenges
- Keeping conversation state without pretending this is core banking.
- Generating demo data that still exercises Bronze → Gold without confidential accounts.
- Drawing a hard line between KPI definitions and numbers I will not sell as production lift.
Results
What I can stand behind:
- A recovered RUNNING demo: chat UI, FastAPI, Streamlit, Bronze events from a live turn, Gold CSVs from the generator.
- Layered data design and a listed KPI vocabulary (conversations, promise rate, promised amount, debt).
- CI, Docker files, tests, and a distributable package name in the repo.
What I will not claim: a production recovery lift, cash collected, or that this ran on real customer books. Azure GPT replies were not used for these captures.
What I learned
A collections agent you cannot inspect in Gold is just a chat window. The interesting loop is conversation in → structured outcome → a metric someone can distrust.
I also learned to keep employer work and thesis work in separate sentences. Same industry instincts; different artifacts.
Stack
Python, FastAPI, optional Azure OpenAI, pandas (demo Gold), PySpark (documented), Streamlit, Docker, GitHub Actions.