-
Aprofunde-se no framework Foundation Models
Aprimore seus projetos com o framework Foundation Models. Saiba como a geração guiada funciona na parte interna e use guias, expressões regulares e esquemas de geração para obter respostas estruturadas personalizadas. Mostraremos como usar a chamada de ferramentas para permitir que o modelo acesse informações externas de maneira autônoma e como executar ações para criar uma experiência personalizada.
Para aproveitar ao máximo este vídeo, recomendamos assistir primeiro ao à sessão "Conheça o framework Foundation Models".Capítulos
- 0:00 - Introdução
- 0:49 - Sessões
- 7:57 - API Generable
- 14:29 - Esquemas dinâmicos
- 18:10 - Chamada de ferramentas
Recursos
- Generate dynamic game content with guided generation and tools
- Human Interface Guidelines: Generative AI
Vídeos relacionados
WWDC25
-
Buscar neste vídeo...
-
-
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 - Introdução
Saiba mais sobre o framework Foundation Models para dispositivos Apple, que fornece um LLM (grande modelo de linguagem) no dispositivo, acessível pela API Swift. A sessão aborda como usar Generable para obter um resultado estruturado, esquemas dinâmicos e chamadas de ferramentas para funções personalizadas.
- 0:49 - Sessões
Neste exemplo, o Foundation Models aprimora um jogo de pixel art sobre uma cafeteria gerando conteúdo e diálogos dinâmicos para o jogo. Ao criar uma LanguageModelSession, instruções personalizadas são fornecidas ao modelo, permitindo que ele responda às perguntas do jogador. O modelo transforma instruções da sessão e de entrada do usuário em tokens, pequenas substrings, que ele usa para gerar novas sequências de tokens como saída. A LanguageModelSession é stateful, gravando todos os prompts e respostas em uma transcrição. Você pode usar essa transcrição para depurar e exibir o histórico de conversas na interface do jogo. No entanto, há um limite para o tamanho da sessão, conhecido como limite de contexto. A geração de respostas não é determinística por padrão. O modelo usa amostragem, criando uma distribuição de probabilidades para cada token, o que insere aleatoriedade. A API GenerationOptions permite controlar a aleatoriedade, ajustando o método de amostragem e a temperatura ou configurando-a como greedy para saída determinística. Além da caixa de diálogo simples, o Foundation Models pode ser empregado para gerar resultados mais complexos, como nomes e pedidos de café para NPCs (personagens não jogáveis). Isso adiciona profundidade e variedade ao mundo do jogo, tornando-o mais vivo e interativo. Você também deve considerar possíveis problemas, como idiomas em que o app não está disponível, e resolvê-los para fornecer uma experiência melhor ao usuário.
- 7:57 - API Generable
A API Generable do Foundation Models é uma ferramenta que simplifica a obtenção de dados estruturados dos LLM (grandes modelos de linguagem). Ao aplicar a macro @Generable a structs ou enums do Swift, um esquema é gerado em tempo de compilação, orientando o resultado do modelo. O Generable gera automaticamente um inicializador e cuida da conversão do texto gerado pelo modelo em objetos Swift que independem de tipo usando decodificação restrita. Essa técnica garante que o resultado do modelo siga o esquema especificado, evitando alucinações e erros estruturais. Você pode personalizar ainda mais o processo usando Guias, que fornecem restrições, intervalos ou descrições de linguagem natural para propriedades específicas. Isso permite mais controle sobre os dados gerados, como especificar formatos de nome, contagens de matrizes ou intervalos numéricos. O Generable permite a geração de dados eficiente e confiável, liberando desenvolvedores para focar aspectos mais complexos dos apps.
- 14:29 - Esquemas dinâmicos
No criador de níveis do jogo, os esquemas dinâmicos permitem que os jogadores definam entidades personalizadas no tempo de execução. Esses esquemas, semelhantes a structs em tempo de compilação, têm propriedades com nomes e tipos, permitindo matrizes e referências a outros esquemas dinâmicos. Na entrada do jogador, um esquema de enigma é criado com uma pergunta (string) e uma matriz de respostas (tipo personalizado com string e propriedades booleanas). Esses esquemas são validados e depois usados para gerar conteúdo pelo Foundation Models, garantindo que o resultado corresponda à estrutura definida. Essa abordagem dinâmica permite que o jogo exiba enigmas criados pelo jogador e outras entidades em uma interface dinâmica, oferecendo alto grau de flexibilidade e criatividade para os jogadores enquanto mantém o processamento de dados estruturados.
- 18:10 - Chamada de ferramentas
Com o Foundation Models, os desenvolvedores podem criar conteúdo para DLC personalizado usando chamadas de ferramentas. Assim, o modelo pode buscar informações de forma autônoma do dispositivo do jogador, como contatos e calendário, preservando a privacidade, pois os dados nunca saem do dispositivo. Definir uma ferramenta envolve especificar nome, descrição e argumentos de entrada. O modelo usa essas informações para decidir quando e como chamar a ferramenta. A implementação da ferramenta interage com APIs externas, como a Contacts API, para recuperar dados.