View in English

  • Apple Developer
    • 今すぐ始める

    「今すぐ始める」を詳しく見る

    • 概要
    • 学ぶ
    • Apple Developer Program

    最新情報

    • 最新ニュース
    • Hello Developer
    • プラットフォーム

    プラットフォームを詳しく見る

    • Appleプラットフォーム
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    特集

    • デザイン
    • 配信
    • ゲーム
    • アクセサリ
    • Web
    • Home
    • CarPlay
    • テクノロジー

    テクノロジーを詳しく見る

    • 概要
    • Xcode
    • Swift
    • SwiftUI

    特集

    • アクセシビリティ
    • App Intent
    • Apple Intelligence
    • ゲーム
    • 機械学習とAI
    • セキュリティ
    • Xcode Cloud
    • コミュニティ

    コミュニティを詳しく見る

    • 概要
    • 「Appleに相談」イベント
    • コミュニティによるイベント
    • デベロッパフォーラム
    • オープンソース

    特集

    • WWDC
    • Swift Student Challenge
    • デベロッパストーリー
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Center
    • ドキュメント

    ドキュメントを詳しく見る

    • ドキュメントライブラリ
    • テクノロジー概要
    • サンプルコード
    • ヒューマンインターフェイスガイドライン
    • ビデオ

    リリースノート

    • 注目のアップデート
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • ダウンロード

    ダウンロードを詳しく見る

    • すべてのダウンロード
    • オペレーティングシステム
    • アプリ
    • デザインリソース

    特集

    • Xcode
    • TestFlight
    • フォント
    • SF Symbols
    • Icon Composer
    • サポート

    サポートを詳しく見る

    • 概要
    • ヘルプガイド
    • デベロッパフォーラム
    • フィードバックアシスタント
    • お問い合わせ

    特集

    • アカウントヘルプ
    • App Reviewガイドライン
    • App Store Connectヘルプ
    • 近日導入予定の要件
    • 契約およびガイドライン
    • システムステータス
  • クイックリンク

    • イベント
    • ニュース
    • Forum
    • サンプルコード
    • ビデオ
 

ビデオ

メニューを開く メニューを閉じる
  • コレクション
  • すべてのビデオ
  • 利用方法

