PocketPal AI Documentation

repository·main·Indexed 27 days ago

https://github.com/a-ghorbani/pocketpal-ai

A private, fully offline AI assistant for iOS and Android that runs GGUF language models and text-to-speech directly on mobile hardware. This documentation covers the installation and execution of end-to-end (E2E) tests using Appium and WebDriverIO, building specific e2e app flavors, and running the Android benchmark matrix to measure prompt processing and generation speeds across different models, quants, and backends.

Tokens
13.2K
Snippets
21
Records
95
Agent score
93%

What's inside PocketPal AI

  1. Overview of PocketPal AI Architecture

    main

    PocketPal AI operates on a four-layer stack designed for on-device inference:

    LayerComponents
    UI & Tool UseReact Native app (React Native Paper, MobX, WatermelonDB). The AgentRunner manages chat turns, token streaming, and Talents (tools) dispatching.
    BridgingNative modules connecting JS to engines: llama.rn (LLM inference via JSI), react-native-speech, and onnxruntime-react-native (TTS).
    Enginellama.cpp (for GGUF language models) and ONNX Runtime (for ONNX TTS models).
    HardwareTargets CPU (fallback), GPU (Metal on iOS, OpenCL on Android), and NPU (Qualcomm Hexagon).
  2. Create personalized assistants (Pals)

    main

    You can create custom personas called Pals to change how the AI interacts with you:

    • Assistant Pal: Allows you to pick a default model, set a custom system prompt (manually or via auto-generation), and customize the chat input color.
    • Roleplay Pal: Includes all Assistant features plus additional contextual parameters like location and specific AI roles.

    You can switch between these personas using the Pal picker on the chat page.

  3. Install and run PocketPal AI locally

    main

    To develop on PocketPal, you must satisfy the following prerequisites:

    • Node.js: Version pinned in .nvmrc (currently 22.21.0). Use nvm use to switch.
    • Yarn 1 (Classic): Pinned to yarn@1.22.22.
    • iOS: Xcode, CocoaPods, Ruby, and Bundler.
    • Android: Android Studio and Android SDK/NDK.

    Follow these steps to clone and run the project:

    git clone https://github.com/a-ghorbani/pocketpal-ai
    cd pocketpal-ai
    
    nvm use                       # match the pinned Node version
    yarn install                  # install JS dependencies
    (cd ios && pod install)       # iOS only
    
    yarn start                    # Metro bundler
    yarn ios                      # build + run on iOS simulator
    yarn android                  # build + run on Android emulator

    Note on Native Changes: If you modify package.json, a native module, ios/, android/, the Podfile, or build.gradle, you must re-run pod install and rebuild the platforms. A standard JS reload will not apply native changes.

    git clone https://github.com/a-ghorbani/pocketpal-ai
    cd pocketpal-ai
    
    nvm use                       # match the pinned Node version
    yarn install                  # install JS dependencies
    (cd ios && pod install)       # iOS only
    
    yarn start                    # Metro bundler
    yarn ios                      # build + run on iOS simulator
    yarn android                  # build + run on Android emulator
  4. Run E2E Tests on AWS Device Farm

    main

    To run tests on AWS Device Farm, ensure you have an AWS account and have configured the following environment variables or GitHub Secrets:

    • AWS_ACCESS_KEY_ID
    • AWS_SECRET_ACCESS_KEY
    • AWS_DEVICE_FARM_PROJECT_ARN

    Manual Execution:

    yarn e2e:aws --platform android --app path/to/app.apk

    GitHub Actions: Navigate to Actions $\rightarrow$ "E2E Tests (AWS Device Farm)" and select the desired platform (android, ios, or both).

  5. Install and Setup PocketPal E2E Tests

    main

    To set up the end-to-end testing environment using Appium and WebDriverIO, navigate to the e2e directory and install dependencies using yarn.

    Prerequisites:

    • Xcode configured (for iOS testing)
    • Android SDK configured (for Android testing)
    • The application must be built using the e2e flavor to include the automation bridge.
    cd e2e
    yarn install
  6. Extend PocketPal with new Talents

    main

    A Talent is a tool that the LLM can call during a conversation. To add a new capability:

    1. Implement a new TalentEngine.
    2. Register the engine in the TalentRegistry.
    3. The AgentRunner will then automatically detect calls to this tool via its schema and execute the engine.

    Existing Talents include:

    • calculate: Uses CalculateEngine for arithmetic.
    • datetime: Uses DatetimeEngine for date/time.
    • render_html: Uses RenderHtmlEngine to render HTML in chat.
  7. Run quality gates and validation

    main

    Before submitting a Pull Request, run the following quality gates to ensure code integrity:

    • yarn lint: Runs ESLint.
    • yarn typecheck: Runs tsc --noEmit for TypeScript validation.
    • yarn test: Runs Jest tests.
    • yarn l10n:validate: Validates locale JSON files for placeholder integrity.

    It is recommended to run yarn lint && yarn typecheck && yarn test as a single command. Commits must follow Conventional Commits via Husky hooks.

    yarn lint && yarn typecheck && yarn test
  8. Write E2E tests using Selectors and Page Objects

    main

    When writing E2E tests, use the Selectors helper for reliable cross-platform element selection and Page Objects to encapsulate common interactions.

    Selectors

    • byTestId(id): Selects by testID.
    • byText(text): Selects by exact text match.
    • byPartialText(text): Selects by partial text match.
    • byAccessibilityLabel(label): Selects by accessibilityLabel.

    Page Objects Use imported page objects (e.g., ChatPage, DrawerPage, ModelsPage) to perform high-level actions like opening drawers or navigating to specific screens.

    import {Selectors} from '../helpers/selectors';
    import {ChatPage, DrawerPage, ModelsPage} from '../pages';
    
    // Selectors
    await $(Selectors.byTestId('send-button')).click();
    await $(Selectors.byText('Models')).click();
    await $(Selectors.byPartialText('Download')).click();
    await $(Selectors.byAccessibilityLabel('Chat input')).click();
    
    // Page Objects
    await ChatPage.openDrawer();
    await DrawerPage.navigateToModels();
    await ModelsPage.openHuggingFaceSearch();
  9. Copy AI-Generated Text

    main

    Currently, copying text while preserving Markdown formatting is limited. You can use the following methods to copy content:

    • Paragraph-level copying: Long-press on a specific paragraph to copy its content.
    • Full response copying: Tap the copy icon at the bottom of the text bubble to copy the entire AI-generated response.
  10. Add a new automation adapter

    main

    Use an adapter when you need to instrument the regular UX flow at specific lifecycle moments (e.g., memory profiling).

    Steps to implement

    1. Create a new functional component in src/__automation__/adapters/FooAdapter.tsx. This component should render a hidden, accessibility-tree-friendly surface.
    2. Render the new adapter inside AutomationBridge.tsx within an __E2E__ gate:
    <>
      <MemoryAdapter />
      <FooAdapter />
    </>
    1. Create a test at adapters/__tests__/FooAdapter.test.tsx to verify the command protocol and testID contract.
    2. If the adapter introduces new protocol strings, register them as new markers in .github/workflows/ci.yml to ensure they are stripped from production builds.
  11. Build E2E App Flavors

    main

    You must build the specific e2e flavor of the app for tests to work. The e2e flavor (package com.pocketpalai.e2e) includes the automation bridge required by Appium. The prod flavor does not support automation and will cause tests to fail.

    Note for Android: The e2e build installs alongside the production app and does not overwrite it.

    # iOS simulator
    yarn ios:build:e2e
    
    # iOS real device (IPA, requires code signing)
    yarn ios:build:ipa
    
    # Android E2E APK (required)
    yarn android:build:e2e