Skip to main content

3 posts tagged with "AI"

View All Tags

Local MCPs and Solo Burnout: How AI is Reshaping iOS Development

Published: · 10 min read
Don Peter
Cofounder and CTO, Appxiom

Shipping a native iOS app in 2026 demands unprecedented cognitive bandwidth. Solo developers and small mobile teams are not just writing SwiftUI views—they are wrestling with Swift 6 Language Mode and complete concurrency checking (SWIFT_VERSION = 6.0 / SWIFT_STRICT_CONCURRENCY = complete), isolating SwiftData containers across actors, tuning App Intents, and debugging main-thread hitches.

While AI coding assistants promised relief, early chat-based tools introduced Reviewer Fatigue: an exhausting loop of copy-pasting code, fighting 30+ compiler errors, and babysitting hallucinated APIs.

Enter the Model Context Protocol (MCP).

By running a Local MCP server directly on macOS, solo iOS developers are transforming AI assistants from detached chatbots into tool-equipped pair programmers. Local MCP connects the AI agent directly to Xcode diagnostics, xcrun simctl, and local SwiftData databases, verifying concurrency safety before code ever touches your branch.

Why Chat-Based AI Exhausts Solo iOS Developers​

Generic LLMs struggle with native Apple development due to three architectural barriers:

  1. The Swift 6 Concurrency Wall: Models trained on legacy Swift 5 produce mutable shared state, non-Sendable closures, and unmanaged background tasks that fail compile-time data-race checks.
  2. The Apple Sandbox Blindspot: Native iOS runs within isolated sandbox containers. Browser chatbots cannot access ~/Library/Developer/CoreSimulator/, inspect local SQLite files, or read system crash logs.
  3. The Manual Verification Tax: Without direct tool execution, the developer bears the full burden of copying code, building in Xcode, running the simulator, and manually testing user flows.

What is a Local MCP Server for iOS?​

The Model Context Protocol (MCP) is an open JSON-RPC standard that enables AI models to safely execute tools and query resources on your local development machine.

Instead of manual copy-pasting, your AI coding agent connects directly to a lightweight Local iOS MCP Server running on your Mac:

When the AI writes or edits Swift code, it triggers xcode_diagnostics via MCP. If the Swift 6 compiler detects a data race, the agent reads the compiler diagnostic directly from the tool response, adds @Sendable or actor confinement, recompiles, boots simctl, and verifies the container state automatically.

Prerequisites & Environment Baseline​

  • Xcode: 16.0+ with Swift 6 Language Mode (SWIFT_VERSION = 6.0 or SWIFT_STRICT_CONCURRENCY = complete in Swift 5 mode)
  • Host OS: macOS 15.0+ (Sequoia) with Xcode Command Line Tools installed
  • Target OS: iOS 18.0+ (for modern SwiftData actor isolation and Sendable model context identifiers)
  • Local Toolchain: /usr/bin/xcrun simctl, /usr/bin/xcodebuild, Node.js v20+ (LTS)

The Production Feature: Swift 6 Concurrency & SwiftData​

To demonstrate how strict architecture eliminates AI concurrency bugs, let us examine an Offline-First Transaction Vault built with Swift 6 strict concurrency, SwiftData actor isolation, and SwiftUI.

1. Sendable Value Model & Actor-Isolated Store​

In Swift 6, data crossing concurrency domains must conform to Sendable. Background persistence is encapsulated in an independent actor to avoid sharing ModelContext across threads:

import Foundation
import SwiftData

// Immutable DTO for data-race-free transfer
public struct TransactionItem: Identifiable, Sendable, Hashable, Codable {
public let id: UUID
public let title: String
public let amount: Decimal
public let timestamp: Date
}

@Model
public final class TransactionEntity {
@Attribute(.unique) public var id: UUID
public var title: String
public var amount: Decimal
public var timestamp: Date

public init(from item: TransactionItem) {
self.id = item.id
self.title = item.title
self.amount = item.amount
self.timestamp = item.timestamp
}

public func toDomain() -> TransactionItem {
TransactionItem(id: id, title: title, amount: amount, timestamp: timestamp)
}
}

/// Actor encapsulating SwiftData writes away from the MainActor
public actor TransactionStorageActor {
private let modelContext: ModelContext

public init(modelContainer: ModelContainer) {
self.modelContext = ModelContext(modelContainer)
self.modelContext.autosaveEnabled = false
}

public func save(_ items: [TransactionItem]) throws {
for item in items { modelContext.insert(TransactionEntity(from: item)) }
try modelContext.save()
}

public func fetchRecent() throws -> [TransactionItem] {
var descriptor = FetchDescriptor<TransactionEntity>(
sortBy: [SortDescriptor(\.timestamp, order: .reverse)]
)
descriptor.fetchLimit = 50
return try modelContext.fetch(descriptor).map { $0.toDomain() }
}
}

2. Presentation Layer (@MainActor & Lifecycle Cancellation)​

We expose state using @Observable bound to @MainActor, using SwiftUI's native .task modifier for automatic cooperative task cancellation:

import SwiftUI
import Observation

@Observable
@MainActor
public final class TransactionViewModel {
public private(set) var transactions: [TransactionItem] = []
public private(set) var isLoading = false
private let storage: TransactionStorageActor

public init(storage: TransactionStorageActor) { self.storage = storage }

public func load() async {
isLoading = true
defer { isLoading = false }
transactions = (try? await storage.fetchRecent()) ?? []
}
}

public struct TransactionListView: View {
@State private var viewModel: TransactionViewModel

public init(viewModel: TransactionViewModel) {
_viewModel = State(initialValue: viewModel)
}

public var body: some View {
NavigationStack {
List(viewModel.transactions) { item in
HStack {
Text(item.title).font(.headline)
Spacer()
Text(item.amount, format: .currency(code: "USD"))
}
}
.overlay { if viewModel.isLoading { ProgressView() } }
.navigationTitle("Vault")
.refreshable { await viewModel.load() }
.task { await viewModel.load() }
}
}
}

Implementing the Local iOS MCP Server​

Below is an implementation of a Local iOS MCP Server in Node.js using execFile with an argument array to prevent command injection. It registers stdio tools to run xcodebuild diagnostics and inspect sandboxed simulator data:

#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import { execFile } from "node:child_process";
import { promisify } from "node:util";

const execFileAsync = promisify(execFile);
const server = new Server({ name: "ios-mcp", version: "1.0.0" }, { capabilities: { tools: {} } });

server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "xcode_diagnostics",
description: "Compiles project and returns parsed Swift 6 errors.",
inputSchema: {
type: "object",
properties: { workspace: { type: "string" }, scheme: { type: "string" } },
required: ["workspace", "scheme"]
}
},
{
name: "simctl_sandbox",
description: "Returns path to app sandbox on booted simulator.",
inputSchema: { type: "object", properties: { bundleId: { type: "string" } }, required: ["bundleId"] }
}
]
}));

server.setRequestHandler(CallToolRequestSchema, async ({ params }) => {
const { name, arguments: args } = params;
try {
if (name === "xcode_diagnostics") {
const buildArgs = [
"build",
"-workspace", String(args.workspace),
"-scheme", String(args.scheme),
"-destination", "generic/platform=iOS Simulator",
"SWIFT_TREAT_WARNINGS_AS_ERRORS=YES"
];
try {
await execFileAsync("xcodebuild", buildArgs, { maxBuffer: 10 * 1024 * 1024 });
return { content: [{ type: "text", text: "✅ Build clean: 0 Swift 6 errors." }] };
} catch (err) {
const errors = (err.stdout || err.message).split("\n").filter(l => l.includes("error:")).slice(0, 10).join("\n");
return { content: [{ type: "text", text: `❌ Swift 6 Errors:\n${errors}` }] };
}
}
if (name === "simctl_sandbox") {
const simArgs = ["simctl", "get_app_container", "booted", String(args.bundleId), "data"];
const { stdout } = await execFileAsync("xcrun", simArgs);
return { content: [{ type: "text", text: `Container: ${stdout.trim()}` }] };
}
throw new Error(`Unknown tool: ${name}`);
} catch (e) {
return { isError: true, content: [{ type: "text", text: e.message }] };
}
});

await server.connect(new StdioServerTransport());

The Autonomous Self-Correction Loop​

With this MCP server active in your IDE:

  1. You define requirements: "Add soft-delete support and refresh the view."
  2. The agent edits code and triggers xcode_diagnostics via MCP.
  3. If compiler errors occur, the agent parses the diagnostic and corrects isolation boundaries automatically.
  4. The agent validates storage via simctl_sandbox.
  5. You review only verified, compilable pull requests.

The solo developer transitions from syntax debugging to architectural oversight.

Actionable Troubleshooting: 4 Swift 6 & AI Pitfalls​

When reviewing AI-generated iOS code, watch for these four concurrency traps:

Concurrency TrapRoot CauseCompiler / Runtime SymptomSenior Architect Fix
Non-Sendable ClosuresAI passes non-sendable escaping closure across task boundaries.Capture of non-sendable type '...' in an escaping '@Sendable' closure risks causing data races.Mark closure @Sendable, ensure captured state conforms to Sendable, or migrate to async/await.
Cross-Actor SwiftData FaultsPassing @Model entity directly to SwiftUI view.Runtime crash: EXC_BAD_ACCESS / context thread violation.Map entities to immutable Sendable structs inside the actor.
Zombie Tasks in NavigationAI triggers unmanaged Task { ... } in .onAppear.Network loops continue running after view dismisses.Replace with SwiftUI's native .task { ... } modifier.
Main-Thread App HangsSynchronous JSON decoding or heavy sorting on @MainActor.Main thread blocked for 2+ seconds; dropped touch events, severe UI hitching, and MetricKit App Hang warnings (iOS Watchdog terminations primarily target unresponsive app launches or background tasks exceeding 15–20+ seconds)Offload transformations to background actors or cooperative background tasks.

Beyond the Simulator: Production Reality & Appxiom​

A Local MCP server guarantees that your project compiles and runs cleanly on a local simulator.

However, the iOS Simulator is not production.

Simulators run on Apple Silicon with unlimited power and host Wi-Fi. Production devices encounter thermal throttling, memory pressure (Jetsam), cellular handoffs, and silent main-thread stalls.

When an unoptimized view body freezes the main thread for 3 seconds during checkout, traditional crash SDKs report a misleading "100% crash-free rate." Yet the user abandons the purchase, and revenue is lost.

Solo developers pair local MCP automation with Appxiom to close this observability gap:

  • Detection of Bugs That Never Crash: Automatically detects iOS App Hangs, hitch rates, and main run-loop freezes before users leave negative App Store ratings.
  • Goal Friction Impact (GFI): Evaluates failed goal attempts and drop-offs to quantify estimated revenue at risk from technical friction in conversion funnels.
  • The Appxiom Quality Score (QS): Provides an objective 0 to 10 release health index, giving solo engineers a clear, data-driven benchmark when promoting TestFlight builds to production.

Solo Developer Playbook: Burnout vs. Sustainable Engineering​

DimensionThe Burnout Model (Chat Copilots)The Sustainable Model (Local MCP + Appxiom)
WorkflowCopy-pasting code snippets between browser and Xcode.AI agent writes directly to repository with local tool access.
Swift 6 ConcurrencyManually triaging dozens of compiler warnings.Agent queries xcodebuild via MCP and auto-corrects code.
Testing & SandboxManually tapping simulator, guessing SQLite state.Agent uses simctl tool calls to inspect sandboxed storage.
Reviewer BurdenExhausted syntax checker fixing trivial errors.High-level system architect approving verified pull requests.
Production HealthGuessing stability from crash-free rates while revenue drops.Real-time Appxiom Quality Score and non-fatal App Hang telemetry.

Conclusion: Architect More, Babysit Less​

The objective of AI in native iOS development is not to generate more code faster—it is to eliminate repetitive engineering friction so you can focus on product excellence.

By combining Swift 6 strict concurrency with a Local iOS MCP Server, you eliminate the compile-and-debug treadmill that causes solo developer burnout. And by backing your releases with Appxiom telemetry, you ensure that your production app delivers flawless user experiences that protect your bottom line.

Build your local MCP tools, demand verified compilation from your agents, and take back your engineering bandwidth.

The Senior Android Architect's Role Managing AI Developers

Published: · 10 min read
Robin Alex Panicker
Cofounder and CPO, Appxiom

The day-to-day reality of a Senior Android Architect has changed more in the past 18 months than in the preceding decade.

You are no longer spending your afternoons handcrafting ViewModel boilerplate, writing repetitive Room entity mappers, or wiring navigation graphs. Instead, AI coding assistants - whether it is Gemini in Android Studio, GitHub Copilot, Cursor, or Claude Code - are acting as an army of hyper-productive, 24/7 Junior Developers embedded directly in your IDE.

They can generate hundreds of lines of code per minute. They never complain about merge conflicts. They know every syntax quirk of Kotlin 2.0 and Jetpack Compose.

