AnatoBot / README.md
stevafernandes's picture
Upload 10 files
191750c verified
|
Raw History Blame Contribute Delete
6.37 kB
---
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](https://teachmeanatomy.info/) and
[Kenhub](https://www.kenhub.com/en/library/education/the-human-anatomy) 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:
```bash
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:
```bash
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
```bash
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:
```bash
LECTURES_DIR=/path/to/Lectures GEMINI_API_KEY=test python -m unittest -v test_app
```