One Interface.
Every AI Model.
Zero Data Lock-In.

Run local GGUF models on-device with zero lock-in, auto-sync Markdown to Obsidian, and orchestrate 8+ cloud providers seamlessly.

100%
Offline GGUF Inference
384D
Vector Memory Recall
<10ms
LiteRT Title Generation
.md
Obsidian Vault Dual-Write
19:42
5G 100%
Oorty
Oorty Mobile LOCAL_GGUF • Quick Mode
420MB / Safe

How do I implement a state-hoisted Compose counter with Flow?

17:02
Qwen 2.5 (0.5B-Instruct) 28.4 tok/s • 0.72s TTFT
Counter.kt
@Composable
fun CounterScreen(viewModel: CounterViewModel) {
    val count by viewModel.counter.collectAsStateWithLifecycle()
    Button(onClick = { viewModel.increment() }) {
        Text("Count: $count")
    }
}

Derive the time complexity of A* pathfinding on a grid.

17:04
DeepSeek-R1 (1.5B Distill) Thinking: 1.84s
Thought Process (148 tokens)
> Branching factor $b$, maximum depth $d$.
> If heuristic $h(n)$ is consistent: $O(b^d)$.
> PriorityQueue heap extraction cost: $O(\log V)$.

The time complexity of $A^*$ in worst-case heuristic scenarios is $O(b^d)$ where $b$ is the branching factor and $d$ is the shortest path depth.

Documents/Oorty/chats/2026-08-compose.md #obsidian
---
id: 8f4e2a1c
title: Compose State Hoisting
model: Qwen2.5-0.5B-Q4_K_M
date: 2026-08-31T17:02:14
tokens: 284
tags: [compose, android, kotlin]
---

### User
How do I implement state-hoisted counter?

### Assistant (Qwen 2.5)
Use `collectAsStateWithLifecycle()`...
ToolCallOrchestrator.kt
> [MCP] Server: http://localhost:8080/mcp
> [CALL] vault_search(query="compose state")
> [MATCH] Score 0.94 → compose.md#L14
> [ORCHESTRATION] Tool call resolved in 42ms
Active Cloud Providers (BYOK)
Gemini 2.5
Flash • Pro
Google AI Studio
Claude 3.7
Sonnet • Haiku
Anthropic API
Groq LPU
Llama 3.3 70B
500+ tok/s
NVIDIA NIM
DeepSeek R1
GPU Accelerated
Ask local model anything...
UNIFYING NATIVE ON-DEVICE HARDWARE & CLOUD FRONTIER MODELS
llama.cpp GGUF Engine Google LiteRT (TensorFlow Lite) Obsidian Markdown Vault Model Context Protocol (MCP) Gemini 2.5 Flash / Pro Anthropic Claude 3.7 Groq Ultra-Fast LPU NVIDIA NIM Accelerated llama.cpp GGUF Engine Google LiteRT (TensorFlow Lite) Obsidian Markdown Vault Model Context Protocol (MCP)
RAPID PRODUCTIVITY STUDIO

Interactive Prompt Lab

Single-turn precision tools implemented in PromptLabScreen.kt. Test real on-device transformations right here in your browser.

Input Text / Code
AI Output & Telemetry

Select a tool and click "Run Transformation" to view the generated output.

ON-DEVICE MODEL REPOSITORY

Built-In HuggingFace GGUF Hub

Search, inspect and stream-download quantized GGUF weights directly into Documents/Oorty/models/ with live download speed telemetry.

Ultra-Light 398 MB

Qwen 2.5 (0.5B-Instruct)

Smallest high-efficiency model. Ideal for 4GB RAM phones. Highest generation speed (35+ tok/s).

Quant: Q4_K_M Context: 2,048
Reasoning 1.6 GB

Gemma 2 (2B-IT)

Google's powerhouse compact architecture with superior knowledge synthesis and mathematical reasoning.

Quant: Q4_K_M Context: 4,096
Autonomous MCP 2.3 GB

Phi-3-Mini (3.8B-4k)

Full agentic tool calling support with high JSON parsing reliability and deep multi-turn context retention.

Quant: Q4_K_M Context: 4,096
In-App HuggingFace Download Pipeline (HuggingFaceApi.kt)
Ready
Llama-3.2-1B-Instruct-Q4_K_M.gguf 0 MB/s
HARDWARE SAFETY

