DEV Community

Cover image for ๐Ÿค– Building an AI Compliance Assistant with Hugging Face, RAG & Observability on AWS
Limani Ndou
Limani Ndou

Posted on

๐Ÿค– Building an AI Compliance Assistant with Hugging Face, RAG & Observability on AWS

I Built an AI Compliance Assistant That Runs Entirely on My Own GPU โ€” Here's What I Learned

Combining RAG, local LLM inference, Terraform-provisioned AWS infrastructure, and full-stack observability to make South African financial regulation searchable


If you've ever worked anywhere near banking compliance, you know the feeling: somewhere in a 200-page guidance note is the exact clause you need, and you have no idea which page it's on ๐Ÿ“„๐Ÿ”. South African financial institutions operate under a dense stack of regulation โ€” AML, CTF, CPF, the FIC Act, cross-border EFT reporting, Prudential Authority requirements โ€” and most of it lives in long, technical PDFs that don't search well.

So I decided to build something that could actually answer compliance questions, grounded in real regulatory text, running on infrastructure I control end to end ๐Ÿ› ๏ธ. No black-box SaaS API calls to a third-party model โ€” the LLM inference happens locally, on my own GPU, provisioned entirely with Terraform โš™๏ธ, and I can watch every request move through the system in real time.

This is the story of building Compliance RAG ๐Ÿค–: a Retrieval-Augmented Generation platform for South African regulatory intelligence, with local GPU inference, a vector database, infrastructure-as-code, and a full observability stack behind it.


๐Ÿงฉ The Problem

South African banks have to navigate obligations spanning:

  • Anti-Money Laundering (AML) and Counter-Terrorist Financing (CTF/CPF)
  • Customer Due Diligence and risk-based approaches
  • Cross-border electronic funds transfers and international reporting
  • FIC Act implementation requirements
  • Rules for representative offices of foreign banking institutions

A compliance officer might ask something like "What information must a bank obtain when conducting customer due diligence?" โ€” a completely reasonable question with an answer buried somewhere in a Guidance Note. Traditional keyword search either misses the context entirely or returns ten tangentially related pages ๐Ÿ˜ฉ. What's actually needed is a system that understands the question, retrieves the relevant passages, and answers using only what's actually in the source documents โ€” no hallucinated legislation, no invented penalties.

๐Ÿ’ก The Solution: Retrieval-Augmented Generation, Self-Hosted

The core idea behind RAG is simple: instead of asking a language model to answer from memory (where it might confidently make things up), you retrieve the most relevant chunks of real source documents first, and then ask the model to answer using only that retrieved context.

Here's the pipeline I built:

PDF โ†’ Document Loader โ†’ Text Splitting โ†’ Embeddings โ†’ ChromaDB
    โ†’ Similarity Search โ†’ Relevant Regulatory Context โ†’ Gemma โ†’ Answer
Enter fullscreen mode Exit fullscreen mode

Regulatory PDFs โ€” the ML/TF/PF Sector Risk Assessment, Guidance Note 7B on the FIC Act, Guidance Note 8 on EFTs, and documentation on representative offices of foreign banks โ€” are stored in an S3 "compliance document vault" ๐Ÿชฃ, ingested, chunked, embedded, and stored in ChromaDB for similarity search.

S3 Bucket
The regulatory document vault in S3 โ€” each PDF is a primary source, ingested and re-embedded whenever it's updated.

When a question comes in, the system retrieves the most relevant chunks and passes them, along with the question, to a locally-hosted Google Gemma 2 2B IT model for generation. I picked Gemma 2 2B specifically because it's small enough to run comfortably on a single GPU without breaking the bank, while still being capable enough to follow strict grounding instructions โ€” exactly the tradeoff a self-hosted compliance tool needs ๐ŸŽฏ. Running the model locally rather than calling an external API meant provisioning real GPU infrastructure.

๐Ÿ—๏ธ Provisioning It All With Terraform

I didn't want to click around the AWS console to spin this up โ€” I wanted it reproducible, versioned, and destroyable in one command. So every piece of AWS infrastructure โ€” the GPU-enabled EC2 instance, the VPC, security groups, IAM roles, and the S3 bucket โ€” is defined and deployed with Terraform ๐Ÿงฑ.

cd infrastructure
terraform init
terraform plan
terraform apply
Enter fullscreen mode Exit fullscreen mode

One terraform apply and I have a fully networked, GPU-ready EC2 instance with the right IAM permissions to talk to S3 โ€” no manual setup, no configuration drift, and a clean terraform destroy when I don't want to pay for idle GPU time ๐Ÿ’ธ.

EC2
A g5.xlarge EC2 instance with an NVIDIA A10G GPU โ€” provisioned by Terraform, running 24/7, hosting the entire Dockerized stack.

๐Ÿ–ฅ๏ธ What It Looks Like in Practice

The frontend is a React/Vite chat interface I called the "Enterprise Regulatory Advisor." I wanted answers that weren't just fluent-sounding text โ€” they needed to cite exactly where in the source documents they came from, so a compliance officer could go verify it themselves in seconds โœ….

