The face of Sean BeirnesSean Beirnes
← All work

Case study

CPAL

Canvas Personal Assistant for Learning: a RAG chatbot that answers Canvas LMS support questions with concise, cited responses.

  • Python
  • RAG
  • LLMs
  • FastAPI
  • Pinecone (Vector Database)
  • React
  • TypeScript
  • Go
  • PostgreSQL
  • Docker

See it work

Answers you can verify.

CPAL displays a cited answer to a Canvas question, with related source links below it.
CPAL answers Canvas questions concisely and links back to the guides and discussions behind each answer.

The frustration

Students and instructors click through a dozen Canvas documentation pages to answer one simple question. Every answer technically exists, but finding it means knowing which guide, which forum thread, which page.

The dig

Every Canvas question already had an answer, buried somewhere in the Instructure Community guides and forum threads. The friction wasn't missing information; it was finding the right answer quickly. With the right context, an LLM could make trusted answers much faster to find, so I built a RAG system over the sources people already trust.

The feature

Ask CPAL a Canvas question in plain language. It rewrites your question for better recall, searches an index of documentation and solved threads, and answers concisely with citations back to the original sources, so you can verify instead of trust.

How it works

Question in. Cited answer out.

  1. 1

    Extract

    A Go web scraper crawls Canvas Community guides and solved forum threads, turning them into clean Markdown with metadata.

  2. 2

    Embed

    Python chunks the corpus, generates embeddings, and stores them with metadata in Pinecone.

  3. 3

    Retrieve

    FastAPI calls an LLM to rewrite the question for better recall, runs similarity search, and reorders results to favor forum answers over questions.

  4. 4

    Answer

    The LLM synthesizes a concise Markdown answer with source links. Every Q&A is logged to Postgres for later LLM evals.

Architecture

The pieces.

Backend

FastAPI serves the API and the built frontend from one container. CAPTCHA-guarded query endpoint.

Frontend

Vite, React, and TypeScript. Ask, stream, verify: sources rendered with every answer.

Retrieval

Pinecone vector store, MiniLM embeddings, top-k search with score filtering.

LLM

Gemini for query rewriting and answer synthesis over retrieved passages.

Data pipeline

Go extractor to Python chunking to embedding generation to vector upsert. Run once to bootstrap the index.

Ops

Q&A events logged to Postgres for quality review. Single-container deploy on Fly.io.

Receipts

See for yourself.

The full source, pipeline, backend, frontend, and deploy config, is on GitHub. CPAL is archived now: Instructure redesigned the Community site and broke the extractor's assumptions. The architecture stands as a reference for how I design RAG systems.