Skip to main content
La meilleure raison d’utiliser Foundation Models dans une app Swift est souvent ici : vous pouvez demander des objets Swift plutôt qu’un bloc de texte à parser. Cette approche rend l’intégration plus robuste et plus simple à maintenir.

Ce que décrivent @Generable et @Guide

Apple expose Generable comme le contrat de sortie que le modèle doit remplir. @Guide n’est pas un simple commentaire : il influence les valeurs que le modèle essaie de produire pour chaque propriété. En pratique :
  • @Generable décrit la forme de l’objet Swift attendu.
  • @Guide(description:) explique le sens métier d’un champ.
  • @Guide(..., .anyOf / .range / .minimumCount) resserre l’espace des valeurs possibles.
import FoundationModels

@Generable
struct TicketLabel {
    @Guide(description: "Niveau de priorité", .anyOf(["basse", "moyenne", "haute"]))
    var priority: String = ""
}
Plus ce contrat est clair, moins vous aurez besoin de parser ou de corriger le résultat après coup.

Pourquoi c’est utile

Si votre UI attend :
  • un titre
  • un résumé
  • une liste d’actions
  • une priorité
le texte libre devient vite fragile. Guided Generation vous permet de générer directement un type Swift.

Définir un type @Generable

import FoundationModels

@Generable
struct FeaturePlan {
    @Guide(description: "Un titre court")
    var title: String = ""

    @Guide(description: "Un résumé en une phrase")
    var summary: String = ""

    @Guide(description: "Entre 2 et 5 actions concrètes", .minimumCount(2))
    var nextSteps: [String] = []
}
Le rôle de @Guide est d’aider le modèle à comprendre ce que vous attendez pour chaque propriété. Autrement dit, @Generable dit “quelle forme doit sortir”, et @Guide dit “quelles valeurs ont du sens pour cette propriété”.

Générer ce type

let session = LanguageModelSession(
    instructions: "You help Swift developers plan AI features."
)

let result = try await session.respond(
    to: "Propose un plan simple pour ajouter un résumé de texte dans une app iOS.",
    generating: FeaturePlan.self
)

let plan = result.content
print(plan.title)
print(plan.nextSteps)
Vous obtenez un FeaturePlan, pas une chaîne.

Ajouter des contraintes utiles

Vous pouvez guider davantage la génération :
@Generable
struct ModelChoice {
    @Guide(description: "Nom du modèle conseillé")
    var model: String = ""

    @Guide(description: "Taille estimée en Go", .range(1...40))
    var estimatedSizeGB: Int = 0

    @Guide(description: "Niveau recommandé", .anyOf(["debutant", "intermediaire", "avance"]))
    var audience: String = ""
}
Ces contraintes ne remplacent pas un vrai contrôle métier, mais elles améliorent la stabilité du résultat.

Types imbriqués

Vous pouvez aussi structurer plusieurs niveaux :
@Generable
struct ActionItem {
    @Guide(description: "Action à effectuer")
    var title: String = ""

    @Guide(description: "Priorité", .anyOf(["basse", "moyenne", "haute"]))
    var priority: String = ""
}

@Generable
struct SprintPlan {
    @Guide(description: "Objectif du sprint")
    var goal: String = ""

    @Guide(description: "Liste des actions")
    var items: [ActionItem] = []
}
Cette forme est idéale dès que votre UI affiche plusieurs champs.

Quand préférer la sortie structurée

Préférez Guided Generation si :
  • vous affichez plusieurs champs distincts
  • vous stockez le résultat
  • vous devez piloter une logique métier
  • vous voulez éviter de parser du Markdown ou du texte libre
Restez sur du texte libre si la réponse doit seulement être lue telle quelle par l’utilisateur.

À garder en tête

Le type fait partie du prompt implicite

Plus votre type et vos @Guide sont clairs, plus la sortie sera stable.

Gardez les types simples au début

Commencez avec peu de propriétés. Complexifiez ensuite seulement si le besoin est réel.

Gérez l’échec de décodage

Même avec un bon schéma, une génération structurée peut échouer. Gérez ce cas dans votre flux d’erreur.

Streaming structuré

Foundation Models prend aussi en charge le streaming pour la sortie structurée. C’est utile si vous voulez remplir progressivement une vue complexe. Vous verrez ce pattern plus loin dans la page Streaming & UX.