Fix/nova grounding#19598
Fix/nova grounding#19598krrishdholakia merged 11 commits intoBerriAI:litellm_oss_staging_01_23_2026from
Conversation
Fix/nova grounding
added integration tests
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
0622ce3
into
BerriAI:litellm_oss_staging_01_23_2026
|
@jquinter Thank you for refactoring my PR per @krrishdholakia comments. please provide details on how you verified this update for nova grounding on your end. I am trying to replicate the same and test but need some support there. Could you share same sample scripts or the payload you ran to test for nova grounding output? I tested my earlier PR and received the response body for citations, however facing some issues after you've refactored it a bit. |
Verification details for Nova grounding update@juhiechandra Here's how to verify the update, plus two bugs I found and fixed while testing. Verification script (mocked — no AWS credentials needed)import json
from unittest.mock import patch, MagicMock
from litellm import completion
from litellm.llms.custom_httpx.http_handler import HTTPHandler
client = HTTPHandler()
with patch.object(client, "post") as mock_post:
mock_post.return_value = MagicMock(
status_code=200,
json=lambda: {
"output": {
"message": {
"role": "assistant",
"content": [
{"text": "The population of Tokyo is approximately 14 million."},
{
"citationsContent": {
"citations": [
{
"location": {
"web": {
"url": "https://example.com/tokyo",
"domain": "example.com",
}
}
}
]
}
},
],
}
},
"stopReason": "end_turn",
"usage": {"inputTokens": 20, "outputTokens": 30, "totalTokens": 50},
},
)
response = completion(
model="bedrock/us.amazon.nova-pro-v1:0",
messages=[{"role": "user", "content": "What is the population of Tokyo?"}],
web_search_options={},
max_tokens=500,
client=client,
)
# Verify request payload
assert mock_post.called, "HTTP POST was not called"
request_body = json.loads(mock_post.call_args.kwargs["data"])
assert "toolConfig" in request_body, "toolConfig missing from request"
tool_config = request_body["toolConfig"]
system_tools = [t for t in tool_config["tools"] if "systemTool" in t]
assert len(system_tools) == 1, f"Expected 1 systemTool, got {len(system_tools)}"
assert system_tools[0]["systemTool"]["name"] == "nova_grounding"
print("Request payload (toolConfig):")
print(json.dumps(tool_config, indent=2))
# Verify response parsing
print("Response text:", response.choices[0].message.content)
provider_fields = response.choices[0].message.provider_specific_fields
assert provider_fields is not None, "provider_specific_fields is None"
assert "citationsContent" in provider_fields, "citationsContent missing from response"
citations = provider_fields["citationsContent"]
assert len(citations) == 1
assert citations[0]["citations"][0]["location"]["web"]["domain"] == "example.com"
print("Citations:", json.dumps(citations, indent=2))
print("PASSED")Live test (requires AWS credentials + Nova quota)from litellm import completion
response = completion(
model="bedrock/us.amazon.nova-pro-v1:0",
messages=[{"role": "user", "content": "What are the latest developments in quantum computing?"}],
web_search_options={},
max_tokens=500,
aws_region_name="us-east-1",
)
print("Response:", response.choices[0].message.content)
provider_fields = getattr(response.choices[0].message, "provider_specific_fields", None)
if provider_fields and "citationsContent" in provider_fields:
for block in provider_fields["citationsContent"]:
for citation in block.get("citations", []):
web = citation.get("location", {}).get("web", {})
print(f" Source: {web.get('url')} ({web.get('domain')})")
else:
print("No citations returned (model may not have used grounding for this query)")What to look for
|
Two bugs prevented web_search_options={} from working for Nova grounding:
1. Empty dict falsy check: The condition `value and isinstance(value, dict)`
short-circuits to False when value is {} (empty dict is falsy in Python).
Changed to `isinstance(value, dict)` to match Anthropic's implementation.
2. Pre-formatted tools mangled by _bedrock_tools_pt: The systemTool
(already in Bedrock format) was added to optional_params["tools"], but
_process_tools_and_beta passed all tools through _bedrock_tools_pt which
expects OpenAI-format tools. This corrupted the systemTool into an empty
toolSpec. Fixed by separating systemTool blocks before transformation
and appending them after.
Fixes follow-up to BerriAI#19598
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
After looking for some minutes, I could successfully run my code in Part of the output I got: |
) * Fix Nova grounding web_search_options={} not applying systemTool Two bugs prevented web_search_options={} from working for Nova grounding: 1. Empty dict falsy check: The condition `value and isinstance(value, dict)` short-circuits to False when value is {} (empty dict is falsy in Python). Changed to `isinstance(value, dict)` to match Anthropic's implementation. 2. Pre-formatted tools mangled by _bedrock_tools_pt: The systemTool (already in Bedrock format) was added to optional_params["tools"], but _process_tools_and_beta passed all tools through _bedrock_tools_pt which expects OpenAI-format tools. This corrupted the systemTool into an empty toolSpec. Fixed by separating systemTool blocks before transformation and appending them after. Fixes follow-up to #19598 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix python-multipart Python version constraint for Poetry lock python-multipart ^0.0.22 requires Python >=3.10 but the project supports >=3.9. Add python = ">=3.10" marker so Poetry can resolve dependencies for Python 3.9. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
) * Fix Nova grounding web_search_options={} not applying systemTool Two bugs prevented web_search_options={} from working for Nova grounding: 1. Empty dict falsy check: The condition `value and isinstance(value, dict)` short-circuits to False when value is {} (empty dict is falsy in Python). Changed to `isinstance(value, dict)` to match Anthropic's implementation. 2. Pre-formatted tools mangled by _bedrock_tools_pt: The systemTool (already in Bedrock format) was added to optional_params["tools"], but _process_tools_and_beta passed all tools through _bedrock_tools_pt which expects OpenAI-format tools. This corrupted the systemTool into an empty toolSpec. Fixed by separating systemTool blocks before transformation and appending them after. Fixes follow-up to #19598 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix python-multipart Python version constraint for Poetry lock python-multipart ^0.0.22 requires Python >=3.10 but the project supports >=3.9. Add python = ">=3.10" marker so Poetry can resolve dependencies for Python 3.9. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Relevant issues
Fixes #17482 (leveraging PR #19474)
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
tests/litellm/directory, Adding at least 1 test is a hard requirement - see detailsallscoped unit tests onmake test-unitCI (LiteLLM team)
Branch creation CI run
Link:
CI run for the last commit
Link:
Merge / cherry-pick CI run
Links:
Type
🆕 New Feature - Added support for web_search_options call for Amazon nova model
🐛 Bug Fix
🧹 Refactoring
📖 Documentation
🚄 Infrastructure
✅ Test
Changes
Changes the approach for enabling Nova grounding (web search) to follow the LiteLLM standard pattern used by other providers (Vertex AI, Anthropic).
Instead of:
Users now use:
Example:
Note: Nova doesn't support
search_context_sizeoruser_location parameters(unlike Anthropic), so those will be silently ignored - similar to how Vertex AI handles it.Implementation changes:
_map_web_search_options()inAmazonConverseConfigto transformweb_search_optionsto Nova's systemTool formatweb_search_optionsto supported params for Nova modelsBedrockToolBlockTypedDict with systemTool supportsystem_toolhandling from_bedrock_tools_pt()as it's no longer needed (web_search_optionsis the entry point)Test changes:
HTTPHandler.get()for optional TypedDict keysRef: https://docs.aws.amazon.com/nova/latest/userguide/grounding.html"