mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-17 14:58:00 +00:00
Added the exact token count for Anthropic and OpenAI (#1004)
Build and Release / Determine run mode (push) Has been cancelled
Build and Release / Verify (push) Has been cancelled
Build and Release / Read metadata (push) Has been cancelled
Build and Release / Sync Flatpak repo (push) Has been cancelled
Build and Release / Collect Flatpak artifacts (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Has been cancelled
Build and Release / Prepare & create release (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
Build and Release / Determine run mode (push) Has been cancelled
Build and Release / Verify (push) Has been cancelled
Build and Release / Read metadata (push) Has been cancelled
Build and Release / Sync Flatpak repo (push) Has been cancelled
Build and Release / Collect Flatpak artifacts (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Has been cancelled
Build and Release / Prepare & create release (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
This commit is contained in:
1 parent
0c585144e2
commit
4baf21656a
25 files changed
+837
-51
No files matched your search
@@ -0,0 +1,95 @@
|
||||
using System.Text.Json;
|
||||
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Provider.OpenAI;
|
||||
|
||||
namespace AIStudio.Tests.Provider;
|
||||
|
||||
/// <summary>
|
||||
/// Checks that what OpenAI says a Responses API call cost is read off the completed event, and only
|
||||
/// believed when it describes the request.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The completed event states the input of the whole response. That is the request as it was sent,
|
||||
/// unless OpenAI ran a hosted tool along the way: what such a tool found is charged as input of the
|
||||
/// same response, and no later request carries it. Believe the number then, and a single web search
|
||||
/// makes the chat look several times as large as it is.
|
||||
/// </remarks>
|
||||
[TestFixture]
|
||||
public sealed class ResponsesUsageTests
|
||||
{
|
||||
private const string COMPLETED_PREFIX = """{"type":"response.completed","sequence_number":42,"response":{"id":"resp_1","object":"response","status":"completed","model":"gpt-5","output":[""";
|
||||
private const string MESSAGE_ITEM = """{"id":"msg_1","type":"message","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Hi there!","annotations":[]}]}""";
|
||||
private const string USAGE_SUFFIX = ""","usage":{"input_tokens":2006,"input_tokens_details":{"cached_tokens":1920},"output_tokens":300,"output_tokens_details":{"reasoning_tokens":120},"total_tokens":2306}}}""";
|
||||
|
||||
[Test]
|
||||
public void TheCompletedEventStatesWhatTheRequestCarried()
|
||||
{
|
||||
//
|
||||
// The cached tokens are a share of the input tokens, not an addition to them: the request
|
||||
// carried 2,006 tokens, 1,920 of which came out of the cache.
|
||||
//
|
||||
var line = Read(COMPLETED_PREFIX + MESSAGE_ITEM + "]" + USAGE_SUFFIX);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(line.GetUsage().IsKnown, Is.True);
|
||||
Assert.That(line.GetUsage().PromptTokens, Is.EqualTo(2006));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReasoningAndFunctionCallsLeaveTheInputAlone()
|
||||
{
|
||||
//
|
||||
// Both are output the model wrote itself. Neither makes OpenAI add anything to the input,
|
||||
// and the function call's result comes back in the next request, which states its own.
|
||||
//
|
||||
var line = Read(COMPLETED_PREFIX +
|
||||
"""{"type":"reasoning","id":"rs_1","summary":[],"encrypted_content":"gAAAAAB0aXRs"},""" +
|
||||
"""{"type":"function_call","call_id":"call_1","name":"web_search","arguments":"{\"query\":\"weather\"}"}""" +
|
||||
"]" + USAGE_SUFFIX);
|
||||
|
||||
Assert.That(line.GetUsage().PromptTokens, Is.EqualTo(2006));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AHostedWebSearchStatesNothing()
|
||||
{
|
||||
//
|
||||
// OpenAI searched on its own, and what it found is part of the input tokens. The next
|
||||
// request carries none of it.
|
||||
//
|
||||
var line = Read(COMPLETED_PREFIX +
|
||||
"""{"type":"web_search_call","id":"ws_1","status":"completed","action":{"type":"search","query":"weather"}},""" +
|
||||
MESSAGE_ITEM +
|
||||
"]" + USAGE_SUFFIX);
|
||||
|
||||
Assert.That(line.GetUsage().IsKnown, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AnOutputItemNobodyKnowsStatesNothing()
|
||||
{
|
||||
//
|
||||
// A hosted tool OpenAI adds later is treated like the web search until somebody checked
|
||||
// what it does to the input.
|
||||
//
|
||||
var line = Read(COMPLETED_PREFIX +
|
||||
"""{"type":"future_tool_call","id":"ft_1","status":"completed"},""" +
|
||||
MESSAGE_ITEM +
|
||||
"]" + USAGE_SUFFIX);
|
||||
|
||||
Assert.That(line.GetUsage().IsKnown, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ACompletedEventWithoutAUsageStatesNothing()
|
||||
{
|
||||
var line = Read(COMPLETED_PREFIX + MESSAGE_ITEM + "]}}");
|
||||
|
||||
Assert.That(line.GetUsage().IsKnown, Is.False);
|
||||
}
|
||||
|
||||
private static ResponsesCompletedStreamLine Read(string data) => JsonSerializer.Deserialize<ResponsesCompletedStreamLine>(data, ProviderJsonOptions.OPTIONS)!;
|
||||
}
|
||||
Reference in new issue
Block a user