Skip to main content

deepseek_recipe/stream/
mod.rs

1//! Parse model output and turn it into protocol-specific response events.
2
3pub use decoder::TokenizerDecoder;
4pub use inference::{
5    CompletionUsage, FinishReason, InferenceChunk, InferenceFinishReason, PromptUsage,
6};
7pub use processor::StreamProcessor;
8
9mod decoder;
10mod inference;
11mod processor;
12pub mod state_machine;
13
14/// An error that ends stream processing before normal completion.
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum StreamError {
17    /// A token-id chunk arrived without an attached tokenizer.
18    MissingTokenizer,
19    /// The tokenizer failed to decode buffered token ids.
20    Decode {
21        /// The decoder's failure message.
22        detail: String,
23    },
24}
25
26impl std::fmt::Display for StreamError {
27    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        match self {
29            Self::MissingTokenizer => {
30                formatter.write_str("token chunk received without a tokenizer")
31            }
32            Self::Decode { detail } => write!(formatter, "failed to decode token ids: {detail}"),
33        }
34    }
35}
36
37impl std::error::Error for StreamError {}
38
39/// A parsed piece of model output, before protocol-specific event conversion.
40#[derive(Debug, Clone, PartialEq, Eq)]
41pub enum OutputChunk {
42    Start {
43        system_fingerprint: Option<String>,
44        usage: PromptUsage,
45    },
46    Raw {
47        content: String,
48    },
49    Reasoning {
50        content: String,
51    },
52    ToolCallBegin,
53    ToolCall {
54        tool_name: String,
55        arguments: String,
56    },
57    ToolArgumentsDelta {
58        content: String,
59    },
60    Finish {
61        reason: FinishReason,
62        stop_sequence: Option<String>,
63        usage: CompletionUsage,
64    },
65}
66
67/// Convert parsed output into a protocol's response events.
68pub trait ChunkGenerator: Send + 'static {
69    /// Event type emitted by this protocol.
70    type Chunk;
71
72    /// Produce zero or more events for one parsed output chunk.
73    fn generate(&mut self, chunk: OutputChunk) -> impl Future<Output = Vec<Self::Chunk>> + Send;
74}