昨年 Foundation Models を使っていて明らかに不足していた機能や、痒いところに手がとこく機能が追加されていて嬉しい。複数エージェントを組み合わせた実装は昨年試行錯誤しながら、うまく行く時もあればその後再現性が得られなかったりもありだいぶ苦労した末に諦めたのだが、今回紹介された Tool calling mode を用いて意図を明確実装できそうなのが素晴らしい。あと、宣言的に見通しよくインストラクションを記述できるのもありがたい。
Build agentic app experiences with the Foundation Models framework
0:00 – Introduction
- Foundation Models フレームワークに追加された Dynamic Profiles の概要と、それが解決する課題を紹介
- 新しいオープンソースパッケージ「Foundation Models framework utilities」の紹介
- コンテキスト管理やモデルの境界設定などのユーティリティを提供
2:47 – The example app and agents
- サンプルアプリ「Origami craft app」を通じてエージェント的な設計を解説
- 3 つのフェーズ(ブレインストーミング・計画・レビュー)でコンテキストを共有しつつ、それぞれ異なる優先度を持つ
- 各フェーズを「エージェント」として扱う
- エージェント:独自のモデル・指示・ツールを持つ設定の単位
- Dynamic Profiles を使って各エージェントを宣言
3:47 – Declaring a dynamic profile
DynamicProfileで個々のProfileを宣言し、エージェントの設定を組み立てるDynamicInstructionsで指示とツールをひとまとめにした再利用可能なコンポーネントを定義- 別の
DynamicInstructionsを内部にネストすると指示とツールが結合される - 例:
OrigamiExpertを必要な箇所で使い回す
- 別の
- 条件分岐でケーパビリティを動的に追加可能
- 例:オリガミプロジェクトの場合のみ
OrigamiExpertを追加
- 例:オリガミプロジェクトの場合のみ
4:45 – Dynamic instructions
DynamicInstructionsの役割:関連する指示・ツールをひとつの再利用可能なコンポーネントにまとめること- ネスト構造で指示とツールが自動的に連結される (composable)
DynamicInstructionsをコンポーネントライブラリとして機能させることで、複数のプロファイル間での再利用が容易になる
5:36 – Configuring models per phase
- フェーズごとに異なるモデルとオプションを割り当て可能
- ブレインストーミング:PCC モデル +
temperature(1)(創造性重視) - 計画:PCC モデル +
reasoningLevel(.deep)(深い推論) - レビュー:
SystemLanguageModel(オンデバイス、軽量処理)
- ブレインストーミング:PCC モデル +
DynamicProfileのbodyはプロンプトのたびに再評価されることに注意- サンプルの Observable オブジェクト
orchestrator.modeの変化に応じてモデルや指示が動的に切り替わる
- サンプルの Observable オブジェクト
LanguageModelSessionの初期化時にprofile:に渡すだけで使用開始
7:21 – Transcript management and history transforms
- トランスクリプトのトリミングが必要になる主な理由
- コンテキストサイズ制限内に収める
- 関係のないエントリを削除することでモデルの注意力を改善する
- プライバシー・機密情報の除去し、プライバシーレベルの低いモデルへ移行可能にする
.historyTransformでステートレスな変換を毎リクエスト前に適用- セッション自体のトランスクリプトは変更せず、そのリクエスト用の履歴ウィンドウにのみ作用するローカル変換(コンテクスト自体は失われない)
- 例:完了済みのツール呼び出しを除外して履歴をスリム化
8:50 – Custom modifiers
.historyTransformの繰り返し使う変換処理をカスタム修飾子としてカプセル化DynamicProfileModifierプロトコルに準拠した型を定義DynamicProfileのextensionとして公開し、各プロファイルから.droppingCompletedToolCalls()のように呼び出せる
- utilities パッケージには既製の履歴管理修飾子が同梱
.rollingWindow(size: .entries(10)):直近 N エントリだけを保持.droppingCompletedToolCalls():完了済みツール呼び出しを除外
9:39 – Lifecycle modifiers and session properties
onResponseなどのライフサイクル修飾子でセッション境界に命令的な処理を差し込む- 用途:UI の更新、プロファイル状態の変更、履歴の整理
@SessionPropertyでツールとプロファイル間の状態を共有- 組み込み:
@SessionProperty(\.history) var history(履歴) - カスタム:
@SessionPropertyEntryマクロで独自のキーを定義して拡張可能 - 例:会話の要約文字列を
summaryプロパティに保存しておき、履歴が長くなったら古い部分を要約に置き換えてトークンを節約する
- 組み込み:
12:52 – Orchestration: baton-pass
- 「バトンパス(baton-pass)」パターン:複数のプロファイルがトランスクリプト全体を共有し(shared transcript)、ツール呼び出しによってアクティブなプロファイルを切り替える(コラボレーション)
- バトンを受け取ったプロファイルが最終的な応答を生成
onToolCallでorchestrator.modeを更新してプロファイルを切り替える- 例:ブレインストーミングフェーズが計画フェーズにバトンを渡す
14:06 – Orchestration: phone-a-friend and skills
- 「電話相談(phone-a-friend)」パターン:ツールが短命な子セッションを独立したトランスクリプトで生成し、結果を親プロファイルに返す(コンサルテーション)
- 親プロファイルが常に最終応答を担当
- 子セッションは使い捨てで、親のコンテキストを汚染しない
- 「スキル(Skills)」パターン:utilities パッケージが提供する手続き的なコンテキスト読み込みの仕組み
- 複数の
Skillを宣言しておき、モデルが必要に応じて参照する
- 複数の
15:18 – Tool calling mode
- ツール呼び出しの実行制御:
allowed・disallowed・requiredの 3 モードを提供allowed:デフォルト、モデルはツールを呼ぶ場合も呼ばない場合もあるdisallowed:モデルはツールを呼び出さない、セッションのツールが無関係と分かっている場合に役立つrequired:モデルは直接応答せずツールのみを呼び出す- プロファイル修飾子
.toolCallingに設定するか、生成オプション(GenerationOptions)として渡す
required指定時の注意点:モデルが無限ループに入るリスクがある- 脱出条件を必ず設ける方法
- 状態フラグで条件分岐してモードを切り替える(例:DB を 1 回クエリしたら
disallowedに) CancellationErrorをスローする専用の「最終回答ツール」を用意して強制終了させる
- 状態フラグで条件分岐してモードを切り替える(例:DB を 1 回クエリしたら
- 脱出条件を必ず設ける方法
17:12 – Transcript error handling
- デフォルトの挙動:ツールエラーや処理のキャンセル時にトランスクリプトを直前の状態に巻き戻す
- 新しい
transcriptErrorHandlingPolicyでエラー後の挙動を選択可能.revertTranscript(デフォルト):巻き戻し.preserveTranscript:エラー後の状態を保持し、手動で修正できる
- 保持モード(
.preserveTranscript)使用時の制約isRespondingがfalseのときのみトランスクリプトを編集可能、応答中の編集は禁止
18:27 – Performance, accuracy, and evaluations
- トランスクリプトの変更がパフォーマンスに与える影響
- 変更はキーバリューキャッシュを無効化してレイテンシを上昇させる
- 追記(append)はキャッシュを維持できるため、可能な限り追記を優先する
- 履歴の書き換えがモデルの挙動に与える影響
- 予期しない動作や回答品質の低下を招く可能性がある
- 変更の効果は Foundation Models Instrument(Xcode)で計測する
- 精度の評価には Evaluations フレームワークを活用
- 変更前後の品質を数値で比較し、感覚に頼らない判断を下す