Skip to content
Hi! I am Gab

All projects

REMAKE: RAG based phlaw chatbot

This is a remake of our RAG based phlaw chatbot capstone Research. This project using industry standard technologies for AI and automation development.

Role
AI and Automation developer
Status
Completed
Timeline
Oct 2026
Stack
FastAPI, n8n, Next.js, Python, Render, Typescript, Vercel, Pinecone, Langchain, Notion

The Problem

Philippine law students and junior legal researchers learn the law through Supreme Court decisions, and each one runs to tens of pages. The standard study aid is a case digest (Facts, Issues, Ruling, Doctrine), usually written by hand. A tool that answers questions from the decision itself, and shows the passage it used, cuts that reading time without asking anyone to trust an unsourced summary. I had already built a research version for my thesis (phlaw-chatbot: Django, Qdrant, hybrid BM25 + RRF retrieval). It worked as research, but nobody outside my machine could try it. This project rebuilds it as a small, deployed product that anyone can open in a browser, plus a no-code way for an admin to add new decisions. Why it matters: in legal research a confident wrong answer is worse than no answer. So the product had to cite its sources on every answer and decline questions it cannot answer from the decisions it holds.

My Role

Sole developer

What I Owned

I owned the whole project end to end, as a solo builder: scope, design, build, evaluation and deployment.

  • Scope and data: picked the six landmark decisions, confirmed each was real and correctly cited, and wrote the case cards against the decision text.
  • Ingestion: fetching and cleaning the decisions from lawphil.net, cutting separate opinions, section tagging, chunking and indexing in Pinecone with stable ids.
  • Backend: the FastAPI service with intent routing, the answer chains (digest, follow-up, search, definition, decline), rate limits and token-protected admin endpoints.
  • Evaluation: wrote the 20-question test set, ran it, and kept the honest result (17/20) instead of tuning the checks to pass.
  • Frontend: a small Next.js app with chat, a cases page and a link to the published digests.
  • Deployment: the public GitHub repo, the backend on Render and the frontend on Vercel, including CORS and environment setup.
  • Admin pipeline: the Notion databases and two n8n workflows that index a new decision and publish its digest page, including both the success and failure paths. I built it with an AI coding assistant: I set the direction and the rules (for example PEP 8 throughout), made the product calls, reviewed each change, debugged the integrations and ran every test and deployment myself.

Technical and Product Decisions

Every choice traded something away to keep the product free to run, grounded in the text, and small enough to ship in two days.

  • Rebuild on FastAPI, LangChain, Pinecone serverless (hosted e5 embeddings) and Groq.
    • Why: runs entirely on free tiers, with no servers or embedding model to host.
    • Cost: lost v1's hybrid BM25 search, so dense search is weak at exact rare names.
  • Six curated decisions, main opinion only.
    • Why: a small corpus I could check by hand; separate opinions would muddy answers.
    • Cost: narrow scope; anything else is declined.
  • Chunks tagged by section (facts, issues, ruling, dispositive, notes).
    • Why: lets retrieval add the dispositive part and skip footnotes.
    • Cost: tags are approximate where decisions lack headings.
  • Router: regex fast path, then a small model (gpt-oss-20b) with structured output.
    • Why: case names skip the LLM; the big model is saved for answers.
    • Cost: the router judges from short summaries and once wrongly declined an in-scope question.
  • Verify before declining: the answer model reads the best excerpt of each case.
    • Why: similarity scores overlapped (0.783 in scope vs 0.819 out of scope), so no cut-off worked.
    • Cost: one extra large-model call for every decline.
  • Rank each case separately in search.
    • Why: one long decision (41 chunks) crowded out the others.
    • Cost: six queries instead of one.
  • Every answer returns its sources; prompts allow only the excerpts.
    • Why: users can check each claim against the decision.
    • Cost: answers stay narrow and sometimes miss context.
  • Rate limits (10/min per IP, 300/day), CORS allow-list, token on admin endpoints, no public "save to Notion".
    • Why: a public demo on free quotas must not be drained or used to write into Notion.
    • Cost: heavy users hit a limit message.
  • Notion + n8n as the admin tool for adding decisions.
    • Why: a non-technical admin can add a case and watch Queued, Indexed or Failed.
    • Cost: n8n must run somewhere always on: my machine or a paid host.
  • Code node builds the Notion request as one raw JSON string.
    • Why: n8n's JSON field mangled nested objects.
    • Cost: a custom script to maintain.
  • A 20-question evaluation with honest reporting.
    • Why: shows where the system fails, not just where it works.
    • Cost: a phrase-match check cannot judge legal correctness.

Visitors only read: the API answers from Pinecone excerpts with Groq models. New decisions enter through Notion, and n8n calls the token-protected API to index them and publish a digest page.

Constraints

One person, about two days (5–6 October 2026), and a budget of zero.

  • Team: solo, with an AI coding assistant.
  • Budget: free tiers only: Pinecone Starter, Groq free tier, Render free web service, Vercel. That set the limits below.
  • Model availability: Groq retired the Llama models I planned around on its free tier, so I moved to gpt-oss-120b and gpt-oss-20b and kept model names in configuration.
  • Rate limits: Groq's per-minute token limits shaped context sizes and output caps, and needed retries in the pipeline.
  • Cold starts: Render's free service sleeps when idle; the first request can take about a minute, and early calls returned 503 until it woke.
  • Legacy: the thesis version (Django, Qdrant) was a reference, not reused code; the frontend was rebuilt from scratch.
  • Source data: lawphil.net serves Windows-1252 pages without declaring it, which corrupted quotes until I decoded it explicitly.
  • Notion API limits: about 2,000 characters per text block and 100 blocks per request.
  • Automation hosting: self-hosted n8n only runs while my machine is on; always-on needs a paid host.

Result and Impact

The app is live on free tiers, answered 17 of 20 evaluation questions correctly by its checks, and declined all 3 out-of-scope questions.

  • Shipped: backend on Render, frontend on Vercel, public repo with a README and setup guides. The index holds 304 chunks from 6 decisions.
  • Evaluation (20 questions, 5 October 2026): digests 6/6, follow-ups 2/2, topic search 2/2, definition 1/1, out of scope 3/3, specific facts 3/6.
  • Reading the 3 failures: one real miss (an answer about Oposa v. Factoran left out intergenerational responsibility); two were check mismatches, where the answer was right but the phrase match missed it (a Unicode space, and an over-strict expected word).
  • Fixes the evaluation drove: a wrong answer about electronic evidence, an incomplete list of struck-down Cybercrime Act provisions, and a party-name question that was wrongly declined were each traced and fixed before the final run.
  • Speed: answers took about 8 to 35 seconds in the evaluation, mostly free-tier model time.
  • Admin pipeline: a decision added in Notion is indexed through the deployed API and marked Indexed (48 chunks for Knights of Rizal v. DMCI Homes). A bad source link is marked Failed with its error, and a digest page is created and linked to the case.
  • Adoption: no usage metrics yet; it is a portfolio prototype, not legal advice.