mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-03 02:22:24 +00:00
fix(gemini): preserve function calls during Gemini content policy checks
- Skip finishReason content_filter when candidate has functionCall parts - Fix false positive from empty promptFeedback.blockReason - Remove redundant thought_signatures from functionCall parts in message-level provider_specific_fields
This commit is contained in:
parent
c23b19f09c
commit
6583c35dff
1 changed files with 27 additions and 16 deletions
|
|
@ -1544,13 +1544,18 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
|
||||
Per Google's docs, thoughtSignature is returned for multi-turn context preservation
|
||||
and can appear on parts even without thought: true (e.g., regular text responses,
|
||||
function calls). This method extracts all thoughtSignature values from parts.
|
||||
function calls).
|
||||
|
||||
Only extracts signatures from non-functionCall parts — functionCall
|
||||
thoughtSignatures are handled via tool_call.provider_specific_fields.
|
||||
|
||||
Returns:
|
||||
List of thoughtSignature strings if any are found, None otherwise
|
||||
"""
|
||||
signatures: List[str] = []
|
||||
for part in parts:
|
||||
if "functionCall" in part:
|
||||
continue
|
||||
signature = part.get("thoughtSignature")
|
||||
if signature is not None:
|
||||
signatures.append(signature)
|
||||
|
|
@ -2116,7 +2121,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
|
||||
# Check if prompt is blocked due to content filtering
|
||||
prompt_feedback = processed_chunk.get("promptFeedback")
|
||||
if prompt_feedback and "blockReason" in prompt_feedback:
|
||||
if prompt_feedback and prompt_feedback.get("blockReason"):
|
||||
verbose_logger.debug(
|
||||
f"Prompt blocked due to: {prompt_feedback.get('blockReason')} - {prompt_feedback.get('blockReasonMessage')}"
|
||||
)
|
||||
|
|
@ -2545,10 +2550,9 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
model_response.model = model
|
||||
|
||||
## CHECK IF RESPONSE FLAGGED
|
||||
if (
|
||||
"promptFeedback" in completion_response
|
||||
and "blockReason" in completion_response["promptFeedback"]
|
||||
):
|
||||
if "promptFeedback" in completion_response and completion_response[
|
||||
"promptFeedback"
|
||||
].get("blockReason"):
|
||||
return self._handle_blocked_response(
|
||||
model_response=model_response,
|
||||
completion_response=completion_response,
|
||||
|
|
@ -2556,17 +2560,24 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
|
||||
_candidates = completion_response.get("candidates")
|
||||
if _candidates and len(_candidates) > 0:
|
||||
content_policy_violations = (
|
||||
VertexGeminiConfig().get_flagged_finish_reasons()
|
||||
)
|
||||
if (
|
||||
"finishReason" in _candidates[0]
|
||||
and _candidates[0]["finishReason"] in content_policy_violations.keys()
|
||||
):
|
||||
return self._handle_content_policy_violation(
|
||||
model_response=model_response,
|
||||
completion_response=completion_response,
|
||||
# Don't short-circuit to content_filter if the candidate has
|
||||
# functionCall parts — Gemini may return a safety finishReason
|
||||
# alongside valid function call data.
|
||||
candidate_parts = _candidates[0].get("content", {}).get("parts", [])
|
||||
has_function_call = any("functionCall" in part for part in candidate_parts)
|
||||
if not has_function_call:
|
||||
content_policy_violations = (
|
||||
VertexGeminiConfig().get_flagged_finish_reasons()
|
||||
)
|
||||
if (
|
||||
"finishReason" in _candidates[0]
|
||||
and _candidates[0]["finishReason"]
|
||||
in content_policy_violations.keys()
|
||||
):
|
||||
return self._handle_content_policy_violation(
|
||||
model_response=model_response,
|
||||
completion_response=completion_response,
|
||||
)
|
||||
|
||||
model_response.choices = []
|
||||
response_id = completion_response.get("responseId")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue