DEV Community

shashank ms
shashank ms

Posted on

Best Practices for Integrating LLM with Mobile Applications

Building LLM features into iOS and Android applications means designing for unreliable networks, strict memory limits, and unpredictable user input lengths. Unlike server-side workloads, mobile clients need streaming responses, aggressive caching, and pricing models that stay predictable when a user pastes a wall of text. Oxlo.ai fits this stack naturally. Its OpenAI-compatible API, request-based pricing, and broad model catalog let you ship chat, vision, and audio features without re-architecting your networking layer.

Choose an Architecture Pattern Before You Ship

Most mobile teams pick one of three integration patterns. The first is direct client-to-provider calls. Oxlo.ai makes this easy during prototyping because the API is fully OpenAI SDK compatible. You can point the official Swift or Kotlin OpenAI client to https://api.oxlo.ai/v1 and start sending requests. The second pattern, and the one we recommend for production, is a lightweight backend proxy. Your mobile app sends messages to your own endpoint, your server forwards them to Oxlo.ai, and you retain control over retries, caching, and rate limits. The third pattern is a hybrid approach: run small models on-device for offline autocomplete or classification, then fall back to Oxlo.ai for heavy reasoning tasks such as DeepSeek R1 671B MoE or GLM 5 long-horizon agentic workflows.

Stream Tokens to Keep the UI Responsive

Mobile users lock their phones, switch apps, and ride through dead zones. Blocking the UI while you wait for a full JSON payload is not an option. Oxlo.ai supports server-sent events (SSE) on the chat/completions endpoint, so you should stream every token to the client and render it incrementally. On iOS, use URLSession.bytes(for:) to read the SSE stream line by line. On Android, libraries like OkHttp Eventsource handle the same behavior. Always make the request cancellable. If the user dismisses the chat sheet, terminate the stream immediately to save battery and avoid wasting requests.

Manage State and Long Context Efficiently

Conversations on mobile can stretch across dozens of turns. Sending the full message history with every request increases payload size, drains battery, and balloons costs on token-based platforms. Oxlo.ai uses flat per-request pricing, so a long context window costs the same as a short one. That makes multi-turn agents, full-document summarization, and chain-of-thought reasoning with Kimi K2.5 or DeepSeek R1 practical in a mobile app. Still, you should trim stale context on the client or backend. A simple strategy is to keep the last ten turns and compress anything older into a running summary generated by an efficient model such as DeepSeek V3.2.

Add Vision and Audio Without Extra SDKs

Modern mobile apps rarely limit users to text. Oxlo.ai exposes vision and audio models through the same OpenAI-compatible endpoints, so you do not need separate vendor SDKs for each modality. Send a base64-encoded image to /v1/chat/completions using Kimi K2.6 or Gemma 3 27B for visual question answering. Transcribe voice memos with Whisper Large v3 by posting audio to /v1/audio/transcriptions. Generate voice feedback with Kokoro 82M via /v1/audio/speech. Because the authentication scheme and response format are identical across modalities, your mobile networking layer stays small and maintainable.

Control Costs with Predictable Request Pricing

Mobile input is inherently volatile. A user might type a ten-character greeting or paste a thousand-line crash log. On token-based providers, that variance makes budgeting nearly impossible. Oxlo.ai charges one flat rate per API request regardless of prompt length, which means your cost per user action stays constant even when context grows. For long-context workloads, request-based pricing can be 10-100x cheaper than token-based alternatives because cost does not scale with input length. For pre-launch testing, the Free tier offers 60 requests per day across more than 16 models, including access to a 7-day full-access trial. When you move to production, Pro and Premium tiers provide fixed daily quotas starting at 1,000 and 5,000 requests respectively. See https://oxlo.ai/pricing for current plan details.

Never Ship API Keys in the Client Binary

An API key embedded in an APK or IPA can be extracted in minutes. If you are using Oxlo.ai in production, route all traffic through your backend. Store the Oxlo.ai key in an environment variable and issue short-lived session tokens to your mobile clients. If you need to call Oxlo.ai directly from the device during early prototyping, rotate keys after every build and restrict them to the smallest possible model whitelist. Never commit keys to Git, and never hardcode them in Swift or Kotlin source files.

Build Offline Resilience and Request Deduplication

Subway tunnels and airplane mode are part of the mobile environment. Queue failed requests in a local SQLite or Core Data store and retry them when connectivity returns. Attach an idempotency key to each Oxlo.ai request so that retries do not generate duplicate charges or side effects. If your app supports local on-device inference, use it to show a cached or simplified response while the queued Oxlo.ai request resolves in the background. This hybrid approach keeps the app usable even when the network is not.

Integration Example: Proxy and Swift SSE Client

The following pattern is what we recommend for most production mobile apps. A Node.js proxy forwards chat requests to Oxlo.ai, keeping your API key secret. The iOS client consumes the SSE stream and updates the UI as tokens arrive.

Backend proxy:

import OpenAI from 'openai';
import express from 'express';

const app = express();
app.use(express.json());

const openai = new OpenAI({
  apiKey: process.env.OXLO_API_KEY,
  baseURL: 'https://api.oxlo.ai/v1',
});

app.post('/chat', async (req, res) => {
  const stream = await openai.chat.completions.create({
    model: 'llama-3.3-70b',
    messages: req.body.messages,
    stream: true,
  });

  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  for await (const chunk of stream) {
    res.write(`data: ${JSON.stringify(chunk)}\n\n`);
  }
  res.end();
});

app.listen(3000);

Swift client:

struct ChatMessage: Codable {
    let role: String
    let content: String
}

func streamChat(messages: [ChatMessage]) async throws {
    let url = URL(string: "https://your-api.example.com/chat")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpBody = try JSONEncoder().encode(["messages": messages])

    let (bytes, response) = try await URLSession.shared.bytes(for: request)
    guard let httpResponse = response as? HTTPURLResponse,
          httpResponse.statusCode == 200 else {
        throw URLError(.badServerResponse)
    }

    for try await line in bytes.lines {
        if line.hasPrefix("data: ") {
            let payload = String(line.dropFirst(6))
            // Deserialize and append to your UI model
            print(payload)
        }
    }
}

This setup gives you the full Oxlo.ai catalog, including models like Qwen 3 32B for multilingual users or DeepSeek V4 Flash for 1M context tasks, while keeping mobile code minimal and secure.

Top comments (0)