And they have absolutely zero architectural conscience.

Modern LLMs behave like eager junior engineers: they memorized the documentation five minutes ago, but have never debugged a silent memory leak at 2 AM, never diagnosed an Application Not Responding (ANR) lock across fragmented OEM devices, and never had to justify a conversion drop to executive leadership.

When code generation velocity increases 10x, regression density increases with it. Your primary role is no longer just typing code. You are the Tech Lead, Code Reviewer, and Architectural Supervisor performing continuous business impact analysis on AI-generated software.

The 4 Cardinal Sins Junior AI Developers Commit in Android​

1. Swallowing CancellationException in Coroutines​

LLMs reflexively wrap asynchronous calls in catch-all try/catch blocks:

// ❌ AI-GENERATED: Silently breaks Coroutine cancellation!
viewModelScope.launch {
try {
val userProfile = repository.fetchUserProfile(userId)
_uiState.value = ProfileUiState.Success(userProfile)
} catch (e: Exception) {
// ⚠️ LANDMINE: Catches CancellationException!
_uiState.value = ProfileUiState.Error("Failed to load profile")
}
}
  • The Problem: In Kotlin Coroutines, cancellation is cooperative. When a user navigates away, the runtime injects CancellationException. Because CancellationException inherits from java.lang.Exception, the AI's catch block intercepts it, treats cancellation as a business error, and keeps the coroutine alive as a zombie job.
  • The Architect's Fix:
    // ✅ ARCHITECTURAL STANDARD: Preserve the cancellation contract
    catch (e: Exception) {
    if (e is CancellationException) throw e // Mandatory rethrow
    _uiState.value = ProfileUiState.Error(e.localizedMessage ?: "Unknown error")
    }

2. Triggering Recomposition Storms in Jetpack Compose​

AI defaults to standard collections, completely ignoring Compose compiler stability:

// ❌ AI-GENERATED: Unstable parameters ruin LazyColumn recycling
@Composable
fun ProductCatalog(
items: List<ProductItem>, // ⚠️ Unstable type!
onItemClick: (String) -> Unit
) {
LazyColumn {
items(items) { item -> // ⚠️ Missing explicit key!
ProductCard(item = item, onClick = { onItemClick(item.id) })
}
}
}
  • The Problem: Standard List<T> is an interface that can be backed by a mutable list, leading the Compose compiler to treat its contents as potentially dynamic. Although Kotlin 2.0.20+ enables Strong Skipping Mode by default to mitigate unnecessary recompositions, parameter stability still plays a critical role in runtime predictability, smart recomposition skipping, and state tree optimization during complex UI updates. Furthermore, missing explicit keys in lazy layouts forces node recreation instead of reuse during scrolling, causing frame drops.
  • The Architect's Fix: Use Kotlinx Immutable Collections and pass explicit identity keys:
    // ✅ ARCHITECTURAL STANDARD: Guaranteed stability & skippability
    import kotlinx.collections.immutable.ImmutableList

    @Composable
    fun ProductCatalog(
    items: ImmutableList<ProductItem>,
    onItemClick: (String) -> Unit,
    modifier: Modifier = Modifier
    ) {
    LazyColumn(modifier = modifier) {
    items(
    items = items,
    key = { it.id }, // Stable identity for node recycling
    contentType = { "product_card" }
    ) { item ->
    ProductCard(item = item, onClick = onItemClick)
    }
    }
    }

3. The Background Flow Lifecycle Leak​

When generating state collection, AI routinely defaults to collectAsState():

// ❌ AI-GENERATED: Leaks flow collection when app is backgrounded
@Composable
fun DashboardScreen(viewModel: DashboardViewModel) {
val state by viewModel.uiState.collectAsState()
DashboardContent(state = state)
}
  • The Problem: collectAsState() is bound strictly to the Composition, ignoring the Android Activity lifecycle. When the user backgrounds the app, the Flow continues pulling updates, reading database cursors, and wasting battery.
  • The Architect's Fix: Always enforce collectAsStateWithLifecycle():
    // ✅ ARCHITECTURAL STANDARD: Lifecycle-aware flow subscription
    import androidx.lifecycle.compose.collectAsStateWithLifecycle

    @Composable
    fun DashboardScreen(viewModel: DashboardViewModel) {
    val state by viewModel.uiState.collectAsStateWithLifecycle()
    DashboardContent(state = state)
    }

4. The Out-of-Order Concurrency Race Condition​

