completeWithTools method
Like ChatModel.complete, but the model may answer with ChatResponse.toolCalls instead of (or as well as) text.
Implementation
@override
Future<ChatResponse> completeWithTools(
List<ChatMessage> messages, {
String? system,
int? maxTokens,
List<Tool> tools = const [],
}) async {
final json = await _http.postJson(
joinUrl(baseUrl, 'chat/completions'),
_auth(apiKey, headers),
_body(messages, system, maxTokens, stream: false, tools: tools),
);
final choices = json['choices'];
if (choices is! List || choices.isEmpty) {
throw const LlmException('the response has no choices');
}
final choice = choices.first as Map;
final message = choice['message'] as Map? ?? const {};
final refusal = message['refusal'];
if (refusal is String && refusal.isNotEmpty) {
throw LlmRefusalException(refusal);
}
final calls = <ToolCall>[];
for (final raw in (message['tool_calls'] as List? ?? const [])) {
if (raw is! Map) continue;
final function = raw['function'];
if (function is! Map) continue;
calls.add(
ToolCall(
id: '${raw['id']}',
name: '${function['name']}',
// Arguments arrive as a JSON *string* in this API.
input: decodeToolInput(function['arguments']),
),
);
}
return ChatResponse(
message['content'] as String? ?? '',
stopReason: choice['finish_reason'] as String?,
model: json['model'] as String?,
usage: _usage(json['usage']),
toolCalls: calls,
);
}