AnatoBot / README.md
stevafernandes's picture
Upload 10 files
191750c verified
|
Raw History Blame Contribute Delete
6.37 kB

A newer version of the Gradio SDK is available: 6.30.0

Upgrade
metadata
title: Creighton Anatomy Learning Platform
colorFrom: blue
colorTo: blue
sdk: gradio
sdk_version: 5.49.1
python_version: '3.10'
app_file: app.py
pinned: false

Creighton Anatomy Learning Platform

A chat-based anatomy tutor grounded in the course lecture slides. Answers, quizzes, and clinical correlations cite the lecture and slide they come from, and the slide viewer renders the cited pages directly from the lecture PDFs.

  • Students sign in with a user ID and email (new users create an account with the same two fields). Accounts, every chat message, time spent on the site, and every button click are stored in Supabase, and a returning student sees their earlier questions and answers again.
  • Every request is answered from the slides first. When the slides do not cover it, the tutor looks the topic up on TeachMeAnatomy and Kenhub and answers from those articles instead. Every answer ends with a Source line naming the slides or the article pages it came from. The tutor never answers from its own knowledge.
  • Articles are looked up per anatomical structure: a question about the knee and the ankle gets the knee joint and ankle joint articles, and a page is never chosen because of a word such as "injury", "fracture", or "layers" alone.
  • Clinical Correlation has two sections, each citing its source: "From the lecture slides" and "From TeachMeAnatomy" / "From Kenhub" / "From TeachMeAnatomy and Kenhub" (the clinical sections of the articles about the topic's structures).
  • While the tutor works, the chat shows a "Thinking" message with a spinner that reports each step.
  • Answers are written on a background thread, so an answer is finished and saved even when the student's connection drops while it is being written. When the connection comes back, the page reloads by itself, signs the student back in, and shows the chat with that answer; the question being typed is kept. After a Space restart the open page signs back in the same way. The sign-in is remembered only by that browser tab (sessionStorage) and used only for that automatic reload: a manual reload, a new tab or window, or a closed tab reopened by the next person on a shared computer starts at the sign-in form, and Sign out forgets it.
  • The viewer shows only the slides an answer actually rests on: slides cited in the answer and the figure slides that follow them.

Files

  • app.py - the application.
  • supabase_store.py - accounts, chat history, sessions, and click events in Supabase (standard library only).
  • web_sources.py - looks up reference articles on TeachMeAnatomy and Kenhub through their sitemaps.
  • supabase_schema.sql - the tables and analytics views; run once in Supabase.
  • verify_supabase.py - checks a Supabase project end to end with a throwaway account.
  • test_app.py - offline tests (Gemini, Supabase, and the web are stubbed).
  • requirements.txt - Python dependencies (Gradio comes from the Space SDK).
  • Lectures/ - the lecture PDFs (Lecture #N - Title.pdf) and the logo (creighton-bluejays@logotyp.us.png, or resize.webp as a fallback) shown at the bottom of the page. Copy the folder here as-is; it is read at startup. Uploading the folder zipped as Lectures.zip next to app.py also works: the app unpacks it on first start.

Set up Supabase (once)

  1. In your Supabase project open SQL Editor, paste the contents of supabase_schema.sql, and run it. It creates anatomy_users, anatomy_messages, anatomy_sessions, anatomy_events, and two views.
  2. Copy the project URL and the service_role key from Project Settings > API. The app runs server-side, so the key never reaches a browser; the tables have Row Level Security on with no policies, so the public anon key can read nothing.
  3. Check the wiring:
export SUPABASE_URL="https://YOUR-PROJECT-REF.supabase.co"
export SUPABASE_KEY="YOUR-SERVICE-ROLE-KEY"
python3 verify_supabase.py

Analytics

  • anatomy_time_per_user - sessions and seconds on the site per user (the open tab reports every 30 s, so a session's length is last_seen_at - started_at). When a tab loses its connection (a laptop going to sleep), its session is closed; when the student comes back a new session starts, so the time away is not counted.
  • anatomy_button_clicks - clicks per user and button (ask, quiz, clinical, simplify, show_image, clear, previous, next, browse_lecture, browse_slide, example, sign_in, create_account, sign_out), plus resume when a page signed the student back in by itself after a reload or a Space restart.
  • anatomy_events holds the raw click log with a detail JSON column (question length, lecture and slide numbers); anatomy_messages holds every question and answer with its source (slides, web, slides+web for a clinical correlation from both, none, error).

Deploy to Hugging Face Spaces

  1. Create a new Space with the Gradio SDK.
  2. In the Space settings, add these secrets: GEMINI_API_KEY (your Gemini API key), SUPABASE_URL, and SUPABASE_KEY (the service_role key). Optional: a variable GEMINI_MODEL to change the model (default gemini-2.5-flash; the app falls back to gemini-3.8-flash and gemini-3.5-flash when the configured model is not available to the key).
  3. Copy the Lectures folder (or Lectures.zip) into this directory, then upload everything:
hf upload <your-username>/<space-name> . . --repo-type space --exclude "__pycache__/*" --exclude ".DS_Store" --exclude "**/.DS_Store"

PDFs larger than 10 MB are stored with Git LFS automatically. The Space indexes the slides when it starts, which takes well under a minute; the reference-site sitemaps are downloaded in the background on startup and refreshed daily.

Run locally

pip install -r requirements.txt gradio==5.49.1
export GEMINI_API_KEY=your_key
export SUPABASE_URL=https://YOUR-PROJECT-REF.supabase.co
export SUPABASE_KEY=YOUR-SERVICE-ROLE-KEY
python app.py

Set LECTURES_DIR to point at the lecture folder if it is not next to app.py. Run the offline tests with:

LECTURES_DIR=/path/to/Lectures GEMINI_API_KEY=test python -m unittest -v test_app