createModel method

Model createModel(
  1. String modelName,
  2. SchemanticType customOptions
)

Implementation

Model createModel(String modelName, SchemanticType customOptions) {
  return Model(
    name: '$name/$modelName',
    customOptions: customOptions,
    metadata: {'model': commonModelInfo.toJson()},
    fn: (req, ctx) async {
      gcl.GenerationConfig generationConfig;
      List<gcl.SafetySetting>? safetySettings;
      List<gcl.Tool>? tools;
      gcl.ToolConfig? toolConfig;
      String? apiKey;

      final isJsonMode =
          req!.output?.format == 'json' ||
          req.output?.contentType == 'application/json';

      if (customOptions == GeminiTtsOptions.$schema) {
        final options = req.config == null
            ? GeminiTtsOptions()
            : GeminiTtsOptions.$schema.parse(req.config!);
        apiKey = options.apiKey;
        generationConfig = toGeminiTtsSettings(
          options,
          req.output?.schema,
          isJsonMode,
        );
        safetySettings = toGeminiSafetySettings(options.safetySettings);
        tools = toGeminiTools(
          req.tools,
          codeExecution: options.codeExecution,
          googleSearch: options.googleSearch,
        );
        toolConfig = toGeminiToolConfig(options.functionCallingConfig);
      } else {
        final options = req.config == null
            ? GeminiOptions()
            : GeminiOptions.$schema.parse(req.config!);
        apiKey = options.apiKey;
        generationConfig = toGeminiSettings(
          options,
          req.output?.schema,
          isJsonMode,
        );
        safetySettings = toGeminiSafetySettings(options.safetySettings);
        tools = toGeminiTools(
          req.tools,
          codeExecution: options.codeExecution,
          googleSearch: options.googleSearch,
        );
        toolConfig = toGeminiToolConfig(options.functionCallingConfig);
      }

      final service = await getApiClient(apiKey);

      try {
        final systemMessage = req.messages
            .where((m) => m.role == Role.system)
            .firstOrNull;
        final messages = req.messages
            .where((m) => m.role != Role.system)
            .toList();

        final generateRequest = gcl.GenerateContentRequest(
          contents: toGeminiContent(messages),
          tools: tools.isEmpty ? null : tools,
          toolConfig: toolConfig,
          generationConfig: generationConfig,
          safetySettings: safetySettings?.isEmpty ?? true
              ? null
              : safetySettings,
          systemInstruction: systemMessage == null
              ? null
              : gcl.Content(
                  parts: systemMessage.content.map(toGeminiPart).toList(),
                  role: 'system',
                ),
        );

        if (ctx.streamingRequested) {
          final stream = service.streamGenerateContent(
            generateRequest,
            model: 'models/$modelName',
          );
          final chunks = <gcl.GenerateContentResponse>[];
          await for (final chunk in stream) {
            chunks.add(chunk);
            if (chunk.candidates?.isNotEmpty == true) {
              final (message, finishReason) = fromGeminiCandidate(
                chunk.candidates!.first,
              );
              ctx.sendChunk(
                ModelResponseChunk(index: 0, content: message.content),
              );
            }
          }
          final aggregated = aggregateResponses(chunks);
          if (aggregated.candidates?.isEmpty ?? true) {
            final blockReason = aggregated.promptFeedback?.blockReason;
            throw Exception(
              'No candidates returned from generative stream. Block reason: $blockReason',
            );
          }
          final (message, finishReason) = fromGeminiCandidate(
            aggregated.candidates!.first,
          );
          return ModelResponse(
            finishReason: finishReason,
            message: message,
            raw: aggregated.toJson(),
            usage: extractUsage(aggregated.usageMetadata),
          );
        } else {
          final response = await service.generateContent(
            generateRequest,
            model: 'models/$modelName',
          );
          if (response.candidates?.isEmpty ?? true) {
            final blockReason = response.promptFeedback?.blockReason;
            throw Exception(
              'No candidates returned from generateContent. Block reason: $blockReason',
            );
          }
          final (message, finishReason) = fromGeminiCandidate(
            response.candidates!.first,
          );
          return ModelResponse(
            finishReason: finishReason,
            message: message,
            raw: response?.toJson(),
            usage: extractUsage(response.usageMetadata),
          );
        }
      } catch (e, stack) {
        throw handleException(e, stack);
      } finally {
        service.client.close();
      }
    },
  );
}