Enforce population estimate wording
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-16 04:00:20 +02:00
parent d0210b9a3c
commit a280de8838
4 changed files with 45 additions and 1 deletions
+2
View File
@@ -26,6 +26,8 @@
- Added deterministic semantic rounding for model context and normalized model
Markdown to the existing plain-text renderer so hectare, population and
score answers remain readable without exposing raw floating-point tails.
- Prevented an area-weighted population estimate from retaining model phrases
such as "official count" when its persisted metric is marked as estimated.
## Sprint 213-214 Cross-domain area profile (2026-07-16)
+15 -1
View File
@@ -108,13 +108,27 @@ class GeoAssistantService:
answer: str,
metrics: list[AssistantContextMetric],
) -> str:
estimated_themes = {metric.theme for metric in metrics if metric.is_estimate}
if "population" in estimated_themes:
answer = re.sub(
r"\bde officiële telling\b",
"de van de officiële bron afgeleide schatting",
answer,
flags=re.IGNORECASE,
)
answer = re.sub(
r"\bofficieel geteld aantal inwoners\b",
"uit een officiële bron afgeleid aantal inwoners",
answer,
flags=re.IGNORECASE,
)
normalized = answer.casefold()
if "schat" in normalized:
return answer
disclosed_themes = {
metric.theme
for metric in metrics
if metric.is_estimate
if metric.theme in estimated_themes
and any(
term in normalized
for term in cls.ESTIMATE_TOPIC_TERMS.get(metric.theme, (metric.label.casefold(),))
@@ -144,6 +144,28 @@ def test_geo_assistant_discloses_estimated_population_values() -> None:
)
def test_geo_assistant_never_labels_area_weighted_population_as_official_count() -> None:
metrics = [
AssistantContextMetric(
theme="population",
label="Geraamd aantal inwoners",
value=38_675,
unit="inwoners",
source="Statbel",
dataset_id=uuid4(),
is_estimate=True,
)
]
answer = GeoAssistantService.ensure_estimate_disclosure(
"De officiële telling uit januari 2025 bedraagt 38.675 inwoners. Deze waarde is een schatting.",
metrics,
)
assert "officiële telling" not in answer.casefold()
assert answer.startswith("de van de officiële bron afgeleide schatting")
def test_geo_assistant_does_not_add_irrelevant_estimate_disclosure() -> None:
metrics = [
AssistantContextMetric(
+6
View File
@@ -20,6 +20,10 @@ Changed:
Markdown and raw floating-point tails in the plain-text chat renderer. Added
deterministic Markdown normalization and unit-aware context rounding while
retaining the unrounded metrics in the canonical API response.
- The next live answer still called an area-weighted Statbel population value
an official count before acknowledging it as an estimate. The deterministic
estimate guard now removes that contradictory label whenever persisted
population context is estimated.
Validation evidence:
- A read-only live production-chain probe with the 1,200-token setting
@@ -33,6 +37,8 @@ Validation evidence:
shell gates.
- After plain-text normalization and semantic prompt rounding, the final
readiness rerun passed 725 backend tests and the same complete gate set.
- After hardening estimated-population wording, the final complete readiness
rerun passed 726 backend tests and all remaining gates unchanged.
- The regional thematic operator dry-run resolved exactly 28 official
municipality Areas. The live Mol run in `Kempen Regional Workbench` imported
all five products with complete source coverage; the DOV operator imported