mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-02 02:11:58 +00:00
feat(moonshot): advertise json_schema response support on live models (#29683)
litellm.responses() already routes Moonshot through the responses->chat-completions bridge, and Moonshot honors response_format json_schema on chat completions. The cost-map entries left supports_response_schema unset, so discovery layers that gate on that flag dropped Moonshot from structured-output / responses listings even though the capability works end to end. Set supports_response_schema on the nine models currently live on api.moonshot.ai: kimi-k2.5, kimi-k2.6, the moonshot-v1 8k/32k/128k text and vision-preview variants, and moonshot-v1-auto. Verified against the live API that each honors json_schema and that litellm.responses() returns schema-valid structured output through the bridge.
This commit is contained in:
parent
13dd954593
commit
21596c82be
3 changed files with 54 additions and 23 deletions
|
|
@ -25024,6 +25024,7 @@
|
|||
"source": "https://platform.moonshot.ai/docs/guide/kimi-k2-5-quickstart",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_video_input": true,
|
||||
"supports_vision": true
|
||||
|
|
@ -25040,6 +25041,7 @@
|
|||
"source": "https://platform.kimi.ai/docs/pricing/chat-k26",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_video_input": true,
|
||||
"supports_vision": true
|
||||
|
|
@ -25152,6 +25154,7 @@
|
|||
"output_cost_per_token": 5e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"moonshot/moonshot-v1-128k-0430": {
|
||||
|
|
@ -25176,6 +25179,7 @@
|
|||
"output_cost_per_token": 5e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
|
|
@ -25189,6 +25193,7 @@
|
|||
"output_cost_per_token": 3e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"moonshot/moonshot-v1-32k-0430": {
|
||||
|
|
@ -25213,6 +25218,7 @@
|
|||
"output_cost_per_token": 3e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
|
|
@ -25226,6 +25232,7 @@
|
|||
"output_cost_per_token": 2e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"moonshot/moonshot-v1-8k-0430": {
|
||||
|
|
@ -25250,6 +25257,7 @@
|
|||
"output_cost_per_token": 2e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
|
|
@ -25263,6 +25271,7 @@
|
|||
"output_cost_per_token": 5e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"morph/morph-v3-fast": {
|
||||
|
|
|
|||
|
|
@ -25024,6 +25024,7 @@
|
|||
"source": "https://platform.moonshot.ai/docs/guide/kimi-k2-5-quickstart",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_video_input": true,
|
||||
"supports_vision": true
|
||||
|
|
@ -25040,6 +25041,7 @@
|
|||
"source": "https://platform.kimi.ai/docs/pricing/chat-k26",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_video_input": true,
|
||||
"supports_vision": true
|
||||
|
|
@ -25152,6 +25154,7 @@
|
|||
"output_cost_per_token": 5e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"moonshot/moonshot-v1-128k-0430": {
|
||||
|
|
@ -25176,6 +25179,7 @@
|
|||
"output_cost_per_token": 5e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
|
|
@ -25189,6 +25193,7 @@
|
|||
"output_cost_per_token": 3e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"moonshot/moonshot-v1-32k-0430": {
|
||||
|
|
@ -25213,6 +25218,7 @@
|
|||
"output_cost_per_token": 3e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
|
|
@ -25226,6 +25232,7 @@
|
|||
"output_cost_per_token": 2e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"moonshot/moonshot-v1-8k-0430": {
|
||||
|
|
@ -25250,6 +25257,7 @@
|
|||
"output_cost_per_token": 2e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
|
|
@ -25263,6 +25271,7 @@
|
|||
"output_cost_per_token": 5e-06,
|
||||
"source": "https://platform.moonshot.ai/docs/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"morph/morph-v3-fast": {
|
||||
|
|
|
|||
|
|
@ -9,15 +9,12 @@ import os
|
|||
import sys
|
||||
from unittest.mock import patch
|
||||
|
||||
sys.path.insert(
|
||||
0, os.path.abspath("../../../../..")
|
||||
) # Adds the parent directory to the system path
|
||||
sys.path.insert(0, os.path.abspath("../../../../..")) # Adds the parent directory to the system path
|
||||
|
||||
import pytest
|
||||
|
||||
import litellm
|
||||
import litellm.utils
|
||||
from litellm import completion
|
||||
from litellm.litellm_core_utils.get_model_cost_map import GetModelCostMap
|
||||
from litellm.llms.moonshot.chat.transformation import MoonshotChatConfig
|
||||
|
||||
|
|
@ -232,10 +229,7 @@ class TestMoonshotConfig:
|
|||
assert result["messages"][0]["role"] == "user"
|
||||
assert result["messages"][0]["content"] == "What's the weather like?"
|
||||
assert result["messages"][1]["role"] == "user"
|
||||
assert (
|
||||
result["messages"][1]["content"]
|
||||
== "Please select a tool to handle the current issue."
|
||||
)
|
||||
assert result["messages"][1]["content"] == "Please select a tool to handle the current issue."
|
||||
|
||||
# Check that tool_choice was removed but tools are preserved
|
||||
assert "tool_choice" not in result
|
||||
|
|
@ -273,10 +267,7 @@ class TestMoonshotConfig:
|
|||
|
||||
# Check that the message was added
|
||||
assert len(result["messages"]) == 2
|
||||
assert (
|
||||
result["messages"][1]["content"]
|
||||
== "Please select a tool to handle the current issue."
|
||||
)
|
||||
assert result["messages"][1]["content"] == "Please select a tool to handle the current issue."
|
||||
|
||||
def test_tool_choice_non_required_preserved(self):
|
||||
"""Test that non-'required' tool_choice values are preserved"""
|
||||
|
|
@ -501,9 +492,7 @@ class TestMoonshotConfig:
|
|||
assert result[0].get("reasoning_content") == "stored thinking"
|
||||
# The promoted key must be removed from provider_specific_fields to
|
||||
# avoid sending the value twice in the serialised request body
|
||||
assert "reasoning_content" not in (
|
||||
result[0].get("provider_specific_fields") or {}
|
||||
)
|
||||
assert "reasoning_content" not in (result[0].get("provider_specific_fields") or {})
|
||||
|
||||
def test_reasoning_model_fill_called_from_transform_request(self):
|
||||
"""transform_request injects reasoning_content end-to-end for reasoning models."""
|
||||
|
|
@ -603,10 +592,7 @@ class TestMoonshotConfig:
|
|||
result = config.fill_reasoning_content(messages)
|
||||
|
||||
# reasoning_content should be preserved, not replaced with placeholder
|
||||
assert (
|
||||
result[0].get("reasoning_content")
|
||||
== "<thinking>User wants weather</thinking>"
|
||||
)
|
||||
assert result[0].get("reasoning_content") == "<thinking>User wants weather</thinking>"
|
||||
|
||||
def test_reasoning_content_preserved_in_multi_turn_flow(self):
|
||||
"""reasoning_content is preserved through multi-turn conversation flow.
|
||||
|
|
@ -650,10 +636,7 @@ class TestMoonshotConfig:
|
|||
result = config.fill_reasoning_content(messages)
|
||||
|
||||
# reasoning_content should be preserved in the assistant message
|
||||
assert (
|
||||
result[1].get("reasoning_content")
|
||||
== "<thinking>Planning to call weather tool</thinking>"
|
||||
)
|
||||
assert result[1].get("reasoning_content") == "<thinking>Planning to call weather tool</thinking>"
|
||||
|
||||
|
||||
class TestKimiK26ModelRegistry:
|
||||
|
|
@ -695,3 +678,33 @@ class TestKimiK26ModelRegistry:
|
|||
"""kimi-k2.6 should be assigned to the moonshot provider."""
|
||||
model_info = model_cost_map["moonshot/kimi-k2.6"]
|
||||
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
|
||||
must be true so the capability is advertised honestly."""
|
||||
|
||||
LIVE_MODELS = [
|
||||
"moonshot/kimi-k2.5",
|
||||
"moonshot/kimi-k2.6",
|
||||
"moonshot/moonshot-v1-8k",
|
||||
"moonshot/moonshot-v1-32k",
|
||||
"moonshot/moonshot-v1-128k",
|
||||
"moonshot/moonshot-v1-8k-vision-preview",
|
||||
"moonshot/moonshot-v1-32k-vision-preview",
|
||||
"moonshot/moonshot-v1-128k-vision-preview",
|
||||
"moonshot/moonshot-v1-auto",
|
||||
]
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def model_cost_map(self):
|
||||
return GetModelCostMap.load_local_model_cost_map()
|
||||
|
||||
@pytest.mark.parametrize("model", LIVE_MODELS)
|
||||
def test_live_model_supports_response_schema(self, model, model_cost_map):
|
||||
assert model_cost_map[model].get("supports_response_schema") is True
|
||||
|
||||
def test_supports_response_schema_utility_reports_true(self, model_cost_map, monkeypatch):
|
||||
monkeypatch.setattr(litellm, "model_cost", model_cost_map)
|
||||
assert litellm.utils.supports_response_schema(model="moonshot/kimi-k2.5") is True
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue