🏝️

「Code Along : Foundation Modelフレームワークによる、アプリへのオンデバイス AIの組み込み」のまとめ

に公開

WWDC25の「Code Along : Foundation Modelフレームワークによる、アプリへのオンデバイス AIの組み込み」のまとめになります。

https://developer.apple.com/jp/videos/play/wwdc2025/259

プロンプトエンジニアリング

@Guide マクロの種類

  • description:ガイドの説明
    • @Guide(description: "エキサイティングな旅行計画の名前")
  • .anyOf: 選択肢のリスト
    • @Guide(.anyOf(Landmarks.landmarkNames))
  • .count: 選択肢の数
    • @Guide(.count: 3)

指示

指示をクロージャで指定すると、複数の文字列やGenerable型のインスタンスを含めることができる。(Itinerary.exampleTripToJapan はGenerable型のインスタンス)

self.session = LanguageModelSession {
  "Your job is to create an itinerary for the user."
  """
  Here is a description of \(landmark.name) for your reference \
  when considering what activities to generate:
  """
  landmark.description
  "Here is an example:"
  Itinerary.exampleTripToJapan
}

Tool Calling

Toolを使うように指示する

指示の中にツールを使うよう明示することで、モデルにツールを使用するよう指示できます。
以下のコードの Use the findPointsOfInterest tool の部分が、ツールを使用するように指示している箇所です。

self.session = LanguageModelSession(tools: [pointOfInterestTooll) {
  "Your job is to create an itinerary for the user."

   """
   Use the findPointsOfInterest tool to find various \ 
   businesses and activities in \(landmark.name).

   These point of interest categories may include
   \(FindPoints0fInterestTool.categories).
   """

   """
   Here is a description of \(landmark.name) for your reference \
   when considering what activities to generate:
   """
   landmark. description

   "Here is an example:"
   Itinerary.exampleTripToJapan
}

Apple Intelligenceを利用できない場合の考慮

Apple Intelligenceに対応していない端末や、有効化していない場合など、モデルが利用できない場合を考慮する必要があります。

1. デバイスがApple Intelligenceをサポートしていない場合

生成ボタンを非表示にし、別の方法でユーザーに結果を提供します (例: ローカルのJSONファイルから読み込む、そもそも機能を提供しないなど)

2. Apple Intelligenceが無効な場合

生成ができない理由をユーザーに説明し、Apple Intelligenceを有効にするよう促します。

3. モデルが利用できない場合

モデルのダウンロードが完了していない場合が該当します。ユーザーにダウンロードが完了したら再度試すよう促します。

モデルが使用できない時のシミュレーション

Xcodeを使ってモデルが使用できない場合をシミュレートするには、Edit SchemeのSimulated Foundation Models Availabilityを使用すると、モデルの利用をコントロールできます。

Steaming output

ストリーミング出力を行うときは、アニメーションを使って表示するとよいでしょう。

struct ItineraryView: View {
  let landmark: Landmark
  let itinerary: Itinerary.PartiallyGenerated

  var body: some View {
    VStack(alignment: .leading) {
      if let description = itinerary.description {
        Text (description)
          .contentTransition(.opacity)
          .font(.subheadline)
          .foregroundStyle(.secondary)
      }

      if let rationale = itinerary.rationale {
        HStack(alignment: .top) {
          Image(systemName: "sparkles")
          Text(rationale)
        }
        .rationaleStyle()
      }

      if let days = itinerary.days {
        ForEach(days) { plan in
          DayView(landmark: landmark, plan: plan)
            .transition(.blurReplace)
        }
      }
    }
    .animation(.easeInOut, value: itinerary)
  }
}

プロファイリング

モデルの生成は、アプリの動作以上に端末の性能に依存します。高性能なMacでシミュレーターを使用している場合、iPhoneよりも高速に動作することがあります。このことを考慮した上でプロファイリングを行う必要があります。

モデルの事前ウォーミング

モデルの生成を開始してからモデルを準備すると生成処理が遅くなるため、アプリの起動時にモデルを事前にウォーミングアップすることが推奨されます。例えば、ユーザーがプロンプトの入力を開始した時や、生成ボタンが存在する画面に遷移した時に、モデルを事前にウォーミングアップするとよいでしょう。

func prepare() {
  session.prewarm()
}

IncludeSchemaInPromptの利用

モデルがすでに応答形式を完全に理解している場合は、IncludeSchemaInPromptfalse に設定することで、生成のパフォーマンスを向上できます。この設定が可能な条件は、以下の2点に合致した場合です。

  1. 複数ターンの会話において、同じタイプのリクエストを行う場合
  2. 指示にスキーマの完全な例が含まれている場合
let stream = session.streamResponse(
  generating: Itinerary.self,
  includeSchemaInPrompt: false
) {
  "Generate a \(dayCount)-day itinerary to \(landmark.name)."
  "Give it a fun title and description."
}

Discussion