mirror of
https://github.com/tiennm99/litellm.git
synced 2026-07-13 17:10:08 +00:00
[Feat] Add new anthropic web fetch tool support (#14951)
* add web_fetch tool for ANTHROPIC_HOSTED_TOOLS * add ANTHROPIC_BETA_HEADER_VALUES, ANTHROPIC_HOSTED_TOOLS * feat: add web fetch tool anthropic * test_anthropic_tool_use * docs web fetch * docs fix * docs fix
This commit is contained in:
@@ -0,0 +1,294 @@
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# Web Fetch
|
||||
|
||||
The web fetch tool allows LLMs to retrieve full content from specified web pages and PDF documents. This enables AI models to access real-time information from the internet and incorporate web content into their responses.
|
||||
|
||||
## Web Fetch vs Web Search
|
||||
|
||||
**Web Fetch** retrieves the full content from specific web pages that you provide URLs for, while **Web Search** performs internet searches to find relevant information based on your queries.
|
||||
|
||||
| Feature | Web Fetch | Web Search |
|
||||
|---------|-----------|------------|
|
||||
| **Purpose** | Retrieve content from specific URLs | Search the internet for information |
|
||||
| **Input** | You provide exact URLs to fetch | You provide search queries/questions |
|
||||
| **Output** | Full page content from specified URLs | Search results with relevant information |
|
||||
| **Use Cases** | - Analyzing specific articles<br/>- Comparing content from known websites<br/>- Extracting data from particular pages | - Finding current news/events<br/>- Researching topics<br/>- Getting real-time information |
|
||||
|
||||
|
||||
**Example Web Fetch**: "Fetch the content from https://example.com/pricing and summarize it"
|
||||
**Example Web Search**: "What are the latest AI developments this week?"
|
||||
|
||||
**Supported Providers:**
|
||||
- Anthropic API (`anthropic/`)
|
||||
|
||||
**Supported Tool Types:**
|
||||
- `web_fetch_20250910` - Web content retrieval tool with usage limits, domain filtering, and citation support
|
||||
|
||||
|
||||
## Quick Start
|
||||
|
||||
### LiteLLM Python SDK
|
||||
|
||||
```python
|
||||
import os
|
||||
from litellm import completion
|
||||
|
||||
os.environ["ANTHROPIC_API_KEY"] = "your-api-key"
|
||||
|
||||
# Web fetch tool
|
||||
tools = [
|
||||
{
|
||||
"type": "web_fetch_20250910",
|
||||
"name": "web_fetch",
|
||||
"max_uses": 5,
|
||||
}
|
||||
]
|
||||
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Please analyze the content at https://example.com/article and summarize the main points"
|
||||
}
|
||||
]
|
||||
|
||||
response = completion(
|
||||
model="anthropic/claude-3-5-sonnet-latest",
|
||||
messages=messages,
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
print(response)
|
||||
```
|
||||
|
||||
### LiteLLM Proxy
|
||||
|
||||
1. Define web fetch models on config.yaml
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: claude-3-5-sonnet-latest # Anthropic claude-3-5-sonnet-latest
|
||||
litellm_params:
|
||||
model: anthropic/claude-3-5-sonnet-latest
|
||||
api_key: os.environ/ANTHROPIC_API_KEY
|
||||
```
|
||||
|
||||
2. Run proxy server
|
||||
|
||||
```bash
|
||||
litellm --config config.yaml
|
||||
```
|
||||
|
||||
3. Test it using the OpenAI Python SDK
|
||||
|
||||
```python
|
||||
import os
|
||||
from openai import OpenAI
|
||||
|
||||
client = OpenAI(
|
||||
api_key="sk-1234", # your litellm proxy api key
|
||||
base_url="http://0.0.0.0:4000"
|
||||
)
|
||||
|
||||
response = client.chat.completions.create(
|
||||
model="claude-3-5-sonnet-latest",
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Please fetch and analyze the content from https://news.ycombinator.com and tell me about the top stories"
|
||||
}
|
||||
],
|
||||
tools=[
|
||||
{
|
||||
"type": "web_fetch_20250910",
|
||||
"name": "web_fetch",
|
||||
"max_uses": 5,
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
print(response)
|
||||
```
|
||||
|
||||
## Supported Models
|
||||
|
||||
Web fetch is available on the following Anthropic API models:
|
||||
|
||||
- `claude-opus-4-1-20250805` (Claude Opus 4.1)
|
||||
- `claude-opus-4-20250514` (Claude Opus 4)
|
||||
- `claude-sonnet-4-20250514` (Claude Sonnet 4)
|
||||
- `claude-3-7-sonnet-20250219` (Claude Sonnet 3.7)
|
||||
- `claude-3-5-sonnet-latest` (Claude Sonnet 3.5 v2 - deprecated)
|
||||
- `claude-3-5-haiku-latest` (Claude Haiku 3.5)
|
||||
|
||||
:::note
|
||||
The web fetch tool currently does not support websites dynamically rendered via JavaScript.
|
||||
:::
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic Web Content Retrieval
|
||||
|
||||
```python
|
||||
import os
|
||||
from litellm import completion
|
||||
|
||||
os.environ["ANTHROPIC_API_KEY"] = "your-api-key"
|
||||
|
||||
tools = [
|
||||
{
|
||||
"type": "web_fetch_20250910",
|
||||
"name": "web_fetch",
|
||||
"max_uses": 3,
|
||||
}
|
||||
]
|
||||
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Fetch the latest news from https://techcrunch.com and summarize the top 3 articles"
|
||||
}
|
||||
]
|
||||
|
||||
response = completion(
|
||||
model="anthropic/claude-3-5-sonnet-latest",
|
||||
messages=messages,
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
print(response)
|
||||
```
|
||||
|
||||
### Research and Analysis
|
||||
|
||||
```python
|
||||
import os
|
||||
from litellm import completion
|
||||
|
||||
os.environ["ANTHROPIC_API_KEY"] = "your-api-key"
|
||||
|
||||
tools = [
|
||||
{
|
||||
"type": "web_fetch_20250910",
|
||||
"name": "web_fetch",
|
||||
"max_uses": 10,
|
||||
}
|
||||
]
|
||||
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Research the latest developments in AI by fetching content from multiple tech news websites and provide a comprehensive analysis"
|
||||
}
|
||||
]
|
||||
|
||||
response = completion(
|
||||
model="anthropic/claude-3-5-sonnet-latest",
|
||||
messages=messages,
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
print(response)
|
||||
```
|
||||
|
||||
### Content Comparison
|
||||
|
||||
```python
|
||||
import os
|
||||
from litellm import completion
|
||||
|
||||
os.environ["ANTHROPIC_API_KEY"] = "your-api-key"
|
||||
|
||||
tools = [
|
||||
{
|
||||
"type": "web_fetch_20250910",
|
||||
"name": "web_fetch",
|
||||
"max_uses": 5,
|
||||
}
|
||||
]
|
||||
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Compare the pricing information from https://openai.com/pricing and https://anthropic.com/pricing and create a comparison table"
|
||||
}
|
||||
]
|
||||
|
||||
response = completion(
|
||||
model="anthropic/claude-3-5-sonnet-latest",
|
||||
messages=messages,
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
print(response)
|
||||
```
|
||||
|
||||
## Advanced Usage with Multiple Tools
|
||||
|
||||
You can combine web fetch with other tools like computer use or text editor:
|
||||
|
||||
```python
|
||||
import os
|
||||
from litellm import completion
|
||||
|
||||
os.environ["ANTHROPIC_API_KEY"] = "your-api-key"
|
||||
|
||||
tools = [
|
||||
{
|
||||
"type": "web_fetch_20250910",
|
||||
"name": "web_fetch",
|
||||
"max_uses": 5,
|
||||
},
|
||||
{
|
||||
"type": "text_editor_20250124",
|
||||
"name": "str_replace_editor"
|
||||
}
|
||||
]
|
||||
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Fetch the latest AI research papers from arXiv, analyze them, and create a detailed report file with your findings"
|
||||
}
|
||||
]
|
||||
|
||||
response = completion(
|
||||
model="anthropic/claude-3-5-sonnet-latest",
|
||||
messages=messages,
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
print(response)
|
||||
```
|
||||
|
||||
## Spec
|
||||
|
||||
### Web Fetch Tool (`web_fetch_20250910`)
|
||||
|
||||
The web fetch tool supports the following parameters:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "web_fetch_20250910",
|
||||
"name": "web_fetch",
|
||||
|
||||
// Optional: Limit the number of fetches per request
|
||||
"max_uses": 10,
|
||||
|
||||
// Optional: Only fetch from these domains
|
||||
"allowed_domains": ["example.com", "docs.example.com"],
|
||||
|
||||
// Optional: Never fetch from these domains
|
||||
"blocked_domains": ["private.example.com"],
|
||||
|
||||
// Optional: Enable citations for fetched content
|
||||
"citations": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
// Optional: Maximum content length in tokens
|
||||
"max_content_tokens": 100000
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# Using Web Search
|
||||
# Web Search
|
||||
|
||||
Use web search with litellm
|
||||
|
||||
|
||||
@@ -898,7 +898,7 @@ curl http://0.0.0.0:4000/chat/completions \
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
</Tabs>
|
||||
|
||||
## Pre-requisites
|
||||
* `pip install google-cloud-aiplatform` (pre-installed on proxy docker image)
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import '@theme/IdealImage'
|
||||
import '@theme/TabItem'
|
||||
import '@theme/Tabs'
|
||||
import Image
|
||||
import TabItem
|
||||
import Tabs
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# LiteLLM Prompt Management (GitOps)
|
||||
|
||||
|
||||
@@ -518,12 +518,19 @@ const sidebars = {
|
||||
type: "category",
|
||||
label: "Guides",
|
||||
items: [
|
||||
{
|
||||
type: "category",
|
||||
label: "Tools",
|
||||
items: [
|
||||
"completion/computer_use",
|
||||
"completion/web_search",
|
||||
"completion/web_fetch",
|
||||
"completion/function_call",
|
||||
]
|
||||
},
|
||||
"completion/audio",
|
||||
"completion/batching",
|
||||
"completion/computer_use",
|
||||
"completion/document_understanding",
|
||||
"completion/drop_params",
|
||||
"completion/function_call",
|
||||
"completion/image_generation_chat",
|
||||
"completion/json_mode",
|
||||
"completion/knowledgebase",
|
||||
@@ -538,8 +545,8 @@ const sidebars = {
|
||||
"completion/stream",
|
||||
"completion/provider_specific_params",
|
||||
"completion/vision",
|
||||
"completion/web_search",
|
||||
"exception_mapping",
|
||||
"completion/batching",
|
||||
"guides/finetuned_models",
|
||||
"guides/security_settings",
|
||||
"proxy/veo_video_generation",
|
||||
|
||||
@@ -18,6 +18,8 @@ from litellm.litellm_core_utils.core_helpers import map_finish_reason
|
||||
from litellm.llms.base_llm.base_utils import type_to_response_format_param
|
||||
from litellm.llms.base_llm.chat.transformation import BaseConfig, BaseLLMException
|
||||
from litellm.types.llms.anthropic import (
|
||||
ANTHROPIC_BETA_HEADER_VALUES,
|
||||
ANTHROPIC_HOSTED_TOOLS,
|
||||
AllAnthropicMessageValues,
|
||||
AllAnthropicToolsValues,
|
||||
AnthropicCodeExecutionTool,
|
||||
@@ -50,7 +52,10 @@ from litellm.types.utils import (
|
||||
CompletionTokensDetailsWrapper,
|
||||
)
|
||||
from litellm.types.utils import Message as LitellmMessage
|
||||
from litellm.types.utils import PromptTokensDetailsWrapper, ServerToolUse
|
||||
from litellm.types.utils import (
|
||||
PromptTokensDetailsWrapper,
|
||||
ServerToolUse,
|
||||
)
|
||||
from litellm.utils import (
|
||||
ModelResponse,
|
||||
Usage,
|
||||
@@ -70,9 +75,6 @@ else:
|
||||
LoggingClass = Any
|
||||
|
||||
|
||||
ANTHROPIC_HOSTED_TOOLS = ["web_search", "bash", "text_editor", "code_execution"]
|
||||
|
||||
|
||||
class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
||||
"""
|
||||
Reference: https://docs.anthropic.com/claude/reference/messages_post
|
||||
@@ -639,6 +641,14 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
||||
)
|
||||
)
|
||||
return tools
|
||||
|
||||
def update_headers_with_optional_anthropic_beta(self, headers: dict, optional_params: dict) -> dict:
|
||||
"""Update headers with optional anthropic beta."""
|
||||
_tools = optional_params.get("tools", [])
|
||||
for tool in _tools:
|
||||
if tool.get("type", None) and tool.get("type").startswith(ANTHROPIC_HOSTED_TOOLS.WEB_FETCH.value):
|
||||
headers["anthropic-beta"] = ANTHROPIC_BETA_HEADER_VALUES.WEB_FETCH_2025_09_10.value
|
||||
return headers
|
||||
|
||||
def transform_request(
|
||||
self,
|
||||
@@ -675,6 +685,8 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
||||
llm_provider="anthropic",
|
||||
)
|
||||
|
||||
headers = self.update_headers_with_optional_anthropic_beta(headers=headers, optional_params=optional_params)
|
||||
|
||||
# Separate system prompt from rest of message
|
||||
anthropic_system_message_list = self.translate_system_message(messages=messages)
|
||||
# Handling anthropic API Prompt Caching
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, Iterable, List, Optional, Union
|
||||
|
||||
from pydantic import BaseModel, validator
|
||||
@@ -440,3 +441,16 @@ ANTHROPIC_API_ONLY_HEADERS = { # fails if calling anthropic on vertex ai / bedr
|
||||
class AnthropicThinkingParam(TypedDict, total=False):
|
||||
type: Literal["enabled"]
|
||||
budget_tokens: int
|
||||
|
||||
class ANTHROPIC_HOSTED_TOOLS(str, Enum):
|
||||
WEB_SEARCH = "web_search"
|
||||
BASH = "bash"
|
||||
TEXT_EDITOR = "text_editor"
|
||||
CODE_EXECUTION = "code_execution"
|
||||
WEB_FETCH = "web_fetch"
|
||||
|
||||
class ANTHROPIC_BETA_HEADER_VALUES(str, Enum):
|
||||
"""
|
||||
Known beta header values for Anthropic.
|
||||
"""
|
||||
WEB_FETCH_2025_09_10 = "web-fetch-2025-09-10"
|
||||
@@ -329,32 +329,51 @@ def test_process_anthropic_headers_with_no_matching_headers():
|
||||
assert result == expected_output, "Unexpected output for non-matching headers"
|
||||
|
||||
|
||||
def test_anthropic_computer_tool_use():
|
||||
from litellm import completion
|
||||
|
||||
tools = [
|
||||
{
|
||||
"type": "computer_20241022",
|
||||
"function": {
|
||||
"name": "computer",
|
||||
"parameters": {
|
||||
"display_height_px": 100,
|
||||
"display_width_px": 100,
|
||||
"display_number": 1,
|
||||
@pytest.mark.parametrize(
|
||||
"tool_type, tool_config, message_content",
|
||||
[
|
||||
(
|
||||
"computer_20241022",
|
||||
{
|
||||
"type": "computer_20241022",
|
||||
"function": {
|
||||
"name": "computer",
|
||||
"parameters": {
|
||||
"display_height_px": 100,
|
||||
"display_width_px": 100,
|
||||
"display_number": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
]
|
||||
"Save a picture of a cat to my desktop.",
|
||||
),
|
||||
(
|
||||
"web_fetch_20250910",
|
||||
{
|
||||
"type": "web_fetch_20250910",
|
||||
"name": "web_fetch",
|
||||
"max_uses": 5,
|
||||
},
|
||||
"Please analyze the content at https://example.com/article",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_anthropic_tool_use(tool_type, tool_config, message_content):
|
||||
"""Test Anthropic tool use with computer use and web fetch tools."""
|
||||
from litellm import completion
|
||||
litellm._turn_on_debug()
|
||||
|
||||
tools = [tool_config]
|
||||
model = "claude-3-5-sonnet-20241022"
|
||||
messages = [{"role": "user", "content": "Save a picture of a cat to my desktop."}]
|
||||
messages = [{"role": "user", "content": message_content}]
|
||||
|
||||
try:
|
||||
resp = completion(
|
||||
model=model,
|
||||
messages=messages,
|
||||
tools=tools,
|
||||
# headers={"anthropic-beta": "computer-use-2024-10-22"},
|
||||
)
|
||||
print(f"Tool type: {tool_type}")
|
||||
print(resp)
|
||||
except litellm.InternalServerError:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user