Skip to main content

StreamingDecoder

Struct StreamingDecoder 

Source
pub struct StreamingDecoder { /* private fields */ }
Expand description

A streaming decoder that handles incomplete UTF-8 sequences across token boundaries.

When decoding tokens one at a time (as in streaming LLM output), a token’s bytes may end in the middle of a multi-byte UTF-8 character. This decoder buffers incomplete sequences and only returns complete, valid UTF-8 strings.

§Obtaining one

There is no public constructor: a decoder is built by a tokenizer’s own streaming_decoderTokenizer::streaming_decoder, SpmTokenizer::streaming_decoder or SentencePieceTokenizer::streaming_decoder or WordPieceTokenizer::streaming_decoder — which takes the surfaces, the skipped-special-token set and every spelling rule (byte level, byte fallback, metaspace) from that tokenizer’s own configuration. A decoder therefore cannot be paired with the wrong kind of vocabulary — the mistake that used to turn a byte-level stream into mojibake is not expressible.

A tokenizer loaded from a tokenizer.json has one more factory, AnyTokenizer::streaming_decoder: it takes those same rules from the file’s declared decoder pipeline when one is declared, and delegates to the backend factory above when none is — the same choice AnyTokenizer::decode makes.

§Agreement with whole-sequence decoding

For any ids, concatenating every emission plus the final flush equals Tokenizer::decode_lossy of the same ids, and equals Tokenizer::decode whenever that succeeds. (A stream cannot see the future, so bytes that are still invalid at flush become U+FFFD instead of an error — that is the one and only case where strict whole-sequence decoding reports something the stream renders lossily.) Chunk boundaries affect only when text is emitted, never what.

The decoder owns its state and borrows nothing, so it can be moved into a generation task and outlive the scope the tokenizer was created in.

§Example

use splintr::{from_pretrained, Backend};

let any = from_pretrained("cl100k_base")?;
let Backend::Bpe(tokenizer) = any.into_backend() else {
    unreachable!("cl100k_base loads as a BPE backend");
};
let mut decoder = tokenizer.streaming_decoder();

for token_id in tokenizer.encode("Hello, world!") {
    if let Some(text) = decoder.add_token(token_id)? {
        print!("{}", text);
    }
}
// Flush any remaining buffered bytes
print!("{}", decoder.flush());

Implementations§

Source§

impl StreamingDecoder

Source

pub fn add_token(&mut self, id: u32) -> Result<Option<String>, TokenizeError>

Add a token and return any complete UTF-8 characters.

Returns Some(string) if there are complete characters to emit, or None if the current bytes are still incomplete.

Errors with TokenizeError::InvalidTokenId if the id is in neither the vocabulary nor the special tokens, matching Tokenizer::decode. Ids already accepted stay buffered; reset discards them.

Source

pub fn add_tokens( &mut self, ids: &[u32], ) -> Result<Option<String>, TokenizeError>

Add multiple tokens at once and return complete UTF-8 characters.

Feeding ids in groups is indistinguishable from feeding them one by one: only the emission points differ, never the concatenated text.

Source

pub fn add_token_lossy(&mut self, id: u32) -> Option<String>

Add a token, skipping it if it is in no table.

The permissive twin of add_token, matching Tokenizer::decode_lossy. This never fails, so on_unknown is instantiated with Infallible, letting the compiler prove the Err arm away rather than a runtime assertion claiming it.

Source

pub fn add_tokens_lossy(&mut self, ids: &[u32]) -> Option<String>

Add multiple tokens at once, skipping any that are in no table.

Source

pub fn flush(&mut self) -> String

Flush any remaining buffered bytes.

If there are incomplete UTF-8 sequences in the buffer, they will be replaced with the Unicode replacement character (U+FFFD).

Source

pub fn reset(&mut self)

Reset the decoder state, discarding any buffered bytes.

The decoder is then indistinguishable from a freshly built one.

Source

pub fn has_pending(&self) -> bool

Check if there are buffered bytes waiting for completion.

Source

pub fn pending_bytes(&self) -> usize

Get the number of pending bytes in the buffer.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.