wpl-discovery / README.md
GameTheory's picture
Update README.md
3635dde verified
|
Raw
History Blame Contribute Delete
8.01 kB
---
title: Worcestershire Libraries Live Assistant
colorFrom: green
colorTo: blue
sdk: gradio
sdk_version: 6.17.3
app_file: app.py
pinned: true
license: mit
short_description: Live, source-cited answers about your local library
tags:
- track:backyard
- sponsor:openbmb
- achievement:offgrid
- achievement:offbrand
- achievement:llama
- achievement:fieldnotes
---
# Team Members
Julian Elliott ( GameTheory )
# Worcestershire Libraries - Live Assistant
A small-model (**≤ 32B**) agent that answers real questions about Worcestershire
Libraries from official data **at every granularity** - service pages → every
page of the Hive's site → catalogue items → the individual copies on a branch's
shelf - mined live at question time wherever the source allows it.
> Built for the [Build Small Hackathon](https://huggingface.co/build-small-hackathon)
> · **Backyard AI** track. The "someone I know" is **Jack, a library resources
> manager in Worcester**, whose recurring complaint is that *the library never
> shouts loudly enough about everything it offers*. This is the megaphone.
Primary Video Demo: [Youtube](https://youtu.be/0JoOqYBQv_4)
Primary Video Demo: [Screen Studio](https://preview.screen.studio/share/Td6VxRdL?state=uploading)
Backup Video Demo: [Arcade Demo](https://app.arcade.software/share/p5cZQyn7OZUXmR6Kqxbk)
## What it does
Ask in plain English and it routes your question to a live tool, reads what comes
back from the council's own systems, and explains it:
| You ask… | It mines… | Source |
|---|---|---|
| “How do I **get** Wolf Hall?” | the item's **copy-level holdings** - which branch has it on the shelf *now*, free reservation, or the eBook on BorrowBox tonight | `wcc.ent.sirsidynix.net.uk` |
| “Do you have Harry Potter audiobooks?” | the **SirsiDynix catalogue** (books, eBooks, audio, DVDs) | `wcc.ent.sirsidynix.net.uk` |
| “What can I do at The Hive?” | **every page of the Hive's site** - archives & archaeology, 800+ study spaces, room hire, open 8:30am–10pm daily | `thehiveworcester.org` |
| “When does the mobile library visit Abberley?” | the **mobile-library timetable** (154 villages) | `worcestershire.gov.uk` |
| “What's on this week?” | **events & activities** | `worcestershire.gov.uk` |
| “How do I print from my phone?” | **Print Your Way** steps & prices | `worcestershire.gov.uk` |
Every reply carries a **“checked live just now” footer** with the tool used and a
link back to the official page.
Each answer is designed around a customer journey - what the person is trying
to do and the next action the reply must hand them. See **[JOURNEYS.md](JOURNEYS.md)**.
As a trusted hub within the local community, libraries often act as the public face for many wider council functions. They work with tight budgets and a mix of old systems, all while offering a huge range of services; everything from baby activity sessions to business support.
This simple library chatbot helps cut through this complexity by giving people one clear, modern way to get information. Instead of fighting through outdated interfaces, residents can ask questions in plain language and receive quick, accurate answers that reflect everything the library provides.
Because this low-cost tool can be built to run as a website, add-on or app, it becomes an easy, always-available point of contact. Each response can be tailored to automatically highlight related services using analytics-driven prompts, helping surface both well-used resources and lesser-known parts of the library offer. The result, a lightweight, affordable upgrade that improves access, boosts discovery, and supports libraries without requiring major system changes.
## The honest small-model fit
The model never invents library facts. The intelligence lives in the **live
retrieval**; a 7-8B model is more than enough to *route* the question and *phrase*
the answer. That's a genuine fit with the brief - not a 32B model pretending to
know a catalogue it was never trained on.
- **Model:** `meta-llama/Llama-3.1-8B-Instruct` by default, with an in-app
selector for OpenBMB MiniCPM 3 4B and Qwen 2.5 7B (set `MODEL_ID` to swap up
to any ≤32B model).
- **Graceful degradation:** with no `HF_TOKEN`, the app still works in *no-LLM
mode* - deterministic keyword routing + the raw live data. The demo never
breaks.
## The Hive, with provenance
I originally excluded thehiveworcester.org because parts of it run stale. The
re-think: **include it page-by-page, but tag every fact with its source** -
because the Hive's site is the *only* place much of Worcester's extended offer
is described (Explore the Past archives & archaeology, Europe's first joint
university+public library, 800+ study spaces, room hire, the BIPC, the Youth
Hub). The rules that keep answers trustworthy:
- every Hive fact carries its **source page + crawl date** (`hive_kb.json`,
rebuilt by `build_hive_kb.py`)
- where Hive and council pages conflict (hours, prices, membership), the
**council page wins** - and the answer says which source it used
- the Hive's own events page is static, so **live events always come from the
council site**
## Architecture
```
question ──▶ route() (LLM JSON router, keyword fallback)
library_sources.py ──▶ the granularity ladder
│ service • 87 council service pages (library_kb.json)
│ page • 57 Hive pages, exact offer (hive_kb.json)
│ item • search_catalogue() (live Atom feed)
│ copy • where_to_get() (live holdings:
│ shelf @ branch → reserve → BorrowBox tonight)
│ plus • mobile_library() · library_events()
│ • find_library() · hive_info() · printing_help()
synthesize() ──▶ warm, grounded answer + named-source footer
```
`library_sources.py` has **zero** Gradio/LLM dependencies and is independently
testable against the live sites: `python library_sources.py`.
## Run locally
```bash
pip install -r requirements.txt gradio
export HF_TOKEN=hf_xxx # optional - omit for no-LLM / offgrid mode
export TRACE_DATASET=you/wpl-traces # optional - persist usage analytics (see below)
python app.py # http://localhost:7860
# refresh the knowledge bases + graph any time:
python build_kb.py # council pages -> library_kb.json
python build_hive_kb.py # every Hive page -> hive_kb.json
python graph_build.py # both KBs -> library_graph.json
```
### No-LLM / Offgrid mode (`achievement:offgrid`)
Run **without** `HF_TOKEN` and the assistant works entirely on its own - no
external AI API call is made. A deterministic keyword router (400+ patterns)
handles every question and returns the raw live data directly. This is the
`achievement:offgrid` mode: the library data still comes from the council's
own public website, but the intelligence layer requires no third-party model
service whatsoever.
```bash
python app.py # no HF_TOKEN → keyword-only, zero AI API calls
```
The UI flags this mode clearly and all tools remain fully functional.
### Usage analytics (optional)
The Space's container is wiped on every reboot, so the local `traces.jsonl`
never accumulates. Set **`TRACE_DATASET`** (e.g. `you/wpl-traces`) with a
write-scoped `HF_TOKEN` and every turn is persisted to a **private** Hugging
Face Dataset - one small file per turn, written on a background worker so it
adds no latency and can never break an answer. Unset, it's a silent no-op.
That gives a queryable record of real behaviour to iterate on: questions that
fall through to the help text (`route.tool == "none"` - a coverage gap), turns
where the LLM router failed over to keyword matching (`route.router ==
"keyword"`), and flaky live sources (a step with `ok == false`). Questions are
user input, so the dataset is created private.
## License
MIT - © Julian Elliott ( GameTheory )