Public Library Systems · Reference Librarians
Automating Library Reference Query Routing with Intent Classification
Librarians must manually sort incoming reference queries into specialized department queues. This example demonstrates how to automate routing decisions by classifying queries into specific archival or research departments.
Updated · Examples verified with jev-1.13.0
The problem
Public library systems receive diverse user queries that often span multiple subjects. Manual sorting results in frequent misrouting of interdisciplinary requests and increased administrative overhead. The application must analyze the query text and provide a consistent department selection to trigger an automated ticketing system update.
How TypeSafe helps
The application sends user queries as 'state' and uses the 'dept_routing' Choice question to categorize intent. When the API returns a 'choice' value like 'genealogy' or 'digital_media', your application code interprets the returned string to map the ticket to the corresponding internal database queue. If the API returns 'manual_review', your code can trigger an escalation flow to alert a human librarian. You can implement custom logic to verify the 'confidence' level before taking action, such as automatically routing high-confidence results while holding lower-confidence classifications for secondary review.
- Input
- A user-submitted query text string regarding research assistance.
- Decision
- Choice: Map the input to a specific department (e.g., genealogy, digital-media, technical-services) or route to manual review.
- Next action
- Downstream code updates the ticketing system status and routes the request to the chosen department queue.
Three verified examples
These responses were returned during a previous API verification. New probabilities can differ.
Standard Genealogy Request (primary)
Expected behavior: The query specifically mentions birth records and family history, mapping directly to the genealogy department.
Input
I need help finding birth records for my grandfather, born in 1920 in Chicago.Previous verification response
jev-1.13.0 ·
{
"model": "jev-1.13.0",
"answers": {
"dept_routing": {
"type": "choice",
"choice": "genealogy",
"probabilities": {
"manual_review": 0,
"technical_services": 0,
"digital_media": 0,
"genealogy": 1
},
"confidence": 1
}
},
"usage": {
"input_tokens": 385,
"output_tokens": 53
}
}Equipment reservation request (alternative)
Expected behavior: The request for 3D printer equipment falls under the purview of digital media services.
Input
Can I reserve the 3D printer for a session on Saturday?Previous verification response
jev-1.13.0 ·
{
"model": "jev-1.13.0",
"answers": {
"dept_routing": {
"type": "choice",
"choice": "digital_media",
"probabilities": {
"manual_review": 0.04,
"genealogy": 0,
"technical_services": 0.01,
"digital_media": 0.95
},
"confidence": 0.93
}
},
"usage": {
"input_tokens": 379,
"output_tokens": 53
}
}Punctuation-only query (edge case)
Expected behavior: The punctuation-only input contains no reference question; the expected label is manual_review.
Input
...Previous verification response
jev-1.13.0 ·
{
"model": "jev-1.13.0",
"answers": {
"dept_routing": {
"type": "choice",
"choice": "manual_review",
"probabilities": {
"digital_media": 0,
"technical_services": 0,
"genealogy": 0,
"manual_review": 1
},
"confidence": 1
}
},
"usage": {
"input_tokens": 366,
"output_tokens": 53
}
}Try online
Start with a verified example, edit the request, then ask Jev. A live request is sent only when you press Try online.
Expected behavior: The query specifically mentions birth records and family history, mapping directly to the genealogy department.
Use non-sensitive test data. Live input goes to typesafe.pro and TypeSafe. Anonymous requests use the gateway’s free rate limit.
The best-fitting label
Probabilities compare your labels. Confidence describes how decisive the model is, not whether it is correct.
import jsonfrom urllib.error import HTTPError, URLErrorfrom urllib.request import Request, urlopenBASE_URL = "https://api.typesafe.pro"payload = { "model": "jev-latest", "state": "I need help finding birth records for my grandfather, born in 1920 in Chicago.", "questions": { "dept_routing": { "type": "choice", "instructions": "Determine the appropriate department for this library query.", "criteria": { "genealogy": "Requests for family history and vital records", "digital_media": "Requests for access to media equipment or digital archives", "technical_services": "Requests for cataloging or procurement assistance", "manual_review": "Unclear or interdisciplinary requests", }, }, },}request = Request( f"{BASE_URL}/v1/systemone", data=json.dumps(payload).encode("utf-8"), headers={"Content-Type": "application/json"}, method="POST",)try: with urlopen(request, timeout=20) as response: result = json.load(response)except HTTPError as error: raise SystemExit(f"API returned HTTP {error.code}") from errorexcept URLError as error: raise SystemExit(f"Connection failed: {error.reason}") from errorprint(json.dumps(result["answers"], indent=2))Limitations and review
- A single Choice question provides only one classification label, though you can support multi-label workflows by defining additional independent questions within the same request.
- The API's output is an observed judgment based on provided criteria and does not constitute a rigid guarantee of accuracy for all future inputs.
Set thresholds against your own examples before relying on an automated decision.