View in English

  • Apple Developer
    • 시작하기

    시작하기 탐색

    • 개요
    • 알아보기
    • Apple Developer Program

    알림 받기

    • 최신 뉴스
    • Hello Developer
    • 플랫폼

    플랫폼 탐색

    • Apple 플랫폼
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    피처링

    • 디자인
    • 배포
    • 게임
    • 액세서리
    • 웹
    • 홈
    • CarPlay
    • 기술

    기술 탐색

    • 개요
    • Xcode
    • Swift
    • SwiftUI

    피처링

    • 손쉬운 사용
    • 앱 인텐트
    • Apple Intelligence
    • 게임
    • 머신 러닝 및 AI
    • 보안
    • Xcode Cloud
    • 커뮤니티

    커뮤니티 탐색

    • 개요
    • Apple과의 만남 이벤트
    • 커뮤니티 주도 이벤트
    • 개발자 포럼
    • 오픈 소스

    피처링

    • WWDC
    • Swift Student Challenge
    • 개발자 이야기
    • App Store 어워드
    • Apple 디자인 어워드
    • 문서

    문서 탐색

    • 문서 라이브러리
    • 기술 개요
    • 샘플 코드
    • 휴먼 인터페이스 가이드라인
    • 비디오

    릴리즈 노트

    • 피처링 업데이트
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • 다운로드

    다운로드 탐색

    • 모든 다운로드
    • 운영 체제
    • 애플리케이션
    • 디자인 리소스

    피처링

    • Xcode
    • TestFlight
    • 서체
    • SF Symbols
    • Icon Composer
    • 지원

    지원 탐색

    • 개요
    • 도움말
    • 개발자 포럼
    • 피드백 지원
    • 문의하기

    피처링

    • 계정 도움말
    • 앱 심사 지침
    • App Store Connect 도움말
    • 새로 추가될 요구 사항
    • 계약 및 지침
    • 시스템 상태
  • 빠른 링크

    • 이벤트
    • 뉴스
    • 포럼
    • 샘플 코드
    • 비디오
 

비디오

메뉴 열기 메뉴 닫기
  • 컬렉션
  • 전체 비디오
  • 소개