その他のビデオ

  • 概要
  • Summary
  • トランスクリプト
  • コード
  • Evaluationsを活用した山登り法によるプロンプトの改善

    プロンプトエンジニアリングのガイドを提供し、アプリに最適なモデルを選択できるようにする比較評価手法を紹介します。パフォーマンスのベースラインの設定や評価戦略の拡張を行い、評価結果をJSONに変換して他のツールと統合する方法を学びましょう。さまざまなプロンプト戦略を適用するタイミングや、最良の結果を得るためにプロンプトを反復によって調整する方法についても解説します。

    関連する章

    • 0:00 - Introduction
    • 2:42 - BookTracker's tagging problem
    • 5:27 - Analyzing the evaluation results
    • 8:26 - Drift between judge and human
    • 9:37 - Measuring drift with Cohen's kappa
    • 12:26 - Building a judge alignment evaluation
    • 15:16 - Analyzing alignment failures
    • 17:16 - Comparative evaluation: control vs experimental
    • 19:12 - Refining the scoring dimensions
    • 21:23 - Adding few-shot examples to the judge
    • 23:38 - Going beyond prompts: adding a tool
    • 27:17 - Next steps

    リソース

    • Book Tracker: Using Evaluations to evaluate an intelligent feature
    • Designing effective model-as-judge evaluators
    • Designing specific, measurable criteria in an evaluation suite
      • HDビデオ
      • SDビデオ
  • このビデオを検索

    私はMarcusといいます Evaluationフレームワークチームのマネージャーです。 Evaluationの使い方を インテリジェンス機能の改善に 活かす方法をご紹介します。 ご存知のように アプリにAIを活用することは ユーザーに新たなレベルの パーソナライズを提供する強力な方法です。 この技術はアプリに 従来のソフトウェアでは 実現できなかった深みをもたらします。 しかし インテリジェンス機能がすべての場面で 期待通りに動作するかどうかは 把握しにくいという課題もあります。 そこで、Evaluationフレームワークを リリースします。 自信を持ってリリースするための ツールを提供するためです。 自信を持ってリリースするには フレームワークだけでは不十分です。 Evaluationフレームワークでは ヒルクライミングも行えます。 これは反復的に改善していく Evaluationのスコアをガイドとして 機能品質を高めるプロセスです。 ヒルクライミングは開発から始まります。 既存機能と比較して測定したい 変更を加えることです。 変更が完了したら Evaluationを実行します。 結果が期待を 満たしているか確認します。 次に結果を分析して 機能をさらに改善できる ポイントを把握します。 ヒルクライミングのプロセスを活用することは 機能を体系的に改善する 優れた方法です。 しかし効果的なヒルクライミングには ループを回すだけでは足りません。 少しばかりの… サイエンスも必要です! このビデオでは ヒルクライミングループに沿って プロンプトを改善する方法を ヒルクライミングループに沿いながら 科学的な思考を取り入れながら ご説明します。 次に比較Evaluationの実施方法を ご紹介します。 ヒルクライミングのプロセスを より簡単にするためです。 そして最後に、プロンプトの変更を超えて インテリジェンス機能の 他の側面を改善する方法を扱います。 先に進む前に このビデオは既存のEvaluationを ヒルクライミングするプロセスについてです。 つまり、Evaluationパイプラインの 基盤をすでに構築済みであることを前提とします。 これにより、インテリジェンス機能の 強みと 弱みを総合的に 把握できます。 その方法に馴染みがない場合は 別のビデオをご覧ください。 "Meet the Evaluations framework" 優れたEvaluationパイプラインを 構築するために 必要なことをすべて カバーしています。 それでは始めましょう。 "Meet the Evaluations framework"で Book Trackerをご紹介しました。 Book Trackerは読者が本を カタログ化してレビューできるアプリです。

    最近、私はクラシック作品を たくさん読んでいて それらをカタログに追加しました。 実は"Treasure Island"を 読み終えたところです! 忠誠と裏切りの葛藤を描いた とても考えさせられる作品です。 Book Trackerの新機能の1つが タグ付けサービスです。 読者のレビューをもとに モデルがタグを生成します。 このレビューのタグは本の 全体的なテーマをカバーしていますが 何かが足りない気がします。 "tense"や"morally grey"のような タグを期待していました。 物語のテーマを表すものです。 "Little Women"のタグにも 同様の問題がありました。 "poignant"のようなタグは 読者の感情に関するもので 本の内容とは別の話です。 レビューに感情が込められるのはいいことですが それがタグのリストに 入るべきではありません。 また"quiet-steadiness"のようなタグは レビューから直接引用されたもので 後でライブラリを検索するときに あまり役立ちません。 Book Trackerのタグ生成機能は 期待するレベルに達していないようです。 幸い、同僚がこの機能を作ったときに Evaluationも作成しており タグを一連の基準で 測定できます。 こちらがBook Trackerの ブックタグ用Evaluationです。 特にタグの品質をどのように 評価しているかが気になるので スクロールして確認します。 アプリの定性的な側面は score dimensionsタイプで把握します。 Relevanceはタグが本のプロット情報を どれだけ表しているかを追跡します。 本のプロット テーマ、またはその他の 関連情報についてです。 Usefulnessはタグが 検索語としてどれだけ優れているかを測定します。

    ModelJudgeEvaluatorは score dimensionsと プロンプトを使って 各タグセットのスコアを生成します。 この2冊をEvaluationに追加して 返ってくるタグを確認する予定です。 モデルジャッジの評価と 自分の評価を比較する 良い機会にもなります。 インテリジェンス機能の一部を 改善したいと思うことが ヒルクライミングプロセスの 出発点です。 ループを開始するには 開発フェーズから始めます。 ここで機能とEvaluationに 必要な変更を加えます。 この場合 "Treasure Island"のレビューを Evaluationデータセットに追加します。 "Little Women"についても 同様にしました。 この2つのエントリをデータセットに追加したので Evaluationを実行して モデルが生成するタグと ジャッジのスコアを確認します。 ただし、そのために まず実行したEvaluationが 期待を満たしているか確認します。

    念のためお伝えすると 期待値はSwift Testingの expectマクロで定義できます。 テストが通るかどうかで 期待値が満たされているか 確認できます。

    この場合、Evaluationは すべての期待値を満たしましたが タグが十分でないことはわかっているので さらに調査が必要です。 そこで分析フェーズに移ります。 Xcodeの新しいEvaluationレポートで 直近のEvaluation実行の 詳細情報を確認できます。 詳細を確認するには BookTaggingEvaluationの実行をクリックします。 Evaluationの詳細ビューが表示されます。 上部には集計メトリクスの チャートがあります。 下には結果のテーブルがあります。

    ここでモデルのレスポンスと あらかじめ作成した 期待タグのリストを比較します。 Assistant Editorを開いて 確認できます。 データセットの各アイテムに対して 生成されたタグの 詳細情報を確認できます。 モデルが生成したものと 期待していたものの違いに 注目します。 このテーブルで詳しく確認できます。 用語のコレクション自体は悪くありませんが 重要な詳細がいくつか欠けています。 ユーザーが検索したいような ストーリーの詳細です。 そのため、これらのタグには relevanceで4点をつけます。 usefulnessは2点です。 モデルジャッジもrelevanceに 4点をつけたのは良かったのですが usefulnessにも4点をつけており これは正しくありません。 "Little Women"のレビューのタグについても 同じように感じるか確認します。 タグには期待していた 有用な情報がすべて含まれていません。 こちらでもジャッジのスコアに 同意できません。 やはりrelevanceは4点 usefulnessは2点が妥当と思います。 この分析から明らかになったのは モデルジャッジと私のタグ評価に 乖離があることです。 モデルと人間のこの乖離は ドリフトと呼ばれており インテリジェント機能を評価しようとする すべてのデベロッパが 直面する課題です。 その理由を説明します。 10サンプルのEvaluationが あるとします。 モデルジャッジと人間に 各サンプルを評価してもらいます。 モデルと人間はそれぞれ 1から4のスケールで評価し 最後にそのスコアを平均して 集計値を作成します。 モデルと人間の評価が 一致しない傾向があると 平均スコアが乖離します これがドリフトという名前の由来です。 データセットが増え続けると ドリフトはどんどん広がります。 そうなると機能が 適切に評価されているかどうか 判断しにくくなります。

    これを解消するために ジャッジを専門家の意見に 合わせることができます。 ドリフトが問題だとわかったので モデルジャッジが専門家の評価から どれだけ 乖離しているかを 測定する方法が必要です。 1つの方法は 専門家の評価を並べて 2つが一致する箇所をマークすることです。 これをパーセンテージとして 表すことができます。 このパーセンテージを accuracyといいます。 スコアリングスケールのすべての値が 均等に出現する場合は 一致度を測る優れた方法です。 しかしデータセットには スコアの分布が偏っている 値が含まれることが多いです。 考えてみると、データセットには 高品質な出力のサンプルが 多く含まれることがあります。 そのため、人間の評価者は データセット内のアイテムを 高いスコアで評価しがちです。 モデルが小さなデータセットを 高いスコアで評価した場合 高得点をつけると 2つが一致しているように見えます。 しかしより大きなデータセットに 適用したとき スコアのばらつきが増えると 高スコアをつける傾向が ドリフトを引き起こします。 そのためaccuracyに代わる指標が必要です。

    データセットの重み付けの性質と モデルが偶然に正解する 可能性を考慮したものです。 幸い解決策があります! Cohen's kappa係数は 1960年に統計学者・心理学者の Jacob Cohenが広めた数学的な式です。 Cohen's kappaは一致度を測定します。 2人の評価者がどれだけ 一致するかです。 そのためには、評価者が一致した 時間の割合を知る必要があります。 これがaccuracyです。 これはまさに先ほどの accuracyメトリクスが計算していたものです。 次に新しい値を計算します。 偶然の一致(coincidence)は 1人の評価者が 偶然一致する可能性を表します。 この偶然性は特定の回答が 出現しやすい 確率に基づいて重み付けされます。 ではどのように計算するのでしょうか。 一致度を計算するには accuracyスコアから始めます。 accuracyスコアから 2人の評価者がランダムに 一致する可能性を引きます。 最後に、その差をランダムな一致の逆数 つまり2人が意図的に 一致した確率で割ります。 その結果が一致度となります。 Cohen's kappaは一致度を測定する 強力な方法です。 モデルジャッジと 専門家の意見の一致度を測ります。 これを使って一致スコアを ヒルクライミングできます。 自分とモデルジャッジの間の一致度です。 ヒルクライミングループの最初に戻り 開発フェーズから始めます。 そのために、Evaluationを設定して 自分とジャッジの評価を比較し 一致スコアを生成します。 Evaluationを記述する必要があります。 4つのコンポーネントで構成されます。 最初はデータセットです。 次にEvaluationの対象です。 そして、Evaluatorを定義します。 最後に、結果を集計します。 データセットから始めましょう。 このEvaluationを正しく機能させるには モデルジャッジと私が まったく同じデータセットを評価する必要があります。 この場合、モデルジャッジはタグをレビューするため ジャッジと私がレビューするための 共通のタグセットを用意する必要があります。 ジャッジと私でレビューします。 ちょうど良いデータセットがあります。 先ほどのEvaluationには レビューとタグのコレクションが 含まれています。 このEvaluationをテストで実行したため Xcodeがアタッチメントを生成しており 生成されたすべてのEvaluationデータが 含まれています。 そのアタッチメントを取得して サマリーとタグのペアを抽出できます。 サマリーとタグのペアを抽出したら 自分の評価を追加します。 その後 このファイルの内容を Evaluationの入力として渡せます。

    次にEvaluationの対象を 設定する必要があります。 通常、subjectメソッドは 機能に関連するAPIを呼び出すためのものですが 機能に関連するAPIを呼び出すものですが 生成されたモデルのレスポンスが データセットの一部なので すでに生成されたタグを そのまま返すことができます。 次にEvaluatorを定義します。 ご想像通り EvaluatorはBook タグEvaluationと まったく同じ ModelJudgeEvaluatorです。 ここでジャッジが評価を提供します。 最後に結果を集計します。 自分の評価とジャッジの評価を 比較する部分です。 そのためにCohen's kappaを 計算する必要があります。 カスタム集計メソッドで 実行できます。 Cohen's kappaに加えて 平均も計算します。 各score dimensionの 標準偏差も計算します。 ジャッジのスコアが 上がっているか下がっているかを 把握するのに役立ちます。 テストでEvaluationを 設定できます。 このテストでは期待値を設定しており 自分の評価とジャッジの評価が 0.6の一致スコアを 出すことを期待しています。 この数値を選んだのは 統計学者によると 0.6の一致スコアは 意義のある一致水準を表すためです。 Evaluationを実行して 一致度のベースラインを取得します。 そして、Evaluationが期待値を 満たしているか確認します。 テストが失敗したようです。 期待値が満たされなかったということです。 改めて結果を詳しく 分析する時間です。 一致スコアが期待値に 達していないことがわかりました。 Evaluationレポートに移動して 詳細を確認できます。 予想通り、usefulnessと relevanceのスコアはかなり低く モデルジャッジと私の評価が 一致していません。 データセットの各サンプルが どのような結果になったか 詳細情報を取得します。 そのためにAssistant Editorを開いて 結果を詳細に確認します。 結果を確認していると "Frankenstein"のこのレビューが 目に留まりました。 タグに対する自分の評価と ジャッジの評価に かなり大きな差があります。 ジャッジはself-helpのようなタグが self-improvementがストーリーに 関連していると判断しているようです。 psychologicalは許容できる検索語ですが ユーザーが実際に検索しそうな 用語ではないでしょう。 次に同様の問題を抱える データセットの他のアイテムを確認したところ 同様の問題があるアイテムを "The Ramakien"のこのレビューが 見つかりました。 ジャッジと私は これらの用語のコレクションが役立ち 本の内容に関連していることで一致しています。 意見が分かれるのはusefulnessです。

    "visual-dimension"や"quaint-dignity"のような 用語は具体的すぎます。 問題は何でしょうか。 モデルが良いタグと悪いタグを 区別するための 十分な知識を単独では 持っていないと思います。 おそらくジャッジのプロンプトが 十分なコンテキストを提供していないためです。 そのため新しいプロンプトを 開発する必要があります。 現在のプロンプトの一致スコアと 新しいプロンプトのスコアを 比較できます。 Xcode 27では 2つのEvaluationの結果を 互いに比較できるようになりました。 比較を行う際には 科学的な思考が 大いに役立ちます。 科学実験では2つのグループがあります。 ベースラインを表す コントロールグループと 実験グループです。 比較しようとしている変化を 表すものです。 2つのバージョンの 指示についても同様に考えられます。 コントロールグループは ベースプロンプトを表します。 実験グループは 新たに変更したプロンプトを表します。 実験的なプロンプトを使った 2番目のバージョンのEvaluationを 作成する必要があります。 ベースラインとして 以前と同じモデルジャッジプロンプトを使った 同じEvaluationを使用します。 実験的なプロンプトとして タグセットの評価方法について より詳しい説明を書きました。 まずジャッジにアプリの コンテキストと 評価しようとしているものを説明します。 次に良いタグの例を示します。 悪いタグを識別する方法も示します。 両方のプロンプトが完成したら 両方のEvaluationを テストスイートに追加して 両方を実行できます。 そのスイートを今すぐ実行して 結果を比較します。 Evaluationが完了したら Evaluationレポートに戻れます。 relevanceの一致スコアが 改善されているようです。 usefulnessの一致スコアは 大幅に低下しました。

    このようなトレードオフのバランスを取るのは 難しく どう進めるかを慎重に 検討する必要があります。 詳細な分析の前に 合格したか確認します。 テストで明らかなように 合格していません。 さらに検討した結果 このプロンプトの変更を維持し 次の反復ではusefulnessスコアの 改善に集中します。 そのため結果を確認する最も効果的な方法は 2つのジャッジのusefulnessスコアを 互いに比較することです。 Evaluationレポートの新しい 比較ビューを使用します。 Evaluationレポートから 比較ボタンを開いて ベースラインのEvaluationを開きます。 2つのプロンプトのスコアを 並べて確認できます。 すぐに気になったのは usefulnessスコアの差異です。 "Picture of Dorian Gray"の このレビューに関するものです。 モデルがusefulnessの評価を 厳しくしすぎているようです。 実験的なEvaluationのusefulnessの列が この推測を裏付けているようです。 すべてのスコアが 3か2のどちらかであることに気づきました。 厳しすぎます。 有効な対処法は 各score dimensionの評価方法を より具体的にすることだと思います。 そのため、実験的なEvaluationに いくつか変更を加えます。 実験的なEvaluationを変更する前に 実験的なEvaluationの 新しいプロンプトを ベースラインに適用しました。 これにより変数が1つだけになります。 具体的にはscore dimensionsの変更です。 relevanceには少し長い説明を加えて ジャンルタグの必要性を 強調しました。 usefulnessの説明です。 過度に具体的なタグに対して より批判的であることを強調しています。 再びEvaluationの実行を待ちます。

    スコアはどちらも ベースラインから大きく改善されました。 これらの具体的な score dimensionsが はるかに役立ちそうです。 しかし、まだ一致の目標に 完全には達していません。 もう一度比較を行って 改善できる箇所を確認します。 さらに分析するために 実験的なEvaluationに戻りました。 結果を詳細に確認したいので Assistant Editorを開きます。 結果をたどると "Moby Dick"のレビューにたどり着きました。 relevanceスコアが 一致し始めています。 しかしusefulnessスコアは まだ改善の余地があります。 有望な結果もありますが まだ大きくずれているものもあります。 "Frankenstein"のこのレビューは 依然としてジャッジに問題を起こしています。 今ジャッジに必要なのは 私の評価パターンのサンプルです。 私のスケールに合わせて 評価するパターンを学習させます。 つまりもう一度 ヒルクライミングが必要です。 新しいscore dimensionsは すでにベースラインのEvaluationに追加しました。 次にメインのジャッジプロンプトを見直して タグ生成機能の目標について より詳しい情報を加えました。 モデルが問題領域を 理解しやすくするためです。 次にモデルが評価の ガイドラインとして使う いくつかの例を 書き出しました。 モデルに渡す例の数は 少なくしました。 長いリストを与えると 一致スコアが過学習しやすく ジャッジが本当に 自分と一致しているかどうか 判断しにくくなります。 これで公平な比較ができるので Evaluationを実行して 結果を確認します。 ついにスコアが 期待値を超えました! ついに合格して ループを抜け出すことができます! これでモデルジャッジが評価を行うとき 自分の基準でタグが良いか悪いかを 自信を持って判断できます。 つまりジャッジを活用して Book TrackerのBook Tagging Serviceを 評価できます。 ここまでプロンプトを ヒルクライミングする方法を見てきました。 少しずつ改善していく方法です。

    次にプロンプト以外の方法で 機能を改善する方法を ご紹介します。 タグを生成するために Book Trackerはオンデバイスモデルを使用します。 本をカタログ化するとき読者は 様々な場所にいることが多いため オンデバイスモデルを使用することで どこにいても タグを生成できます。 モデルにタグを生成する本について より多くのコンテキストを与えたいと思います。 タグを生成する本についてです。 追加コンテキストがあれば モデルはより関連性の高い 有用なタグを生成できると思います。 さらに、Book Trackerはすでに このために必要なデータを持っています。 レビューを書いたときに 著者名と 書籍タイトルを保存しているためです。 タグジェネレーターを支援するために 本に関する追加情報を取得するための ツールを作成しました。 利用可能であれば書籍タイトルと 著者を提供します。 このツールの追加は ヒルクライミングの一形態です。 機能の品質を改善しようとしているためです。 段階的な変更によって実現します。 このEvaluationでは 改善されたモデルジャッジを使った Book Tagging Evaluationを使用します。 ただし、ツールなしの 機能の品質と ツールありの品質を 比較する方法が必要です。 そのためBook Tagging Serviceに 変更を加えます。 BookTaggingServiceはツールのリストを 入力として受け取るようになりました。 デフォルトを空の配列に設定したので 既存のEvaluationを 変更する必要はありません。 ただし新しいEvaluationを書いて ツールありのサービスと なしのサービスを比較する必要があります。 こちらが作成した新しいEvaluationです。 他のEvaluationとまったく同じです。 唯一の違いは新しいlookupツールを toolsの配列に渡す点です。 Evaluationの2つのインスタンスを 定義するだけです。 1つはツールなし もう1つはツールありです。 では評価して リリースの準備ができているか 確認します。 ツールを使用するサービスは すべての期待値を満たしたので 良い結果です。 しかしBook Trackerのデータセットには 13組の本とレビューしかなく ユーザーがタグ付けのために 送信するかもしれない 多様な本とレビューをカバーしていません。

    加えて ツールを使ったサービスの Evaluationの結果を 確認していたところ ツールありのサービスの方が パフォーマンスが向上していますが ツールが必要なすべての場面で 呼び出されていないようです。 ツールが適切な状況で 呼び出されているかどうかを 確認する方法が必要です。 幸いEvaluationフレームワークは どちらの問題にも対応できます。 ツール使用の評価と 包括的なデータセットの生成に関する APIの詳細については "Create robust evaluations for agentic apps"ビデオをご覧ください。 そこではツールコールEvaluatorについて Sample Generator APIの使い方を アプリが直面するさまざまな ユースケースのテストに活用する方法を学べます。 まとめる前に今日の 内容を振り返ります。 ヒルクライミングは一度に1つの 変更に集中することで効果を発揮します。 そのためにループの各反復を 科学実験のように扱います。 変更を分離できると 機能の各部分が 全体の品質にどう貢献するかを理解できます。 各部分がどのように動作するかを知ることで どこを変更する必要があるかも わかります。 後でバグや望ましくないパターンを 解決する際に役立ちます。

    2番目に、このプロセスには時間がかかります。 加えた変更がすべて 良い結果につながるわけではありません。 しかし失敗した実験は 成功した実験と同じくらい多くを教えてくれます。 3番目に、良い実験には 創造性が必要です。 インテリジェント機能では 変更できることがたくさんあります。 機能の中では 指示 ツール レスポンスを生成するために使用する モデルを変更できます。 Evaluation側では データセットを変更できます。 集計メソッド Evaluator自体も変更できます。 何でも試すことができます。 ヒルクライミングの方法を 考えるときは これらすべてを検討してください。 最後に、ドリフトに注意してください。 Evaluatorを評価するのは 少しメタに感じるかもしれませんが よく調整されたモデルのEvaluatorは 長期的に時間を節約してくれます。 モデルは人間より はるかに速く評価を生成できます。 一致した状態を保つことで データセットがより多くの ユースケースをカバーするにつれて 有用なシグナルが得られます。 今日の内容についてさらに学びたい場合は 使用したBook Trackerアプリや モデルジャッジを調整するための Evaluationを確認できます。 すべての新しいAPIの 包括的な概要は デベロッパドキュメントの Webサイトでご確認ください。 ヒルクライミングで Evaluationスコアを向上させる方法を 学んでいただきありがとうございます。 皆さんの取り組みは必ず実を結び ユーザーに高品質な 体験を届けられるでしょう。 ご視聴ありがとうございました 良いヒルクライミングを!

    • 3:54 - The BookTaggingEvaluation

      // MARK: - Evaluation
        struct BookTaggingEvaluation: Evaluation {
            func subject(from sample: ModelSample<BookTags>) async throws -> ModelSubject<BookTags> {
                let result = try await BookTaggingService.generateTags(for: sample.promptDescription)
                return ModelSubject(value: result)
            }
      
            // MARK: - Dataset
            var dataset = ArrayLoader(samples:
                Book.sampleBooks.map { book in
                    ModelSample(prompt: book.review, expected: BookTags(tags: book.tags))
                }
            )
      
            // MARK: - Evaluators & Metrics
            var tagCount = Metric("Tag Count")
            let hasGenreTag = Metric("Has Genre Tag")
            let noDuplicates = Metric("No Duplicates")
      
            let relevance = ScoreDimension(
                "Relevance",
                description: """
                    Whether each tag describes a quality, theme, or tone of the
                    book itself rather than incidental details or the reader's
                    personal reactions.
                    """,
                scale: .numeric([
                    4: "Every tag describes the book itself",
                    3: "Most tags describe the book, one picks up a reader reaction or minor detail",
                    2: "Most tags are surface details or personal reactions, not book descriptors",
                    1: "Tags don't meaningfully describe the book"
                ])
            )
      
            let usefulness = ScoreDimension(
                "Usefulness",
                description: """
                    Whether tags are at the right granularity for browsing — broad
                    enough that multiple books could share the tag, specific enough
                    to help filter.
                    """,
                scale: .numeric([
                    4: "Every tag could group multiple books while still narrowing a search",
                    3: "Most tags are at the right level, one is either too broad or too narrow",
                    2: "Most tags are too broad to filter or too narrow to group",
                    1: "Tags would not help with browsing"
                ])
            )
      
            var evaluators: Evaluators {
                // 1. Tag count is within the required 3–8 range
                Evaluator { _, subject in
                    let count = subject.value.tags.count
                    if (count >= 3 && count <= 8) {
                        return tagCount.passing(rationale: "\(count) tags")
                    }
                    return tagCount.failing(rationale: "Got \(count) tags, expected 3–8")
                }
        
                // 2. At least one tag identifies the genre or literary form
                Evaluator { _, subject in
                    let tags = subject.value.tags.map { $0.lowercased() }
                    let knownGenres = await BookTaggingService.knownGenres
                    for tag in tags {
                        if knownGenres.contains(tag) {
                            return hasGenreTag.passing(rationale: "Matched \(tag)")
                        }
                    }
                    return hasGenreTag.failing()
                }
      
                // 3. No duplicate tags
                Evaluator { _, subject in
                    let uniqueCount = Set(subject.value.tags.map { $0.lowercased() }).count
                    if (subject.value.tags.count - uniqueCount) > 0 {
                        return noDuplicates.failing(rationale: "Found \(subject.value.tags.count - uniqueCount) duplicates")
                    }
                    return noDuplicates.passing()
                }
        
                // 4. Overall tag quality — groundedness, coverage, specificity
                ModelJudgeEvaluator(
                    judge: .default,
                    dimensions: [relevance, usefulness],
                    prompt: ModelJudgePrompt(
                        instructions: """
                            You are evaluating automatically generated tags for Shelf, a personal
                            book tracking app. Users write a short summary of their reading
                            experience, and the app generates tags to make their library browsable.
                            A good tag describes the book itself — its genre, themes, tone, or
                            setting. A bad tag picks up incidental details or the reader's personal
                            reactions that don't describe the book.
                            """,
                        evaluationTarget: { output in output.tags.joined(separator: ", ") },
                        reference: { input, _ in
                            ["Expected Tags": input.expected?.tags.joined(separator: ", ") ?? ""]
                        }
                    )
                )
            }
      
            // MARK: - Analysis
            func aggregateMetrics(using aggregator: inout MetricsAggregator) {
                aggregator.group("Heuristics") { group in
                    group.computeMean(of: tagCount)
                    group.computeMean(of: hasGenreTag)
                    group.computeMean(of: noDuplicates)
                }
                aggregator.group("Quality") { group in
                    group.computeMean(of: relevance.metric)
                    group.computeMean(of: usefulness.metric)
                }
            }
        }
    • 4:05 - Refined Relevance & Usefulness score dimensions

      let relevance = ScoreDimension(
            "Relevance",
            description: """
                Whether each tag describes the book itself — its genre, themes,
                tone, or setting — rather than the reader's reactions, meta-
                commentary about the review, or facts about the author. A book
                can be "suspenseful" (a property of the text); a reader is
                "exhausted" (a reaction). Mis-labeling the genre is a serious failure.
                """,
            scale: .numeric([
                4: "Every tag describes the book itself",
                3: "Most tags describe the book, one picks up a reader reaction or minor detail",
                2: "Most tags are surface details or personal reactions, not book descriptors",
                1: "Tags don't meaningfully describe the book"
            ])
        )
      
        let usefulness = ScoreDimension(
            "Usefulness",
            description: """
                Whether tags work as library shelf labels — broad enough that
                several books could plausibly share the tag, specific enough to
                meaningfully narrow a search. Standard genre and theme tags work;
                made-up phrases, character names, hyper-specific descriptors, and
                overly generic words like "interesting" don't.
                """,
            scale: .numeric([
                4: "Every tag could group multiple books while still narrowing a search",
                3: "Most tags are at the right level, one is either too broad or too narrow",
                2: "Most tags are too broad to filter or too narrow to group",
                1: "Tags would not help with browsing"
            ])
        )
    • 11:56 - The alignment dataset, extracted to JSON

      // Model judge alignment dataset
        [
          {
            "input": "I have read this book more times than I can count…",
            "response": "[\"literary-fiction\", \"historical-fiction\", \"family-drama\", \"romantic-drama\", 
        \"character-driven\", \"emotional-intensity\", \"multigenerational-narrative\", \"penned-by-a-woman\"]"
          }
          // ... add your expert ratings to each entry
        ]
    • 12:31 - The judge alignment evaluation: dataset, subject, evaluator

      // Model judge alignment evaluation
        struct BookTagJudgmentCalibration: Evaluation {
      
            // MARK: Dataset — load the extracted summary/tag pairs
            static let samples: [ModelSample<BookTagJudgmentValue>] = {
                guard let url = Bundle(for: BundleToken.self).url(
                        forResource: "BookTaggingEvaluation-extracted", withExtension: "json"),
                      let data = try? Data(contentsOf: url) else { return [] }
                // Build ModelSample array (adding expert ratings)
                // ...
            }()
      
            var dataset: some Loader { ArrayLoader(samples: Self.samples) }
        
            // MARK: Capture Subject — tags are already generated, so just return them
            func subject(from sample: ModelSample<BookTagJudgmentValue>) async throws -> ModelSubject<BookTagJudgmentValue> {
                ModelSubject(value: sample.expected ?? BookTagJudgmentValue(
                    tags: [], expertRelevanceScore: 0, expertUsefulnessScore: 0))
            }
      
            // MARK: Evaluators — the same model judge as the book-tags evaluation
            var evaluators: Evaluators {
                ModelJudgeEvaluator(
                    judge: .default,
                    dimensions: [relevance, usefulness],
                    prompt: ModelJudgePrompt(
                        instructions: "You are evaluating automatically generated tags for Book Tracker…",
                        evaluationTarget: { output in output.tags.joined(separator: ", ") },
                        reference: { input, _ in
                            ["Expected Tags": input.expected?.tags.joined(separator: ", ") ?? ""]
                        }
                    )
                )
            }
        }
    • 13:00 - Cohen's kappa aggregation

      func aggregateMetrics(using aggregator: inout MetricsAggregator) {
            let expertRelevance = Self.samples.map { Double($0.expected?.expertRelevanceScore ?? 0) }
            let expertUsefulness = Self.samples.map { Double($0.expected?.expertUsefulnessScore ?? 0) }
      
            aggregator.group("Relevance") { group in
                group.computeMean(of: relevance.metric)
                group.computeStandardDeviation(of: relevance.metric)
                group.custom(of: relevance.metric, label: "Relevance Alignment Score") { judge in
                    cohensKappa(ratings1: expertRelevance, ratings2: judge) ?? 0
                }
            }
            aggregator.group("Usefulness") { group in
                group.computeMean(of: usefulness.metric)
                group.computeStandardDeviation(of: usefulness.metric)
                group.custom(of: usefulness.metric, label: "Usefulness Alignment Score") { judge in
                    cohensKappa(ratings1: expertUsefulness, ratings2: judge) ?? 0
                }
            }
        }
    • 13:24 - The judge calibration test

      // Model judge alignment tests
        @Suite("Book Tag Judge Calibration")
        struct BookTagJudgmentCalibrationTests {
            static let evaluation = BookTagJudgmentCalibration()
      
            @Test("Judge Calibration", .evaluates(evaluation))
            func evaluateJudgeCalibration() async throws {
                let result = EvaluationContext.current.result
      
                let usefulnessMetric = BookTagJudgmentCalibrationTests.evaluation.usefulness.metric
                let relevanceMetric = BookTagJudgmentCalibrationTests.evaluation.relevance.metric
      
                #expect(result.aggregateValue(.custom(label: "Relevance: Judge vs Expert")) > 0.6)
                #expect(result.aggregateValue(.custom(label: "Usefulness: Judge vs Expert")) > 0.6)
            }
        }
    • 16:33 - The experimental judge prompt

      // Experimental evaluation
        struct BookTagJudgmentCalibrationExperimental: Evaluation {
            var evaluators: Evaluators {
                ModelJudgeEvaluator(
                    judge: .default,
                    dimensions: [relevance, usefulness],
                    prompt: ModelJudgePrompt(
                        instructions: """
                            You are an experienced reader and librarian evaluating tags
                            automatically generated for Book Tracker... Score the tag set on two
                            independent dimensions: Relevance and Usefulness.
      
                            ## What a good tag looks like
                            - Genre/form, theme/subject, tone/atmosphere, setting/era
      
                            ## Common failure modes
                            - Reader reactions, meta-commentary, author facts, genre contradictions
                            """,   // ← full prompt is ~40 lines; abbreviated here
                        evaluationTarget: { output in output.tags.joined(separator: ", ") },
                        reference: { input, _ in
                            ["Book Review": input.promptDescription,
                             "Tags Generated for the Review": input.expected?.tags.joined(separator: ", ") ?? ""]
                        }
                    )
                )
            }
        }
    • 20:12 - Few-shot worked examples in the judge prompt

      struct ExperimentalBookTagJudgmentCalibration: Evaluation {
            var evaluators: Evaluators {
                ModelJudgeEvaluator(
                    judge: SystemLanguageModel(),
                    dimensions: [relevance, usefulness],
                    prompt: ModelJudgePrompt(
                        instructions: """
                            You are calibrating with an expert librarian who scores
                            automatically generated tags for Book Tracker... Your goal is to
                            match how the librarian scores. Use the worked examples to calibrate.
      
                            ## Worked examples
                            ### Example A — clean fit (Pride and Prejudice)
                            Tags: romance, historical-fiction, love, redemption, passion
                            Librarian: Relevance 4, Usefulness 4
      
                            ### Example E — flat genre contradiction (Frankenstein)
                            Tags: horror, science-fiction, ... self-help, self-improvement
                            Librarian: Relevance 2, Usefulness 3
                            ... (6 examples A–F; keep the set small to avoid overfitting)
                            """,   // ← full prompt is ~60 lines; abbreviated here
                        evaluationTarget: { output in output.tags.joined(separator: ", ") },
                        reference: { input, _ in
                            ["Book Review": input.promptDescription,
                             "Tags Generated for the Review": input.expected?.tags.joined(separator: ", ") ?? ""]
                        }
                    )
                )
            }
        }
      
        9. The BookLookupTool — slides 166–167
    • 22:03 - The BookLookupTool

      // Book Information Lookup Tool
        struct BookLookupTool: Tool {
            let name = "lookupBook"
            let description = "Looks up the title and author of a book given distinguishing details — such as character names, 
        settings, quoted lines, or notable plot points — extracted from a reader's review."
      
            @Generable
            struct Arguments {
                @Guide(description: "Distinguishing details from the review that identify the book, such as character names, 
        settings, quoted lines, or notable plot points.")
                var details: String
            }
        
            @Generable
            struct Output {
                @Guide(description: "The title of the identified book, or an empty string if no match was found.")
                var title: String
      
                @Guide(description: "The author of the identified book, or an empty string if no match was found.")
                var author: String
            }
        
            func call(arguments: Arguments) async throws -> Output {
                let needles = arguments.details
                    .lowercased()
                    .split(whereSeparator: { !$0.isLetter && !$0.isNumber })
                    .map(String.init)
                    .filter { $0.count >= 4 }
      
                let best = Book.sampleBooks
                    .map { book -> (book: Book, score: Int) in
                        let review = book.review.lowercased()
                        let score = needles.reduce(0) { partial, needle in
                            partial + (review.contains(needle) ? 1 : 0)
                        }
                        return (book, score)
                    }
                    .max(by: { $0.score < $1.score })
      
                guard let match = best, match.score > 0 else {
                    return Output(title: "", author: "")
                }
                return Output(title: match.book.title, author: match.book.author)
            }
        }
    • 22:36 - BookTaggingService with a tools parameter

      // Book Tagging Service
        struct BookTaggingService {
            static func generateTags(for review: String, tools: [any Tool] = []) async throws -> BookTags {
                let prompt = tagsPrompt(review: review)
                let session = LanguageModelSession(
                    model: SystemLanguageModel(guardrails: .permissiveContentTransformations),
                    tools: tools,
                    instructions: instructions
                )
                let response = try await session.respond(to: prompt, generating: BookTags.self)
                return response.content
            }
        }
    • 22:57 - Evaluation with the lookup tool

      // Evaluation of tags with tool
        struct BookTaggingWithLookupEvaluation: Evaluation {
            func subject(from sample: ModelSample<BookTags>) async throws -> ModelSubject<BookTags> {
                let result = try await BookTaggingService.generateTags(
                    for: sample.promptDescription,
                    tools: [BookLookupTool()]
                )
                return ModelSubject(value: result)
            }
            // ... same dataset, evaluators, and aggregation as BookTaggingEvaluation
        }
    • 23:09 - Compare with/without the tool in one suite

      @Suite("Book Tag Evaluations")
        struct BookTagEvaluationTests {
            static let evaluation = BookTaggingEvaluation()
            static let lookupEvaluation = BookTaggingWithLookupEvaluation()
      
            @Test("Book Tag Evaluations", .evaluates(evaluation, info: evaluationInfo))
            func evaluateBookTagging() async throws {
                let result = EvaluationContext.current.result
                let rangeMetric = BookTagEvaluationTests.evaluation.tagCount
                let dupeMetric = BookTagEvaluationTests.evaluation.noDuplicates
                #expect(result.aggregateValue(.mean(of: rangeMetric)) >= 0.8)
                #expect(result.aggregateValue(.mean(of: dupeMetric)) == 1)
            }
      
            @Test("Book Tag Evaluations (with BookLookupTool)", .evaluates(lookupEvaluation, info: lookupEvaluationInfo))
            func evaluateBookTaggingWithLookup() async throws {
                let result = EvaluationContext.current.result
                let rangeMetric = BookTagEvaluationTests.lookupEvaluation.tagCount
                let dupeMetric = BookTagEvaluationTests.lookupEvaluation.noDuplicates
                #expect(result.aggregateValue(.mean(of: rangeMetric)) >= 0.8)
                #expect(result.aggregateValue(.mean(of: dupeMetric)) == 1)
            }
        }
    • 0:00 - Introduction
    • Hill-climbing — iteratively improving an intelligence feature using evaluation scores as a guide (develop, run, analyze) — framed around bringing scientific thinking to that loop. Assumes you've already built an evaluation pipeline (see "Meet the Evaluations framework").

    • 2:42 - BookTracker's tagging problem
    • Revisits BookTracker, whose tag generator produces tags that miss key themes or reflect the reader's feelings rather than the book. The existing evaluation judges tag quality via score dimensions (Relevance, Usefulness) and a ModelJudgeEvaluator.

    • 5:27 - Analyzing the evaluation results
    • Adds two reviews to the dataset, runs the evaluation (Swift Testing #expect), and uses the Xcode evaluation report and assistant editor to compare generated tags against expected ones, revealing the human and model judge disagree on usefulness.

    • 8:26 - Drift between judge and human
    • That disagreement is drift, the divergence between a model judge's ratings and an expert's. As the dataset grows, drift widens, making it hard to trust the evaluation, so the judge must be aligned to expert opinion.

    • 9:37 - Measuring drift with Cohen's kappa
    • Accuracy alone misleads on unevenly-distributed scores (a high-scoring judge looks aligned by luck). Cohen's kappa coefficient measures true alignment by subtracting the chance of random agreement from accuracy and normalizing, a robust drift metric.

    • 12:26 - Building a judge alignment evaluation
    • Builds an evaluation comparing the presenter's ratings to the judge's over a shared dataset: extract summary/tag pairs from the prior run's attachment, add human ratings, reuse the same ModelJudgeEvaluator as subject, and aggregate Cohen's kappa (plus mean and standard deviation), targeting an alignment of 0.6.

    • 15:16 - Analyzing alignment failures
    • The alignment test fails. Drilling into the report (for example Frankenstein, The Ramakien) shows the judge rating overly-specific or off-theme tags too highly, the judge's prompt lacks the context to tell a good tag from a bad one.

    • 17:16 - Comparative evaluation: control vs experimental
    • Xcode 27 can compare two evaluations like a controlled experiment: a baseline (control) prompt versus an experimental prompt that adds app context plus examples of good and bad tags. Running both shows relevance improved while usefulness dropped, a tradeoff to weigh.

    • 19:12 - Refining the scoring dimensions
    • Keeping the prompt change, the side-by-side comparison view reveals the judge grading usefulness too harshly. Applying the new prompt to the baseline to isolate one variable, the ScoreDimension descriptions are sharpened (emphasizing genre tags; being critical of overly-specific ones), improving both scores.

    • 21:23 - Adding few-shot examples to the judge
    • Still short of the goal, the judge prompt is grounded with the feature's purpose and a few worked examples of how the presenter rates, deliberately few to avoid overfitting the alignment score. Scores finally exceed expectations, so the judge is trusted and the loop exits.

    • 23:38 - Going beyond prompts: adding a tool
    • Hill-climbing isn't only prompts: to give the on-device tag model more context, a BookLookupTool supplies the title and author. BookTaggingService gains a tools parameter (defaulting empty), and a second evaluation compares the feature with versus without the tool, the tool version scores better, though the small 13-sample dataset and unobserved tool calls point to "Create robust evaluations for agentic apps."

    • 27:17 - Next steps
    • Think like a scientist (one change at a time), invest the time (failed experiments still inform), be creative (instructions, tools, models, datasets, aggregations, and evaluators are all fair game), and watch for drift. Download the Book Tracker sample and review the documentation.

Developer Footer

  • ビデオ
  • WWDC26
  • Evaluationsを活用した山登り法によるプロンプトの改善
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • Apple Intelligence
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習とAI
    • オープンソース(英語)
    • セキュリティ
    • SafariとWeb(英語)
    メニューを開く メニューを閉じる
    • 英語ドキュメント(完全版)
    • 日本語ドキュメント(一部トピック)
    • チュートリアル
    • ダウンロード
    • フォーラム(英語)
    • ビデオ
    Open Menu Close Menu
    • サポートドキュメント
    • お問い合わせ
    • バグ報告
    • システム状況(英語)
    メニューを開く メニューを閉じる
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles(英語)
    • フィードバックアシスタント
    メニューを開く メニューを閉じる
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(英語)
    • Mini Apps Partner Program
    • News Partner Program(英語)
    • Video Partner Program(英語)
    • セキュリティ報奨金プログラム(英語)
    • Security Research Device Program(英語)
    Open Menu Close Menu
    • Appleに相談
    • Apple Developer Center
    • App Store Awards(英語)
    • Apple Design Awards
    • Apple Developer Academy(英語)
    • WWDC
    最新ニュースを読む。
    Apple Developerアプリを入手する。
    Copyright © 2026 Apple Inc. All rights reserved.
    利用規約 プライバシーポリシー 契約とガイドライン