diff --git a/Anthropic.SDK.Tests/CacheControlTests.cs b/Anthropic.SDK.Tests/CacheControlTests.cs index 6719b29..ba8f364 100644 --- a/Anthropic.SDK.Tests/CacheControlTests.cs +++ b/Anthropic.SDK.Tests/CacheControlTests.cs @@ -236,6 +236,11 @@ public async Task TestCacheControlStreaming() Assert.IsTrue(messageResponses.First().StreamStartMessage.Usage.CacheCreationInputTokens > 0 || messageResponses.First().StreamStartMessage.Usage.CacheReadInputTokens > 0); + if (messageResponses.First().StreamStartMessage.Usage.CacheCreationInputTokens > 0) + { + Assert.IsTrue(messageResponses.First().StreamStartMessage.Usage.CacheCreation.Ephemeral5mInputTokens > 0); + } + messages.Add(new Message(messageResponses)); messages.Add(new Message(RoleType.User, "Who is the main character and how old is he?")); @@ -487,7 +492,11 @@ public async Task TestCacheControlOfAssistantMessages() var systemMessages = new List() { new SystemMessage("You are an expert at analyzing literary texts."), - new SystemMessage(content, new CacheControl() { Type = CacheControlType.ephemeral }) + new SystemMessage(content, new CacheControl() + { + Type = CacheControlType.ephemeral, + TTL = CacheDuration.OneHour, + }) }; var parameters = new MessageParameters() { @@ -505,7 +514,11 @@ public async Task TestCacheControlOfAssistantMessages() Assert.IsTrue(res.Usage.CacheCreationInputTokens > 0 || res.Usage.CacheReadInputTokens > 0); //try caching an assistant message - res.Message.Content.First().CacheControl = new CacheControl() { Type = CacheControlType.ephemeral }; + res.Message.Content.First().CacheControl = new CacheControl() + { + Type = CacheControlType.ephemeral, + TTL = CacheDuration.OneHour, + }; messages.Add(res.Message); messages.Add(new Message(RoleType.User, "Who is the main character and how old is he?")); @@ -513,7 +526,8 @@ public async Task TestCacheControlOfAssistantMessages() var res2 = await client.Messages.GetClaudeMessageAsync(parameters); Assert.IsTrue(res2.Usage.CacheReadInputTokens > 0); - + Assert.IsNotNull(res2.Usage.CacheCreation); + Assert.IsTrue(res2.Usage.CacheCreation.Ephemeral1hInputTokens > 0); Assert.IsNotNull(res2.Message.ToString()); //message 3 diff --git a/Anthropic.SDK.Tests/DocumentTests.cs b/Anthropic.SDK.Tests/DocumentTests.cs index dea21e3..b84381a 100644 --- a/Anthropic.SDK.Tests/DocumentTests.cs +++ b/Anthropic.SDK.Tests/DocumentTests.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; +using System.Reflection; using Anthropic.SDK.Constants; using Anthropic.SDK.Messaging; @@ -41,7 +35,8 @@ public async Task TestPDF() }, CacheControl = new CacheControl() { - Type = CacheControlType.ephemeral + Type = CacheControlType.ephemeral, + TTL = CacheDuration.FiveMinutes, } }), new Message(RoleType.User, "Which model has the highest human preference win rates across each use-case?"), @@ -60,8 +55,11 @@ public async Task TestPDF() Assert.IsNotNull(res.FirstMessage.ToString()); Assert.IsTrue(res.Usage.CacheCreationInputTokens > 0 || res.Usage.CacheReadInputTokens > 0); - - + if (res.Usage.CacheCreationInputTokens > 0) + { + Assert.IsNotNull(res.Usage.CacheCreation); + Assert.IsTrue(res.Usage.CacheCreation.Ephemeral5mInputTokens > 0); + } } [TestMethod] diff --git a/Anthropic.SDK/Messaging/CacheControl.cs b/Anthropic.SDK/Messaging/CacheControl.cs index 35cb195..e915474 100644 --- a/Anthropic.SDK/Messaging/CacheControl.cs +++ b/Anthropic.SDK/Messaging/CacheControl.cs @@ -6,6 +6,14 @@ public class CacheControl { [JsonPropertyName("type")] public CacheControlType Type { get; set; } + + /// + /// The duration to cache. + /// Supported values are or + /// + [JsonPropertyName("ttl")] + [JsonConverter(typeof(CacheDurationConverter))] + public CacheDuration TTL { get; set; } } [JsonConverter(typeof(JsonStringEnumConverter))] diff --git a/Anthropic.SDK/Messaging/CacheDurationConverter.cs b/Anthropic.SDK/Messaging/CacheDurationConverter.cs new file mode 100644 index 0000000..702c3eb --- /dev/null +++ b/Anthropic.SDK/Messaging/CacheDurationConverter.cs @@ -0,0 +1,36 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Anthropic.SDK.Messaging; + +public enum CacheDuration +{ + FiveMinutes, + OneHour +} + +public class CacheDurationConverter : JsonConverter +{ + public override CacheDuration Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + string? value = reader.GetString(); + return value switch + { + "5m" => CacheDuration.FiveMinutes, + "1h" => CacheDuration.OneHour, + _ => throw new JsonException($"Invalid cache duration: {value}") + }; + } + + public override void Write(Utf8JsonWriter writer, CacheDuration value, JsonSerializerOptions options) + { + string str = value switch + { + CacheDuration.FiveMinutes => "5m", + CacheDuration.OneHour => "1h", + _ => throw new JsonException($"Invalid cache duration enum: {value}") + }; + writer.WriteStringValue(str); + } +} \ No newline at end of file diff --git a/Anthropic.SDK/Messaging/MessageResponse.cs b/Anthropic.SDK/Messaging/MessageResponse.cs index fa28d8e..8eb7aed 100644 --- a/Anthropic.SDK/Messaging/MessageResponse.cs +++ b/Anthropic.SDK/Messaging/MessageResponse.cs @@ -165,6 +165,18 @@ public class Usage [JsonPropertyName("server_tool_use")] public ServerToolUse ServerToolUse { get; set; } + + [JsonPropertyName("cache_creation")] + public CacheCreation CacheCreation { get; set; } + } + + public class CacheCreation + { + [JsonPropertyName("ephemeral_5m_input_tokens")] + public int? Ephemeral5mInputTokens { get; set; } + + [JsonPropertyName("ephemeral_1h_input_tokens")] + public int? Ephemeral1hInputTokens { get; set; } } public class ServerToolUse