For search or real-time filtering, AI frequently combines debounce() with sequential collect():

// ❌ AI-GENERATED: Sequential execution blocks flow & wastes network calls
searchQuery
.debounce(300L)
.collect { query ->
val results = api.search(query) // Stale query can overwrite newer fast query!
_searchResults.value = results
}
  • The Problem: Because collect{} processes items sequentially, each network call blocks the flow collector until it completes. If a user rapidly types "pix" and then "pixel", the initial request for "pix" continues executing in full rather than being cancelled. This creates unneeded network overhead, delays the response time for the latest query ("pixel"), and wastes system resources on outdated requests.
  • The Architect's Fix: Use flatMapLatest to automatically cancel in-flight stale requests:
    // ✅ ARCHITECTURAL STANDARD: Auto-cancelling reactive pipeline
    val searchResults: StateFlow<SearchUiState> = searchQuery
    .debounce(300L)
    .distinctUntilChanged()
    .flatMapLatest { query ->
    if (query.isBlank()) flowOf(SearchUiState.Idle)
    else repository.search(query)
    }
    .stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(5_000L),
    initialValue = SearchUiState.Idle
    )

The Senior Architect's Governance Playbook​

As an architect, your value is measured by the quality of the boundaries and guardrails you enforce.

1. Prompt Like an Architect, Not a Programmer​

Don't ask AI: "Write a repository for fetching transactions."

Specify architectural invariants up front:

"Implement TransactionRepository using Room and Retrofit. Enforce offline-first Single Source of Truth where Room emits the reactive Flow. Confine all disk/network IO to Dispatchers.IO. Ensure all Coroutine exceptions rethrow CancellationException. Use @Upsert for atomic SQLite caching."

2. Automate Architecture Guardrails in CI​

Catch AI bugs deterministically before code review:

  • Compose Compiler Metrics: Enable compiler stability flags (-Pplugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=...) to generate stability reports, then pair them with custom CI scripts or strict check tasks to track non-skippable composables across PRs.
  • Konsist / ArchUnit: Enforce architectural boundaries with unit tests:
@Test
fun `viewmodels should never expose mutable stateflow` () {
Konsist.scopeFromProject()
.classes()
.withNameEndingWith("ViewModel")
.properties()
.withoutModifier(KoModifier.PRIVATE)
.assertFalse { it.hasType("kotlinx.coroutines.flow.MutableStateFlow") }
}
  • Custom Lint Checks: Ban collectAsState() in favor of collectAsStateWithLifecycle().

3. Conduct Continuous Business Impact Analysis on AI-Generated Code​

AI code passes happy-path tests in an emulator, but production environments expose subtle concurrency contention, thread starvation, and non-fatal ANRs across thousands of physical device configurations.

When AI writes code at scale, engineering backlogs quickly flood with edge cases. You cannot fix everything at once. This is where Business Impact Analysis (BIA) becomes an architect's most strategic competency.

Traditional crash reporting tools excel at tracking unhandled fatal exceptions, but they often lack direct visibility into user journey friction. When AI code freezes the UI thread on an unindexed SQLite query or swallows an error into an infinite loading spinner, standard crash logs can report a misleading 99.9% crash-free rate despite users experiencing broken workflows.

Performing automated Business Impact Analysis bridges technical health with financial realities:

  • Quantify Conversion Loss Over Bug Frequency: A background logging exception occurring 50,000 times typically has negligible commercial impact. For example, an intermittent 3,000 ms payment thread stall affecting 200 users puts thousands of dollars in potential conversion revenue at risk.
  • The Appxiom Quality Score (QS): Rather than relying solely on binary crash metrics, modern architects rely on Appxiom to provide a weighted 0 to 10 release health index. QS evaluates silent freezes, ANRs, and memory pressure warnings across staged rollouts to give a comprehensive, data-driven view of stability.
  • Goal Friction Impact (GFI): Appxiom's continuous business impact analysis automatically connects technical anomalies to specific business milestones (Complete Checkout, KYC Verification), quantifying the estimated revenue at risk from AI-generated bugs.
  • The Activity Trail: Traces the chronological sequence of user interaction events and network calls leading to a UI freeze or stall - pinpointing the exact AI-generated race condition in seconds without privacy compromises.

The Evolution of the Senior Android Architect​

