aa8fff2c0d
Integrates LiteRT-LM (Google) with Gemma 4 E2B-it for on-device spell/grammar correction in HeliBoard. After sentence-ending punctuation, the model checks the sentence and shows a correction in the suggestion strip. Tapping it replaces the original text — fully offline, no cloud API. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100 lines
5.6 KiB
Diff
100 lines
5.6 KiB
Diff
From: AIKeyboard AI Integration <ai@aikeyboard.local>
|
|
Date: Wed, 09 Apr 2025 00:00:00 +0000
|
|
Subject: [PATCH 2/3] Wire AI engine lifecycle into LatinIME
|
|
|
|
- Declare AI component fields after existing field declarations
|
|
- Initialize AiCorrectionEngine, AiSuggestionManager, AiTriggerHook in onCreate()
|
|
- Clean up (cancel coroutines, close LlmInference) in onDestroy()
|
|
- Expose getAiTriggerHook() accessor used by InputLogic patch
|
|
---
|
|
.../keyboard/latin/LatinIME.java | 54 ++++++++++++++++++
|
|
1 file changed, 54 insertions(+)
|
|
|
|
diff --git a/app/src/main/java/helium314/keyboard/latin/LatinIME.java b/app/src/main/java/helium314/keyboard/latin/LatinIME.java
|
|
index xxxxxxx..xxxxxxx 100644
|
|
--- a/app/src/main/java/helium314/keyboard/latin/LatinIME.java
|
|
+++ b/app/src/main/java/helium314/keyboard/latin/LatinIME.java
|
|
@@ -133,6 +133,15 @@ public class LatinIME extends InputMethodService implements
|
|
private RichInputMethodManager mRichImm;
|
|
final KeyboardSwitcher mKeyboardSwitcher;
|
|
|
|
+ // ── AI spell correction components ──────────────────────────────────────
|
|
+ // Lazily initialised in onCreate(); destroyed in onDestroy().
|
|
+ private helium314.keyboard.latin.ai.AiCorrectionEngine mAiCorrectionEngine;
|
|
+ private helium314.keyboard.latin.ai.AiSuggestionManager mAiSuggestionManager;
|
|
+ private helium314.keyboard.latin.ai.AiTriggerHook mAiTriggerHook;
|
|
+ // CoroutineScope type requires kotlin.coroutines on classpath (satisfied by
|
|
+ // kotlinx-coroutines-android dependency in app/build.gradle.kts).
|
|
+ private kotlinx.coroutines.CoroutineScope mAiScope;
|
|
+ // ────────────────────────────────────────────────────────────────────────
|
|
+
|
|
private final SubtypeState mSubtypeState = new SubtypeState(
|
|
(InputMethodSubtype subtype) -> { switchToSubtype(subtype); return Unit.INSTANCE; });
|
|
private final StatsUtilsManager mStatsUtilsManager;
|
|
@@ -572,6 +581,21 @@ public class LatinIME extends InputMethodService implements
|
|
registerReceiver(mRestartAfterDeviceUnlockReceiver, restartAfterUnlockFilter);
|
|
|
|
StatsUtils.onCreate(mSettings.getCurrent(), mRichImm);
|
|
+
|
|
+ // ── Initialise AI components ─────────────────────────────────────────
|
|
+ // AiSuggestionManager must be attached before AiTriggerHook is created
|
|
+ // so that the first correction result has somewhere to go.
|
|
+ mAiSuggestionManager = new helium314.keyboard.latin.ai.AiSuggestionManager();
|
|
+ mAiSuggestionManager.attachAccessor(this);
|
|
+ mAiCorrectionEngine = new helium314.keyboard.latin.ai.AiCorrectionEngine(this);
|
|
+ // createImeScope() returns a SupervisorJob-backed CoroutineScope.
|
|
+ // Using @JvmStatic companion factory avoids complex Java↔Kotlin interop.
|
|
+ mAiScope = helium314.keyboard.latin.ai.AiSuggestionManager.createImeScope();
|
|
+ mAiTriggerHook = new helium314.keyboard.latin.ai.AiTriggerHook(
|
|
+ mAiCorrectionEngine,
|
|
+ mAiSuggestionManager,
|
|
+ mAiScope
|
|
+ );
|
|
+ // ────────────────────────────────────────────────────────────────────
|
|
}
|
|
|
|
@@ -683,6 +697,22 @@ public class LatinIME extends InputMethodService implements
|
|
@Override
|
|
public void onDestroy() {
|
|
mClipboardHistoryManager.onDestroy();
|
|
+
|
|
+ // ── Tear down AI components before releasing dictionaries ────────────
|
|
+ if (mAiTriggerHook != null) {
|
|
+ mAiTriggerHook.cancel();
|
|
+ }
|
|
+ if (mAiScope != null) {
|
|
+ // Cancel the coroutine scope to stop any in-flight correction jobs.
|
|
+ kotlinx.coroutines.JobKt.cancel(
|
|
+ (kotlinx.coroutines.Job) mAiScope.getCoroutineContext()
|
|
+ .get(kotlinx.coroutines.Job.Key),
|
|
+ null
|
|
+ );
|
|
+ }
|
|
+ if (mAiCorrectionEngine != null) {
|
|
+ mAiCorrectionEngine.close();
|
|
+ }
|
|
+ if (mAiSuggestionManager != null) {
|
|
+ mAiSuggestionManager.detachAccessor();
|
|
+ }
|
|
+ // ────────────────────────────────────────────────────────────────────
|
|
+
|
|
mDictionaryFacilitator.closeDictionaries();
|
|
mSettings.onDestroy();
|
|
unregisterReceiver(mRingerModeChangeReceiver);
|
|
@@ -695,4 +725,14 @@ public class LatinIME extends InputMethodService implements
|
|
mHandler.removeCallbacksAndMessages(null);
|
|
deallocateMemory();
|
|
}
|
|
+
|
|
+ // ── AI accessor ──────────────────────────────────────────────────────────
|
|
+ /**
|
|
+ * Returns the AiTriggerHook instance for use by InputLogic.
|
|
+ * Returns null if AI initialisation has not yet completed (race-safe).
|
|
+ */
|
|
+ @androidx.annotation.Nullable
|
|
+ public helium314.keyboard.latin.ai.AiTriggerHook getAiTriggerHook() {
|
|
+ return mAiTriggerHook;
|
|
+ }
|
|
+ // ────────────────────────────────────────────────────────────────────────
|
|
}
|