@capgo/capacitor-llm 8.1.0 → 8.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -8
- package/android/src/main/java/ee/forgr/capgo_llm/LLM.java +20 -6
- package/android/src/main/java/ee/forgr/capgo_llm/LLMPlugin.java +3 -1
- package/dist/docs.json +12 -0
- package/dist/esm/definitions.d.ts +6 -0
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Sources/LLMPlugin/LLMPlugin.swift +27 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -380,14 +380,15 @@ Get the native Capacitor plugin version.
|
|
|
380
380
|
Model configuration options
|
|
381
381
|
Only `path` is required. All other properties are optional overrides.
|
|
382
382
|
|
|
383
|
-
| Prop | Type
|
|
384
|
-
| ----------------- |
|
|
385
|
-
| **`path`** | <code>string</code>
|
|
386
|
-
| **`modelType`** | <code>string</code>
|
|
387
|
-
| **`maxTokens`** | <code>number</code>
|
|
388
|
-
| **`topk`** | <code>number</code>
|
|
389
|
-
| **`temperature`** | <code>number</code>
|
|
390
|
-
| **`randomSeed`** | <code>number</code>
|
|
383
|
+
| Prop | Type | Description | Since |
|
|
384
|
+
| ----------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
|
|
385
|
+
| **`path`** | <code>string</code> | Model path, "Apple Intelligence" for the Apple system model on iOS, or "Gemini Nano" for the Android AICore system model when already available on the device. On iOS, custom `.litertlm` models require the plugin to be integrated through Swift Package Manager. Gemma 4 examples use `.litertlm` on mobile and `*-web.task` on web. | |
|
|
386
|
+
| **`modelType`** | <code>string</code> | Optional. Model file type/extension (for example `task`, `bin`, `litertlm`, or `gemini-nano`). If not provided, it is extracted from the path. Use `litertlm` on iOS only in SwiftPM integrations. | |
|
|
387
|
+
| **`maxTokens`** | <code>number</code> | Maximum number of tokens the model handles | |
|
|
388
|
+
| **`topk`** | <code>number</code> | Number of tokens the model considers at each step | |
|
|
389
|
+
| **`temperature`** | <code>number</code> | Amount of randomness in generation (0.0-1.0) | |
|
|
390
|
+
| **`randomSeed`** | <code>number</code> | Optional. Random seed for generation. | |
|
|
391
|
+
| **`backend`** | <code>'gpu' \| 'cpu'</code> | Optional. LiteRT-LM engine backend for iOS (SwiftPM) and Android. Use `cpu` for stable long generations. When omitted, iOS prefers CPU then falls back to GPU; Android uses CPU. | 8.2.0 |
|
|
391
392
|
|
|
392
393
|
|
|
393
394
|
#### DownloadModelResult
|
|
@@ -84,9 +84,10 @@ public class LLM {
|
|
|
84
84
|
Integer topk,
|
|
85
85
|
Float temperature,
|
|
86
86
|
Integer randomSeed,
|
|
87
|
+
String backend,
|
|
87
88
|
ModelLoadCallback callback
|
|
88
89
|
) {
|
|
89
|
-
ModelLoadRequest request = nextLoadRequest(path, modelType, maxTokens, topk, temperature, randomSeed);
|
|
90
|
+
ModelLoadRequest request = nextLoadRequest(path, modelType, maxTokens, topk, temperature, randomSeed, backend);
|
|
90
91
|
resetModelState();
|
|
91
92
|
|
|
92
93
|
android.util.Log.d(
|
|
@@ -111,10 +112,11 @@ public class LLM {
|
|
|
111
112
|
Integer maxTokens,
|
|
112
113
|
Integer topk,
|
|
113
114
|
Float temperature,
|
|
114
|
-
Integer randomSeed
|
|
115
|
+
Integer randomSeed,
|
|
116
|
+
String backend
|
|
115
117
|
) {
|
|
116
118
|
currentLoadId += 1;
|
|
117
|
-
return new ModelLoadRequest(path, modelType, maxTokens, topk, temperature, randomSeed, currentLoadId);
|
|
119
|
+
return new ModelLoadRequest(path, modelType, maxTokens, topk, temperature, randomSeed, backend, currentLoadId);
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
private synchronized boolean isCurrentLoad(long loadId) {
|
|
@@ -210,11 +212,12 @@ public class LLM {
|
|
|
210
212
|
}
|
|
211
213
|
|
|
212
214
|
private Engine initializeLiteRtModel(String actualPath, ModelLoadRequest request) {
|
|
215
|
+
Backend primaryBackend = resolveLiteRtBackend(request.backend);
|
|
213
216
|
EngineConfig config = new EngineConfig(
|
|
214
217
|
actualPath,
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
+
primaryBackend,
|
|
219
|
+
primaryBackend,
|
|
220
|
+
primaryBackend,
|
|
218
221
|
request.maxTokens,
|
|
219
222
|
context.getCacheDir().getAbsolutePath()
|
|
220
223
|
);
|
|
@@ -223,6 +226,14 @@ public class LLM {
|
|
|
223
226
|
return loadedEngine;
|
|
224
227
|
}
|
|
225
228
|
|
|
229
|
+
private Backend resolveLiteRtBackend(String backend) {
|
|
230
|
+
if (backend != null && "gpu".equalsIgnoreCase(backend.trim())) {
|
|
231
|
+
return new Backend.GPU();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return new Backend.CPU();
|
|
235
|
+
}
|
|
236
|
+
|
|
226
237
|
private LlmInference initializeMediaPipeModel(String actualPath, ModelLoadRequest request) {
|
|
227
238
|
LlmInferenceOptions options = LlmInferenceOptions.builder()
|
|
228
239
|
.setModelPath(actualPath)
|
|
@@ -820,6 +831,7 @@ public class LLM {
|
|
|
820
831
|
private final Integer topk;
|
|
821
832
|
private final Float temperature;
|
|
822
833
|
private final Integer randomSeed;
|
|
834
|
+
private final String backend;
|
|
823
835
|
private final long loadId;
|
|
824
836
|
|
|
825
837
|
private ModelLoadRequest(
|
|
@@ -829,6 +841,7 @@ public class LLM {
|
|
|
829
841
|
Integer topk,
|
|
830
842
|
Float temperature,
|
|
831
843
|
Integer randomSeed,
|
|
844
|
+
String backend,
|
|
832
845
|
long loadId
|
|
833
846
|
) {
|
|
834
847
|
this.modelPath = modelPath;
|
|
@@ -837,6 +850,7 @@ public class LLM {
|
|
|
837
850
|
this.topk = topk;
|
|
838
851
|
this.temperature = temperature;
|
|
839
852
|
this.randomSeed = randomSeed;
|
|
853
|
+
this.backend = backend;
|
|
840
854
|
this.loadId = loadId;
|
|
841
855
|
}
|
|
842
856
|
}
|
|
@@ -9,7 +9,7 @@ import com.getcapacitor.annotation.CapacitorPlugin;
|
|
|
9
9
|
@CapacitorPlugin(name = "CapgoLLM")
|
|
10
10
|
public class LLMPlugin extends Plugin {
|
|
11
11
|
|
|
12
|
-
private final String pluginVersion = "8.1.
|
|
12
|
+
private final String pluginVersion = "8.1.1";
|
|
13
13
|
|
|
14
14
|
private LLM llm;
|
|
15
15
|
|
|
@@ -106,6 +106,7 @@ public class LLMPlugin extends Plugin {
|
|
|
106
106
|
Float temperature = call.getFloat("temperature", 0.8f);
|
|
107
107
|
Integer randomSeed = call.getInt("randomSeed", 0);
|
|
108
108
|
String modelType = call.getString("modelType");
|
|
109
|
+
String backend = call.getString("backend");
|
|
109
110
|
|
|
110
111
|
llm.setModel(
|
|
111
112
|
path,
|
|
@@ -114,6 +115,7 @@ public class LLMPlugin extends Plugin {
|
|
|
114
115
|
topk,
|
|
115
116
|
temperature,
|
|
116
117
|
randomSeed,
|
|
118
|
+
backend,
|
|
117
119
|
new LLM.ModelLoadCallback() {
|
|
118
120
|
@Override
|
|
119
121
|
public void onSuccess() {
|
package/dist/docs.json
CHANGED
|
@@ -374,6 +374,18 @@
|
|
|
374
374
|
"docs": "Optional. Random seed for generation.",
|
|
375
375
|
"complexTypes": [],
|
|
376
376
|
"type": "number | undefined"
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
"name": "backend",
|
|
380
|
+
"tags": [
|
|
381
|
+
{
|
|
382
|
+
"text": "8.2.0",
|
|
383
|
+
"name": "since"
|
|
384
|
+
}
|
|
385
|
+
],
|
|
386
|
+
"docs": "Optional. LiteRT-LM engine backend for iOS (SwiftPM) and Android.\nUse `cpu` for stable long generations. When omitted, iOS prefers CPU then falls back to GPU; Android uses CPU.",
|
|
387
|
+
"complexTypes": [],
|
|
388
|
+
"type": "'gpu' | 'cpu' | undefined"
|
|
377
389
|
}
|
|
378
390
|
]
|
|
379
391
|
},
|
|
@@ -188,4 +188,10 @@ export interface ModelOptions {
|
|
|
188
188
|
temperature?: number;
|
|
189
189
|
/** Optional. Random seed for generation. */
|
|
190
190
|
randomSeed?: number;
|
|
191
|
+
/**
|
|
192
|
+
* Optional. LiteRT-LM engine backend for iOS (SwiftPM) and Android.
|
|
193
|
+
* Use `cpu` for stable long generations. When omitted, iOS prefers CPU then falls back to GPU; Android uses CPU.
|
|
194
|
+
* @since 8.2.0
|
|
195
|
+
*/
|
|
196
|
+
backend?: 'gpu' | 'cpu';
|
|
191
197
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * LLM Plugin interface for interacting with on-device language models\n */\nexport interface LLMPlugin {\n /**\n * Creates a new chat session\n * @returns Promise with chat id and optional instructions\n */\n createChat(): Promise<{ id: string; instructions?: string }>;\n\n /**\n * Sends a message to the AI in a specific chat session\n * @param options - The chat id and message to send\n * @returns Promise that resolves when message is sent\n */\n sendMessage(options: { chatId: string; message: string }): Promise<void>;\n\n /**\n * Gets the readiness status of the LLM\n * @returns Promise with readiness status string\n */\n getReadiness(): Promise<{ readiness: string }>;\n\n /**\n * Sets the model configuration\n * - iOS: Use \"Apple Intelligence\" as path for the system model. Custom LiteRT-LM `.litertlm` models are supported on iOS only when this plugin is integrated through Swift Package Manager.\n * - Android: Use \"Gemini Nano\" for the AICore system model on supported devices where it is already available. Prefer LiteRT-LM `.litertlm` bundles for custom models; legacy MediaPipe `.task` models are still supported\n * - Web: Provide a web-ready model asset for `@mediapipe/tasks-genai` such as Gemma 4 `*-web.task`\n * @param options - The model configuration\n * @returns Promise that resolves when model is loaded\n */\n setModel(options: ModelOptions): Promise<void>;\n\n /**\n * Downloads a model from a URL and saves it to the appropriate location\n * - iOS: Downloads to the app's documents directory\n * - Android: Downloads to the app's files directory\n * @param options - The download configuration\n * @returns Promise with download result including the saved path\n */\n downloadModel(options: DownloadModelOptions): Promise<DownloadModelResult>;\n\n /**\n * Adds a listener for text received from AI\n * @param eventName - Event name 'textFromAi'\n * @param listenerFunc - Callback function for text events\n * @returns Promise with remove function to unsubscribe\n */\n addListener(\n eventName: 'textFromAi',\n listenerFunc: (event: TextFromAiEvent) => void,\n ): Promise<{ remove: () => Promise<void> }>;\n\n /**\n * Adds a listener for AI completion events\n * @param eventName - Event name 'aiFinished'\n * @param listenerFunc - Callback function for finish events\n * @returns Promise with remove function to unsubscribe\n */\n addListener(\n eventName: 'aiFinished',\n listenerFunc: (event: AiFinishedEvent) => void,\n ): Promise<{ remove: () => Promise<void> }>;\n\n /**\n * Adds a listener for generation failures that happen after streaming starts\n * @param eventName - Event name 'generationError'\n * @param listenerFunc - Callback function for generation errors\n * @returns Promise with remove function to unsubscribe\n */\n addListener(\n eventName: 'generationError',\n listenerFunc: (event: GenerationErrorEvent) => void,\n ): Promise<{ remove: () => Promise<void> }>;\n\n /**\n * Adds a listener for model download progress events\n * @param eventName - Event name 'downloadProgress'\n * @param listenerFunc - Callback function for progress events\n * @returns Promise with remove function to unsubscribe\n */\n addListener(\n eventName: 'downloadProgress',\n listenerFunc: (event: DownloadProgressEvent) => void,\n ): Promise<{ remove: () => Promise<void> }>;\n\n /**\n * Adds a listener for readiness status changes\n * @param eventName - Event name 'readinessChange'\n * @param listenerFunc - Callback function for readiness events\n * @returns Promise with remove function to unsubscribe\n */\n addListener(\n eventName: 'readinessChange',\n listenerFunc: (event: ReadinessChangeEvent) => void,\n ): Promise<{ remove: () => Promise<void> }>;\n\n /**\n * Get the native Capacitor plugin version.\n *\n * @returns Promise that resolves with the plugin version\n * @throws Error if getting the version fails\n * @since 1.0.0\n * @example\n * ```typescript\n * const { version } = await CapgoLLM.getPluginVersion();\n * console.log('Plugin version:', version);\n * ```\n */\n getPluginVersion(): Promise<{ version: string }>;\n}\n\n/**\n * Event data for text received from AI\n */\nexport interface TextFromAiEvent {\n /** The text content from AI - this is an incremental chunk, not the full text */\n text: string;\n /** The chat session ID */\n chatId: string;\n /** Whether this is a complete chunk (true) or partial streaming data (false) */\n isChunk?: boolean;\n}\n\n/**\n * Event data for AI completion\n */\nexport interface AiFinishedEvent {\n /** The chat session ID that finished */\n chatId: string;\n}\n\n/**\n * Event data for generation failures\n * `chatId` is optional and may be omitted when the failure is not tied to a specific chat.\n */\nexport interface GenerationErrorEvent {\n /** Optional. The chat session ID that failed, when available. */\n chatId?: string;\n /** Error message describing the failure */\n error: string;\n}\n\n/**\n * Options for downloading a model\n * Only `url` is required. `companionUrl` and `filename` are optional.\n */\nexport interface DownloadModelOptions {\n /** URL of the model file to download */\n url: string;\n /** Optional: URL of a companion file for legacy model formats */\n companionUrl?: string;\n /** Optional: Custom filename (defaults to filename from URL) */\n filename?: string;\n}\n\n/**\n * Result of model download\n */\nexport interface DownloadModelResult {\n /** Path where the model was saved */\n path: string;\n /** Path where the companion file was saved (if applicable) */\n companionPath?: string;\n}\n\n/**\n * Event data for download progress\n */\nexport interface DownloadProgressEvent {\n /** Percentage of download completed (0-100) */\n progress: number;\n /** Total bytes to download */\n totalBytes?: number;\n /** Bytes downloaded so far */\n downloadedBytes?: number;\n}\n\n/**\n * Event data for readiness status changes\n */\nexport interface ReadinessChangeEvent {\n /** The readiness status */\n readiness: string;\n}\n\n/**\n * Model configuration options\n * Only `path` is required. All other properties are optional overrides.\n */\nexport interface ModelOptions {\n /** Model path, \"Apple Intelligence\" for the Apple system model on iOS, or \"Gemini Nano\" for the Android AICore system model when already available on the device. On iOS, custom `.litertlm` models require the plugin to be integrated through Swift Package Manager. Gemma 4 examples use `.litertlm` on mobile and `*-web.task` on web. */\n path: string;\n /** Optional. Model file type/extension (for example `task`, `bin`, `litertlm`, or `gemini-nano`). If not provided, it is extracted from the path. Use `litertlm` on iOS only in SwiftPM integrations. */\n modelType?: string;\n /** Maximum number of tokens the model handles */\n maxTokens?: number;\n /** Number of tokens the model considers at each step */\n topk?: number;\n /** Amount of randomness in generation (0.0-1.0) */\n temperature?: number;\n /** Optional. Random seed for generation. */\n randomSeed?: number;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * LLM Plugin interface for interacting with on-device language models\n */\nexport interface LLMPlugin {\n /**\n * Creates a new chat session\n * @returns Promise with chat id and optional instructions\n */\n createChat(): Promise<{ id: string; instructions?: string }>;\n\n /**\n * Sends a message to the AI in a specific chat session\n * @param options - The chat id and message to send\n * @returns Promise that resolves when message is sent\n */\n sendMessage(options: { chatId: string; message: string }): Promise<void>;\n\n /**\n * Gets the readiness status of the LLM\n * @returns Promise with readiness status string\n */\n getReadiness(): Promise<{ readiness: string }>;\n\n /**\n * Sets the model configuration\n * - iOS: Use \"Apple Intelligence\" as path for the system model. Custom LiteRT-LM `.litertlm` models are supported on iOS only when this plugin is integrated through Swift Package Manager.\n * - Android: Use \"Gemini Nano\" for the AICore system model on supported devices where it is already available. Prefer LiteRT-LM `.litertlm` bundles for custom models; legacy MediaPipe `.task` models are still supported\n * - Web: Provide a web-ready model asset for `@mediapipe/tasks-genai` such as Gemma 4 `*-web.task`\n * @param options - The model configuration\n * @returns Promise that resolves when model is loaded\n */\n setModel(options: ModelOptions): Promise<void>;\n\n /**\n * Downloads a model from a URL and saves it to the appropriate location\n * - iOS: Downloads to the app's documents directory\n * - Android: Downloads to the app's files directory\n * @param options - The download configuration\n * @returns Promise with download result including the saved path\n */\n downloadModel(options: DownloadModelOptions): Promise<DownloadModelResult>;\n\n /**\n * Adds a listener for text received from AI\n * @param eventName - Event name 'textFromAi'\n * @param listenerFunc - Callback function for text events\n * @returns Promise with remove function to unsubscribe\n */\n addListener(\n eventName: 'textFromAi',\n listenerFunc: (event: TextFromAiEvent) => void,\n ): Promise<{ remove: () => Promise<void> }>;\n\n /**\n * Adds a listener for AI completion events\n * @param eventName - Event name 'aiFinished'\n * @param listenerFunc - Callback function for finish events\n * @returns Promise with remove function to unsubscribe\n */\n addListener(\n eventName: 'aiFinished',\n listenerFunc: (event: AiFinishedEvent) => void,\n ): Promise<{ remove: () => Promise<void> }>;\n\n /**\n * Adds a listener for generation failures that happen after streaming starts\n * @param eventName - Event name 'generationError'\n * @param listenerFunc - Callback function for generation errors\n * @returns Promise with remove function to unsubscribe\n */\n addListener(\n eventName: 'generationError',\n listenerFunc: (event: GenerationErrorEvent) => void,\n ): Promise<{ remove: () => Promise<void> }>;\n\n /**\n * Adds a listener for model download progress events\n * @param eventName - Event name 'downloadProgress'\n * @param listenerFunc - Callback function for progress events\n * @returns Promise with remove function to unsubscribe\n */\n addListener(\n eventName: 'downloadProgress',\n listenerFunc: (event: DownloadProgressEvent) => void,\n ): Promise<{ remove: () => Promise<void> }>;\n\n /**\n * Adds a listener for readiness status changes\n * @param eventName - Event name 'readinessChange'\n * @param listenerFunc - Callback function for readiness events\n * @returns Promise with remove function to unsubscribe\n */\n addListener(\n eventName: 'readinessChange',\n listenerFunc: (event: ReadinessChangeEvent) => void,\n ): Promise<{ remove: () => Promise<void> }>;\n\n /**\n * Get the native Capacitor plugin version.\n *\n * @returns Promise that resolves with the plugin version\n * @throws Error if getting the version fails\n * @since 1.0.0\n * @example\n * ```typescript\n * const { version } = await CapgoLLM.getPluginVersion();\n * console.log('Plugin version:', version);\n * ```\n */\n getPluginVersion(): Promise<{ version: string }>;\n}\n\n/**\n * Event data for text received from AI\n */\nexport interface TextFromAiEvent {\n /** The text content from AI - this is an incremental chunk, not the full text */\n text: string;\n /** The chat session ID */\n chatId: string;\n /** Whether this is a complete chunk (true) or partial streaming data (false) */\n isChunk?: boolean;\n}\n\n/**\n * Event data for AI completion\n */\nexport interface AiFinishedEvent {\n /** The chat session ID that finished */\n chatId: string;\n}\n\n/**\n * Event data for generation failures\n * `chatId` is optional and may be omitted when the failure is not tied to a specific chat.\n */\nexport interface GenerationErrorEvent {\n /** Optional. The chat session ID that failed, when available. */\n chatId?: string;\n /** Error message describing the failure */\n error: string;\n}\n\n/**\n * Options for downloading a model\n * Only `url` is required. `companionUrl` and `filename` are optional.\n */\nexport interface DownloadModelOptions {\n /** URL of the model file to download */\n url: string;\n /** Optional: URL of a companion file for legacy model formats */\n companionUrl?: string;\n /** Optional: Custom filename (defaults to filename from URL) */\n filename?: string;\n}\n\n/**\n * Result of model download\n */\nexport interface DownloadModelResult {\n /** Path where the model was saved */\n path: string;\n /** Path where the companion file was saved (if applicable) */\n companionPath?: string;\n}\n\n/**\n * Event data for download progress\n */\nexport interface DownloadProgressEvent {\n /** Percentage of download completed (0-100) */\n progress: number;\n /** Total bytes to download */\n totalBytes?: number;\n /** Bytes downloaded so far */\n downloadedBytes?: number;\n}\n\n/**\n * Event data for readiness status changes\n */\nexport interface ReadinessChangeEvent {\n /** The readiness status */\n readiness: string;\n}\n\n/**\n * Model configuration options\n * Only `path` is required. All other properties are optional overrides.\n */\nexport interface ModelOptions {\n /** Model path, \"Apple Intelligence\" for the Apple system model on iOS, or \"Gemini Nano\" for the Android AICore system model when already available on the device. On iOS, custom `.litertlm` models require the plugin to be integrated through Swift Package Manager. Gemma 4 examples use `.litertlm` on mobile and `*-web.task` on web. */\n path: string;\n /** Optional. Model file type/extension (for example `task`, `bin`, `litertlm`, or `gemini-nano`). If not provided, it is extracted from the path. Use `litertlm` on iOS only in SwiftPM integrations. */\n modelType?: string;\n /** Maximum number of tokens the model handles */\n maxTokens?: number;\n /** Number of tokens the model considers at each step */\n topk?: number;\n /** Amount of randomness in generation (0.0-1.0) */\n temperature?: number;\n /** Optional. Random seed for generation. */\n randomSeed?: number;\n /**\n * Optional. LiteRT-LM engine backend for iOS (SwiftPM) and Android.\n * Use `cpu` for stable long generations. When omitted, iOS prefers CPU then falls back to GPU; Android uses CPU.\n * @since 8.2.0\n */\n backend?: 'gpu' | 'cpu';\n}\n"]}
|
|
@@ -17,7 +17,7 @@ import MediaPipeTasksGenAI
|
|
|
17
17
|
|
|
18
18
|
@objc(LLMPlugin)
|
|
19
19
|
public class LLMPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
20
|
-
private let pluginVersion: String = "8.1.
|
|
20
|
+
private let pluginVersion: String = "8.1.1"
|
|
21
21
|
private let liteRtTopP: Float = 0.95
|
|
22
22
|
|
|
23
23
|
public let identifier = "LLMPlugin"
|
|
@@ -80,6 +80,7 @@ public class LLMPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
80
80
|
let temperature = call.getFloat("temperature") ?? 0.8
|
|
81
81
|
let randomSeed = call.getInt("randomSeed") ?? 0
|
|
82
82
|
let modelType = call.getString("modelType")
|
|
83
|
+
let backend = call.getString("backend")
|
|
83
84
|
|
|
84
85
|
modelPath = path
|
|
85
86
|
isReady = false
|
|
@@ -112,7 +113,11 @@ public class LLMPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
112
113
|
Task {
|
|
113
114
|
do {
|
|
114
115
|
let modelURL = try resolveModelURL(path: path, modelType: modelType)
|
|
115
|
-
let engine = try await initializeLiteRtEngine(
|
|
116
|
+
let engine = try await initializeLiteRtEngine(
|
|
117
|
+
modelURL: modelURL,
|
|
118
|
+
maxTokens: maxTokens,
|
|
119
|
+
backend: backend
|
|
120
|
+
)
|
|
116
121
|
liteRtEngine = engine
|
|
117
122
|
liteRtTopk = topk
|
|
118
123
|
liteRtTemperature = temperature
|
|
@@ -528,7 +533,11 @@ private extension LLMPlugin {
|
|
|
528
533
|
|
|
529
534
|
#if canImport(LiteRTLM)
|
|
530
535
|
private extension LLMPlugin {
|
|
531
|
-
func initializeLiteRtEngine(
|
|
536
|
+
func initializeLiteRtEngine(
|
|
537
|
+
modelURL: URL,
|
|
538
|
+
maxTokens: Int,
|
|
539
|
+
backend: String?
|
|
540
|
+
) async throws -> LiteRTLM.Engine {
|
|
532
541
|
guard let cacheDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else {
|
|
533
542
|
throw NSError(
|
|
534
543
|
domain: "CapgoLLM",
|
|
@@ -537,20 +546,25 @@ private extension LLMPlugin {
|
|
|
537
546
|
)
|
|
538
547
|
}
|
|
539
548
|
|
|
540
|
-
let
|
|
549
|
+
let cacheDir = cacheDirectory.path
|
|
550
|
+
let makeConfig = { (selectedBackend: LiteRTLM.Backend) throws -> LiteRTLM.EngineConfig in
|
|
541
551
|
try LiteRTLM.EngineConfig(
|
|
542
552
|
modelPath: modelURL.path,
|
|
543
|
-
backend:
|
|
553
|
+
backend: selectedBackend,
|
|
544
554
|
maxNumTokens: maxTokens,
|
|
545
|
-
cacheDir:
|
|
546
|
-
),
|
|
547
|
-
try LiteRTLM.EngineConfig(
|
|
548
|
-
modelPath: modelURL.path,
|
|
549
|
-
backend: .cpu(),
|
|
550
|
-
maxNumTokens: maxTokens,
|
|
551
|
-
cacheDir: cacheDirectory.path
|
|
555
|
+
cacheDir: cacheDir
|
|
552
556
|
)
|
|
553
|
-
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
let configs: [LiteRTLM.EngineConfig]
|
|
560
|
+
switch backend?.lowercased() {
|
|
561
|
+
case "cpu":
|
|
562
|
+
configs = [try makeConfig(.cpu())]
|
|
563
|
+
case "gpu":
|
|
564
|
+
configs = [try makeConfig(.gpu), try makeConfig(.cpu())]
|
|
565
|
+
default:
|
|
566
|
+
configs = [try makeConfig(.cpu()), try makeConfig(.gpu)]
|
|
567
|
+
}
|
|
554
568
|
|
|
555
569
|
var lastError: Error?
|
|
556
570
|
for config in configs {
|