Spaces:
Running on Zero
Running on Zero
File size: 5,544 Bytes
f00d669 c552106 f00d669 | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | """Brick 6 tests: grounded narration + the hard 0% hallucination gate (P0-6)."""
from __future__ import annotations
import pytest
from discoverroute import config
from discoverroute.narrate import grounding
from discoverroute.narrate.narrate import template_narration
class FakePOI:
def __init__(self, name, category):
self.name, self.category = name, category
POIS = [
FakePOI("Jardin des Plantes", "park_garden"),
FakePOI("Fontaine Médicis", "water_feature"),
FakePOI(None, "cafe"), # unnamed -> referred to by type, not a place name
]
def test_extract_multiword_place_names():
mentions = grounding.extract_mentions(
"Start at Place de la République, then visit Jardin des Plantes."
)
joined = " | ".join(mentions)
assert "Place de la République" in joined
assert "Jardin des Plantes" in joined
def test_gate_passes_grounded_text():
text = ("From Bastille, pass by Jardin des Plantes for some green, then "
"Fontaine Médicis. Finally on to the Panthéon area.")
ok, offenders = grounding.verify_grounded(
text, POIS, start_label="Bastille", end_label="Panthéon area"
)
assert ok, offenders
def test_gate_catches_hallucination():
text = "Pass by Jardin des Plantes, then the Eiffel Tower, a lovely detour."
ok, offenders = grounding.verify_grounded(text, POIS, start_label="Bastille")
assert not ok
assert any("Eiffel" in o for o in offenders)
def test_gate_catches_appended_qualifier():
"""A real name extended with an invented qualifier must NOT pass (the
'Café de la Paix' -> 'Café de la Paix sur Seine' hallucination vector)."""
pois = [FakePOI("Fontaine Médicis", "water_feature")]
text = "Pass by Fontaine Médicis sur Montmartre, a lovely spot."
ok, offenders = grounding.verify_grounded(text, pois, start_label="Bastille")
assert not ok
assert any("Montmartre" in o for o in offenders)
def test_gate_allows_shortened_reference():
"""Referring to a place by a shortened form of its real name is fine."""
pois = [FakePOI("Jardin des Plantes de Paris", "park_garden")]
text = "Stroll through Jardin des Plantes, then onward."
ok, offenders = grounding.verify_grounded(text, pois, start_label="Bastille")
assert ok, offenders
def test_gate_allows_unnamed_by_type():
text = "Stop at a cafe near Jardin des Plantes for a coffee-stop pause."
ok, offenders = grounding.verify_grounded(text, POIS, start_label="Bastille")
assert ok, offenders
def test_geo_gazetteer_allows_real_districts():
"""A guide may name the city's real districts/river when given the gazetteer,
so vivid prose passes the gate instead of being thrown out for the template."""
from discoverroute.narrate import gazetteer
geo = gazetteer.geo_terms("paris", "Paris")
text = ("From the Marais, drift down toward the Seine and into the Latin "
"Quarter, passing Jardin des Plantes for some green and Fontaine "
"Médicis. A very Parisian wander with Roman echoes near the Panthéon.")
ok, offenders = grounding.verify_grounded(
text, POIS, start_label="Bastille", end_label="Panthéon",
extra_allowed=geo,
)
assert ok, offenders
def test_geo_gazetteer_still_blocks_invented_venue():
"""Loosening for districts must NOT let an invented venue through."""
from discoverroute.narrate import gazetteer
geo = gazetteer.geo_terms("paris", "Paris")
text = ("Cross the Marais, then stop at Café des Mensonges, a charming "
"invented spot, before Jardin des Plantes.")
ok, offenders = grounding.verify_grounded(
text, POIS, start_label="Bastille", extra_allowed=geo,
)
assert not ok
assert any("Mensonges" in o for o in offenders)
def test_uncurated_city_has_no_extra_context():
"""An on-demand area (bbox-hash key) gets no gazetteer => fails closed."""
from discoverroute.narrate import gazetteer
assert gazetteer.geo_terms("48.1,2.2,48.2,2.3", "this area") == ["this area"]
class _Route:
def __init__(self, time_min):
self.time_min = time_min
def test_template_is_grounded_by_construction():
plain, discovery = _Route(40), _Route(58)
text = template_narration(
plain, discovery, POIS, vibe="quiet green wander", mode="walk",
start_label="Bastille", end_label="Panthéon",
posture={"park_garden": "pass", "water_feature": "pass", "cafe": "stop"},
)
ok, offenders = grounding.verify_grounded(
text, POIS, start_label="Bastille", end_label="Panthéon"
)
assert ok, f"template leaked place names: {offenders}"
assert "Jardin des Plantes" in text and "Fontaine Médicis" in text
data_ready = pytest.mark.skipif(
not (config.GRAPH_WALK_PATH.exists() and config.POIS_PATH.exists()),
reason="Graph or POI table not built",
)
@data_ready
def test_end_to_end_narration_grounded():
"""The shipped itinerary for a real route must pass the gate (the release gate)."""
from discoverroute.pipeline import plan_route
r = plan_route("Place de la République, Paris", "Jardin du Luxembourg, Paris",
budget=0.7, vibe="quiet green wander")
assert r.discovery is not None and r.pois
ok, offenders = grounding.verify_grounded(
r.itinerary_md, r.pois,
start_label="Place de la République, Paris",
end_label="Jardin du Luxembourg, Paris",
)
assert ok, f"hallucinated place names in shipped narration: {offenders}"
|