Why On-Device AI Matters Now More Than Ever
Cloud-based AI APIs are convenient, but they come with inherent limitations: latency, connectivity costs, and privacy concerns. Edge AI — running inference directly on the device — addresses all of these challenges at their root.
In 2026, both Apple's Core ML and Google's TensorFlow Lite have matured into robust mobile inference engines. Combined with Antigravity's AI agent capabilities, you can streamline the entire workflow from model conversion and quantization to app integration and testing.
The Edge AI Development Pipeline
On-device AI development follows four main phases:
1. Model Preparation and Conversion
Start with a pre-trained model and convert it to a mobile-friendly format. This means taking PyTorch or TensorFlow models and converting them to Core ML (.mlmodel / .mlpackage) or TensorFlow Lite (.tflite) format.
2. Quantization and Optimization
Reduce model size to fit mobile resource constraints. INT8 quantization can shrink models by up to 75% while maintaining over 95% accuracy in most cases — a remarkably practical trade-off.
3. App Integration
Embed the converted model into your iOS or Android app. This includes implementing inference code, handling input/output format conversion, and connecting to the UI.
4. Testing and Benchmarking
Measure real-device latency, memory usage, and battery consumption to ensure production quality.
Antigravity's agents can assist with code generation, review, and test automation across all four phases.
Implementing Core ML for iOS On-Device Inference
Generating the Model Conversion Script with Antigravity
Ask Antigravity's agent to generate a script that converts a PyTorch model to Core ML format:
# convert_to_coreml.py
# Convert a PyTorch image classification model to Core ML format
import torch
import coremltools as ct
from torchvision.models import mobilenet_v3_small, MobileNet_V3_Small_Weights
# Load the pre-trained model
weights = MobileNet_V3_Small_Weights.DEFAULT
model = mobilenet_v3_small(weights=weights)
model.eval()
# Create a dummy input for tracing
dummy_input = torch.randn(1, 3, 224, 224)
traced_model = torch.jit.trace(model, dummy_input)
# Convert to Core ML with quantization options
mlmodel = ct.convert(
traced_model,
inputs=[ct.ImageType(name="image", shape=(1, 3, 224, 224))],
convert_to="mlprogram", # ML Program format (iOS 15+)
compute_precision=ct.precision.FLOAT16, # FP16 quantization halves the size
)
# Expected output:
# A .mlpackage file with metadata is generated
mlmodel.save("ImageClassifier.mlpackage")
print("✅ Core ML model conversion complete")
print(f" Model size: ~{mlmodel.__sizeof__() / 1024 / 1024:.1f} MB")By specifying compute_precision=ct.precision.FLOAT16, we reduce model size by approximately 50% while preserving accuracy.
Real-Time Inference in Swift
Integrate the converted model into your iOS app. You can use Antigravity's inline chat (⌘+I) to efficiently generate the Swift implementation:
// ImageClassifierService.swift
// Service for real-time image classification using Core ML
import CoreML
import Vision
class ImageClassifierService {
private let model: VNCoreMLModel
init() throws {
// Load the Core ML model
let config = MLModelConfiguration()
config.computeUnits = .all // Automatically selects Neural Engine + GPU + CPU
let mlModel = try ImageClassifier(configuration: config).model
self.model = try VNCoreMLModel(for: mlModel)
}
func classify(image: CGImage) async throws -> [(label: String, confidence: Float)] {
return try await withCheckedThrowingContinuation { continuation in
let request = VNCoreMLRequest(model: model) { request, error in
if let error = error {
continuation.resume(throwing: error)
return
}
guard let results = request.results as? [VNClassificationObservation] else {
continuation.resume(returning: [])
return
}
// Return the top 5 classification results
let topResults = results.prefix(5).map {
(label: $0.identifier, confidence: $0.confidence)
}
continuation.resume(returning: topResults)
}
// Prefer Neural Engine over CPU
request.usesCPUOnly = false
let handler = VNImageRequestHandler(cgImage: image)
try? handler.perform([request])
}
}
}
// Expected output:
// [("golden_retriever", 0.92), ("labrador", 0.05), ("dog", 0.02), ...]Setting computeUnits = .all allows the system to automatically leverage the Apple Neural Engine (ANE) on supported devices, dramatically improving inference speed.
Cross-Platform Support with TensorFlow Lite
INT8 Quantization for Model Compression
TensorFlow Lite supports post-training quantization (PTQ) that drastically reduces model size. Have Antigravity's agent generate the conversion script:
# quantize_tflite.py
# Convert a TensorFlow model to INT8 quantized TFLite format
import tensorflow as tf
import numpy as np
# Representative dataset generator for quantization calibration
def representative_dataset():
"""Provide representative data to maintain quantization accuracy"""
for _ in range(100):
# Use input data similar to actual use cases
data = np.random.rand(1, 224, 224, 3).astype(np.float32)
yield [data]
# Convert SavedModel to TFLite
converter = tf.lite.TFLiteConverter.from_saved_model("saved_model/")
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8
tflite_model = converter.convert()
# Save the quantized model
with open("model_quantized.tflite", "wb") as f:
f.write(tflite_model)
# Expected output:
# File size reduced to approximately 25% of the original
# Example: 16MB → 4MB (after INT8 quantization)
original_size = 16.0 # MB (example)
quantized_size = len(tflite_model) / 1024 / 1024
print(f"✅ Quantization complete")
print(f" Original size: {original_size:.1f} MB")
print(f" Quantized: {quantized_size:.1f} MB")
print(f" Reduction: {(1 - quantized_size / original_size) * 100:.0f}%")INT8 quantization can reduce model size by approximately 75% while maintaining over 95% inference accuracy — a significant win for mobile deployment.
Android Inference with Kotlin
Use Antigravity's Agent mode to generate Android inference code in one shot:
// EdgeAIClassifier.kt
// Image classification for Android using TensorFlow Lite
import android.content.Context
import android.graphics.Bitmap
import org.tensorflow.lite.Interpreter
import org.tensorflow.lite.gpu.GpuDelegate
import java.io.FileInputStream
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.MappedByteBuffer
import java.nio.channels.FileChannel
class EdgeAIClassifier(private val context: Context) {
private var interpreter: Interpreter? = null
private var gpuDelegate: GpuDelegate? = null
fun initialize() {
// Enable GPU delegate for hardware acceleration
gpuDelegate = GpuDelegate()
val options = Interpreter.Options().apply {
addDelegate(gpuDelegate!!)
setNumThreads(4) // Fallback when GPU is unavailable
}
val modelBuffer = loadModelFile("model_quantized.tflite")
interpreter = Interpreter(modelBuffer, options)
}
fun classify(bitmap: Bitmap): List<Pair<String, Float>> {
val inputBuffer = preprocessImage(bitmap)
val outputBuffer = Array(1) { FloatArray(1000) }
interpreter?.run(inputBuffer, outputBuffer)
// Return top 5 results as label-score pairs
return outputBuffer[0]
.mapIndexed { index, score -> Pair(labels[index], score) }
.sortedByDescending { it.second }
.take(5)
}
// Expected output:
// [("golden_retriever", 0.91), ("labrador", 0.04), ...]
private fun preprocessImage(bitmap: Bitmap): ByteBuffer {
val buffer = ByteBuffer.allocateDirect(1 * 224 * 224 * 3)
buffer.order(ByteOrder.nativeOrder())
val resized = Bitmap.createScaledBitmap(bitmap, 224, 224, true)
val pixels = IntArray(224 * 224)
resized.getPixels(pixels, 0, 224, 0, 0, 224, 224)
for (pixel in pixels) {
buffer.put(((pixel shr 16) and 0xFF).toByte()) // R
buffer.put(((pixel shr 8) and 0xFF).toByte()) // G
buffer.put((pixel and 0xFF).toByte()) // B
}
return buffer
}
private fun loadModelFile(filename: String): MappedByteBuffer {
val fd = context.assets.openFd(filename)
val input = FileInputStream(fd.fileDescriptor)
val channel = input.channel
return channel.map(FileChannel.MapMode.READ_ONLY, fd.startOffset, fd.declaredLength)
}
fun release() {
interpreter?.close()
gpuDelegate?.close()
}
companion object {
private val labels = listOf(/* ImageNet labels — 1000 entries */)
}
}The GpuDelegate enables hardware acceleration on supported devices, delivering 2–5x speed improvements over CPU-only execution.
Leveraging Antigravity Agents in Your Workflow
Step 1: Project Setup
Launch Antigravity and create a new project. Writing an AGENTS.md file with mobile AI development context improves agent accuracy:
<!-- AGENTS.md -->
# Edge AI Mobile App Project
## Context
- iOS: Swift + Core ML (targeting iOS 17+)
- Android: Kotlin + TensorFlow Lite (targeting API 26+)
- Model: MobileNetV3-based image classification
## Coding Standards
- Never skip error handling
- Always implement model release/cleanup to prevent memory leaks
- Include performance measurement logging in inference codeStep 2: Agent-Driven Code Generation
In Antigravity's Agent mode, simply ask "Create a Core ML inference service class" and the implementation shown above will be generated automatically. Follow up with "Create a TensorFlow Lite version with the same interface" for cross-platform coverage.
Step 3: Testing and Benchmarking
Ask Antigravity's agent to "generate unit tests and performance benchmarks for inference," and it will produce test code automatically:
// ImageClassifierTests.swift
// Benchmark tests for inference accuracy and latency
import XCTest
@testable import MyApp
class ImageClassifierTests: XCTestCase {
var classifier: ImageClassifierService!
override func setUpWithError() throws {
classifier = try ImageClassifierService()
}
func testClassificationAccuracy() async throws {
let testImage = loadTestImage("golden_retriever.jpg")
let results = try await classifier.classify(image: testImage)
XCTAssertFalse(results.isEmpty, "Classification results are empty")
XCTAssertEqual(results[0].label, "golden_retriever")
XCTAssertGreaterThan(results[0].confidence, 0.8)
}
func testInferenceLatency() async throws {
let testImage = loadTestImage("sample.jpg")
// Measure average latency over 10 runs
let start = CFAbsoluteTimeGetCurrent()
for _ in 0..<10 {
_ = try await classifier.classify(image: testImage)
}
let elapsed = (CFAbsoluteTimeGetCurrent() - start) / 10
// Expect under 20ms when using Neural Engine
print("Average inference time: \(elapsed * 1000)ms")
XCTAssertLessThan(elapsed, 0.1, "Inference time exceeds 100ms")
}
// Expected output:
// Average inference time: 12.3ms (iPhone 15 Pro, Neural Engine)
}Looking back
Edge AI is quickly becoming the standard for mobile app development. On-device inference with Core ML and TensorFlow Lite delivers three major benefits: reduced latency, enhanced privacy, and offline capability.
By leveraging Antigravity's AI agents, you can streamline model conversion scripts, inference code, and test generation — significantly reducing development time. Start by converting an existing model to Core ML or TFLite format and building a small prototype to see the results firsthand.
For more hands-on mobile development techniques, check out the Antigravity × Flutter Mobile Development Complete Guide and Antigravity × Xcode 26 / iOS 26 Development Guide.
If you'd like to dive deeper into the topics covered in this article,