fix(ai): skip temperature and thinking-disable for Kimi K2.5+ models
This commit is contained in:
parent
4ebf041601
commit
a9d1b48dd5
|
|
@ -384,8 +384,29 @@ fn is_openai_reasoning_model(model: &str) -> bool {
|
|||
model.starts_with("gpt-5") || model.starts_with("o1") || model.starts_with("o3") || model.starts_with("o4")
|
||||
}
|
||||
|
||||
/// Kimi K2.5+ models (including K2.7-Code) require fixed sampling parameters:
|
||||
/// temperature=1.0, top_p=0.95, n=1. Any other value returns an error.
|
||||
///
|
||||
/// Matches `kimi-k2.5`, `kimi-k2.6`, `kimi-k2.7-code`, K3+, and future versions,
|
||||
/// while excluding older K2 variants (`kimi-k2`, `kimi-k2-thinking`, etc.).
|
||||
/// Regex equivalent: /kimi-k(?:2\.[5-9]\d*|[3-9]\d*)/
|
||||
fn is_kimi_model(model: &str) -> bool {
|
||||
let model = model.trim().to_ascii_lowercase();
|
||||
if let Some(rest) = model.strip_prefix("kimi-k") {
|
||||
if rest.starts_with("2.") && rest.len() > 2 {
|
||||
// K2.x — the digit after "2." must be >= 5 (so K2.5+)
|
||||
rest[2..].chars().next().map_or(false, |c| c.is_ascii_digit() && c >= '5')
|
||||
} else {
|
||||
// K3+ — first char must be digit >= 3
|
||||
rest.chars().next().map_or(false, |c| c.is_ascii_digit() && c >= '3')
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn supports_temperature(config: &AiConfig) -> bool {
|
||||
!(is_openai_api_config(config) && is_openai_reasoning_model(&config.model))
|
||||
!(is_openai_api_config(config) && is_openai_reasoning_model(&config.model)) && !is_kimi_model(&config.model)
|
||||
}
|
||||
|
||||
pub fn add_temperature_if_supported(body: &mut serde_json::Value, request: &AiCompletionRequest) {
|
||||
|
|
@ -654,7 +675,7 @@ pub async fn call_openai_compatible(client: &reqwest::Client, request: AiComplet
|
|||
"max_tokens": request.max_tokens.unwrap_or(2048),
|
||||
});
|
||||
add_temperature_if_supported(&mut body_obj, &request);
|
||||
if !request.config.enable_thinking {
|
||||
if !request.config.enable_thinking && !is_kimi_model(&request.config.model) {
|
||||
body_obj["extra_body"] = json!({
|
||||
"chat_template_kwargs": { "enable_thinking": false }
|
||||
});
|
||||
|
|
@ -1102,7 +1123,7 @@ async fn stream_openai(
|
|||
"stream": true,
|
||||
});
|
||||
add_temperature_if_supported(&mut body_obj, request);
|
||||
if !request.config.enable_thinking {
|
||||
if !request.config.enable_thinking && !is_kimi_model(&request.config.model) {
|
||||
body_obj["extra_body"] = json!({
|
||||
"chat_template_kwargs": { "enable_thinking": false }
|
||||
});
|
||||
|
|
@ -2001,7 +2022,7 @@ pub fn load_config(path: &Path) -> Result<Option<AiConfig>, String> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
build_ai_http_client, claude_headers, claude_system_prompt, gemini_text, openai_response_text,
|
||||
build_ai_http_client, claude_headers, claude_system_prompt, gemini_text, is_kimi_model, openai_response_text,
|
||||
openai_stream_reasoning, openai_stream_text, parse_model_list_response, resolve_endpoint,
|
||||
resolve_model_list_endpoint, responses_max_output_tokens, responses_text, supports_temperature,
|
||||
validate_config, AiApiStyle, AiAuthMethod, AiConfig, AiModelInfo, AiProvider, AUTHORIZATION,
|
||||
|
|
@ -2299,6 +2320,41 @@ mod tests {
|
|||
config.endpoint = "http://localhost:11434/v1".to_string();
|
||||
config.model = "gpt-5-local".to_string();
|
||||
assert!(supports_temperature(&config));
|
||||
|
||||
// Kimi K2.5+ models: temperature is forced to 1.0 by the API
|
||||
config.model = "kimi-k2.7-code".to_string();
|
||||
assert!(!supports_temperature(&config));
|
||||
assert!(is_kimi_model(&config.model));
|
||||
|
||||
config.model = "kimi-k2.6".to_string();
|
||||
assert!(!supports_temperature(&config));
|
||||
assert!(is_kimi_model(&config.model));
|
||||
|
||||
config.model = "kimi-k2.5".to_string();
|
||||
assert!(!supports_temperature(&config));
|
||||
assert!(is_kimi_model(&config.model));
|
||||
|
||||
// K3+ should also be matched
|
||||
config.model = "kimi-k3".to_string();
|
||||
assert!(!supports_temperature(&config));
|
||||
assert!(is_kimi_model(&config.model));
|
||||
|
||||
// Older K2 variants should NOT be matched (they support custom temperature)
|
||||
config.model = "kimi-k2".to_string();
|
||||
assert!(supports_temperature(&config));
|
||||
assert!(!is_kimi_model(&config.model));
|
||||
|
||||
config.model = "kimi-k2-thinking".to_string();
|
||||
assert!(supports_temperature(&config));
|
||||
assert!(!is_kimi_model(&config.model));
|
||||
|
||||
config.model = "kimi-k2-0711-preview".to_string();
|
||||
assert!(supports_temperature(&config));
|
||||
assert!(!is_kimi_model(&config.model));
|
||||
|
||||
config.model = "kimi-k2.4".to_string();
|
||||
assert!(supports_temperature(&config));
|
||||
assert!(!is_kimi_model(&config.model));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Reference in New Issue