From 17068c9e8e12b41d75e0304e007e2f35e43c37f1 Mon Sep 17 00:00:00 2001 From: Ricken Bazolo Date: Sat, 25 Jan 2025 14:30:28 +0100 Subject: [PATCH 1/2] improved ability to use openAiApi to support DeepSeek Signed-off-by: Ricken Bazolo --- .../springframework/ai/openai/api/OpenAiApi.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java index c9e54ceee66..ea42e912828 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java @@ -1323,17 +1323,28 @@ public record TopLogProbs(// @formatter:off * completion). * @param promptTokensDetails Breakdown of tokens used in the prompt. * @param completionTokenDetails Breakdown of tokens used in a completion. + * @param promptCacheHitTokens Number of tokens in the prompt that were served from + * (util for + * DeepSeek + * support). + * @param promptCacheMissTokens Number of tokens in the prompt that were not served + * (util for + * DeepSeek + * support). */ @JsonInclude(Include.NON_NULL) + @JsonIgnoreProperties(ignoreUnknown = true) public record Usage(// @formatter:off @JsonProperty("completion_tokens") Integer completionTokens, @JsonProperty("prompt_tokens") Integer promptTokens, @JsonProperty("total_tokens") Integer totalTokens, @JsonProperty("prompt_tokens_details") PromptTokensDetails promptTokensDetails, - @JsonProperty("completion_tokens_details") CompletionTokenDetails completionTokenDetails) { // @formatter:on + @JsonProperty("completion_tokens_details") CompletionTokenDetails completionTokenDetails, + @JsonProperty("prompt_cache_hit_tokens") Integer promptCacheHitTokens, + @JsonProperty("prompt_cache_miss_tokens") Integer promptCacheMissTokens) { // @formatter:on public Usage(Integer completionTokens, Integer promptTokens, Integer totalTokens) { - this(completionTokens, promptTokens, totalTokens, null, null); + this(completionTokens, promptTokens, totalTokens, null, null, null, null); } /** From 3057df69c61f0c945e0257db2896ffc3561070e2 Mon Sep 17 00:00:00 2001 From: Ricken Bazolo Date: Sat, 25 Jan 2025 14:30:28 +0100 Subject: [PATCH 2/2] improved ability to use openAiApi to support DeepSeek Signed-off-by: Ricken Bazolo --- .../ai/openai/metadata/OpenAiUsageTests.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/metadata/OpenAiUsageTests.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/metadata/OpenAiUsageTests.java index 92e8f595b3f..7a177918b42 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/metadata/OpenAiUsageTests.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/metadata/OpenAiUsageTests.java @@ -74,7 +74,7 @@ void whenTotalTokensIsNull() { @Test void whenPromptAndCompletionTokensDetailsIsNull() { - OpenAiApi.Usage openAiUsage = new OpenAiApi.Usage(100, 200, 300, null, null); + OpenAiApi.Usage openAiUsage = new OpenAiApi.Usage(100, 200, 300, null, null, null, null); OpenAiUsage usage = OpenAiUsage.from(openAiUsage); assertThat(usage.getTotalTokens()).isEqualTo(300); assertThat(usage.getCompletionTokenDetails().reasoningTokens()).isEqualTo(0); @@ -85,7 +85,7 @@ void whenPromptAndCompletionTokensDetailsIsNull() { @Test void whenCompletionTokenDetailsIsNull() { - OpenAiApi.Usage openAiUsage = new OpenAiApi.Usage(100, 200, 300, null, null); + OpenAiApi.Usage openAiUsage = new OpenAiApi.Usage(100, 200, 300, null, null, null, null); OpenAiUsage usage = OpenAiUsage.from(openAiUsage); assertThat(usage.getTotalTokens()).isEqualTo(300); assertThat(usage.getReasoningTokens()).isEqualTo(0); @@ -94,7 +94,7 @@ void whenCompletionTokenDetailsIsNull() { @Test void whenReasoningTokensIsNull() { OpenAiApi.Usage openAiUsage = new OpenAiApi.Usage(100, 200, 300, null, - new OpenAiApi.Usage.CompletionTokenDetails(null, null, null, null)); + new OpenAiApi.Usage.CompletionTokenDetails(null, null, null, null), null, null); OpenAiUsage usage = OpenAiUsage.from(openAiUsage); assertThat(usage.getReasoningTokens()).isEqualTo(0); } @@ -102,7 +102,7 @@ void whenReasoningTokensIsNull() { @Test void whenCompletionTokenDetailsIsPresent() { OpenAiApi.Usage openAiUsage = new OpenAiApi.Usage(100, 200, 300, null, - new OpenAiApi.Usage.CompletionTokenDetails(50, null, null, null)); + new OpenAiApi.Usage.CompletionTokenDetails(50, null, null, null), null, null); OpenAiUsage usage = OpenAiUsage.from(openAiUsage); assertThat(usage.getCompletionTokenDetails().reasoningTokens()).isEqualTo(50); assertThat(usage.getCompletionTokenDetails().acceptedPredictionTokens()).isEqualTo(0); @@ -113,7 +113,7 @@ void whenCompletionTokenDetailsIsPresent() { @Test void whenAcceptedPredictionTokensIsPresent() { OpenAiApi.Usage openAiUsage = new OpenAiApi.Usage(100, 200, 300, null, - new OpenAiApi.Usage.CompletionTokenDetails(null, 75, null, null)); + new OpenAiApi.Usage.CompletionTokenDetails(null, 75, null, null), null, null); OpenAiUsage usage = OpenAiUsage.from(openAiUsage); assertThat(usage.getCompletionTokenDetails().reasoningTokens()).isEqualTo(0); assertThat(usage.getCompletionTokenDetails().acceptedPredictionTokens()).isEqualTo(75); @@ -124,7 +124,7 @@ void whenAcceptedPredictionTokensIsPresent() { @Test void whenAudioTokensIsPresent() { OpenAiApi.Usage openAiUsage = new OpenAiApi.Usage(100, 200, 300, null, - new OpenAiApi.Usage.CompletionTokenDetails(null, null, 125, null)); + new OpenAiApi.Usage.CompletionTokenDetails(null, null, 125, null), null, null); OpenAiUsage usage = OpenAiUsage.from(openAiUsage); assertThat(usage.getCompletionTokenDetails().reasoningTokens()).isEqualTo(0); assertThat(usage.getCompletionTokenDetails().acceptedPredictionTokens()).isEqualTo(0); @@ -135,7 +135,7 @@ void whenAudioTokensIsPresent() { @Test void whenRejectedPredictionTokensIsNull() { OpenAiApi.Usage openAiUsage = new OpenAiApi.Usage(100, 200, 300, null, - new OpenAiApi.Usage.CompletionTokenDetails(null, null, null, null)); + new OpenAiApi.Usage.CompletionTokenDetails(null, null, null, null), null, null); OpenAiUsage usage = OpenAiUsage.from(openAiUsage); assertThat(usage.getCompletionTokenDetails().reasoningTokens()).isEqualTo(0); assertThat(usage.getCompletionTokenDetails().acceptedPredictionTokens()).isEqualTo(0); @@ -147,7 +147,7 @@ void whenRejectedPredictionTokensIsNull() { @Test void whenRejectedPredictionTokensIsPresent() { OpenAiApi.Usage openAiUsage = new OpenAiApi.Usage(100, 200, 300, null, - new OpenAiApi.Usage.CompletionTokenDetails(null, null, null, 25)); + new OpenAiApi.Usage.CompletionTokenDetails(null, null, null, 25), null, null); OpenAiUsage usage = OpenAiUsage.from(openAiUsage); assertThat(usage.getCompletionTokenDetails().reasoningTokens()).isEqualTo(0); assertThat(usage.getCompletionTokenDetails().acceptedPredictionTokens()).isEqualTo(0); @@ -158,7 +158,7 @@ void whenRejectedPredictionTokensIsPresent() { @Test void whenCacheTokensIsNull() { OpenAiApi.Usage openAiUsage = new OpenAiApi.Usage(100, 200, 300, - new OpenAiApi.Usage.PromptTokensDetails(null, null), null); + new OpenAiApi.Usage.PromptTokensDetails(null, null), null, null, null); OpenAiUsage usage = OpenAiUsage.from(openAiUsage); assertThat(usage.getPromptTokensDetails().audioTokens()).isEqualTo(0); assertThat(usage.getPromptTokensDetails().cachedTokens()).isEqualTo(0); @@ -167,7 +167,7 @@ void whenCacheTokensIsNull() { @Test void whenCacheTokensIsPresent() { OpenAiApi.Usage openAiUsage = new OpenAiApi.Usage(100, 200, 300, - new OpenAiApi.Usage.PromptTokensDetails(99, 15), null); + new OpenAiApi.Usage.PromptTokensDetails(99, 15), null, null, null); OpenAiUsage usage = OpenAiUsage.from(openAiUsage); assertThat(usage.getPromptTokensDetails().audioTokens()).isEqualTo(99); assertThat(usage.getPromptTokensDetails().cachedTokens()).isEqualTo(15);