getChatResponse method

  1. @override
Future<ChatResponse> getChatResponse({
  1. required Iterable<ChatMessage> messages,
  2. ChatOptions? options,
  3. CancellationToken? cancellationToken,
})
override

Sends a chat request and returns the complete response.

Implementation

@override
Future<ChatResponse> getChatResponse({
  required Iterable<ChatMessage> messages,
  ChatOptions? options,
  CancellationToken? cancellationToken,
}) async {
  final allTools = _getAllTools(options);
  if (allTools.isEmpty) {
    return super.getChatResponse(
      messages: messages,
      options: options,
      cancellationToken: cancellationToken,
    );
  }

  final messageList = messages.toList();
  var iterations = 0;
  var consecutiveErrors = 0;

  while (true) {
    final response = await super.getChatResponse(
      messages: messageList,
      options: options,
      cancellationToken: cancellationToken,
    );

    // Check for function calls in the response
    final lastMessage =
        response.messages.isNotEmpty ? response.messages.last : null;
    if (lastMessage == null) return response;

    final functionCalls =
        lastMessage.contents.whereType<FunctionCallContent>().toList();

    if (functionCalls.isEmpty) return response;

    iterations++;
    if (iterations > maximumIterationsPerRequest) return response;

    // Add the assistant message with function calls
    messageList.add(lastMessage);

    // Invoke the functions
    final results = await _invokeFunctions(
      functionCalls,
      allTools,
      cancellationToken,
    );

    // Check for errors
    final hasErrors =
        results.any((r) => r.status == FunctionInvocationStatus.exception);
    if (hasErrors) {
      consecutiveErrors++;
      if (consecutiveErrors >= maximumConsecutiveErrorsPerRequest) {
        return response;
      }
    } else {
      consecutiveErrors = 0;
    }

    // Check for termination
    if (results.any((r) => r.terminate)) return response;

    // Add tool results as a tool message
    final resultContents = results
        .map((r) => FunctionResultContent(
              callId: r.callContent.callId,
              result: r.result,
              exception:
                  r.exception is Exception ? r.exception as Exception : null,
            ))
        .toList();

    messageList.add(ChatMessage(
      role: ChatRole.tool,
      contents: resultContents.cast<AIContent>(),
    ));
  }
}