UBCHelper / src /router.py
Devdan Schretlen
Claude Opus 5 (1M context)
Expand the calendar corpus to every faculty, and rewrite the UI copy
fcdba1d
Raw History Blame Contribute Delete
1.82 kB
"""
Router — the "adaptive" in adaptive RAG (Phase 4).
One small function decides how much machinery a question deserves:
simple a single fact or page lookup -> the fast Phase-2 retriever
complex needs several pages, a -> the agentic loop (decompose ->
comparison, or multi-step reasoning multi-hop retrieve -> synthesize)
The classification is a cheap zero-shot LLM call reusing the generation backend, so there
is no extra model to configure. Anything the model returns other than a clear "complex"
falls back to "simple" — the cheaper path is the safe default, so a misparse never sends a
simple question down the expensive agent.
"""
from __future__ import annotations
from . import generate, trace
CLASSIFY_SYSTEM = (
"You are a query router for a UBC academic-calendar Q&A system. Classify the user's "
"question as either 'simple' or 'complex'.\n"
" simple: answerable from one calendar page (a single course's prerequisites or "
"description, one program's requirements, one policy or date).\n"
" complex: needs multiple courses or programs, a comparison (between programs, "
"student cohorts, or calendar editions), or a prerequisite/requirement chain "
"(e.g. 'compare X and Y', or 'what do I need to take before Z').\n"
"Reply with exactly one word: simple or complex."
)
def classify(question: str) -> str:
"""Return "simple" or "complex" for `question`. Defaults to "simple" on any surprise."""
trace.step("ROUTE - classify (simple vs complex)")
reply = generate.complete(CLASSIFY_SYSTEM, question, purpose="route").strip().lower()
route = "complex" if "complex" in reply else "simple"
trace.event("route", decision=route, raw_reply=reply)
trace.detail("decision", route)
return route