Conversations and vision
A TextRequest carries more than one prompt. Prior turns go in history, the current user turn stays in prompt, and a vision-capable model can also read an image attached to that current turn.
Multi-turn conversations
TextRequest.history is a List<TextMessage>, oldest first. Build each earlier turn with TextMessage.user(...) or TextMessage.assistant(...). Do not put the current turn in history. It stays in prompt, and the client appends it after the history when it builds the request.
system sets an optional system prompt that frames how the model answers. It is not a conversation turn, so leave it out of history.
Here is a two-turn conversation. The first user question and the assistant's reply are the history. The follow-up question is the current turn.
import 'package:ai_abstracted/ai_abstracted.dart';
Future<void> main() async {
final credentials = ProviderCredentials(apiKey: 'your-anthropic-key');
final client = ClaudeTextClient(credentials: credentials);
final request = TextRequest(
prompt: 'And what is its population?',
system: 'You are a concise geography tutor.',
history: const [
TextMessage.user('What is the capital of France?'),
TextMessage.assistant('Paris.'),
],
);
final result = await client.generateText(request); // makes a real API call
print(result.text);
}
To continue the conversation, append the model's answer and the next question. Take result.text, wrap it in TextMessage.assistant(...), add it to the history alongside the previous turns, and set the new question as prompt.
Attaching an image
TextRequest.image is a TextImage. It holds raw bytes and a mimeType (default image/png), and it attaches to the current user turn only. Use it to ask a question about a picture.
Every text client forwards the image, each in its provider's own encoding: Claude and Gemini send it inline, Mistral sends an OpenAI-style image_url content part holding a data: URI, and Ollama sends bare base64 in its per-message images array.
Whether the model can see it is a separate question, and the package cannot answer it — there is no capability introspection in any provider API it speaks. Pick a multimodal model: pixtral-* or mistral-medium-* on Mistral, and a tag with a vision projector (llama3.2-vision, qwen2.5vl, gemma3, …) on Ollama. A text-only model rejects the request with an AiInvalidRequestException, which the retry policy deliberately does not retry.
Be aware of the quieter failure: some Ollama server and runner combinations drop the images array instead of erroring, and answer from the text prompt alone. The reply looks confident and is entirely invented. If you store such answers, defend against it at the application level — for example by asking the prompt to emit a known sentinel when it received no image, and treating that sentinel as a failure.
The package never touches the filesystem, so you load the bytes yourself. This example reads a file with dart:io and hands the bytes to TextImage. Set mimeType to match the file (image/jpeg here, not the image/png default).
import 'dart:io';
import 'package:ai_abstracted/ai_abstracted.dart';
Future<void> main() async {
final credentials = ProviderCredentials(apiKey: 'your-anthropic-key');
final client = ClaudeTextClient(credentials: credentials);
final bytes = await File('photo.jpg').readAsBytes();
final request = TextRequest(
prompt: 'What is in this picture?',
image: TextImage(bytes: bytes, mimeType: 'image/jpeg'),
);
final result = await client.generateText(request); // makes a real API call
print(result.text);
}
You can combine history and image in the same request. The image always rides on the current turn, never on a turn from the history.
Tokens and temperature
maxTokens caps the length of the reply. It defaults to 4096. Lower it to keep answers short or to bound cost, raise it when you expect a long completion.
temperature is optional. It controls how much the sampling varies. A low value gives steadier, more repeatable answers, a higher value gives more variation. Leave it unset to use the provider's own default.
final request = TextRequest(
prompt: 'Summarize the plot of Hamlet in two sentences.',
maxTokens: 512,
temperature: 0.2,
);
See also
- Structured output constrains the reply to a JSON schema.
- Claude covers the vision-capable text client used above.