DimensionThe Traditional Android LeadThe AI-Era Android Architect
Primary FocusHandcrafting Kotlin code & PR authoringArchitectural system prompts & boundary governance
Code ReviewNaming conventions, syntax, and logicAuditing concurrency, lifecycle contracts, and stability
Triage StrategyPrioritizing by crash count or developer gut feelingPrioritizing via Business Impact Analysis (BIA)
ToolingGradle scripts and IDE shortcutsKonsist rules, compiler metrics, and automated linters
Error HandlingNull safety and basic try/catch checksEnforcing cooperative cancellation & structured concurrency
Quality MetricThe 99.9% crash-free session rateAppxiom Quality Score (QS) & Goal Friction Impact

Conclusion: Lead the Machine​

AI coding assistants are not going to replace Senior Android Architects.

Instead, they make deep architectural judgment more valuable than ever. When anyone can produce hundreds of lines of code in seconds, the engineer who understands coroutine hierarchies, memory management, Compose stability contracts, and business impact analysis becomes the most critical asset in the organization.

Stop writing boilerplate. Start managing your junior AI developers like a seasoned engineering leader.

Further Reading & Resources​

Gemini Nano for Android: An Offline AI Model

Published: · Last updated: · 3 min read
Don Peter
Cofounder and CTO, Appxiom

What is Gemini Nano​

Gemini Nano is an efficient AI model for on device tasks according to Google. With Gemini Nano, developers will be able to deliver rich generative AI experiences without requiring a network connection or moving data off-device. Gemini Nano is ideal for use cases where low latency, low cost, and privacy safeguards are paramount.

Architecture​

To handle AI services, Android OS has introduced a new module called AICore. It is available in Android 14.

AICore, a brand new system service that simplifies using AI features in your apps. AICore takes care of everything behind the scenes, from managing AI models to ensuring their safe operation on your device. AICore lets your apps run powerful AI models like Gemini Nano directly on your device. This means faster processing compared to sending data to the cloud.

Gemini Nano and AICore Architecture - Image from Google

AICore prioritizes Privacy​

Limited Connections:  AICore operates in a restricted environment, only interacting with essential system functions. This isolation helps prevent unauthorized access to your data by other other apps.

  • Secure Downloads: AICore doesn't directly access the internet. Instead, it relies on a separate, privacy-focused app (Private Compute Services) to download any required models. This ensures your information stays secure during the download process.

Getting Started with Gemini Nano​

You will need Google AI Edge SDK for Android to work with Gemini Nano. This SDK provides APIs for interacting with the model and managing its functionalities.

Currently the SDK is available only for private review and is not available for public, but soon it will be.

Compatibility Check​

Not all Android devices support Gemini Nano. Hence you need to run a compatibility check in your code.

fun isDeviceSupported(): Boolean {
val edgeManager = AiEdgeManager.getInstance(context)
return edgeManager.isModelSupported(GeminiNano.MODEL_NAME)
}

Accessing Gemini Nano​

Once you've confirmed compatibility, you can obtain an instance of the GeminiNano class using the AIEdgeManager in AI Edge SDK:

val geminiNano = AiEdgeManager.getInstance(context).getAiModel(GeminiNano.MODEL_NAME) as GeminiNano

Example: Sentiment classification​

Gemini Nano claims it is good in performing inference on data. Let's run a piece of text and infer the sentiment score.

val text = "I'm happy to meet you again."
val i = TextInput.Builder().setText(text).build()
val o = geminiNano.runInference(i) as TextClassificationOutput
val sentimentClassification = o.classification

Pretty straight forward. The model classifies the sentiment and stores in a variable.

Gemini Nano UseCases​

Comming back to Gemini Nano, here are some of the use cases of the model that can be put to use by developer once it is out of private beta.

  • Get smarter summaries:  Gemini Nano can condense lengthy articles or reports into easy-to-understand summaries, saving you time.

  • Find answers fast:  Have questions? Ask away! Gemini Nano can analyze text and provide relevant answers.

  • Write with confidence:  Gemini Nano helps you polish your writing with features like grammar correction, proofreading, and writing suggestions. It can even generate smart replies based on the context.

  • Analyze emotions:  Understand the sentiment behind text.  Gemini Nano can detect the overall mood or feeling expressed in writing.

  • Built-in privacy:  Use powerful AI features without compromising your data.  Gemini Nano is designed with privacy in mind.

Already on Pixel:  Several Google Pixel apps, like Voice Recorder and Gboard, leverage the power of AICore to enhance your experience.