UI
Asking "What information must a bank obtain when conducting customer due diligence?" Notice the "AI Engine: Gemma-2 Active" status in the sidebar ๐Ÿค– โ€” the model answers only from retrieved context, and โ€” critically โ€” flags when the source text doesn't specify something, rather than filling in the gap itself. Every answer comes with verified source references down to the page number.

That last detail mattered a lot to me. The system prompt explicitly instructs the model to avoid inventing legislation, requirements, penalties, or dates, and to say plainly when the answer isn't in the available documents. In a compliance context, a confident wrong answer is worse than no answer at all โš ๏ธ.

๐Ÿ“ก Watching the System Think: Observability

Running your own LLM infrastructure means you can't just trust that it's "working" โ€” you need to actually see what's happening under the hood ๐Ÿ”ฌ. I instrumented the entire FastAPI backend with OpenTelemetry, exporting traces and metrics through an OTEL Collector to Prometheus, Grafana, and Jaeger.

Prometheus
Prometheus querying metrics scraped from the OTEL Collector โ€” request durations, active requests, histogram buckets, all labeled and queryable.

Prometheus gives me the raw metrics โ€” request rates, latency histograms, active request counts ๐Ÿ“Š โ€” and Grafana turns those into dashboards I can actually read at a glance.

Grafana
A live Grafana dashboard built on the Metrics Drilldown view โ€” request duration buckets, throughput, and payload sizes updating in real time.

And when I need to understand why a specific request was slow โ€” was it the embedding step, the ChromaDB similarity search, or the Gemma generation itself? โ€” Jaeger gives me the full distributed trace ๐Ÿ”Ž.

Jaeger
Jaeger tracing individual API calls through the RAG pipeline, down to the microsecond.

This turned what could have been a black box into something genuinely observable โ€” I can see request rate, latency percentiles, GPU health, and trace-level detail on any single query.

๐Ÿงฐ The Stack, End to End

  • ๐Ÿ Backend: Python, FastAPI, LangChain, ChromaDB, PyTorch, Hugging Face Transformers
  • ๐Ÿค– AI/ML: Google Gemma 2 2B IT, local GPU inference on an NVIDIA A10G
  • โš›๏ธ Frontend: React + Vite
  • ๐Ÿ“ˆ Observability: OpenTelemetry, Prometheus, Grafana, Jaeger
  • โ˜๏ธ Infrastructure: AWS EC2 (GPU) + AWS S3, provisioned with Terraform, containerized with Docker Compose, with Kubernetes/Helm manifests for scaling out
  • ๐Ÿš€ CI/CD: GitHub Actions

Everything runs in Docker Compose for local/single-instance deployment, with a parallel Helm chart if I ever need to move this onto Kubernetes โ€” and every underlying AWS resource traces back to a Terraform module, not a manual console click.

๐ŸŽ“ What I Learned

Grounding is everything. ๐ŸŽฏ The hardest part wasn't wiring up the pipeline โ€” it was getting the prompt-level guardrails right so the model would refuse to speculate. A 2B parameter model is small enough to run affordably on a single GPU, but it also means you have to be deliberate about keeping it on a short leash: retrieved context in, grounded answer out, and an honest "not found" when the documents don't say.

Infrastructure-as-code pays for itself fast. ๐Ÿ—๏ธ Provisioning the GPU instance, networking, and S3 vault with Terraform meant I could tear the whole environment down between sessions and bring it back identically an hour later โ€” a huge win for both cost control and sanity.

Observability isn't optional once you self-host. ๐Ÿ”ญ The moment you're responsible for your own inference infrastructure, "is it working?" becomes a real question you need real tooling to answer. Watching a trace waterfall through embedding โ†’ retrieval โ†’ generation taught me more about where latency actually lives than any amount of guessing would have.

Compliance AI has a very specific bar. โš–๏ธ This project is explicitly not a replacement for a compliance officer or legal advisor โ€” the disclaimer sits front and center in the docs. The goal was never "trust the AI's judgment." It was "make the source material searchable, and always show your work."

๐Ÿ”ฎ What's Next

On the roadmap: hybrid search (BM25 + vector) with cross-encoder reranking, RAGAS-based evaluation for faithfulness and retrieval precision, regulatory change detection so the vault flags when a source document gets superseded, and proper enterprise auth via Cognito/OIDC before this goes anywhere near production data.

If you're curious about the architecture or want to build something similar, the full project โ€” Terraform configs, Helm charts, ingestion pipeline, and all โ€” is open on GitHub. โญ

CODE: https://github.com/limanindou/compliance-rag
YOUTUBE DEMO PC:https://youtu.be/MgLLihgKUuc?si=GoLwfbuwJBZNLQ9c
YOUTUBE DEMO MOBILE:https://youtube.com/shorts/mRaoCBRngaY?si=RFCkVGLzyi1ohKOh


Built as an AI, cloud, and compliance engineering project focused on South African regulatory intelligence ๐Ÿ‡ฟ๐Ÿ‡ฆ. Not legal advice โš ๏ธ โ€” always verify against the latest official regulatory publications.

Top comments (0)