Dynamic RAM Watchdog & Fit Matrix

Implemented with ActivityManager.MemoryInfo in HardwareChecker.kt. Never worry about Out-Of-Memory system crashes.

Llama 3.2 (1B-Instruct)

Quant: Q4_K_M • ~850 MB VRAM
Comfortable Fit

Optimal choice for 6GB devices. Delivers 25–35 tok/s decode speed with fast responses and low battery consumption. Leaves ample RAM for Android OS.

Estimated VRAM Usage ~850 MB / 6,144 MB (13.8%)
Expected Speed ~30 tok/s
Max Context 4,096 Tokens
Agentic Rating Limited (Fast)
Crash Risk Zero (Safe)
COMPLETE CAPABILITIES

Built Without Compromise

Designed from the ground up in native Kotlin with Jetpack Compose for uncompromising speed and privacy.

Native llama.cpp JNI Engine

Zero Python, zero Node.js daemon overhead. High-performance C++ bindings via llamacpp-kotlin executing direct ARM NEON & Vulkan instructions.

Obsidian Markdown Dual-Write

Every chat turn is automatically formatted into clean Markdown with YAML frontmatter tags and saved directly to your local documents folder.

Model Context Protocol (MCP)

Run multi-server tool loops with strict JSON schema validation, human approval prompts, and local SQLite query execution.

Zero Telemetry & 100% Offline

Your chats, memory embeddings, and API keys never leave your phone. Works seamlessly in airplane mode without internet connectivity.

Real-Time Reasoning Parser

Streaming <think> token parser dynamically hides/reveals model reasoning accordions without blocking generation flow.

Multi-Cloud Router (BYOK)

Bring your own API keys for Google Gemini 2.5, Claude 3.7, OpenAI, Groq, Mistral, and NVIDIA NIM with zero subscription fees.

ZERO LOCK-IN STORAGE

Your Chats Belong In Your Obsidian Vault

Unlike proprietary apps that trap your conversations inside locked SQLite databases, Oorty dual-writes every session as plain text Markdown.

YAML Metadata Frontmatter

Includes session ID, model name, token timestamps, and auto-generated topic tags.

Direct File System Access

Open Documents/Oorty/chats/ directly in Obsidian, Logseq, VS Code, or Git.

Bi-directional Wikilinks

Link ideas across conversations with standard [[note-title]] syntax.

---
id: a7f89b32-e1c4-4091-88f2
title: Jetpack Compose Flow Lifecycle
model: Qwen2.5-0.5B-Instruct-Q4_K_M
date: 2026-08-31T17:02:14Z
tokens_in: 42
tokens_out: 186
tok_per_sec: 28.4
tags:
  - #android
  - #jetpack-compose
  - #stateflow
---

# Jetpack Compose Flow Lifecycle

## User
How do I implement a state-hoisted Compose counter with Flow?

## Assistant (Qwen 2.5)
Here is the production implementation:

```kotlin
@Composable
fun CounterScreen(viewModel: CounterViewModel) {
    val count by viewModel.counter.collectAsStateWithLifecycle()
    Button(onClick = { viewModel.increment() }) {
        Text("Count: $count")
    }
}
```
#android #jetpack-compose #stateflow

Jetpack Compose Flow Lifecycle

User 17:02

How do I implement a state-hoisted Compose counter with Flow?


Assistant (Qwen 2.5) 17:02

Here is the production implementation:

@Composable
fun CounterScreen(viewModel: CounterViewModel) {
    val count by viewModel.counter.collectAsStateWithLifecycle()
    Button(onClick = { viewModel.increment() }) {
        Text("Count: $count")
    }
}
MODEL CONTEXT PROTOCOL

Autonomous MCP Agent Workbench

Connect local tools and remote MCP servers through standard JSON-RPC contracts. Enable tool-calling on both local GGUF and frontier cloud models.

Registered MCP Servers

Configure authorized tools and permission boundaries.

Local SQLite Tool • Active
sqlite://app_vault.db
Obsidian Vault Recall • Active
mcp://localhost:8080/vault
Agent Execution Trace Idle
// Click "Execute Sample Agent Loop" to view live tool execution...
NATIVE ARCHITECTURE

Under The Hood

Explore the exact Kotlin and JNI abstractions driving Oorty's on-device performance.

