🤡

アプリをApple Intelligenceに対応する

2024/12/25に公開

これは株式会社TimeTree Advent Calendar 2024の25日目の記事です。

こんにちは。iOSエンジニアの伊藤です。
本記事では、現時点(2024年12月24日時点)で実装可能なApple Intelligenceの機能について調査・検証した内容をまとめました。まだ情報が少ない領域ではありますが、少しでも参考になればうれしいです。


テスト環境
・Xcode 16.2
・MacBook Pro 2023 (Apple M2 MAX, macOS Sequoia 15.2)
・iPhone 15 Pro Max (iOS 18.2)


Apple Intelligenceとは

最新のドキュメントはこちらから確認できます。

Apple Intelligence is a new personal intelligence system that deeply integrates powerful generative models into the core of iPhone, iPad and Mac
Apple Intelligence は、iPhone、iPad、Mac のコアに強力な生成モデルを深く統合した新しいパーソナル インテリジェンス システムです

現状、Apple Intelligenceは日本語に対応していませんが、2025年4月には対応予定とアナウンスされています。

端末の言語を英語に設定するとApple Intelligenceを試すことが可能です。さらにiOS18.1から追加された「Type to Siri」機能を使えば、画面下部をタブルタップしてSiriへの入力をテキストで行えるようになります。英語が発音できなくても大丈夫です。
https://support.apple.com/ja-jp/guide/iphone/iphaff1d606/ios

そのため、待ちきれない気持ちを抑えつつ、少しフライング気味ではありますが、調査結果を記録しておこうと思います。


Apple Intelligenceをアプリに搭載

Apple Intelligenceをアプリで利用できるようするには以下のような手法があります。

1. AppIntent / Shortcut

Siriからアプリ内で定義したIntentを呼び出し、アプリの機能を実行します。
意図した機能をショートカットから呼び出せるようにしておくと、Siriおよびショートカットアプリからの操作が可能になります。
また、AppIntentとして定義しシステムに登録されたIntentであれば、ユーザーがどのアプリを開いていても、フレーズが一致しさえすればSiriが見つけて実行してくれます。

ショートカットの呼び出しを許可 ショートカットを呼び出す
shortcut shortcut

2. Make onscreen content available to Siri and Apple Intelligence

アプリの画面上に表示されているコンテンツを、SiriやApple Intelligenceから活用できるようにする仕組みです。
特定の画面を開いた状態でSiriを呼び出すと、その画面上の画像や動画、ドキュメントなどをSiriに渡して、詳細や要約を確認できます。
ただし、画像解析にはChatGPTのアカウントが必要といった制限もあるようです。

画像を渡す 読み込み結果
shopping image shopping image

3. SiriKit(Standard intents and custom intents)

Appleが標準で用意しているStandard Intents(アラームの設定、アプリの起動など)や、独自定義したCustom Intentsは、SiriやApple Intelligenceから自動的に利用が可能となります。
テキスト入力(Type to Siriなど)を行っている際に、関連するShortcutやIntentがサジェストされ、効率的に呼び出せる仕組みも用意されています。

アラームを設定 knock-knock jokesを聞く
knock-knock jokes

Assistantマクロを活用してSiriとApple Intelligenceを連携

Apple Intelligenceがアプリの機能を認識し、自在に呼び出せるようにするためには、Assistantマクロと特定のプロトコルへの適合が不可欠です。以下では、その概要とサンプルコードを紹介します。

1. Assistantマクロを使ったコードの用意

たとえば、アプリに「お気に入り画面を開く」機能を提供したい場合は、OpenFavoritesIntentのようなIntent構造体を用意し、そこに@AssistantIntent(schema: ...)アトリビュートを付与します。これにより、SiriやApple Intelligenceが「OpenFavorites」というアクションを認識できるようになります。

2. 特定プロトコルへの適合

・AppIntent: 実際に呼び出す処理を定義します。
・AppEntity: アプリ内で扱うデータモデルを表現します。
・AppEnum: 定数や列挙型を定義し、対話しやすいように整理します。

以下、公式サンプルコードの抜粋を元に紹介します。

AssistantIntentを定義するマクロ

@AssistantIntent(schema: .photos.openAsset) // アプリ内の写真または動画を開くことを明示する
struct OpenAssetIntent: OpenIntent {
    var target: AssetEntity

    @Dependency
    var library: MediaLibrary

    @Dependency
    var navigation: NavigationManager

    @MainActor
    func perform() async throws -> some IntentResult {
        let assets = library.assets(for: [target.id])
        guard let asset = assets.first else {
            throw IntentError.noEntity
        }
        navigation.openAsset(asset)
        return .result()
    }
}

AssistantEntityを定義するマクロ

import AppIntents
import CoreLocation
import CoreTransferable

@AssistantEntity(schema: .photos.asset) // 画像または動画のAssetであることを明示する
struct AssetEntity: IndexedEntity {

    // MARK: Static

    static let defaultQuery = AssetQuery()

    // MARK: Properties

    let id: String
    let asset: Asset

    @Property(title: "Title")
    var title: String?

    var creationDate: Date?
    var location: CLPlacemark?
    var assetType: AssetType?
    var isFavorite: Bool
    var isHidden: Bool
    var hasSuggestedEdits: Bool

    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(
            title: title.map { "\($0)" } ?? "Unknown",
            subtitle: assetType?.localizedStringResource ?? "Photo"
        )
    }
}

extension AssetEntity: Transferable {

