mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-29 06:33:28 +00:00
feat(moonshot): add Kimi K3 and Together AI Inkling model support
This commit is contained in:
parent
bd44c9e305
commit
4bdb4d12eb
5 changed files with 258 additions and 4 deletions
|
|
@ -92,6 +92,10 @@ class MoonshotChatConfig(OpenAIGPTConfig):
|
|||
- functions parameter is not supported (use tools instead)
|
||||
- tool_choice doesn't support "required" value
|
||||
- kimi-thinking-preview doesn't support tool calls at all
|
||||
|
||||
Reasoning models (kimi-k3, ...) expose a top-level `reasoning_effort`
|
||||
field to control the thinking budget, so advertise it for them.
|
||||
https://platform.kimi.ai/docs/pricing/chat-k3
|
||||
"""
|
||||
excluded_params: List[str] = ["functions"]
|
||||
|
||||
|
|
@ -100,10 +104,10 @@ class MoonshotChatConfig(OpenAIGPTConfig):
|
|||
excluded_params.extend(["tools", "tool_choice"])
|
||||
|
||||
base_openai_params = super().get_supported_openai_params(model=model)
|
||||
final_params: List[str] = []
|
||||
for param in base_openai_params:
|
||||
if param not in excluded_params:
|
||||
final_params.append(param)
|
||||
final_params = [p for p in base_openai_params if p not in excluded_params]
|
||||
|
||||
if supports_reasoning(model=model, custom_llm_provider="moonshot"):
|
||||
final_params = [*final_params, "reasoning_effort"]
|
||||
|
||||
return final_params
|
||||
|
||||
|
|
|
|||
|
|
@ -27604,6 +27604,22 @@
|
|||
"supports_video_input": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"moonshot/kimi-k3": {
|
||||
"cache_read_input_token_cost": 3e-07,
|
||||
"input_cost_per_token": 3e-06,
|
||||
"litellm_provider": "moonshot",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 1048576,
|
||||
"max_tokens": 1048576,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.5e-05,
|
||||
"source": "https://platform.kimi.ai/docs/pricing/chat-k3",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"moonshot/kimi-latest": {
|
||||
"cache_read_input_token_cost": 1.5e-07,
|
||||
"deprecation_date": "2026-01-28",
|
||||
|
|
@ -34015,6 +34031,38 @@
|
|||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"together_ai/thinkingmachines/Inkling": {
|
||||
"cache_read_input_token_cost": 1.7e-07,
|
||||
"input_cost_per_token": 1e-06,
|
||||
"litellm_provider": "together_ai",
|
||||
"max_input_tokens": 524288,
|
||||
"max_tokens": 524288,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.05e-06,
|
||||
"source": "https://www.together.ai/models/inkling",
|
||||
"supports_audio_input": true,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"together_ai/thinkingmachines/inkling": {
|
||||
"cache_read_input_token_cost": 1.7e-07,
|
||||
"input_cost_per_token": 1e-06,
|
||||
"litellm_provider": "together_ai",
|
||||
"max_input_tokens": 524288,
|
||||
"max_tokens": 524288,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.05e-06,
|
||||
"source": "https://www.together.ai/models/inkling",
|
||||
"supports_audio_input": true,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"together_ai/togethercomputer/CodeLlama-34b-Instruct": {
|
||||
"litellm_provider": "together_ai",
|
||||
"mode": "chat",
|
||||
|
|
|
|||
|
|
@ -27679,6 +27679,22 @@
|
|||
"supports_video_input": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"moonshot/kimi-k3": {
|
||||
"cache_read_input_token_cost": 3e-07,
|
||||
"input_cost_per_token": 3e-06,
|
||||
"litellm_provider": "moonshot",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 1048576,
|
||||
"max_tokens": 1048576,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.5e-05,
|
||||
"source": "https://platform.kimi.ai/docs/pricing/chat-k3",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"moonshot/kimi-latest": {
|
||||
"cache_read_input_token_cost": 1.5e-07,
|
||||
"deprecation_date": "2026-01-28",
|
||||
|
|
@ -34106,6 +34122,38 @@
|
|||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"together_ai/thinkingmachines/Inkling": {
|
||||
"cache_read_input_token_cost": 1.7e-07,
|
||||
"input_cost_per_token": 1e-06,
|
||||
"litellm_provider": "together_ai",
|
||||
"max_input_tokens": 524288,
|
||||
"max_tokens": 524288,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.05e-06,
|
||||
"source": "https://www.together.ai/models/inkling",
|
||||
"supports_audio_input": true,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"together_ai/thinkingmachines/inkling": {
|
||||
"cache_read_input_token_cost": 1.7e-07,
|
||||
"input_cost_per_token": 1e-06,
|
||||
"litellm_provider": "together_ai",
|
||||
"max_input_tokens": 524288,
|
||||
"max_tokens": 524288,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.05e-06,
|
||||
"source": "https://www.together.ai/models/inkling",
|
||||
"supports_audio_input": true,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"together_ai/togethercomputer/CodeLlama-34b-Instruct": {
|
||||
"litellm_provider": "together_ai",
|
||||
"mode": "chat",
|
||||
|
|
|
|||
|
|
@ -63,6 +63,61 @@ class TestMoonshotConfig:
|
|||
# Should NOT include functions (not supported by Moonshot AI)
|
||||
assert "functions" not in supported_params
|
||||
|
||||
def test_reasoning_effort_supported_for_reasoning_models(self):
|
||||
"""Reasoning models (kimi-k3) expose a top-level reasoning_effort control,
|
||||
so it must be advertised as a supported OpenAI param for them."""
|
||||
config = MoonshotChatConfig()
|
||||
|
||||
with patch(
|
||||
"litellm.llms.moonshot.chat.transformation.supports_reasoning",
|
||||
return_value=True,
|
||||
):
|
||||
assert "reasoning_effort" in config.get_supported_openai_params("kimi-k3")
|
||||
|
||||
def test_reasoning_effort_not_supported_for_non_reasoning_models(self):
|
||||
"""Non-reasoning Moonshot models must not advertise reasoning_effort."""
|
||||
config = MoonshotChatConfig()
|
||||
|
||||
with patch(
|
||||
"litellm.llms.moonshot.chat.transformation.supports_reasoning",
|
||||
return_value=False,
|
||||
):
|
||||
assert "reasoning_effort" not in config.get_supported_openai_params("moonshot-v1-8k")
|
||||
|
||||
def test_reasoning_effort_passed_through_for_reasoning_models(self):
|
||||
"""reasoning_effort should be forwarded to the request body for reasoning models."""
|
||||
config = MoonshotChatConfig()
|
||||
|
||||
with patch(
|
||||
"litellm.llms.moonshot.chat.transformation.supports_reasoning",
|
||||
return_value=True,
|
||||
):
|
||||
result = config.map_openai_params(
|
||||
non_default_params={"reasoning_effort": "max"},
|
||||
optional_params={},
|
||||
model="kimi-k3",
|
||||
drop_params=False,
|
||||
)
|
||||
|
||||
assert result.get("reasoning_effort") == "max"
|
||||
|
||||
def test_reasoning_effort_dropped_for_non_reasoning_models(self):
|
||||
"""reasoning_effort must not leak into requests for non-reasoning models."""
|
||||
config = MoonshotChatConfig()
|
||||
|
||||
with patch(
|
||||
"litellm.llms.moonshot.chat.transformation.supports_reasoning",
|
||||
return_value=False,
|
||||
):
|
||||
result = config.map_openai_params(
|
||||
non_default_params={"reasoning_effort": "max"},
|
||||
optional_params={},
|
||||
model="moonshot-v1-8k",
|
||||
drop_params=True,
|
||||
)
|
||||
|
||||
assert "reasoning_effort" not in result
|
||||
|
||||
def test_map_openai_params_excludes_functions(self):
|
||||
"""Test that functions parameter is not mapped"""
|
||||
config = MoonshotChatConfig()
|
||||
|
|
@ -744,6 +799,46 @@ class TestKimiK26ModelRegistry:
|
|||
assert model_info["litellm_provider"] == "moonshot"
|
||||
|
||||
|
||||
class TestKimiK3ModelRegistry:
|
||||
"""Tests that kimi-k3 is correctly registered in the model registry."""
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def model_cost_map(self):
|
||||
"""Load directly from the bundled backup so tests don't depend on remote fetch."""
|
||||
return GetModelCostMap.load_local_model_cost_map()
|
||||
|
||||
def test_kimi_k3_in_model_cost_map(self, model_cost_map):
|
||||
"""kimi-k3 should be present in the model cost map."""
|
||||
assert "moonshot/kimi-k3" in model_cost_map, "moonshot/kimi-k3 not found in model_cost"
|
||||
|
||||
def test_kimi_k3_pricing(self, model_cost_map):
|
||||
"""kimi-k3 pricing should match official Kimi API rates."""
|
||||
model_info = model_cost_map["moonshot/kimi-k3"]
|
||||
assert model_info["input_cost_per_token"] == pytest.approx(3e-06)
|
||||
assert model_info["output_cost_per_token"] == pytest.approx(1.5e-05)
|
||||
assert model_info["cache_read_input_token_cost"] == pytest.approx(3e-07)
|
||||
|
||||
def test_kimi_k3_context_window(self, model_cost_map):
|
||||
"""kimi-k3 should have a 1M (1048576 token) context window."""
|
||||
model_info = model_cost_map["moonshot/kimi-k3"]
|
||||
assert model_info["max_input_tokens"] == 1048576
|
||||
assert model_info["max_tokens"] == 1048576
|
||||
|
||||
def test_kimi_k3_capabilities(self, model_cost_map):
|
||||
"""kimi-k3 should support function calling, vision, tool choice, reasoning, and json schema."""
|
||||
model_info = model_cost_map["moonshot/kimi-k3"]
|
||||
assert model_info.get("supports_function_calling") is True
|
||||
assert model_info.get("supports_tool_choice") is True
|
||||
assert model_info.get("supports_vision") is True
|
||||
assert model_info.get("supports_reasoning") is True
|
||||
assert model_info.get("supports_response_schema") is True
|
||||
|
||||
def test_kimi_k3_provider(self, model_cost_map):
|
||||
"""kimi-k3 should be assigned to the moonshot provider."""
|
||||
model_info = model_cost_map["moonshot/kimi-k3"]
|
||||
assert model_info["litellm_provider"] == "moonshot"
|
||||
|
||||
|
||||
class TestMoonshotResponseSchemaSupport:
|
||||
"""Every model currently live on api.moonshot.ai supports json_schema
|
||||
response_format, which gates discovery via litellm.responses(). The flag
|
||||
|
|
@ -752,6 +847,7 @@ class TestMoonshotResponseSchemaSupport:
|
|||
LIVE_MODELS = [
|
||||
"moonshot/kimi-k2.5",
|
||||
"moonshot/kimi-k2.6",
|
||||
"moonshot/kimi-k3",
|
||||
"moonshot/moonshot-v1-8k",
|
||||
"moonshot/moonshot-v1-32k",
|
||||
"moonshot/moonshot-v1-128k",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
"""
|
||||
Registry tests for Together AI models in the bundled model cost map.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath("../../../../.."))
|
||||
|
||||
import pytest
|
||||
|
||||
from litellm.litellm_core_utils.get_model_cost_map import GetModelCostMap
|
||||
|
||||
INKLING_KEYS = [
|
||||
"together_ai/thinkingmachines/Inkling",
|
||||
"together_ai/thinkingmachines/inkling",
|
||||
]
|
||||
|
||||
|
||||
class TestInklingModelRegistry:
|
||||
"""Tests that Thinking Machines Lab's Inkling is registered under together_ai."""
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def model_cost_map(self):
|
||||
"""Load directly from the bundled backup so tests don't depend on remote fetch."""
|
||||
return GetModelCostMap.load_local_model_cost_map()
|
||||
|
||||
@pytest.mark.parametrize("model", INKLING_KEYS)
|
||||
def test_inkling_in_model_cost_map(self, model, model_cost_map):
|
||||
assert model in model_cost_map, f"{model} not found in model_cost"
|
||||
|
||||
@pytest.mark.parametrize("model", INKLING_KEYS)
|
||||
def test_inkling_pricing(self, model, model_cost_map):
|
||||
"""Inkling pricing should match Together AI's published serverless rates."""
|
||||
model_info = model_cost_map[model]
|
||||
assert model_info["input_cost_per_token"] == pytest.approx(1e-06)
|
||||
assert model_info["output_cost_per_token"] == pytest.approx(4.05e-06)
|
||||
assert model_info["cache_read_input_token_cost"] == pytest.approx(1.7e-07)
|
||||
|
||||
@pytest.mark.parametrize("model", INKLING_KEYS)
|
||||
def test_inkling_context_window(self, model, model_cost_map):
|
||||
"""Inkling should expose a 524K token context window."""
|
||||
assert model_cost_map[model]["max_input_tokens"] == 524288
|
||||
|
||||
@pytest.mark.parametrize("model", INKLING_KEYS)
|
||||
def test_inkling_capabilities(self, model, model_cost_map):
|
||||
"""Inkling is a multimodal reasoning model with tools and json schema support."""
|
||||
model_info = model_cost_map[model]
|
||||
assert model_info.get("supports_function_calling") is True
|
||||
assert model_info.get("supports_tool_choice") is True
|
||||
assert model_info.get("supports_reasoning") is True
|
||||
assert model_info.get("supports_vision") is True
|
||||
assert model_info.get("supports_audio_input") is True
|
||||
assert model_info.get("supports_response_schema") is True
|
||||
|
||||
@pytest.mark.parametrize("model", INKLING_KEYS)
|
||||
def test_inkling_provider(self, model, model_cost_map):
|
||||
assert model_cost_map[model]["litellm_provider"] == "together_ai"
|
||||
Loading…
Add table
Reference in a new issue