using AIStudio.Provider; namespace AIStudio.Models; /// /// Everything the app knows about one model. /// /// /// This is the answer the registry gives, and it is a struct on purpose. The question is asked from /// inside components which re-render on every streamed chunk, so an answer which allocates a list /// each time is an answer asked too often. Testing a capability is one bit test here, and because /// the value cannot be changed after it was built, the same answer can be handed to every caller. /// /// The reasoning question is answered by the Reasoning field alone. The three reasoning members of /// the capability enum are override vocabulary and are never part of Capabilities, so that the /// contradictory combinations of them cannot be expressed in a result at all. /// public readonly record struct ModelProfile { /// /// The three capability members which say something about reasoning. /// /// /// They are the vocabulary a person writes an override in, not something a profile carries. /// Kept here as one value so that the rule engine, the tests, and the verification run all mean /// the same three members by it. /// public const Capability REASONING_VOCABULARY = Capability.OPTIONAL_REASONING | Capability.ALWAYS_REASONING | Capability.REASONING_BY_DEFAULT; /// /// What we know about a model nobody has written a rule for. /// /// /// Nothing, which is what the default value of this type says already. Note that this still /// reports the model as a chat model: that is the deliberate fallback of ModelKind, because a /// model we fail to recognize has to stay visible to the user rather than disappear. /// public static readonly ModelProfile UNKNOWN = new(); /// /// What the model can do. /// public Capability Capabilities { get; init; } /// /// How the model reasons. /// public ReasoningSupport Reasoning { get; init; } /// /// What the model is made for. /// public ModelKind Kind { get; init; } /// /// How much the model can read and write in one conversation. /// public ContextWindow Context { get; init; } /// /// Which tokenizer counts this model's tokens. /// public TokenizerRef Tokenizer { get; init; } /// /// How many images the model accepts. /// public ImageLimits Images { get; init; } /// /// Whether the model has every one of the given capabilities. /// /// /// Asking for no capability at all is a mistake rather than a question with a trivial answer, /// which is why it says no: without that, a variable which happens to hold NONE would report /// every model as able to do it. /// /// One capability, or several combined with the or operator. /// True, when the model has all of them. public bool Has(Capability capability) => capability is not Capability.NONE && (this.Capabilities & capability) == capability; /// /// Whether the model has at least one of the given capabilities. /// /// Several capabilities combined with the or operator. /// True, when the model has any of them. public bool HasAny(Capability capabilities) => (this.Capabilities & capabilities) is not Capability.NONE; }