더 많은 비디오

  • 소개
  • 요약
  • 자막 전문
  • 코드
  • Foundation Models 프레임워크로 에이전틱 앱 경험 빌드하기

    Foundation Models 프레임워크 프리미티브로 동적 컨텍스트와 에이전틱 워크플로를 위한 인텔리전스 기능을 한 단계 더 발전시키는 방법을 알아보세요. 공유 컨텍스트를 설계하고, 개인정보 보호 경계를 설정하며, 키 값 캐싱을 관리하는 방법을 안내합니다. 로컬 모델과 서버 모델 간의 원활한 핸드오프를 오케스트레이션하는 방법을 살펴보세요.

    챕터

    • 0:00 - Introduction
    • 2:47 - The example app and agents
    • 3:47 - Declaring a dynamic profile
    • 4:45 - Dynamic instructions
    • 5:36 - Configuring models per phase
    • 7:21 - Transcript management and history transforms
    • 8:50 - Custom modifiers
    • 9:39 - Lifecycle modifiers and session properties
    • 12:52 - Orchestration: baton-pass
    • 14:06 - Orchestration: phone-a-friend and skills
    • 15:18 - Tool calling mode
    • 17:12 - Transcript error handling
    • 18:27 - Performance, accuracy, and evaluations
    • 21:24 - Next steps

    리소스

    • Composing dynamic sessions with instructions and profiles
      • HD 비디오
      • SD 비디오
  • 비디오 검색…

    안녕하세요, 여러분 함께해 주셔서 감사합니다 저는 Erik입니다 저는 Oliver예요 오늘은 완전히 새로운 가능성을 열어주는 새 API 세트를 살펴봅니다 여러분 앱을 위한 Dynamic profiles입니다 코드로 넘어가기 전에 먼저 기반을 다져볼게요 이 API가 해결하는 문제와 설계 철학을 살펴봅니다 이 API가 해결하는 첫 번째 과제는 컨텍스트 관리입니다 긴 세션에서 dynamic profiles를 사용하면 트랜스크립트를 정리하거나 요약해서 모델의 컨텍스트 윈도우 내에 유지할 수 있습니다 이 API가 해결하는 두 번째 문제는 경계 설정입니다 여러 모델을 사용할 때는 기능과 비용을 고려해 설계해야 합니다 Dynamic profiles로 이런 선택이 가능합니다 이 분야는 매주 빠르게 변하고 있습니다 저희가 소개하는 기본 요소는 유연하게 설계되어 현재와 미래의 추상화를 모두 구현할 수 있습니다 맞습니다 Dynamic profiles는 컨텍스트 엔지니어링과 모델 경계 정의를 가능하게 하며 거의 모든 아키텍처에 적용할 수 있습니다 그런 정신으로 오늘 새 패키지를 발표합니다 Foundation Models 프레임워크 utilities입니다 Utilities는 오픈 소스 Swift 패키지로 에이전트 경험 구축에 도움이 되는 컴포넌트를 제공합니다 OS 릴리스 사이에 업데이트되며 새롭게 등장하는 또는 실험적인 패턴을 제공합니다 모두 dynamic profiles 기반입니다 배경을 설명했으니 이제 목차로 넘어가겠습니다 이 영상의 전반부에서는 Oliver가 dynamic profiles의 작동 방식을 설명합니다 후반부에서는 제가 다시 나와 몇 가지 고급 주제를 다룹니다 오케스트레이션 패턴 관련 주제입니다 마지막으로 성능과 정확도 관련 고려사항을 살펴볼게요 그럼 Oliver에게 넘기겠습니다 감사합니다, Erik LanguageModel 프로토콜 도입과 PrivateCloudComputeLanguageModel로 선택할 수 있는 모델이 그 어느 때보다 많아졌습니다 DynamicProfile은 모델을 전환할 수 있는 새 API로 LanguageModelSession 내에서 최적의 구성을 선택할 수 있는 유연성을 제공합니다 현재 작업에 맞게 DynamicProfile은 유용한 추상화를 구축할 수 있는 기반으로 에이전트나 스킬 같은 것들입니다 오늘은 여러 모델 활용부터 시작해 API를 안내해 드릴게요 트랜스크립트 고려사항으로 들어가기 전에 세션 라이프사이클 이벤트로 마무리합니다 예시부터 살펴볼게요

    저는 Origami라는 공예 앱을 개발 중입니다 이 앱은 종이접기와 뜨개질 튜토리얼을 제공합니다 사용자가 이미지를 업로드하면 앱이 도움을 줍니다 이미지를 영감으로 삼아 아이디어를 브레인스토밍합니다 사용자는 추려진 아이디어에 피드백을 제공하고 선택한 개념에 대한 튜토리얼이 생성됩니다 사용자가 튜토리얼을 진행하는 동안 진행 중인 사진을 업로드하고 기법에 대한 조언을 받을 수 있습니다

    앱의 각 단계는 공유 컨텍스트가 필요하지만 개별적으로는 고유한 우선순위가 있습니다 다양한 모델 세트에서 혜택을 얻을 수 있으며 서로 다른 지시사항과 생성 옵션을 사용합니다 이러한 구성이 에이전트입니다 앱을 대신해서 동작하며 특정 목표와 기능 세트를 염두에 두고 구성됩니다 DynamicProfile을 사용하면 개별 Profile을 선언할 수 있습니다 이는 LanguageModelSession의 구성 상태 또는 에이전트를 나타냅니다 Profile은 지시사항, 툴, 수정자로 구성되어 있으며 모델, temperature, samplingMode 등을 구성할 수 있습니다 공예 경험을 위한 DynamicProfile 선언부터 시작해 보겠습니다 여기 CraftOrchestrator라는 Observable 클래스가 있습니다 앱의 다양한 단계를 추적합니다 먼저 브레인스토밍 단계에 집중해 볼게요 다양한 공예 프로젝트 아이디어를 사용자에게 제시하는 단계입니다 새 profile에는 지시사항이 있고 목표를 설명합니다 제목 생성을 위한 툴도 있습니다 종이접기는 복잡한 공예이므로 추가 지시사항과 툴도 포함해 봅시다 단, 사용자가 종이접기 프로젝트를 작업할 때만 적용합니다 OrigamiExpert는 DynamicInstructions라는 또 다른 새 타입을 사용합니다 DynamicInstructions를 사용하면 관련 툴과 지시사항을 그룹화하여 코드베이스 전체에서 재사용할 수 있는 단일 컴포넌트로 만들 수 있습니다 OrigamiExpert에는 지식과 툴이 있어 종이접기에 대해 모델에 프롬프트할 때마다 재사용할 수 있습니다 DynamicInstructions는 합성도 가능하며 OrigamiExpert를 다른 DynamicInstructions 바디 안에 중첩하면 지시사항과 툴이 연결됩니다 여기서 profile의 지시사항을 담기 위해 BrainstormFacilitator를 만들었습니다 이제 새 선언을 사용해서 브레인스토밍 profile을 정리할 수 있습니다 브레인스토밍은 폭넓은 공예 지식과 창의적인 사고가 필요하므로 이 profile은 PrivateCloudComputeLanguageModel을 사용합니다 Foundation Models에서 사용할 수 있는 새 모델입니다

    Louis의 발표를 꼭 확인하세요 Foundation Models의 PCC에 관한 발표로 이 모델이 제공하는 내용을 알 수 있습니다 temperature도 1로 설정해서 모델이 더 창의적인 응답을 생성할 수 있도록 합니다 DynamicProfiles를 사용해서 첫 번째 에이전트를 정의했습니다

    profile의 다음 모드로 넘어갑니다 바로 planning입니다 "planning" profile은 방향을 만드는 역할을 합니다 합의된 공예 프로젝트를 위한 것입니다 공예에 대한 심층적인 지식이 필요하므로 다시 PCCLanguageModel을 사용합니다 reasoningLevel도 구성할 것입니다 대부분의 서버 모델에서 사용 가능한 기능입니다 이는 모델이 문제를 생각하는 능력을 제어합니다 응답하기 전에 튜토리얼 생성은 복잡하므로 deep으로 설정합니다

    마지막으로 "reviewing" 단계는 조언과 안내를 제공합니다 사용자가 튜토리얼을 진행하는 동안 불필요한 서버 호출을 줄이기 위해 SystemLanguageModel을 사용합니다 이렇게 해서 공예 DynamicProfile 정의를 완성했습니다

    세션에서 DynamicProfile을 사용하려면 새 LanguageModelSession 이니셜라이저를 사용하기만 하면 됩니다 DynamicProfile의 바디는 다시 평가된다는 점에 유의하세요 모델에 프롬프트할 때마다 앱이 각 모드 사이를 이동할 때 LanguageModelSession의 페르소나가 바뀝니다 모자를 바꿔 쓰거나 에이전트를 전환한다고 생각하면 됩니다 브레인스토밍에서 planning으로 reviewing으로 이동할 수 있습니다 모두 모드 변경만으로 가능합니다 DynamicProfile로 다양한 모델 간에 라우팅하는 방법을 보셨습니다 각 모델은 컨텍스트 크기 제한이 다를 수 있음을 고려해야 합니다 공예 예시는 PCCLanguageModel과 SystemLanguageModel 사이를 전환합니다 모델 간 이동 시 컨텍스트 크기 내에 있으려면 불필요한 항목을 정리해야 할 수 있습니다 하지만 모델의 컨텍스트를 조정하는 이유가 그것만은 아닙니다 관련 없는 항목을 제거해서 모델의 집중도를 높일 수도 있습니다 또는 기존 항목에서 개인 정보를 삭제할 수도 있습니다 덜 비공개적인 모델로 이동할 때 트랜스크립트는 LanguageModelSession의 모델 컨텍스트 표현입니다 DynamicInstructions는 트랜스크립트를 수정하는 한 가지 방법을 제공합니다 더 구체적으로는 지시사항 항목을 수정할 수 있습니다 나머지 항목을 업데이트하려면 "history"라는 트랜스크립트의 창을 사용합니다 툴 호출을 삭제하는 것이 history를 정리하는 간단한 방법입니다 구현 방법을 살펴볼게요

    historyTransform을 profile에 적용하면 모델에 프롬프트하기 전에 history를 변환할 수 있습니다 요청에 불필요한 항목을 필터링하기에 좋은 시점입니다 요청에 필요하지 않을 수 있는 항목입니다 "reviewing" profile에 변환을 적용하면 기기 내 모델의 컨텍스트 크기 내에서 트랜스크립트를 유지하는 데 도움이 됩니다 변환은 세션의 트랜스크립트를 영구적으로 변경하지 않습니다 대신 모델에 프롬프트하기 전에 적용되는 로컬 변환입니다 나중에 관련성이 생길 수 있는 컨텍스트를 잃을 걱정이 없습니다 나중에 관련성이 생길 수 있습니다 historyTransform에 많은 내용이 있습니다 커스텀 수정자를 사용해서 어떻게 변환의 복잡성을 숨길 수 있는지 보여드릴게요 먼저 새 타입을 선언합니다 DynamicProfileModifier를 준수하고 historyTransform을 적용합니다 DynamicProfile의 extension을 구현해서 재사용할 수 있게 만들 수 있습니다 DynamicProfile의 extension으로 컨텍스트 줄이기가 필요한 새 Profile은 이제 새 수정자를 활용할 수 있습니다 새 Foundation Models 프레임워크 utilities 패키지에 유용한 수정자를 제공합니다 한번 살펴보시기 바랍니다 커스텀 수정자는 선언에 재사용 가능한 구성을 만드는 좋은 방법입니다 하지만 변환만이 트랜스크립트에 영향을 미치는 방법은 아닙니다 보다 상태 기반의 다른 접근 방식을 살펴봅시다 세션의 특정 지점에서 이전 항목을 요약해서 컨텍스트를 확보해야 할 수 있습니다 기존 트랜스크립트에서 컨텍스트를 확보합니다 모델의 각 응답 후에 이를 수행하면 세션 라이프사이클에 명확한 경계가 생깁니다 새 수정자 세트를 사용해서 각 응답 후에 요약 작업을 수행하는 방법을 살펴봅시다 라이프사이클 수정자는 profile의 진행 상황에 접근할 수 있게 합니다 명령형 코드를 실행할 기회를 줍니다 profile 선언에서 직접 실행됩니다 세션 외부의 상태를 업데이트하는 데 유용합니다 UI에서 진행 상황을 반영하는 것처럼 하지만 내부 상태 업데이트에도 유용합니다 공예 profile에서 모드 변경이나 세션 history 수정처럼 onResponse 수정자로 history를 변경합니다 앞서 언급한 응답 경계에서 또 다른 새 개념인 session properties도 사용하고 있습니다 Session properties를 사용하면 상태를 정의할 수 있습니다 모든 Tool 또는 Profile에서 접근할 수 있습니다 방금 사용한 history 속성은 내장 속성입니다 프레임워크에서 제공합니다 세션의 history를 캡처하며 대안으로 사용할 수 있습니다 트랜스크립트 업데이트 시 historyTransform의 대안입니다 history 속성은 손실이 있고 변경 사항은 세션의 모든 profile에 반영됩니다 특정 profile을 대상으로 하는 무손실 변환에는 historyTransform을 사용하는 것이 좋습니다 history 외에도 자체 session properties를 만들 수 있습니다 onResponse 호출 시 대화 요약을 저장하는 새 속성을 만들어 봅시다 @SessionPropertyEntry 매크로를 사용해서 속성을 선언할 수 있습니다 SessionPropertyValues의 extension 안에서 모든 session properties는 변경 가능하며 초기값이 있어야 합니다 여기서 요약을 optional string으로 선언했습니다 각 Profile은 이제 요약 값을 읽을 수 있습니다 방금 선언한 session property에 접근해서 profile의 지시사항에 요약을 포함해서 컨텍스트를 유지합니다 삭제된 트랜스크립트 항목에 대한 컨텍스트입니다

    모든 profile은 속성에 쓸 수 있으며 변경 사항은 세션 전체에서 볼 수 있습니다

    이제 대화 요약을 만들어 드릴게요 라이프사이클 수정자로 세션의 특정 지점에서 코드를 실행하세요 history 속성으로 모든 profile의 세션 history를 업데이트하세요 커스텀 session properties를 사용하세요 모든 세션 컴포넌트가 공유하는 상태를 저장합니다 이제 Erik에게 넘겨서 에이전트 오케스트레이션에 대해 알아보겠습니다 감사합니다, Oliver

    이제 profile로 에이전트 같은 것들을 구축하는 방법에 대한 직관을 쌓고 계시길 바랍니다 에이전트 경험을 오케스트레이션하는 두 가지 일반적인 패턴을 살펴봅시다 이 패턴들을 baton-pass와 phone-a-friend라고 부릅니다 Baton-pass는 협업이고 phone-a-friend는 자문입니다 먼저 baton-pass를 살펴봅시다

    이 패턴에는 두 개 이상의 profile이 있으며 일반적으로 각각 다른 모델을 활용합니다 어떤 profile이 활성화되어 있는지 제어하는 변수도 필요합니다 마지막으로 각 profile에 모델이 해당 변수를 설정하는 툴을 제공합니다 이러한 요소들을 합치면 baton-pass 패턴이 완성됩니다

    현재 브레인스토밍 중에 두루미 접는 방법을 물어보면 브레인스토밍 profile이 툴을 호출해서 tutorial profile에 바통을 넘깁니다 툴 출력이 성공적인 핸드오프를 알리고 tutorial profile이 생성합니다 최종 답변을 baton-pass 패턴의 가장 중요한 속성은 전체 트랜스크립트 history가 두 profile 모두에게 보인다는 점과 바통을 받은 profile이 결승선까지 이어받아 최종 응답을 제공한다는 점입니다 이 두 속성은 다음 패턴인 phone-a-friend와는 대조적입니다 phone-a-friend입니다

    phone-a-friend 패턴에서도 툴 호출을 사용합니다 핵심 차이점은 변수를 토글하는 대신 툴이 단기 세션을 생성한다는 것입니다 아이들을 위한 재미있는 프로젝트를 요청하면 모델이 프로젝트 제목이 필요하다고 판단하여 phone-a-friend 툴을 호출해서 title profile에 자문을 구합니다

    phone-a-friend 툴이 독립된 트랜스크립트로 새 세션을 생성하고 프롬프트한 후 응답을 툴 출력으로 전달합니다

    자식 세션이 사라지고 부모 세션이 최종 응답을 생성합니다 phone-a-friend 패턴의 가장 중요한 속성은 각 profile의 트랜스크립트가 격리되어 있다는 점과 부모 profile이 항상 최종 답변을 제공한다는 점입니다 Baton-pass와 phone-a-friend는 유용한 도구입니다 하지만 다른 옵션도 있습니다

    예를 들어 Foundation Models 프레임워크 utilities 패키지에는 인기 있는 패턴으로 잘 알려진 Skills 타입이 있습니다 절차적 컨텍스트 로딩 패턴입니다 오케스트레이션에 툴을 활용하는 다양한 방법을 이해했으니 새로운 제어 방법을 살펴보겠습니다 툴 호출 시점을 제어할 수 있는 Tool calling mode입니다

    Tool calling mode에는 세 가지 옵션이 있습니다 allowed, disallowed, required입니다 기본값은 "allowed"로 기존 동작과 동일합니다 모델이 툴 호출을 생성하거나 직접 응답할 수 있습니다 툴이 필요한지 모를 때 사용하는 옵션으로 가장 일반적인 경우입니다 가장 일반적인 경우입니다 "disallowed"는 모델이 툴을 호출하지 못하게 합니다 사용자가 앱의 특정 부분으로 이동할 때 유용합니다 세션의 툴이 관련 없다고 알려진 경우입니다 마지막으로 "required"는 모델이 툴만 호출할 수 있습니다 모든 동작을 툴 호출로 표현하는 에이전트 시스템에서 유용합니다 툴 호출로 표현할 때입니다

    profile을 사용하면 수정자로 tool calling mode를 지정할 수 있습니다 profile을 사용하지 않는 경우 tool calling mode를 설정할 수 있습니다 respond(to:)를 호출할 때 GenerationOptions로

    가장 중요하게 기억해야 할 사항입니다 tool calling이 required이면 모델은 기본적으로 while 루프 상태입니다 어떤 형태로든 종료 조건을 만드는 것은 여러분의 몫입니다 좋은 방법 중 하나는 변수에 따라 tool call mode를 조건화하는 것입니다 여기서는 모델이 데이터베이스 툴을 호출할 때까지 툴 호출을 강제합니다

    두 번째로 강력한 방법은 모델에 오류를 throw하는 최종 답변 툴을 제공하는 것입니다 오류를 throw합니다 오류를 throw하면 툴 호출 루프가 중단되고 즉시 제어권이 여러분에게 반환됩니다 기본적으로 툴에서 오류를 throw하거나 응답을 취소하면 세션의 트랜스크립트가 이전 상태로 롤백됩니다 응답 도중 취소했다가 다시 재개하려는 고급 사용 사례에서는 오류 후에도 트랜스크립트를 상태 그대로 유지해야 합니다 이를 지원하는 새 API를 추가했습니다 profile을 사용하면 수정자로 "transcriptErrorHandlingPolicy"를 설정할 수 있습니다 수정자를 사용합니다 profile을 사용하지 않는 경우 세션에서 직접 설정할 수 있습니다

    두 가지 옵션은 ".revertTranscript"와 ".preserveTranscript"입니다

    ".preserveTranscript"를 사용할 때는 트랜스크립트를 올바른 상태로 되돌리는 것이 세션을 계속 사용하려면 여러분의 책임입니다

    이를 위해 세션의 "transcript" 속성이 이제 변경 가능합니다 단, 세션의 "isResponding" 속성이 false일 때만 트랜스크립트를 수정할 수 있습니다 응답 중에 트랜스크립트를 변경하려고 하면 프로그래머 오류입니다

    새 API를 살펴봤으니 이제 이야기해야 할 것이 있습니다 트랜스크립트 수정이 성능과 정확도에 미치는 영향입니다 키-값(KV) 캐시는 대규모 언어 모델의 중요한 최적화 메커니즘입니다 대규모 언어 모델의 트랜스크립트 수정으로 무효화될 수 있습니다

    일반적으로 트랜스크립트에 추가하면 KV 캐시가 유지되고 첫 토큰 출력 시간이 최소화됩니다

    항목을 제거하여 history를 재작성하거나 첨부된 툴을 변경하거나 지시사항을 업데이트하면 일반적으로 캐시 무효화가 발생해 지연 시간이 늘어납니다 작년에 이 내용을 다루지 않은 이유는 의도적으로 LanguageModelsSession API를 추가만 가능하도록 설계했기 때문입니다 기본적으로 최적의 사용이 보장됐습니다 하지만 올해는 제약을 풀었습니다

    모델마다 캐싱 동작이 다르며 확실히 알 수 있는 방법은 측정뿐이라는 점을 이해하는 것이 중요합니다

    가장 좋은 방법은 Xcode의 업그레이드된 Foundation Models Instrument입니다 Instruments로 캐시 무효화를 감지하는 방법에 대한 자세한 내용은 디버깅 및 프로파일링 영상을 확인하세요

    성능 영향 외에도 history를 재작성할 때 주의해야 할 것이 또 있습니다 바로 정확도입니다 모델이 혼란스러워질 수 있기 때문입니다

    모델에게 재미있는 것을 생각해 달라고 요청한 세션이 있다고 해봅시다 종이접기 프로젝트 이름입니다 그런 다음 세션에 제목 생성 툴을 추가하고 더 많은 아이디어를 프롬프트합니다 다음에 무슨 일이 일어날까요?

    운이 좋으면 모델이 원하는 대로 툴을 사용합니다

    하지만 모델이 이전에 툴 없이 제목을 생성했다는 것을 알아채고 툴 없이 또 그렇게 해야 한다고 생각할 수도 있습니다 원하는 결과가 아닙니다 history 수정이 모델을 혼란스럽게 했습니다

    이런 세밀한 트랜스크립트 수정을 시작하다 보면 Evaluations 프레임워크로 eval 세트를 만드는 것이 더욱 중요해집니다 컨텍스트 엔지니어링 전략의 효과를 수치화하세요 데이터 기반 최적화만이 확신을 가질 수 있는 방법입니다 evaluations 프레임워크에 관한 모든 영상을 강력히 추천합니다 이제 성능과 정확도 섹션의 마지막에 도달했습니다 내용이 정말 많았네요 Oliver, 마무리해 주실 수 있나요? 물론이죠 dynamic profiles로 모델 동작을 제어하고 세션 트랜스크립트를 관리하는 방법을 보여드렸습니다 phone-a-friend와 baton-pass 같은 패턴을 살펴봤고 tool calling mode, 수동 트랜스크립트 관리, KV 캐시도 다뤘습니다 여러분도 저희만큼 열정적이시길 바랍니다 Foundation Models 프레임워크 utilities에 대해 다음으로 샘플 앱을 직접 사용해 보세요 또는 새롭게 개선된 Xcode instrument로 PCC를 테스트해 보세요

    다음에 만나요, 시청해 주셔서 감사합니다 감사합니다

    • 5:04 - DynamicInstructions

      // DynamicInstructions
        
        struct BrainstormFacilitator: DynamicInstructions {
            var orchestrator: CraftOrchestrator
            var body: some DynamicInstructions {
                Instructions {
                    "You are a warm and friendly expert crafting brainstorm facilitator."
                }
                // Tools
                GenerateProjectTitle()
                // Conditionally include Origami knowledge
                if orchestrator.techniques.contains(.origami) {
                    OrigamiExpert()
                }
            }
        }
    • 6:41 - DynamicProfile

      // DynamicProfile
      
        struct CraftProfile: LanguageModelSession.DynamicProfile {
            var orchestrator: CraftOrchestrator
            var body: some DynamicProfile {
                switch orchestrator.mode {
                case .brainstorming:
                    Profile { BrainstormFacilitator(orchestrator: orchestrator) }
                        .model(orchestrator.pccLanguageModel)
                        .temperature(1)
                case .planning:
                    Profile { TutorialAuthor(orchestrator: orchestrator) }
                        .model(orchestrator.pccLanguageModel)
                        .reasoningLevel(.deep)
                case .reviewing:
                    Profile { CraftCoach() }
                        .model(orchestrator.systemLanguageModel)
                }
            }
        }
    • 6:43 - Initialize your session with your dynamic profile

      // Initialize your session with your dynamic profile
        let session = LanguageModelSession(profile: CraftProfile(orchestrator: orchestrator))
    • 8:33 - Transcript management

      // Transcript management
        
        struct CraftProfile: LanguageModelSession.DynamicProfile {
            var orchestrator: CraftOrchestrator
            var body: some DynamicProfile {
                switch orchestrator.mode {
                case .reviewing:
                    Profile { CraftCoach() }
                        .model(orchestrator.systemLanguageModel)
                        .historyTransform { history in
                            // Update the history for your profile
                            guard let latestResponseIndex = lastResponseEntryIndex(history) else {
                                return history
                            }
                            let filteredHistory = history[0..<latestResponseIndex].filter { entry in
                                isToolCallsOrToolOutput(entry)
                            }
                            return filteredHistory + history[latestResponseIndex...]
                        }
                }
            }
        }
    • 9:15 - Custom modifiers

      // Custom modifiers
        
        struct DroppingToolCallsProfileModifier: LanguageModelSession.DynamicProfileModifier {
            func body(content: Content) -> some DynamicProfile {
                content
                    .historyTransform { history in
                        guard let latestResponseIndex = lastResponseEntryIndex(history) else {
                            return history
                        }
                        let filteredHistory = history[0..<latestResponseIndex].filter { entry in
                            isToolCallsOrToolOutput(entry)
                        }
                        return filteredHistory + history[latestResponseIndex...]
                    }
            }
        }
      
        extension LanguageModelSession.DynamicProfile {
            func droppingCompletedToolCalls() -> some DynamicProfile {
                self.modifier(DroppingToolCallsProfileModifier())
            }
        }
    • 9:27 - History management modifiers

      // History management modifiers
      
        import FoundationModelsUtilities
      
        struct CraftProfile: LanguageModelSession.DynamicProfile {
            var orchestrator: CraftOrchestrator
            var body: some DynamicProfile {
                switch orchestrator.mode {
                case .reviewing:
                    Profile { CraftCoach() }
                        // Keep the most recent 10 entries
                        // after dropping finished tool calls
                        .rollingWindow(size: .entries(10))
                        .droppingCompletedToolCalls()
                }
            }
        }
    • 10:48 - Lifecycle modifiers

      // Lifecycle modifiers
        
        struct CraftProfile: LanguageModelSession.DynamicProfile {
            @SessionProperty(\.history) var history
            var orchestrator: CraftOrchestrator
            var body: some DynamicProfile {
                switch orchestrator.mode {
                case .planning:
                    Profile { TutorialAuthor(orchestrator: orchestrator) }
                        .model(orchestrator.pccLanguageModel)
                        .reasoningLevel(.deep)
                        .onResponse {
                            // Update history
                            if history.count > 50, let responseIndex = lastResponseIndex(history) {
                                history = history[responseIndex...]
                            }
                        }
                }
            }
        }
    • 11:40 - Declare a custom session property

      // Session properties — declaration
      
        extension SessionPropertyValues {
            @SessionPropertyEntry var summary: String?
        }
    • 12:24 - Read and write session properties in a profile

      // Session properties
        
        struct CraftProfile: LanguageModelSession.DynamicProfile {
            @SessionProperty(\.history) var history
            @SessionProperty(\.summary) var summary
            var orchestrator: CraftOrchestrator
            var body: some DynamicProfile {
                switch orchestrator.mode {
                case .planning:
                    Profile {
                        TutorialAuthor(orchestrator: orchestrator)
                        if let summary {
                            Instructions { "Summary: \(summary)" }
                        }
                    }
                    .onResponse {
                        if history.count > 50, let responseIndex = lastResponse(history.prefix(40)) {
                            summary = try await summarize(history[0..<responseIndex])
                            history = history[responseIndex...]
                        }
                    }
                }
            }
        }
    • 13:02 - Orchestration: baton-pass

      // Baton-pass
        
        struct CraftProfile: LanguageModelSession.DynamicProfile {
            var orchestrator: CraftOrchestrator
            var body: some DynamicProfile {
                switch orchestrator.mode {
                case .brainstorm:
                    Profile {
                        BrainstormInstructions()
                        BatonPassTool()
                    }
                    .onToolCall { orchestrator.mode = .tutorial }
                    .model(orchestrator.serverModel)
                case .tutorial:
                    Profile {
                        TutorialInstructions()
                        BatonPassTool()
                    }
                    .onToolCall { orchestrator.mode = .brainstorm }
                    .model(orchestrator.systemModel)
                }
            }
        }
    • 14:14 - Orchestration: phone-a-friend

      // Phone-a-friend
      
        struct CraftProfile: LanguageModelSession.DynamicProfile {
            var body: some DynamicProfile {
                Profile {
                    BrainstormInstructions()
                    PhoneFriendTool(
                        name: "generate_title",
                        description: "Generate a creative project title",
                        profile: TitleProfile()
                    )
                }
            }
        }
      
        struct PhoneFriendTool<P: LanguageModelSession.DynamicProfile>: Tool {
            func call(arguments: GeneratedContent) async throws -> String {
                let session = LanguageModelSession(profile: profile())
                let response = try await session.respond(to: arguments)
                return response.content
            }
        }
    • 15:15 - The skills pattern

      // The skills pattern
        
        struct CraftingSkills: LanguageModelSession.DynamicInstructions {
            var activations: SkillActivations
            var body: some DynamicInstructions {
                Skills(activations: activations) {
                    Skill(
                        name: "origami_folds",
                        description: "Details about specific types of folds",
                        prompt: """
                            Valley Fold: Paper is folded toward you, creating a V-shaped crease
                            Mountain Fold: Paper is folded away from you, creating an inverted V
                            ...
                            """
                    )
                    Skill(...)
                    Skill(...)
                }
            }
        }
    • 15:31 - Tool calling mode

      // Tool calling mode
        
        public struct ToolCallingMode: Sendable {
            public static let allowed: ToolCallingMode
            public static let disallowed: ToolCallingMode
            public static let required: ToolCallingMode
        }
        
        // Pass tool calling mode as a profile modifier
        struct OrigamiExpert: LanguageModelSession.DynamicProfile {
            var body: some LanguageModelSession.DynamicProfile {
                Profile {
                    Instructions("You are an origami expert")
                    QueryOrigamiDatabaseTool()
                    ShowDirectionsTool()
                }
                .toolCallingMode(.required)
            }
        }
      
        // Or pass it as a generation option
        let response = try await session.respond(
            to: "Write out the instructions for folding a paper crane.",
            options: GenerationOptions(toolCallingMode: .required)
        )
    • 16:47 - Escaping a tool call loop

      // Escaping a tool call loop
      
        struct OrigamiExpert: LanguageModelSession.DynamicProfile {
            let state: OrigamiAppState
      
            var body: some LanguageModelSession.DynamicProfile {
                Profile {
                    Instructions("Answer questions about how to fold origami")
                    QueryOrigamiDatabaseTool()
                }
                .toolCallingMode(state.queriedDatabase ? .disallowed : .required)
                .onToolCall { state.queriedDatabase = true }
            }
        }
    • 16:57 - Define a tool that throws an error

      // Define a tool that throws an error
            var output: String?
      
            @Generable struct Arguments {
                var answer: String
            }
      
            func call(arguments: Arguments) async throws -> Never {
                output = arguments.answer
                throw CancellationError()
            }
        }
    • 17:28 - Set the transcript error handling policy

      // Specify transcript behavior on a profile
        struct OrigamiExpert: LanguageModelSession.DynamicProfile {
            let state: OrigamiAppState
      
            var body: some LanguageModelSession.DynamicProfile {
                Profile {
                    Instructions("Answer questions about how to fold origami")
                    QueryOrigamiDatabaseTool()
                }
                .transcriptErrorHandlingPolicy(.preserveTranscript)
            }
        }
      
        // Or specify it on a session
        let session = LanguageModelSession()
        session.transcriptErrorHandlingPolicy = .preserveTranscript
      
        // Policy options
        extension LanguageModelSession {
            public struct TranscriptErrorHandlingPolicy: Sendable {
                // Roll the transcript back to its previous state
                public static let revertTranscript: TranscriptErrorHandlingPolicy
                // Keep the transcript in state following an error
                public static let preserveTranscript: TranscriptErrorHandlingPolicy
            }
        }
    • 17:51 - Transcript mutation

      // Transcript mutation
      
        public final class LanguageModelSession: Sendable {
            public var transcriptErrorHandlingPolicy: TranscriptErrorHandlingPolicy { get set }
      
            // Transcript is now settable
            public var transcript: Transcript { get set }
      
            // But you must not modify it during a response!
            public var isResponding: Bool { get }
        }
    • 0:00 - Introduction
    • Erik Hornberger and Oliver O'Neill introduce Dynamic Profiles and the problems they solve, context management and model boundaries, plus the new open-source Foundation Models framework utilities package. Agenda: dynamic profiles, orchestration patterns, performance and accuracy.

    • 2:47 - The example app and agents
    • Introduces the Origami craft app with three phases (brainstorming, planning, reviewing) that share context but have different priorities. Each phase becomes an agent: a configuration with its own model, instructions, and tools.

    • 3:47 - Declaring a dynamic profile
    • A DynamicProfile declares individual Profiles representing a configuration or agent. Build the brainstorming profile from an Observable orchestrator, instructions, and tools, conditionally adding capabilities for origami projects.

    • 4:45 - Dynamic instructions
    • DynamicInstructions groups related instructions and tools into a single reusable, composable component. Nesting one inside another concatenates their instructions and tools, such as an OrigamiExpert reused wherever needed.

    • 5:36 - Configuring models per phase
    • Assign different models and options per profile: Private Cloud Compute with temperature and deep reasoningLevel for brainstorming and planning, and SystemLanguageModel for reviewing. The profile body is re-evaluated on each prompt, swapping the session's persona by mode.

    • 7:21 - Transcript management and history transforms
    • Trim or redact the transcript to stay within context limits, keep the model focused, or protect privacy. historyTransform applies stateless, per-request transforms over the history window (such as dropping tool calls) without mutating the session.

    • 8:50 - Custom modifiers
    • Custom modifiers hide transform complexity — a type conforming to DynamicProfileModifier, exposed through a DynamicProfile extension for reuse across profiles, alongside the ready-made history-management modifiers in the utilities package.

    • 9:39 - Lifecycle modifiers and session properties
    • onResponse and other lifecycle modifiers run imperative code at session boundaries to update UI, profile state, or history. Session properties (the built-in history, plus custom @SessionPropertyEntry values) share state across tools and profiles, for example storing a conversation summary.

    • 12:52 - Orchestration: baton-pass
    • A collaboration pattern: multiple profiles share the full transcript, and a tool toggles which profile is active. The profile that receives the baton produces the final response.

    • 14:06 - Orchestration: phone-a-friend and skills
    • A consultation pattern: a tool spawns a short-lived child session with an isolated transcript, and the parent profile always gives the final answer. Also notes the Skills pattern in the utilities package for procedural context loading.

    • 15:18 - Tool calling mode
    • Control when tools run via allowed, disallowed, or required (as a profile modifier or generation option). When required, the model loops, so ensure an exit condition by conditionalizing the mode or using a final-answer tool that throws to break out.

    • 17:12 - Transcript error handling
    • By default a thrown tool error or cancellation reverts the transcript; the new transcriptErrorHandlingPolicy (.revertTranscript or .preserveTranscript) keeps it. With preserve, the now-mutable transcript is yours to fix, only when isResponding is false.

    • 18:27 - Performance, accuracy, and evaluations
    • Transcript mutations can invalidate key-value caches and raise latency; appending preserves them. Rewriting history can also confuse the model, so measure with the Foundation Models Instrument and quantify changes with the Evaluations framework.

    • 21:24 - Next steps
    • Where to go next — try the sample app, explore the Foundation Models framework utilities, and measure performance with Private Cloud Compute and the revamped Xcode instrument.