    struct AssetQuery: EntityQuery {
        @Dependency
        var library: MediaLibrary

        @MainActor
        func entities(for identifiers: [AssetEntity.ID]) async throws -> [AssetEntity] {
            library.assets(for: identifiers).map(\.entity)
        }

        @MainActor
        func suggestedEntities() async throws -> [AssetEntity] {
            // Suggest the first three assets in the photo library.
            return library.assets.prefix(3).map(\.entity)
        }
    }

    static var transferRepresentation: some TransferRepresentation {
        DataRepresentation(exportedContentType: .png) { entity in
            return try await entity.asset.pngData()
        }
    }
}

AssistantEnumを定義するマクロ

import AppIntents

@AssistantEnum(schema: .photos.assetType) // Assetに画像または動画という種類があることを明示する
enum AssetType: String, AppEnum {
    case photo
    case video

    static let caseDisplayRepresentations: [AssetType: DisplayRepresentation] = [
        .photo: "Photo",
        .video: "Video"
    ]
}

3. AppShortcutの定義

以下のようにAppShortcutsProviderを定義すると、ShortcutsアプリやSiriから呼び出せるフレーズやアイコンが自動的に用意されます。

import AppIntents

struct ExampleAppShortcutsProvider: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: OpenAssetIntent(),
            phrases: [
                "Open Asset \(.applicationName)" // Siriで呼び出せるフレーズを登録する
            ],
            shortTitle: "Open Asset",
            systemImageName: "photo"
        )
    }
}

Assistantマクロによって、アプリの独自機能をSiriやApple Intelligenceに簡単に公開できるイメージです。
実際には、どの機能(Intent)を提供するか、どのデータ(Entity)を扱うか、どういう列挙型(Enum)を用意するか、などを個別に検討・設計してマクロで定義する流れになります。

このようなAppIntentを通じてShortcutからIntentを扱えるようになれば、Apple Intelligenceが他のアプリから取得したデータを別のアプリへ引き渡すといった連携も期待できるかもしれません。


AppIntent対応ドメイン

現在、.photosドメインも含め13種類のドメインがサポートされています。
アプリの機能をシステムへ提供するには、対応するドメインを指定する必要があるようです。たとえばカメラ機能ならCameraドメインを使うなど、機能とIntentが連動しているかどうかが重要になります。
審査においても、このドメイン指定がチェック対象になる可能性が高いため、留意が必要です。


画面上のコンテンツをSiriとApple Intelligenceで利用する

SwiftUIの場合、.userActivityモディファイアでViewの持つコンテンツを指定することで、SiriやApple Intelligenceが画面上のデータを活用できるようになります。
サンプルコードを見ると、asset.entityクラスがTransferableプロトコルに準拠しており、実際のImageビューに直接アクセスするのではなく、データの共有という仕組みでSiriに渡されます。

var body: some View {
    MediaView(
        image: image,
        duration: asset.duration,
        isFavorite: asset.isFavorite,
        proxy: proxy
    )
    .userActivity(
        "com.example.asssistant-schemas-example.ViewingPhoto",
        element: asset.entity
    ) { asset, activity in
        activity.title = "Viewing a photo"
        activity.appEntityIdentifier = EntityIdentifier(for: asset)
    }
extension AssetEntity: Transferable {
    static var transferRepresentation: some TransferRepresentation {
        DataRepresentation(exportedContentType: .png) { entity in
            return try await entity.asset.pngData()
        }
    }
}

注意点
・呼び出し挙動の違い
AppIntentで定義した機能をSiriから使用する場合とShortcutアプリから呼び出す場合で動作が異なることがあります。
・ChatGPTアカウントを利用しているが、パーソナライズは反映されない
ユーザーの個人アカウント情報は特に使われないようでした(現時点の挙動)。
・チャット履歴の扱い
Apple IntelligenceとChatGPT間のやりとりが履歴として残るため、気になる場合はプライバシーポリシーやログの取り扱いを十分に検討する必要があります。


終わりに

以上、2024年12月24日時点で検証できたApple Intelligence関連の機能や注意点を紹介しました。
AppIntentを通じてSiriやApple Intelligenceがアプリ機能を自由に呼び出せるようになれば、ユーザー体験の向上やアプリ間連携など、新たな可能性も大きいと感じています。ただ、その分セキュリティやプライバシー保護の観点も見逃せません。今後のアップデートや実装仕様の変化に注目しつつ、引き続き情報を追っていきたいと思います。


参考リンク

https://developer.apple.com/documentation/appintents/integrating-actions-with-siri-and-apple-intelligence

https://developer.apple.com/documentation/appintents/app-intent-domains

https://developer.apple.com/documentation/appintents/making-onscreen-content-available-to-siri-and-apple-intelligence

https://developer.apple.com/documentation/appintents/making-your-app-s-functionality-available-to-siri


TimeTreeの採用情報

TimeTreeでは "「誘おう」をつくる" というミッションに向かって一緒に挑戦してくれる仲間を探しています。TimeTreeで働くことに興味がある方はぜひ一度お話ししましょう✨

TimeTreeのiOS開発チームの雰囲気がわかる募集要項はこちら🍎

https://open.talentio.com/r/1/c/timetree/pages/16544

いきなり面接は…という方はコーヒーでも飲みながら気軽にお話ししましょう☕️

https://open.talentio.com/r/1/c/timetree/pages/29064

会社概要やiOSアプリエンジニア以外の募集要項はフッターにございます📝
こちらもお待ちしております🙌

TimeTree Tech Blog

Discussion