[Rust Frontend] Fix Kimi K3 reasoning_effort="none" handling (#53043)
Co-authored-by: Bugen Zhao <i@bugenzhao.com> Signed-off-by: reidliu41 <reid201711@gmail.com>
Reid committed
Aug 21, 2026 at 10:47 UTC
2adf4b9e2a915bd30876ab0c5dba2243f54fe5b7
2 files changed
+50
-9
rust/src/chat/src/renderer/kimi_k3/encoding.rs
+19
-6
@@ -236,11 +236,15 @@ fn thinking_enabled(request: &ChatRequest) -> Result<bool> {
236
if let Some(enable_thinking) = request.parse_template_bool("enable_thinking")? {
237
return Ok(enable_thinking);
238
}
239
+ if let Some(reasoning_effort) = request.chat_options.reasoning_effort {
240
+ return Ok(reasoning_effort != crate::request::ReasoningEffort::None);
241
+ }
242
Ok(request
243
.chat_options
241
- .reasoning_effort
242
- .map(|effort| effort != crate::request::ReasoningEffort::None)
243
- .unwrap_or(true))
244
+ .template_kwargs
245
+ .get("reasoning_effort")
246
+ .and_then(Value::as_str)
247
+ != Some("none"))
248
}
249
250
fn thinking_effort(request: &ChatRequest) -> Result<String> {
@@ -251,13 +255,22 @@ fn thinking_effort(request: &ChatRequest) -> Result<String> {
255
))
256
})?
257
} else if let Some(effort) = request.chat_options.reasoning_effort {
254
- effort.as_str()
258
+ if effort == crate::request::ReasoningEffort::None {
259
+ DEFAULT_THINKING_EFFORT
260
+ } else {
261
+ effort.as_str()
262
+ }
263
} else if let Some(value) = request.chat_options.template_kwargs.get("reasoning_effort") {
256
- value.as_str().ok_or_else(|| {
264
+ let effort = value.as_str().ok_or_else(|| {
265
Error::ChatTemplate(format!(
266
"template kwarg `reasoning_effort` must be a string, got {value}"
267
))
260
- })?
268
+ })?;
269
+ if effort == "none" {
270
+ DEFAULT_THINKING_EFFORT
271
+ } else {
272
+ effort
273
+ }
274
} else {
275
DEFAULT_THINKING_EFFORT
276
};
rust/src/chat/src/renderer/kimi_k3/tests.rs
+31
-3
@@ -329,16 +329,44 @@ fn native_k3_kwargs_take_precedence() {
329
330
#[test]
331
fn standard_none_disables_thinking() {
332
+ let mut request = crate::request::ChatRequest::for_test();
333
+ request
334
+ .chat_options
335
+ .template_kwargs
336
+ .insert("reasoning_effort".to_string(), json!("none"));
337
+
338
+ let rendered = render_request(&request);
339
+
340
+ assert!(!rendered.contains("type=\"thinking-effort\""));
341
+ assert!(rendered.ends_with("<|open|>response<|sep|>"));
342
+}
343
+
344
+#[test]
345
+fn native_thinking_true_overrides_standard_none() {
346
let mut request = crate::request::ChatRequest::for_test();
347
request.chat_options.template_kwargs.extend([
334
- ("enable_thinking".to_string(), json!(false)),
348
+ ("thinking".to_string(), json!(true)),
349
("reasoning_effort".to_string(), json!("none")),
350
]);
351
352
let rendered = render_request(&request);
353
340
- assert!(!rendered.contains("type=\"thinking-effort\""));
341
- assert!(rendered.ends_with("<|open|>response<|sep|>"));
354
+ assert!(rendered.contains("thinking_effort=max"));
355
+ assert!(rendered.ends_with("<|open|>think<|sep|>"));
356
+}
357
+
358
+#[test]
359
+fn enable_thinking_true_overrides_standard_none() {
360
+ let mut request = crate::request::ChatRequest::for_test();
361
+ request.chat_options.template_kwargs.extend([
362
+ ("enable_thinking".to_string(), json!(true)),
363
+ ("reasoning_effort".to_string(), json!("none")),
364
+ ]);
365
+
366
+ let rendered = render_request(&request);
367
+
368
+ assert!(rendered.contains("thinking_effort=max"));
369
+ assert!(rendered.ends_with("<|open|>think<|sep|>"));
370
}
371
372
#[test]