forked from ChelseaKR/fare-policy-assistant
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_domain.py
More file actions
119 lines (97 loc) · 4.64 KB
/
Copy pathtest_domain.py
File metadata and controls
119 lines (97 loc) · 4.64 KB
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
"""Domain profile abstraction (R3-3): the transit defaults are unchanged, and a
new domain is a new profile, not a pipeline edit."""
from __future__ import annotations
import re
from assistant import config, domain, guards
from assistant.domain import DomainProfile
from assistant.retrieve import AGENCY_ALIASES, detect_agencies
def test_default_profile_is_transit():
assert domain.get_profile() is domain.TRANSIT
assert domain.get_profile().name.lower().startswith("california transit")
def test_reexports_match_the_profile():
# The isolation did not change any value: the modules now read from the
# profile, and the profile holds exactly what used to be hardcoded.
p = domain.TRANSIT
assert (
config.KNOWN_AGENCIES
== p.scopes
== (
"MST",
"SBMTD",
"Yolobus",
"SacRT",
"HTA",
"E-tran",
"SCMTD",
"SolTrans",
"FAX",
"CCCTA",
"SJRTD",
"AC Transit",
"WestCAT",
"SLORTA",
"VTA",
"VINE",
"SamTrans",
"Marin Transit",
)
)
assert config.STATEWIDE_TRANSIT_INFO == p.fallback_contact
assert AGENCY_ALIASES == p.aliases
assert guards.OUT_OF_SCOPE_PATTERNS == p.scope_topics
assert set(p.scope_topics) == {"medical_advice", "immigration", "legal_advice"}
def test_detect_agencies_uses_the_active_aliases():
assert detect_agencies("senior fare on SBMTD?") == ["SBMTD"]
assert detect_agencies("Monterey to Salinas") == ["MST"]
assert detect_agencies("day pass in Vallejo") == ["SolTrans"]
assert detect_agencies("how do I pay on the Tempo?") == ["AC Transit"]
assert detect_agencies("is the Transbay bus more expensive?") == ["AC Transit"]
assert detect_agencies("light rail fare in San Jose") == ["VTA"]
assert detect_agencies("bus fare in San Mateo") == ["SamTrans"]
assert detect_agencies("does Redi-Wheels cost extra?") == ["SamTrans"]
assert detect_agencies("bus fare in San Rafael") == ["Marin Transit"]
# Word-boundary matching keeps the broad "marin" alias off lookalikes.
assert detect_agencies("is there a bus to the marina?") == []
def test_clipper_is_not_an_agency_alias():
"""A regional fare card must not resolve to the one agency that takes it.
SolTrans is the corpus's only Clipper participant, so mapping "clipper" to
SolTrans would silently turn "does Clipper work on <other agency>?" into a
SolTrans question and invite an answer the corpus cannot support. The word
is deliberately absent from the alias table; eval cases xagency-009/010 and
refuse-soltrans-001 cover the answer-side behavior.
"""
p = domain.TRANSIT
assert "clipper" not in p.aliases
assert detect_agencies("does my Clipper card work?") == []
def test_a_new_domain_is_just_a_new_profile():
# A housing-voucher assistant: different scopes, aliases, and adjacent
# topics, reusing every line of retrieve/guards/config unchanged.
housing = DomainProfile(
name="housing voucher policy",
scopes=("HACLA", "SDHC"),
aliases={"hacla": "HACLA", "los angeles": "HACLA", "san diego": "SDHC", "sdhc": "SDHC"},
fallback_contact="your local housing authority",
scope_topics={"legal_advice": re.compile(r"\b(evict|lawsuit|attorney)\b", re.I)},
)
# Detection works with the injected alias map, no code change.
assert detect_agencies("voucher rules in San Diego?", aliases=housing.aliases) == ["SDHC"]
# And the profile can be registered and selected by key.
domain.register("housing-test", housing)
assert domain.get_profile("housing-test") is housing
def test_unknown_profile_falls_back_to_transit():
assert domain.get_profile("no-such-domain") is domain.TRANSIT
def test_spanish_legal_advice_flagged():
# Multilingual guard parity (FIX-05): Spanish legal-advice phrasing is
# redirected the same way as the English "sue/lawyer" family.
check = guards.check_input("¿Puedo demandar a la agencia si me niegan el descuento?")
assert not check.ok
assert "scope:legal_advice" in check.flags
def test_spanish_abogado_flagged():
check = guards.check_input("Necesito un abogado para pelear la multa del autobús.")
assert not check.ok
assert "scope:legal_advice" in check.flags
def test_benign_spanish_fare_question_not_flagged_as_legal():
# "demanda"-adjacent words must not fire: an ordinary reduced-fare question
# stays in scope (no false positive from the new Spanish alternation).
check = guards.check_input("¿Cuánto cuesta el pasaje reducido?")
assert check.ok