@@ -95,4 +95,94 @@ struct GenerativeModelSessionTests {
9595 #expect( catProfile. age <= 20 )
9696 #expect( !catProfile. profile. isEmpty)
9797 }
98+
99+ @Generable
100+ @available ( iOS 26 . 0 , macOS 26 . 0 , * )
101+ @available ( tvOS, unavailable)
102+ @available ( watchOS, unavailable)
103+ enum Difficulty : String , Codable , CaseIterable {
104+ case easy
105+ case medium
106+ case hard
107+ }
108+
109+ @Generable ( description: " A recipe for a delicious dish " )
110+ @available ( iOS 26 . 0 , macOS 26 . 0 , * )
111+ @available ( tvOS, unavailable)
112+ @available ( watchOS, unavailable)
113+ struct Recipe {
114+ @Guide ( description: " The name of the dish " )
115+ var name : String
116+
117+ @Guide ( description: " The time it takes to prepare the dish in minutes " , . range( 5 ... 120 ) )
118+ var preparationTime : Int
119+
120+ @Guide ( description: " Whether the dish is vegetarian " )
121+ var isVegetarian : Bool
122+
123+ @Guide ( description: " The rating of the dish from 1.0 to 5.0 " , . range( 1.0 ... 5.0 ) )
124+ var rating : Double
125+
126+ @Guide ( description: " A list of ingredients " )
127+ var ingredients : [ String ]
128+
129+ @Guide ( description: " The difficulty of the recipe " )
130+ var difficulty : Difficulty
131+ }
132+
133+ @Generable ( description: " A list of recipes " )
134+ @available ( iOS 26 . 0 , macOS 26 . 0 , * )
135+ @available ( tvOS, unavailable)
136+ @available ( watchOS, unavailable)
137+ struct RecipeList {
138+ @Guide ( description: " A list of recipes for a three-course meal. " )
139+ var recipes : [ Recipe ]
140+ }
141+
142+ @Test ( arguments: [ InstanceConfig . vertexAI_v1beta_global] )
143+ @available ( iOS 26 . 0 , macOS 26 . 0 , * )
144+ @available ( tvOS, unavailable)
145+ @available ( watchOS, unavailable)
146+ func respondGenerableRecipe( _ config: InstanceConfig ) async throws {
147+ let model = FirebaseAI . componentInstance ( config) . generativeModel (
148+ modelName: ModelNames . gemini2_5_FlashLite,
149+ )
150+ let session = GenerativeModelSession ( model: model)
151+ let prompt = " Generate a recipe for a vegetarian pasta dish. "
152+
153+ let response = try await session. respond ( to: prompt, generating: Recipe . self)
154+
155+ let recipe = response. content
156+ #expect( !recipe. name. isEmpty)
157+ #expect( recipe. preparationTime >= 5 )
158+ #expect( recipe. preparationTime <= 120 )
159+ #expect( recipe. isVegetarian == true )
160+ #expect( recipe. rating >= 1.0 )
161+ #expect( recipe. rating <= 5.0 )
162+ #expect( !recipe. ingredients. isEmpty)
163+ }
164+
165+ @Test ( arguments: [ InstanceConfig . vertexAI_v1beta_global] )
166+ @available ( iOS 26 . 0 , macOS 26 . 0 , * )
167+ @available ( tvOS, unavailable)
168+ @available ( watchOS, unavailable)
169+ func respondGenerableRecipeList( _ config: InstanceConfig ) async throws {
170+ let model = FirebaseAI . componentInstance ( config) . generativeModel (
171+ modelName: ModelNames . gemini2_5_FlashLite,
172+ )
173+ let session = GenerativeModelSession ( model: model)
174+ let prompt =
175+ " Generate three recipes for a full-course vegetarian meal (appetizer, main, dessert). "
176+
177+ let response = try await session. respond ( to: prompt, generating: RecipeList . self)
178+
179+ let recipeList = response. content
180+ #expect( recipeList. recipes. count == 3 )
181+ for recipe in recipeList. recipes {
182+ #expect( !recipe. name. isEmpty)
183+ #expect( recipe. preparationTime >= 5 )
184+ #expect( recipe. preparationTime <= 120 )
185+ #expect( !recipe. ingredients. isEmpty)
186+ }
187+ }
98188}
0 commit comments