Fix grounded assistant cross-domain responses
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 03:30:21 +02:00
parent 035ec3b233
commit a19bff9d14
12 changed files with 56 additions and 8 deletions
+11
View File
@@ -7,6 +7,17 @@
# Changelog
## Sprint 215 Grounded assistant cross-domain reliability (2026-07-16)
- Raised the bounded local Ollama answer budget from 700 to 1,200 tokens after
a live Mol profile exhausted the smaller limit; `done_reason=length` remains
a hard error and incomplete text is still never returned.
- Required listed themes to be covered without adding unrelated themes and
kept cross-domain answers compact without weakening source, unit, estimate,
chronology or unsupported-metric rules.
- Exposed the output limit in the Unraid DockerMan template and aligned all
Compose, runtime, example and operator documentation defaults.
## Sprint 213-214 Cross-domain area profile (2026-07-16)
- Implemented one allowlisted MercatorNet WCS registry for official Flemish
+4 -2
View File
@@ -1114,7 +1114,7 @@ OLLAMA_ENABLED=true
OLLAMA_BASE_URL=http://host.docker.internal:11434
OLLAMA_DEFAULT_MODEL=qwen3.5:9b
OLLAMA_TIMEOUT_SECONDS=120
OLLAMA_MAX_OUTPUT_TOKENS=700
OLLAMA_MAX_OUTPUT_TOKENS=1200
OLLAMA_CONTEXT_TOKENS=16384
```
@@ -1125,7 +1125,9 @@ models with `GET /api/v1/assistant/models` and ask a grounded question through
present in Ollama `/api/tags`. Missing water depth/bathymetry remains explicit;
the assistant cannot turn 2D water geometry into volume. GeoIntel rejects an
answer when Ollama reports `done_reason=length`, so a visibly truncated sentence
is never presented as a complete result.
is never presented as a complete result. The 1,200-token default leaves enough
room for a compact cross-domain profile while the system prompt requires every
explicitly requested theme and excludes unrelated themes.
## Agricultural-use parcel history
+1 -1
View File
@@ -82,7 +82,7 @@ class Settings(BaseSettings):
ollama_base_url: str = Field(default="http://127.0.0.1:11434", validation_alias="OLLAMA_BASE_URL")
ollama_default_model: str = Field(default="qwen3.5:9b", validation_alias="OLLAMA_DEFAULT_MODEL")
ollama_timeout_seconds: int = Field(default=120, ge=5, le=600, validation_alias="OLLAMA_TIMEOUT_SECONDS")
ollama_max_output_tokens: int = Field(default=700, ge=100, le=4_000, validation_alias="OLLAMA_MAX_OUTPUT_TOKENS")
ollama_max_output_tokens: int = Field(default=1_200, ge=100, le=4_000, validation_alias="OLLAMA_MAX_OUTPUT_TOKENS")
ollama_context_tokens: int = Field(default=16_384, ge=4_096, le=131_072, validation_alias="OLLAMA_CONTEXT_TOKENS")
cors_origins: list[str] | str = Field(
default=["http://localhost:5173", "http://127.0.0.1:5173"],
@@ -525,6 +525,8 @@ class GeoAssistantService:
"Noem bij cijfers de bron en eenheid. Maak duidelijk onderscheid tussen exacte metingen en schattingen. "
"Als is_estimate true is, noem de waarde verplicht een schatting en nooit exact. "
"Objectaantallen zijn ondersteunend; geef betekenisvolle oppervlakte-, lengte- of bevolkingsmetriek voorrang. "
"Wanneer de gebruiker meerdere thema's opsomt, behandel elk gevraagd thema en voeg geen ongevraagd thema toe. "
"Houd het antwoord beknopt: groepeer de kernmetrieken per gevraagd thema en herhaal geen beperkingen. "
"Beschrijf alleen waargenomen verschillen; verzin geen oorzaak, voorspelling, verzadiging of andere verklaring. "
"Neem waarden en jaren letterlijk over en bereken zelf geen gemiddelde, tempo, oorzaak of afgeleide trend. "
"Gebruik platte tekst met korte alinea's en opsommingen, zonder Markdown-symbolen. "
@@ -202,12 +202,15 @@ def test_geo_assistant_sends_grounded_context_without_thinking_trace(monkeypatch
assert captured["payload"]["think"] is False
assert captured["payload"]["options"]["temperature"] == 0.0
assert captured["payload"]["options"]["num_ctx"] == 16_384
assert captured["payload"]["options"]["num_predict"] == 1_200
assert "Gebruik uitsluitend feiten en cijfers uit CONTEXT_JSON" in captured["payload"]["messages"][0]["content"]
assert "scope.label is het exact geanalyseerde gebied" in captured["payload"]["messages"][0]["content"]
assert "noem de waarde verplicht een schatting" in captured["payload"]["messages"][0]["content"]
assert "verzin geen oorzaak, voorspelling, verzadiging" in captured["payload"]["messages"][0]["content"]
assert "bereken zelf geen gemiddelde, tempo, oorzaak of afgeleide trend" in captured["payload"]["messages"][0]["content"]
assert "zonder Markdown-symbolen" in captured["payload"]["messages"][0]["content"]
assert "behandel elk gevraagd thema en voeg geen ongevraagd thema toe" in captured["payload"]["messages"][0]["content"]
assert "Houd het antwoord beknopt" in captured["payload"]["messages"][0]["content"]
assert "water_volume_available" in captured["payload"]["messages"][0]["content"]
@@ -254,6 +257,9 @@ def test_unraid_ollama_context_window_is_configurable() -> None:
assert "OLLAMA_CONTEXT_TOKENS: ${OLLAMA_CONTEXT_TOKENS:-16384}" in compose
assert 'Target="OLLAMA_CONTEXT_TOKENS"' in template
assert "OLLAMA_CONTEXT_TOKENS=16384" in env_example
assert "OLLAMA_MAX_OUTPUT_TOKENS: ${OLLAMA_MAX_OUTPUT_TOKENS:-1200}" in compose
assert 'Target="OLLAMA_MAX_OUTPUT_TOKENS"' in template
assert "OLLAMA_MAX_OUTPUT_TOKENS=1200" in env_example
def test_temporal_comparison_preserves_all_compatible_semantic_metrics() -> None:
+1 -1
View File
@@ -200,7 +200,7 @@ OLLAMA_ENABLED=true
OLLAMA_BASE_URL=http://host.docker.internal:11434
OLLAMA_DEFAULT_MODEL=qwen3.5:9b
OLLAMA_TIMEOUT_SECONDS=120
OLLAMA_MAX_OUTPUT_TOKENS=700
OLLAMA_MAX_OUTPUT_TOKENS=1200
OLLAMA_CONTEXT_TOKENS=16384
```
@@ -51,5 +51,6 @@
<Config Name="Ollama Base URL" Target="OLLAMA_BASE_URL" Default="http://host.docker.internal:11434" Mode="" Description="Ollama API reachable from the container. The deployment maps host.docker.internal to the Unraid host gateway." Type="Variable" Display="always" Required="true" Mask="false">http://host.docker.internal:11434</Config>
<Config Name="Default Ollama Model" Target="OLLAMA_DEFAULT_MODEL" Default="qwen3.5:9b" Mode="" Description="Preferred locally installed Ollama model. Users can select another installed model in GeoIntel." Type="Variable" Display="always" Required="true" Mask="false">qwen3.5:9b</Config>
<Config Name="Ollama Timeout Seconds" Target="OLLAMA_TIMEOUT_SECONDS" Default="120" Mode="" Description="Maximum wait for one local assistant response." Type="Variable" Display="advanced" Required="true" Mask="false">120</Config>
<Config Name="Ollama Maximum Output Tokens" Target="OLLAMA_MAX_OUTPUT_TOKENS" Default="1200" Mode="" Description="Maximum generated tokens for one grounded answer. Length-truncated responses remain rejected." Type="Variable" Display="advanced" Required="true" Mask="false">1200</Config>
<Config Name="Ollama Context Tokens" Target="OLLAMA_CONTEXT_TOKENS" Default="16384" Mode="" Description="Context window reserved for grounded GIS measurements and the generated answer." Type="Variable" Display="advanced" Required="true" Mask="false">16384</Config>
</Container>
+1 -1
View File
@@ -71,5 +71,5 @@ OLLAMA_ENABLED=true
OLLAMA_BASE_URL=http://host.docker.internal:11434
OLLAMA_DEFAULT_MODEL=qwen3.5:9b
OLLAMA_TIMEOUT_SECONDS=120
OLLAMA_MAX_OUTPUT_TOKENS=700
OLLAMA_MAX_OUTPUT_TOKENS=1200
OLLAMA_CONTEXT_TOKENS=16384
+1 -1
View File
@@ -67,7 +67,7 @@ OLLAMA_ENABLED="${OLLAMA_ENABLED:-true}"
OLLAMA_BASE_URL="${OLLAMA_BASE_URL:-http://host.docker.internal:11434}"
OLLAMA_DEFAULT_MODEL="${OLLAMA_DEFAULT_MODEL:-qwen3.5:9b}"
OLLAMA_TIMEOUT_SECONDS="${OLLAMA_TIMEOUT_SECONDS:-120}"
OLLAMA_MAX_OUTPUT_TOKENS="${OLLAMA_MAX_OUTPUT_TOKENS:-700}"
OLLAMA_MAX_OUTPUT_TOKENS="${OLLAMA_MAX_OUTPUT_TOKENS:-1200}"
OLLAMA_CONTEXT_TOKENS="${OLLAMA_CONTEXT_TOKENS:-16384}"
install_dockerman_metadata() {
+1 -1
View File
@@ -65,7 +65,7 @@ services:
OLLAMA_BASE_URL: ${OLLAMA_BASE_URL:-http://host.docker.internal:11434}
OLLAMA_DEFAULT_MODEL: ${OLLAMA_DEFAULT_MODEL:-qwen3.5:9b}
OLLAMA_TIMEOUT_SECONDS: ${OLLAMA_TIMEOUT_SECONDS:-120}
OLLAMA_MAX_OUTPUT_TOKENS: ${OLLAMA_MAX_OUTPUT_TOKENS:-700}
OLLAMA_MAX_OUTPUT_TOKENS: ${OLLAMA_MAX_OUTPUT_TOKENS:-1200}
OLLAMA_CONTEXT_TOKENS: ${OLLAMA_CONTEXT_TOKENS:-16384}
ports:
- "${GEOINTEL_FRONTEND_PORT:-1202}:80"
+1 -1
View File
@@ -70,7 +70,7 @@ services:
OLLAMA_BASE_URL: ${OLLAMA_BASE_URL:-http://host.docker.internal:11434}
OLLAMA_DEFAULT_MODEL: ${OLLAMA_DEFAULT_MODEL:-qwen3.5:9b}
OLLAMA_TIMEOUT_SECONDS: ${OLLAMA_TIMEOUT_SECONDS:-120}
OLLAMA_MAX_OUTPUT_TOKENS: ${OLLAMA_MAX_OUTPUT_TOKENS:-700}
OLLAMA_MAX_OUTPUT_TOKENS: ${OLLAMA_MAX_OUTPUT_TOKENS:-1200}
OLLAMA_CONTEXT_TOKENS: ${OLLAMA_CONTEXT_TOKENS:-16384}
ports:
- "${GEOINTEL_BACKEND_PORT:-8000}:8000"
+26
View File
@@ -1,3 +1,29 @@
## Sprint 215 Grounded assistant cross-domain reliability (2026-07-16)
Changed:
- Measured the exact live Mol assistant context at 12 current themes, 36
semantic metrics, six temporal series and 17,302 compact JSON characters.
- Increased the bounded output allowance to 1,200 tokens and instructed the
local model to cover every explicitly listed theme, omit unrelated themes
and avoid repeated limitations.
- Kept `think=false`, deterministic temperature, the 16,384-token context and
fail-closed rejection of `done_reason=length` unchanged.
- Added the output limit to the editable Unraid template and aligned all
deployment defaults and documentation.
Validation evidence:
- A read-only live production-chain probe with the 1,200-token setting
completed without truncation against the full persisted Mol context.
- The focused assistant suite passed 14 tests.
- The complete readiness gate passed 713 backend tests, backend compilation,
105 documented API routes with three explicit binary/non-envelope routes,
one Alembic head and the frontend TypeScript and production build.
- Tower deployment and browser verification follow in this pass.
Next:
- Deploy, rerun the exact six-theme Dutch question and verify the end-user
response and responsive assistant UI in the browser.
## Sprint 213-214 Cross-domain thematic rasters and DOV soil map (2026-07-16)
Changed: