complete method

  1. @override
Future<LLMResponse> complete(
  1. LLMRequest request
)
override

Sends request to the LLM and returns its response.

Implementation

@override
Future<LLMResponse> complete(LLMRequest request) async {
  final url = Uri.parse('$baseUrl/chat/completions');

  final body = jsonEncode({
    'model': request.model ?? model,
    'messages': request.messages.map((m) => m.toJson()).toList(),
    'max_tokens': request.maxTokens,
    'temperature': request.temperature,
    if (request.stopSequences.isNotEmpty) 'stop': request.stopSequences,
  });

  final headers = <String, String>{
    'Content-Type': 'application/json',
    'Authorization': 'Bearer $apiKey',
    if (organizationId != null) 'OpenAI-Organization': organizationId!,
  };

  _logger.debug('POST $url (model: ${request.model ?? model})');

  try {
    final response = await _client
        .post(url, headers: headers, body: body)
        .timeout(const Duration(seconds: 60));

    if (response.statusCode != 200) {
      throw LLMProviderException(
        'HTTP ${response.statusCode}: ${response.body}',
        statusCode: response.statusCode,
      );
    }

    final json = jsonDecode(response.body) as Map<String, dynamic>;
    final choices = json['choices'] as List<dynamic>;
    if (choices.isEmpty) {
      throw const LLMProviderException('No choices returned by LLM');
    }

    final choice = choices.first as Map<String, dynamic>;
    final message = choice['message'] as Map<String, dynamic>;
    final text = message['content'] as String? ?? '';
    final usage = json['usage'] as Map<String, dynamic>? ?? {};

    return LLMResponse(
      text: text,
      promptTokens: (usage['prompt_tokens'] as int?) ?? 0,
      completionTokens: (usage['completion_tokens'] as int?) ?? 0,
      model: json['model'] as String? ?? model,
      finishReason: choice['finish_reason'] as String?,
    );
  } on LLMProviderException {
    rethrow;
  } catch (e, st) {
    _logger.error('LLM request failed', e, st);
    throw LLMProviderException('Network error: $e');
  }
}