Skip to main content

Mistral

Mistral gives you text completions through MistralTextClient. It posts to Mistral's /v1/chat/completions endpoint, which follows the OpenAI request shape, so the messages, temperature, and JSON-mode fields look like ones you have seen before. The default model is mistral-large-latest.

Credentials​

Mistral uses one API key. Create it in your Mistral console (console.mistral.ai) under API keys, then put it in the environment as MISTRAL_API_KEY. The client sends it as an Authorization: Bearer header.

import 'dart:io';

import 'package:ai_abstracted/ai_abstracted.dart';

Future<void> main() async {
final credentials = credentialsFromEnv(ProviderId.mistral, Platform.environment);
if (credentials == null) {
stderr.writeln('Set MISTRAL_API_KEY first.');
return;
}

// Makes a real, billed request to Mistral.
final client = MistralTextClient(credentials: credentials);
final result = await client.generateText(
const TextRequest(prompt: 'Give me one fact about the Mistral wind.'),
);

print(result.text);
}

result.text is the completion decoded from result.bytes (UTF-8). The client never touches the filesystem. If you want to save the raw bytes, write them yourself with dart:io: File('out.txt').writeAsBytes(result.bytes).

System prompt, history, and temperature​

For the current user turn you set prompt. A system prompt frames the model's behavior, and history carries prior turns oldest first. Set temperature to control sampling. This fragment assumes you already built client as above.

final result = await client.generateText(
TextRequest(
prompt: 'And a shorter version?',
system: 'You write terse, factual answers. No preamble.',
history: [
TextMessage.user('Explain the Mistral wind in two sentences.'),
TextMessage.assistant('The Mistral is a strong, cold northwesterly wind '
'that blows through the Rhone valley toward the Mediterranean.'),
],
temperature: 0.2,
),
);

The client maps these straight onto the messages array: the system prompt first, then each history turn, then your prompt as the final user message.

JSON mode​

Pass a jsonSchema to turn on JSON mode. On this client the schema's presence toggles Mistral's response_format: {"type": "json_object"}. The schema keys themselves are not forwarded, so Mistral returns valid JSON but does not enforce your exact shape. Decode result.text yourself.

final result = await client.generateText(
TextRequest(
prompt: 'List three French wine regions with their main color, as JSON.',
jsonSchema: {
'type': 'object',
'properties': {
'regions': {'type': 'array'},
},
},
),
);

// Needs `import 'dart:convert';`.
final data = jsonDecode(result.text) as Map<String, Object?>;

For the full picture of structured output across providers, see structured output.

Notes and limits​

  • The OpenAI-style request shape makes this client familiar if you have used chat completions before. Messages, temperature, and max_tokens all line up.
  • TextRequest has an image field, but this client does not send images. Passing one has no effect here. For text plus image, use Claude, which supports vision.

Errors​

Failures raise the usual AiException subtypes, tagged with the provider:

  • AiAuthException when the key is missing or wrong (HTTP 401/403).
  • AiRateLimitException on HTTP 429, with an optional retryAfter.
  • AiInvalidRequestException for a rejected request (HTTP 400/422).
  • AiTransientException for 5xx and network errors; the client retries these under its RetryPolicy before giving up.
  • AiResponseException if the body arrives without message content.

See error handling for catching and reacting to these.

See also​