mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-17 19:38:00 +00:00
Added the exact token count where the provider reports it
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c95cc5bacc
commit
0aa3b23b81
21 files changed
+598
-7
No files matched your search
@@ -0,0 +1,81 @@
|
||||
namespace AIStudio.Provider;
|
||||
|
||||
/// <summary>
|
||||
/// What a provider said one request actually cost, in tokens.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The counterpart to what the app counts for itself: the app estimates what the next request will
|
||||
/// cost, while this is what the provider charged for the last one. Two different statements, and
|
||||
/// this one is the only exact one of the two.
|
||||
///
|
||||
/// Nothing here says "unknown" with a zero. The default value of this type is unknown, which is the
|
||||
/// right answer for every provider which reports nothing, and a counted request can never cost zero
|
||||
/// prompt tokens because the factory below refuses to build one.
|
||||
/// </remarks>
|
||||
public readonly record struct TokenUsage
|
||||
{
|
||||
/// <summary>
|
||||
/// The usage of a request nobody reported anything about.
|
||||
/// </summary>
|
||||
public static readonly TokenUsage UNKNOWN = new();
|
||||
|
||||
/// <summary>
|
||||
/// Whether a provider reported anything at all. When false, the numbers are meaningless.
|
||||
/// </summary>
|
||||
public bool IsKnown { get; private init; }
|
||||
|
||||
/// <summary>
|
||||
/// What everything sent to the model cost: the conversation so far, its attachments, the system
|
||||
/// prompt, and whatever tools were offered.
|
||||
/// </summary>
|
||||
public int PromptTokens { get; private init; }
|
||||
|
||||
/// <summary>
|
||||
/// What the model wrote in answer.
|
||||
/// </summary>
|
||||
public int CompletionTokens { get; private init; }
|
||||
|
||||
/// <summary>
|
||||
/// What the whole exchange cost, which is what the next request carries as its history.
|
||||
/// </summary>
|
||||
public int TotalTokens => this.PromptTokens + this.CompletionTokens;
|
||||
|
||||
/// <summary>
|
||||
/// States what a provider reported.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A completion of zero tokens is a real answer: a model which was cut off before writing
|
||||
/// anything still cost its prompt. A prompt of zero is not, because there is no request
|
||||
/// without one, and a provider sending it means we read the wrong field.
|
||||
/// </remarks>
|
||||
/// <param name="promptTokens">What the request carried. Has to be greater than zero.</param>
|
||||
/// <param name="completionTokens">What the answer cost. Zero or more.</param>
|
||||
/// <returns>The usage.</returns>
|
||||
public static TokenUsage Of(int promptTokens, int completionTokens)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(promptTokens);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(completionTokens);
|
||||
|
||||
return new()
|
||||
{
|
||||
IsKnown = true,
|
||||
PromptTokens = promptTokens,
|
||||
CompletionTokens = completionTokens,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// States what a provider reported, or unknown when it reported nothing usable.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For the reading side, where the numbers come out of somebody else's JSON: a missing field, a
|
||||
/// null, or a zero prompt all mean the same thing there, and none of them is worth an exception.
|
||||
/// </remarks>
|
||||
/// <param name="promptTokens">What the request carried, as the provider stated it.</param>
|
||||
/// <param name="completionTokens">What the answer cost, as the provider stated it.</param>
|
||||
/// <returns>The usage, or <see cref="UNKNOWN"/>.</returns>
|
||||
public static TokenUsage OfReported(int? promptTokens, int? completionTokens) =>
|
||||
promptTokens is > 0
|
||||
? Of(promptTokens.Value, completionTokens is > 0 ? completionTokens.Value : 0)
|
||||
: UNKNOWN;
|
||||
}
|
||||
Reference in new issue
Block a user