File size: 2,343 Bytes
3947185 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | """Deterministic detection of e-resource access problems.
Access problems ("I can't access ScienceDirect", "OpenAthens login keeps
failing", "how do I access databases off campus") are routed straight to the
knowledge-base RAG path. Requests for a specific article's full text stay on
the full-text chain. Kept separate from constants.py so it has no dependencies
and can be tested on its own.
"""
import re
# Unambiguous access/authentication cues. Context-dependent words (remote,
# VPN, off campus) only count next to an access or sign-in verb, so research
# topics such as "remote sensing" or "VPN security" are not misrouted.
ACCESS_PROBLEM_RE = re.compile(
r"\b("
r"openathens|single sign.?on"
r"|access (denied|error|issue|problem)s?"
r"|(asks?|asking|wants?) me to (pay|purchase|buy|subscribe)"
r"|(log(?:ging)?\s?(?:in|on)|sign(?:ing)?\s?in|sso)\W+(?:\w+\W+){0,4}(fail\w*|error|problem|issue|loop\w*|not working|keeps)"
r"|(off[\s-]?campus|remote(ly)?|from home|outside (the )?campus|vpn)\W+(?:\w+\W+){0,4}(access\w*|log(?:ging)?\s?(?:in|on)|sign(?:ing)?\s?in)"
r"|(access\w*|log(?:ging)?\s?(?:in|on)|sign(?:ing)?\s?in)\W+(?:\w+\W+){0,4}(off[\s-]?campus|remote(ly)?|from home|outside (the )?campus)"
r"|(link|database|platform|e-?resource)s?\W+(?:\w+\W+){0,3}(not working|broken|down|dead)"
r")\b",
re.IGNORECASE,
)
# "can't access X", "trouble logging in to X", "problem opening X"
ACCESS_FAIL_RE = re.compile(
r"\b(can.?t|cannot|unable to|not able to|couldn.?t|trouble|problems?|issues?|lost)\b"
r"\W+(?:\w+\W+){0,3}(access\w*|log(?:ging)?\s?(?:in|on)|sign(?:ing)?\s?in|connect\w*|open\w*)\b",
re.IGNORECASE,
)
ARTICLE_CUE_RE = re.compile(r"\b(pdf|full.?text|articles?|papers?|chapters?)\b", re.IGNORECASE)
# Extra tokens appended to the retrieval query so BM25 reliably surfaces the
# access-troubleshooting and remote-access chunks alongside any resource chunk.
ACCESS_RETRIEVAL_HINT = "access troubleshooting sign in remote access electronic resources"
def _is_access_problem(question: str) -> bool:
q = question or ""
if ACCESS_PROBLEM_RE.search(q):
return True
# "can't access ScienceDirect" is a platform problem;
# "can't access this article" is a full-text request.
return bool(ACCESS_FAIL_RE.search(q)) and not ARTICLE_CUE_RE.search(q)
|