Rendered notebook
Generated from 04_rag_compliance.ipynb. Run it yourself with
make docs-up — see Run locally.
04 — RAG over compliance regulations¶
We build a tiny RAG pipeline over a few snippets of made-up bank compliance text. This stays offline (no API keys) by using the HashingEmbedder and InMemoryVectorStore from apogee-ai-rag.
In production, globaltrust-bank swaps the in-memory store for QdrantVectorStore (already provisioned via apogee add:qdrant).
04_rag_compliance.ipynb · cell 1
import asyncio
from apogee_ai_rag import (
Document,
EchoGenerator,
HashingEmbedder,
IngestionJob,
InMemoryVectorStore,
PipelineSpec,
RagFactory,
RagQuery,
RagType,
RecursiveTextChunker,
)
04_rag_compliance.ipynb · cell 2
REGULATIONS = [
Document(id='aml-1', text='Customer due diligence requires identity verification before opening any account.'),
Document(id='aml-2', text='Transactions over USD 10,000 must be reviewed by a compliance officer within 24 hours.'),
Document(id='kyc-1', text='KYC documents must be re-validated annually for high-risk customers.'),
Document(id='fx-1', text='Cross-border transfers require specifying purpose code and recipient address.'),
Document(id='priv-1', text='Customer data is retained for 5 years after account closure for regulatory purposes.'),
]
# Every component here is offline: HashingEmbedder needs no model download and
# EchoGenerator echoes the retrieved context instead of calling an LLM.
spec = PipelineSpec(
chunker=RecursiveTextChunker(chunk_size=200, chunk_overlap=20),
embedder=HashingEmbedder(dims=256),
vector_store=InMemoryVectorStore(),
generator=EchoGenerator(),
)
pipeline = RagFactory.build(RagType.NAIVE, spec)
await pipeline.ingest(IngestionJob(documents=REGULATIONS))
print(f'Ingested {len(REGULATIONS)} regulations.')
04_rag_compliance.ipynb · cell 3
questions = [
'What is required when opening a new account?',
'How long do we keep customer data after closure?',
'Quem revisa transações grandes?',
]
for question in questions:
response = await pipeline.run(RagQuery(text=question, top_k=2))
top = response.sources[0].chunk.text if response.sources else '—'
print(f'\nQ: {question}\nTop source: {top}')
In production¶
- Replace
HashingEmbedderwithOpenAIEmbedderorBgeEmbedderfor real semantic similarity. - Replace
InMemoryVectorStorewithQdrantVectorStore(theglobaltrust-bankcompose already has Qdrant). - Wrap
raginside anapogee-aiagent (compliance officer) that decides when to retrieve and how to phrase the answer. - Per-language indexes: ingest the same regulations translated into EN/PT/ES/ZH and route queries by
customer.preferred_language.