render method
Renders messages (with optional tools) into a Mistral prompt.
Implementation
RenderedPrompt render(
Iterable<ChatMessage> messages, {
Iterable<AIFunctionDeclaration> tools = const <AIFunctionDeclaration>[],
bool addGenerationPrompt = true,
}) {
final all = messages.toList();
final images = <Uint8List>[];
var loopStart = 0;
String? system;
if (all.isNotEmpty && all.first.role == ChatRole.system) {
final text = all.first.text;
if (text.isNotEmpty) system = text;
loopStart = 1;
}
final body = all.sublist(loopStart);
final toolsBlock = _toolsBlock(tools);
final lastUser = body.lastIndexWhere((m) => m.role == ChatRole.user);
final out = StringBuffer();
var firstUserSeen = false;
for (var i = 0; i < body.length; i++) {
final msg = body[i];
if (msg.role == ChatRole.user) {
final prefix = StringBuffer();
if (i == lastUser && toolsBlock.isNotEmpty) prefix.write(toolsBlock);
prefix.write(instStart);
prefix.write(' ');
if (!firstUserSeen && system != null) {
prefix
..write(system)
..write('\n\n');
firstUserSeen = true;
}
out
..write(prefix)
..write(_userContent(msg, images))
..write(' ')
..write(instEnd);
} else if (msg.role == ChatRole.tool) {
out
..write(toolResultsStart)
..write(_toolResult(msg))
..write(toolResultsEnd);
} else {
// Assistant turn: prose and/or a tool-call block, then EOS.
final calls = msg.contents.whereType<FunctionCallContent>().toList();
if (calls.isNotEmpty) {
out
..write(toolCalls)
..write('[')
..write(calls.map(_callJson).join(', '))
..write(']');
} else {
out
..write(' ')
..write(msg.text);
}
out.write(eos);
}
}
return RenderedPrompt(
text: out.toString(),
stopSequences: stopSequences,
media: images,
);
}