app/api/LlamaHelper.kt • Native Token Flow
// Native Coroutine Flow Stream from llama.cpp JNI
fun generateStream(prompt: String, params: InferenceParams): Flow<StreamChunk> = callbackFlow {
    val startTime = System.nanoTime()
    var tokenCount = 0
    
    llamaEngine.streamTokens(prompt) { token ->
        tokenCount++
        val elapsedSec = (System.nanoTime() - startTime) / 1_000_000_000.0
        val tokPerSec = if (elapsedSec > 0) tokenCount / elapsedSec else 0.0
        trySend(StreamChunk(text = token, tokPerSec = tokPerSec))
    }
    awaitClose { llamaEngine.cancel() }
}.flowOn(Dispatchers.Default)
app/api/LiteRtTitleGen.kt • Sub-10ms TF-IDF Title Generator
// Sub-10ms Title Extraction without loading LLM
fun extractTopicTitle(firstMessage: String): String {
    val clean = firstMessage.replace(PUNCTUATION_REGEX, "")
    val keywords = clean.split(" ")
        .filter { it.length > 3 && !STOP_WORDS.contains(it.lowercase()) }
        .take(4)
        .joinToString(" ") { it.replaceFirstChar { c -> c.uppercase() } }
    return keywords.ifEmpty { "New Conversation" }
}
app/api/StreamingThoughtParser.kt • Dynamic <think> Parser
// Real-time parse of DeepSeek <think> reasoning tags
class StreamingThoughtParser {
    fun parseChunk(chunk: String): ParsedThoughtState {
        val thinkStart = chunk.indexOf("<think>")
        val thinkEnd = chunk.indexOf("</think>")
        
        return when {
            thinkStart != -1 && thinkEnd != -1 ->
                ParsedThoughtState.Complete(thought = chunk.substring(thinkStart + 7, thinkEnd))
            thinkStart != -1 ->
                ParsedThoughtState.Thinking(partial = chunk.substring(thinkStart + 7))
            else -> ParsedThoughtState.Output(response = chunk)
        }
    }
}
app/StorageHelper.kt • Obsidian Markdown Dual-Write
// Dual-write Markdown with YAML Frontmatter
suspend fun writeChatToObsidian(session: ChatSession, messages: List<ChatMessage>) = withContext(Dispatchers.IO) {
    val frontmatter = buildFrontmatter(session)
    val body = messages.joinToString("

") { "### ${it.sender}
${it.content}" }
    val file = File(vaultDir, "${session.id}.md")
    file.writeText("$frontmatter

$body")
}
FREQUENTLY ASKED QUESTIONS

Everything You Need To Know

Clear answers to your technical and architectural questions.

What is Oorty and why is it unique?
Oorty is a native Android application engineered in Kotlin with Jetpack Compose. It allows you to run local open-source GGUF AI models directly on your phone's processor using llamacpp-kotlin, with zero internet requirement, while automatically syncing every turn as an open Markdown document into an Obsidian vault.
Which GGUF models are supported on my phone?
Any GGUF quantization format (Q4_K_M, Q5_K_M, Q8_0) is supported. For phones with 4GB RAM, we recommend Qwen 2.5 (0.5B); for 6GB–8GB RAM, Llama 3.2 (1B) or Gemma 2 (2B); and for 12GB+ devices, Phi-3 Mini (3.8B) or Llama 3.1 (8B).
How does the Obsidian vault dual-write work?
Whenever you chat, Oorty persists the session to SQLite for instantaneous UI queries and simultaneously writes an open .md file with structured YAML frontmatter (session ID, model name, tokens/sec, and timestamp) directly into Documents/Oorty/chats/.
Can I use cloud frontier models as well?
Yes. Oorty features a built-in Multi-Cloud Router allowing you to bring your own API keys (BYOK) for Google Gemini 2.5, Anthropic Claude 3.7, OpenAI, Groq, Mistral, and NVIDIA NIM. Your keys are encrypted locally on-device.
Does Oorty require root access or Termux?
No. Oorty is a self-contained, native APK package that ships with pre-compiled ARM64 JNI binaries for llama.cpp. Simply install the APK on Android 8.0+ and start running models immediately.
EXPERIENCE FREEDOM

Take Full Ownership of Your AI Today

Download the native Android APK or inspect the complete open-source codebase on GitHub.