Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Mistral AI

Mistral AI offers state-of-the-art open and proprietary language models with excellent multilingual support and strong function-calling capabilities. The Mistral API is fully compatible with the OpenAI API format.

Mistral AI is available as a compatibility submodule inside synaptic-models. No separate crate is needed. The submodule also provides an embeddings helper for the Mistral embeddings endpoint.

Setup

[dependencies]
synaptic = { version = "0.4", features = ["openai"] }

Obtain an API key from console.mistral.ai.

Configuration

use synaptic::openai::compat::mistral::{self, MistralModel};
use synaptic::models::HttpBackend;
use std::sync::Arc;

let model = mistral::chat_model("your-api-key", MistralModel::MistralLargeLatest.to_string(), Arc::new(HttpBackend::new()));

Builder methods

Use OpenAiConfig builder methods for customization:

use synaptic::openai::compat::mistral::{self, MistralModel};
use synaptic::openai::OpenAiChatModel;
use synaptic::models::HttpBackend;
use std::sync::Arc;

let config = mistral::config("key", MistralModel::MistralLargeLatest.to_string())
    .with_temperature(0.7)
    .with_max_tokens(4096)
    .with_top_p(0.95);

let model = OpenAiChatModel::new(config, Arc::new(HttpBackend::new()));

For unlisted models, pass a string directly:

let model = mistral::chat_model("key", "mistral-large-2411", Arc::new(HttpBackend::new()));

Available Models

Enum VariantAPI Model IDContextBest For
MistralLargeLatestmistral-large-latest128 KMost capable, complex reasoning
MistralSmallLatestmistral-small-latest32 KBalanced performance and cost
OpenMistralNemoopen-mistral-nemo128 KOpen-source, strong multilingual
CodestralLatestcodestral-latest32 KCode generation and completion
Custom(String)(any)--Unlisted / preview models

Usage

The model returned by chat_model() implements the ChatModel trait:

use synaptic::openai::compat::mistral::{self, MistralModel};
use synaptic::core::{ChatModel, ChatRequest, Message};
use synaptic::models::HttpBackend;
use std::sync::Arc;

let model = mistral::chat_model("key", MistralModel::MistralLargeLatest.to_string(), Arc::new(HttpBackend::new()));

let request = ChatRequest::new(vec![
    Message::system("You are a helpful multilingual assistant."),
    Message::human("Bonjour! Explain Rust ownership in one sentence."),
]);

let response = model.chat(request).await?;
println!("{}", response.message.content().unwrap_or_default());

Streaming

Use stream_chat() to receive tokens incrementally:

use futures::StreamExt;

let request = ChatRequest::new(vec![
    Message::human("Write a haiku about distributed systems."),
]);

let mut stream = model.stream_chat(request);
while let Some(chunk) = stream.next().await {
    print!("{}", chunk?.content);
}
println!();

Tool Calling

Mistral models have strong function-calling capabilities:

use synaptic::core::{ChatRequest, Message, ToolDefinition, ToolChoice};
use serde_json::json;

let tools = vec![ToolDefinition {
    name: "search_documents".to_string(),
    description: "Search a document database.".to_string(),
    parameters: json!({
        "type": "object",
        "properties": { "query": {"type": "string"} },
        "required": ["query"]
    }),
}];

let request = ChatRequest::new(vec![Message::human("Find documents about Rust async.")])
    .with_tools(tools)
    .with_tool_choice(ToolChoice::Auto);

let response = model.chat(request).await?;
for tc in response.message.tool_calls() {
    println!("Tool: {}, Args: {}", tc.name, tc.arguments);
}

Embeddings

Mistral provides an embeddings API through the same base URL. Use the embeddings helper function:

use synaptic::openai::compat::mistral;
use synaptic::models::HttpBackend;
use synaptic::core::Embeddings;
use std::sync::Arc;

let embeddings = mistral::embeddings(
    "your-api-key",
    "mistral-embed",
    Arc::new(HttpBackend::new()),
);

// Embed a single query
let vector = embeddings.embed_query("What is ownership in Rust?").await?;
println!("Dimension: {}", vector.len()); // 1024

// Embed multiple documents for indexing
let docs = ["Rust is safe.", "Rust is fast.", "Rust is fun."];
let vectors = embeddings.embed_documents(&docs).await?;
println!("Embedded {} documents", vectors.len());

Error Handling

The SynapticError::RateLimit variant is returned when the API responds with HTTP 429:

use synaptic::core::SynapticError;

match model.chat(request).await {
    Ok(response) => println!("{}", response.message.content().unwrap_or_default()),
    Err(SynapticError::RateLimit(msg)) => eprintln!("Rate limited: {}", msg),
    Err(e) => return Err(e.into()),
}

Configuration Reference

All configuration is done through OpenAiConfig builder methods. See the OpenAI-Compatible Providers page for the full reference.

MethodDescription
.with_temperature(f64)Sampling temperature (0.0-1.0)
.with_max_tokens(u32)Maximum tokens to generate
.with_top_p(f64)Nucleus sampling threshold
.with_stop(Vec<String>)Stop sequences
.with_seed(u64)Seed for reproducible output