Refactor ChatResponseMetadata Builder methods
- Refactor builder methods in `ChatResponseMetadata` to remove `with` prefixes and introduce new methods with updated naming conventions. - Deprecate existing `with*` methods while maintaining backward compatibility. - Ensure dependent files and tests are compatible with the updated `ChatResponseMetadata` class.
This commit is contained in:
committed by
Ilayaperumal Gopinathan
parent
8c51f7a84c
commit
19e61bf71a
@@ -81,6 +81,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mariusz Bernacki
|
||||
* @author Thomas Vitale
|
||||
* @author Claudio Silva Junior
|
||||
* @author Alexandros Pappas
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class AnthropicChatModel extends AbstractToolCallSupport implements ChatModel {
|
||||
@@ -357,12 +358,12 @@ public class AnthropicChatModel extends AbstractToolCallSupport implements ChatM
|
||||
private ChatResponseMetadata from(AnthropicApi.ChatCompletionResponse result, Usage usage) {
|
||||
Assert.notNull(result, "Anthropic ChatCompletionResult must not be null");
|
||||
return ChatResponseMetadata.builder()
|
||||
.withId(result.id())
|
||||
.withModel(result.model())
|
||||
.withUsage(usage)
|
||||
.withKeyValue("stop-reason", result.stopReason())
|
||||
.withKeyValue("stop-sequence", result.stopSequence())
|
||||
.withKeyValue("type", result.type())
|
||||
.id(result.id())
|
||||
.model(result.model())
|
||||
.usage(usage)
|
||||
.keyValue("stop-reason", result.stopReason())
|
||||
.keyValue("stop-sequence", result.stopSequence())
|
||||
.keyValue("type", result.type())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* @author Soby Chacko
|
||||
* @author Jihoon Kim
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Alexandros Pappas
|
||||
* @see ChatModel
|
||||
* @see com.azure.ai.openai.OpenAIClient
|
||||
* @since 1.0.0
|
||||
@@ -184,11 +185,11 @@ public class AzureOpenAiChatModel extends AbstractToolCallSupport implements Cha
|
||||
Assert.notNull(chatCompletions, "Azure OpenAI ChatCompletions must not be null");
|
||||
String id = chatCompletions.getId();
|
||||
return ChatResponseMetadata.builder()
|
||||
.withId(id)
|
||||
.withUsage(usage)
|
||||
.withModel(chatCompletions.getModel())
|
||||
.withPromptMetadata(promptFilterMetadata)
|
||||
.withKeyValue("system-fingerprint", chatCompletions.getSystemFingerprint())
|
||||
.id(id)
|
||||
.usage(usage)
|
||||
.model(chatCompletions.getModel())
|
||||
.promptMetadata(promptFilterMetadata)
|
||||
.keyValue("system-fingerprint", chatCompletions.getSystemFingerprint())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -206,12 +207,12 @@ public class AzureOpenAiChatModel extends AbstractToolCallSupport implements Cha
|
||||
Assert.notNull(chatResponse, "ChatResponse must not be null");
|
||||
ChatResponseMetadata chatResponseMetadata = chatResponse.getMetadata();
|
||||
ChatResponseMetadata.Builder builder = ChatResponseMetadata.builder();
|
||||
builder.withId(chatResponseMetadata.getId())
|
||||
.withUsage(usage)
|
||||
.withModel(chatResponseMetadata.getModel())
|
||||
.withPromptMetadata(chatResponseMetadata.getPromptMetadata());
|
||||
builder.id(chatResponseMetadata.getId())
|
||||
.usage(usage)
|
||||
.model(chatResponseMetadata.getModel())
|
||||
.promptMetadata(chatResponseMetadata.getPromptMetadata());
|
||||
if (chatResponseMetadata.containsKey("system-fingerprint")) {
|
||||
builder.withKeyValue("system-fingerprint", chatResponseMetadata.get("system-fingerprint"));
|
||||
builder.keyValue("system-fingerprint", chatResponseMetadata.get("system-fingerprint"));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Christian Tzolov
|
||||
* @author Wei Jiang
|
||||
* @author Alexandros Pappas
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class BedrockProxyChatModel extends AbstractToolCallSupport implements ChatModel {
|
||||
@@ -564,8 +565,8 @@ public class BedrockProxyChatModel extends AbstractToolCallSupport implements Ch
|
||||
ConverseMetrics metrics = response.metrics();
|
||||
|
||||
var chatResponseMetaData = ChatResponseMetadata.builder()
|
||||
.withId(response.responseMetadata() != null ? response.responseMetadata().requestId() : "Unknown")
|
||||
.withUsage(usage)
|
||||
.id(response.responseMetadata() != null ? response.responseMetadata().requestId() : "Unknown")
|
||||
.usage(usage)
|
||||
.build();
|
||||
|
||||
return new ChatResponse(allGenerations, chatResponseMetaData);
|
||||
|
||||
@@ -62,6 +62,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Wei Jiang
|
||||
* @author Christian Tzolov
|
||||
* @author Alexandros Pappas
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public final class ConverseApiUtils {
|
||||
@@ -144,7 +145,7 @@ public final class ConverseApiUtils {
|
||||
ChatGenerationMetadata.builder().finishReason("tool_use").build());
|
||||
|
||||
var chatResponseMetaData = ChatResponseMetadata.builder()
|
||||
.withUsage(new DefaultUsage(promptTokens, generationTokens, totalTokens))
|
||||
.usage(new DefaultUsage(promptTokens, generationTokens, totalTokens))
|
||||
.build();
|
||||
|
||||
return new Aggregation(
|
||||
@@ -210,7 +211,7 @@ public final class ConverseApiUtils {
|
||||
metadataEvent.usage().outputTokens().longValue(),
|
||||
metadataEvent.usage().totalTokens().longValue());
|
||||
|
||||
var chatResponseMetaData = ChatResponseMetadata.builder().withUsage(usage).build();
|
||||
var chatResponseMetaData = ChatResponseMetadata.builder().usage(usage).build();
|
||||
|
||||
return new Aggregation(newMeta, new ChatResponse(List.of(), chatResponseMetaData));
|
||||
}
|
||||
@@ -235,10 +236,10 @@ public final class ConverseApiUtils {
|
||||
Long totalTokens = perviousChatResponse.getMetadata().getUsage().getTotalTokens();
|
||||
|
||||
if (chatResponse.getMetadata() != null) {
|
||||
metadataBuilder.withId(chatResponse.getMetadata().getId());
|
||||
metadataBuilder.withModel(chatResponse.getMetadata().getModel());
|
||||
metadataBuilder.withRateLimit(chatResponse.getMetadata().getRateLimit());
|
||||
metadataBuilder.withPromptMetadata(chatResponse.getMetadata().getPromptMetadata());
|
||||
metadataBuilder.id(chatResponse.getMetadata().getId());
|
||||
metadataBuilder.model(chatResponse.getMetadata().getModel());
|
||||
metadataBuilder.rateLimit(chatResponse.getMetadata().getRateLimit());
|
||||
metadataBuilder.promptMetadata(chatResponse.getMetadata().getPromptMetadata());
|
||||
|
||||
if (chatResponse.getMetadata().getUsage() != null) {
|
||||
promptTokens = promptTokens + chatResponse.getMetadata().getUsage().getPromptTokens();
|
||||
@@ -248,7 +249,7 @@ public final class ConverseApiUtils {
|
||||
}
|
||||
}
|
||||
|
||||
metadataBuilder.withUsage(new DefaultUsage(promptTokens, generationTokens, totalTokens));
|
||||
metadataBuilder.usage(new DefaultUsage(promptTokens, generationTokens, totalTokens));
|
||||
|
||||
return new ChatResponse(chatResponse.getResults(), metadataBuilder.build());
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* @author Ben Middleton
|
||||
* @author Christian Tzolov
|
||||
* @author Wei Jiang
|
||||
* @author Alexandros Pappas
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class BedrockAnthropic3ChatModel implements ChatModel, StreamingChatModel {
|
||||
@@ -92,9 +93,9 @@ public class BedrockAnthropic3ChatModel implements ChatModel, StreamingChatModel
|
||||
.toList();
|
||||
|
||||
ChatResponseMetadata metadata = ChatResponseMetadata.builder()
|
||||
.withId(response.id())
|
||||
.withModel(response.model())
|
||||
.withUsage(extractUsage(response))
|
||||
.id(response.id())
|
||||
.model(response.model())
|
||||
.usage(extractUsage(response))
|
||||
.build();
|
||||
|
||||
return new ChatResponse(generations, metadata);
|
||||
|
||||
@@ -76,6 +76,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* backed by {@link MiniMaxApi}.
|
||||
*
|
||||
* @author Geng Rong
|
||||
* @author Alexandros Pappas
|
||||
* @see ChatModel
|
||||
* @see StreamingChatModel
|
||||
* @see MiniMaxApi
|
||||
@@ -386,11 +387,11 @@ public class MiniMaxChatModel extends AbstractToolCallSupport implements ChatMod
|
||||
private ChatResponseMetadata from(ChatCompletion result) {
|
||||
Assert.notNull(result, "MiniMax ChatCompletionResult must not be null");
|
||||
return ChatResponseMetadata.builder()
|
||||
.withId(result.id() != null ? result.id() : "")
|
||||
.withUsage(result.usage() != null ? MiniMaxUsage.from(result.usage()) : new EmptyUsage())
|
||||
.withModel(result.model() != null ? result.model() : "")
|
||||
.withKeyValue("created", result.created() != null ? result.created() : 0L)
|
||||
.withKeyValue("system-fingerprint", result.systemFingerprint() != null ? result.systemFingerprint() : "")
|
||||
.id(result.id() != null ? result.id() : "")
|
||||
.usage(result.usage() != null ? MiniMaxUsage.from(result.usage()) : new EmptyUsage())
|
||||
.model(result.model() != null ? result.model() : "")
|
||||
.keyValue("created", result.created() != null ? result.created() : 0L)
|
||||
.keyValue("system-fingerprint", result.systemFingerprint() != null ? result.systemFingerprint() : "")
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* @author Thomas Vitale
|
||||
* @author luocongqiu
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Alexandros Pappas
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class MistralAiChatModel extends AbstractToolCallSupport implements ChatModel {
|
||||
@@ -151,20 +152,20 @@ public class MistralAiChatModel extends AbstractToolCallSupport implements ChatM
|
||||
Assert.notNull(result, "Mistral AI ChatCompletion must not be null");
|
||||
MistralAiUsage usage = MistralAiUsage.from(result.usage());
|
||||
return ChatResponseMetadata.builder()
|
||||
.withId(result.id())
|
||||
.withModel(result.model())
|
||||
.withUsage(usage)
|
||||
.withKeyValue("created", result.created())
|
||||
.id(result.id())
|
||||
.model(result.model())
|
||||
.usage(usage)
|
||||
.keyValue("created", result.created())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ChatResponseMetadata from(MistralAiApi.ChatCompletion result, Usage usage) {
|
||||
Assert.notNull(result, "Mistral AI ChatCompletion must not be null");
|
||||
return ChatResponseMetadata.builder()
|
||||
.withId(result.id())
|
||||
.withModel(result.model())
|
||||
.withUsage(usage)
|
||||
.withKeyValue("created", result.created())
|
||||
.id(result.id())
|
||||
.model(result.model())
|
||||
.usage(usage)
|
||||
.keyValue("created", result.created())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -318,10 +318,10 @@ public class MoonshotChatModel extends AbstractToolCallSupport implements ChatMo
|
||||
private ChatResponseMetadata from(ChatCompletion result) {
|
||||
Assert.notNull(result, "Moonshot ChatCompletionResult must not be null");
|
||||
return ChatResponseMetadata.builder()
|
||||
.withId(result.id() != null ? result.id() : "")
|
||||
.withUsage(result.usage() != null ? MoonshotUsage.from(result.usage()) : new EmptyUsage())
|
||||
.withModel(result.model() != null ? result.model() : "")
|
||||
.withKeyValue("created", result.created() != null ? result.created() : 0L)
|
||||
.id(result.id() != null ? result.id() : "")
|
||||
.usage(result.usage() != null ? MoonshotUsage.from(result.usage()) : new EmptyUsage())
|
||||
.model(result.model() != null ? result.model() : "")
|
||||
.keyValue("created", result.created() != null ? result.created() : 0L)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ import org.springframework.util.StringUtils;
|
||||
* {@link ChatModel} implementation that uses the OCI GenAI Chat API.
|
||||
*
|
||||
* @author Anders Swanson
|
||||
* @author Alexandros Pappas
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class OCICohereChatModel implements ChatModel {
|
||||
@@ -138,8 +139,8 @@ public class OCICohereChatModel implements ChatModel {
|
||||
validateChatOptions(options);
|
||||
|
||||
ChatResponseMetadata metadata = ChatResponseMetadata.builder()
|
||||
.withModel(options.getModel())
|
||||
.withKeyValue("compartment", options.getCompartment())
|
||||
.model(options.getModel())
|
||||
.keyValue("compartment", options.getCompartment())
|
||||
.build();
|
||||
return new ChatResponse(getGenerations(prompt, options), metadata);
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author luocongqiu
|
||||
* @author Thomas Vitale
|
||||
* @author Jihoon Kim
|
||||
* @author Alexandros Pappas
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class OllamaChatModel extends AbstractToolCallSupport implements ChatModel {
|
||||
@@ -164,16 +165,16 @@ public class OllamaChatModel extends AbstractToolCallSupport implements ChatMode
|
||||
DefaultUsage aggregatedUsage = new DefaultUsage(promptTokens, generationTokens, totalTokens);
|
||||
|
||||
return ChatResponseMetadata.builder()
|
||||
.withUsage(aggregatedUsage)
|
||||
.withModel(response.model())
|
||||
.withKeyValue(METADATA_CREATED_AT, response.createdAt())
|
||||
.withKeyValue(METADATA_EVAL_DURATION, evalDuration)
|
||||
.withKeyValue(METADATA_EVAL_COUNT, aggregatedUsage.getGenerationTokens().intValue())
|
||||
.withKeyValue(METADATA_LOAD_DURATION, loadDuration)
|
||||
.withKeyValue(METADATA_PROMPT_EVAL_DURATION, promptEvalDuration)
|
||||
.withKeyValue(METADATA_PROMPT_EVAL_COUNT, aggregatedUsage.getPromptTokens().intValue())
|
||||
.withKeyValue(METADATA_TOTAL_DURATION, totalDuration)
|
||||
.withKeyValue(DONE, response.done())
|
||||
.usage(aggregatedUsage)
|
||||
.model(response.model())
|
||||
.keyValue(METADATA_CREATED_AT, response.createdAt())
|
||||
.keyValue(METADATA_EVAL_DURATION, evalDuration)
|
||||
.keyValue(METADATA_EVAL_COUNT, aggregatedUsage.getGenerationTokens().intValue())
|
||||
.keyValue(METADATA_LOAD_DURATION, loadDuration)
|
||||
.keyValue(METADATA_PROMPT_EVAL_DURATION, promptEvalDuration)
|
||||
.keyValue(METADATA_PROMPT_EVAL_COUNT, aggregatedUsage.getPromptTokens().intValue())
|
||||
.keyValue(METADATA_TOTAL_DURATION, totalDuration)
|
||||
.keyValue(DONE, response.done())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
/**
|
||||
* @author Jihoon Kim
|
||||
* @author Christian Tzolov
|
||||
* @author Alexandros Pappas
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@@ -99,9 +100,9 @@ public class OllamaChatModelTests {
|
||||
ChatResponse previousChatResponse = ChatResponse.builder()
|
||||
.generations(List.of())
|
||||
.metadata(ChatResponseMetadata.builder()
|
||||
.withUsage(new DefaultUsage(66L, 99L))
|
||||
.withKeyValue("eval-duration", Duration.ofSeconds(2))
|
||||
.withKeyValue("prompt-eval-duration", Duration.ofSeconds(2))
|
||||
.usage(new DefaultUsage(66L, 99L))
|
||||
.keyValue("eval-duration", Duration.ofSeconds(2))
|
||||
.keyValue("prompt-eval-duration", Duration.ofSeconds(2))
|
||||
.build())
|
||||
.build();
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author luocongqiu
|
||||
* @author Thomas Vitale
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Alexandros Pappas
|
||||
* @see ChatModel
|
||||
* @see StreamingChatModel
|
||||
* @see OpenAiApi
|
||||
@@ -461,13 +462,13 @@ public class OpenAiChatModel extends AbstractToolCallSupport implements ChatMode
|
||||
private ChatResponseMetadata from(OpenAiApi.ChatCompletion result, RateLimit rateLimit, Usage usage) {
|
||||
Assert.notNull(result, "OpenAI ChatCompletionResult must not be null");
|
||||
var builder = ChatResponseMetadata.builder()
|
||||
.withId(result.id() != null ? result.id() : "")
|
||||
.withUsage(usage)
|
||||
.withModel(result.model() != null ? result.model() : "")
|
||||
.withKeyValue("created", result.created() != null ? result.created() : 0L)
|
||||
.withKeyValue("system-fingerprint", result.systemFingerprint() != null ? result.systemFingerprint() : "");
|
||||
.id(result.id() != null ? result.id() : "")
|
||||
.usage(usage)
|
||||
.model(result.model() != null ? result.model() : "")
|
||||
.keyValue("created", result.created() != null ? result.created() : 0L)
|
||||
.keyValue("system-fingerprint", result.systemFingerprint() != null ? result.systemFingerprint() : "");
|
||||
if (rateLimit != null) {
|
||||
builder.withRateLimit(rateLimit);
|
||||
builder.rateLimit(rateLimit);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
@@ -475,11 +476,11 @@ public class OpenAiChatModel extends AbstractToolCallSupport implements ChatMode
|
||||
private ChatResponseMetadata from(ChatResponseMetadata chatResponseMetadata, Usage usage) {
|
||||
Assert.notNull(chatResponseMetadata, "OpenAI ChatResponseMetadata must not be null");
|
||||
var builder = ChatResponseMetadata.builder()
|
||||
.withId(chatResponseMetadata.getId() != null ? chatResponseMetadata.getId() : "")
|
||||
.withUsage(usage)
|
||||
.withModel(chatResponseMetadata.getModel() != null ? chatResponseMetadata.getModel() : "");
|
||||
.id(chatResponseMetadata.getId() != null ? chatResponseMetadata.getId() : "")
|
||||
.usage(usage)
|
||||
.model(chatResponseMetadata.getModel() != null ? chatResponseMetadata.getModel() : "");
|
||||
if (chatResponseMetadata.getRateLimit() != null) {
|
||||
builder.withRateLimit(chatResponseMetadata.getRateLimit());
|
||||
builder.rateLimit(chatResponseMetadata.getRateLimit());
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ import org.springframework.util.Assert;
|
||||
* @see ChatModel
|
||||
* @see StreamingChatModel
|
||||
* @see QianFanApi
|
||||
* @author Alexandros Pappas
|
||||
* @since 1.0
|
||||
*/
|
||||
public class QianFanChatModel implements ChatModel, StreamingChatModel {
|
||||
@@ -290,10 +291,10 @@ public class QianFanChatModel implements ChatModel, StreamingChatModel {
|
||||
private ChatResponseMetadata from(QianFanApi.ChatCompletion result, String model) {
|
||||
Assert.notNull(result, "QianFan ChatCompletionResult must not be null");
|
||||
return ChatResponseMetadata.builder()
|
||||
.withId(result.id() != null ? result.id() : "")
|
||||
.withUsage(result.usage() != null ? QianFanUsage.from(result.usage()) : new EmptyUsage())
|
||||
.withModel(model)
|
||||
.withKeyValue("created", result.created() != null ? result.created() : 0L)
|
||||
.id(result.id() != null ? result.id() : "")
|
||||
.usage(result.usage() != null ? QianFanUsage.from(result.usage()) : new EmptyUsage())
|
||||
.model(model)
|
||||
.keyValue("created", result.created() != null ? result.created() : 0L)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mark Pollack
|
||||
* @author Soby Chacko
|
||||
* @author Jihoon Kim
|
||||
* @author Alexandros Pappas
|
||||
* @since 0.8.1
|
||||
*/
|
||||
public class VertexAiGeminiChatModel extends AbstractToolCallSupport implements ChatModel, DisposableBean {
|
||||
@@ -427,7 +428,7 @@ public class VertexAiGeminiChatModel extends AbstractToolCallSupport implements
|
||||
}
|
||||
|
||||
private ChatResponseMetadata toChatResponseMetadata(GenerateContentResponse response) {
|
||||
return ChatResponseMetadata.builder().withUsage(new VertexAiUsage(response.getUsageMetadata())).build();
|
||||
return ChatResponseMetadata.builder().usage(new VertexAiUsage(response.getUsageMetadata())).build();
|
||||
}
|
||||
|
||||
private VertexAiGeminiChatOptions vertexAiGeminiChatOptions(Prompt prompt) {
|
||||
|
||||
@@ -83,6 +83,7 @@ import org.springframework.util.MimeType;
|
||||
* @see ChatModel
|
||||
* @see StreamingChatModel
|
||||
* @see ZhiPuAiApi
|
||||
* @author Alexandros Pappas
|
||||
* @since 1.0.0 M1
|
||||
*/
|
||||
public class ZhiPuAiChatModel extends AbstractToolCallSupport implements ChatModel, StreamingChatModel {
|
||||
@@ -324,11 +325,11 @@ public class ZhiPuAiChatModel extends AbstractToolCallSupport implements ChatMod
|
||||
private ChatResponseMetadata from(ChatCompletion result) {
|
||||
Assert.notNull(result, "ZhiPuAI ChatCompletionResult must not be null");
|
||||
return ChatResponseMetadata.builder()
|
||||
.withId(result.id() != null ? result.id() : "")
|
||||
.withUsage(result.usage() != null ? ZhiPuAiUsage.from(result.usage()) : new EmptyUsage())
|
||||
.withModel(result.model() != null ? result.model() : "")
|
||||
.withKeyValue("created", result.created() != null ? result.created() : 0L)
|
||||
.withKeyValue("system-fingerprint", result.systemFingerprint() != null ? result.systemFingerprint() : "")
|
||||
.id(result.id() != null ? result.id() : "")
|
||||
.usage(result.usage() != null ? ZhiPuAiUsage.from(result.usage()) : new EmptyUsage())
|
||||
.model(result.model() != null ? result.model() : "")
|
||||
.keyValue("created", result.created() != null ? result.created() : 0L)
|
||||
.keyValue("system-fingerprint", result.systemFingerprint() != null ? result.systemFingerprint() : "")
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.ai.model.ResponseMetadata;
|
||||
* @author John Blum
|
||||
* @author Thomas Vitale
|
||||
* @author Mark Pollack
|
||||
* @author Alexandros Pappas
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ChatResponseMetadata extends AbstractResponseMetadata implements ResponseMetadata {
|
||||
@@ -126,12 +127,12 @@ public class ChatResponseMetadata extends AbstractResponseMetadata implements Re
|
||||
this.chatResponseMetadata = new ChatResponseMetadata();
|
||||
}
|
||||
|
||||
public Builder withMetadata(Map<String, Object> mapToCopy) {
|
||||
public Builder metadata(Map<String, Object> mapToCopy) {
|
||||
this.chatResponseMetadata.map.putAll(mapToCopy);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withKeyValue(String key, Object value) {
|
||||
public Builder keyValue(String key, Object value) {
|
||||
if (key == null) {
|
||||
throw new IllegalArgumentException("Key must not be null");
|
||||
}
|
||||
@@ -144,31 +145,87 @@ public class ChatResponseMetadata extends AbstractResponseMetadata implements Re
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withId(String id) {
|
||||
public Builder id(String id) {
|
||||
this.chatResponseMetadata.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withModel(String model) {
|
||||
public Builder model(String model) {
|
||||
this.chatResponseMetadata.model = model;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withRateLimit(RateLimit rateLimit) {
|
||||
public Builder rateLimit(RateLimit rateLimit) {
|
||||
this.chatResponseMetadata.rateLimit = rateLimit;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withUsage(Usage usage) {
|
||||
public Builder usage(Usage usage) {
|
||||
this.chatResponseMetadata.usage = usage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withPromptMetadata(PromptMetadata promptMetadata) {
|
||||
public Builder promptMetadata(PromptMetadata promptMetadata) {
|
||||
this.chatResponseMetadata.promptMetadata = promptMetadata;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #metadata(Map)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public Builder wihtMetadata(Map<String, Object> mapToCopy) {
|
||||
return metadata(mapToCopy);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #keyValue(String, Object)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public Builder withKeyValue(String key, Object value) {
|
||||
return keyValue(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #id(String)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public Builder withId(String id) {
|
||||
return id(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #model(String)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public Builder withModel(String model) {
|
||||
return model(model);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #rateLimit(RateLimit)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public Builder withRateLimit(RateLimit rateLimit) {
|
||||
return rateLimit(rateLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #usage(Usage)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public Builder withUsage(Usage usage) {
|
||||
return usage(usage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #promptMetadata(PromptMetadata)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public Builder withPromptMetadata(PromptMetadata promptMetadata) {
|
||||
return promptMetadata(promptMetadata);
|
||||
}
|
||||
|
||||
public ChatResponseMetadata build() {
|
||||
return this.chatResponseMetadata;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,12 @@ import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* The chat completion (e.g. generation) response returned by an AI provider.
|
||||
*
|
||||
* @author Christian Tzolov
|
||||
* @author Mark Pollack
|
||||
* @author Soby Chacko
|
||||
* @author John Blum
|
||||
* @author Alexandros Pappas
|
||||
*/
|
||||
public class ChatResponse implements ModelResponse<Generation> {
|
||||
|
||||
@@ -136,24 +142,24 @@ public class ChatResponse implements ModelResponse<Generation> {
|
||||
*/
|
||||
@Deprecated
|
||||
public Builder withMetadata(String key, Object value) {
|
||||
this.chatResponseMetadataBuilder.withKeyValue(key, value);
|
||||
this.chatResponseMetadataBuilder.keyValue(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder metadata(String key, Object value) {
|
||||
this.chatResponseMetadataBuilder.withKeyValue(key, value);
|
||||
this.chatResponseMetadataBuilder.keyValue(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder metadata(ChatResponseMetadata other) {
|
||||
this.chatResponseMetadataBuilder.withModel(other.getModel());
|
||||
this.chatResponseMetadataBuilder.withId(other.getId());
|
||||
this.chatResponseMetadataBuilder.withRateLimit(other.getRateLimit());
|
||||
this.chatResponseMetadataBuilder.withUsage(other.getUsage());
|
||||
this.chatResponseMetadataBuilder.withPromptMetadata(other.getPromptMetadata());
|
||||
this.chatResponseMetadataBuilder.model(other.getModel());
|
||||
this.chatResponseMetadataBuilder.id(other.getId());
|
||||
this.chatResponseMetadataBuilder.rateLimit(other.getRateLimit());
|
||||
this.chatResponseMetadataBuilder.usage(other.getUsage());
|
||||
this.chatResponseMetadataBuilder.promptMetadata(other.getPromptMetadata());
|
||||
Set<Map.Entry<String, Object>> entries = other.entrySet();
|
||||
for (Map.Entry<String, Object> entry : entries) {
|
||||
this.chatResponseMetadataBuilder.withKeyValue(entry.getKey(), entry.getValue());
|
||||
this.chatResponseMetadataBuilder.keyValue(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.springframework.util.StringUtils;
|
||||
* single AssistantMessage. Job is performed in parallel to the chat response processing.
|
||||
*
|
||||
* @author Christian Tzolov
|
||||
* @author Alexandros Pappas
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class MessageAggregator {
|
||||
@@ -146,11 +147,11 @@ public class MessageAggregator {
|
||||
metadataUsageTotalTokensRef.get());
|
||||
|
||||
var chatResponseMetadata = ChatResponseMetadata.builder()
|
||||
.withId(metadataIdRef.get())
|
||||
.withModel(metadataModelRef.get())
|
||||
.withRateLimit(metadataRateLimitRef.get())
|
||||
.withUsage(usage)
|
||||
.withPromptMetadata(metadataPromptMetadataRef.get())
|
||||
.id(metadataIdRef.get())
|
||||
.model(metadataModelRef.get())
|
||||
.rateLimit(metadataRateLimitRef.get())
|
||||
.usage(usage)
|
||||
.promptMetadata(metadataPromptMetadataRef.get())
|
||||
.build();
|
||||
|
||||
onAggregationComplete.accept(new ChatResponse(List.of(new Generation(
|
||||
|
||||
@@ -45,6 +45,7 @@ import static org.mockito.BDDMockito.given;
|
||||
|
||||
/**
|
||||
* @author Christian Tzolov
|
||||
* @author Alexandros Pappas
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class ChatClientAdvisorTests {
|
||||
@@ -63,11 +64,11 @@ public class ChatClientAdvisorTests {
|
||||
public void promptChatMemory() {
|
||||
|
||||
var builder = ChatResponseMetadata.builder()
|
||||
.withId("124")
|
||||
.withUsage(new MessageAggregator.DefaultUsage(1, 2, 3))
|
||||
.withModel("gpt4o")
|
||||
.withKeyValue("created", 0L)
|
||||
.withKeyValue("system-fingerprint", "john doe");
|
||||
.id("124")
|
||||
.usage(new MessageAggregator.DefaultUsage(1, 2, 3))
|
||||
.model("gpt4o")
|
||||
.keyValue("created", 0L)
|
||||
.keyValue("system-fingerprint", "john doe");
|
||||
ChatResponseMetadata chatResponseMetadata = builder.build();
|
||||
|
||||
given(this.chatModel.call(this.promptCaptor.capture()))
|
||||
|
||||
@@ -42,6 +42,7 @@ import static org.mockito.BDDMockito.given;
|
||||
|
||||
/**
|
||||
* @author Christian Tzolov
|
||||
* @author Alexandros Pappas
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class ChatClientResponseEntityTests {
|
||||
@@ -55,7 +56,7 @@ public class ChatClientResponseEntityTests {
|
||||
@Test
|
||||
public void responseEntityTest() {
|
||||
|
||||
ChatResponseMetadata metadata = ChatResponseMetadata.builder().withKeyValue("key1", "value1").build();
|
||||
ChatResponseMetadata metadata = ChatResponseMetadata.builder().keyValue("key1", "value1").build();
|
||||
|
||||
var chatResponse = new ChatResponse(List.of(new Generation(new AssistantMessage("""
|
||||
{"name":"John", "age":30}
|
||||
|
||||
@@ -50,6 +50,7 @@ import static org.mockito.BDDMockito.given;
|
||||
/**
|
||||
* @author Christian Tzolov
|
||||
* @author Timo Salm
|
||||
* @author Alexandros Pappas
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class QuestionAnswerAdvisorTests {
|
||||
@@ -72,13 +73,7 @@ public class QuestionAnswerAdvisorTests {
|
||||
// @formatter:off
|
||||
given(this.chatModel.call(this.promptCaptor.capture()))
|
||||
.willReturn(new ChatResponse(List.of(new Generation(new AssistantMessage("Your answer is ZXY"))),
|
||||
ChatResponseMetadata.builder()
|
||||
.withId("678")
|
||||
.withModel("model1")
|
||||
.withKeyValue("key6", "value6")
|
||||
.withMetadata(Map.of("key1", "value1"))
|
||||
.withPromptMetadata(null)
|
||||
.withRateLimit(new RateLimit() {
|
||||
ChatResponseMetadata.builder().id("678").model("model1").keyValue("key6", "value6").metadata(Map.of("key1", "value1")).promptMetadata(null).rateLimit(new RateLimit() {
|
||||
|
||||
@Override
|
||||
public Long getRequestsLimit() {
|
||||
@@ -109,8 +104,7 @@ public class QuestionAnswerAdvisorTests {
|
||||
public Duration getTokensReset() {
|
||||
return Duration.ofSeconds(9);
|
||||
}
|
||||
})
|
||||
.withUsage(new DefaultUsage(6L, 7L))
|
||||
}).usage(new DefaultUsage(6L, 7L))
|
||||
.build()));
|
||||
// @formatter:on
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ import static org.springframework.ai.chat.observation.ChatModelObservationDocume
|
||||
* Unit tests for {@link ChatModelMeterObservationHandler}.
|
||||
*
|
||||
* @author Thomas Vitale
|
||||
* @author Alexandros Pappas
|
||||
*/
|
||||
class ChatModelMeterObservationHandlerTests {
|
||||
|
||||
@@ -68,7 +69,7 @@ class ChatModelMeterObservationHandlerTests {
|
||||
.start();
|
||||
|
||||
observationContext.setResponse(new ChatResponse(List.of(new Generation(new AssistantMessage("test"))),
|
||||
ChatResponseMetadata.builder().withModel("mistral-42").withUsage(new TestUsage()).build()));
|
||||
ChatResponseMetadata.builder().model("mistral-42").usage(new TestUsage()).build()));
|
||||
|
||||
observation.stop();
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import static org.springframework.ai.chat.observation.ChatModelObservationDocume
|
||||
* Unit tests for {@link DefaultChatModelObservationConvention}.
|
||||
*
|
||||
* @author Thomas Vitale
|
||||
* @author Alexandros Pappas
|
||||
*/
|
||||
class DefaultChatModelObservationConventionTests {
|
||||
|
||||
@@ -112,11 +113,7 @@ class DefaultChatModelObservationConventionTests {
|
||||
observationContext.setResponse(new ChatResponse(
|
||||
List.of(new Generation(new AssistantMessage("response"),
|
||||
ChatGenerationMetadata.builder().finishReason("this-is-the-end").build())),
|
||||
ChatResponseMetadata.builder()
|
||||
.withId("say33")
|
||||
.withModel("mistral-42")
|
||||
.withUsage(new TestUsage())
|
||||
.build()));
|
||||
ChatResponseMetadata.builder().id("say33").model("mistral-42").usage(new TestUsage()).build()));
|
||||
assertThat(this.observationConvention.getLowCardinalityKeyValues(observationContext))
|
||||
.contains(KeyValue.of(LowCardinalityKeyNames.RESPONSE_MODEL.asString(), "mistral-42"));
|
||||
assertThat(this.observationConvention.getHighCardinalityKeyValues(observationContext)).contains(
|
||||
@@ -170,7 +167,7 @@ class DefaultChatModelObservationConventionTests {
|
||||
observationContext.setResponse(new ChatResponse(
|
||||
List.of(new Generation(new AssistantMessage("response"),
|
||||
ChatGenerationMetadata.builder().finishReason("").build())),
|
||||
ChatResponseMetadata.builder().withId("").build()));
|
||||
ChatResponseMetadata.builder().id("").build()));
|
||||
assertThat(this.observationConvention.getHighCardinalityKeyValues(observationContext)
|
||||
.stream()
|
||||
.map(KeyValue::getKey)
|
||||
|
||||
Reference in New Issue
Block a user