using AIStudio.Provider; namespace AIStudio.Chat; /// /// What a provider said the request behind one answer cost, as it is stored on that answer. /// /// /// The numbers and the model they were charged for travel as one value. Each of them is meaningless /// without the others, and loose fields on the answer could be set, cleared, or copied apart. /// /// Plain numbers rather than a TokenUsage: that type only ever comes out of its own factory, which /// is what keeps an impossible usage from existing, while a stored value has to be readable back by /// the serializer. ToTokenUsage is the way back, and it treats a chat file somebody edited by hand /// the same way the reading side treats a provider's JSON. /// public sealed record ReportedTokenUsage { /// /// What everything sent to the model cost. /// public int PromptTokens { get; init; } /// /// What the model wrote in answer. /// public int CompletionTokens { get; init; } /// /// Which model the numbers were charged for. /// /// /// A token count belongs to the tokenizer which produced it. Switch the model of a chat, and /// the same conversation is worth a different number of tokens -- so the reported one stops /// being an answer about the request which is about to be sent, and the estimate, wrong as it /// is, is at least wrong about the right model. /// public string ModelId { get; init; } = string.Empty; /// /// States the stored numbers as a usage again. /// /// The usage, or TokenUsage.UNKNOWN when the stored numbers state nothing usable. public TokenUsage ToTokenUsage() => TokenUsage.OfReported(this.PromptTokens, this.CompletionTokens); }