MistralClient.Stream (mistralex_ai v0.1.0)

View Source

Server-Sent Events (SSE) streaming support for the Mistral AI client.

This module provides utilities for handling streaming responses from the Mistral API, particularly for chat completions that return data in real-time.

Features

  • SSE parsing and handling
  • Chunk processing and validation
  • Stream error recovery
  • Callback-based processing
  • Stream completion detection

Usage

# Process a stream with a callback
MistralClient.Stream.process_stream(stream_data, fn chunk ->
  content = get_in(chunk, ["choices", Access.at(0), "delta", "content"])
  if content, do: IO.write(content)
end)

# Parse individual SSE chunks
{:ok, chunk} = MistralClient.Stream.parse_chunk("data: {...}")

Summary

Functions

Accumulate content from multiple stream chunks.

Extract content from a stream chunk.

Extract finish reason from a stream chunk.

Extract tool calls from a stream chunk.

Parse a single SSE chunk.

Process a stream of Server-Sent Events.

Check if a chunk indicates the stream is complete.

Validate a parsed chunk.

Types

callback()

@type callback() :: (chunk() -> any())

chunk()

@type chunk() :: map()

Functions

accumulate_content(chunks, choice_index \\ 0)

@spec accumulate_content([chunk()], integer()) :: String.t()

Accumulate content from multiple stream chunks.

Parameters

  • chunks - List of parsed chunks
  • choice_index - Index of the choice to accumulate (default: 0)

Examples

"Hello world!" = MistralClient.Stream.accumulate_content([chunk1, chunk2, chunk3])

extract_content(chunk, choice_index \\ 0)

@spec extract_content(chunk(), integer()) :: String.t() | nil

Extract content from a stream chunk.

Parameters

  • chunk - Parsed chunk data
  • choice_index - Index of the choice to extract (default: 0)

Examples

"Hello" = MistralClient.Stream.extract_content(chunk)
nil = MistralClient.Stream.extract_content(chunk_without_content)

extract_finish_reason(chunk, choice_index \\ 0)

@spec extract_finish_reason(chunk(), integer()) :: String.t() | nil

Extract finish reason from a stream chunk.

Parameters

  • chunk - Parsed chunk data
  • choice_index - Index of the choice to extract (default: 0)

Examples

"stop" = MistralClient.Stream.extract_finish_reason(chunk)
nil = MistralClient.Stream.extract_finish_reason(incomplete_chunk)

extract_tool_calls(chunk, choice_index \\ 0)

@spec extract_tool_calls(chunk(), integer()) :: list() | nil

Extract tool calls from a stream chunk.

Parameters

  • chunk - Parsed chunk data
  • choice_index - Index of the choice to extract (default: 0)

Examples

[%{"id" => "call_123", ...}] = MistralClient.Stream.extract_tool_calls(chunk)
nil = MistralClient.Stream.extract_tool_calls(chunk_without_tools)

parse_chunk(chunk_data, options \\ [])

@spec parse_chunk(
  binary(),
  keyword()
) :: {:ok, chunk()} | :done | {:error, Exception.t()}

Parse a single SSE chunk.

Parameters

  • chunk_data - Raw chunk data
  • options - Parsing options (optional)

Options

  • :validate - Validate the parsed chunk (default: true)

Examples

{:ok, chunk} = MistralClient.Stream.parse_chunk("data: {...}")
:done = MistralClient.Stream.parse_chunk("data: [DONE]")

process_stream(stream_data, callback, options \\ [])

@spec process_stream(binary(), callback(), keyword()) :: :ok | {:error, Exception.t()}

Process a stream of Server-Sent Events.

Parameters

  • stream_data - Raw stream data
  • callback - Function to process each chunk
  • options - Processing options (optional)

Options

  • :validate - Validate chunks before processing (default: true)
  • :skip_empty - Skip empty chunks (default: true)
  • :timeout - Stream timeout in milliseconds (default: 30_000)

Examples

MistralClient.Stream.process_stream(data, fn chunk ->
  case get_in(chunk, ["choices", Access.at(0), "delta", "content"]) do
    nil -> :ok
    content -> IO.write(content)
  end
end)

request_stream(config, method, path, body, query_params, callback)

@spec request_stream(
  MistralClient.Config.t(),
  atom(),
  String.t(),
  map(),
  list(),
  callback()
) ::
  {:ok, term()} | {:error, term()}

Make a streaming HTTP request.

Parameters

  • config - Client configuration
  • method - HTTP method
  • path - API path
  • body - Request body
  • query_params - Query parameters
  • callback - Function to handle each chunk

Examples

MistralClient.Stream.request_stream(config, :post, "/v1/chat/completions", body, [], callback)

stream_complete?(chunk)

@spec stream_complete?(chunk()) :: boolean()

Check if a chunk indicates the stream is complete.

Parameters

  • chunk - Parsed chunk data

Examples

true = MistralClient.Stream.stream_complete?(final_chunk)
false = MistralClient.Stream.stream_complete?(intermediate_chunk)

validate_chunk(chunk)

@spec validate_chunk(chunk()) :: :ok | {:error, Exception.t()}

Validate a parsed chunk.

Parameters

  • chunk - Parsed chunk data

Examples

:ok = MistralClient.Stream.validate_chunk(%{"choices" => [...]})
{:error, reason} = MistralClient.Stream.validate_chunk(%{})