render method
Renders messages (with optional tools) into a Qwen prompt.
Qwen3 thinks by default; enableThinking false pre-fills the
generation prompt with an empty <think></think> block — exactly what
the upstream template's enable_thinking=false emits — so the model
skips the reasoning pass instead of burning decode tokens on it.
Implementation
RenderedPrompt render(
Iterable<ChatMessage> messages, {
Iterable<AIFunctionDeclaration> tools = const <AIFunctionDeclaration>[],
bool enableThinking = true,
bool addGenerationPrompt = true,
}) {
final all = messages.toList();
final out = StringBuffer();
final images = <Uint8List>[];
var loopStart = 0;
final systemParts = <String>[];
if (all.isNotEmpty && all.first.role == ChatRole.system) {
final text = all.first.text;
if (text.isNotEmpty) systemParts.add(text);
loopStart = 1;
}
final toolsSection = hermesToolsSection(tools);
if (toolsSection.isNotEmpty) systemParts.add(toolsSection);
if (systemParts.isNotEmpty) {
out
..write(imStart)
..write('system\n')
..write(systemParts.join('\n\n'))
..write(imEnd)
..write('\n');
}
final body = all.sublist(loopStart);
var i = 0;
while (i < body.length) {
if (body[i].role == ChatRole.tool) {
// Qwen groups a run of consecutive tool results into one `user` turn,
// each wrapped in `<tool_response>` (matching the upstream template).
final responses = <String>[];
while (i < body.length && body[i].role == ChatRole.tool) {
for (final r in body[i].contents.whereType<FunctionResultContent>()) {
responses.add(
'$toolResponseOpen\n${_resultText(r.result)}\n$toolResponseClose',
);
}
i++;
}
out
..write(imStart)
..write('user\n')
..write(responses.join('\n'))
..write(imEnd)
..write('\n');
continue;
}
out
..write(imStart)
..write(body[i].role.value)
..write('\n')
..write(_contentFor(body[i], images))
..write(imEnd)
..write('\n');
i++;
}
if (addGenerationPrompt) {
out
..write(imStart)
..write('assistant\n');
if (!enableThinking) {
out.write('$thinkOpen\n\n$thinkClose\n\n');
}
}
return RenderedPrompt(
text: out.toString(),
stopSequences: stopSequences,
media: images,
);
}