Skip to content

Commit 537345a

Browse files
committed
feat: Introduce reasoning delta
Stop gap to differentiate between the full reasoning and partial
1 parent 4ff8c60 commit 537345a

File tree

10 files changed

+63
-29
lines changed

10 files changed

+63
-29
lines changed

rig-bedrock/src/streaming.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,9 @@ impl CompletionModel {
107107
}
108108

109109
if !text.is_empty() {
110-
yield Ok(RawStreamingChoice::Reasoning {
110+
yield Ok(RawStreamingChoice::ReasoningDelta {
111111
reasoning: text.clone(),
112112
id: None,
113-
signature: None,
114113
})
115114
}
116115
},

rig-core/src/agent/prompt_request/streaming.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,10 @@ where
359359
yield Ok(MultiTurnStreamItem::stream_item(StreamedAssistantContent::Reasoning(rig::message::Reasoning { reasoning, id, signature })));
360360
did_call_tool = false;
361361
},
362+
Ok(StreamedAssistantContent::ReasoningDelta { reasoning, id }) => {
363+
yield Ok(MultiTurnStreamItem::stream_item(StreamedAssistantContent::ReasoningDelta { reasoning, id }));
364+
did_call_tool = false;
365+
},
362366
Ok(StreamedAssistantContent::Final(final_resp)) => {
363367
if let Some(usage) = final_resp.token_usage() { aggregated_usage += usage; };
364368
if is_text_response {

rig-core/src/providers/anthropic/streaming.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,9 @@ fn handle_event(
323323
state.thinking.push_str(thinking);
324324
}
325325

326-
Some(Ok(RawStreamingChoice::Reasoning {
326+
Some(Ok(RawStreamingChoice::ReasoningDelta {
327327
id: None,
328328
reasoning: thinking.clone(),
329-
signature: None,
330329
}))
331330
}
332331
ContentDelta::SignatureDelta { signature } => {
@@ -504,11 +503,11 @@ mod tests {
504503
let choice = result.unwrap().unwrap();
505504

506505
match choice {
507-
RawStreamingChoice::Reasoning { id, reasoning, .. } => {
506+
RawStreamingChoice::ReasoningDelta { id, reasoning, .. } => {
508507
assert_eq!(id, None);
509508
assert_eq!(reasoning, "Analyzing the request...");
510509
}
511-
_ => panic!("Expected Reasoning choice"),
510+
_ => panic!("Expected ReasoningDelta choice"),
512511
}
513512

514513
// Verify thinking state was updated
@@ -584,10 +583,10 @@ mod tests {
584583
let choice = result.unwrap().unwrap();
585584

586585
match choice {
587-
RawStreamingChoice::Reasoning { reasoning, .. } => {
586+
RawStreamingChoice::ReasoningDelta { reasoning, .. } => {
588587
assert_eq!(reasoning, "Thinking while tool is active...");
589588
}
590-
_ => panic!("Expected Reasoning choice"),
589+
_ => panic!("Expected ReasoningDelta choice"),
591590
}
592591

593592
// Tool call state should remain unchanged

rig-core/src/providers/deepseek.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -879,10 +879,9 @@ where
879879

880880
// DeepSeek-specific reasoning stream
881881
if let Some(content) = &delta.reasoning_content {
882-
yield Ok(crate::streaming::RawStreamingChoice::Reasoning {
883-
reasoning: content.to_string(),
882+
yield Ok(crate::streaming::RawStreamingChoice::ReasoningDelta {
884883
id: None,
885-
signature: None,
884+
reasoning: content.to_string()
886885
});
887886
}
888887

rig-core/src/providers/gemini/streaming.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ where
158158
thought: Some(true),
159159
..
160160
} => {
161-
yield Ok(streaming::RawStreamingChoice::Reasoning { reasoning: text.clone(), id: None, signature: None });
161+
yield Ok(streaming::RawStreamingChoice::ReasoningDelta {
162+
id: None,
163+
reasoning: text.clone(),
164+
});
162165
},
163166
Part {
164167
part: PartKind::Text(text),

rig-core/src/providers/groq.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -780,10 +780,9 @@ where
780780
if let Some(choice) = data.choices.first() {
781781
match &choice.delta {
782782
StreamingDelta::Reasoning { reasoning } => {
783-
yield Ok(crate::streaming::RawStreamingChoice::Reasoning {
783+
yield Ok(crate::streaming::RawStreamingChoice::ReasoningDelta {
784784
id: None,
785785
reasoning: reasoning.to_string(),
786-
signature: None,
787786
});
788787
}
789788

rig-core/src/providers/ollama.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -738,10 +738,9 @@ where
738738
if let Some(thinking_content) = thinking
739739
&& !thinking_content.is_empty() {
740740
thinking_response += &thinking_content;
741-
yield RawStreamingChoice::Reasoning {
742-
reasoning: thinking_content,
741+
yield RawStreamingChoice::ReasoningDelta {
743742
id: None,
744-
signature: None,
743+
reasoning: thinking_content,
745744
};
746745
}
747746

rig-core/src/providers/openai/responses_api/streaming.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ pub enum ItemChunkKind {
117117
ReasoningSummaryPartAdded(SummaryPartChunk),
118118
#[serde(rename = "response.reasoning_summary_part.done")]
119119
ReasoningSummaryPartDone(SummaryPartChunk),
120-
#[serde(rename = "response.reasoning_summary_text.added")]
121-
ReasoningSummaryTextAdded(SummaryTextChunk),
120+
#[serde(rename = "response.reasoning_summary_text.delta")]
121+
ReasoningSummaryTextDelta(SummaryTextChunk),
122122
#[serde(rename = "response.reasoning_summary_text.done")]
123123
ReasoningSummaryTextDone(SummaryTextChunk),
124124
}
@@ -295,7 +295,11 @@ where
295295
})
296296
.collect::<Vec<String>>()
297297
.join("\n");
298-
yield Ok(streaming::RawStreamingChoice::Reasoning { reasoning, id: Some(id.to_string()), signature: None })
298+
yield Ok(streaming::RawStreamingChoice::Reasoning {
299+
id: Some(id.to_string()),
300+
reasoning,
301+
signature: None,
302+
})
299303
}
300304
_ => continue
301305
}
@@ -304,6 +308,9 @@ where
304308
combined_text.push_str(&delta.delta);
305309
yield Ok(streaming::RawStreamingChoice::Message(delta.delta.clone()))
306310
}
311+
ItemChunkKind::ReasoningSummaryTextDelta(delta) => {
312+
yield Ok(streaming::RawStreamingChoice::ReasoningDelta { id: None, reasoning: delta.delta.clone() })
313+
}
307314
ItemChunkKind::RefusalDelta(delta) => {
308315
combined_text.push_str(&delta.delta);
309316
yield Ok(streaming::RawStreamingChoice::Message(delta.delta.clone()))

rig-core/src/providers/openrouter/streaming.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,10 +252,9 @@ where
252252

253253
// Streamed reasoning content
254254
if let Some(reasoning) = &delta.reasoning && !reasoning.is_empty() {
255-
yield Ok(streaming::RawStreamingChoice::Reasoning {
255+
yield Ok(streaming::RawStreamingChoice::ReasoningDelta {
256256
reasoning: reasoning.clone(),
257257
id: None,
258-
signature: None,
259258
});
260259
}
261260

rig-core/src/streaming.rs

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,17 @@ where
7979
},
8080
/// A tool call partial/delta
8181
ToolCallDelta { id: String, delta: String },
82-
/// A reasoning chunk
82+
/// A reasoning (in its entirety)
8383
Reasoning {
8484
id: Option<String>,
8585
reasoning: String,
8686
signature: Option<String>,
8787
},
88+
/// A reasoning partial/delta
89+
ReasoningDelta {
90+
id: Option<String>,
91+
reasoning: String,
92+
},
8893

8994
/// The final response object, must be yielded if you want the
9095
/// `response` field to be populated on the `StreamingCompletionResponse`
@@ -231,15 +236,19 @@ where
231236
id,
232237
reasoning,
233238
signature,
234-
} => {
239+
} => Poll::Ready(Some(Ok(StreamedAssistantContent::Reasoning(Reasoning {
240+
id,
241+
reasoning: vec![reasoning],
242+
signature,
243+
})))),
244+
RawStreamingChoice::ReasoningDelta { id, reasoning } => {
235245
// Forward the streaming tokens to the outer stream
236246
// and concat the text together
237247
stream.reasoning = format!("{}{}", stream.reasoning, reasoning);
238-
Poll::Ready(Some(Ok(StreamedAssistantContent::Reasoning(Reasoning {
248+
Poll::Ready(Some(Ok(StreamedAssistantContent::ReasoningDelta {
239249
id,
240-
reasoning: vec![reasoning],
241-
signature,
242-
}))))
250+
reasoning,
251+
})))
243252
}
244253
RawStreamingChoice::ToolCall {
245254
id,
@@ -362,6 +371,12 @@ impl<R: Clone + Unpin + GetTokenUsage> Stream for StreamingResultDyn<R> {
362371
reasoning,
363372
signature,
364373
}))),
374+
RawStreamingChoice::ReasoningDelta { id, reasoning } => {
375+
Poll::Ready(Some(Ok(RawStreamingChoice::ReasoningDelta {
376+
id,
377+
reasoning,
378+
})))
379+
}
365380
RawStreamingChoice::ToolCall {
366381
id,
367382
name,
@@ -514,6 +529,10 @@ mod tests {
514529
print!("{reasoning}");
515530
std::io::Write::flush(&mut std::io::stdout()).unwrap();
516531
}
532+
Ok(StreamedAssistantContent::ReasoningDelta { reasoning, .. }) => {
533+
println!("Reasoning delta: {reasoning}");
534+
chunk_count += 1;
535+
}
517536
Err(e) => {
518537
eprintln!("Error: {e:?}");
519538
break;
@@ -555,8 +574,15 @@ mod tests {
555574
pub enum StreamedAssistantContent<R> {
556575
Text(Text),
557576
ToolCall(ToolCall),
558-
ToolCallDelta { id: String, delta: String },
577+
ToolCallDelta {
578+
id: String,
579+
delta: String,
580+
},
559581
Reasoning(Reasoning),
582+
ReasoningDelta {
583+
id: Option<String>,
584+
reasoning: String,
585+
},
560586
Final(R),
561587
}
562588

0 commit comments

Comments
 (0)