Problem
Gemma-4 E4B natively supports a "thinking" mode where it generates internal reasoning tokens (<think>...</think>) before producing its visible response. Our app already captures these tokens:
// LiteRtInferenceEngine.kt, lines 180-183
val thought = message.channels["thought"]
if (thought != null) {
// Routes as GenerationResult.Thinking
}
However, we have zero control over this behavior:
- No thinking budget — we can't tell the model to use more or fewer thinking tokens. It uses whatever its default is.
- No on/off toggle — users can't disable thinking mode for simple queries (wastes tokens and adds latency) or enable it for complex reasoning tasks.
- No UI configuration —
ModelSettingsEntity has no thinking-related fields. The settings screen has no thinking controls.
- Unknown API surface — we need to investigate what
LiteRT-LM actually exposes for thinking budget configuration.
Impact
- TTFT (Time to First Token): Thinking adds significant latency because the model generates reasoning tokens before the visible response. For simple queries like "turn on torch" or "what time is it", this is wasted time.
- Token budget: Thinking tokens consume context window space. On a 4096-token window, even 200 thinking tokens is meaningful.
- Quality: For complex queries (multi-step reasoning, math, planning), thinking dramatically improves output quality. We should enable users to leverage this.
Research Needed
LiteRT-LM Thinking Configuration API
Before implementation, investigate:
-
Does LiteRT-LM support thinkingConfig / thinkingBudget?
- Check the LiteRT-LM Kotlin SDK for configuration options when creating/initializing the engine
- Look for
ThinkingConfig, thinkingBudget, enableThinking, or similar parameters
- Reference: https://github.com/AIDevelopersMonster/LiteRT-LM (check Kotlin API)
-
How does Gemma-4 E4B handle thinking natively?
- The model likely uses
<think> tags in its tokenizer vocabulary
- Can we suppress thinking by including "Do not think" in the system prompt? (crude but may work)
- Is there a generation config parameter that controls thinking token budget?
-
What does Edge Gallery do?
- Check if AI Edge Gallery configures thinking budget in its
LlmChatModelHelper.initialize()
- Look for any
thinkingConfig in their model initialization code
Implementation Plan
Phase A: Research + Basic Toggle
-
Investigate LiteRT-LM API — document what's available for thinking configuration:
- Check
LlmModelConfig, SamplerConfig, or engine initialization params
- File findings in a comment on this issue
-
Add thinkingEnabled: Boolean to ModelSettingsEntity:
@Entity(tableName = "model_settings")
data class ModelSettingsEntity(
@PrimaryKey val modelName: String,
val contextWindowSize: Int = 4096,
val temperature: Float = 0.7f,
val topP: Float = 0.95f,
val topK: Int = 40,
val thinkingEnabled: Boolean = true // NEW
)
-
Add thinking toggle to ModelSettingsScreen.kt:
- Switch: "Enable thinking mode"
- Description: "Model reasons internally before responding. Improves quality but adds latency."
- Default: ON (for Gemma-4 models that support it)
-
Apply toggle in LiteRtInferenceEngine:
- If
thinkingEnabled == false:
- Option A (API): Pass
thinkingBudget = 0 to LiteRT-LM (if supported)
- Option B (prompt): Prepend "Do not use internal reasoning" to system prompt
- Option C (filter): Suppress
channels["thought"] output (model still thinks, we just ignore it — least useful)
Phase B: Budget Control (if API supports it)
-
Add thinkingBudget: Int to ModelSettingsEntity (nullable, null = auto):
val thinkingBudget: Int? = null // null = model default, 0 = off, 100-2000 = custom
-
Add thinking budget slider to settings UI:
- Only visible when thinking toggle is ON
- Range: 0-2000 tokens (step 50)
- Special values: "Auto" (null/default), "Off" (0)
- Label: "Thinking budget (tokens)"
-
Pass budget to LiteRT-LM during inference:
// Pseudocode — actual API TBD from research
val thinkingConfig = ThinkingConfig(
enabled = settings.thinkingEnabled,
budget = settings.thinkingBudget ?: -1 // -1 = auto
)
engine.configure(thinkingConfig = thinkingConfig)
Phase C: Smart Defaults
-
Auto-detect thinking capability — not all models support thinking:
- If model doesn't emit
channels["thought"] tokens, hide thinking settings
- Show thinking settings only for compatible models (Gemma-4 E4B, future thinking models)
-
Task-aware thinking (advanced, optional):
- Disable thinking for simple tool calls (alarm, torch, timer)
- Enable thinking for complex queries (math, reasoning, planning)
- Implementation: lightweight classifier before inference, or just use low thinking budget for tool-call turns
- Decision needed: worth the complexity? May defer.
UI Mockup
Model Settings
├── Context Window: [====|========] 4096
├── Temperature: [===|=========] 0.7
├── Top-P: [========|====] 0.95
├── Top-K: [====|========] 40
├── ── Presets: [Precise] [Balanced] [Creative]
├──
├── Thinking Mode
│ ├── [✓] Enable thinking mode
│ ├── Budget: [Auto ▼] / [=====|=====] 500 tokens
│ └── ℹ️ "Model reasons internally before responding"
Files to Modify
| File |
Changes |
ModelSettingsEntity.kt |
Add thinkingEnabled, thinkingBudget fields |
ModelSettingsDao.kt |
Room migration |
ModelSettingsScreen.kt |
Add thinking toggle + budget slider |
ChatViewModel.kt |
Pass thinking config to engine |
LiteRtInferenceEngine.kt |
Apply thinking configuration to LiteRT-LM |
ModelConfig.kt |
Add thinking defaults |
Success Criteria
Related
Problem
Gemma-4 E4B natively supports a "thinking" mode where it generates internal reasoning tokens (
<think>...</think>) before producing its visible response. Our app already captures these tokens:However, we have zero control over this behavior:
ModelSettingsEntityhas no thinking-related fields. The settings screen has no thinking controls.LiteRT-LMactually exposes for thinking budget configuration.Impact
Research Needed
LiteRT-LM Thinking Configuration API
Before implementation, investigate:
Does
LiteRT-LMsupportthinkingConfig/thinkingBudget?ThinkingConfig,thinkingBudget,enableThinking, or similar parametersHow does Gemma-4 E4B handle thinking natively?
<think>tags in its tokenizer vocabularyWhat does Edge Gallery do?
LlmChatModelHelper.initialize()thinkingConfigin their model initialization codeImplementation Plan
Phase A: Research + Basic Toggle
Investigate LiteRT-LM API — document what's available for thinking configuration:
LlmModelConfig,SamplerConfig, or engine initialization paramsAdd
thinkingEnabled: BooleantoModelSettingsEntity:Add thinking toggle to
ModelSettingsScreen.kt:Apply toggle in
LiteRtInferenceEngine:thinkingEnabled == false:thinkingBudget = 0to LiteRT-LM (if supported)channels["thought"]output (model still thinks, we just ignore it — least useful)Phase B: Budget Control (if API supports it)
Add
thinkingBudget: InttoModelSettingsEntity(nullable, null = auto):Add thinking budget slider to settings UI:
Pass budget to LiteRT-LM during inference:
Phase C: Smart Defaults
Auto-detect thinking capability — not all models support thinking:
channels["thought"]tokens, hide thinking settingsTask-aware thinking (advanced, optional):
UI Mockup
Files to Modify
ModelSettingsEntity.ktthinkingEnabled,thinkingBudgetfieldsModelSettingsDao.ktModelSettingsScreen.ktChatViewModel.ktLiteRtInferenceEngine.ktModelConfig.ktSuccess Criteria
Related