Skip to content

C4 Architecture Model

This page documents the paiOS architecture using the C4 model – a hierarchical approach to software architecture visualization.

The highest level of abstraction shows PAI and its external actors.

graph TB
  subgraph External_Actors["External Actors"]
      User["👤 User"]
      Developer["👩‍💻 Developer"]
  end

  subgraph External_Systems["External Systems"]
      HostPC["💻 Host PC/Mac"]
      OllamaApps["🔌 Ollama Apps"]
      Store["🏪 First Party Store"]
      CICD["⚙️ CI/CD Pipeline"]
  end

  subgraph PAI["🧠 PAI Device"]
      PAI_SYS["paiOS"]
  end

  User -->|"Voice, HID, USB"| PAI_SYS
  Developer -->|"pai-builder SDK"| PAI_SYS
  PAI_SYS -->|"HID Keyboard"| HostPC
  OllamaApps -->|"Ollama API"| PAI_SYS
  Store -->|"Downloads"| PAI_SYS
  CICD -->|"OS Images"| PAI_SYS
Actor/SystemRelationshipDescription
UserVoice, HID, USBPrimary interaction via speech and USB connection
Developerpai-builder SDKDevelops apps using the Dockerized toolchain
Host PCHID KeyboardReceives transcribed text as keyboard input
Ollama AppsAPI RequestsCompatible apps send inference requests
StoreDownloadsDistributes apps and Intelligence Packs
CI/CDOS ImagesBuilds reproducible OS images via Debos

Shows the main containers (deployable units) within the PAI Device.

graph TB
  subgraph External["External"]
      Host["💻 Host PC"]
      Store["🏪 Store"]
  end

  subgraph Device["🧠 PAI Device"]
      subgraph OS["paiOS"]
          Systemd["systemd"]
          RAUC["RAUC"]
          USB["USB Gadget"]
      end

      subgraph Engine["pai-engine"]
          Core["core/"]
          Orchestrator["orchestrator/"]
          RPC["rpc/"]
      end

      subgraph HAL["HAL Layer"]
          NPU["NPU"]
          GPU["GPU"]
          Audio["Audio"]
          HID["HID"]
          Camera["Camera"]
      end

      subgraph Apps["Apps Container"]
          RefApp["Reference App"]
          Packs["Intelligence Packs"]
      end
  end

  Host <-->|"USB"| USB
  USB --> Engine
  Systemd --> Engine
  Apps <-->|"gRPC/UDS"| RPC
  RPC --> Core
  Core --> Orchestrator
  Orchestrator --> HAL
  Store -->|"HTTPS"| Apps
ContainerTechnologyResponsibility
paiOSDebian + DebosCustom Linux OS with RAUC A/B updates
pai-engineRust DaemonCore brain: Audio, Inference, HID, SystemController
gRPC ServerTonic + UDSIPC interface for Apps
HALRust + C BindingsHardware abstraction: NPU, GPU, Audio, Camera, LED
Apps ContainerRust/PythonFirst/Third party Apps & Intelligence Packs

Level 3 – Component Diagram (pai-engine)

Section titled “Level 3 – Component Diagram (pai-engine)”

Zooms into the pai-engine container to show its internal components following Clean Architecture.

graph TB
  subgraph rpc_layer["rpc/ - Interface Adapter"]
      gRPCServer["gRPC Server"]
      ProtoConvert["Protobuf Converter"]
      ConnMgr["Connection Manager"]
  end

  subgraph core_layer["core/ - Domain Layer"]
      SystemCtrl["SystemController"]
      StateMachine["State Machine"]
      Events["Event Bus"]
      DomainTypes["Domain Types"]
  end

  subgraph orchestrator_layer["orchestrator/ - Application Logic"]
      InferOrch["InferenceOrchestrator"]
      ModelLoader["Model Loader"]
      BackendSelector["Backend Selector"]
      Scheduler["Inference Scheduler"]
  end

  subgraph hal_layer["hal/ - Infrastructure"]
      AudioHAL["Audio HAL"]
      NPUHAL["NPU HAL"]
      GPUHAL["GPU HAL"]
      HIDHAL["HID HAL"]
      CameraHAL["Camera HAL"]
  end

  subgraph libs_layer["libs/ - Sys-Crates"]
      rknn_sys["rknn-sys"]
      usb_gadget["usb-gadget"]
  end

  %% Dependency Direction: Outside-In
  gRPCServer --> ProtoConvert
  ProtoConvert --> SystemCtrl
  ConnMgr --> gRPCServer

  SystemCtrl --> StateMachine
  SystemCtrl --> Events
  StateMachine --> DomainTypes

  InferOrch --> BackendSelector
  InferOrch --> ModelLoader
  BackendSelector --> Scheduler
  
  %% Orchestrator uses Core
  InferOrch --> SystemCtrl
  Scheduler --> Events

  %% HAL implements traits from Core/Orchestrator
  AudioHAL -.-> SystemCtrl
  NPUHAL -.-> InferOrch
  GPUHAL -.-> InferOrch
  HIDHAL -.-> SystemCtrl
  CameraHAL -.-> SystemCtrl

  %% Sys-crates used by HAL
  NPUHAL --> rknn_sys
  HIDHAL --> usb_gadget

