One shared chat API behind the family of OHM ruler galleries. Each gallery is a
static GitHub-Pages site that publishes its people as
<base>/data/rulers/<id>.json; this service grounds an in-character avatar
on that published record and answers through an OpenAI-compatible model.
It replaces the per-repo chat/ stubs that used to live inside each gallery.
Served at chat.people.ofthepast.org (Vercel). It never fabricates history:
the grounding is the harvested record, and a missing key/model returns a clear
503 instead of an invented reply.
| key | gallery | voice |
|---|---|---|
rome |
rulers.ofancientrome.org | imperial Roman |
egypt |
rulers.ofancientegypt.org | Lord of the Two Lands |
past |
rulers.ofthepast.org | a ruler of your own age |
Add one in avatars/sites.py (base URL + manner) — no per-site code.
GET / health + whether the model is configured
GET /sites the site keys served
GET /chat/{site}/{id}/persona the exact grounding system prompt (preview/debug)
POST /chat/{site}/{id} {"messages":[{"role","content"}]} -> {"reply"}
{site} is a key above; {id} is the gallery's own slug (e.g. cleopatra,
augustus). The service fetches <base>/data/rulers/{id}.json, builds the
grounding prompt (shared core + the site's manner), and calls the model.
Only the SDK is fixed; endpoint and model are set via env:
| var | required | meaning |
|---|---|---|
OPENAI_API_KEY |
to answer | key for the OpenAI-compatible endpoint |
OPENAI_BASE_URL |
no | any OpenAI-compatible endpoint; blank = api.openai.com |
CHAT_MODEL |
to answer | model id to call (no default baked in) |
SITE_BASE_<KEY> |
no | override a gallery's base URL (local tests / DNS rollout) |
No host Python needed.
docker build -t avatars .
# health + persona grounding (no key required); point egypt at its live origin:
docker run --rm -p 8000:8000 \
-e SITE_BASE_EGYPT=https://openhistorymap.github.io/rulers.ofancientegypt.org \
avatars
curl localhost:8000/
curl localhost:8000/chat/egypt/cleopatra/persona
# a real answer: add your endpoint + model
docker run --rm -p 8000:8000 \
-e OPENAI_API_KEY=sk-... -e CHAT_MODEL=... -e OPENAI_BASE_URL=... \
avatars
curl -s localhost:8000/chat/egypt/cleopatra \
-H 'content-type: application/json' \
-d '{"messages":[{"role":"user","content":"Tell me of Actium."}]}'@vercel/python serves the ASGI app exported by api/index.py; vercel.json
rewrites all paths to it. Set OPENAI_API_KEY / CHAT_MODEL (and optionally
OPENAI_BASE_URL) in the Vercel project, and map the domain
chat.people.ofthepast.org to it.