createSession method

  1. @override
Future<InferenceModelSession> createSession({
  1. double temperature = .8,
  2. int randomSeed = 1,
  3. int topK = 1,
  4. double? topP,
  5. String? loraPath,
  6. bool? enableVisionModality,
  7. bool? enableAudioModality,
  8. String? systemInstruction,
  9. bool enableThinking = false,
  10. List<Tool> tools = const [],
})
override

Creates a new InferenceModelSession for generation.

temperature, randomSeed, topK, topP — parameters for sampling. loraPath — optional path to LoRA model. enableVisionModality — enable vision modality for multimodal models. enableAudioModality — enable audio modality for Gemma 3n E4B models.

Implementation

@override
Future<InferenceModelSession> createSession({
  double temperature = .8,
  int randomSeed = 1,
  int topK = 1,
  double? topP,
  String? loraPath,
  bool? enableVisionModality,
  bool? enableAudioModality,
  String? systemInstruction,
  bool enableThinking = false,
  List<Tool> tools = const [],
}) async {
  if (_isClosed) {
    throw StateError(
        'Model is closed. Create a new instance to use it again');
  }
  if (loraPath != null) {
    throw UnsupportedError(
      'LoRA weights are not supported on the .litertlm web path '
      '(loraPath=$loraPath). Track upstream @litert-lm/core; remove '
      'loraPath or use a MediaPipe .task web model.',
    );
  }

  // Vision/audio modality on web @litert-lm/core@0.12.1 requires a
  // dedicated Vision/AudioExecutor to be loaded at Engine.create() time.
  // The WASM runtime asserts "Vision executor should not be null, please
  // TryLoadingVisionExecutor() first.", but the TypeScript-level
  // `EngineSettings` interface (wasm_binding_types.d.ts) only exposes
  // `getMutableMainExecutorSettings()` — there's no setter for
  // VisionExecutorSettings or AudioExecutorSettings in the early preview.
  // Engine logs confirm this with `max_num_images: 0` baked in at create.
  //
  // Until upstream adds the Vision/Audio executor setters to the JS API,
  // setting `visionModalityEnabled`/`audioModalityEnabled: true` in
  // SessionConfig throws "Audio options should not be null" / "Vision
  // options should not be null" — so we force-disable them and warn.
  if (enableVisionModality == true || enableAudioModality == true) {
    if (kDebugMode) {
      debugPrint('[LiteRtLmWebInferenceModel] Warning: vision/audio modality '
          'is requested but @litert-lm/core@0.12.1 does not expose the '
          'Vision/AudioExecutor config in its TypeScript API — image/audio '
          'inputs are dropped on web until upstream extends EngineSettings. '
          'Track: https://github.com/google-ai-edge/LiteRT-LM');
    }
  }
  const visionEnabled = false;
  const audioEnabled = false;

  if (_createCompleter case Completer<InferenceModelSession> completer) {
    return completer.future;
  }
  final completer = _createCompleter = Completer<InferenceModelSession>();
  final sessionSw = Stopwatch()..start();

  try {
    final conversation = await _buildConversation(
      temperature: temperature,
      randomSeed: randomSeed,
      topK: topK,
      topP: topP,
      systemInstruction: systemInstruction,
      enableThinking: enableThinking,
      tools: tools,
      sw: sessionSw,
    );

    final session = _session = LiteRtLmWebSession(
      conversation: conversation,
      modelType: modelType,
      fileType: fileType,
      supportImage: visionEnabled,
      supportAudio: audioEnabled,
      generationMutex: generationMutex,
      onClose: () {
        _session = null;
        _createCompleter = null;
      },
    );

    completer.complete(session);
    if (kDebugMode) {
      debugPrint(
          '[LiteRtLmWebInferenceModel/perf] createSession total: ${sessionSw.elapsedMilliseconds}ms');
    }
    return session;
  } catch (e, st) {
    completer.completeError(e, st);
    _createCompleter = null;
    rethrow;
  }
}