Class ValueObjectAIExtensions
Namespace: AdCodicem.ValueObjects.AI
Assembly: AdCodicem.ValueObjects.AI.dll
Describes value objects in the schemas Microsoft.Extensions.AI publishes, and answers a model that sends one a value its rules refuse with the rule, not with an exception the model never sees.
public static class ValueObjectAIExtensions
Inheritance
object ← ValueObjectAIExtensions
Inherited Members
object.Equals(object?), object.Equals(object?, object?), object.GetHashCode(), object.GetType(), object.MemberwiseClone(), object.ReferenceEquals(object?, object?), object.ToString()
Remarks
AIFunctionFactory describes a tool's parameters from their JsonTypeInfo, and a value object, serialized
by a converter of its own, has none to read: each value-object parameter is published as true, the schema that
accepts anything, and the model has to guess its length, pattern, bounds and allowed values. Binding still validates
each argument, through the generated converter, but FunctionInvokingChatClient answers the exception it throws
with "Error: Function failed.", which tells the model nothing it can correct. The two calls together close both gaps:
AIFunction placeOrder = AIFunctionFactory.Create(
tools.PlaceOrder,
new AIFunctionFactoryOptions { JsonSchemaCreateOptions = new AIJsonSchemaCreateOptions().WithValueObjects() })
.WithValueObjectValidation();
Where reflection-based serialization is disabled, as native AOT disables it, the factory's default options describe
no value object at all, and refuse to: hand it SerializerOptions whose resolver is a source-generated context
naming
Methods
WithValueObjectValidation(AIFunction)
Wraps a function so that an argument a value object refuses is answered with its rule, not an exception.
public static AIFunction WithValueObjectValidation(this AIFunction function)
Parameters
function AIFunction
The function, built from a method by
Returns
AIFunction
The wrapping function, or function itself when it wraps one already.
Remarks
Before the function binds its arguments, each argument of a value-object parameter is read as the binding reads it,
through the contract the function's serializer options hold for the parameter, which runs the value object's
converter and its rules. The first refused, in the order of the parameters, is returned instead of calling the
function, as a JSON object FunctionInvokingChatClient hands the model as it is:
{"error":"invalid_argument","argument":"quantity","code":"value_object.out_of_range","message":"The value is not a valid Quantity: The value must be less than or equal to 100."}
The message is the converter's, which names the value object and the rule, never the value sent; where the
converter leaves it to System.Text.Json, for a number its underlying type cannot hold, or where a converter of the
application's own refuses the value with an exception of its own, it is The value is not a valid Quantity.,
naming the value object alone. An argument the value object cannot read at all is value_object.not_parsable, unless a
converter of the application's own carries a code; an absent one the parameter has no default for, and a
null for a value object that cannot be null, which the binding would pass on as an
uninitialized instance, are value_object.required. A collection, a dictionary or an object is read the same
way, and answered for a value object it holds, under the parameter's name; any other error is left to the
function, which throws it as it would without the wrapper.
An instance of the parameter's type is passed on as it is. Text or a number, which the binding converts through a JSON round trip of its own rather than refuses, is read as the binding converts it: text that may be JSON as JSON first, then the value written through the contract of its own type and read back; it is refused only when neither reading takes it.
The parameters are read from BindParameter callback binds, while
the schema still lists it, is read as the serializer would read it.
Exceptions
function is null.
WithValueObjects(AIJsonSchemaCreateOptions?)
Returns a copy of the options whose
public static AIJsonSchemaCreateOptions WithValueObjects(this AIJsonSchemaCreateOptions? options)
Parameters
options AIJsonSchemaCreateOptions?
The options to copy, or null for
Returns
AIJsonSchemaCreateOptions
A copy of the options, every other setting kept; the options given are left as they are.
Remarks
Each value object, alone, nullable, or held by a collection, a dictionary or an object, is described as its
underlying value under enum, a date bound as a sentence of the
description, its description after the one a [Description] gives the parameter, and its example; a format
JSON Schema does not define moves into the description. A transform the options already carry runs first, and
this one completes what it wrote.
Under OpenAI's strict mode, Microsoft.Extensions.AI.OpenAI moves the lengths, the pattern, the bounds and the
format into the description, and keeps type, enum and examples: the rules still reach the
model.