open_ai: Support reasoning content (#43662)
Aero
and
Bennet Bo Fenner
created 2 days ago
Support for Kimi K2 Thinking
Release Notes:
- Added support for thinking traces when using OpenAI-API-compatible AI providers
---------
Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>
Change summary
crates/language_models/src/provider/open_ai.rs | 21 ++++++++++++++++++-
crates/open_ai/src/open_ai.rs | 2 +
2 files changed, 21 insertions(+), 2 deletions(-)
Detailed changes
@@ -426,7 +426,14 @@ pub fn into_open_ai(
for content in message.content {
match content {
MessageContent::Text(text) | MessageContent::Thinking { text, .. } => {
- if !text.trim().is_empty() {
+ let should_add = if message.role == Role::User {
+ // Including whitespace-only user messages can cause error with OpenAI compatible APIs
+ // See https://github.com/zed-industries/zed/issues/40097
+ !text.trim().is_empty()
+ } else {
+ !text.is_empty()
+ };
+ if should_add {
add_message_content_part(
open_ai::MessagePart::Text { text },
message.role,
@@ -792,8 +799,18 @@ impl OpenAiEventMapper {
};
if let Some(delta) = choice.delta.as_ref() {
+ if let Some(reasoning_content) = delta.reasoning_content.clone() {
+ if !reasoning_content.is_empty() {
+ events.push(Ok(LanguageModelCompletionEvent::Thinking {
+ text: reasoning_content,
+ signature: None,
+ }));
+ }
+ }
if let Some(content) = delta.content.clone() {
- events.push(Ok(LanguageModelCompletionEvent::Text(content)));
+ if !content.is_empty() {
+ events.push(Ok(LanguageModelCompletionEvent::Text(content)));
+ }
}
if let Some(tool_calls) = delta.tool_calls.as_ref() {
@@ -463,6 +463,8 @@ pub struct ResponseMessageDelta {
pub content: Option<String>,
#[serde(default, skip_serializing_if = "is_none_or_empty")]
pub tool_calls: Option<Vec<ToolCallChunk>>,
+ #[serde(default, skip_serializing_if = "is_none_or_empty")]
+ pub reasoning_content: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]