fix(google): map content blocks to refusal - #2715
Open
BILLKISHORE wants to merge 1 commit into
Open
Conversation
IMAGE_SAFETY, RECITATION and IMAGE_RECITATION were missing from REFUSAL_REASONS, so a blocked generation fell through to the default and was reported as a normal completion.
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.
What
FINISH_REASON_MAPintranslators/google_chat.pycovers 7 of the 17 finish reasons thegoogle-genaiSDK declares. Everything else falls through to the"stop"default, including three cases where Gemini blocked the content:IMAGE_PROHIBITED_CONTENTis inREFUSAL_REASONSbut its siblingIMAGE_SAFETYis not, which looks like an oversight rather than a decision.REFUSAL_REASONShasn't changed since #2329 introduced it.This matters for scan results: when Gemini blocks a generation, the choice comes back as
finish_reason="stop"with no refusal set, so a scenario reads as though the agent answered normally. #2595 fixed the enum lookup that collapsed every non-STOP reason to"stop", but the map itself stayed incomplete.RECITATIONis the one I'd flag most: it fires when output reproduces memorised or copyrighted material, andAdversarialScenarioGeneratorships a "Copyright Violations" category. Right now that block is invisible to the scan.Fix
Add the three content-block reasons to
REFUSAL_REASONS:Three lines. They flow into
FINISH_REASON_MAPthrough the existing comprehension, and the refusal text path already handles them.What I left alone
Seven reasons are still unmapped and I did not touch them, because none is clearly a refusal and there is no obvious target value:
LANGUAGE,OTHER,MALFORMED_FUNCTION_CALL,UNEXPECTED_TOOL_CALL,NO_IMAGE,IMAGE_OTHER,FINISH_REASON_UNSPECIFIEDMALFORMED_FUNCTION_CALLandUNEXPECTED_TOOL_CALLin particular look like they deserve something other than"stop", but that seemed like your call rather than mine. Happy to follow up if you want a direction.Testing
Added
test_from_google_content_blocks_map_to_refusal, parametrised over the three reasons, next to the existingSAFETYtest. All three fail before the change and pass after. Nothing covered the map previously.libs/giskard-llm/tests/translators/test_google_chat_return.py: 13 passed.make checkexits 0.make test-unit: 41 / 218 / 129 / 805 / 168 passed across core, llm, agents, checks and scan.xref: the one open PR touching this file (#2653) changes thinking-token usage only, not the finish-reason map.
Type of Change
Disclosure: drafted with AI assistance (Claude Code). I diffed the map against the SDK enum, confirmed the tests fail before the fix and pass after, and ran the checks myself before submitting.