Developer Footer

  • 비디오
  • WWDC26
  • Foundation Models 프레임워크로 에이전틱 앱 경험 빌드하기
  • 메뉴 열기 메뉴 닫기
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    메뉴 열기 메뉴 닫기
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    메뉴 열기 메뉴 닫기
    • 손쉬운 사용
    • 액세서리
    • Apple Intelligence
    • 앱 확장 프로그램
    • App Store
    • 오디오 및 비디오(영문)
    • 증강 현실
    • 디자인
    • 배포
    • 교육
    • 서체(영문)
    • 게임
    • 건강 및 피트니스
    • 앱 내 구입
    • 현지화
    • 지도 및 위치
    • 머신 러닝 및 AI
    • 오픈 소스(영문)
    • 보안
    • Safari 및 웹(영문)
    메뉴 열기 메뉴 닫기
    • 문서(영문)
    • 튜토리얼
    • 다운로드
    • 포럼(영문)
    • 비디오
    메뉴 열기 메뉴 닫기
    • 지원 문서
    • 문의하기
    • 버그 보고
    • 시스템 상태(영문)
    메뉴 열기 메뉴 닫기
    • Apple Developer
    • App Store Connect
    • 인증서, 식별자 및 프로파일(영문)
    • 피드백 지원
    메뉴 열기 메뉴 닫기
    • 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 Bounty Program(영문)
    • Security Research Device Program(영문)
    메뉴 열기 메뉴 닫기
    • Apple과의 만남
    • Apple Developer Center
    • App Store 어워드(영문)
    • Apple 디자인 어워드
    • Apple Developer Academy(영문)
    • WWDC
    최신 뉴스 읽기.
    Apple Developer 앱 받기.
    Copyright © 2026 Apple Inc. 모든 권리 보유.
    약관 개인정보 처리방침 계약 및 지침