getActiveModel static method

Future<InferenceModel> getActiveModel({
  1. ModelRuntimeDefaults? defaults,
  2. int? maxTokens,
  3. PreferredBackend? preferredBackend,
  4. PreferredBackend? preferredVisionBackend,
  5. PreferredBackend? preferredAudioBackend,
  6. bool? supportImage,
  7. bool? supportAudio,
  8. int? maxNumImages,
  9. bool? enableSpeculativeDecoding,
  10. int? maxConcurrentSessions,
})

Get the active inference model as a ready-to-use InferenceModel

Returns an InferenceModel configured with runtime parameters. The model type and file type come from the active InferenceModelSpec.

Runtime parameters:

  • maxTokens: Maximum context size (default: 1024)
  • preferredBackend: CPU or GPU preference (optional)
  • preferredVisionBackend: vision-encoder backend override; null defaults to CPU (optional)
  • preferredAudioBackend: audio-encoder backend override; null defaults to CPU (optional)
  • supportImage: Enable multimodal image support (default: false)
  • supportAudio: Enable audio input support for Gemma 3n E4B (default: false)
  • maxNumImages: Maximum number of images if supportImage is true
  • defaults: overridable runtime defaults from a HF manifest (see resolveHuggingFace / ResolvedHfModel.runtime). Each explicit argument above wins over the matching field here, which in turn wins over the SDK default — so getActiveModel(defaults: r.runtime) applies the manifest's guidance and getActiveModel() behaves exactly as before. NOTE: the two session-level fields (isThinking, minOutputTokens) are NOT applied here — forward them to createSession yourself.

Throws:

Example:

// Install model first
await FlutterGemma.installModel(
  modelType: ModelType.gemmaIt,
).fromNetwork('https://example.com/model.task').install();

// Create with short context
final shortModel = await FlutterGemma.getActiveModel(
  maxTokens: 512,
);

// Create with long context and GPU
final longModel = await FlutterGemma.getActiveModel(
  maxTokens: 4096,
  preferredBackend: PreferredBackend.gpu,
);

// Create with audio support (Gemma 3n E4B only)
final audioModel = await FlutterGemma.getActiveModel(
  supportAudio: true,
);

Implementation

static Future<InferenceModel> getActiveModel({
  ModelRuntimeDefaults? defaults,
  int? maxTokens,
  PreferredBackend? preferredBackend,
  PreferredBackend? preferredVisionBackend,
  PreferredBackend? preferredAudioBackend,
  bool? supportImage,
  bool? supportAudio,
  int? maxNumImages,
  bool? enableSpeculativeDecoding,
  int? maxConcurrentSessions,
}) async {
  final manager = FlutterGemmaPlugin.instance.modelManager;
  final activeSpec = manager.activeInferenceModel;

  if (activeSpec == null) {
    throw StateError(
      'No active inference model set. Use FlutterGemma.installModel() first.',
    );
  }

  if (activeSpec is! InferenceModelSpec) {
    throw StateError(
      'Active model is not an InferenceModelSpec. '
      'Expected InferenceModelSpec, got ${activeSpec.runtimeType}',
    );
  }

  // Merge precedence: explicit argument > manifest [defaults] > SDK default.
  // maxTokens keeps its historical 1024 fallback, so an omitted arg with no
  // defaults behaves exactly as before. The .litertlm engine still clamps
  // this value downstream (clampLitertlmContextTokens) — a manifest cannot
  // set a context window the engine rejects (guards #318).
  final effMaxTokens = mergeRuntimeDefault(
    maxTokens,
    defaults?.maxTokens,
    1024,
  );
  final effPreferredBackend = preferredBackend ?? defaults?.preferredBackend;
  final effSupportImage = mergeRuntimeDefault(
    supportImage,
    defaults?.supportImage,
    false,
  );
  final effSupportAudio = mergeRuntimeDefault(
    supportAudio,
    defaults?.supportAudio,
    false,
  );

  // [defaults] also carries two SESSION-level fields (isThinking,
  // minOutputTokens) that this model-level call cannot apply. Warn (debug
  // builds) so a caller who passes `defaults:` here and forgets to forward
  // them to createSession finds out, instead of a reasoning model silently
  // truncating mid-<think>.
  if (defaults != null &&
      (defaults.isThinking != null || defaults.minOutputTokens != null)) {
    gemmaLog(
      '[flutter_gemma] getActiveModel: manifest defaults carry session-level '
      'fields (isThinking/minOutputTokens) that getActiveModel does not apply '
      '— forward them to createSession(enableThinking:, maxOutputTokens:).',
    );
  }

  // Create InferenceModel using identity from spec + runtime params
  return await FlutterGemmaPlugin.instance.createModel(
    modelType: activeSpec.modelType,
    fileType: activeSpec.fileType,
    maxTokens: effMaxTokens,
    preferredBackend: effPreferredBackend,
    preferredVisionBackend: preferredVisionBackend,
    preferredAudioBackend: preferredAudioBackend,
    supportImage: effSupportImage,
    supportAudio: effSupportAudio,
    maxNumImages: maxNumImages,
    enableSpeculativeDecoding: enableSpeculativeDecoding,
    maxConcurrentSessions: maxConcurrentSessions,
  );
}