Two LangChain retrieval demos: a FastAPI/LangServe service that answers questions about a company's rules and screens emails for phishing, and a notebook that answers questions about a SQL database by writing and running the query itself.
Both halves are built on the same idea — put real context in front of the model instead of trusting it to remember.
The service (app/) exposes two chains. /rules is a classic RAG pipeline: rules.txt is chunked, embedded with a local MiniLM model, stored in Chroma, and the chunks most relevant to your question are handed to Gemini 1.5 Flash along with the rlm/rag-prompt template from LangChain Hub. /emailchecker sends an email body through a local Ollama llama3.1 with a prompt that asks for nine phishing checks, each answered true/false with an English and an Arabic justification, returned as one JSON object.
The notebook (notebooks/sql_rag.ipynb) does retrieval over a database instead of documents: it feeds the live Chinook schema to Gemini, has it write a SQL query, runs that query, then feeds the schema, question, query and result back to Gemini to phrase an answer in plain English.
- Rules Q&A (
/rules) — RAG overapp/rules.txtwith MiniLM embeddings, a Chroma vector store, and Gemini 1.5 Flash. - Phishing checker (
/emailchecker) — nine checks (grammar, urgency, call-to-action, confidential-info requests, phishing phrases, fake alerts, fake offers, personalization, suspicious character encoding), each with a bilingual justification, run against a local Ollama model. - Two ways to call each chain — LangServe's interactive playground (
/rules/playground,/emailchecker/playground) and plain JSON endpoints (POST /api/rules,POST /api/emailchecker). - Text-to-SQL (
notebooks/sql_rag.ipynb) — schema → generated SQL → executed query → natural-language answer, over the Chinook sample database. - Containerized — Dockerfile and Compose file for the service.
Python · FastAPI · LangServe · LangChain · Chroma · sentence-transformers (all-MiniLM-L6-v2) · Google Gemini 1.5 Flash · Ollama (llama3.1) · MySQL · Docker
Prerequisites
- Python 3.11+
- A Google AI Studio API key (for the
/ruleschain and the notebook) - Ollama with
llama3.1pulled (for/emailchecker):ollama pull llama3.1 - MySQL, only for the SQL notebook
Install
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtConfigure
Both GOOGLE_API_KEY and DATABASE_URL are read straight from the environment. Copy the template and fill it in:
cp .env.example .env
export $(grep -v '^#' .env | xargs)Run
uvicorn app.server:app --reload --port 8000Open http://localhost:8000/rules/playground to ask about the rules, or http://localhost:8000/emailchecker/playground to screen an email.
With Docker
docker compose up --buildThe Compose file passes GOOGLE_API_KEY through from your shell. Note that /emailchecker calls Ollama on localhost, which inside a container means the container itself — so that endpoint needs Ollama reachable from the container to work.
curl -X POST http://localhost:8000/api/rules \
-H 'Content-Type: application/json' \
-d '{"text": "What is the latest I can arrive?"}'{ "response": "You have to come in by 10:30 am." }curl -X POST http://localhost:8000/api/emailchecker \
-H 'Content-Type: application/json' \
-d '{"text": "URGENT: verify your account within 24 hours or it will be suspended."}'Returns one JSON object per check, e.g.:
{
"urgencyCheck": {
"result": true,
"english_justification": ["The email demands action within 24 hours."],
"arabic_justification": ["يطالب البريد باتخاذ إجراء خلال 24 ساعة."]
}
}The tests exercise the live API, so start the server (and Ollama) first. They skip themselves if nothing is listening on port 8000.
python -m unittest discover testsapp/
server.py FastAPI app: routes, the phishing-check prompt, the Ollama model
rag.py the /rules RAG chain (chunk → embed → Chroma → Gemini)
rules.txt the company rules the /rules chain retrieves over
notebooks/
rules_rag.ipynb the RAG chain, built up step by step
sql_rag.ipynb text-to-SQL over Chinook
data/
Chinook_MySql.sql sample database for the SQL notebook
tests/
test_api.py end-to-end tests against /api/emailchecker
Load the sample database, then point DATABASE_URL at it:
mysql -u root -p < data/Chinook_MySql.sql