mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-09 16:24:38 +00:00
[New Model] Add Amazon Nova as first party provider for chat completions (#17351)
* Add Amazon Nova as a first party provider * Added new provider folder under llms/ to outline the openai supported params * Updated supported endpoints on the documnetation
This commit is contained in:
@@ -0,0 +1,291 @@
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# Amazon Nova
|
||||
|
||||
| Property | Details |
|
||||
|-------|-------|
|
||||
| Description | Amazon Nova is a family of foundation models built by Amazon that deliver frontier intelligence and industry-leading price performance. |
|
||||
| Provider Route on LiteLLM | `amazon-nova/` |
|
||||
| Provider Doc | [Amazon Nova ↗](https://docs.aws.amazon.com/nova/latest/userguide/what-is-nova.html) |
|
||||
| Supported OpenAI Endpoints | `/chat/completions`, `v1/responses` |
|
||||
| Other Supported Endpoints | `v1/messages`, `/generateContent` |
|
||||
|
||||
## Authentication
|
||||
|
||||
Amazon Nova uses API key authentication. You can obtain your API key from the [Amazon Nova developer console ↗](https://nova.amazon.com/dev/documentation).
|
||||
|
||||
```bash
|
||||
export AMAZON_NOVA_API_KEY="your-api-key"
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="sdk" label="SDK">
|
||||
|
||||
```python
|
||||
import os
|
||||
from litellm import completion
|
||||
|
||||
# Set your API key
|
||||
os.environ["AMAZON_NOVA_API_KEY"] = "your-api-key"
|
||||
|
||||
response = completion(
|
||||
model="amazon-nova/nova-micro-v1",
|
||||
messages=[
|
||||
{"role": "system", "content": "You are a helpful assistant"},
|
||||
{"role": "user", "content": "Hello, how are you?"}
|
||||
]
|
||||
)
|
||||
|
||||
print(response)
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="proxy" label="PROXY">
|
||||
|
||||
### 1. Setup config.yaml
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: amazon-nova-micro
|
||||
litellm_params:
|
||||
model: amazon-nova/nova-micro-v1
|
||||
api_key: os.environ/AMAZON_NOVA_API_KEY
|
||||
```
|
||||
### 2. Start the proxy
|
||||
```bash
|
||||
litellm --config /path/to/config.yaml
|
||||
```
|
||||
|
||||
### 3. Test it
|
||||
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/chat/completions' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"model": "amazon-nova-micro",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Hello, how are you?"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Supported Models
|
||||
|
||||
| Model Name | Usage | Context Window |
|
||||
|------------|-------|----------------|
|
||||
| Nova Micro | `completion(model="amazon-nova/nova-micro-v1", messages=messages)` | 128K tokens |
|
||||
| Nova Lite | `completion(model="amazon-nova/nova-lite-v1", messages=messages)` | 300K tokens |
|
||||
| Nova Pro | `completion(model="amazon-nova/nova-pro-v1", messages=messages)` | 300K tokens |
|
||||
| Nova Premier | `completion(model="amazon-nova/nova-premier-v1", messages=messages)` | 1M tokens |
|
||||
|
||||
## Usage - Streaming
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="sdk" label="SDK">
|
||||
|
||||
```python
|
||||
import os
|
||||
from litellm import completion
|
||||
|
||||
os.environ["AMAZON_NOVA_API_KEY"] = "your-api-key"
|
||||
|
||||
response = completion(
|
||||
model="amazon-nova/nova-micro-v1",
|
||||
messages=[
|
||||
{"role": "system", "content": "You are a helpful assistant"},
|
||||
{"role": "user", "content": "Tell me about machine learning"}
|
||||
],
|
||||
stream=True
|
||||
)
|
||||
|
||||
for chunk in response:
|
||||
print(chunk.choices[0].delta.content or "", end="")
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="proxy" label="PROXY">
|
||||
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/chat/completions' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"model": "amazon-nova-micro",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Tell me about machine learning"
|
||||
}
|
||||
],
|
||||
"stream": true
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Usage - Function Calling / Tool Usage
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="sdk" label="SDK">
|
||||
|
||||
```python
|
||||
import os
|
||||
from litellm import completion
|
||||
|
||||
os.environ["AMAZON_NOVA_API_KEY"] = "your-api-key"
|
||||
|
||||
tools = [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "getCurrentWeather",
|
||||
"description": "Get the current weather in a given city",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"location": {
|
||||
"type": "string",
|
||||
"description": "City and country e.g. San Francisco, CA"
|
||||
}
|
||||
},
|
||||
"required": ["location"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
response = completion(
|
||||
model="amazon-nova/nova-micro-v1",
|
||||
messages=[
|
||||
{"role": "user", "content": "What's the weather like in San Francisco?"}
|
||||
],
|
||||
tools=tools
|
||||
)
|
||||
|
||||
print(response)
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="proxy" label="PROXY">
|
||||
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/chat/completions' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"model": "amazon-nova-micro",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "What'\''s the weather like in San Francisco?"
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "getCurrentWeather",
|
||||
"description": "Get the current weather in a given city",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"location": {
|
||||
"type": "string",
|
||||
"description": "City and country e.g. San Francisco, CA"
|
||||
}
|
||||
},
|
||||
"required": ["location"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Set temperature, top_p, etc.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="sdk" label="SDK">
|
||||
|
||||
```python
|
||||
import os
|
||||
from litellm import completion
|
||||
|
||||
os.environ["AMAZON_NOVA_API_KEY"] = "your-api-key"
|
||||
|
||||
response = completion(
|
||||
model="amazon-nova/nova-pro-v1",
|
||||
messages=[
|
||||
{"role": "user", "content": "Write a creative story"}
|
||||
],
|
||||
temperature=0.8,
|
||||
max_tokens=500,
|
||||
top_p=0.9
|
||||
)
|
||||
|
||||
print(response)
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="proxy" label="PROXY">
|
||||
|
||||
**Set on yaml**
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: amazon-nova-pro
|
||||
litellm_params:
|
||||
model: amazon-nova/nova-pro-v1
|
||||
temperature: 0.8
|
||||
max_tokens: 500
|
||||
top_p: 0.9
|
||||
```
|
||||
**Set on request**
|
||||
```bash
|
||||
curl --location 'http://0.0.0.0:4000/chat/completions' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"model": "amazon-nova-pro",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Write a creative story"
|
||||
}
|
||||
],
|
||||
"temperature": 0.8,
|
||||
"max_tokens": 500,
|
||||
"top_p": 0.9
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Model Comparison
|
||||
|
||||
| Model | Best For | Speed | Cost | Context |
|
||||
|-------|----------|-------|------|---------|
|
||||
| **Nova Micro** | Simple tasks, high throughput | Fastest | Lowest | 128K |
|
||||
| **Nova Lite** | Balanced performance | Fast | Low | 300K |
|
||||
| **Nova Pro** | Complex reasoning | Medium | Medium | 300K |
|
||||
| **Nova Premier** | Most advanced tasks | Slower | Higher | 1M |
|
||||
|
||||
## Error Handling
|
||||
|
||||
Common error codes and their meanings:
|
||||
|
||||
- `401 Unauthorized`: Invalid API key
|
||||
- `429 Too Many Requests`: Rate limit exceeded
|
||||
- `400 Bad Request`: Invalid request format
|
||||
- `500 Internal Server Error`: Service temporarily unavailable
|
||||
@@ -265,6 +265,7 @@ heroku_key: Optional[str] = None
|
||||
cometapi_key: Optional[str] = None
|
||||
ovhcloud_key: Optional[str] = None
|
||||
lemonade_key: Optional[str] = None
|
||||
amazon_nova_api_key: Optional[str] = None
|
||||
common_cloud_provider_auth_params: dict = {
|
||||
"params": ["project", "region_name", "token"],
|
||||
"providers": ["vertex_ai", "bedrock", "watsonx", "azure", "vertex_ai_beta"],
|
||||
@@ -1359,6 +1360,7 @@ from .llms.ovhcloud.embedding.transformation import OVHCloudEmbeddingConfig
|
||||
from .llms.cometapi.embed.transformation import CometAPIEmbeddingConfig
|
||||
from .llms.lemonade.chat.transformation import LemonadeChatConfig
|
||||
from .llms.snowflake.embedding.transformation import SnowflakeEmbeddingConfig
|
||||
from .llms.amazon_nova.chat.transformation import AmazonNovaChatConfig
|
||||
from .main import * # type: ignore
|
||||
|
||||
# Skills API
|
||||
|
||||
@@ -414,6 +414,7 @@ LITELLM_CHAT_PROVIDERS = [
|
||||
"ovhcloud",
|
||||
"lemonade",
|
||||
"docker_model_runner",
|
||||
"amazon-nova",
|
||||
]
|
||||
|
||||
LITELLM_EMBEDDING_PROVIDERS_SUPPORTING_INPUT_ARRAY_OF_TOKENS = [
|
||||
|
||||
@@ -404,6 +404,8 @@ def get_llm_provider( # noqa: PLR0915
|
||||
custom_llm_provider = "lemonade"
|
||||
elif model.startswith("clarifai/"):
|
||||
custom_llm_provider = "clarifai"
|
||||
elif model.startswith("amazon-nova"):
|
||||
custom_llm_provider = "amazon-nova"
|
||||
if not custom_llm_provider:
|
||||
if litellm.suppress_debug_info is False:
|
||||
print() # noqa
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
"""
|
||||
Translate from OpenAI's `/v1/chat/completions` to Amazon Nova's `/v1/chat/completions`
|
||||
"""
|
||||
from typing import Any, List, Optional, Tuple, Union
|
||||
|
||||
import httpx
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
|
||||
from litellm.secret_managers.main import get_secret_str
|
||||
from litellm.types.llms.openai import (
|
||||
AllMessageValues,
|
||||
)
|
||||
from litellm.types.utils import ModelResponse
|
||||
|
||||
from ...openai_like.chat.transformation import OpenAILikeChatConfig
|
||||
|
||||
|
||||
class AmazonNovaChatConfig(OpenAILikeChatConfig):
|
||||
max_completion_tokens: Optional[int] = None
|
||||
max_tokens: Optional[int] = None
|
||||
metadata: Optional[int] = None
|
||||
temperature: Optional[int] = None
|
||||
top_p: Optional[int] = None
|
||||
tools: Optional[list] = None
|
||||
reasoning_effort: Optional[list] = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
max_completion_tokens: Optional[int] = None,
|
||||
max_tokens: Optional[int] = None,
|
||||
temperature: Optional[int] = None,
|
||||
top_p: Optional[int] = None,
|
||||
tools: Optional[list] = None,
|
||||
reasoning_effort: Optional[list] = None,
|
||||
) -> None:
|
||||
locals_ = locals().copy()
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
||||
@property
|
||||
def custom_llm_provider(self) -> Optional[str]:
|
||||
return "amazon-nova"
|
||||
|
||||
@classmethod
|
||||
def get_config(cls):
|
||||
return super().get_config()
|
||||
|
||||
def _get_openai_compatible_provider_info(
|
||||
self, api_base: Optional[str], api_key: Optional[str]
|
||||
) -> Tuple[Optional[str], Optional[str]]:
|
||||
# Amazon Nova is openai compatible, we just need to set this to custom_openai and have the api_base be Nova's endpoint
|
||||
api_base = (
|
||||
api_base
|
||||
or get_secret_str("AMAZON_NOVA_API_BASE")
|
||||
or "https://api.nova.amazon.com/v1"
|
||||
) # type: ignore
|
||||
|
||||
# Get API key from multiple sources
|
||||
key = (
|
||||
api_key
|
||||
or litellm.amazon_nova_api_key
|
||||
or get_secret_str("AMAZON_NOVA_API_KEY")
|
||||
or litellm.api_key
|
||||
)
|
||||
return api_base, key
|
||||
|
||||
def get_supported_openai_params(self, model: str) -> List:
|
||||
return [
|
||||
"top_p",
|
||||
"temperature",
|
||||
"max_tokens",
|
||||
"max_completion_tokens",
|
||||
"metadata",
|
||||
"stop",
|
||||
"stream",
|
||||
"stream_options",
|
||||
"tools",
|
||||
"tool_choice",
|
||||
"reasoning_effort"
|
||||
]
|
||||
|
||||
def transform_response(
|
||||
self,
|
||||
model: str,
|
||||
raw_response: httpx.Response,
|
||||
model_response: ModelResponse,
|
||||
logging_obj: LiteLLMLoggingObj,
|
||||
request_data: dict,
|
||||
messages: List[AllMessageValues],
|
||||
optional_params: dict,
|
||||
litellm_params: dict,
|
||||
encoding: Any,
|
||||
api_key: Optional[str] = None,
|
||||
json_mode: Optional[bool] = None,
|
||||
) -> ModelResponse:
|
||||
model_response = super().transform_response(
|
||||
model=model,
|
||||
model_response=model_response,
|
||||
raw_response=raw_response,
|
||||
messages=messages,
|
||||
logging_obj=logging_obj,
|
||||
request_data=request_data,
|
||||
encoding=encoding,
|
||||
optional_params=optional_params,
|
||||
json_mode=json_mode,
|
||||
litellm_params=litellm_params,
|
||||
api_key=api_key,
|
||||
)
|
||||
|
||||
# Storing amazon_nova in the model response for easier cost calculation later
|
||||
setattr(model_response, "model", "amazon-nova/" + model)
|
||||
|
||||
return model_response
|
||||
@@ -0,0 +1,21 @@
|
||||
"""
|
||||
Helper util for handling amazon nova cost calculation
|
||||
- e.g.: prompt caching
|
||||
"""
|
||||
|
||||
from typing import TYPE_CHECKING, Tuple
|
||||
|
||||
from litellm.litellm_core_utils.llm_cost_calc.utils import generic_cost_per_token
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from litellm.types.utils import Usage
|
||||
|
||||
|
||||
def cost_per_token(model: str, usage: "Usage") -> Tuple[float, float]:
|
||||
"""
|
||||
Calculates the cost per token for a given model, prompt tokens, and completion tokens.
|
||||
Follows the same logic as Anthropic's cost per token calculation.
|
||||
"""
|
||||
return generic_cost_per_token(
|
||||
model=model, usage=usage, custom_llm_provider="amazon-nova"
|
||||
)
|
||||
@@ -2662,6 +2662,35 @@ def completion( # type: ignore # noqa: PLR0915
|
||||
)
|
||||
|
||||
response = model_response
|
||||
elif custom_llm_provider == "amazon-nova":
|
||||
api_key = (
|
||||
api_key
|
||||
or litellm.amazon_nova_api_key
|
||||
or get_secret_str("AMAZON_NOVA_API_KEY")
|
||||
or litellm.api_key
|
||||
)
|
||||
api_base = (
|
||||
api_base
|
||||
or litellm.api_base
|
||||
or get_secret_str("AMAZON_NOVA_API_BASE")
|
||||
or "https://api.nova.amazon.com/v1"
|
||||
)
|
||||
response = openai_like_chat_completion.completion(
|
||||
model=model,
|
||||
messages=messages,
|
||||
api_base=api_base,
|
||||
model_response=model_response,
|
||||
print_verbose=print_verbose,
|
||||
optional_params=optional_params,
|
||||
litellm_params=litellm_params,
|
||||
logger_fn=logger_fn,
|
||||
encoding=encoding,
|
||||
api_key=api_key,
|
||||
logging_obj=logging,
|
||||
timeout=timeout,
|
||||
custom_llm_provider=custom_llm_provider,
|
||||
custom_prompt_dict=custom_prompt_dict,
|
||||
)
|
||||
elif custom_llm_provider == "huggingface":
|
||||
huggingface_key = (
|
||||
api_key
|
||||
|
||||
@@ -16955,6 +16955,60 @@
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"amazon-nova/nova-micro-v1": {
|
||||
"input_cost_per_token": 3.5e-08,
|
||||
"litellm_provider": "amazon-nova",
|
||||
"max_input_tokens": 128000,
|
||||
"max_output_tokens": 10000,
|
||||
"max_tokens": 10000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.4e-07,
|
||||
"supports_function_calling": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_response_schema": true
|
||||
},
|
||||
"amazon-nova/nova-lite-v1": {
|
||||
"input_cost_per_token": 6e-08,
|
||||
"litellm_provider": "amazon-nova",
|
||||
"max_input_tokens": 300000,
|
||||
"max_output_tokens": 10000,
|
||||
"max_tokens": 10000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 2.4e-07,
|
||||
"supports_function_calling": true,
|
||||
"supports_pdf_input": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"amazon-nova/nova-premier-v1": {
|
||||
"input_cost_per_token": 2.5e-06,
|
||||
"litellm_provider": "amazon-nova",
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 10000,
|
||||
"max_tokens": 10000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.25e-05,
|
||||
"supports_function_calling": true,
|
||||
"supports_pdf_input": true,
|
||||
"supports_prompt_caching": false,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"amazon-nova/nova-pro-v1": {
|
||||
"input_cost_per_token": 8e-07,
|
||||
"litellm_provider": "amazon-nova",
|
||||
"max_input_tokens": 300000,
|
||||
"max_output_tokens": 10000,
|
||||
"max_tokens": 10000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.2e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_pdf_input": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"groq/deepseek-r1-distill-llama-70b": {
|
||||
"input_cost_per_token": 7.5e-07,
|
||||
"litellm_provider": "groq",
|
||||
|
||||
@@ -3002,6 +3002,7 @@ class LlmProviders(str, Enum):
|
||||
WANDB = "wandb"
|
||||
OVHCLOUD = "ovhcloud"
|
||||
LEMONADE = "lemonade"
|
||||
AMAZON_NOVA = "amazon-nova"
|
||||
A2A_AGENT = "a2a_agent"
|
||||
|
||||
|
||||
|
||||
@@ -7254,6 +7254,8 @@ class ProviderConfigManager:
|
||||
return litellm.HyperbolicChatConfig()
|
||||
elif litellm.LlmProviders.OVHCLOUD == provider:
|
||||
return litellm.OVHCloudChatConfig()
|
||||
elif litellm.LlmProviders.AMAZON_NOVA == provider:
|
||||
return litellm.AmazonNovaChatConfig()
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -16955,6 +16955,60 @@
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"amazon-nova/nova-micro-v1": {
|
||||
"input_cost_per_token": 3.5e-08,
|
||||
"litellm_provider": "amazon-nova",
|
||||
"max_input_tokens": 128000,
|
||||
"max_output_tokens": 10000,
|
||||
"max_tokens": 10000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.4e-07,
|
||||
"supports_function_calling": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_response_schema": true
|
||||
},
|
||||
"amazon-nova/nova-lite-v1": {
|
||||
"input_cost_per_token": 6e-08,
|
||||
"litellm_provider": "amazon-nova",
|
||||
"max_input_tokens": 300000,
|
||||
"max_output_tokens": 10000,
|
||||
"max_tokens": 10000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 2.4e-07,
|
||||
"supports_function_calling": true,
|
||||
"supports_pdf_input": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"amazon-nova/nova-premier-v1": {
|
||||
"input_cost_per_token": 2.5e-06,
|
||||
"litellm_provider": "amazon-nova",
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 10000,
|
||||
"max_tokens": 10000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.25e-05,
|
||||
"supports_function_calling": true,
|
||||
"supports_pdf_input": true,
|
||||
"supports_prompt_caching": false,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"amazon-nova/nova-pro-v1": {
|
||||
"input_cost_per_token": 8e-07,
|
||||
"litellm_provider": "amazon-nova",
|
||||
"max_input_tokens": 300000,
|
||||
"max_output_tokens": 10000,
|
||||
"max_tokens": 10000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.2e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_pdf_input": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"groq/deepseek-r1-distill-llama-70b": {
|
||||
"input_cost_per_token": 7.5e-07,
|
||||
"litellm_provider": "groq",
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
import os
|
||||
import sys
|
||||
import pytest
|
||||
|
||||
# Ensure the project root is on the import path
|
||||
sys.path.insert(0, os.path.abspath("../../../../../.."))
|
||||
|
||||
from litellm import completion
|
||||
from litellm.types.utils import ModelResponse, Usage, Choices, Message
|
||||
|
||||
def _has_api_key() -> bool:
|
||||
"""Check if Amazon Nova API key is available"""
|
||||
return "AMAZON_NOVA_API_KEY" in os.environ and os.environ["AMAZON_NOVA_API_KEY"] is not None
|
||||
|
||||
def _create_mock_nova_response():
|
||||
"""Helper function to create mock Amazon Nova response for testing"""
|
||||
return ModelResponse(
|
||||
id="chatcmpl-test-nova-micro",
|
||||
choices=[
|
||||
Choices(
|
||||
finish_reason="stop",
|
||||
index=0,
|
||||
message=Message(
|
||||
content="I am Amazon Nova Micro. 777 times 9 equals 6993.",
|
||||
role="assistant"
|
||||
)
|
||||
)
|
||||
],
|
||||
created=1234567890,
|
||||
model="amazon-nova/nova-micro-v1",
|
||||
object="chat.completion",
|
||||
usage=Usage(
|
||||
prompt_tokens=25,
|
||||
completion_tokens=15,
|
||||
total_tokens=40
|
||||
)
|
||||
)
|
||||
|
||||
def test_amazon_nova_chat_completion_nova_micro():
|
||||
if _has_api_key():
|
||||
response: ModelResponse = completion(model="amazon-nova/nova-micro-v1", messages=[{
|
||||
"role": "system",
|
||||
"content": "You are a helpful assistant"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "What model are you? Can you calculate 777 times 9?"
|
||||
}], api_key=os.environ["AMAZON_NOVA_API_KEY"])
|
||||
else:
|
||||
# Use mock response when API key is not available
|
||||
response = _create_mock_nova_response()
|
||||
# Additional mock-specific assertions for code review reference
|
||||
assert response.choices[0].message.content == "I am Amazon Nova Micro. 777 times 9 equals 6993."
|
||||
assert response.model == "amazon-nova/nova-micro-v1"
|
||||
assert response.usage.prompt_tokens == 25
|
||||
assert response.usage.completion_tokens == 15
|
||||
assert response.object == "chat.completion"
|
||||
assert response.choices[0].finish_reason == "stop"
|
||||
assert response.choices[0].message.role == "assistant"
|
||||
|
||||
# Common assertions for both real and mock responses
|
||||
assert response is not None
|
||||
assert hasattr(response, 'choices')
|
||||
assert len(response.choices) > 0
|
||||
assert response.choices[0].message.content is not None
|
||||
assert response.usage.total_tokens > 0
|
||||
|
||||
@pytest.mark.skipif(not _has_api_key(), reason="Amazon Nova API key not available")
|
||||
def test_amazon_nova_chat_completion_nova_lite():
|
||||
response: ModelResponse = completion(model="amazon-nova/nova-lite-v1", messages=[{
|
||||
"role": "system",
|
||||
"content": "You are a helpful assistant"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "What model are you? Please tell me a poem on rain"
|
||||
}], api_key=os.environ["AMAZON_NOVA_API_KEY"])
|
||||
|
||||
assert response is not None
|
||||
assert hasattr(response, 'choices')
|
||||
assert len(response.choices) > 0
|
||||
assert response.choices[0].message.content is not None
|
||||
assert response.usage.total_tokens > 0
|
||||
|
||||
@pytest.mark.skipif(not _has_api_key(), reason="Amazon Nova API key not available")
|
||||
def test_amazon_nova_chat_completion_nova_pro():
|
||||
response: ModelResponse = completion(model="amazon-nova/nova-pro-v1", messages=[{
|
||||
"role": "system",
|
||||
"content": "You are a helpful assistant"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "What model are you? What is MCP server and how does that help in building GenAI applications?"
|
||||
}], timeout=30, api_key=os.environ["AMAZON_NOVA_API_KEY"])
|
||||
|
||||
assert response is not None
|
||||
assert hasattr(response, 'choices')
|
||||
assert len(response.choices) > 0
|
||||
assert response.choices[0].message.content is not None
|
||||
assert response.usage.total_tokens > 0
|
||||
|
||||
@pytest.mark.skipif(not _has_api_key(), reason="Amazon Nova API key not available")
|
||||
def test_amazon_nova_chat_completion_nova_premier():
|
||||
response: ModelResponse = completion(model="amazon-nova/nova-premier-v1", messages=[{
|
||||
"role": "system",
|
||||
"content": "You are a helpful assistant"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "What model are you? Can you help me understand what Trigonometry is?"
|
||||
}], timeout=60, api_key=os.environ["AMAZON_NOVA_API_KEY"])
|
||||
|
||||
assert response is not None
|
||||
print(response.choices[0].message.content)
|
||||
assert hasattr(response, 'choices')
|
||||
assert len(response.choices) > 0
|
||||
assert response.choices[0].message.content is not None
|
||||
assert response.usage.total_tokens > 0
|
||||
|
||||
@pytest.mark.skipif(not _has_api_key(), reason="Amazon Nova API key not available")
|
||||
def test_amazon_nova_chat_completion_with_tool_usage():
|
||||
response: ModelResponse = completion(model="amazon-nova/nova-micro-v1", messages=[{
|
||||
"role": "system",
|
||||
"content": "You are a helpful assistant"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "What is the temperature in SFO?"
|
||||
}],
|
||||
tools=[{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "getCurrentWeather",
|
||||
"description": "Get the current weather in a given city",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"location": {
|
||||
"type": "string",
|
||||
"description": "City and country e.g. Bogotá, Colombia"
|
||||
}
|
||||
},
|
||||
"required": ["location"]
|
||||
}
|
||||
}
|
||||
}], api_key=os.environ["AMAZON_NOVA_API_KEY"])
|
||||
|
||||
assert response is not None
|
||||
assert hasattr(response, 'choices')
|
||||
assert len(response.choices) > 0
|
||||
assert response.choices[0].message is not None
|
||||
|
||||
@pytest.mark.skipif(not _has_api_key(), reason="Amazon Nova API key not available")
|
||||
def test_amazon_nova_chat_completion_with_stream_response():
|
||||
response = completion(model="amazon-nova/nova-micro-v1", stream=True, messages=[{
|
||||
"role": "system",
|
||||
"content": "You are a helpful assistant"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "What are MMO games? Can you give me some sample references?"
|
||||
}], api_key=os.environ["AMAZON_NOVA_API_KEY"])
|
||||
|
||||
assert response is not None
|
||||
chunks = list(response)
|
||||
assert chunks is not None
|
||||
assert len(chunks) > 0
|
||||
Reference in New Issue
Block a user