Alvaro Guzman Résumé ↓
← Work
Fintech & applied AI · professional work

AI for banking, built inside the fence.

7+ years building enterprise software for banks, payment providers and fintech: systems that move money and answer to regulators. The current focus is applied AI in regulated environments, meaning LLM capability without sending a byte to the public cloud. Employers are on the career timeline; client names stay private, and I'm happy to walk through any of it under NDA.

60+
PAYMENT APIS
integrated
0 bytes
EXTERNAL
data egress
+15%
E-COMMERCE CONVERSION
measured; checkout work contributed
7+ yrs
FULL STACK
regulated systems
Case studies

Two production systems.

Also ongoing: monolith → .NET microservices migrations in banking environments.

.NETmicroservices
Local AI lab

AI tools, run against a daemon I control.

Personal builds sitting on a local Ollama daemon. Embeddings come from mxbai-embed-large, chat from whichever model fits the task. No API keys checked into anything, no provider lock-in — the cloud bridge is opt-in via the :cloud suffix when a model is too heavy to host.

Runtime
ollama on :11434
Embeddings
mxbai-embed-large
Index
sqlite-vec, vec0 table
01

Document OCR & extraction pipeline

Active

Ingests document scans, runs OCR, then hands the raw text to a local LLM that classifies the document type and pulls out the fields that actually matter — dates, parties, totals, identifiers. Output drops into a searchable store, not a wall of unstructured text.

OCRclassifierstructured extractionollama
02

Retrieval-augmented chat, end to end

Active

The unglamorous one. Embed a corpus, store the vectors, do a kNN lookup at query time, stitch the top chunks into the prompt, send it to the model. Built to wire the moving parts together myself instead of trusting a framework — chunking, recall thresholds, and prompt budget all picked deliberately.

embeddingsvector searchprompt budgetstreaming
03

Terminal coding assistant, in Go

Active

A single Go binary that talks to the local Ollama daemon and answers from inside the shell. Streams tokens as they arrive, keeps a session buffer, and stays out of the way — no browser tab, no auth dance, no leaving the terminal to ask a small question.

goollamastreamingsingle binary
04

The Council — multi-agent deliberation

Shipped · cloud API

Four Claude personas — Philosopher, Contrarian, Romanticist, Analyst — argue a question in parallel. An Arbiter persona reads the four outputs and synthesizes a single answer. Dark grimoire UI, hand-drawn SVG avatars. Built to see if forcing disagreement produces better answers than asking one model twice. The one exception to the local-first rule: it calls the Claude API rather than the local daemon.

Reactmulti-agentClaude APISVG avatars
Posture

Local first, small models first.

local firstcloud is opt-in, not default
cloud exceptionthe council, via the claude api
no framework magicwire the pieces by hand
small models firstreach for big only when needed
ollama daemonlocal + :cloud bridge
mxbai-embed-large1024-dim, L2-normalized
sqlite-vecvec0 virtual table
go net/httpstreaming json decoder
python glueingest + write paths
// cli/chat.go — stream chat tokens straight to stdout
func stream(ctx context.Context, prompt string) error {
    body, _ := json.Marshal(map[string]any{
        "model":  cfg.Model,
        "prompt": prompt,
        "stream": true,
    })
    req, _ := http.NewRequestWithContext(ctx, "POST",
        cfg.Host+"/api/generate", bytes.NewReader(body))

    res, err := http.DefaultClient.Do(req)
    if err != nil { return err }
    defer res.Body.Close()

    dec := json.NewDecoder(res.Body)
    for {
        var chunk struct{ Response string; Done bool }
        if err := dec.Decode(&chunk); err != nil { return err }
        fmt.Print(chunk.Response)
        if chunk.Done { return nil }
    }
}