Component Responsibilities (Clean Architecture)

Section titled “Component Responsibilities (Clean Architecture)”
LayerComponentResponsibility
rpc/gRPC ServerListens on Unix Domain Socket, handles connections
rpc/Protobuf ConverterTransforms Protobuf ↔ Domain Types
core/SystemControllerCentral state machine, orchestrates all subsystems
core/Event BusPublishes domain events (e.g., “SpeechEnd”, “TranscriptReady”)
core/Domain TypesPure Rust structs, no external dependencies
orchestrator/InferenceOrchestratorDecides NPU/GPU/CPU routing based on availability
orchestrator/Backend SelectorProbes hardware, selects optimal inference backend
orchestrator/Model LoaderLoads/converts models (ONNX → RKNN)
hal/Audio HALCaptures audio via cpal, runs VAD
hal/NPU HALWraps rknn-sys, runs Whisper on NPU
hal/HID HALEmulates USB keyboard via usb-gadget
libs/rknn-sysUnsafe Rust bindings to Rockchip RKNN SDK
┌─────────────────────────────────────────────────────────────┐
│ External (Apps, gRPC Clients) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ rpc/ (Interface Adapter) │
│ - Converts external requests to domain commands │
└─────────────────────────────────────────────────────────────┘
│ depends on
┌─────────────────────────────────────────────────────────────┐
│ core/ (Domain Layer) ◄──── THE HEART ────► │
│ - Pure business logic, NO external dependencies │
│ - SystemController, State Machine, Domain Events │
└─────────────────────────────────────────────────────────────┘
│ depends on
┌─────────────────────────────────────────────────────────────┐
│ orchestrator/ (Application Logic) │
│ - InferenceOrchestrator, Backend Selection │
│ - Uses HAL via trait interfaces │
└─────────────────────────────────────────────────────────────┘
│ uses traits from
┌─────────────────────────────────────────────────────────────┐
│ hal/ (Infrastructure) │
│ - Implements traits defined in core/orchestrator │
│ - Hardware-specific code (Audio, NPU, HID, Camera) │
└─────────────────────────────────────────────────────────────┘
│ wraps
┌─────────────────────────────────────────────────────────────┐
│ libs/ (Sys-Crates) │
│ - Unsafe Rust bindings (rknn-sys, usb-gadget) │
│ - All `unsafe` code isolated here │
└─────────────────────────────────────────────────────────────┘

The primary use case: Voice-to-Text via USB HID.

sequenceDiagram
  participant User as 👤 User
  participant Mic as 🎤 Mic
  participant HAL as HAL
  participant Core as Core
  participant Orch as Orchestrator
  participant NPU as NPU
  participant HID as HID
  participant Host as 💻 Host

  User->>Mic: Speaks
  Mic->>HAL: Audio Stream
  HAL->>Core: Audio Chunks
  Core->>Core: VAD Detection
  Core->>Orch: Audio Buffer
  Orch->>NPU: Whisper Inference
  NPU->>Orch: Transcription
  Orch->>Core: Transcript
  Core->>HID: Keystrokes
  HID->>Host: USB HID Report
  Host->>Host: Text appears

Inference Orchestrator – Backend Selection

Section titled “Inference Orchestrator – Backend Selection”

The InferenceOrchestrator dynamically routes inference to NPU, GPU, or CPU.

flowchart TD
  Start["Inference Request"] --> CheckNPU{"NPU Available?"}
  
  CheckNPU -->|Yes| NPUModel{"RKNN Format?"}
  NPUModel -->|Yes| UseNPU["🚀 Run on NPU"]
  NPUModel -->|No| ConvertRKNN["Convert ONNX → RKNN"]
  ConvertRKNN --> UseNPU
  
  CheckNPU -->|No| CheckGPU{"GPU Available?"}
  CheckGPU -->|Yes| UseGPU["⚡ Run on GPU"]
  CheckGPU -->|No| UseCPU["🐢 Run on CPU"]
  
  UseNPU --> Metrics["📊 Log Metrics"]
  UseGPU --> Metrics
  UseCPU --> Metrics

The pai-daemon service owns all hardware resources.

graph TB
  subgraph Privileged["pai-daemon - privileged"]
      Daemon["pai-daemon"]
      HW["/dev/rknpu, /dev/video0"]
  end

  subgraph Sandboxed["Apps - sandboxed"]
      App1["App 1"]
      App2["App 2"]
  end

  App1 -->|"gRPC/UDS"| Daemon
  App2 -->|"gRPC/UDS"| Daemon
  Daemon -->|"udev MODE=0600"| HW