--- title: LibBee emoji: 🐝 colorFrom: blue colorTo: yellow sdk: docker app_file: app.py pinned: false --- # 🐝 LibBee — KU Library AI Assistant An open-source, institution-aware AI library assistant for Khalifa University Library, Abu Dhabi, UAE. Built with FastAPI, hybrid FAISS + BM25 RAG, and live LibCal integration. **Live interface:** https://ku-library.github.io/LibBee **GitHub:** https://github.com/ku-library/LibBee --- ## Architecture - **Backend:** FastAPI + Python 3.9 (this Space) - **Frontend:** GitHub Pages (single-file HTML/JS) - **RAG:** FAISS dense + BM25 sparse + RRF fusion - **Live data:** LibCal API via Cloudflare Worker proxy - **Analytics:** Cloudflare D1 ## Secrets required Set these in the Space **Settings → Variables and Secrets**: | Secret | Description | |---|---| | `OPENAI_API_KEY` | Required for classification and answering | | `ANTHROPIC_API_KEY` | Optional — enables Claude Haiku toggle | | `PRIMO_API_KEY` | Required for PRIMO discovery search | | `ADMIN_PASSWORD` | Required for /admin dashboard | | `CLOUDFLARE_WORKER_URL` | Required for live hours/events and analytics | | `SESSION_SECRET` | Required for admin session | ## Version **v3.7** — Navigation-first agentic AI. See GitHub for changelog. ## Architecture (v3.8) The pipeline is split by stage under `src/agentcore/` - each module's docstring explains its role: | Module | Role | |---|---| | `models.py` | Pydantic I/O contracts | | `constants.py` | Regexes, URLs, prompts (no logic) | | `utils.py` | Shared helpers, LLM factory, query/URL builders | | `classify.py` | Rule pre-classifier + LLM intent classifier | | `libcal.py` | Live hours/events via Cloudflare Worker proxy | | `scholarly.py` | OpenAlex, Semantic Scholar, Crossref, Unpaywall clients | | `rendering.py` | HTML fragments (badges, trace blocks, AI-tools footer) | | `intents_library.py` | library_info handlers | | `intents_search.py` | search_academic / search_medical machinery | | `intents_general.py` | general / social handlers | | `orchestrator.py` | Injection gate, routing pipeline, analytics logging | `src/api/agent.py` is a thin router. Tests: `pytest tests/ -q` (20 tests, no API keys required). ## Environment variables (new in v3.8) | Variable | Purpose | |---|---| | `CLOUDFLARE_WORKER_TOKEN` | Bearer token for the Worker analytics surface; must equal the Worker's `ANALYTICS_TOKEN` secret | | `CONTACT_EMAIL` | Polite-pool contact sent to OpenAlex / Unpaywall / Crossref (default `library@ku.ac.ae`) | ## Privacy Before any query reaches metrics or the D1 analytics store it passes `_redact_for_analytics`: e-mail addresses and digit runs of 6+ are masked and text is truncated to 200 characters. Answer excerpts logged for the daily relevance agent get the same treatment. The Worker applies the identical redaction server-side as defence in depth.