@@ -159,7 +159,7 @@ public static void CreateJsonSchema_DefaultParameters_GeneratesExpectedJsonSchem
159159
160160 JsonElement actual = AIJsonUtilities . CreateJsonSchema ( typeof ( MyPoco ) , serializerOptions : JsonContext . Default . Options ) ;
161161
162- Assert . True ( DeepEquals ( expected , actual ) ) ;
162+ AssertDeepEquals ( expected , actual ) ;
163163 }
164164
165165 [ Fact ]
@@ -204,7 +204,7 @@ public static void CreateJsonSchema_OverriddenParameters_GeneratesExpectedJsonSc
204204 serializerOptions : JsonContext . Default . Options ,
205205 inferenceOptions : inferenceOptions ) ;
206206
207- Assert . True ( DeepEquals ( expected , actual ) ) ;
207+ AssertDeepEquals ( expected , actual ) ;
208208 }
209209
210210 [ Fact ]
@@ -249,7 +249,7 @@ public static void CreateJsonSchema_UserDefinedTransformer()
249249
250250 JsonElement actual = AIJsonUtilities . CreateJsonSchema ( typeof ( MyPoco ) , serializerOptions : JsonContext . Default . Options , inferenceOptions : inferenceOptions ) ;
251251
252- Assert . True ( DeepEquals ( expected , actual ) ) ;
252+ AssertDeepEquals ( expected , actual ) ;
253253 }
254254
255255 [ Fact ]
@@ -277,7 +277,7 @@ public static void CreateJsonSchema_FiltersDisallowedKeywords()
277277
278278 JsonElement actual = AIJsonUtilities . CreateJsonSchema ( typeof ( PocoWithTypesWithOpenAIUnsupportedKeywords ) , serializerOptions : JsonContext . Default . Options ) ;
279279
280- Assert . True ( DeepEquals ( expected , actual ) ) ;
280+ AssertDeepEquals ( expected , actual ) ;
281281 }
282282
283283 public class PocoWithTypesWithOpenAIUnsupportedKeywords
@@ -301,7 +301,67 @@ public static void CreateFunctionJsonSchema_ReturnsExpectedValue()
301301 Assert . NotNull ( func . UnderlyingMethod ) ;
302302
303303 JsonElement resolvedSchema = AIJsonUtilities . CreateFunctionJsonSchema ( func . UnderlyingMethod , title : func . Name ) ;
304- Assert . True ( DeepEquals ( resolvedSchema , func . JsonSchema ) ) ;
304+ AssertDeepEquals ( resolvedSchema , func . JsonSchema ) ;
305+ }
306+
307+ [ Theory ]
308+ [ InlineData ( true ) ]
309+ [ InlineData ( false ) ]
310+ public static void CreateFunctionJsonSchema_OptionalParameters ( bool requireAllProperties )
311+ {
312+ string unitJsonSchema = requireAllProperties ? """
313+ {
314+ "description": "The unit to calculate the current temperature to (Default value: \u0022celsius\u0022)",
315+ "type": "string"
316+ }
317+ """ :
318+ """
319+ {
320+ "description": "The unit to calculate the current temperature to",
321+ "type": "string",
322+ "default": "celsius"
323+ }
324+ """ ;
325+
326+ string requiredParamsJsonSchema = requireAllProperties ?
327+ """["city", "unit"]""" :
328+ """["city"]""" ;
329+
330+ JsonElement expected = JsonDocument . Parse ( $$ """
331+ {
332+ "title": "get_weather",
333+ "description": "Gets the current weather for a current location",
334+ "type": "object",
335+ "properties": {
336+ "city": {
337+ "description": "The city to get the weather for",
338+ "type": "string"
339+ },
340+ "unit": {{ unitJsonSchema }}
341+ },
342+ "required": {{ requiredParamsJsonSchema }}
343+ }
344+ """ ) . RootElement ;
345+
346+ AIFunction func = AIFunctionFactory . Create ( (
347+ [ Description ( "The city to get the weather for" ) ] string city ,
348+ [ Description ( "The unit to calculate the current temperature to" ) ] string unit = "celsius" ) => "sunny" ,
349+ new AIFunctionFactoryOptions
350+ {
351+ Name = "get_weather" ,
352+ Description = "Gets the current weather for a current location" ,
353+ JsonSchemaCreateOptions = new AIJsonSchemaCreateOptions { RequireAllProperties = requireAllProperties }
354+ } ) ;
355+
356+ Assert . NotNull ( func . UnderlyingMethod ) ;
357+ AssertDeepEquals ( expected , func . JsonSchema ) ;
358+
359+ JsonElement resolvedSchema = AIJsonUtilities . CreateFunctionJsonSchema (
360+ func . UnderlyingMethod ,
361+ title : func . Name ,
362+ description : func . Description ,
363+ inferenceOptions : new AIJsonSchemaCreateOptions { RequireAllProperties = requireAllProperties } ) ;
364+ AssertDeepEquals ( expected , resolvedSchema ) ;
305365 }
306366
307367 [ Fact ]
@@ -331,7 +391,7 @@ public static void CreateFunctionJsonSchema_TreatsIntegralTypesAsInteger_EvenWit
331391 """ ) . RootElement ;
332392
333393 JsonElement actualSchema = property . Value ;
334- Assert . True ( DeepEquals ( expected , actualSchema ) ) ;
394+ AssertDeepEquals ( expected , actualSchema ) ;
335395 i ++ ;
336396 }
337397 }
@@ -514,4 +574,17 @@ private static bool DeepEquals(JsonElement element1, JsonElement element2)
514574 JsonSerializer . SerializeToNode ( element2 , AIJsonUtilities . DefaultOptions ) ) ;
515575#endif
516576 }
577+
578+ private static void AssertDeepEquals ( JsonElement element1 , JsonElement element2 )
579+ {
580+ #pragma warning disable SA1118 // Parameter should not span multiple lines
581+ Assert . True ( DeepEquals ( element1 , element2 ) , $ """
582+ Elements are not equal.
583+ Expected:
584+ { element1 }
585+ Actual:
586+ { element2 }
587+ """ ) ;
588+ #pragma warning restore SA1118 // Parameter should not span multiple lines
589+ }
517590}
0 commit comments