using AIStudio.Provider; namespace AIStudio.Models; /// /// What a rule states about a model, as a change to what is known so far. /// /// /// A selector applies its change to nothing and so states a whole profile; a modifier applies its /// change to whatever the selector decided. One type for both, because "adds web search" and "takes /// web search away again" are the same kind of sentence. /// /// Everything left unsaid stays as it was. That is what lets a rule for a variant say only what /// makes the variant different, instead of repeating the family it belongs to. /// public sealed record ModelProfileChange { /// /// A change which states nothing. /// public static readonly ModelProfileChange NOTHING = new(); /// /// Capabilities the model has. /// public Capability Adds { get; init; } /// /// Capabilities the model does not have, applied after the ones it has. /// public Capability Removes { get; init; } /// /// How the model reasons, or null to leave that as it was. /// public ReasoningSupport? Reasoning { get; init; } /// /// What the model is made for, or null to leave that as it was. /// public ModelKind? Kind { get; init; } /// /// The context window, or null to leave it as it was. /// public ContextWindow? Context { get; init; } /// /// The tokenizer reference, or null to leave it as it was. /// public TokenizerRef? Tokenizer { get; init; } /// /// The image limits, or null to leave them as they were. /// public ImageLimits? Images { get; init; } /// /// Applies this change to a profile. /// /// /// The three reasoning members of the capability enum are dropped here rather than trusted to /// stay out: they are the vocabulary a person writes an override in, and a profile which /// carried them could say that a model both always reasons and reasons on request. A rule which /// declares one has still made a mistake, which is why the tests and the verification run look /// for it instead of relying on this line to hide it. /// /// Every member of a profile is named below, so the copy could be written as a new profile /// instead. It stays a copy on purpose: the day a profile learns something this change does not /// know about yet, a modifier has to hand that on rather than reset it to nothing. /// /// What is known so far. /// What is known afterward. // ReSharper disable once WithExpressionModifiesAllMembers public ModelProfile ApplyTo(in ModelProfile profile) => profile with { Capabilities = (profile.Capabilities | this.Adds) & ~this.Removes & ~ModelProfile.REASONING_VOCABULARY, Reasoning = this.Reasoning ?? profile.Reasoning, Kind = this.Kind ?? profile.Kind, Context = this.Context ?? profile.Context, Tokenizer = this.Tokenizer ?? profile.Tokenizer, Images = this.Images ?? profile.Images, }; }