-
Présentation approfondie du framework de Foundation Models
Mettez-vous à niveau avec le framework de Foundation Models. Découvrez comment fonctionne la génération guidée et utilisez des guides, des expressions régulières et des schémas de génération pour obtenir des réponses structurées personnalisées. Nous vous montrerons comment utiliser l'appel d'outil pour permettre au modèle d'accéder de manière autonome à des informations externes et d'effectuer des actions, pour une expérience personnalisée.
Pour tirer le meilleur parti de cette vidéo, nous vous recommandons de regarder d'abord « Voici le framework de Foundation Models ».Chapitres
- 0:00 - Introduction
- 0:49 - Séances
- 7:57 - Generable
- 14:29 - Schémas dynamiques
- 18:10 - Appel d’outils
Ressources
- Generate dynamic game content with guided generation and tools
- Human Interface Guidelines: Generative AI
Vidéos connexes
WWDC25
-
Rechercher dans cette vidéo…
-
-
1:05 - Prompting a session
import FoundationModels func respond(userInput: String) async throws -> String { let session = LanguageModelSession(instructions: """ You are a friendly barista in a world full of pixels. Respond to the player’s question. """ ) let response = try await session.respond(to: userInput) return response.content } -
3:37 - Handle context size errors
var session = LanguageModelSession() do { let answer = try await session.respond(to: prompt) print(answer.content) } catch LanguageModelSession.GenerationError.exceededContextWindowSize { // New session, without any history from the previous session. session = LanguageModelSession() } -
3:55 - Handling context size errors with a new session
var session = LanguageModelSession() do { let answer = try await session.respond(to: prompt) print(answer.content) } catch LanguageModelSession.GenerationError.exceededContextWindowSize { // New session, with some history from the previous session. session = newSession(previousSession: session) } private func newSession(previousSession: LanguageModelSession) -> LanguageModelSession { let allEntries = previousSession.transcript.entries var condensedEntries = [Transcript.Entry]() if let firstEntry = allEntries.first { condensedEntries.append(firstEntry) if allEntries.count > 1, let lastEntry = allEntries.last { condensedEntries.append(lastEntry) } } let condensedTranscript = Transcript(entries: condensedEntries) // Note: transcript includes instructions. return LanguageModelSession(transcript: condensedTranscript) } -
6:14 - Sampling
// Deterministic output let response = try await session.respond( to: prompt, options: GenerationOptions(sampling: .greedy) ) // Low-variance output let response = try await session.respond( to: prompt, options: GenerationOptions(temperature: 0.5) ) // High-variance output let response = try await session.respond( to: prompt, options: GenerationOptions(temperature: 2.0) ) -
7:06 - Handling languages
var session = LanguageModelSession() do { let answer = try await session.respond(to: userInput) print(answer.content) } catch LanguageModelSession.GenerationError.unsupportedLanguageOrLocale { // Unsupported language in prompt. } let supportedLanguages = SystemLanguageModel.default.supportedLanguages guard supportedLanguages.contains(Locale.current.language) else { // Show message return } -
8:14 - Generable
@Generable struct NPC { let name: String let coffeeOrder: String } func makeNPC() async throws -> NPC { let session = LanguageModelSession(instructions: ...) let response = try await session.respond(generating: NPC.self) { "Generate a character that orders a coffee." } return response.content } -
9:22 - NPC
@Generable struct NPC { let name: String let coffeeOrder: String } -
10:49 - Generable with enum
@Generable struct NPC { let name: String let encounter: Encounter @Generable enum Encounter { case orderCoffee(String) case wantToTalkToManager(complaint: String) } } -
11:20 - Generable with guides
@Generable struct NPC { @Guide(description: "A full name") let name: String @Guide(.range(1...10)) let level: Int @Guide(.count(3)) let attributes: [Attribute] let encounter: Encounter @Generable enum Attribute { case sassy case tired case hungry } @Generable enum Encounter { case orderCoffee(String) case wantToTalkToManager(complaint: String) } } -
13:40 - Regex guide
@Generable struct NPC { @Guide(Regex { Capture { ChoiceOf { "Mr" "Mrs" } } ". " OneOrMore(.word) }) let name: String } session.respond(to: "Generate a fun NPC", generating: NPC.self) // > {name: "Mrs. Brewster"} -
14:50 - Generable riddle
@Generable struct Riddle { let question: String let answers: [Answer] @Generable struct Answer { let text: String let isCorrect: Bool } } -
15:10 - Dynamic schema
struct LevelObjectCreator { var properties: [DynamicGenerationSchema.Property] = [] mutating func addStringProperty(name: String) { let property = DynamicGenerationSchema.Property( name: name, schema: DynamicGenerationSchema(type: String.self) ) properties.append(property) } mutating func addArrayProperty(name: String, customType: String) { let property = DynamicGenerationSchema.Property( name: name, schema: DynamicGenerationSchema( arrayOf: DynamicGenerationSchema(referenceTo: customType) ) ) properties.append(property) } var root: DynamicGenerationSchema { DynamicGenerationSchema( name: name, properties: properties ) } } var riddleBuilder = LevelObjectCreator(name: "Riddle") riddleBuilder.addStringProperty(name: "question") riddleBuilder.addArrayProperty(name: "answers", customType: "Answer") var answerBuilder = LevelObjectCreator(name: "Answer") answerBuilder.addStringProperty(name: "text") answerBuilder.addBoolProperty(name: "isCorrect") let riddleDynamicSchema = riddleBuilder.root let answerDynamicSchema = answerBuilder.root let schema = try GenerationSchema( root: riddleDynamicSchema, dependencies: [answerDynamicSchema] ) let session = LanguageModelSession() let response = try await session.respond( to: "Generate a fun riddle about coffee", schema: schema ) let generatedContent = response.content let question = try generatedContent.value(String.self, forProperty: "question") let answers = try generatedContent.value([GeneratedContent].self, forProperty: "answers") -
18:47 - FindContactTool
import FoundationModels import Contacts struct FindContactTool: Tool { let name = "findContact" let description = "Finds a contact from a specified age generation." @Generable struct Arguments { let generation: Generation @Generable enum Generation { case babyBoomers case genX case millennial case genZ } } func call(arguments: Arguments) async throws -> ToolOutput { let store = CNContactStore() let keysToFetch = [CNContactGivenNameKey, CNContactBirthdayKey] as [CNKeyDescriptor] let request = CNContactFetchRequest(keysToFetch: keysToFetch) var contacts: [CNContact] = [] try store.enumerateContacts(with: request) { contact, stop in if let year = contact.birthday?.year { if arguments.generation.yearRange.contains(year) { contacts.append(contact) } } } guard let pickedContact = contacts.randomElement() else { return ToolOutput("Could not find a contact.") } return ToolOutput(pickedContact.givenName) } } -
20:26 - Call FindContactTool
import FoundationModels let session = LanguageModelSession( tools: [FindContactTool()], instructions: "Generate fun NPCs" ) -
21:55 - FindContactTool with state
import FoundationModels import Contacts class FindContactTool: Tool { let name = "findContact" let description = "Finds a contact from a specified age generation." var pickedContacts = Set<String>() ... func call(arguments: Arguments) async throws -> ToolOutput { contacts.removeAll(where: { pickedContacts.contains($0.givenName) }) guard let pickedContact = contacts.randomElement() else { return ToolOutput("Could not find a contact.") } return ToolOutput(pickedContact.givenName) } } -
22:27 - GetContactEventTool
import FoundationModels import EventKit struct GetContactEventTool: Tool { let name = "getContactEvent" let description = "Get an event with a contact." let contactName: String @Generable struct Arguments { let day: Int let month: Int let year: Int } func call(arguments: Arguments) async throws -> ToolOutput { ... } }
-
-
- 0:00 - Introduction
Découvrez le framework de Foundation Models pour les appareils Apple, qui fournit un grand modèle de langage accessible via l’API Swift. Il explique comment utiliser Generable pour obtenir des résultats structurés, des schémas dynamiques et appeler des outils pour des fonctions personnalisées.
- 0:49 - Séances
Dans cet exemple, Foundation Models améliore un jeu de café en style pixel art en générant des dialogues et du contenu dynamiques. Grâce à la création d’une « LanguageModelSession », des instructions personnalisées sont fournies au modèle, ce qui lui permet de répondre aux questions des joueurs. Le modèle traite les entrées de l’utilisateur et les instructions de la séance en jetons, de petites sous-chaînes, qu’il utilise ensuite pour générer de nouvelles séquences de jetons en sortie. La « LanguageModelSession » est une session avec état qui enregistre toutes les invites et toutes les réponses dans une transcription. Vous pouvez utiliser cette transcription pour déboguer et afficher l’historique des conversations dans l’interface utilisateur du jeu. Cependant, la taille de la session est limitée, cette limite étant appelée « limite de contexte ». La génération des réponses n’est pas déterministe par défaut. Le modèle utilise l’échantillonnage, ce qui crée une distribution de probabilités pour chaque jeton et introduit ainsi un élément aléatoire. Ce caractère aléatoire peut être contrôlé à l’aide de l’API GenerationOptions, qui vous permet d’ajuster la méthode d’échantillonnage, la température ou même de la définir sur greedy pour obtenir un résultat déterministe. Foundation Models va bien plus loin que le simple dialogue : il peut créer des contenus élaborés, comme imaginer les goûts et les commandes de café des personnages non-joueurs (PNJ). Cette dimension enrichit considérablement l’univers du jeu. Elle lui donne vie et le rend plus immersif. Vous devez également tenir compte des problèmes potentiels, tels que les langues non prises en charge et les gérer de façon appropriée afin d’offrir une expérience utilisateur conviviale.
- 7:57 - Generable
L’API Generable de Foundation Models est un outil puissant qui simplifie l’obtention de données structurées à partir de grands modèles de langage. En ajoutant l’annotation @Generable aux structures et énumérations Swift, un schéma est automatiquement créé lors de la compilation, ce qui permet de définir la structure de sortie du modèle. Generable génère automatiquement un initialiseur et analyse le texte généré par le modèle pour le convertir en objets Swift de type sécurisé à l’aide d’un décodage limité. Cette méthode assure que les résultats générés par le modèle suivent parfaitement le schéma spécifié, ce qui permet d’éviter toute hallucination ou erreur dans la structure des données. Vous pouvez personnaliser la génération de données grâce aux « Guides », qui vous permettent d’établir des critères précis, des intervalles ou des descriptions en langage courant pour chaque propriété. Cette fonctionnalité vous offre un meilleur contrôle sur vos données, que ce soit pour définir des formats de noms, choisir le nombre de tableaux ou fixer des plages de valeurs. Grâce à Generable, générer des données devient un jeu d’enfant. Les développeurs peuvent ainsi se concentrer sur les éléments essentiels de leurs apps.
- 14:29 - Schémas dynamiques
Dans le créateur de niveaux du jeu, les schémas dynamiques permettent aux joueurs de définir des entités personnalisées lors de l’exécution. Ces schémas, similaires aux structures de compilation, possèdent des propriétés avec des noms et des types, ce qui permet d’utiliser des tableaux et des références à d’autres schémas dynamiques. À partir des informations fournies par le joueur, un schéma de devinette est créé avec une question (chaîne de caractères) et un ensemble de réponses (type personnalisé avec propriétés de chaîne de caractères et booléennes). Ces schémas dynamiques sont validés, puis utilisés pour générer du contenu par Foundation Models, ce qui garantit que le résultat correspond à la structure définie. Cette méthode interactive permet aux joueurs de partager leurs propres énigmes qui s’affichent de manière fluide dans le jeu. Le système offre ainsi une grande liberté créative tout en gardant une organisation claire des informations.
- 18:10 - Appel d’outils
Grâce à Foundation Models, les développeurs de jeux peuvent créer des DLC personnalisés à l’aide d’appels d’outils. Le modèle peut ainsi récupérer de manière autonome des informations sur l’appareil du joueur, telles que ses contacts et son calendrier, tout en préservant sa confidentialité, car les données ne quittent jamais l’appareil. La configuration d’un outil nécessite trois éléments essentiels : son nom, sa description et ses paramètres d’entrée. Ces informations permettent au modèle de comprendre quand il doit faire appel à l’outil et de quelle manière. Une fois activé, l’outil peut alors communiquer avec différentes API externes, comme Contacts API, pour extraire les informations souhaitées.