Skip to main content

LlmClient

Trait LlmClient 

Source
pub trait LlmClient: Send + Sync {
    // Required methods
    fn chat<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        messages: &'life1 [Message],
        model: Option<&'life2 str>,
        tools: Option<Vec<ToolDefinition>>,
    ) -> Pin<Box<dyn Future<Output = Result<ChatResponse, LlmError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait;
    fn chat_json<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        messages: &'life1 [Message],
        model: Option<&'life2 str>,
        tools: Option<Vec<ToolDefinition>>,
    ) -> Pin<Box<dyn Future<Output = Result<Value, LlmError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait;
    fn list_models<'life0, 'async_trait>(
        &'life0 self,
    ) -> Pin<Box<dyn Future<Output = Result<Vec<ModelInfo>, LlmError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;
    fn health_check<'life0, 'async_trait>(
        &'life0 self,
    ) -> Pin<Box<dyn Future<Output = Result<bool, LlmError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;

    // Provided methods
    fn chat_stream<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        messages: &'life1 [Message],
        model: Option<&'life2 str>,
        event_tx: Option<UnboundedSender<StreamEvent>>,
        tools: Option<Vec<ToolDefinition>>,
    ) -> Pin<Box<dyn Future<Output = Result<ChatResponse, LlmError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait { ... }
    fn chat_stream_with_params<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        messages: &'life1 [Message],
        model: Option<&'life2 str>,
        event_tx: Option<UnboundedSender<StreamEvent>>,
        tools: Option<Vec<ToolDefinition>>,
        _max_completion_tokens: Option<u32>,
        _temperature: Option<f32>,
    ) -> Pin<Box<dyn Future<Output = Result<ChatResponse, LlmError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait { ... }
    fn chat_stream_with_reuse<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        messages: &'life1 [Message],
        model: Option<&'life2 str>,
        event_tx: Option<UnboundedSender<StreamEvent>>,
        tools: Option<Vec<ToolDefinition>>,
        _reuse: PromptReuse,
    ) -> Pin<Box<dyn Future<Output = Result<ChatResponse, LlmError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait { ... }
}
Expand description

Unified interface for sending chat messages to any LLM provider.

This trait is implemented by each LLM provider (Ollama, OpenAI, Anthropic, etc.).

Required Methods§

Source

fn chat<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, messages: &'life1 [Message], model: Option<&'life2 str>, tools: Option<Vec<ToolDefinition>>, ) -> Pin<Box<dyn Future<Output = Result<ChatResponse, LlmError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Send a chat completion request and get a text response.

Parameters:

  • messages: The conversation messages.
  • model: Optional model override; None uses the provider default.
  • tools: Optional list of tools the LLM can invoke. When non-empty, the LLM may return tool calls instead of (or alongside) text.
Source

fn chat_json<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, messages: &'life1 [Message], model: Option<&'life2 str>, tools: Option<Vec<ToolDefinition>>, ) -> Pin<Box<dyn Future<Output = Result<Value, LlmError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Send a chat completion request and get a JSON-structured response.

Source

fn list_models<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<Vec<ModelInfo>, LlmError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

List available models on this provider.

§Errors

Returns an error if the operation fails.

Source

fn health_check<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<bool, LlmError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Health check — is the provider reachable?

§Errors

Returns an error if the operation fails.

Provided Methods§

Source

fn chat_stream<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, messages: &'life1 [Message], model: Option<&'life2 str>, event_tx: Option<UnboundedSender<StreamEvent>>, tools: Option<Vec<ToolDefinition>>, ) -> Pin<Box<dyn Future<Output = Result<ChatResponse, LlmError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Send a streaming chat request, emitting StreamEvents via the channel.

Each token/chunk is sent through event_tx as it arrives from the provider, enabling real-time progress visibility. The full assembled response is still returned as a ChatResponse when the stream completes.

Callers pass None for event_tx to skip streaming events (equivalent to calling chat).

Default implementation falls back to non-streaming chat() and sends the complete content as a single Token event.

Source

fn chat_stream_with_params<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, messages: &'life1 [Message], model: Option<&'life2 str>, event_tx: Option<UnboundedSender<StreamEvent>>, tools: Option<Vec<ToolDefinition>>, _max_completion_tokens: Option<u32>, _temperature: Option<f32>, ) -> Pin<Box<dyn Future<Output = Result<ChatResponse, LlmError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Send a streaming chat request honoring the caller’s generation params.

max_completion_tokens bounds the response budget; temperature sets determinism. The default IGNORES them and delegates to chat_stream so no provider is forced to change — only providers that honor generation params (the OpenAI-compatible client) override this. The workspace chat/rail path calls this so the LlmRequest’s max_tokens/temperature actually reach the wire instead of being silently dropped at the gateway bridge.

Source

fn chat_stream_with_reuse<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, messages: &'life1 [Message], model: Option<&'life2 str>, event_tx: Option<UnboundedSender<StreamEvent>>, tools: Option<Vec<ToolDefinition>>, _reuse: PromptReuse, ) -> Pin<Box<dyn Future<Output = Result<ChatResponse, LlmError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Send a streaming chat request that says which part of it will be sent again (see PromptReuse).

The default ignores the hint and delegates to chat_stream; only a provider with a prompt cache overrides it.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§