fix: prevent abstention control-token leaks - #9
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
INSUFFICIENT_EVIDENCEcontrol token before citation validationValidation
uv lock --checkpassedScope
No benchmark data, evaluation results, metrics, prompts, datasets, or generated reports were changed.
Greptile Summary
This PR closes a leakage path where a model producing a mixed response — the
INSUFFICIENT_EVIDENCEcontrol token alongside real prose and citations — could have that token rendered in the Streamlit UI. A single guard (if INSUFFICIENT_EVIDENCE_TOKEN in normalized_answer) is inserted between the clean-abstention check and the citation-validation step, returningCITATION_VALIDATION_MESSAGEwithoutabstained=True.agent.py: The new guard runs only whennormalized_answer != INSUFFICIENT_EVIDENCE_TOKEN(the equality check fires first for token-only responses, preserving theabstained=True/NO_MATCH_MESSAGEpath), so the two branches are mutually exclusive.tests/test_agent.py: The existing abstention test is updated to use a whitespace-padded token to exercise the.strip()boundary; three parametrized sub-tests cover "preceded", "followed", and "embedded" token positions in mixed responses.tests/test_dashboard.py: A newMixedTokenModel+DashboardStorefixture drives an end-to-end Streamlit regression confirming thatINSUFFICIENT_EVIDENCEand#### Evidenceare never rendered when the model returns a mixed response.Confidence Score: 5/5
Safe to merge — the change is a narrowly scoped guard that plugs a specific token-leak path without touching any other logic.
The new guard is inserted at exactly the right place in the control flow: after the clean-abstention equality check and before citation validation, so the two branches remain mutually exclusive. The abstained flag, message constants, and retrieved_source_ids are all set correctly. Tests cover the three mixed-position variants at the unit level plus a full Streamlit render regression, and the PR description reports a clean 65-test run with type checking and linting.
Files Needing Attention: No files require special attention.
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[answer_question called] --> B{matches found?} B -- No --> C[Return NO_MATCH_MESSAGE] B -- Yes --> D{any missing source IDs?} D -- Yes --> E[Return CITATION_VALIDATION_MESSAGE] D -- No --> F[model.invoke prompt] F --> G[normalized_answer = response.strip] G --> H{normalized_answer == INSUFFICIENT_EVIDENCE_TOKEN?} H -- Yes --> I[Return NO_MATCH_MESSAGE\nabstained=True] H -- No --> J{INSUFFICIENT_EVIDENCE_TOKEN\nin normalized_answer?} J -- Yes --> K[Return CITATION_VALIDATION_MESSAGE\nabstained=False\nNEW GUARD] J -- No --> L[_validate_and_number_citations] L --> M{validated is None?} M -- Yes --> N[Return CITATION_VALIDATION_MESSAGE] M -- No --> O[Return validated answer with sources] style K fill:#d4edda,stroke:#28a745 style J fill:#d4edda,stroke:#28a745Reviews (1): Last reviewed commit: "fix: reject mixed abstention control tok..." | Re-trigger Greptile