Skip to content

Commit 5043aff

Browse files
fontanierhHenry Fontanier
and
Henry Fontanier
authored
feat: parse and expose DeepSeek's reasoning content (#10121)
Co-authored-by: Henry Fontanier <henry@dust.tt>
1 parent 0c6104b commit 5043aff

File tree

4 files changed

+36
-0
lines changed

4 files changed

+36
-0
lines changed

core/src/providers/anthropic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ impl TryFrom<ChatResponse> for AssistantChatMessage {
557557
role: ChatMessageRole::Assistant,
558558
name: None,
559559
content: text_content,
560+
reasoning_content: None,
560561
function_call,
561562
function_calls,
562563
})

core/src/providers/chat_messages.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ pub struct AssistantChatMessage {
7676
#[serde(skip_serializing_if = "Option::is_none")]
7777
pub content: Option<String>,
7878
#[serde(skip_serializing_if = "Option::is_none")]
79+
pub reasoning_content: Option<String>,
80+
#[serde(skip_serializing_if = "Option::is_none")]
7981
pub function_call: Option<ChatFunctionCall>,
8082
#[serde(skip_serializing_if = "Option::is_none")]
8183
pub function_calls: Option<Vec<ChatFunctionCall>>,

core/src/providers/mistral.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ impl TryFrom<&MistralChatMessage> for AssistantChatMessage {
237237

238238
Ok(AssistantChatMessage {
239239
content,
240+
reasoning_content: None,
240241
role,
241242
name: None,
242243
function_call,

core/src/providers/openai_compatible_helpers.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ pub struct OpenAIChatMessage {
252252
#[serde(skip_serializing_if = "Option::is_none")]
253253
pub content: Option<OpenAIChatMessageContent>,
254254
#[serde(skip_serializing_if = "Option::is_none")]
255+
pub reasoning_content: Option<String>,
256+
#[serde(skip_serializing_if = "Option::is_none")]
255257
pub name: Option<String>,
256258
#[serde(skip_serializing_if = "Option::is_none")]
257259
pub tool_calls: Option<Vec<OpenAIToolCall>>,
@@ -264,6 +266,8 @@ pub struct OpenAICompletionChatMessage {
264266
#[serde(skip_serializing_if = "Option::is_none")]
265267
pub content: Option<String>,
266268
#[serde(skip_serializing_if = "Option::is_none")]
269+
pub reasoning_content: Option<String>,
270+
#[serde(skip_serializing_if = "Option::is_none")]
267271
pub name: Option<String>,
268272
pub role: OpenAIChatMessageRole,
269273
#[serde(skip_serializing_if = "Option::is_none")]
@@ -331,6 +335,10 @@ impl TryFrom<&OpenAICompletionChatMessage> for AssistantChatMessage {
331335
Some(c) => Some(c.clone()),
332336
None => None,
333337
};
338+
let reasoning_content = match cm.reasoning_content.as_ref() {
339+
Some(c) => Some(c.clone()),
340+
None => None,
341+
};
334342

335343
let function_calls = if let Some(tool_calls) = cm.tool_calls.as_ref() {
336344
let cfc = tool_calls
@@ -360,6 +368,7 @@ impl TryFrom<&OpenAICompletionChatMessage> for AssistantChatMessage {
360368

361369
Ok(AssistantChatMessage {
362370
content,
371+
reasoning_content,
363372
role,
364373
name,
365374
function_call,
@@ -429,6 +438,7 @@ impl TryFrom<&ChatMessage> for OpenAIChatMessage {
429438
Some(c) => Some(OpenAIChatMessageContent::try_from(c)?),
430439
None => None,
431440
},
441+
reasoning_content: None,
432442
name: assistant_msg.name.clone(),
433443
role: OpenAIChatMessageRole::from(&assistant_msg.role),
434444
tool_calls: match assistant_msg.function_calls.as_ref() {
@@ -443,20 +453,23 @@ impl TryFrom<&ChatMessage> for OpenAIChatMessage {
443453
}),
444454
ChatMessage::Function(function_msg) => Ok(OpenAIChatMessage {
445455
content: Some(OpenAIChatMessageContent::try_from(&function_msg.content)?),
456+
reasoning_content: None,
446457
name: None,
447458
role: OpenAIChatMessageRole::Tool,
448459
tool_calls: None,
449460
tool_call_id: Some(function_msg.function_call_id.clone()),
450461
}),
451462
ChatMessage::System(system_msg) => Ok(OpenAIChatMessage {
452463
content: Some(OpenAIChatMessageContent::try_from(&system_msg.content)?),
464+
reasoning_content: None,
453465
name: None,
454466
role: OpenAIChatMessageRole::from(&system_msg.role),
455467
tool_calls: None,
456468
tool_call_id: None,
457469
}),
458470
ChatMessage::User(user_msg) => Ok(OpenAIChatMessage {
459471
content: Some(OpenAIChatMessageContent::try_from(&user_msg.content)?),
472+
reasoning_content: None,
460473
name: user_msg.name.clone(),
461474
role: OpenAIChatMessageRole::from(&user_msg.role),
462475
tool_calls: None,
@@ -806,6 +819,7 @@ fn to_openai_messages(
806819
// Case 3: there's more than one content, the content isn't text or we don't want to squash them => keep structured format
807820
(_, _, _) => Some(OpenAIChatMessageContent::Structured(contents)),
808821
},
822+
reasoning_content: None,
809823
}
810824
}
811825
})
@@ -829,6 +843,7 @@ fn to_openai_messages(
829843
.collect()
830844
}),
831845
content: m.content,
846+
reasoning_content: None,
832847
}
833848
})
834849
// Remove system messages if requested.
@@ -1215,6 +1230,7 @@ async fn streamed_chat_completion(
12151230
.map(|c| OpenAIChatChoice {
12161231
message: OpenAICompletionChatMessage {
12171232
content: Some("".to_string()),
1233+
reasoning_content: None,
12181234
name: None,
12191235
role: OpenAIChatMessageRole::System,
12201236
tool_calls: None,
@@ -1272,6 +1288,14 @@ async fn streamed_chat_completion(
12721288
},
12731289
};
12741290

1291+
match a.choices[j].delta.get("reasoning_content") {
1292+
None => (),
1293+
Some(reasoning_content) => {
1294+
c.choices[j].message.reasoning_content =
1295+
Some(reasoning_content.as_str().unwrap_or("").to_string());
1296+
}
1297+
};
1298+
12751299
if let Some(tool_calls) = a.choices[j]
12761300
.delta
12771301
.get("tool_calls")
@@ -1346,6 +1370,10 @@ async fn streamed_chat_completion(
13461370
None => None,
13471371
Some(c) => Some(c.trim().to_string()),
13481372
};
1373+
m.message.reasoning_content = match m.message.reasoning_content.as_ref() {
1374+
None => None,
1375+
Some(c) => Some(c.trim().to_string()),
1376+
};
13491377
}
13501378

13511379
Ok((completion, request_id))
@@ -1497,6 +1525,10 @@ async fn chat_completion(
14971525
None => None,
14981526
Some(c) => Some(c.trim().to_string()),
14991527
};
1528+
m.message.reasoning_content = match m.message.reasoning_content.as_ref() {
1529+
None => None,
1530+
Some(c) => Some(c.trim().to_string()),
1531+
};
15001532
}
15011533

15021534
Ok((completion, request_id))

0 commit comments

Comments
 (0)