From a2147e8572268205c8e6cef8fca5f660028d9502 Mon Sep 17 00:00:00 2001 From: Josh Long Date: Fri, 17 May 2024 17:55:33 +0200 Subject: [PATCH] yolo --- ...lient.java => AnthropicChatConnector.java} | 28 +-- .../ai/anthropic/AnthropicChatOptions.java | 4 +- ...tIT.java => AnthropicChatConnectorIT.java} | 22 +- .../anthropic/AnthropicTestConfiguration.java | 4 +- .../anthropic/ChatCompletionRequestTests.java | 2 +- ...ent.java => AzureOpenAiChatConnector.java} | 22 +- .../azure/openai/AzureOpenAiChatOptions.java | 10 +- .../AzureChatCompletionsOptionsTests.java | 2 +- ...T.java => AzureOpenAiChatConnectorIT.java} | 20 +- .../MockAzureOpenAiTestConfiguration.java | 4 +- ...ureOpenAiChatConnectorFunctionCallIT.java} | 20 +- ...zureOpenAiChatConnectorMetadataTests.java} | 12 +- ...ava => BedrockAnthropicChatConnector.java} | 14 +- ...va => BedrockAnthropic3ChatConnector.java} | 14 +- ...t.java => BedrockCohereChatConnector.java} | 10 +- ...=> BedrockAi21Jurassic2ChatConnector.java} | 16 +- ...nt.java => BedrockLlamaChatConnector.java} | 12 +- ...nt.java => BedrockTitanChatConnector.java} | 10 +- ...a => BedrockAnthropicChatConnectorIT.java} | 18 +- .../BedrockAnthropicCreateRequestTests.java | 2 +- ... => BedrockAnthropic3ChatConnectorIT.java} | 20 +- .../BedrockAnthropic3CreateRequestTests.java | 2 +- ...java => BedrockCohereChatConnectorIT.java} | 16 +- .../BedrockCohereChatCreateRequestTests.java | 2 +- ... BedrockAi21Jurassic2ChatConnectorIT.java} | 18 +- ....java => BedrockLlamaChatConnectorIT.java} | 16 +- .../llama/BedrockLlamaCreateRequestTests.java | 2 +- ....java => BedrockTitanChatConnectorIT.java} | 16 +- .../BedrockTitanChatCreateRequestTests.java | 2 +- ...ent.java => HuggingfaceChatConnector.java} | 13 +- .../HuggingfaceTestConfiguration.java | 4 +- .../ai/huggingface/client/ClientIT.java | 6 +- ...lient.java => MistralAiChatConnector.java} | 14 +- .../ai/mistralai/MistralAiChatOptions.java | 4 +- .../MistralAiChatCompletionRequestTest.java | 2 +- ...tIT.java => MistralAiChatConnectorIT.java} | 22 +- .../ai/mistralai/MistralAiRetryTests.java | 8 +- .../mistralai/MistralAiTestConfiguration.java | 4 +- ...atClient.java => OllamaChatConnector.java} | 16 +- ...ientIT.java => OllamaChatConnectorIT.java} | 22 +- ...a => OllamaChatConnectorMultimodalIT.java} | 12 +- .../ai/ollama/OllamaChatRequestTests.java | 4 +- ...atClient.java => OpenAiChatConnector.java} | 28 +-- .../ai/openai/OpenAiChatOptions.java | 4 +- .../ai/openai/ChatClientTest.java | 56 +++++ .../ai/openai/ChatCompletionRequestTests.java | 6 +- .../ai/openai/OpenAiTestConfiguration.java | 4 +- .../ai/openai/acme/AcmeIT.java | 6 +- ...atClientWithChatResponseMetadataTests.java | 10 +- ...nt2IT.java => OpenAiChatConnector2IT.java} | 14 +- ...ientIT.java => OpenAiChatConnectorIT.java} | 28 +-- .../ai/openai/chat/OpenAiRetryTests.java | 10 +- .../ChatMemoryLongTermSystemPromptIT.java | 12 +- .../ChatMemoryShortTermMessageListIT.java | 12 +- .../ChatMemoryShortTermSystemPromptIT.java | 12 +- .../LongShortTermChatMemoryWithRagIT.java | 13 +- ...OpenAiPromptTransformingChatServiceIT.java | 21 +- .../ai/openai/testutils/AbstractIT.java | 8 +- .../transformer/MetadataTransformerIT.java | 10 +- ....java => VertexAiGeminiChatConnector.java} | 16 +- .../gemini/VertexAiGeminiChatOptions.java | 4 +- .../aot/VertexAiGeminiRuntimeHints.java | 4 +- ...ava => VertexAiGeminiChatConnectorIT.java} | 20 +- .../aot/VertexAiGeminiRuntimeHintsTests.java | 4 +- ...GeminiChatConnectorFunctionCallingIT.java} | 35 ++-- ...t.java => VertexAiPaLm2ChatConnector.java} | 10 +- .../VertexAiPaLm2ChatGenerationClientIT.java | 14 +- .../palm2/VertexAiPaLm2ChatRequestTests.java | 2 +- ...lient.java => WatsonxAiChatConnector.java} | 12 +- ...t.java => WatsonxAiChatConnectorTest.java} | 12 +- .../springframework/ai/chat/ChatClient.java | 195 +++++++++++++++--- .../ai/chat/connector/ChatConnector.java | 35 ++++ .../PromptTransformingChatService.java | 24 +-- .../ai/evaluation/RelevancyEvaluator.java | 14 +- .../function/AbstractFunctionCallback.java | 2 +- .../function/FunctionCallingOptions.java | 22 +- .../transformer/KeywordMetadataEnricher.java | 12 +- .../transformer/SummaryMetadataEnricher.java | 16 +- ...ientTests.java => ChatConnectorTests.java} | 17 +- .../ai/chat/memory/ChatMemoryTests.java | 10 +- .../modules/ROOT/pages/api/bedrock.adoc | 2 +- .../ROOT/pages/api/chat/anthropic-chat.adoc | 8 +- .../pages/api/chat/azure-openai-chat.adoc | 10 +- .../api/chat/bedrock/bedrock-anthropic.adoc | 4 +- .../api/chat/bedrock/bedrock-anthropic3.adoc | 4 +- .../api/chat/bedrock/bedrock-cohere.adoc | 4 +- .../api/chat/bedrock/bedrock-jurassic2.adoc | 4 +- .../pages/api/chat/bedrock/bedrock-llama.adoc | 4 +- .../pages/api/chat/bedrock/bedrock-titan.adoc | 4 +- .../functions/anthropic-chat-functions.adoc | 12 +- .../azure-open-ai-chat-functions.adoc | 10 +- .../functions/mistralai-chat-functions.adoc | 12 +- .../chat/functions/openai-chat-functions.adoc | 20 +- .../vertexai-gemini-chat-functions.adoc | 14 +- .../ROOT/pages/api/chat/mistralai-chat.adoc | 8 +- .../ROOT/pages/api/chat/ollama-chat.adoc | 12 +- .../ROOT/pages/api/chat/openai-chat.adoc | 8 +- .../pages/api/chat/vertexai-gemini-chat.adoc | 6 +- .../pages/api/chat/vertexai-palm2-chat.adoc | 6 +- .../ROOT/pages/api/chat/watsonx-ai-chat.adoc | 2 +- .../modules/ROOT/pages/api/chatclient.adoc | 4 +- .../embeddings/azure-openai-embeddings.adoc | 2 +- .../api/embeddings/mistralai-embeddings.adoc | 6 +- .../api/embeddings/ollama-embeddings.adoc | 4 +- .../api/embeddings/openai-embeddings.adoc | 6 +- .../antora/modules/ROOT/pages/api/prompt.adoc | 4 +- .../ROOT/pages/api/vectordbs/hana.adoc | 4 +- .../modules/ROOT/pages/upgrade-notes.adoc | 4 +- .../anthropic/AnthropicAutoConfiguration.java | 6 +- .../anthropic/AnthropicChatProperties.java | 8 +- .../openai/AzureOpenAiAutoConfiguration.java | 8 +- ...BedrockAnthropicChatAutoConfiguration.java | 6 +- ...edrockAnthropic3ChatAutoConfiguration.java | 6 +- .../BedrockCohereChatAutoConfiguration.java | 6 +- ...ockAi21Jurassic2ChatAutoConfiguration.java | 8 +- .../BedrockLlamaChatAutoConfiguration.java | 7 +- .../BedrockTitanChatAutoConfiguration.java | 6 +- .../HuggingfaceChatAutoConfiguration.java | 8 +- .../mistralai/MistralAiAutoConfiguration.java | 6 +- .../ollama/OllamaAutoConfiguration.java | 6 +- .../openai/OpenAiAutoConfiguration.java | 11 +- .../VertexAiGeminiAutoConfiguration.java | 11 +- .../gemini/VertexAiGeminiChatProperties.java | 4 +- .../palm2/VertexAiPalm2AutoConfiguration.java | 6 +- .../watsonxai/WatsonxAiAutoConfiguration.java | 6 +- .../AnthropicAutoConfigurationIT.java | 8 +- .../anthropic/AnthropicPropertiesTests.java | 8 +- .../tool/FunctionCallWithFunctionBeanIT.java | 8 +- .../FunctionCallWithPromptFunctionIT.java | 6 +- .../azure/AzureOpenAiAutoConfigurationIT.java | 14 +- .../tool/FunctionCallWithFunctionBeanIT.java | 10 +- .../FunctionCallWithFunctionWrapperIT.java | 6 +- .../FunctionCallWithPromptFunctionIT.java | 6 +- ...drockAnthropicChatAutoConfigurationIT.java | 14 +- ...rockAnthropic3ChatAutoConfigurationIT.java | 14 +- .../BedrockCohereChatAutoConfigurationIT.java | 14 +- ...kAi21Jurassic2ChatAutoConfigurationIT.java | 14 +- .../BedrockLlamaChatAutoConfigurationIT.java | 14 +- .../BedrockTitanChatAutoConfigurationIT.java | 14 +- .../MistralAiAutoConfigurationIT.java | 8 +- .../mistralai/tool/PaymentStatusBeanIT.java | 6 +- .../tool/PaymentStatusBeanOpenAiIT.java | 8 +- .../mistralai/tool/PaymentStatusPromptIT.java | 6 +- .../tool/WeatherServicePromptIT.java | 6 +- .../ollama/OllamaChatAutoConfigurationIT.java | 14 +- .../openai/OpenAiAutoConfigurationIT.java | 13 +- .../openai/OpenAiPropertiesTests.java | 8 +- .../tool/FunctionCallbackInPromptIT.java | 8 +- ...nctionCallbackWithPlainFunctionBeanIT.java | 14 +- .../tool/FunctionCallbackWrapperIT.java | 8 +- .../VertexAiGeminiAutoConfigurationIT.java | 8 +- .../tool/FunctionCallWithFunctionBeanIT.java | 18 +- .../FunctionCallWithFunctionWrapperIT.java | 8 +- .../FunctionCallWithPromptFunctionIT.java | 10 +- .../VertexAiPaLm2AutoConfigurationIT.java | 12 +- .../ai/evaluation/BasicEvaluationTest.java | 8 +- .../CricketWorldCupHanaController.java | 10 +- 157 files changed, 1026 insertions(+), 809 deletions(-) rename models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/{AnthropicChatClient.java => AnthropicChatConnector.java} (94%) rename models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/{AnthropicChatClientIT.java => AnthropicChatConnectorIT.java} (92%) rename models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/{AzureOpenAiChatClient.java => AzureOpenAiChatConnector.java} (96%) rename models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/{AzureOpenAiChatClientIT.java => AzureOpenAiChatConnectorIT.java} (91%) rename models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/function/{AzureOpenAiChatClientFunctionCallIT.java => AzureOpenAiChatConnectorFunctionCallIT.java} (89%) rename models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/metadata/{AzureOpenAiChatClientMetadataTests.java => AzureOpenAiChatConnectorMetadataTests.java} (95%) rename models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic/{BedrockAnthropicChatClient.java => BedrockAnthropicChatConnector.java} (88%) rename models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic3/{BedrockAnthropic3ChatClient.java => BedrockAnthropic3ChatConnector.java} (92%) rename models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/cohere/{BedrockCohereChatClient.java => BedrockCohereChatConnector.java} (91%) rename models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/jurassic2/{BedrockAi21Jurassic2ChatClient.java => BedrockAi21Jurassic2ChatConnector.java} (87%) rename models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/llama/{BedrockLlamaChatClient.java => BedrockLlamaChatConnector.java} (90%) rename models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/{BedrockTitanChatClient.java => BedrockTitanChatConnector.java} (93%) rename models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic/{BedrockAnthropicChatClientIT.java => BedrockAnthropicChatConnectorIT.java} (93%) rename models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic3/{BedrockAnthropic3ChatClientIT.java => BedrockAnthropic3ChatConnectorIT.java} (93%) rename models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/cohere/{BedrockCohereChatClientIT.java => BedrockCohereChatConnectorIT.java} (94%) rename models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/jurassic2/{BedrockAi21Jurassic2ChatClientIT.java => BedrockAi21Jurassic2ChatConnectorIT.java} (92%) rename models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/llama/{BedrockLlamaChatClientIT.java => BedrockLlamaChatConnectorIT.java} (94%) rename models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/titan/{BedrockTitanChatClientIT.java => BedrockTitanChatConnectorIT.java} (94%) rename models/spring-ai-huggingface/src/main/java/org/springframework/ai/huggingface/{HuggingfaceChatClient.java => HuggingfaceChatConnector.java} (90%) rename models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/{MistralAiChatClient.java => MistralAiChatConnector.java} (96%) rename models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/{MistralAiChatClientIT.java => MistralAiChatConnectorIT.java} (93%) rename models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/{OllamaChatClient.java => OllamaChatConnector.java} (92%) rename models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/{OllamaChatClientIT.java => OllamaChatConnectorIT.java} (92%) rename models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/{OllamaChatClientMultimodalIT.java => OllamaChatConnectorMultimodalIT.java} (90%) rename models/spring-ai-openai/src/main/java/org/springframework/ai/openai/{OpenAiChatClient.java => OpenAiChatConnector.java} (95%) create mode 100644 models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatClientTest.java rename models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/{OpenAiChatClient2IT.java => OpenAiChatConnector2IT.java} (89%) rename models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/{OpenAiChatClientIT.java => OpenAiChatConnectorIT.java} (92%) rename models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/{VertexAiGeminiChatClient.java => VertexAiGeminiChatConnector.java} (96%) rename models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/{VertexAiGeminiChatClientIT.java => VertexAiGeminiChatConnectorIT.java} (93%) rename models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/function/{VertexAiGeminiChatClientFunctionCallingIT.java => VertexAiGeminiChatConnectorFunctionCallingIT.java} (86%) rename models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/{VertexAiPaLm2ChatClient.java => VertexAiPaLm2ChatConnector.java} (91%) rename models/spring-ai-watsonx-ai/src/main/java/org/springframework/ai/watsonx/{WatsonxAiChatClient.java => WatsonxAiChatConnector.java} (92%) rename models/spring-ai-watsonx-ai/src/test/java/org/springframework/ai/watsonx/{WatsonxAiChatClientTest.java => WatsonxAiChatConnectorTest.java} (96%) create mode 100644 spring-ai-core/src/main/java/org/springframework/ai/chat/connector/ChatConnector.java rename spring-ai-core/src/test/java/org/springframework/ai/chat/{ChatClientTests.java => ChatConnectorTests.java} (84%) diff --git a/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatClient.java b/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatConnector.java similarity index 94% rename from models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatClient.java rename to models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatConnector.java index 0f9bcbf44..e123d336d 100644 --- a/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatClient.java +++ b/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatConnector.java @@ -26,6 +26,7 @@ import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.ai.chat.connector.ChatConnector; import reactor.core.publisher.Flux; import org.springframework.ai.anthropic.api.AnthropicApi; @@ -38,7 +39,6 @@ import org.springframework.ai.anthropic.api.AnthropicApi.Role; import org.springframework.ai.anthropic.api.AnthropicApi.StreamResponse; import org.springframework.ai.anthropic.api.AnthropicApi.Usage; import org.springframework.ai.anthropic.metadata.AnthropicChatResponseMetadata; -import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.StreamingChatClient; @@ -56,16 +56,16 @@ import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; /** - * The {@link ChatClient} implementation for the Anthropic service. + * The {@link ChatConnector} implementation for the Anthropic service. * * @author Christian Tzolov * @since 1.0.0 */ -public class AnthropicChatClient extends +public class AnthropicChatConnector extends AbstractFunctionCallSupport> - implements ChatClient, StreamingChatClient { + implements ChatConnector, StreamingChatClient { - private static final Logger logger = LoggerFactory.getLogger(AnthropicChatClient.class); + private static final Logger logger = LoggerFactory.getLogger(AnthropicChatConnector.class); public static final String DEFAULT_MODEL_NAME = AnthropicApi.ChatModel.CLAUDE_3_OPUS.getValue(); @@ -89,10 +89,10 @@ public class AnthropicChatClient extends public final RetryTemplate retryTemplate; /** - * Construct a new {@link AnthropicChatClient} instance. + * Construct a new {@link AnthropicChatConnector} instance. * @param anthropicApi the lower-level API for the Anthropic service. */ - public AnthropicChatClient(AnthropicApi anthropicApi) { + public AnthropicChatConnector(AnthropicApi anthropicApi) { this(anthropicApi, AnthropicChatOptions.builder() .withModel(DEFAULT_MODEL_NAME) @@ -102,34 +102,34 @@ public class AnthropicChatClient extends } /** - * Construct a new {@link AnthropicChatClient} instance. + * Construct a new {@link AnthropicChatConnector} instance. * @param anthropicApi the lower-level API for the Anthropic service. * @param defaultOptions the default options used for the chat completion requests. */ - public AnthropicChatClient(AnthropicApi anthropicApi, AnthropicChatOptions defaultOptions) { + public AnthropicChatConnector(AnthropicApi anthropicApi, AnthropicChatOptions defaultOptions) { this(anthropicApi, defaultOptions, RetryUtils.DEFAULT_RETRY_TEMPLATE); } /** - * Construct a new {@link AnthropicChatClient} instance. + * Construct a new {@link AnthropicChatConnector} instance. * @param anthropicApi the lower-level API for the Anthropic service. * @param defaultOptions the default options used for the chat completion requests. * @param retryTemplate the retry template used to retry the Anthropic API calls. */ - public AnthropicChatClient(AnthropicApi anthropicApi, AnthropicChatOptions defaultOptions, + public AnthropicChatConnector(AnthropicApi anthropicApi, AnthropicChatOptions defaultOptions, RetryTemplate retryTemplate) { this(anthropicApi, defaultOptions, retryTemplate, null); } /** - * Construct a new {@link AnthropicChatClient} instance. + * Construct a new {@link AnthropicChatConnector} instance. * @param anthropicApi the lower-level API for the Anthropic service. * @param defaultOptions the default options used for the chat completion requests. * @param retryTemplate the retry template used to retry the Anthropic API calls. * @param functionCallbackContext the function callback context used to store the * state of the function calls. */ - public AnthropicChatClient(AnthropicApi anthropicApi, AnthropicChatOptions defaultOptions, + public AnthropicChatConnector(AnthropicApi anthropicApi, AnthropicChatOptions defaultOptions, RetryTemplate retryTemplate, FunctionCallbackContext functionCallbackContext) { super(functionCallbackContext); @@ -144,7 +144,7 @@ public class AnthropicChatClient extends } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { ChatCompletionRequest request = createRequest(prompt, false); diff --git a/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatOptions.java b/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatOptions.java index 7cd7bdb23..f5de6d33a 100644 --- a/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatOptions.java +++ b/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatOptions.java @@ -51,11 +51,11 @@ public class AnthropicChatOptions implements ChatOptions, FunctionCallingOptions private @JsonProperty("top_k") Integer topK; /** - * Tool Function Callbacks to register with the ChatClient. For Prompt + * Tool Function Callbacks to register with the ChatConnector. For Prompt * Options the functionCallbacks are automatically enabled for the duration of the * prompt execution. For Default Options the functionCallbacks are registered but * disabled by default. Use the enableFunctions to set the functions from the registry - * to be used by the ChatClient chat completion requests. + * to be used by the ChatConnector chat completion requests. */ @NestedConfigurationProperty @JsonIgnore diff --git a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatClientIT.java b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatConnectorIT.java similarity index 92% rename from models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatClientIT.java rename to models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatConnectorIT.java index ce5b45d37..c8dff1c4b 100644 --- a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatClientIT.java +++ b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatConnectorIT.java @@ -29,7 +29,7 @@ import org.slf4j.LoggerFactory; import org.springframework.ai.anthropic.api.AnthropicApi; import org.springframework.ai.anthropic.api.tool.MockWeatherService; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.StreamingChatClient; @@ -56,12 +56,12 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(classes = AnthropicTestConfiguration.class, properties = "spring.ai.retry.on-http-codes=429") @EnabledIfEnvironmentVariable(named = "ANTHROPIC_API_KEY", matches = ".+") -class AnthropicChatClientIT { +class AnthropicChatConnectorIT { - private static final Logger logger = LoggerFactory.getLogger(AnthropicChatClientIT.class); + private static final Logger logger = LoggerFactory.getLogger(AnthropicChatConnectorIT.class); @Autowired - protected ChatClient chatClient; + protected ChatConnector chatConnector; @Autowired protected StreamingChatClient streamingChatClient; @@ -76,7 +76,7 @@ class AnthropicChatClientIT { SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource); Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", "Bob", "voice", "pirate")); Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = chatClient.call(prompt); + ChatResponse response = chatConnector.execute(prompt); assertThat(response.getResults()).hasSize(1); assertThat(response.getMetadata().getUsage().getGenerationTokens()).isGreaterThan(0); assertThat(response.getMetadata().getUsage().getPromptTokens()).isGreaterThan(0); @@ -102,7 +102,7 @@ class AnthropicChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "ice cream flavors", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.chatClient.call(prompt).getResult(); + Generation generation = this.chatConnector.execute(prompt).getResult(); List list = listOutputConverter.convert(generation.getOutput().getContent()); assertThat(list).hasSize(5); @@ -120,7 +120,7 @@ class AnthropicChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = chatClient.call(prompt).getResult(); + Generation generation = chatConnector.execute(prompt).getResult(); Map result = mapOutputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -142,7 +142,7 @@ class AnthropicChatClientIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = chatClient.call(prompt).getResult(); + Generation generation = chatConnector.execute(prompt).getResult(); ActorsFilmsRecord actorsFilms = beanOutputConverter.convert(generation.getOutput().getContent()); logger.info("" + actorsFilms); @@ -187,14 +187,14 @@ class AnthropicChatClientIT { var userMessage = new UserMessage("Explain what do you see on this picture?", List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageData))); - var response = chatClient.call(new Prompt(List.of(userMessage))); + var response = chatConnector.execute(new Prompt(List.of(userMessage))); logger.info(response.getResult().getOutput().getContent()); assertThat(response.getResult().getOutput().getContent()).contains("bananas", "apple", "basket"); } @Test - void functionCallTest() { + void functionExecuteTest() { UserMessage userMessage = new UserMessage( "What's the weather like in San Francisco, Tokyo and Paris? Return the result in Celsius."); @@ -209,7 +209,7 @@ class AnthropicChatClientIT { .build())) .build(); - ChatResponse response = chatClient.call(new Prompt(messages, promptOptions)); + ChatResponse response = chatConnector.execute(new Prompt(messages, promptOptions)); logger.info("Response: {}", response); diff --git a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicTestConfiguration.java b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicTestConfiguration.java index 649fbef1a..3fe3345ec 100644 --- a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicTestConfiguration.java +++ b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicTestConfiguration.java @@ -38,8 +38,8 @@ public class AnthropicTestConfiguration { } @Bean - public AnthropicChatClient openAiChatClient(AnthropicApi api) { - AnthropicChatClient anthropicChatClient = new AnthropicChatClient(api); + public AnthropicChatConnector openAiChatClient(AnthropicApi api) { + AnthropicChatConnector anthropicChatClient = new AnthropicChatConnector(api); return anthropicChatClient; } diff --git a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/ChatCompletionRequestTests.java b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/ChatCompletionRequestTests.java index bc777a846..c0e343ac2 100644 --- a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/ChatCompletionRequestTests.java +++ b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/ChatCompletionRequestTests.java @@ -30,7 +30,7 @@ public class ChatCompletionRequestTests { @Test public void createRequestWithChatOptions() { - var client = new AnthropicChatClient(new AnthropicApi("TEST"), + var client = new AnthropicChatConnector(new AnthropicApi("TEST"), AnthropicChatOptions.builder().withModel("DEFAULT_MODEL").withTemperature(66.6f).build()); var request = client.createRequest(new Prompt("Test message content"), false); diff --git a/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatClient.java b/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatConnector.java similarity index 96% rename from models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatClient.java rename to models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatConnector.java index a49a42ff5..e2fd74d6c 100644 --- a/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatClient.java +++ b/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatConnector.java @@ -38,7 +38,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.azure.openai.metadata.AzureOpenAiChatResponseMetadata; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.StreamingChatClient; @@ -63,7 +63,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** - * {@link ChatClient} implementation for {@literal Microsoft Azure AI} backed by + * {@link ChatConnector} implementation for {@literal Microsoft Azure AI} backed by * {@link OpenAIClient}. * * @author Mark Pollack @@ -71,12 +71,12 @@ import java.util.concurrent.atomic.AtomicBoolean; * @author John Blum * @author Christian Tzolov * @author Grogdunn - * @see ChatClient + * @see ChatConnector * @see com.azure.ai.openai.OpenAIClient */ -public class AzureOpenAiChatClient +public class AzureOpenAiChatConnector extends AbstractFunctionCallSupport - implements ChatClient, StreamingChatClient { + implements ChatConnector, StreamingChatClient { private static final String DEFAULT_DEPLOYMENT_NAME = "gpt-35-turbo"; @@ -94,7 +94,7 @@ public class AzureOpenAiChatClient */ private final OpenAIClient openAIClient; - public AzureOpenAiChatClient(OpenAIClient microsoftOpenAiClient) { + public AzureOpenAiChatConnector(OpenAIClient microsoftOpenAiClient) { this(microsoftOpenAiClient, AzureOpenAiChatOptions.builder() .withDeploymentName(DEFAULT_DEPLOYMENT_NAME) @@ -102,11 +102,11 @@ public class AzureOpenAiChatClient .build()); } - public AzureOpenAiChatClient(OpenAIClient microsoftOpenAiClient, AzureOpenAiChatOptions options) { + public AzureOpenAiChatConnector(OpenAIClient microsoftOpenAiClient, AzureOpenAiChatOptions options) { this(microsoftOpenAiClient, options, null); } - public AzureOpenAiChatClient(OpenAIClient microsoftOpenAiClient, AzureOpenAiChatOptions options, + public AzureOpenAiChatConnector(OpenAIClient microsoftOpenAiClient, AzureOpenAiChatOptions options, FunctionCallbackContext functionCallbackContext) { super(functionCallbackContext); Assert.notNull(microsoftOpenAiClient, "com.azure.ai.openai.OpenAIClient must not be null"); @@ -117,10 +117,10 @@ public class AzureOpenAiChatClient /** * @deprecated since 0.8.0, use - * {@link #AzureOpenAiChatClient(OpenAIClient, AzureOpenAiChatOptions)} instead. + * {@link #AzureOpenAiChatConnector(OpenAIClient, AzureOpenAiChatOptions)} instead. */ @Deprecated(forRemoval = true, since = "0.8.0") - public AzureOpenAiChatClient withDefaultOptions(AzureOpenAiChatOptions defaultOptions) { + public AzureOpenAiChatConnector withDefaultOptions(AzureOpenAiChatOptions defaultOptions) { Assert.notNull(defaultOptions, "DefaultOptions must not be null"); this.defaultOptions = defaultOptions; return this; @@ -131,7 +131,7 @@ public class AzureOpenAiChatClient } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { ChatCompletionsOptions options = toAzureChatCompletionsOptions(prompt); options.setStream(false); diff --git a/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatOptions.java b/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatOptions.java index 681285ecc..dd7585ac9 100644 --- a/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatOptions.java +++ b/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatOptions.java @@ -127,11 +127,11 @@ public class AzureOpenAiChatOptions implements FunctionCallingOptions, ChatOptio private String deploymentName; /** - * OpenAI Tool Function Callbacks to register with the ChatClient. For Prompt Options - * the functionCallbacks are automatically enabled for the duration of the prompt - * execution. For Default Options the functionCallbacks are registered but disabled by - * default. Use the enableFunctions to set the functions from the registry to be used - * by the ChatClient chat completion requests. + * OpenAI Tool Function Callbacks to register with the ChatConnector. For Prompt + * Options the functionCallbacks are automatically enabled for the duration of the + * prompt execution. For Default Options the functionCallbacks are registered but + * disabled by default. Use the enableFunctions to set the functions from the registry + * to be used by the ChatConnector chat completion requests. */ @NestedConfigurationProperty @JsonIgnore diff --git a/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureChatCompletionsOptionsTests.java b/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureChatCompletionsOptionsTests.java index 1e0ba2939..93407c4cd 100644 --- a/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureChatCompletionsOptionsTests.java +++ b/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureChatCompletionsOptionsTests.java @@ -53,7 +53,7 @@ public class AzureChatCompletionsOptionsTests { .withUser("user") .build(); - var client = new AzureOpenAiChatClient(mockClient, defaultOptions); + var client = new AzureOpenAiChatConnector(mockClient, defaultOptions); var requestOptions = client.toAzureChatCompletionsOptions(new Prompt("Test message content")); diff --git a/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureOpenAiChatClientIT.java b/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureOpenAiChatConnectorIT.java similarity index 91% rename from models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureOpenAiChatClientIT.java rename to models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureOpenAiChatConnectorIT.java index 253e13d57..e52439722 100644 --- a/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureOpenAiChatClientIT.java +++ b/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureOpenAiChatConnectorIT.java @@ -46,13 +46,13 @@ import org.springframework.core.convert.support.DefaultConversionService; import static org.assertj.core.api.Assertions.assertThat; -@SpringBootTest(classes = AzureOpenAiChatClientIT.TestConfiguration.class) +@SpringBootTest(classes = AzureOpenAiChatConnectorIT.TestConfiguration.class) @EnabledIfEnvironmentVariable(named = "AZURE_OPENAI_API_KEY", matches = ".+") @EnabledIfEnvironmentVariable(named = "AZURE_OPENAI_ENDPOINT", matches = ".+") -class AzureOpenAiChatClientIT { +class AzureOpenAiChatConnectorIT { @Autowired - private AzureOpenAiChatClient chatClient; + private AzureOpenAiChatConnector chatClient; record ActorsFilms(String actor, List movies) { } @@ -69,7 +69,7 @@ class AzureOpenAiChatClientIT { UserMessage userMessage = new UserMessage("Generate the names of 5 famous pirates."); Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = chatClient.call(prompt); + ChatResponse response = chatClient.execute(prompt); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); } @@ -86,7 +86,7 @@ class AzureOpenAiChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "ice cream flavors", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = chatClient.call(prompt).getResult(); + Generation generation = chatClient.execute(prompt).getResult(); List list = outputConverter.convert(generation.getOutput().getContent()); assertThat(list).hasSize(5); @@ -105,7 +105,7 @@ class AzureOpenAiChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = chatClient.call(prompt).getResult(); + Generation generation = chatClient.execute(prompt).getResult(); Map result = outputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -124,7 +124,7 @@ class AzureOpenAiChatClientIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = chatClient.call(prompt).getResult(); + Generation generation = chatClient.execute(prompt).getResult(); ActorsFilms actorsFilms = outputConverter.convert(generation.getOutput().getContent()); assertThat(actorsFilms.actor()).isNotNull(); @@ -145,7 +145,7 @@ class AzureOpenAiChatClientIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = chatClient.call(prompt).getResult(); + Generation generation = chatClient.execute(prompt).getResult(); ActorsFilmsRecord actorsFilms = outputConverter.convert(generation.getOutput().getContent()); System.out.println(actorsFilms); @@ -194,8 +194,8 @@ class AzureOpenAiChatClientIT { } @Bean - public AzureOpenAiChatClient azureOpenAiChatClient(OpenAIClient openAIClient) { - return new AzureOpenAiChatClient(openAIClient, + public AzureOpenAiChatConnector azureOpenAiChatClient(OpenAIClient openAIClient) { + return new AzureOpenAiChatConnector(openAIClient, AzureOpenAiChatOptions.builder().withDeploymentName("gpt-35-turbo").withMaxTokens(200).build()); } diff --git a/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/MockAzureOpenAiTestConfiguration.java b/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/MockAzureOpenAiTestConfiguration.java index f5e7b438a..f96328b4b 100644 --- a/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/MockAzureOpenAiTestConfiguration.java +++ b/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/MockAzureOpenAiTestConfiguration.java @@ -59,8 +59,8 @@ public class MockAzureOpenAiTestConfiguration { } @Bean - AzureOpenAiChatClient azureOpenAiChatClient(OpenAIClient microsoftAzureOpenAiClient) { - return new AzureOpenAiChatClient(microsoftAzureOpenAiClient); + AzureOpenAiChatConnector azureOpenAiChatClient(OpenAIClient microsoftAzureOpenAiClient) { + return new AzureOpenAiChatConnector(microsoftAzureOpenAiClient); } } diff --git a/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/function/AzureOpenAiChatClientFunctionCallIT.java b/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/function/AzureOpenAiChatConnectorFunctionCallIT.java similarity index 89% rename from models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/function/AzureOpenAiChatClientFunctionCallIT.java rename to models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/function/AzureOpenAiChatConnectorFunctionCallIT.java index 08c81ebd1..32a02f077 100644 --- a/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/function/AzureOpenAiChatClientFunctionCallIT.java +++ b/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/function/AzureOpenAiChatConnectorFunctionCallIT.java @@ -29,7 +29,7 @@ import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.ai.azure.openai.AzureOpenAiChatClient; +import org.springframework.ai.azure.openai.AzureOpenAiChatConnector; import org.springframework.ai.azure.openai.AzureOpenAiChatOptions; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; @@ -46,21 +46,21 @@ import reactor.core.publisher.Flux; import static org.assertj.core.api.Assertions.assertThat; -@SpringBootTest(classes = AzureOpenAiChatClientFunctionCallIT.TestConfiguration.class) +@SpringBootTest(classes = AzureOpenAiChatConnectorFunctionCallIT.TestConfiguration.class) @EnabledIfEnvironmentVariable(named = "AZURE_OPENAI_API_KEY", matches = ".+") @EnabledIfEnvironmentVariable(named = "AZURE_OPENAI_ENDPOINT", matches = ".+") -class AzureOpenAiChatClientFunctionCallIT { +class AzureOpenAiChatConnectorFunctionCallIT { - private static final Logger logger = LoggerFactory.getLogger(AzureOpenAiChatClientFunctionCallIT.class); + private static final Logger logger = LoggerFactory.getLogger(AzureOpenAiChatConnectorFunctionCallIT.class); @Autowired private String selectedModel; @Autowired - private AzureOpenAiChatClient chatClient; + private AzureOpenAiChatConnector chatClient; @Test - void functionCallTest() { + void functionExecuteTest() { UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, in Tokyo, and in Paris?"); @@ -75,7 +75,7 @@ class AzureOpenAiChatClientFunctionCallIT { .build())) .build(); - ChatResponse response = chatClient.call(new Prompt(messages, promptOptions)); + ChatResponse response = chatClient.execute(new Prompt(messages, promptOptions)); logger.info("Response: {}", response); @@ -85,7 +85,7 @@ class AzureOpenAiChatClientFunctionCallIT { } @Test - void streamFunctionCallTest() { + void streamFunctionExecuteTest() { UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?"); List messages = new ArrayList<>(List.of(userMessage)); @@ -129,8 +129,8 @@ class AzureOpenAiChatClientFunctionCallIT { } @Bean - public AzureOpenAiChatClient azureOpenAiChatClient(OpenAIClient openAIClient, String selectedModel) { - return new AzureOpenAiChatClient(openAIClient, + public AzureOpenAiChatConnector azureOpenAiChatClient(OpenAIClient openAIClient, String selectedModel) { + return new AzureOpenAiChatConnector(openAIClient, AzureOpenAiChatOptions.builder().withDeploymentName(selectedModel).withMaxTokens(500).build()); } diff --git a/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/metadata/AzureOpenAiChatClientMetadataTests.java b/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/metadata/AzureOpenAiChatConnectorMetadataTests.java similarity index 95% rename from models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/metadata/AzureOpenAiChatClientMetadataTests.java rename to models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/metadata/AzureOpenAiChatConnectorMetadataTests.java index cc938c9b9..ca8fddc53 100644 --- a/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/metadata/AzureOpenAiChatClientMetadataTests.java +++ b/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/metadata/AzureOpenAiChatConnectorMetadataTests.java @@ -23,7 +23,7 @@ import com.azure.ai.openai.models.ContentFilterResultsForChoice; import com.azure.ai.openai.models.ContentFilterSeverity; import org.junit.jupiter.api.Test; -import org.springframework.ai.azure.openai.AzureOpenAiChatClient; +import org.springframework.ai.azure.openai.AzureOpenAiChatConnector; import org.springframework.ai.azure.openai.MockAzureOpenAiTestConfiguration; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; @@ -55,7 +55,7 @@ import org.springframework.web.context.request.WebRequest; import static org.assertj.core.api.Assertions.assertThat; /** - * Unit Tests for {@link AzureOpenAiChatClient} asserting AI metadata. + * Unit Tests for {@link AzureOpenAiChatConnector} asserting AI metadata. * * @author John Blum * @author Christian Tzolov @@ -63,19 +63,19 @@ import static org.assertj.core.api.Assertions.assertThat; */ @SpringBootTest @ActiveProfiles("spring-ai-azure-openai-mocks") -@ContextConfiguration(classes = AzureOpenAiChatClientMetadataTests.TestConfiguration.class) +@ContextConfiguration(classes = AzureOpenAiChatConnectorMetadataTests.TestConfiguration.class) @SuppressWarnings("unused") -class AzureOpenAiChatClientMetadataTests { +class AzureOpenAiChatConnectorMetadataTests { @Autowired - private AzureOpenAiChatClient aiClient; + private AzureOpenAiChatConnector aiClient; @Test void azureOpenAiMetadataCapturedDuringGeneration() { Prompt prompt = new Prompt("Can I fly like a bird?"); - ChatResponse response = this.aiClient.call(prompt); + ChatResponse response = this.aiClient.execute(prompt); assertThat(response).isNotNull(); diff --git a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatClient.java b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatConnector.java similarity index 88% rename from models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatClient.java rename to models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatConnector.java index 26b887344..e80201bc2 100644 --- a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatClient.java +++ b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatConnector.java @@ -17,7 +17,7 @@ package org.springframework.ai.bedrock.anthropic; import java.util.List; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.metadata.ChatGenerationMetadata; @@ -33,19 +33,19 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.ModelOptionsUtils; /** - * Java {@link ChatClient} and {@link StreamingChatClient} for the Bedrock Anthropic chat - * generative. + * Java {@link ChatConnector} and {@link StreamingChatClient} for the Bedrock Anthropic + * chat generative. * * @author Christian Tzolov * @since 0.8.0 */ -public class BedrockAnthropicChatClient implements ChatClient, StreamingChatClient { +public class BedrockAnthropicChatConnector implements ChatConnector, StreamingChatClient { private final AnthropicChatBedrockApi anthropicChatApi; private final AnthropicChatOptions defaultOptions; - public BedrockAnthropicChatClient(AnthropicChatBedrockApi chatApi) { + public BedrockAnthropicChatConnector(AnthropicChatBedrockApi chatApi) { this(chatApi, AnthropicChatOptions.builder() .withTemperature(0.8f) @@ -55,13 +55,13 @@ public class BedrockAnthropicChatClient implements ChatClient, StreamingChatClie .build()); } - public BedrockAnthropicChatClient(AnthropicChatBedrockApi chatApi, AnthropicChatOptions options) { + public BedrockAnthropicChatConnector(AnthropicChatBedrockApi chatApi, AnthropicChatOptions options) { this.anthropicChatApi = chatApi; this.defaultOptions = options; } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { AnthropicChatRequest request = createRequest(prompt); diff --git a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatClient.java b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatConnector.java similarity index 92% rename from models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatClient.java rename to models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatConnector.java index 12dba850c..12805f5b7 100644 --- a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatClient.java +++ b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatConnector.java @@ -22,7 +22,7 @@ import org.springframework.ai.bedrock.anthropic3.api.Anthropic3ChatBedrockApi.An import org.springframework.ai.bedrock.anthropic3.api.Anthropic3ChatBedrockApi.MediaContent; import org.springframework.ai.bedrock.anthropic3.api.Anthropic3ChatBedrockApi.ChatCompletionMessage; import org.springframework.ai.bedrock.anthropic3.api.Anthropic3ChatBedrockApi.ChatCompletionMessage.Role; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.StreamingChatClient; @@ -43,20 +43,20 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; /** - * Java {@link ChatClient} and {@link StreamingChatClient} for the Bedrock Anthropic chat - * generative. + * Java {@link ChatConnector} and {@link StreamingChatClient} for the Bedrock Anthropic + * chat generative. * * @author Ben Middleton * @author Christian Tzolov * @since 1.0.0 */ -public class BedrockAnthropic3ChatClient implements ChatClient, StreamingChatClient { +public class BedrockAnthropic3ChatConnector implements ChatConnector, StreamingChatClient { private final Anthropic3ChatBedrockApi anthropicChatApi; private final Anthropic3ChatOptions defaultOptions; - public BedrockAnthropic3ChatClient(Anthropic3ChatBedrockApi chatApi) { + public BedrockAnthropic3ChatConnector(Anthropic3ChatBedrockApi chatApi) { this(chatApi, Anthropic3ChatOptions.builder() .withTemperature(0.8f) @@ -66,13 +66,13 @@ public class BedrockAnthropic3ChatClient implements ChatClient, StreamingChatCli .build()); } - public BedrockAnthropic3ChatClient(Anthropic3ChatBedrockApi chatApi, Anthropic3ChatOptions options) { + public BedrockAnthropic3ChatConnector(Anthropic3ChatBedrockApi chatApi, Anthropic3ChatOptions options) { this.anthropicChatApi = chatApi; this.defaultOptions = options; } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { AnthropicChatRequest request = createRequest(prompt); diff --git a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatClient.java b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatConnector.java similarity index 91% rename from models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatClient.java rename to models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatConnector.java index 3ff2b2cee..a2e84923b 100644 --- a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatClient.java +++ b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatConnector.java @@ -17,6 +17,7 @@ package org.springframework.ai.bedrock.cohere; import java.util.List; +import org.springframework.ai.chat.connector.ChatConnector; import reactor.core.publisher.Flux; import org.springframework.ai.bedrock.BedrockUsage; @@ -24,7 +25,6 @@ import org.springframework.ai.bedrock.MessageToPromptConverter; import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi; import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi.CohereChatRequest; import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi.CohereChatResponse; -import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; @@ -39,17 +39,17 @@ import org.springframework.util.Assert; * @author Christian Tzolov * @since 0.8.0 */ -public class BedrockCohereChatClient implements ChatClient, StreamingChatClient { +public class BedrockCohereChatConnector implements ChatConnector, StreamingChatClient { private final CohereChatBedrockApi chatApi; private final BedrockCohereChatOptions defaultOptions; - public BedrockCohereChatClient(CohereChatBedrockApi chatApi) { + public BedrockCohereChatConnector(CohereChatBedrockApi chatApi) { this(chatApi, BedrockCohereChatOptions.builder().build()); } - public BedrockCohereChatClient(CohereChatBedrockApi chatApi, BedrockCohereChatOptions options) { + public BedrockCohereChatConnector(CohereChatBedrockApi chatApi, BedrockCohereChatOptions options) { Assert.notNull(chatApi, "CohereChatBedrockApi must not be null"); Assert.notNull(options, "BedrockCohereChatOptions must not be null"); @@ -58,7 +58,7 @@ public class BedrockCohereChatClient implements ChatClient, StreamingChatClient } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { CohereChatResponse response = this.chatApi.chatCompletion(this.createRequest(prompt, false)); List generations = response.generations().stream().map(g -> { return new Generation(g.text()); diff --git a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatClient.java b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatConnector.java similarity index 87% rename from models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatClient.java rename to models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatConnector.java index 7a11a2524..e820a8a51 100644 --- a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatClient.java +++ b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatConnector.java @@ -19,7 +19,7 @@ package org.springframework.ai.bedrock.jurassic2; import org.springframework.ai.bedrock.MessageToPromptConverter; import org.springframework.ai.bedrock.jurassic2.api.Ai21Jurassic2ChatBedrockApi; import org.springframework.ai.bedrock.jurassic2.api.Ai21Jurassic2ChatBedrockApi.Ai21Jurassic2ChatRequest; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.metadata.ChatGenerationMetadata; @@ -29,18 +29,18 @@ import org.springframework.ai.model.ModelOptionsUtils; import org.springframework.util.Assert; /** - * Java {@link ChatClient} for the Bedrock Jurassic2 chat generative model. + * Java {@link ChatConnector} for the Bedrock Jurassic2 chat generative model. * * @author Ahmed Yousri * @since 1.0.0 */ -public class BedrockAi21Jurassic2ChatClient implements ChatClient { +public class BedrockAi21Jurassic2ChatConnector implements ChatConnector { private final Ai21Jurassic2ChatBedrockApi chatApi; private final BedrockAi21Jurassic2ChatOptions defaultOptions; - public BedrockAi21Jurassic2ChatClient(Ai21Jurassic2ChatBedrockApi chatApi, + public BedrockAi21Jurassic2ChatConnector(Ai21Jurassic2ChatBedrockApi chatApi, BedrockAi21Jurassic2ChatOptions options) { Assert.notNull(chatApi, "Ai21Jurassic2ChatBedrockApi must not be null"); Assert.notNull(options, "BedrockAi21Jurassic2ChatOptions must not be null"); @@ -49,7 +49,7 @@ public class BedrockAi21Jurassic2ChatClient implements ChatClient { this.defaultOptions = options; } - public BedrockAi21Jurassic2ChatClient(Ai21Jurassic2ChatBedrockApi chatApi) { + public BedrockAi21Jurassic2ChatConnector(Ai21Jurassic2ChatBedrockApi chatApi) { this(chatApi, BedrockAi21Jurassic2ChatOptions.builder() .withTemperature(0.8f) @@ -59,7 +59,7 @@ public class BedrockAi21Jurassic2ChatClient implements ChatClient { } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { var request = createRequest(prompt); var response = this.chatApi.chatCompletion(request); @@ -114,8 +114,8 @@ public class BedrockAi21Jurassic2ChatClient implements ChatClient { return this; } - public BedrockAi21Jurassic2ChatClient build() { - return new BedrockAi21Jurassic2ChatClient(chatApi, + public BedrockAi21Jurassic2ChatConnector build() { + return new BedrockAi21Jurassic2ChatConnector(chatApi, options != null ? options : BedrockAi21Jurassic2ChatOptions.builder().build()); } diff --git a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatClient.java b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatConnector.java similarity index 90% rename from models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatClient.java rename to models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatConnector.java index c1be58e5a..0598c4db9 100644 --- a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatClient.java +++ b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatConnector.java @@ -17,13 +17,13 @@ package org.springframework.ai.bedrock.llama; import java.util.List; +import org.springframework.ai.chat.connector.ChatConnector; import reactor.core.publisher.Flux; import org.springframework.ai.bedrock.MessageToPromptConverter; import org.springframework.ai.bedrock.llama.api.LlamaChatBedrockApi; import org.springframework.ai.bedrock.llama.api.LlamaChatBedrockApi.LlamaChatRequest; import org.springframework.ai.bedrock.llama.api.LlamaChatBedrockApi.LlamaChatResponse; -import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; @@ -35,25 +35,25 @@ import org.springframework.ai.model.ModelOptionsUtils; import org.springframework.util.Assert; /** - * Java {@link ChatClient} and {@link StreamingChatClient} for the Bedrock Llama chat + * Java {@link ChatConnector} and {@link StreamingChatClient} for the Bedrock Llama chat * generative. * * @author Christian Tzolov * @author Wei Jiang * @since 0.8.0 */ -public class BedrockLlamaChatClient implements ChatClient, StreamingChatClient { +public class BedrockLlamaChatConnector implements ChatConnector, StreamingChatClient { private final LlamaChatBedrockApi chatApi; private final BedrockLlamaChatOptions defaultOptions; - public BedrockLlamaChatClient(LlamaChatBedrockApi chatApi) { + public BedrockLlamaChatConnector(LlamaChatBedrockApi chatApi) { this(chatApi, BedrockLlamaChatOptions.builder().withTemperature(0.8f).withTopP(0.9f).withMaxGenLen(100).build()); } - public BedrockLlamaChatClient(LlamaChatBedrockApi chatApi, BedrockLlamaChatOptions options) { + public BedrockLlamaChatConnector(LlamaChatBedrockApi chatApi, BedrockLlamaChatOptions options) { Assert.notNull(chatApi, "LlamaChatBedrockApi must not be null"); Assert.notNull(options, "BedrockLlamaChatOptions must not be null"); @@ -62,7 +62,7 @@ public class BedrockLlamaChatClient implements ChatClient, StreamingChatClient { } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { var request = createRequest(prompt); diff --git a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanChatClient.java b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanChatConnector.java similarity index 93% rename from models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanChatClient.java rename to models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanChatConnector.java index e77d8277c..17fc4ce9a 100644 --- a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanChatClient.java +++ b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanChatConnector.java @@ -17,6 +17,7 @@ package org.springframework.ai.bedrock.titan; import java.util.List; +import org.springframework.ai.chat.connector.ChatConnector; import reactor.core.publisher.Flux; import org.springframework.ai.bedrock.MessageToPromptConverter; @@ -24,7 +25,6 @@ import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi; import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi.TitanChatRequest; import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi.TitanChatResponse; import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi.TitanChatResponseChunk; -import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; @@ -39,17 +39,17 @@ import org.springframework.util.Assert; * @author Christian Tzolov * @since 0.8.0 */ -public class BedrockTitanChatClient implements ChatClient, StreamingChatClient { +public class BedrockTitanChatConnector implements ChatConnector, StreamingChatClient { private final TitanChatBedrockApi chatApi; private final BedrockTitanChatOptions defaultOptions; - public BedrockTitanChatClient(TitanChatBedrockApi chatApi) { + public BedrockTitanChatConnector(TitanChatBedrockApi chatApi) { this(chatApi, BedrockTitanChatOptions.builder().withTemperature(0.8f).build()); } - public BedrockTitanChatClient(TitanChatBedrockApi chatApi, BedrockTitanChatOptions defaultOptions) { + public BedrockTitanChatConnector(TitanChatBedrockApi chatApi, BedrockTitanChatOptions defaultOptions) { Assert.notNull(chatApi, "ChatApi must not be null"); Assert.notNull(defaultOptions, "DefaultOptions must not be null"); this.chatApi = chatApi; @@ -57,7 +57,7 @@ public class BedrockTitanChatClient implements ChatClient, StreamingChatClient { } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { TitanChatResponse response = this.chatApi.chatCompletion(this.createRequest(prompt)); List generations = response.results().stream().map(result -> { return new Generation(result.outputText()); diff --git a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatClientIT.java b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatConnectorIT.java similarity index 93% rename from models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatClientIT.java rename to models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatConnectorIT.java index 43eb7e776..3e6259be5 100644 --- a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatClientIT.java +++ b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatConnectorIT.java @@ -55,12 +55,12 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY_ID", matches = ".*") @EnabledIfEnvironmentVariable(named = "AWS_SECRET_ACCESS_KEY", matches = ".*") -class BedrockAnthropicChatClientIT { +class BedrockAnthropicChatConnectorIT { - private static final Logger logger = LoggerFactory.getLogger(BedrockAnthropicChatClientIT.class); + private static final Logger logger = LoggerFactory.getLogger(BedrockAnthropicChatConnectorIT.class); @Autowired - private BedrockAnthropicChatClient client; + private BedrockAnthropicChatConnector client; @Value("classpath:/prompts/system-message.st") private Resource systemResource; @@ -101,7 +101,7 @@ class BedrockAnthropicChatClientIT { Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); } @@ -119,7 +119,7 @@ class BedrockAnthropicChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "ice cream flavors.", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.client.call(prompt).getResult(); + Generation generation = this.client.execute(prompt).getResult(); List list = outputParser.convert(generation.getOutput().getContent()); assertThat(list).hasSize(5); @@ -137,7 +137,7 @@ class BedrockAnthropicChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); Map result = outputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -161,7 +161,7 @@ class BedrockAnthropicChatClientIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); ActorsFilmsRecord actorsFilms = outputConvert.convert(generation.getOutput().getContent()); assertThat(actorsFilms.actor()).isEqualTo("Tom Hanks"); @@ -209,8 +209,8 @@ class BedrockAnthropicChatClientIT { } @Bean - public BedrockAnthropicChatClient anthropicChatClient(AnthropicChatBedrockApi anthropicApi) { - return new BedrockAnthropicChatClient(anthropicApi); + public BedrockAnthropicChatConnector anthropicChatClient(AnthropicChatBedrockApi anthropicApi) { + return new BedrockAnthropicChatConnector(anthropicApi); } } diff --git a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicCreateRequestTests.java b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicCreateRequestTests.java index 928e183ad..6fa4144b3 100644 --- a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicCreateRequestTests.java +++ b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicCreateRequestTests.java @@ -38,7 +38,7 @@ public class BedrockAnthropicCreateRequestTests { @Test public void createRequestWithChatOptions() { - var client = new BedrockAnthropicChatClient(anthropicChatApi, + var client = new BedrockAnthropicChatConnector(anthropicChatApi, AnthropicChatOptions.builder() .withTemperature(66.6f) .withTopK(66) diff --git a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatClientIT.java b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatConnectorIT.java similarity index 93% rename from models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatClientIT.java rename to models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatConnectorIT.java index 9568f4f69..03badfd6e 100644 --- a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatClientIT.java +++ b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatConnectorIT.java @@ -59,12 +59,12 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY_ID", matches = ".*") @EnabledIfEnvironmentVariable(named = "AWS_SECRET_ACCESS_KEY", matches = ".*") -class BedrockAnthropic3ChatClientIT { +class BedrockAnthropic3ChatConnectorIT { - private static final Logger logger = LoggerFactory.getLogger(BedrockAnthropic3ChatClientIT.class); + private static final Logger logger = LoggerFactory.getLogger(BedrockAnthropic3ChatConnectorIT.class); @Autowired - private BedrockAnthropic3ChatClient client; + private BedrockAnthropic3ChatConnector client; @Value("classpath:/prompts/system-message.st") private Resource systemResource; @@ -105,7 +105,7 @@ class BedrockAnthropic3ChatClientIT { Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); } @@ -123,7 +123,7 @@ class BedrockAnthropic3ChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "ice cream flavors.", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.client.call(prompt).getResult(); + Generation generation = this.client.execute(prompt).getResult(); List list = outputConverter.convert(generation.getOutput().getContent()); assertThat(list).hasSize(5); @@ -142,7 +142,7 @@ class BedrockAnthropic3ChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); Map result = outputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -166,7 +166,7 @@ class BedrockAnthropic3ChatClientIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); ActorsFilmsRecord actorsFilms = outputConverter.convert(generation.getOutput().getContent()); assertThat(actorsFilms.actor()).isEqualTo("Tom Hanks"); @@ -211,7 +211,7 @@ class BedrockAnthropic3ChatClientIT { var userMessage = new UserMessage("Explain what do you see o this picture?", List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageData))); - var response = client.call(new Prompt(List.of(userMessage))); + var response = client.execute(new Prompt(List.of(userMessage))); logger.info(response.getResult().getOutput().getContent()); assertThat(response.getResult().getOutput().getContent()).contains("bananas", "apple", "basket"); @@ -228,8 +228,8 @@ class BedrockAnthropic3ChatClientIT { } @Bean - public BedrockAnthropic3ChatClient anthropicChatClient(Anthropic3ChatBedrockApi anthropicApi) { - return new BedrockAnthropic3ChatClient(anthropicApi); + public BedrockAnthropic3ChatConnector anthropicChatClient(Anthropic3ChatBedrockApi anthropicApi) { + return new BedrockAnthropic3ChatConnector(anthropicApi); } } diff --git a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3CreateRequestTests.java b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3CreateRequestTests.java index 480f914c3..8541018ad 100644 --- a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3CreateRequestTests.java +++ b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3CreateRequestTests.java @@ -37,7 +37,7 @@ public class BedrockAnthropic3CreateRequestTests { @Test public void createRequestWithChatOptions() { - var client = new BedrockAnthropic3ChatClient(anthropicChatApi, + var client = new BedrockAnthropic3ChatConnector(anthropicChatApi, Anthropic3ChatOptions.builder() .withTemperature(66.6f) .withTopK(66) diff --git a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatClientIT.java b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatConnectorIT.java similarity index 94% rename from models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatClientIT.java rename to models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatConnectorIT.java index 567926810..f4f66e951 100644 --- a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatClientIT.java +++ b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatConnectorIT.java @@ -54,10 +54,10 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY_ID", matches = ".*") @EnabledIfEnvironmentVariable(named = "AWS_SECRET_ACCESS_KEY", matches = ".*") -class BedrockCohereChatClientIT { +class BedrockCohereChatConnectorIT { @Autowired - private BedrockCohereChatClient client; + private BedrockCohereChatConnector client; @Value("classpath:/prompts/system-message.st") private Resource systemResource; @@ -98,7 +98,7 @@ class BedrockCohereChatClientIT { SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource); Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice)); Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); } @@ -115,7 +115,7 @@ class BedrockCohereChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "ice cream flavors.", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.client.call(prompt).getResult(); + Generation generation = this.client.execute(prompt).getResult(); List list = outputConverter.convert(generation.getOutput().getContent()); assertThat(list).hasSize(5); @@ -134,7 +134,7 @@ class BedrockCohereChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); Map result = outputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -157,7 +157,7 @@ class BedrockCohereChatClientIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); ActorsFilmsRecord actorsFilms = outputConverter.convert(generation.getOutput().getContent()); assertThat(actorsFilms.actor()).isEqualTo("Tom Hanks"); @@ -205,8 +205,8 @@ class BedrockCohereChatClientIT { } @Bean - public BedrockCohereChatClient cohereChatClient(CohereChatBedrockApi cohereApi) { - return new BedrockCohereChatClient(cohereApi); + public BedrockCohereChatConnector cohereChatClient(CohereChatBedrockApi cohereApi) { + return new BedrockCohereChatConnector(cohereApi); } } diff --git a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatCreateRequestTests.java b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatCreateRequestTests.java index 661c19e32..88df8bdac 100644 --- a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatCreateRequestTests.java +++ b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatCreateRequestTests.java @@ -45,7 +45,7 @@ public class BedrockCohereChatCreateRequestTests { @Test public void createRequestWithChatOptions() { - var client = new BedrockCohereChatClient(chatApi, + var client = new BedrockCohereChatConnector(chatApi, BedrockCohereChatOptions.builder() .withTemperature(66.6f) .withTopK(66) diff --git a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatClientIT.java b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatConnectorIT.java similarity index 92% rename from models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatClientIT.java rename to models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatConnectorIT.java index f6614b852..1c8700046 100644 --- a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatClientIT.java +++ b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatConnectorIT.java @@ -49,10 +49,10 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY_ID", matches = ".*") @EnabledIfEnvironmentVariable(named = "AWS_SECRET_ACCESS_KEY", matches = ".*") -class BedrockAi21Jurassic2ChatClientIT { +class BedrockAi21Jurassic2ChatConnectorIT { @Autowired - private BedrockAi21Jurassic2ChatClient client; + private BedrockAi21Jurassic2ChatConnector client; @Value("classpath:/prompts/system-message.st") private Resource systemResource; @@ -66,7 +66,7 @@ class BedrockAi21Jurassic2ChatClientIT { Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); } @@ -83,7 +83,7 @@ class BedrockAi21Jurassic2ChatClientIT { UserMessage userMessage = new UserMessage("Can you express happiness using an emoji like 😄 ?"); Prompt prompt = new Prompt(List.of(userMessage), options); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); assertThat(response.getResult().getOutput().getContent()).matches(content -> content.contains("😄")); } @@ -103,7 +103,7 @@ class BedrockAi21Jurassic2ChatClientIT { Prompt prompt = new Prompt(List.of(userMessage, systemMessage), options); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); assertThat(response.getResult().getOutput().getContent()).doesNotContain("😄"); } @@ -120,7 +120,7 @@ class BedrockAi21Jurassic2ChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); Map result = outputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -135,7 +135,7 @@ class BedrockAi21Jurassic2ChatClientIT { Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); assertThat(response.getResult().getOutput().getContent()).contains("AI"); } @@ -152,9 +152,9 @@ class BedrockAi21Jurassic2ChatClientIT { } @Bean - public BedrockAi21Jurassic2ChatClient bedrockAi21Jurassic2ChatClient( + public BedrockAi21Jurassic2ChatConnector bedrockAi21Jurassic2ChatClient( Ai21Jurassic2ChatBedrockApi jurassic2ChatBedrockApi) { - return new BedrockAi21Jurassic2ChatClient(jurassic2ChatBedrockApi, + return new BedrockAi21Jurassic2ChatConnector(jurassic2ChatBedrockApi, BedrockAi21Jurassic2ChatOptions.builder() .withTemperature(0.5f) .withMaxTokens(100) diff --git a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatClientIT.java b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatConnectorIT.java similarity index 94% rename from models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatClientIT.java rename to models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatConnectorIT.java index 3ecaf8650..0bbde7d08 100644 --- a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatClientIT.java +++ b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatConnectorIT.java @@ -54,10 +54,10 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY_ID", matches = ".*") @EnabledIfEnvironmentVariable(named = "AWS_SECRET_ACCESS_KEY", matches = ".*") -class BedrockLlamaChatClientIT { +class BedrockLlamaChatConnectorIT { @Autowired - private BedrockLlamaChatClient client; + private BedrockLlamaChatConnector client; @Value("classpath:/prompts/system-message.st") private Resource systemResource; @@ -98,7 +98,7 @@ class BedrockLlamaChatClientIT { Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); } @@ -116,7 +116,7 @@ class BedrockLlamaChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "ice cream flavors.", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.client.call(prompt).getResult(); + Generation generation = this.client.execute(prompt).getResult(); List list = outputConverter.convert(generation.getOutput().getContent()); assertThat(list).hasSize(5); @@ -134,7 +134,7 @@ class BedrockLlamaChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); Map result = outputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -158,7 +158,7 @@ class BedrockLlamaChatClientIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); ActorsFilmsRecord actorsFilms = outputConverter.convert(generation.getOutput().getContent()); assertThat(actorsFilms.actor()).isEqualTo("Tom Hanks"); @@ -206,8 +206,8 @@ class BedrockLlamaChatClientIT { } @Bean - public BedrockLlamaChatClient llamaChatClient(LlamaChatBedrockApi llamaApi) { - return new BedrockLlamaChatClient(llamaApi, + public BedrockLlamaChatConnector llamaChatClient(LlamaChatBedrockApi llamaApi) { + return new BedrockLlamaChatConnector(llamaApi, BedrockLlamaChatOptions.builder().withTemperature(0.5f).withMaxGenLen(100).withTopP(0.9f).build()); } diff --git a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/llama/BedrockLlamaCreateRequestTests.java b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/llama/BedrockLlamaCreateRequestTests.java index 77018af9e..f6aec30f7 100644 --- a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/llama/BedrockLlamaCreateRequestTests.java +++ b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/llama/BedrockLlamaCreateRequestTests.java @@ -45,7 +45,7 @@ public class BedrockLlamaCreateRequestTests { @Test public void createRequestWithChatOptions() { - var client = new BedrockLlamaChatClient(api, + var client = new BedrockLlamaChatConnector(api, BedrockLlamaChatOptions.builder().withTemperature(66.6f).withMaxGenLen(666).withTopP(0.66f).build()); var request = client.createRequest(new Prompt("Test message content")); diff --git a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/titan/BedrockTitanChatClientIT.java b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/titan/BedrockTitanChatConnectorIT.java similarity index 94% rename from models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/titan/BedrockTitanChatClientIT.java rename to models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/titan/BedrockTitanChatConnectorIT.java index 3f6b611c9..b6e3f7af2 100644 --- a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/titan/BedrockTitanChatClientIT.java +++ b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/titan/BedrockTitanChatConnectorIT.java @@ -55,10 +55,10 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY_ID", matches = ".*") @EnabledIfEnvironmentVariable(named = "AWS_SECRET_ACCESS_KEY", matches = ".*") -class BedrockTitanChatClientIT { +class BedrockTitanChatConnectorIT { @Autowired - private BedrockTitanChatClient client; + private BedrockTitanChatConnector client; @Value("classpath:/prompts/system-message.st") private Resource systemResource; @@ -99,7 +99,7 @@ class BedrockTitanChatClientIT { SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource); Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice)); Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); } @@ -117,7 +117,7 @@ class BedrockTitanChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "ice cream flavors.", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.client.call(prompt).getResult(); + Generation generation = this.client.execute(prompt).getResult(); List list = outputConverter.convert(generation.getOutput().getContent()); assertThat(list).hasSize(5); @@ -138,7 +138,7 @@ class BedrockTitanChatClientIT { Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); Map result = outputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -162,7 +162,7 @@ class BedrockTitanChatClientIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); ActorsFilmsRecord actorsFilms = outputConverter.convert(generation.getOutput().getContent()); assertThat(actorsFilms.actor()).isEqualTo("Tom Hanks"); @@ -211,8 +211,8 @@ class BedrockTitanChatClientIT { } @Bean - public BedrockTitanChatClient titanChatClient(TitanChatBedrockApi titanApi) { - return new BedrockTitanChatClient(titanApi); + public BedrockTitanChatConnector titanChatClient(TitanChatBedrockApi titanApi) { + return new BedrockTitanChatConnector(titanApi); } } diff --git a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/titan/BedrockTitanChatCreateRequestTests.java b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/titan/BedrockTitanChatCreateRequestTests.java index 5f8065bc3..48a77a087 100644 --- a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/titan/BedrockTitanChatCreateRequestTests.java +++ b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/titan/BedrockTitanChatCreateRequestTests.java @@ -41,7 +41,7 @@ public class BedrockTitanChatCreateRequestTests { @Test public void createRequestWithChatOptions() { - var client = new BedrockTitanChatClient(api, + var client = new BedrockTitanChatConnector(api, BedrockTitanChatOptions.builder() .withTemperature(66.6f) .withTopP(0.66f) diff --git a/models/spring-ai-huggingface/src/main/java/org/springframework/ai/huggingface/HuggingfaceChatClient.java b/models/spring-ai-huggingface/src/main/java/org/springframework/ai/huggingface/HuggingfaceChatConnector.java similarity index 90% rename from models/spring-ai-huggingface/src/main/java/org/springframework/ai/huggingface/HuggingfaceChatClient.java rename to models/spring-ai-huggingface/src/main/java/org/springframework/ai/huggingface/HuggingfaceChatConnector.java index 65b6ecdc9..d3ddbe9bd 100644 --- a/models/spring-ai-huggingface/src/main/java/org/springframework/ai/huggingface/HuggingfaceChatClient.java +++ b/models/spring-ai-huggingface/src/main/java/org/springframework/ai/huggingface/HuggingfaceChatConnector.java @@ -22,7 +22,7 @@ import java.util.Map; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.huggingface.api.TextGenerationInferenceApi; @@ -34,12 +34,12 @@ import org.springframework.ai.huggingface.model.GenerateResponse; import org.springframework.ai.chat.prompt.Prompt; /** - * An implementation of {@link ChatClient} that interfaces with HuggingFace Inference + * An implementation of {@link ChatConnector} that interfaces with HuggingFace Inference * Endpoints for text generation. * * @author Mark Pollack */ -public class HuggingfaceChatClient implements ChatClient { +public class HuggingfaceChatConnector implements ChatConnector { /** * Token required for authenticating with the HuggingFace Inference API. @@ -68,11 +68,12 @@ public class HuggingfaceChatClient implements ChatClient { private int maxNewTokens = 1000; /** - * Constructs a new HuggingfaceChatClient with the specified API token and base path. + * Constructs a new HuggingfaceChatConnector with the specified API token and base + * path. * @param apiToken The API token for HuggingFace. * @param basePath The base path for API requests. */ - public HuggingfaceChatClient(final String apiToken, String basePath) { + public HuggingfaceChatConnector(final String apiToken, String basePath) { this.apiToken = apiToken; this.apiClient.setBasePath(basePath); this.apiClient.addDefaultHeader("Authorization", "Bearer " + this.apiToken); @@ -85,7 +86,7 @@ public class HuggingfaceChatClient implements ChatClient { * @return ChatResponse containing the generated text and other related details. */ @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { GenerateRequest generateRequest = new GenerateRequest(); generateRequest.setInputs(prompt.getContents()); GenerateParameters generateParameters = new GenerateParameters(); diff --git a/models/spring-ai-huggingface/src/test/java/org/springframework/ai/huggingface/HuggingfaceTestConfiguration.java b/models/spring-ai-huggingface/src/test/java/org/springframework/ai/huggingface/HuggingfaceTestConfiguration.java index e4adf3bb8..9a1051b8c 100644 --- a/models/spring-ai-huggingface/src/test/java/org/springframework/ai/huggingface/HuggingfaceTestConfiguration.java +++ b/models/spring-ai-huggingface/src/test/java/org/springframework/ai/huggingface/HuggingfaceTestConfiguration.java @@ -23,7 +23,7 @@ import org.springframework.util.StringUtils; public class HuggingfaceTestConfiguration { @Bean - public HuggingfaceChatClient huggingfaceChatClient() { + public HuggingfaceChatConnector huggingfaceChatClient() { String apiKey = System.getenv("HUGGINGFACE_API_KEY"); if (!StringUtils.hasText(apiKey)) { throw new IllegalArgumentException( @@ -31,7 +31,7 @@ public class HuggingfaceTestConfiguration { } // Created aws-mistral-7b-instruct-v0-1-805 via // https://ui.endpoints.huggingface.co/ - HuggingfaceChatClient huggingfaceChatClient = new HuggingfaceChatClient(apiKey, + HuggingfaceChatConnector huggingfaceChatClient = new HuggingfaceChatConnector(apiKey, "https://f6hg7b3cvlmntp5i.us-east-1.aws.endpoints.huggingface.cloud"); return huggingfaceChatClient; } diff --git a/models/spring-ai-huggingface/src/test/java/org/springframework/ai/huggingface/client/ClientIT.java b/models/spring-ai-huggingface/src/test/java/org/springframework/ai/huggingface/client/ClientIT.java index f21c7b9ab..0d8653373 100644 --- a/models/spring-ai-huggingface/src/test/java/org/springframework/ai/huggingface/client/ClientIT.java +++ b/models/spring-ai-huggingface/src/test/java/org/springframework/ai/huggingface/client/ClientIT.java @@ -20,7 +20,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.springframework.ai.chat.ChatResponse; -import org.springframework.ai.huggingface.HuggingfaceChatClient; +import org.springframework.ai.huggingface.HuggingfaceChatConnector; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -33,7 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class ClientIT { @Autowired - protected HuggingfaceChatClient huggingfaceChatClient; + protected HuggingfaceChatConnector huggingfaceChatClient; @Test void helloWorldCompletion() { @@ -46,7 +46,7 @@ public class ClientIT { [/INST] """; Prompt prompt = new Prompt(mistral7bInstruct); - ChatResponse chatResponse = huggingfaceChatClient.call(prompt); + ChatResponse chatResponse = huggingfaceChatClient.execute(prompt); assertThat(chatResponse.getResult().getOutput().getContent()).isNotEmpty(); String expectedResponse = """ ```json diff --git a/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatClient.java b/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatConnector.java similarity index 96% rename from models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatClient.java rename to models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatConnector.java index 98a25025d..9475414cb 100644 --- a/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatClient.java +++ b/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatConnector.java @@ -17,7 +17,7 @@ package org.springframework.ai.mistralai; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.StreamingChatClient; @@ -50,9 +50,9 @@ import java.util.concurrent.ConcurrentHashMap; * @author Grogdunn * @since 0.8.1 */ -public class MistralAiChatClient extends +public class MistralAiChatConnector extends AbstractFunctionCallSupport> - implements ChatClient, StreamingChatClient { + implements ChatConnector, StreamingChatClient { private final Logger log = LoggerFactory.getLogger(getClass()); @@ -68,7 +68,7 @@ public class MistralAiChatClient extends private final RetryTemplate retryTemplate; - public MistralAiChatClient(MistralAiApi mistralAiApi) { + public MistralAiChatConnector(MistralAiApi mistralAiApi) { this(mistralAiApi, MistralAiChatOptions.builder() .withTemperature(0.7f) @@ -78,11 +78,11 @@ public class MistralAiChatClient extends .build()); } - public MistralAiChatClient(MistralAiApi mistralAiApi, MistralAiChatOptions options) { + public MistralAiChatConnector(MistralAiApi mistralAiApi, MistralAiChatOptions options) { this(mistralAiApi, options, null, RetryUtils.DEFAULT_RETRY_TEMPLATE); } - public MistralAiChatClient(MistralAiApi mistralAiApi, MistralAiChatOptions options, + public MistralAiChatConnector(MistralAiApi mistralAiApi, MistralAiChatOptions options, FunctionCallbackContext functionCallbackContext, RetryTemplate retryTemplate) { super(functionCallbackContext); Assert.notNull(mistralAiApi, "MistralAiApi must not be null"); @@ -94,7 +94,7 @@ public class MistralAiChatClient extends } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { var request = createRequest(prompt, false); return retryTemplate.execute(ctx -> { diff --git a/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatOptions.java b/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatOptions.java index 86c0bda36..179176906 100644 --- a/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatOptions.java +++ b/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatOptions.java @@ -101,11 +101,11 @@ public class MistralAiChatOptions implements FunctionCallingOptions, ChatOptions private @JsonProperty("tool_choice") ToolChoice toolChoice; /** - * MistralAI Tool Function Callbacks to register with the ChatClient. For Prompt + * MistralAI Tool Function Callbacks to register with the ChatConnector. For Prompt * Options the functionCallbacks are automatically enabled for the duration of the * prompt execution. For Default Options the functionCallbacks are registered but * disabled by default. Use the enableFunctions to set the functions from the registry - * to be used by the ChatClient chat completion requests. + * to be used by the ChatConnector chat completion requests. */ @NestedConfigurationProperty @JsonIgnore diff --git a/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatCompletionRequestTest.java b/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatCompletionRequestTest.java index 57135164b..a43522dce 100644 --- a/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatCompletionRequestTest.java +++ b/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatCompletionRequestTest.java @@ -32,7 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; @EnabledIfEnvironmentVariable(named = "MISTRAL_AI_API_KEY", matches = ".+") public class MistralAiChatCompletionRequestTest { - MistralAiChatClient chatClient = new MistralAiChatClient(new MistralAiApi("test")); + MistralAiChatConnector chatClient = new MistralAiChatConnector(new MistralAiApi("test")); @Test void chatCompletionDefaultRequestTest() { diff --git a/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatClientIT.java b/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatConnectorIT.java similarity index 93% rename from models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatClientIT.java rename to models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatConnectorIT.java index 87e6acbdb..c2e075833 100644 --- a/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatClientIT.java +++ b/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatConnectorIT.java @@ -27,7 +27,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import reactor.core.publisher.Flux; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.StreamingChatClient; @@ -56,12 +56,12 @@ import static org.assertj.core.api.Assertions.assertThat; */ @SpringBootTest(classes = MistralAiTestConfiguration.class) @EnabledIfEnvironmentVariable(named = "MISTRAL_AI_API_KEY", matches = ".+") -class MistralAiChatClientIT { +class MistralAiChatConnectorIT { - private static final Logger logger = LoggerFactory.getLogger(MistralAiChatClientIT.class); + private static final Logger logger = LoggerFactory.getLogger(MistralAiChatConnectorIT.class); @Autowired - protected ChatClient chatClient; + protected ChatConnector chatConnector; @Autowired protected StreamingChatClient streamingChatClient; @@ -90,7 +90,7 @@ class MistralAiChatClientIT { // NOTE: Mistral expects the system message to be before the user message or will // fail with 400 error. Prompt prompt = new Prompt(List.of(systemMessage, userMessage)); - ChatResponse response = chatClient.call(prompt); + ChatResponse response = chatConnector.execute(prompt); assertThat(response.getResults()).hasSize(1); assertThat(response.getResults().get(0).getOutput().getContent()).contains("Blackbeard"); } @@ -108,7 +108,7 @@ class MistralAiChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "ice cream flavors", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.chatClient.call(prompt).getResult(); + Generation generation = this.chatConnector.execute(prompt).getResult(); List list = outputConverter.convert(generation.getOutput().getContent()); assertThat(list).hasSize(5); @@ -126,7 +126,7 @@ class MistralAiChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = chatClient.call(prompt).getResult(); + Generation generation = chatConnector.execute(prompt).getResult(); Map result = outputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -148,7 +148,7 @@ class MistralAiChatClientIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = chatClient.call(prompt).getResult(); + Generation generation = chatConnector.execute(prompt).getResult(); ActorsFilmsRecord actorsFilms = outputConverter.convert(generation.getOutput().getContent()); logger.info("" + actorsFilms); @@ -186,7 +186,7 @@ class MistralAiChatClientIT { } @Test - void functionCallTest() { + void functionExecuteTest() { UserMessage userMessage = new UserMessage("What's the weather like in San Francisco?"); @@ -201,7 +201,7 @@ class MistralAiChatClientIT { .build())) .build(); - ChatResponse response = chatClient.call(new Prompt(messages, promptOptions)); + ChatResponse response = chatConnector.execute(new Prompt(messages, promptOptions)); logger.info("Response: {}", response); @@ -209,7 +209,7 @@ class MistralAiChatClientIT { } @Test - void streamFunctionCallTest() { + void streamFunctionExecuteTest() { UserMessage userMessage = new UserMessage("What's the weather like in Tokyo, Japan?"); diff --git a/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiRetryTests.java b/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiRetryTests.java index 1ca349d21..e163610c9 100644 --- a/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiRetryTests.java +++ b/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiRetryTests.java @@ -82,7 +82,7 @@ public class MistralAiRetryTests { private @Mock MistralAiApi mistralAiApi; - private MistralAiChatClient chatClient; + private MistralAiChatConnector chatClient; private MistralAiEmbeddingClient embeddingClient; @@ -92,7 +92,7 @@ public class MistralAiRetryTests { retryListener = new TestRetryListener(); retryTemplate.registerListener(retryListener); - chatClient = new MistralAiChatClient(mistralAiApi, + chatClient = new MistralAiChatConnector(mistralAiApi, MistralAiChatOptions.builder() .withTemperature(0.7f) .withTopP(1f) @@ -118,7 +118,7 @@ public class MistralAiRetryTests { .thenThrow(new TransientAiException("Transient Error 2")) .thenReturn(ResponseEntity.of(Optional.of(expectedChatCompletion))); - var result = chatClient.call(new Prompt("text")); + var result = chatClient.execute(new Prompt("text")); assertThat(result).isNotNull(); assertThat(result.getResult().getOutput().getContent()).isSameAs("Response"); @@ -130,7 +130,7 @@ public class MistralAiRetryTests { public void mistralAiChatNonTransientError() { when(mistralAiApi.chatCompletionEntity(isA(ChatCompletionRequest.class))) .thenThrow(new RuntimeException("Non Transient Error")); - assertThrows(RuntimeException.class, () -> chatClient.call(new Prompt("text"))); + assertThrows(RuntimeException.class, () -> chatClient.execute(new Prompt("text"))); } @Test diff --git a/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiTestConfiguration.java b/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiTestConfiguration.java index 7952571d6..45b04aa4c 100644 --- a/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiTestConfiguration.java +++ b/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiTestConfiguration.java @@ -41,8 +41,8 @@ public class MistralAiTestConfiguration { } @Bean - public MistralAiChatClient mistralAiChatClient(MistralAiApi mistralAiApi) { - return new MistralAiChatClient(mistralAiApi, + public MistralAiChatConnector mistralAiChatClient(MistralAiApi mistralAiApi) { + return new MistralAiChatConnector(mistralAiApi, MistralAiChatOptions.builder().withModel(MistralAiApi.ChatModel.MIXTRAL.getValue()).build()); } diff --git a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatClient.java b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatConnector.java similarity index 92% rename from models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatClient.java rename to models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatConnector.java index 273d98866..81bf2e40e 100644 --- a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatClient.java +++ b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatConnector.java @@ -21,7 +21,7 @@ import java.util.List; import org.springframework.ai.ollama.metadata.OllamaChatResponseMetadata; import reactor.core.publisher.Flux; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.StreamingChatClient; @@ -39,7 +39,7 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; /** - * {@link ChatClient} implementation for {@literal Ollama}. + * {@link ChatConnector} implementation for {@literal Ollama}. * * Ollama allows developers to run large language models and generate embeddings locally. * It supports open-source models available on [Ollama AI @@ -52,7 +52,7 @@ import org.springframework.util.StringUtils; * @author Christian Tzolov * @since 0.8.0 */ -public class OllamaChatClient implements ChatClient, StreamingChatClient { +public class OllamaChatConnector implements ChatConnector, StreamingChatClient { /** * Low-level Ollama API library. @@ -64,11 +64,11 @@ public class OllamaChatClient implements ChatClient, StreamingChatClient { */ private OllamaOptions defaultOptions; - public OllamaChatClient(OllamaApi chatApi) { + public OllamaChatConnector(OllamaApi chatApi) { this(chatApi, OllamaOptions.create().withModel(OllamaOptions.DEFAULT_MODEL)); } - public OllamaChatClient(OllamaApi chatApi, OllamaOptions defaultOptions) { + public OllamaChatConnector(OllamaApi chatApi, OllamaOptions defaultOptions) { Assert.notNull(chatApi, "OllamaApi must not be null"); Assert.notNull(defaultOptions, "DefaultOptions must not be null"); this.chatApi = chatApi; @@ -79,7 +79,7 @@ public class OllamaChatClient implements ChatClient, StreamingChatClient { * @deprecated Use {@link OllamaOptions#setModel} instead. */ @Deprecated - public OllamaChatClient withModel(String model) { + public OllamaChatConnector withModel(String model) { this.defaultOptions.setModel(model); return this; } @@ -88,13 +88,13 @@ public class OllamaChatClient implements ChatClient, StreamingChatClient { * @deprecated Use {@link OllamaOptions} constructor instead. */ @Deprecated - public OllamaChatClient withDefaultOptions(OllamaOptions options) { + public OllamaChatConnector withDefaultOptions(OllamaOptions options) { this.defaultOptions = options; return this; } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { OllamaApi.ChatResponse response = this.chatApi.chat(ollamaChatRequest(prompt, false)); diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatClientIT.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatConnectorIT.java similarity index 92% rename from models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatClientIT.java rename to models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatConnectorIT.java index 6f4254fa4..676da0f7e 100644 --- a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatClientIT.java +++ b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatConnectorIT.java @@ -56,11 +56,11 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @Testcontainers @Disabled("For manual smoke testing only.") -class OllamaChatClientIT { +class OllamaChatConnectorIT { private static String MODEL = "mistral"; - private static final Log logger = LogFactory.getLog(OllamaChatClientIT.class); + private static final Log logger = LogFactory.getLog(OllamaChatConnectorIT.class); @Container static OllamaContainer ollamaContainer = new OllamaContainer("ollama/ollama:0.1.32"); @@ -77,7 +77,7 @@ class OllamaChatClientIT { } @Autowired - private OllamaChatClient client; + private OllamaChatConnector client; @Test void roleTest() { @@ -95,13 +95,13 @@ class OllamaChatClientIT { Prompt prompt = new Prompt(List.of(userMessage, systemMessage), portableOptions); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); // ollama specific options var ollamaOptions = new OllamaOptions().withLowVRAM(true); - response = client.call(new Prompt(List.of(userMessage, systemMessage), ollamaOptions)); + response = client.execute(new Prompt(List.of(userMessage, systemMessage), ollamaOptions)); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); } @@ -109,7 +109,7 @@ class OllamaChatClientIT { @Test void usageTest() { Prompt prompt = new Prompt("Tell me a joke"); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); Usage usage = response.getMetadata().getUsage(); assertThat(usage).isNotNull(); @@ -131,7 +131,7 @@ class OllamaChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "ice cream flavors.", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.client.call(prompt).getResult(); + Generation generation = this.client.execute(prompt).getResult(); List list = outputConverter.convert(generation.getOutput().getContent()); assertThat(list).hasSize(5); @@ -151,7 +151,7 @@ class OllamaChatClientIT { Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); Map result = outputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -173,7 +173,7 @@ class OllamaChatClientIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); ActorsFilmsRecord actorsFilms = outputConverter.convert(generation.getOutput().getContent()); assertThat(actorsFilms.actor()).isEqualTo("Tom Hanks"); @@ -219,8 +219,8 @@ class OllamaChatClientIT { } @Bean - public OllamaChatClient ollamaChat(OllamaApi ollamaApi) { - return new OllamaChatClient(ollamaApi, OllamaOptions.create().withModel(MODEL).withTemperature(0.9f)); + public OllamaChatConnector ollamaChat(OllamaApi ollamaApi) { + return new OllamaChatConnector(ollamaApi, OllamaOptions.create().withModel(MODEL).withTemperature(0.9f)); } } diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatClientMultimodalIT.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatConnectorMultimodalIT.java similarity index 90% rename from models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatClientMultimodalIT.java rename to models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatConnectorMultimodalIT.java index 8599cfe9e..d8c354b22 100644 --- a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatClientMultimodalIT.java +++ b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatConnectorMultimodalIT.java @@ -44,11 +44,11 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @Testcontainers @Disabled("For manual smoke testing only.") -class OllamaChatClientMultimodalIT { +class OllamaChatConnectorMultimodalIT { private static String MODEL = "llava"; - private static final Log logger = LogFactory.getLog(OllamaChatClientIT.class); + private static final Log logger = LogFactory.getLog(OllamaChatConnectorIT.class); @Container static OllamaContainer ollamaContainer = new OllamaContainer("ollama/ollama:0.1.32"); @@ -65,7 +65,7 @@ class OllamaChatClientMultimodalIT { } @Autowired - private OllamaChatClient client; + private OllamaChatConnector client; @Test void multiModalityTest() throws IOException { @@ -75,7 +75,7 @@ class OllamaChatClientMultimodalIT { var userMessage = new UserMessage("Explain what do you see on this picture?", List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageData))); - var response = client.call(new Prompt(List.of(userMessage))); + var response = client.execute(new Prompt(List.of(userMessage))); logger.info(response.getResult().getOutput().getContent()); assertThat(response.getResult().getOutput().getContent()).contains("bananas", "apple", "basket"); @@ -90,8 +90,8 @@ class OllamaChatClientMultimodalIT { } @Bean - public OllamaChatClient ollamaChat(OllamaApi ollamaApi) { - return new OllamaChatClient(ollamaApi, OllamaOptions.create().withModel(MODEL).withTemperature(0.9f)); + public OllamaChatConnector ollamaChat(OllamaApi ollamaApi) { + return new OllamaChatConnector(ollamaApi, OllamaOptions.create().withModel(MODEL).withTemperature(0.9f)); } } diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatRequestTests.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatRequestTests.java index f78b8f2fc..1fdefb245 100644 --- a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatRequestTests.java +++ b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatRequestTests.java @@ -30,7 +30,7 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class OllamaChatRequestTests { - OllamaChatClient client = new OllamaChatClient(new OllamaApi(), + OllamaChatConnector client = new OllamaChatConnector(new OllamaApi(), new OllamaOptions().withModel("MODEL_NAME").withTopK(99).withTemperature(66.6f).withNumGPU(1)); @Test @@ -105,7 +105,7 @@ public class OllamaChatRequestTests { @Test public void createRequestWithDefaultOptionsModelOverride() { - OllamaChatClient client2 = new OllamaChatClient(new OllamaApi(), + OllamaChatConnector client2 = new OllamaChatConnector(new OllamaApi(), new OllamaOptions().withModel("DEFAULT_OPTIONS_MODEL")); var request = client2.ollamaChatRequest(new Prompt("Test message content"), true); diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatClient.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatConnector.java similarity index 95% rename from models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatClient.java rename to models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatConnector.java index 6ec6904db..f3bc4cdec 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatClient.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatConnector.java @@ -17,7 +17,7 @@ package org.springframework.ai.openai; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.StreamingChatClient; @@ -58,8 +58,8 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** - * {@link ChatClient} and {@link StreamingChatClient} implementation for {@literal OpenAI} - * backed by {@link OpenAiApi}. + * {@link ChatConnector} and {@link StreamingChatClient} implementation for + * {@literal OpenAI} backed by {@link OpenAiApi}. * * @author Mark Pollack * @author Christian Tzolov @@ -68,15 +68,15 @@ import java.util.concurrent.ConcurrentHashMap; * @author Josh Long * @author Jemin Huh * @author Grogdunn - * @see ChatClient + * @see ChatConnector * @see StreamingChatClient * @see OpenAiApi */ -public class OpenAiChatClient extends +public class OpenAiChatConnector extends AbstractFunctionCallSupport> - implements ChatClient, StreamingChatClient { + implements ChatConnector, StreamingChatClient { - private static final Logger logger = LoggerFactory.getLogger(OpenAiChatClient.class); + private static final Logger logger = LoggerFactory.getLogger(OpenAiChatConnector.class); /** * The default options used for the chat completion requests. @@ -94,35 +94,35 @@ public class OpenAiChatClient extends private final OpenAiApi openAiApi; /** - * Creates an instance of the OpenAiChatClient. + * Creates an instance of the OpenAiChatConnector. * @param openAiApi The OpenAiApi instance to be used for interacting with the OpenAI * Chat API. * @throws IllegalArgumentException if openAiApi is null */ - public OpenAiChatClient(OpenAiApi openAiApi) { + public OpenAiChatConnector(OpenAiApi openAiApi) { this(openAiApi, OpenAiChatOptions.builder().withModel(OpenAiApi.DEFAULT_CHAT_MODEL).withTemperature(0.7f).build()); } /** - * Initializes an instance of the OpenAiChatClient. + * Initializes an instance of the OpenAiChatConnector. * @param openAiApi The OpenAiApi instance to be used for interacting with the OpenAI * Chat API. * @param options The OpenAiChatOptions to configure the chat client. */ - public OpenAiChatClient(OpenAiApi openAiApi, OpenAiChatOptions options) { + public OpenAiChatConnector(OpenAiApi openAiApi, OpenAiChatOptions options) { this(openAiApi, options, null, RetryUtils.DEFAULT_RETRY_TEMPLATE); } /** - * Initializes a new instance of the OpenAiChatClient. + * Initializes a new instance of the OpenAiChatConnector. * @param openAiApi The OpenAiApi instance to be used for interacting with the OpenAI * Chat API. * @param options The OpenAiChatOptions to configure the chat client. * @param functionCallbackContext The function callback context. * @param retryTemplate The retry template. */ - public OpenAiChatClient(OpenAiApi openAiApi, OpenAiChatOptions options, + public OpenAiChatConnector(OpenAiApi openAiApi, OpenAiChatOptions options, FunctionCallbackContext functionCallbackContext, RetryTemplate retryTemplate) { super(functionCallbackContext); Assert.notNull(openAiApi, "OpenAiApi must not be null"); @@ -134,7 +134,7 @@ public class OpenAiChatClient extends } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { ChatCompletionRequest request = createRequest(prompt, false); diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatOptions.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatOptions.java index d45d4db18..36417688e 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatOptions.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatOptions.java @@ -134,10 +134,10 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions { private @JsonProperty("user") String user; /** - * OpenAI Tool Function Callbacks to register with the ChatClient. + * OpenAI Tool Function Callbacks to register with the ChatConnector. * For Prompt Options the functionCallbacks are automatically enabled for the duration of the prompt execution. * For Default Options the functionCallbacks are registered but disabled by default. Use the enableFunctions to set the functions - * from the registry to be used by the ChatClient chat completion requests. + * from the registry to be used by the ChatConnector chat completion requests. */ @NestedConfigurationProperty @JsonIgnore diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatClientTest.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatClientTest.java new file mode 100644 index 000000000..c4214ed01 --- /dev/null +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatClientTest.java @@ -0,0 +1,56 @@ +package org.springframework.ai.openai; + +import org.junit.jupiter.api.Test; +import org.springframework.ai.chat.ChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Map; + +class ChatClientTest { + + @Configuration + static class ChatClientTestConfiguration { + + @Bean + ChatClient client(OpenAiChatConnector openAiChatConnector) { + return ChatClient.builder(openAiChatConnector).defaultSystemPrompt(""" + you are customer service agent designed to answer questions + about a the user, {userName}'s, orders. Here are their outstanding orders. + + {orders} + + """).defaultFunctions("cancelOrder", "refundOrder").build(); + } + + } + + private final ChatClient singularity; + + ChatClientTest(@Autowired ChatClient singularity) { + this.singularity = singularity; + } + + @Test + void products() throws Exception { + var product0 = this.client.userPrompt("tell me about this product from the merchant {merchant}") + .userPromptParams(Map.of("merchant", "24u92")) + .execute(Product.class); + + /* + * var product1 = this.client .build() .userPromptParam("a", "b") + * .functions("cancelOrder", "refundOrder") .execute(new + * ParameterizedTypeReference() { }); + * + * var product2 = this.client + * .userPrompt("tell me about this product from the merchant {merchant}", + * Map.of("merchant", "232")) .execute(Product.class); + */ + + } + + record Product(String sku) { + } + +} diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatCompletionRequestTests.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatCompletionRequestTests.java index 300cdfafb..68998e133 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatCompletionRequestTests.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatCompletionRequestTests.java @@ -34,7 +34,7 @@ public class ChatCompletionRequestTests { @Test public void createRequestWithChatOptions() { - var client = new OpenAiChatClient(new OpenAiApi("TEST"), + var client = new OpenAiChatConnector(new OpenAiApi("TEST"), OpenAiChatOptions.builder().withModel("DEFAULT_MODEL").withTemperature(66.6f).build()); var request = client.createRequest(new Prompt("Test message content"), false); @@ -60,7 +60,7 @@ public class ChatCompletionRequestTests { final String TOOL_FUNCTION_NAME = "CurrentWeather"; - var client = new OpenAiChatClient(new OpenAiApi("TEST"), + var client = new OpenAiChatConnector(new OpenAiApi("TEST"), OpenAiChatOptions.builder().withModel("DEFAULT_MODEL").build()); var request = client.createRequest(new Prompt("Test message content", @@ -90,7 +90,7 @@ public class ChatCompletionRequestTests { final String TOOL_FUNCTION_NAME = "CurrentWeather"; - var client = new OpenAiChatClient(new OpenAiApi("TEST"), + var client = new OpenAiChatConnector(new OpenAiApi("TEST"), OpenAiChatOptions.builder() .withModel("DEFAULT_MODEL") .withFunctionCallbacks(List.of(FunctionCallbackWrapper.builder(new MockWeatherService()) diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/OpenAiTestConfiguration.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/OpenAiTestConfiguration.java index 3a235cf7a..8fd9d0386 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/OpenAiTestConfiguration.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/OpenAiTestConfiguration.java @@ -51,8 +51,8 @@ public class OpenAiTestConfiguration { } @Bean - public OpenAiChatClient openAiChatClient(OpenAiApi api) { - OpenAiChatClient openAiChatClient = new OpenAiChatClient(api); + public OpenAiChatConnector openAiChatClient(OpenAiApi api) { + OpenAiChatConnector openAiChatClient = new OpenAiChatConnector(api); return openAiChatClient; } diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/acme/AcmeIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/acme/AcmeIT.java index e38595b90..f79c478e8 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/acme/AcmeIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/acme/AcmeIT.java @@ -26,8 +26,8 @@ import org.slf4j.LoggerFactory; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.document.Document; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.ai.openai.OpenAiTestConfiguration; -import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiEmbeddingClient; import org.springframework.ai.openai.testutils.AbstractIT; import org.springframework.ai.chat.prompt.Prompt; @@ -61,7 +61,7 @@ public class AcmeIT extends AbstractIT { private OpenAiEmbeddingClient embeddingClient; @Autowired - private OpenAiChatClient chatClient; + private OpenAiChatConnector chatClient; @Test void beanTest() { @@ -108,7 +108,7 @@ public class AcmeIT extends AbstractIT { logger.info("Asking AI generative to reply to question."); Prompt prompt = new Prompt(List.of(systemMessage, userMessage)); logger.info("AI responded."); - ChatResponse response = chatClient.call(prompt); + ChatResponse response = chatClient.execute(prompt); evaluateQuestionAndAnswer(userQuery, response, true); } diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatClientWithChatResponseMetadataTests.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatClientWithChatResponseMetadataTests.java index b1ef5e43b..198cfdde8 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatClientWithChatResponseMetadataTests.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatClientWithChatResponseMetadataTests.java @@ -26,8 +26,8 @@ import org.springframework.ai.chat.metadata.ChatResponseMetadata; import org.springframework.ai.chat.metadata.PromptMetadata; import org.springframework.ai.chat.metadata.RateLimit; import org.springframework.ai.chat.metadata.Usage; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.metadata.support.OpenAiApiResponseHeaders; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.beans.factory.annotation.Autowired; @@ -57,7 +57,7 @@ public class OpenAiChatClientWithChatResponseMetadataTests { private static String TEST_API_KEY = "sk-1234567890"; @Autowired - private OpenAiChatClient openAiChatClient; + private OpenAiChatConnector openAiChatClient; @Autowired private MockRestServiceServer server; @@ -74,7 +74,7 @@ public class OpenAiChatClientWithChatResponseMetadataTests { Prompt prompt = new Prompt("Reach for the sky."); - ChatResponse response = this.openAiChatClient.call(prompt); + ChatResponse response = this.openAiChatClient.execute(prompt); assertThat(response).isNotNull(); @@ -171,8 +171,8 @@ public class OpenAiChatClientWithChatResponseMetadataTests { } @Bean - public OpenAiChatClient openAiClient(OpenAiApi openAiApi) { - return new OpenAiChatClient(openAiApi); + public OpenAiChatConnector openAiClient(OpenAiApi openAiApi) { + return new OpenAiChatConnector(openAiApi); } } diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatClient2IT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatConnector2IT.java similarity index 89% rename from models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatClient2IT.java rename to models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatConnector2IT.java index fc5904be1..9a256d820 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatClient2IT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatConnector2IT.java @@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.openai.OpenAiChatClient; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest; @@ -41,14 +41,14 @@ import static org.assertj.core.api.Assertions.assertThat; /** * @author Christian Tzolov */ -@SpringBootTest(classes = OpenAiChatClient2IT.Config.class) +@SpringBootTest(classes = OpenAiChatConnector2IT.Config.class) @EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".+") -public class OpenAiChatClient2IT { +public class OpenAiChatConnector2IT { private final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired - private OpenAiChatClient openAiChatClient; + private OpenAiChatConnector openAiChatClient; @Test void responseFormatTest() throws JsonMappingException, JsonProcessingException { @@ -67,7 +67,7 @@ public class OpenAiChatClient2IT { .withResponseFormat(new ChatCompletionRequest.ResponseFormat("json_object")) .build()); - ChatResponse response = this.openAiChatClient.call(prompt); + ChatResponse response = this.openAiChatClient.execute(prompt); assertThat(response).isNotNull(); @@ -99,8 +99,8 @@ public class OpenAiChatClient2IT { } @Bean - public OpenAiChatClient openAiClient(OpenAiApi openAiApi) { - return new OpenAiChatClient(openAiApi); + public OpenAiChatConnector openAiClient(OpenAiApi openAiApi) { + return new OpenAiChatConnector(openAiApi); } } diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatClientIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatConnectorIT.java similarity index 92% rename from models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatClientIT.java rename to models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatConnectorIT.java index 0366aa626..f2c5bfd34 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatClientIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatConnectorIT.java @@ -60,9 +60,9 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(classes = OpenAiTestConfiguration.class) @EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".+") -class OpenAiChatClientIT extends AbstractIT { +class OpenAiChatConnectorIT extends AbstractIT { - private static final Logger logger = LoggerFactory.getLogger(OpenAiChatClientIT.class); + private static final Logger logger = LoggerFactory.getLogger(OpenAiChatConnectorIT.class); @Value("classpath:/prompts/system-message.st") private Resource systemResource; @@ -74,7 +74,7 @@ class OpenAiChatClientIT extends AbstractIT { SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource); Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", "Bob", "voice", "pirate")); Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = chatClient.call(prompt); + ChatResponse response = chatConnector.execute(prompt); assertThat(response.getResults()).hasSize(1); assertThat(response.getResults().get(0).getOutput().getContent()).contains("Blackbeard"); // needs fine tuning... evaluateQuestionAndAnswer(request, response, false); @@ -93,7 +93,7 @@ class OpenAiChatClientIT extends AbstractIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "ice cream flavors", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.chatClient.call(prompt).getResult(); + Generation generation = this.chatConnector.execute(prompt).getResult(); List list = outputConverter.convert(generation.getOutput().getContent()); assertThat(list).hasSize(5); @@ -112,7 +112,7 @@ class OpenAiChatClientIT extends AbstractIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = chatClient.call(prompt).getResult(); + Generation generation = chatConnector.execute(prompt).getResult(); Map result = outputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -131,7 +131,7 @@ class OpenAiChatClientIT extends AbstractIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = chatClient.call(prompt).getResult(); + Generation generation = chatConnector.execute(prompt).getResult(); ActorsFilms actorsFilms = outputConverter.convert(generation.getOutput().getContent()); } @@ -151,7 +151,7 @@ class OpenAiChatClientIT extends AbstractIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = chatClient.call(prompt).getResult(); + Generation generation = chatConnector.execute(prompt).getResult(); ActorsFilmsRecord actorsFilms = outputConverter.convert(generation.getOutput().getContent()); logger.info("" + actorsFilms); @@ -189,7 +189,7 @@ class OpenAiChatClientIT extends AbstractIT { } @Test - void functionCallTest() { + void functionExecuteTest() { UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?"); @@ -204,7 +204,7 @@ class OpenAiChatClientIT extends AbstractIT { .build())) .build(); - ChatResponse response = chatClient.call(new Prompt(messages, promptOptions)); + ChatResponse response = chatConnector.execute(new Prompt(messages, promptOptions)); logger.info("Response: {}", response); @@ -214,7 +214,7 @@ class OpenAiChatClientIT extends AbstractIT { } @Test - void streamFunctionCallTest() { + void streamFunctionExecuteTest() { UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?"); @@ -255,8 +255,8 @@ class OpenAiChatClientIT extends AbstractIT { var userMessage = new UserMessage("Explain what do you see on this picture?", List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageData))); - var response = chatClient - .call(new Prompt(List.of(userMessage), OpenAiChatOptions.builder().withModel(modelName).build())); + var response = chatConnector + .execute(new Prompt(List.of(userMessage), OpenAiChatOptions.builder().withModel(modelName).build())); logger.info(response.getResult().getOutput().getContent()); assertThat(response.getResult().getOutput().getContent()).contains("bananas", "apple"); @@ -271,8 +271,8 @@ class OpenAiChatClientIT extends AbstractIT { .of(new Media(MimeTypeUtils.IMAGE_PNG, new URL("https://docs.spring.io/spring-ai/reference/1.0-SNAPSHOT/_images/multimodal.test.png")))); - ChatResponse response = chatClient - .call(new Prompt(List.of(userMessage), OpenAiChatOptions.builder().withModel(modelName).build())); + ChatResponse response = chatConnector + .execute(new Prompt(List.of(userMessage), OpenAiChatOptions.builder().withModel(modelName).build())); logger.info(response.getResult().getOutput().getContent()); assertThat(response.getResult().getOutput().getContent()).contains("bananas", "apple"); diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiRetryTests.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiRetryTests.java index dcf0f303f..a3ee313b1 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiRetryTests.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiRetryTests.java @@ -31,7 +31,7 @@ import org.springframework.ai.image.ImageMessage; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.openai.OpenAiAudioTranscriptionClient; import org.springframework.ai.openai.OpenAiAudioTranscriptionOptions; -import org.springframework.ai.openai.OpenAiChatClient; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.OpenAiEmbeddingClient; import org.springframework.ai.openai.OpenAiEmbeddingOptions; @@ -107,7 +107,7 @@ public class OpenAiRetryTests { private @Mock OpenAiImageApi openAiImageApi; - private OpenAiChatClient chatClient; + private OpenAiChatConnector chatClient; private OpenAiEmbeddingClient embeddingClient; @@ -121,7 +121,7 @@ public class OpenAiRetryTests { retryListener = new TestRetryListener(); retryTemplate.registerListener(retryListener); - chatClient = new OpenAiChatClient(openAiApi, OpenAiChatOptions.builder().build(), null, retryTemplate); + chatClient = new OpenAiChatConnector(openAiApi, OpenAiChatOptions.builder().build(), null, retryTemplate); embeddingClient = new OpenAiEmbeddingClient(openAiApi, MetadataMode.EMBED, OpenAiEmbeddingOptions.builder().build(), retryTemplate); audioTranscriptionClient = new OpenAiAudioTranscriptionClient(openAiAudioApi, @@ -146,7 +146,7 @@ public class OpenAiRetryTests { .thenThrow(new TransientAiException("Transient Error 2")) .thenReturn(ResponseEntity.of(Optional.of(expectedChatCompletion))); - var result = chatClient.call(new Prompt("text")); + var result = chatClient.execute(new Prompt("text")); assertThat(result).isNotNull(); assertThat(result.getResult().getOutput().getContent()).isSameAs("Response"); @@ -158,7 +158,7 @@ public class OpenAiRetryTests { public void openAiChatNonTransientError() { when(openAiApi.chatCompletionEntity(isA(ChatCompletionRequest.class))) .thenThrow(new RuntimeException("Non Transient Error")); - assertThrows(RuntimeException.class, () -> chatClient.call(new Prompt("text"))); + assertThrows(RuntimeException.class, () -> chatClient.execute(new Prompt("text"))); } @Test diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryLongTermSystemPromptIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryLongTermSystemPromptIT.java index 4516e08ae..cdac0c599 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryLongTermSystemPromptIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryLongTermSystemPromptIT.java @@ -23,6 +23,7 @@ import io.qdrant.client.QdrantGrpcClient; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.springframework.ai.chat.service.ChatService; import org.springframework.ai.chat.service.StreamingChatService; +import org.springframework.ai.openai.OpenAiChatConnector; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.qdrant.QdrantContainer; @@ -36,7 +37,6 @@ import org.springframework.ai.chat.memory.SystemPromptChatMemoryAugmentor; import org.springframework.ai.embedding.EmbeddingClient; import org.springframework.ai.evaluation.BaseMemoryTest; import org.springframework.ai.evaluation.RelevancyEvaluator; -import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiEmbeddingClient; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator; @@ -75,8 +75,8 @@ public class ChatMemoryLongTermSystemPromptIT extends BaseMemoryTest { } @Bean - public OpenAiChatClient openAiClient(OpenAiApi openAiApi) { - return new OpenAiChatClient(openAiApi); + public OpenAiChatConnector openAiClient(OpenAiApi openAiApi) { + return new OpenAiChatConnector(openAiApi); } @Bean @@ -98,7 +98,7 @@ public class ChatMemoryLongTermSystemPromptIT extends BaseMemoryTest { } @Bean - public ChatService memoryChatService(OpenAiChatClient chatClient, VectorStore vectorStore, + public ChatService memoryChatService(OpenAiChatConnector chatClient, VectorStore vectorStore, TokenCountEstimator tokenCountEstimator) { return PromptTransformingChatService.builder(chatClient) @@ -110,7 +110,7 @@ public class ChatMemoryLongTermSystemPromptIT extends BaseMemoryTest { } @Bean - public StreamingChatService memoryStreamingChatService(OpenAiChatClient streamingChatClient, + public StreamingChatService memoryStreamingChatService(OpenAiChatConnector streamingChatClient, VectorStore vectorStore, TokenCountEstimator tokenCountEstimator) { return StreamingPromptTransformingChatService.builder(streamingChatClient) @@ -122,7 +122,7 @@ public class ChatMemoryLongTermSystemPromptIT extends BaseMemoryTest { } @Bean - public RelevancyEvaluator relevancyEvaluator(OpenAiChatClient chatClient) { + public RelevancyEvaluator relevancyEvaluator(OpenAiChatConnector chatClient) { return new RelevancyEvaluator(chatClient); } diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryShortTermMessageListIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryShortTermMessageListIT.java index d26f6c563..2bf642da2 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryShortTermMessageListIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryShortTermMessageListIT.java @@ -31,7 +31,7 @@ import org.springframework.ai.chat.memory.LastMaxTokenSizeContentTransformer; import org.springframework.ai.chat.memory.MessageChatMemoryAugmentor; import org.springframework.ai.evaluation.BaseMemoryTest; import org.springframework.ai.evaluation.RelevancyEvaluator; -import org.springframework.ai.openai.OpenAiChatClient; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator; import org.springframework.ai.tokenizer.TokenCountEstimator; @@ -59,8 +59,8 @@ public class ChatMemoryShortTermMessageListIT extends BaseMemoryTest { } @Bean - public OpenAiChatClient openAiClient(OpenAiApi openAiApi) { - return new OpenAiChatClient(openAiApi); + public OpenAiChatConnector openAiClient(OpenAiApi openAiApi) { + return new OpenAiChatConnector(openAiApi); } @Bean @@ -74,7 +74,7 @@ public class ChatMemoryShortTermMessageListIT extends BaseMemoryTest { } @Bean - public ChatService memoryChatService(OpenAiChatClient chatClient, ChatMemory chatHistory, + public ChatService memoryChatService(OpenAiChatConnector chatClient, ChatMemory chatHistory, TokenCountEstimator tokenCountEstimator) { return PromptTransformingChatService.builder(chatClient) @@ -86,7 +86,7 @@ public class ChatMemoryShortTermMessageListIT extends BaseMemoryTest { } @Bean - public StreamingChatService memoryStreamingChatService(OpenAiChatClient streamingChatClient, + public StreamingChatService memoryStreamingChatService(OpenAiChatConnector streamingChatClient, ChatMemory chatHistory, TokenCountEstimator tokenCountEstimator) { return StreamingPromptTransformingChatService.builder(streamingChatClient) @@ -98,7 +98,7 @@ public class ChatMemoryShortTermMessageListIT extends BaseMemoryTest { } @Bean - public RelevancyEvaluator relevancyEvaluator(OpenAiChatClient chatClient) { + public RelevancyEvaluator relevancyEvaluator(OpenAiChatConnector chatClient) { return new RelevancyEvaluator(chatClient); } diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryShortTermSystemPromptIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryShortTermSystemPromptIT.java index 7ca4c795b..ea9707848 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryShortTermSystemPromptIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryShortTermSystemPromptIT.java @@ -32,7 +32,7 @@ import org.springframework.ai.chat.memory.LastMaxTokenSizeContentTransformer; import org.springframework.ai.chat.memory.SystemPromptChatMemoryAugmentor; import org.springframework.ai.evaluation.BaseMemoryTest; import org.springframework.ai.evaluation.RelevancyEvaluator; -import org.springframework.ai.openai.OpenAiChatClient; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator; import org.springframework.ai.tokenizer.TokenCountEstimator; @@ -60,8 +60,8 @@ public class ChatMemoryShortTermSystemPromptIT extends BaseMemoryTest { } @Bean - public OpenAiChatClient openAiClient(OpenAiApi openAiApi) { - return new OpenAiChatClient(openAiApi); + public OpenAiChatConnector openAiClient(OpenAiApi openAiApi) { + return new OpenAiChatConnector(openAiApi); } @Bean @@ -75,7 +75,7 @@ public class ChatMemoryShortTermSystemPromptIT extends BaseMemoryTest { } @Bean - public ChatService memoryChatService(OpenAiChatClient chatClient, ChatMemory chatHistory, + public ChatService memoryChatService(OpenAiChatConnector chatClient, ChatMemory chatHistory, TokenCountEstimator tokenCountEstimator) { return PromptTransformingChatService.builder(chatClient) @@ -87,7 +87,7 @@ public class ChatMemoryShortTermSystemPromptIT extends BaseMemoryTest { } @Bean - public StreamingChatService memoryStreamingChatService(OpenAiChatClient streamingChatClient, + public StreamingChatService memoryStreamingChatService(OpenAiChatConnector streamingChatClient, ChatMemory chatHistory, TokenCountEstimator tokenCountEstimator) { return StreamingPromptTransformingChatService.builder(streamingChatClient) @@ -99,7 +99,7 @@ public class ChatMemoryShortTermSystemPromptIT extends BaseMemoryTest { } @Bean - public RelevancyEvaluator relevancyEvaluator(OpenAiChatClient chatClient) { + public RelevancyEvaluator relevancyEvaluator(OpenAiChatConnector chatClient) { return new RelevancyEvaluator(chatClient); } diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/LongShortTermChatMemoryWithRagIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/LongShortTermChatMemoryWithRagIT.java index c2739a018..87779e194 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/LongShortTermChatMemoryWithRagIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/LongShortTermChatMemoryWithRagIT.java @@ -50,10 +50,9 @@ import org.springframework.ai.chat.prompt.transformer.VectorStoreRetriever; import org.springframework.ai.document.Document; import org.springframework.ai.document.DocumentTransformer; import org.springframework.ai.embedding.EmbeddingClient; -import org.springframework.ai.evaluation.EvaluationRequest; import org.springframework.ai.evaluation.EvaluationResponse; import org.springframework.ai.evaluation.RelevancyEvaluator; -import org.springframework.ai.openai.OpenAiChatClient; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.ai.openai.OpenAiEmbeddingClient; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.reader.JsonReader; @@ -164,8 +163,8 @@ public class LongShortTermChatMemoryWithRagIT { } @Bean - public OpenAiChatClient openAiClient(OpenAiApi openAiApi) { - return new OpenAiChatClient(openAiApi); + public OpenAiChatConnector openAiClient(OpenAiApi openAiApi) { + return new OpenAiChatConnector(openAiApi); } @Bean @@ -187,7 +186,7 @@ public class LongShortTermChatMemoryWithRagIT { } @Bean - public ChatService memoryChatService(OpenAiChatClient chatClient, VectorStore vectorStore, + public ChatService memoryChatService(OpenAiChatConnector chatClient, VectorStore vectorStore, TokenCountEstimator tokenCountEstimator, ChatMemory chatHistory) { return PromptTransformingChatService.builder(chatClient) @@ -224,7 +223,7 @@ public class LongShortTermChatMemoryWithRagIT { } // @Bean - // public StreamingChatService memoryStreamingChatAgent(OpenAiChatClient + // public StreamingChatService memoryStreamingChatAgent(OpenAiChatConnector // streamingChatClient, // VectorStore vectorStore, TokenCountEstimator tokenCountEstimator, ChatHistory // chatHistory) { @@ -241,7 +240,7 @@ public class LongShortTermChatMemoryWithRagIT { // } @Bean - public RelevancyEvaluator relevancyEvaluator(OpenAiChatClient chatClient) { + public RelevancyEvaluator relevancyEvaluator(OpenAiChatConnector chatClient) { // Use GPT 4 as a better model for determining relevancy. gpt 3.5 makes basic // mistakes OpenAiChatOptions openAiChatOptions = OpenAiChatOptions.builder() diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/OpenAiPromptTransformingChatServiceIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/OpenAiPromptTransformingChatServiceIT.java index a5f1ed415..18c00ad32 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/OpenAiPromptTransformingChatServiceIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/OpenAiPromptTransformingChatServiceIT.java @@ -23,15 +23,16 @@ import io.qdrant.client.QdrantClient; import io.qdrant.client.QdrantGrpcClient; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.service.ChatService; import org.springframework.ai.chat.prompt.transformer.TransformerContentType; import org.springframework.ai.document.Document; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.ai.openai.OpenAiChatOptions; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.qdrant.QdrantContainer; -import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.service.PromptTransformingChatService; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; @@ -39,10 +40,8 @@ import org.springframework.ai.chat.prompt.transformer.ChatServiceContext; import org.springframework.ai.chat.prompt.transformer.QuestionContextAugmentor; import org.springframework.ai.chat.prompt.transformer.VectorStoreRetriever; import org.springframework.ai.embedding.EmbeddingClient; -import org.springframework.ai.evaluation.EvaluationRequest; import org.springframework.ai.evaluation.EvaluationResponse; import org.springframework.ai.evaluation.RelevancyEvaluator; -import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiEmbeddingClient; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.reader.JsonReader; @@ -72,7 +71,7 @@ public class OpenAiPromptTransformingChatServiceIT { @Container static QdrantContainer qdrantContainer = new QdrantContainer("qdrant/qdrant:v1.9.2"); - private final ChatClient chatClient; + private final ChatConnector chatConnector; private final VectorStore vectorStore; @@ -82,9 +81,9 @@ public class OpenAiPromptTransformingChatServiceIT { private ChatService chatService; @Autowired - public OpenAiPromptTransformingChatServiceIT(ChatClient chatClient, ChatService chatService, + public OpenAiPromptTransformingChatServiceIT(ChatConnector chatConnector, ChatService chatService, VectorStore vectorStore) { - this.chatClient = chatClient; + this.chatConnector = chatConnector; this.chatService = chatService; this.vectorStore = vectorStore; } @@ -103,7 +102,7 @@ public class OpenAiPromptTransformingChatServiceIT { OpenAiChatOptions openAiChatOptions = OpenAiChatOptions.builder() .withModel(GPT_4_TURBO_PREVIEW.getValue()) .build(); - var relevancyEvaluator = new RelevancyEvaluator(this.chatClient, openAiChatOptions); + var relevancyEvaluator = new RelevancyEvaluator(this.chatConnector, openAiChatOptions); EvaluationResponse evaluationResponse = relevancyEvaluator.evaluate(chatServiceResponse.toEvaluationRequest()); assertTrue(evaluationResponse.isPass(), "Response is not relevant to the question"); @@ -146,8 +145,8 @@ public class OpenAiPromptTransformingChatServiceIT { } @Bean - public ChatClient openAiClient(OpenAiApi openAiApi) { - return new OpenAiChatClient(openAiApi); + public ChatConnector openAiClient(OpenAiApi openAiApi) { + return new OpenAiChatConnector(openAiApi); } @Bean @@ -164,8 +163,8 @@ public class OpenAiPromptTransformingChatServiceIT { } @Bean - public ChatService chatService(ChatClient chatClient, VectorStore vectorStore) { - return PromptTransformingChatService.builder(chatClient) + public ChatService chatService(ChatConnector chatConnector, VectorStore vectorStore) { + return PromptTransformingChatService.builder(chatConnector) .withRetrievers(List.of(new VectorStoreRetriever(vectorStore, SearchRequest.defaults()))) .withAugmentors(List.of(new QuestionContextAugmentor())) .build(); diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/testutils/AbstractIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/testutils/AbstractIT.java index 89155e9e8..74b49a618 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/testutils/AbstractIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/testutils/AbstractIT.java @@ -21,7 +21,7 @@ import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.chat.prompt.Prompt; @@ -43,7 +43,7 @@ public abstract class AbstractIT { private static final Logger logger = LoggerFactory.getLogger(AbstractIT.class); @Autowired - protected ChatClient chatClient; + protected ChatConnector chatConnector; @Autowired protected StreamingChatClient streamingChatClient; @@ -85,12 +85,12 @@ public abstract class AbstractIT { } Message userMessage = userPromptTemplate.createMessage(); Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - String yesOrNo = chatClient.call(prompt).getResult().getOutput().getContent(); + String yesOrNo = chatConnector.execute(prompt).getResult().getOutput().getContent(); logger.info("Is Answer related to question: " + yesOrNo); if (yesOrNo.equalsIgnoreCase("no")) { SystemMessage notRelatedSystemMessage = new SystemMessage(qaEvaluatorNotRelatedResource); prompt = new Prompt(List.of(userMessage, notRelatedSystemMessage)); - String reasonForFailure = chatClient.call(prompt).getResult().getOutput().getContent(); + String reasonForFailure = chatConnector.execute(prompt).getResult().getOutput().getContent(); fail(reasonForFailure); } else { diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/transformer/MetadataTransformerIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/transformer/MetadataTransformerIT.java index d13c06612..bf01df15c 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/transformer/MetadataTransformerIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/transformer/MetadataTransformerIT.java @@ -24,8 +24,8 @@ import org.junit.jupiter.api.Test; import org.springframework.ai.document.DefaultContentFormatter; import org.springframework.ai.document.Document; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.transformer.ContentFormatTransformer; import org.springframework.ai.transformer.KeywordMetadataEnricher; import org.springframework.ai.transformer.SummaryMetadataEnricher; @@ -163,18 +163,18 @@ public class MetadataTransformerIT { } @Bean - public OpenAiChatClient openAiChatClient(OpenAiApi openAiApi) { - OpenAiChatClient openAiChatClient = new OpenAiChatClient(openAiApi); + public OpenAiChatConnector openAiChatClient(OpenAiApi openAiApi) { + OpenAiChatConnector openAiChatClient = new OpenAiChatConnector(openAiApi); return openAiChatClient; } @Bean - public KeywordMetadataEnricher keywordMetadata(OpenAiChatClient aiClient) { + public KeywordMetadataEnricher keywordMetadata(OpenAiChatConnector aiClient) { return new KeywordMetadataEnricher(aiClient, 5); } @Bean - public SummaryMetadataEnricher summaryMetadata(OpenAiChatClient aiClient) { + public SummaryMetadataEnricher summaryMetadata(OpenAiChatConnector aiClient) { return new SummaryMetadataEnricher(aiClient, List.of(SummaryType.PREVIOUS, SummaryType.CURRENT, SummaryType.NEXT)); } diff --git a/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatClient.java b/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatConnector.java similarity index 96% rename from models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatClient.java rename to models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatConnector.java index 4091cdd36..f3edd2d37 100644 --- a/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatClient.java +++ b/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatConnector.java @@ -32,7 +32,7 @@ import com.google.cloud.vertexai.generativeai.PartMaker; import com.google.cloud.vertexai.generativeai.ResponseStream; import com.google.protobuf.Struct; import com.google.protobuf.util.JsonFormat; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.StreamingChatClient; @@ -65,9 +65,9 @@ import java.util.stream.Collectors; * @author Grogdunn * @since 0.8.1 */ -public class VertexAiGeminiChatClient - extends AbstractFunctionCallSupport - implements ChatClient, StreamingChatClient, DisposableBean { +public class VertexAiGeminiChatConnector + extends AbstractFunctionCallSupport + implements ChatConnector, StreamingChatClient, DisposableBean { private final static boolean IS_RUNTIME_CALL = true; @@ -117,7 +117,7 @@ public class VertexAiGeminiChatClient } - public VertexAiGeminiChatClient(VertexAI vertexAI) { + public VertexAiGeminiChatConnector(VertexAI vertexAI) { this(vertexAI, VertexAiGeminiChatOptions.builder() .withModel(ChatModel.GEMINI_PRO_VISION.getValue()) @@ -125,11 +125,11 @@ public class VertexAiGeminiChatClient .build()); } - public VertexAiGeminiChatClient(VertexAI vertexAI, VertexAiGeminiChatOptions options) { + public VertexAiGeminiChatConnector(VertexAI vertexAI, VertexAiGeminiChatOptions options) { this(vertexAI, options, null); } - public VertexAiGeminiChatClient(VertexAI vertexAI, VertexAiGeminiChatOptions options, + public VertexAiGeminiChatConnector(VertexAI vertexAI, VertexAiGeminiChatOptions options, FunctionCallbackContext functionCallbackContext) { super(functionCallbackContext); @@ -145,7 +145,7 @@ public class VertexAiGeminiChatClient // https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/gemini @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { var geminiRequest = createGeminiRequest(prompt); diff --git a/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatOptions.java b/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatOptions.java index 7d4e9875a..a0dae53e1 100644 --- a/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatOptions.java +++ b/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatOptions.java @@ -77,10 +77,10 @@ public class VertexAiGeminiChatOptions implements FunctionCallingOptions, ChatOp private @JsonProperty("modelName") String model; /** - * Tool Function Callbacks to register with the ChatClient. + * Tool Function Callbacks to register with the ChatConnector. * For Prompt Options the functionCallbacks are automatically enabled for the duration of the prompt execution. * For Default Options the functionCallbacks are registered but disabled by default. Use the enableFunctions to set the functions - * from the registry to be used by the ChatClient chat completion requests. + * from the registry to be used by the ChatConnector chat completion requests. */ @NestedConfigurationProperty @JsonIgnore diff --git a/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/aot/VertexAiGeminiRuntimeHints.java b/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/aot/VertexAiGeminiRuntimeHints.java index 8911288fa..416dbad37 100644 --- a/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/aot/VertexAiGeminiRuntimeHints.java +++ b/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/aot/VertexAiGeminiRuntimeHints.java @@ -15,7 +15,7 @@ */ package org.springframework.ai.vertexai.gemini.aot; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatConnector; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; @@ -34,7 +34,7 @@ public class VertexAiGeminiRuntimeHints implements RuntimeHintsRegistrar { @Override public void registerHints(RuntimeHints hints, ClassLoader classLoader) { var mcs = MemberCategory.values(); - for (var tr : findJsonAnnotatedClassesInPackage(VertexAiGeminiChatClient.class)) + for (var tr : findJsonAnnotatedClassesInPackage(VertexAiGeminiChatConnector.class)) hints.reflection().registerType(tr, mcs); } diff --git a/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatClientIT.java b/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatConnectorIT.java similarity index 93% rename from models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatClientIT.java rename to models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatConnectorIT.java index 9eff8981e..d22a7bc7d 100644 --- a/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatClientIT.java +++ b/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatConnectorIT.java @@ -53,10 +53,10 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @EnabledIfEnvironmentVariable(named = "VERTEX_AI_GEMINI_PROJECT_ID", matches = ".*") @EnabledIfEnvironmentVariable(named = "VERTEX_AI_GEMINI_LOCATION", matches = ".*") -class VertexAiGeminiChatClientIT { +class VertexAiGeminiChatConnectorIT { @Autowired - private VertexAiGeminiChatClient client; + private VertexAiGeminiChatConnector client; @Value("classpath:/prompts/system-message.st") private Resource systemResource; @@ -70,7 +70,7 @@ class VertexAiGeminiChatClientIT { SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource); Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice)); Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); } @@ -87,7 +87,7 @@ class VertexAiGeminiChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "ice cream flavors.", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.client.call(prompt).getResult(); + Generation generation = this.client.execute(prompt).getResult(); List list = outputParser.convert(generation.getOutput().getContent()); assertThat(list).hasSize(5); @@ -106,7 +106,7 @@ class VertexAiGeminiChatClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); Map result = outputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -129,7 +129,7 @@ class VertexAiGeminiChatClientIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); ActorsFilmsRecord actorsFilms = outputConvert.convert(generation.getOutput().getContent()); assertThat(actorsFilms.actor()).isEqualTo("Tom Hanks"); @@ -191,7 +191,7 @@ class VertexAiGeminiChatClientIT { var userMessage = new UserMessage("Explain what do you see o this picture?", List.of(new Media(MimeTypeUtils.IMAGE_PNG, data))); - var response = client.call(new Prompt(List.of(userMessage))); + var response = client.execute(new Prompt(List.of(userMessage))); // Response should contain something like: // I see a bunch of bananas in a golden basket. The bananas are ripe and yellow. @@ -231,10 +231,10 @@ class VertexAiGeminiChatClientIT { } @Bean - public VertexAiGeminiChatClient vertexAiEmbedding(VertexAI vertexAi) { - return new VertexAiGeminiChatClient(vertexAi, + public VertexAiGeminiChatConnector vertexAiEmbedding(VertexAI vertexAi) { + return new VertexAiGeminiChatConnector(vertexAi, VertexAiGeminiChatOptions.builder() - .withModel(VertexAiGeminiChatClient.ChatModel.GEMINI_PRO_VISION.getValue()) + .withModel(VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO_VISION.getValue()) .build()); } diff --git a/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/aot/VertexAiGeminiRuntimeHintsTests.java b/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/aot/VertexAiGeminiRuntimeHintsTests.java index 2e3f12f12..21c0e00a8 100644 --- a/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/aot/VertexAiGeminiRuntimeHintsTests.java +++ b/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/aot/VertexAiGeminiRuntimeHintsTests.java @@ -19,7 +19,7 @@ import java.util.Set; import org.junit.jupiter.api.Test; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatConnector; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.TypeReference; @@ -38,7 +38,7 @@ class VertexAiGeminiRuntimeHintsTests { RuntimeHints runtimeHints = new RuntimeHints(); VertexAiGeminiRuntimeHints vertexAiGeminiRuntimeHints = new VertexAiGeminiRuntimeHints(); vertexAiGeminiRuntimeHints.registerHints(runtimeHints, null); - Set jsonAnnotatedClasses = findJsonAnnotatedClassesInPackage(VertexAiGeminiChatClient.class); + Set jsonAnnotatedClasses = findJsonAnnotatedClassesInPackage(VertexAiGeminiChatConnector.class); for (TypeReference jsonAnnotatedClass : jsonAnnotatedClasses) { assertThat(runtimeHints).matches(reflection().onType(jsonAnnotatedClass)); } diff --git a/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/function/VertexAiGeminiChatClientFunctionCallingIT.java b/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/function/VertexAiGeminiChatConnectorFunctionCallingIT.java similarity index 86% rename from models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/function/VertexAiGeminiChatClientFunctionCallingIT.java rename to models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/function/VertexAiGeminiChatConnectorFunctionCallingIT.java index 2026729e3..f993cbad8 100644 --- a/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/function/VertexAiGeminiChatClientFunctionCallingIT.java +++ b/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/function/VertexAiGeminiChatConnectorFunctionCallingIT.java @@ -23,11 +23,11 @@ import java.util.stream.Collectors; import com.google.cloud.vertexai.Transport; import com.google.cloud.vertexai.VertexAI; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatConnector; import reactor.core.publisher.Flux; import org.springframework.ai.chat.ChatResponse; @@ -38,7 +38,6 @@ import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.function.FunctionCallbackWrapper; import org.springframework.ai.model.function.FunctionCallbackWrapper.Builder.SchemaType; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringBootConfiguration; @@ -50,12 +49,12 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @EnabledIfEnvironmentVariable(named = "VERTEX_AI_GEMINI_PROJECT_ID", matches = ".*") @EnabledIfEnvironmentVariable(named = "VERTEX_AI_GEMINI_LOCATION", matches = ".*") -public class VertexAiGeminiChatClientFunctionCallingIT { +public class VertexAiGeminiChatConnectorFunctionCallingIT { private final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired - private VertexAiGeminiChatClient vertexGeminiClient; + private VertexAiGeminiChatConnector vertexGeminiClient; @AfterEach public void afterEach() { @@ -69,7 +68,7 @@ public class VertexAiGeminiChatClientFunctionCallingIT { @Test // @Disabled("Google Vertex AI degraded support for parallel function calls") - public void functionCallExplicitOpenApiSchema() { + public void functionExecuteExplicitOpenApiSchema() { UserMessage userMessage = new UserMessage( "What's the weather like in San Francisco, in Paris and in Tokyo, Japan?" @@ -98,8 +97,8 @@ public class VertexAiGeminiChatClientFunctionCallingIT { """; var promptOptions = VertexAiGeminiChatOptions.builder() - // .withModel(VertexAiGeminiChatClient.ChatModel.GEMINI_PRO.getValue()) - .withModel(VertexAiGeminiChatClient.ChatModel.GEMINI_PRO_1_5_PRO.getValue()) + // .withModel(VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO.getValue()) + .withModel(VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO_1_5_PRO.getValue()) .withFunctionCallbacks(List.of(FunctionCallbackWrapper.builder(new MockWeatherService()) .withName("get_current_weather") .withDescription("Get the current weather in a given location") @@ -107,7 +106,7 @@ public class VertexAiGeminiChatClientFunctionCallingIT { .build())) .build(); - ChatResponse response = vertexGeminiClient.call(new Prompt(messages, promptOptions)); + ChatResponse response = vertexGeminiClient.execute(new Prompt(messages, promptOptions)); logger.info("Response: {}", response); @@ -119,15 +118,15 @@ public class VertexAiGeminiChatClientFunctionCallingIT { } @Test - public void functionCallTestInferredOpenApiSchema() { + public void functionExecuteTestInferredOpenApiSchema() { UserMessage userMessage = new UserMessage("What's the weather like in Paris? Use Celsius units."); List messages = new ArrayList<>(List.of(userMessage)); var promptOptions = VertexAiGeminiChatOptions.builder() - .withModel(VertexAiGeminiChatClient.ChatModel.GEMINI_PRO_1_5_PRO.getValue()) - // .withModel(VertexAiGeminiChatClient.ChatModel.GEMINI_PRO.getValue()) + .withModel(VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO_1_5_PRO.getValue()) + // .withModel(VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO.getValue()) .withFunctionCallbacks(List.of( FunctionCallbackWrapper.builder(new MockWeatherService()) .withSchemaType(SchemaType.OPEN_API_SCHEMA) @@ -142,14 +141,14 @@ public class VertexAiGeminiChatClientFunctionCallingIT { .build())) .build(); - ChatResponse response = vertexGeminiClient.call(new Prompt(messages, promptOptions)); + ChatResponse response = vertexGeminiClient.execute(new Prompt(messages, promptOptions)); logger.info("Response: {}", response); assertThat(response.getResult().getOutput().getContent()).containsAnyOf("15.0", "15"); ChatResponse response2 = vertexGeminiClient - .call(new Prompt("What is the payment status for transaction 696?", promptOptions)); + .execute(new Prompt("What is the payment status for transaction 696?", promptOptions)); logger.info("Response: {}", response2); @@ -158,7 +157,7 @@ public class VertexAiGeminiChatClientFunctionCallingIT { } @Test - public void functionCallTestInferredOpenApiSchemaStream() { + public void functionExecuteTestInferredOpenApiSchemaStream() { UserMessage userMessage = new UserMessage("What's the weather like in San Francisco in Celsius units?"); // UserMessage userMessage = new UserMessage( @@ -168,7 +167,7 @@ public class VertexAiGeminiChatClientFunctionCallingIT { List messages = new ArrayList<>(List.of(userMessage)); var promptOptions = VertexAiGeminiChatOptions.builder() - .withModel(VertexAiGeminiChatClient.ChatModel.GEMINI_PRO.getValue()) + .withModel(VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO.getValue()) .withFunctionCallbacks(List.of(FunctionCallbackWrapper.builder(new MockWeatherService()) .withSchemaType(SchemaType.OPEN_API_SCHEMA) .withName("getCurrentWeather") @@ -224,10 +223,10 @@ public class VertexAiGeminiChatClientFunctionCallingIT { } @Bean - public VertexAiGeminiChatClient vertexAiEmbedding(VertexAI vertexAi) { - return new VertexAiGeminiChatClient(vertexAi, + public VertexAiGeminiChatConnector vertexAiEmbedding(VertexAI vertexAi) { + return new VertexAiGeminiChatConnector(vertexAi, VertexAiGeminiChatOptions.builder() - .withModel(VertexAiGeminiChatClient.ChatModel.GEMINI_PRO.getValue()) + .withModel(VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO.getValue()) .withTemperature(0.9f) .build()); } diff --git a/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatClient.java b/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatConnector.java similarity index 91% rename from models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatClient.java rename to models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatConnector.java index 671097615..8dff115be 100644 --- a/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatClient.java +++ b/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatConnector.java @@ -18,7 +18,7 @@ package org.springframework.ai.vertexai.palm2; import java.util.List; import java.util.stream.Collectors; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; @@ -35,18 +35,18 @@ import org.springframework.util.CollectionUtils; /** * @author Christian Tzolov */ -public class VertexAiPaLm2ChatClient implements ChatClient { +public class VertexAiPaLm2ChatConnector implements ChatConnector { private final VertexAiPaLm2Api vertexAiApi; private final VertexAiPaLm2ChatOptions defaultOptions; - public VertexAiPaLm2ChatClient(VertexAiPaLm2Api vertexAiApi) { + public VertexAiPaLm2ChatConnector(VertexAiPaLm2Api vertexAiApi) { this(vertexAiApi, VertexAiPaLm2ChatOptions.builder().withTemperature(0.7f).withCandidateCount(1).withTopK(20).build()); } - public VertexAiPaLm2ChatClient(VertexAiPaLm2Api vertexAiApi, VertexAiPaLm2ChatOptions defaultOptions) { + public VertexAiPaLm2ChatConnector(VertexAiPaLm2Api vertexAiApi, VertexAiPaLm2ChatOptions defaultOptions) { Assert.notNull(defaultOptions, "Default options must not be null!"); Assert.notNull(vertexAiApi, "VertexAiPaLm2Api must not be null!"); @@ -55,7 +55,7 @@ public class VertexAiPaLm2ChatClient implements ChatClient { } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { GenerateMessageRequest request = createRequest(prompt); diff --git a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatGenerationClientIT.java b/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatGenerationClientIT.java index 5fd43b0d5..f924cb86e 100644 --- a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatGenerationClientIT.java +++ b/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatGenerationClientIT.java @@ -48,7 +48,7 @@ import static org.assertj.core.api.Assertions.assertThat; class VertexAiPaLm2ChatGenerationClientIT { @Autowired - private VertexAiPaLm2ChatClient client; + private VertexAiPaLm2ChatConnector client; @Value("classpath:/prompts/system-message.st") private Resource systemResource; @@ -62,7 +62,7 @@ class VertexAiPaLm2ChatGenerationClientIT { SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource); Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice)); Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); assertThat(response.getResult().getOutput().getContent()).contains("Bartholomew"); } @@ -79,7 +79,7 @@ class VertexAiPaLm2ChatGenerationClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "ice cream flavors.", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.client.call(prompt).getResult(); + Generation generation = this.client.execute(prompt).getResult(); List list = outputConverter.convert(generation.getOutput().getContent()); assertThat(list).hasSize(5); @@ -98,7 +98,7 @@ class VertexAiPaLm2ChatGenerationClientIT { PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); Map result = outputConverter.convert(generation.getOutput().getContent()); assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); @@ -120,7 +120,7 @@ class VertexAiPaLm2ChatGenerationClientIT { """; PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = client.call(prompt).getResult(); + Generation generation = client.execute(prompt).getResult(); ActorsFilmsRecord actorsFilms = outputConverter.convert(generation.getOutput().getContent()); assertThat(actorsFilms.actor()).isEqualTo("Tom Hanks"); @@ -136,8 +136,8 @@ class VertexAiPaLm2ChatGenerationClientIT { } @Bean - public VertexAiPaLm2ChatClient vertexAiEmbedding(VertexAiPaLm2Api vertexAiApi) { - return new VertexAiPaLm2ChatClient(vertexAiApi); + public VertexAiPaLm2ChatConnector vertexAiEmbedding(VertexAiPaLm2Api vertexAiApi) { + return new VertexAiPaLm2ChatConnector(vertexAiApi); } } diff --git a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatRequestTests.java b/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatRequestTests.java index 6c5478f67..0644241b5 100644 --- a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatRequestTests.java +++ b/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatRequestTests.java @@ -29,7 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class VertexAiPaLm2ChatRequestTests { - VertexAiPaLm2ChatClient client = new VertexAiPaLm2ChatClient(new VertexAiPaLm2Api("bla")); + VertexAiPaLm2ChatConnector client = new VertexAiPaLm2ChatConnector(new VertexAiPaLm2Api("bla")); @Test public void createRequestWithDefaultOptions() { diff --git a/models/spring-ai-watsonx-ai/src/main/java/org/springframework/ai/watsonx/WatsonxAiChatClient.java b/models/spring-ai-watsonx-ai/src/main/java/org/springframework/ai/watsonx/WatsonxAiChatConnector.java similarity index 92% rename from models/spring-ai-watsonx-ai/src/main/java/org/springframework/ai/watsonx/WatsonxAiChatClient.java rename to models/spring-ai-watsonx-ai/src/main/java/org/springframework/ai/watsonx/WatsonxAiChatConnector.java index b4f5c14ff..a8306585e 100644 --- a/models/spring-ai-watsonx-ai/src/main/java/org/springframework/ai/watsonx/WatsonxAiChatClient.java +++ b/models/spring-ai-watsonx-ai/src/main/java/org/springframework/ai/watsonx/WatsonxAiChatConnector.java @@ -20,7 +20,7 @@ import java.util.Map; import reactor.core.publisher.Flux; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.StreamingChatClient; @@ -35,7 +35,7 @@ import org.springframework.ai.watsonx.utils.MessageToPromptConverter; import org.springframework.util.Assert; /** - * {@link ChatClient} implementation for {@literal watsonx.ai}. + * {@link ChatConnector} implementation for {@literal watsonx.ai}. * * watsonx.ai allows developers to use large language models within a SaaS service. It * supports multiple open-source models as well as IBM created models @@ -48,13 +48,13 @@ import org.springframework.util.Assert; * @author Christian Tzolov * @since 1.0.0 */ -public class WatsonxAiChatClient implements ChatClient, StreamingChatClient { +public class WatsonxAiChatConnector implements ChatConnector, StreamingChatClient { private final WatsonxAiApi watsonxAiApi; private final WatsonxAiChatOptions defaultOptions; - public WatsonxAiChatClient(WatsonxAiApi watsonxAiApi) { + public WatsonxAiChatConnector(WatsonxAiApi watsonxAiApi) { this(watsonxAiApi, WatsonxAiChatOptions.builder() .withTemperature(0.7f) @@ -68,7 +68,7 @@ public class WatsonxAiChatClient implements ChatClient, StreamingChatClient { .build()); } - public WatsonxAiChatClient(WatsonxAiApi watsonxAiApi, WatsonxAiChatOptions defaultOptions) { + public WatsonxAiChatConnector(WatsonxAiApi watsonxAiApi, WatsonxAiChatOptions defaultOptions) { Assert.notNull(watsonxAiApi, "watsonxAiApi cannot be null"); Assert.notNull(defaultOptions, "defaultOptions cannot be null"); this.watsonxAiApi = watsonxAiApi; @@ -76,7 +76,7 @@ public class WatsonxAiChatClient implements ChatClient, StreamingChatClient { } @Override - public ChatResponse call(Prompt prompt) { + public ChatResponse execute(Prompt prompt) { WatsonxAiRequest request = request(prompt); diff --git a/models/spring-ai-watsonx-ai/src/test/java/org/springframework/ai/watsonx/WatsonxAiChatClientTest.java b/models/spring-ai-watsonx-ai/src/test/java/org/springframework/ai/watsonx/WatsonxAiChatConnectorTest.java similarity index 96% rename from models/spring-ai-watsonx-ai/src/test/java/org/springframework/ai/watsonx/WatsonxAiChatClientTest.java rename to models/spring-ai-watsonx-ai/src/test/java/org/springframework/ai/watsonx/WatsonxAiChatConnectorTest.java index c74afa427..153c45937 100644 --- a/models/spring-ai-watsonx-ai/src/test/java/org/springframework/ai/watsonx/WatsonxAiChatClientTest.java +++ b/models/spring-ai-watsonx-ai/src/test/java/org/springframework/ai/watsonx/WatsonxAiChatConnectorTest.java @@ -46,9 +46,9 @@ import static org.mockito.Mockito.when; * @author Pablo Sanchidrian Herrera * @author John Jairo Moreno Rojas */ -public class WatsonxAiChatClientTest { +public class WatsonxAiChatConnectorTest { - WatsonxAiChatClient chatClient = new WatsonxAiChatClient(mock(WatsonxAiApi.class)); + WatsonxAiChatConnector chatClient = new WatsonxAiChatConnector(mock(WatsonxAiApi.class)); @Test public void testCreateRequestWithNoModelId() { @@ -155,9 +155,9 @@ public class WatsonxAiChatClientTest { } @Test - public void testCallMethod() { + public void testExecuteMethod() { WatsonxAiApi mockChatApi = mock(WatsonxAiApi.class); - WatsonxAiChatClient client = new WatsonxAiChatClient(mockChatApi); + WatsonxAiChatConnector client = new WatsonxAiChatConnector(mockChatApi); Prompt prompt = new Prompt(List.of(new SystemMessage("Your prompt here")), WatsonxAiChatOptions.builder().withModel("google/flan-ul2").build()); @@ -177,7 +177,7 @@ public class WatsonxAiChatClientTest { Map.of("warnings", List.of(Map.of("message", "the message", "id", "disclaimer_warning"))))); ChatResponse expectedResponse = new ChatResponse(List.of(expectedGenerator)); - ChatResponse response = client.call(prompt); + ChatResponse response = client.execute(prompt); Assert.assertEquals(expectedResponse.getResults().size(), response.getResults().size()); Assert.assertEquals(expectedResponse.getResult().getOutput(), response.getResult().getOutput()); @@ -186,7 +186,7 @@ public class WatsonxAiChatClientTest { @Test public void testStreamMethod() { WatsonxAiApi mockChatApi = mock(WatsonxAiApi.class); - WatsonxAiChatClient client = new WatsonxAiChatClient(mockChatApi); + WatsonxAiChatConnector client = new WatsonxAiChatConnector(mockChatApi); Prompt prompt = new Prompt(List.of(new SystemMessage("Your prompt here")), WatsonxAiChatOptions.builder().withModel("google/flan-ul2").build()); diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/ChatClient.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/ChatClient.java index cff4f8674..400cda614 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/ChatClient.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/ChatClient.java @@ -1,44 +1,175 @@ -/* - * Copyright 2023 - 2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package org.springframework.ai.chat; -import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.chat.connector.ChatConnector; +import org.springframework.ai.chat.messages.Media; +import org.springframework.core.ParameterizedTypeReference; -import java.util.Arrays; +import java.util.*; -import org.springframework.ai.chat.messages.Message; -import org.springframework.ai.chat.messages.UserMessage; -import org.springframework.ai.model.ModelClient; -@FunctionalInterface -public interface ChatClient extends ModelClient { +/** + * @author Mark Pollack + * @author Christian Tsolov + * @author Josh Long + */ +public class ChatClient { + + private final ChatConnector connector; + + private final String userPrompt, systemPrompt; + + private final List functions; + + private final List media; + + public ChatClient(ChatConnector connector, String defaultSystemPrompt, String defaultUserPrompt, + List defaultFunctions, List defaultMedia) { + this.connector = connector; + this.userPrompt = defaultUserPrompt; + this.systemPrompt = defaultSystemPrompt; + this.functions = defaultFunctions; + this.media = defaultMedia; - default String call(String message) { - Prompt prompt = new Prompt(new UserMessage(message)); - Generation generation = call(prompt).getResult(); - return (generation != null) ? generation.getOutput().getContent() : ""; } - default String call(Message... messages) { - Prompt prompt = new Prompt(Arrays.asList(messages)); - Generation generation = call(prompt).getResult(); - return (generation != null) ? generation.getOutput().getContent() : ""; + public ChatClientRequest build() { + return new ChatClientRequest(this.userPrompt, this.systemPrompt, this.functions, this.media); } - @Override - ChatResponse call(Prompt prompt); + public ChatClientRequest userPrompt(String userPrompt, Map params) { + var ccr = new ChatClientRequest(userPrompt, this.systemPrompt, this.functions, this.media); + ccr.userPromptParams(params); + return ccr; + } + + public ChatClientRequest userPrompt(String userPrompt) { + return new ChatClientRequest(userPrompt, this.systemPrompt, this.functions, this.media); + } + + public static class ChatClientRequest { + + private String userPrompt = ""; + + private String systemPrompt = ""; + + private final List media = new ArrayList<>(); + + private final List functions = new ArrayList<>(); + + private final Map userPromptParams = new HashMap<>(); + + private final Map systemPromptParams = new HashMap<>(); + + List media() { + return this.media; + } + + String systemPrompt() { + return this.systemPrompt; + } + + String userPrompt() { + return this.userPrompt; + } + + List functions() { + return this.functions; + } + + public ChatClientRequest(String userPrompt, String systemPrompt, List functions, List media) { + this.userPrompt = userPrompt; + this.systemPrompt = systemPrompt; + this.functions.addAll(functions); + this.media.addAll(media); + } + + public ChatClientRequest userPromptParam(String key, String value) { + this.userPromptParams.put(key, value); + return this; + } + + public ChatClientRequest systemPromptParam(String key, String value) { + this.systemPromptParams.put(key, value); + return this; + } + + public ChatClientRequest systemPromptParams(Map systemPromptParams) { + this.systemPromptParams.putAll(systemPromptParams); + return this; + } + + public ChatClientRequest userPromptParams(Map userPromptParams) { + this.userPromptParams.putAll(userPromptParams); + return this; + } + + public ChatClientRequest userPrompt(String userPrompt) { + this.userPrompt = userPrompt; + return this; + } + + public ChatClientRequest systemPrompt(String systemPrompt) { + this.systemPrompt = systemPrompt; + return this; + } + + public ChatClientRequest media(Media... media) { + this.media.addAll(Arrays.asList(media)); + return this; + } + + public ChatClientRequest functions(String... functions) { + this.functions.addAll(Arrays.asList(functions)); + return this; + } + + public T chat(Class clzz) { + return null; + } + + public T chat(ParameterizedTypeReference clzz) { + return null; + } + + } + + public static class ChatClientBuilder { + + private final ChatConnector connector; + + private final List defaultMedia = new ArrayList<>(); + + private final List defaultFunctions = new ArrayList<>(); + + private String defaultSystemPrompt; + + private String defaultUserPrompt; + + ChatClientBuilder(ChatConnector connector) { + this.connector = connector; + } + + public ChatClient build() { + return new ChatClient(this.connector, this.defaultSystemPrompt, this.defaultUserPrompt, + this.defaultFunctions, this.defaultMedia); + } + + public ChatClientBuilder defaultSystemPrompt(String systemPrompt) { + return this; + } + + public ChatClientBuilder defaultFunctions(String... functionNames) { + return this; + } + + public ChatClientBuilder defaultUserPrompt(String userPrompt) { + return this; + } + + } + + public static ChatClientBuilder builder(ChatConnector connector) { + return new ChatClientBuilder(connector); + } } diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/connector/ChatConnector.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/connector/ChatConnector.java new file mode 100644 index 000000000..0af5bb033 --- /dev/null +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/connector/ChatConnector.java @@ -0,0 +1,35 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ai.chat.connector; + +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.prompt.Prompt; + +public interface ChatConnector { + + /* + * default String call(String message) { Prompt prompt = new Prompt(new + * UserMessage(message)); Generation generation = call(prompt).getResult(); return + * (generation != null) ? generation.getOutput().getContent() : ""; } + * + * public String call(Message... messages) { Prompt prompt = new + * Prompt(Arrays.asList(messages)); Generation generation = call(prompt).getResult(); + * return (generation != null) ? generation.getOutput().getContent() : ""; } + */ + + ChatResponse execute(Prompt prompt); + +} diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/service/PromptTransformingChatService.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/service/PromptTransformingChatService.java index 761ae5f42..c7fc3b73a 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/service/PromptTransformingChatService.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/service/PromptTransformingChatService.java @@ -15,7 +15,7 @@ */ package org.springframework.ai.chat.service; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.prompt.transformer.ChatServiceContext; import org.springframework.ai.chat.prompt.transformer.PromptTransformer; @@ -35,7 +35,7 @@ import java.util.Objects; */ public class PromptTransformingChatService implements ChatService { - private ChatClient chatClient; + private ChatConnector chatConnector; private List retrievers; @@ -45,19 +45,19 @@ public class PromptTransformingChatService implements ChatService { private List chatServiceListeners; - public PromptTransformingChatService(ChatClient chatClient, List retrievers, + public PromptTransformingChatService(ChatConnector chatConnector, List retrievers, List documentPostProcessors, List augmentors, List chatServiceListeners) { - Objects.requireNonNull(chatClient, "chatClient must not be null"); - this.chatClient = chatClient; + Objects.requireNonNull(chatConnector, "chatConnector must not be null"); + this.chatConnector = chatConnector; this.retrievers = retrievers; this.documentPostProcessors = documentPostProcessors; this.augmentors = augmentors; this.chatServiceListeners = chatServiceListeners; } - public static Builder builder(ChatClient chatClient) { - return new Builder().withChatClient(chatClient); + public static Builder builder(ChatConnector chatConnector) { + return new Builder().withChatClient(chatConnector); } @Override @@ -86,7 +86,7 @@ public class PromptTransformingChatService implements ChatService { } // Perform generation - ChatResponse chatResponse = this.chatClient.call(chatServiceContext.getPrompt()); + ChatResponse chatResponse = this.chatConnector.execute(chatServiceContext.getPrompt()); // Invoke Listeners onComplete ChatServiceResponse chatServiceResponse = new ChatServiceResponse(chatServiceContext, chatResponse); @@ -98,7 +98,7 @@ public class PromptTransformingChatService implements ChatService { public static class Builder { - private ChatClient chatClient; + private ChatConnector chatConnector; private List retrievers = new ArrayList<>(); @@ -108,8 +108,8 @@ public class PromptTransformingChatService implements ChatService { private List chatServiceListeners = new ArrayList<>(); - public Builder withChatClient(ChatClient chatClient) { - this.chatClient = chatClient; + public Builder withChatClient(ChatConnector chatConnector) { + this.chatConnector = chatConnector; return this; } @@ -134,7 +134,7 @@ public class PromptTransformingChatService implements ChatService { } public PromptTransformingChatService build() { - return new PromptTransformingChatService(chatClient, retrievers, documentPostProcessors, augmentors, + return new PromptTransformingChatService(chatConnector, retrievers, documentPostProcessors, augmentors, chatServiceListeners); } diff --git a/spring-ai-core/src/main/java/org/springframework/ai/evaluation/RelevancyEvaluator.java b/spring-ai-core/src/main/java/org/springframework/ai/evaluation/RelevancyEvaluator.java index 8afc9dcff..e6d898b08 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/evaluation/RelevancyEvaluator.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/evaluation/RelevancyEvaluator.java @@ -1,6 +1,6 @@ package org.springframework.ai.evaluation; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.MessageType; @@ -31,14 +31,14 @@ public class RelevancyEvaluator implements Evaluator { private final ChatOptions chatOptions; - private ChatClient chatClient; + private ChatConnector chatConnector; - public RelevancyEvaluator(ChatClient chatClient) { - this(chatClient, ChatOptionsBuilder.builder().build()); + public RelevancyEvaluator(ChatConnector chatConnector) { + this(chatConnector, ChatOptionsBuilder.builder().build()); } - public RelevancyEvaluator(ChatClient chatClient, ChatOptions chatOptions) { - this.chatClient = chatClient; + public RelevancyEvaluator(ChatConnector chatConnector, ChatOptions chatOptions) { + this.chatConnector = chatConnector; this.chatOptions = chatOptions; } @@ -52,7 +52,7 @@ public class RelevancyEvaluator implements Evaluator { Message message = promptTemplate .createMessage(Map.of("query", query, "response", response, "context", context)); - ChatResponse chatResponse = this.chatClient.call(new Prompt(message, this.chatOptions)); + ChatResponse chatResponse = this.chatConnector.execute(new Prompt(message, this.chatOptions)); var evaluationResponse = chatResponse.getResult().getOutput().getContent(); boolean passing = false; diff --git a/spring-ai-core/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallback.java b/spring-ai-core/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallback.java index f4cdd4ef8..8e092be14 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallback.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallback.java @@ -54,7 +54,7 @@ abstract class AbstractFunctionCallback implements Function, Functio /** * Constructs a new {@link AbstractFunctionCallback} with the given name, description, * input type and default object mapper. - * @param name Function name. Should be unique within the ChatClient's function + * @param name Function name. Should be unique within the ChatConnector's function * registry. * @param description Function description. Used as a "system prompt" by the model to * decide if the function should be called. diff --git a/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallingOptions.java b/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallingOptions.java index 146b35c47..e11c11467 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallingOptions.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallingOptions.java @@ -24,33 +24,33 @@ import java.util.Set; public interface FunctionCallingOptions { /** - * Function Callbacks to be registered with the ChatClient. For Prompt Options the + * Function Callbacks to be registered with the ChatConnector. For Prompt Options the * functionCallbacks are automatically enabled for the duration of the prompt * execution. For Default Options the FunctionCallbacks are registered but disabled by * default. You have to use "functions" property to list the function names from the - * ChatClient registry to be used in the chat completion requests. - * @return Return the Function Callbacks to be registered with the ChatClient. + * ChatConnector registry to be used in the chat completion requests. + * @return Return the Function Callbacks to be registered with the ChatConnector. */ List getFunctionCallbacks(); /** - * Set the Function Callbacks to be registered with the ChatClient. + * Set the Function Callbacks to be registered with the ChatConnector. * @param functionCallbacks the Function Callbacks to be registered with the - * ChatClient. + * ChatConnector. */ void setFunctionCallbacks(List functionCallbacks); /** - * @return List of function names from the ChatClient registry to be used in the next - * chat completion requests. + * @return List of function names from the ChatConnector registry to be used in the + * next chat completion requests. */ Set getFunctions(); /** - * Set the list of function names from the ChatClient registry to be used in the next - * chat completion requests. - * @param functions the list of function names from the ChatClient registry to be used - * in the next chat completion requests. + * Set the list of function names from the ChatConnector registry to be used in the + * next chat completion requests. + * @param functions the list of function names from the ChatConnector registry to be + * used in the next chat completion requests. */ void setFunctions(Set functions); diff --git a/spring-ai-core/src/main/java/org/springframework/ai/transformer/KeywordMetadataEnricher.java b/spring-ai-core/src/main/java/org/springframework/ai/transformer/KeywordMetadataEnricher.java index 67807e419..7b695ca32 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/transformer/KeywordMetadataEnricher.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/transformer/KeywordMetadataEnricher.java @@ -18,7 +18,7 @@ package org.springframework.ai.transformer; import java.util.List; import java.util.Map; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.document.Document; import org.springframework.ai.document.DocumentTransformer; import org.springframework.ai.chat.prompt.Prompt; @@ -43,18 +43,18 @@ public class KeywordMetadataEnricher implements DocumentTransformer { /** * Model predictor */ - private final ChatClient chatClient; + private final ChatConnector chatConnector; /** * The number of keywords to extract. */ private final int keywordCount; - public KeywordMetadataEnricher(ChatClient chatClient, int keywordCount) { - Assert.notNull(chatClient, "ChatClient must not be null"); + public KeywordMetadataEnricher(ChatConnector chatConnector, int keywordCount) { + Assert.notNull(chatConnector, "ChatConnector must not be null"); Assert.isTrue(keywordCount >= 1, "Document count must be >= 1"); - this.chatClient = chatClient; + this.chatConnector = chatConnector; this.keywordCount = keywordCount; } @@ -64,7 +64,7 @@ public class KeywordMetadataEnricher implements DocumentTransformer { var template = new PromptTemplate(String.format(KEYWORDS_TEMPLATE, keywordCount)); Prompt prompt = template.create(Map.of(CONTEXT_STR_PLACEHOLDER, document.getContent())); - String keywords = this.chatClient.call(prompt).getResult().getOutput().getContent(); + String keywords = this.chatConnector.execute(prompt).getResult().getOutput().getContent(); document.getMetadata().putAll(Map.of(EXCERPT_KEYWORDS_METADATA_KEY, keywords)); } return documents; diff --git a/spring-ai-core/src/main/java/org/springframework/ai/transformer/SummaryMetadataEnricher.java b/spring-ai-core/src/main/java/org/springframework/ai/transformer/SummaryMetadataEnricher.java index e882ac497..f50aaf543 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/transformer/SummaryMetadataEnricher.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/transformer/SummaryMetadataEnricher.java @@ -20,7 +20,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.document.Document; import org.springframework.ai.document.DocumentTransformer; import org.springframework.ai.document.MetadataMode; @@ -62,7 +62,7 @@ public class SummaryMetadataEnricher implements DocumentTransformer { /** * AI client. */ - private final ChatClient chatClient; + private final ChatConnector chatConnector; /** * Number of documents from front to use for title extraction. @@ -76,16 +76,16 @@ public class SummaryMetadataEnricher implements DocumentTransformer { */ private final String summaryTemplate; - public SummaryMetadataEnricher(ChatClient chatClient, List summaryTypes) { - this(chatClient, summaryTypes, DEFAULT_SUMMARY_EXTRACT_TEMPLATE, MetadataMode.ALL); + public SummaryMetadataEnricher(ChatConnector chatConnector, List summaryTypes) { + this(chatConnector, summaryTypes, DEFAULT_SUMMARY_EXTRACT_TEMPLATE, MetadataMode.ALL); } - public SummaryMetadataEnricher(ChatClient chatClient, List summaryTypes, String summaryTemplate, + public SummaryMetadataEnricher(ChatConnector chatConnector, List summaryTypes, String summaryTemplate, MetadataMode metadataMode) { - Assert.notNull(chatClient, "ChatClient must not be null"); + Assert.notNull(chatConnector, "ChatConnector must not be null"); Assert.hasText(summaryTemplate, "Summary template must not be empty"); - this.chatClient = chatClient; + this.chatConnector = chatConnector; this.summaryTypes = CollectionUtils.isEmpty(summaryTypes) ? List.of(SummaryType.CURRENT) : summaryTypes; this.metadataMode = metadataMode; this.summaryTemplate = summaryTemplate; @@ -101,7 +101,7 @@ public class SummaryMetadataEnricher implements DocumentTransformer { Prompt prompt = new PromptTemplate(this.summaryTemplate) .create(Map.of(CONTEXT_STR_PLACEHOLDER, documentContext)); - documentSummaries.add(this.chatClient.call(prompt).getResult().getOutput().getContent()); + documentSummaries.add(this.chatConnector.execute(prompt).getResult().getOutput().getContent()); } for (int i = 0; i < documentSummaries.size(); i++) { diff --git a/spring-ai-core/src/test/java/org/springframework/ai/chat/ChatClientTests.java b/spring-ai-core/src/test/java/org/springframework/ai/chat/ChatConnectorTests.java similarity index 84% rename from spring-ai-core/src/test/java/org/springframework/ai/chat/ChatClientTests.java rename to spring-ai-core/src/test/java/org/springframework/ai/chat/ChatConnectorTests.java index 28e4a528c..9083c4c75 100644 --- a/spring-ai-core/src/test/java/org/springframework/ai/chat/ChatClientTests.java +++ b/spring-ai-core/src/test/java/org/springframework/ai/chat/ChatConnectorTests.java @@ -30,16 +30,17 @@ import static org.mockito.Mockito.when; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.prompt.Prompt; /** - * Unit Tests for {@link ChatClient}. + * Unit Tests for {@link ChatConnector}. * * @author John Blum * @since 0.2.0 */ -class ChatClientTests { +class ChatConnectorTests { @Test void generateWithStringCallsGenerateWithPromptAndReturnsResponseCorrectly() { @@ -47,7 +48,7 @@ class ChatClientTests { String userMessage = "Zero Wing"; String responseMessage = "All your bases are belong to us"; - ChatClient mockClient = Mockito.mock(ChatClient.class); + ChatConnector mockClient = Mockito.mock(ChatConnector.class); AssistantMessage mockAssistantMessage = Mockito.mock(AssistantMessage.class); when(mockAssistantMessage.getContent()).thenReturn(responseMessage); @@ -64,7 +65,7 @@ class ChatClientTests { // ChatResponse response = spy(new // ChatResponse(Collections.singletonList(generation))); - doCallRealMethod().when(mockClient).call(anyString()); + doCallRealMethod().when(mockClient).execute(anyString()); doAnswer(invocationOnMock -> { @@ -75,12 +76,12 @@ class ChatClientTests { return response; - }).when(mockClient).call(any(Prompt.class)); + }).when(mockClient).execute(any(Prompt.class)); - assertThat(mockClient.call(userMessage)).isEqualTo(responseMessage); + assertThat(mockClient.execute(userMessage)).isEqualTo(responseMessage); - verify(mockClient, times(1)).call(eq(userMessage)); - verify(mockClient, times(1)).call(isA(Prompt.class)); + verify(mockClient, times(1)).execute(eq(userMessage)); + verify(mockClient, times(1)).execute(isA(Prompt.class)); verify(response, times(1)).getResult(); verify(generation, times(1)).getOutput(); verify(mockAssistantMessage, times(1)).getContent(); diff --git a/spring-ai-core/src/test/java/org/springframework/ai/chat/memory/ChatMemoryTests.java b/spring-ai-core/src/test/java/org/springframework/ai/chat/memory/ChatMemoryTests.java index 741fd5341..557619610 100644 --- a/spring-ai-core/src/test/java/org/springframework/ai/chat/memory/ChatMemoryTests.java +++ b/spring-ai-core/src/test/java/org/springframework/ai/chat/memory/ChatMemoryTests.java @@ -25,7 +25,7 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.StreamingChatClient; @@ -48,7 +48,7 @@ import static org.mockito.Mockito.when; public class ChatMemoryTests { @Mock - ChatClient chatClient; + ChatConnector chatConnector; @Mock StreamingChatClient streamingChatClient; @@ -61,7 +61,7 @@ public class ChatMemoryTests { ChatMemory chatHistory = new InMemoryChatMemory(); - PromptTransformingChatService chatService = PromptTransformingChatService.builder(chatClient) + PromptTransformingChatService chatService = PromptTransformingChatService.builder(chatConnector) .withRetrievers(List.of(ChatMemoryRetriever.builder().withChatHistory(chatHistory).build())) .withContentPostProcessors( List.of(new LastMaxTokenSizeContentTransformer(new JTokkitTokenCountEstimator(), 10))) @@ -77,7 +77,7 @@ public class ChatMemoryTests { ChatMemory chatHistory = new InMemoryChatMemory(); - PromptTransformingChatService chatService = PromptTransformingChatService.builder(chatClient) + PromptTransformingChatService chatService = PromptTransformingChatService.builder(chatConnector) .withRetrievers(List.of(new ChatMemoryRetriever(chatHistory))) .withContentPostProcessors( List.of(new LastMaxTokenSizeContentTransformer(new JTokkitTokenCountEstimator(), 10))) @@ -90,7 +90,7 @@ public class ChatMemoryTests { public void chatClientUserMessages(PromptTransformingChatService chatService, ChatMemory chatHistory) { - when(chatClient.call(promptCaptor.capture())) + when(chatConnector.execute(promptCaptor.capture())) .thenReturn(new ChatResponse(List.of(new Generation("assistant:1")))) .thenReturn(new ChatResponse(List.of(new Generation("assistant:2")))) .thenReturn(new ChatResponse(List.of(new Generation("assistant:3")))); diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/bedrock.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/bedrock.adoc index 3bdb84e10..7b64b7824 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/bedrock.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/bedrock.adoc @@ -2,7 +2,7 @@ link:https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html[Amazon Bedrock] is a managed service that provides foundation models from various AI providers, available through a unified API. -Spring AI supports https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids-arns.html[all the Chat and Embedding AI models] available through Amazon Bedrock by implementing the Spring interfaces `ChatClient`, `StreamingChatClient`, and `EmbeddingClient`. +Spring AI supports https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids-arns.html[all the Chat and Embedding AI models] available through Amazon Bedrock by implementing the Spring interfaces `ChatConnector`, `StreamingChatClient`, and `EmbeddingClient`. Additionally, Spring AI provides Spring Auto-Configurations and Boot Starters for all clients, making it easy to bootstrap and configure for the Bedrock models. diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/anthropic-chat.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/anthropic-chat.adoc index 6bb187048..cb704a43d 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/anthropic-chat.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/anthropic-chat.adoc @@ -132,7 +132,7 @@ TIP: In addition to the model specific https://github.com/spring-projects/spring == Function Calling -You can register custom Java functions with the `AnthropicChatClient` and have the Anthropic Claude model intelligently choose to output a JSON object containing arguments to call one or many of the registered functions. +You can register custom Java functions with the `AnthropicChatConnector` and have the Anthropic Claude model intelligently choose to output a JSON object containing arguments to call one or many of the registered functions. This is a powerful technique to connect the LLM capabilities with external tools and APIs. Read more about xref:api/chat/functions/anthropic-chat-functions.adoc[Anthropic Function Calling]. @@ -194,7 +194,7 @@ spring.ai.anthropic.chat.options.max-tokens=450 TIP: replace the `api-key` with your Anthropic credentials. -This will create a `AnthropicChatClient` implementation that you can inject into your class. +This will create a `AnthropicChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. [source,java] @@ -224,7 +224,7 @@ public class ChatController { == Manual Configuration -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatClient.java[AnthropicChatClient] implements the `ChatClient` and `StreamingChatClient` and uses the <> to connect to the Anthropic service. +The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatClient.java[AnthropicChatClient] implements the `ChatConnector` and `StreamingChatClient` and uses the <> to connect to the Anthropic service. Add the `spring-ai-anthropic` dependency to your project's Maven `pom.xml` file: @@ -247,7 +247,7 @@ dependencies { TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. -Next, create a `AnthropicChatClient` and use it for text generations: +Next, create a `AnthropicChatConnector` and use it for text generations: [source,java] ---- diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/azure-openai-chat.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/azure-openai-chat.adoc index 000d7f4c4..520f86339 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/azure-openai-chat.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/azure-openai-chat.adoc @@ -88,7 +88,7 @@ The prefix `spring.ai.azure.openai` is the property prefix to configure the conn | spring.ai.azure.openai.endpoint | The endpoint from the Azure AI OpenAI `Keys and Endpoint` section under `Resource Management` | - |==== -The prefix `spring.ai.azure.openai.chat` is the property prefix that configures the `ChatClient` implementation for Azure OpenAI. +The prefix `spring.ai.azure.openai.chat` is the property prefix that configures the `ChatConnector` implementation for Azure OpenAI. [cols="3,5,3"] |==== @@ -157,7 +157,7 @@ spring.ai.azure.openai.chat.options.temperature=0.7 TIP: replace the `api-key` and `endpoint` with your Azure OpenAI credentials. -This will create a `AzureOpenAiChatClient` implementation that you can inject into your class. +This will create a `AzureOpenAiChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. @@ -188,7 +188,7 @@ public class ChatController { == Manual Configuration -The link:https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatClient.java[AzureOpenAiChatClient] implements the `ChatClient` and `StreamingChatClient` and uses the link:https://learn.microsoft.com/en-us/java/api/overview/azure/ai-openai-readme?view=azure-java-preview[Azure OpenAI Java Client]. +The link:https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatClient.java[AzureOpenAiChatClient] implements the `ChatConnector` and `StreamingChatClient` and uses the link:https://learn.microsoft.com/en-us/java/api/overview/azure/ai-openai-readme?view=azure-java-preview[Azure OpenAI Java Client]. To enable it, add the `spring-ai-azure-openai` dependency to your project's Maven `pom.xml` file: [source, xml] @@ -210,9 +210,9 @@ dependencies { TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. -TIP: The `spring-ai-azure-openai` dependency also provide the access to the `AzureOpenAiChatClient`. For more information about the `AzureOpenAiChatClient` refer to the link:../chat/azure-openai-chat.html[Azure OpenAI Chat] section. +TIP: The `spring-ai-azure-openai` dependency also provide the access to the `AzureOpenAiChatConnector`. For more information about the `AzureOpenAiChatConnector` refer to the link:../chat/azure-openai-chat.html[Azure OpenAI Chat] section. -Next, create an `AzureOpenAiChatClient` instance and use it to generate text responses: +Next, create an `AzureOpenAiChatConnector` instance and use it to generate text responses: [source,java] ---- diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-anthropic.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-anthropic.adoc index 806b5d9eb..527f56f3c 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-anthropic.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-anthropic.adoc @@ -138,7 +138,7 @@ spring.ai.bedrock.anthropic.chat.options.top-k=15 TIP: replace the `regions`, `access-key` and `secret-key` with your AWS credentials. -This will create a `BedrockAnthropicChatClient` implementation that you can inject into your class. +This will create a `BedrockAnthropicChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. [source,java] @@ -168,7 +168,7 @@ public class ChatController { == Manual Configuration -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatClient.java[BedrockAnthropicChatClient] implements the `ChatClient` and `StreamingChatClient` and uses the <> to connect to the Bedrock Anthropic service. +The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic/BedrockAnthropicChatClient.java[BedrockAnthropicChatClient] implements the `ChatConnector` and `StreamingChatClient` and uses the <> to connect to the Bedrock Anthropic service. Add the `spring-ai-bedrock` dependency to your project's Maven `pom.xml` file: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-anthropic3.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-anthropic3.adoc index af1ac613a..28ab58dfc 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-anthropic3.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-anthropic3.adoc @@ -179,7 +179,7 @@ spring.ai.bedrock.anthropic3.chat.options.top-k=15 TIP: replace the `regions`, `access-key` and `secret-key` with your AWS credentials. -This will create a `BedrockAnthropicChatClient` implementation that you can inject into your class. +This will create a `BedrockAnthropicChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. [source,java] @@ -209,7 +209,7 @@ public class ChatController { == Manual Configuration -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatClient.java[BedrockAnthropic3ChatClient] implements the `ChatClient` and `StreamingChatClient` and uses the <> to connect to the Bedrock Anthropic service. +The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic3/BedrockAnthropic3ChatClient.java[BedrockAnthropic3ChatClient] implements the `ChatConnector` and `StreamingChatClient` and uses the <> to connect to the Bedrock Anthropic service. Add the `spring-ai-bedrock` dependency to your project's Maven `pom.xml` file: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-cohere.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-cohere.adoc index 9f0c53592..62620f848 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-cohere.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-cohere.adoc @@ -130,7 +130,7 @@ spring.ai.bedrock.cohere.chat.options.temperature=0.8 TIP: replace the `regions`, `access-key` and `secret-key` with your AWS credentials. -This will create a `BedrockCohereChatClient` implementation that you can inject into your class. +This will create a `BedrockCohereChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. [source,java] @@ -160,7 +160,7 @@ public class ChatController { == Manual Configuration -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatClient.java[BedrockCohereChatClient] implements the `ChatClient` and `StreamingChatClient` and uses the <> to connect to the Bedrock Cohere service. +The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/cohere/BedrockCohereChatClient.java[BedrockCohereChatClient] implements the `ChatConnector` and `StreamingChatClient` and uses the <> to connect to the Bedrock Cohere service. Add the `spring-ai-bedrock` dependency to your project's Maven `pom.xml` file: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-jurassic2.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-jurassic2.adoc index cf7a083de..3e87d3880 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-jurassic2.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-jurassic2.adoc @@ -123,7 +123,7 @@ spring.ai.bedrock.jurassic2.chat.options.temperature=0.8 TIP: replace the `regions`, `access-key` and `secret-key` with your AWS credentials. -This will create a `BedrockAi21Jurassic2ChatClient` implementation that you can inject into your class. +This will create a `BedrockAi21Jurassic2ChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. [source,java] @@ -148,7 +148,7 @@ public class ChatController { == Manual Configuration -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatClient.java[BedrockAi21Jurassic2ChatClient] implements the `ChatClient` uses the <> to connect to the Bedrock Jurassic-2 service. +The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/jurassic2/BedrockAi21Jurassic2ChatClient.java[BedrockAi21Jurassic2ChatClient] implements the `ChatConnector` uses the <> to connect to the Bedrock Jurassic-2 service. Add the `spring-ai-bedrock` dependency to your project's Maven `pom.xml` file: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-llama.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-llama.adoc index 1d04b2b8f..88328dea3 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-llama.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-llama.adoc @@ -128,7 +128,7 @@ spring.ai.bedrock.llama.chat.options.temperature=0.8 TIP: replace the `regions`, `access-key` and `secret-key` with your AWS credentials. -This will create a `BedrockLlamaChatClient` implementation that you can inject into your class. +This will create a `BedrockLlamaChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. [source,java] @@ -158,7 +158,7 @@ public class ChatController { == Manual Configuration -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatClient.java[BedrockLlamaChatClient] implements the `ChatClient` and `StreamingChatClient` and uses the <> to connect to the Bedrock Anthropic service. +The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/llama/BedrockLlamaChatClient.java[BedrockLlamaChatClient] implements the `ChatConnector` and `StreamingChatClient` and uses the <> to connect to the Bedrock Anthropic service. Add the `spring-ai-bedrock` dependency to your project's Maven `pom.xml` file: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-titan.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-titan.adoc index 7ba332e67..55425e80f 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-titan.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock/bedrock-titan.adoc @@ -126,7 +126,7 @@ spring.ai.bedrock.titan.chat.options.temperature=0.8 TIP: replace the `regions`, `access-key` and `secret-key` with your AWS credentials. -This will create a `BedrockTitanChatClient` implementation that you can inject into your class. +This will create a `BedrockTitanChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. [source,java] @@ -156,7 +156,7 @@ public class ChatController { == Manual Configuration -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanChatClient.java[BedrockTitanChatClient] implements the `ChatClient` and `StreamingChatClient` and uses the <> to connect to the Bedrock Titanic service. +The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanChatClient.java[BedrockTitanChatClient] implements the `ChatConnector` and `StreamingChatClient` and uses the <> to connect to the Bedrock Titanic service. Add the `spring-ai-bedrock` dependency to your project's Maven `pom.xml` file: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/anthropic-chat-functions.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/anthropic-chat-functions.adoc index 3b4d9fcee..20276dace 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/anthropic-chat-functions.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/anthropic-chat-functions.adoc @@ -1,6 +1,6 @@ = Anthropic Function Calling -You can register custom Java functions with the `AnthropicChatClient` and have the Anthropic models intelligently choose to output a JSON object containing arguments to call one or many of the registered functions. +You can register custom Java functions with the `AnthropicChatConnector` and have the Anthropic models intelligently choose to output a JSON object containing arguments to call one or many of the registered functions. This allows you to connect the LLM capabilities with external tools and APIs. The `claude-3-opus`, `claude-3-sonnet` and `claude-3-haiku` link:https://docs.anthropic.com/claude/docs/tool-use#tool-use-best-practices-and-limitations[models are trained to detect when a function should be called] and to respond with JSON that adheres to the function signature. @@ -15,7 +15,7 @@ The `description` helps the model to understand when to call the function. As a developer, you need to implement a function that takes the function call arguments sent from the AI model, and respond with the result back to the model. Your function can in turn invoke other 3rd party services to provide the results. -Spring AI makes this as easy as defining a `@Bean` definition that returns a `java.util.Function` and supplying the bean name as an option when invoking the `ChatClient`. +Spring AI makes this as easy as defining a `@Bean` definition that returns a `java.util.Function` and supplying the bean name as an option when invoking the `ChatConnector`. Under the hood, Spring wraps your POJO (the function) with the appropriate adapter code that enables interaction with the AI Model, saving you from writing tedious boilerplate code. The basis of the underlying infrastructure is the link:https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallback.java[FunctionCallback.java] interface and the companion link:https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java[FunctionCallbackWrapper.java] utility class to simplify the implementation and registration of Java callback functions. @@ -70,7 +70,7 @@ We start with describing the most POJO friendly options. In this approach you define `@Beans` in your application context as you would any other Spring managed object. -Internally, Spring AI `ChatClient` will create an instance of a `FunctionCallbackWrapper` wrapper that adds the logic for it being invoked via the AI model. +Internally, Spring AI `ChatConnector` will create an instance of a `FunctionCallbackWrapper` wrapper that adds the logic for it being invoked via the AI model. The name of the `@Bean` is passed as a `ChatOption`. @@ -136,7 +136,7 @@ static class Config { } ---- -It wraps the 3rd party `MockWeatherService` function and registers it as a `CurrentWeather` function with the `AnthropicChatClient`. +It wraps the 3rd party `MockWeatherService` function and registers it as a `CurrentWeather` function with the `AnthropicChatConnector`. It also provides a description (2) and an optional response converter (3) to convert the response into a text as expected by the model. NOTE: By default, the response converter does a JSON serialization of the Response object. @@ -159,7 +159,7 @@ ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), logger.info("Response: {}", response); ---- -// NOTE: You can can have multiple functions registered in your `ChatClient` but only those enabled in the prompt request will be considered for the function calling. +// NOTE: You can can have multiple functions registered in your `ChatConnector` but only those enabled in the prompt request will be considered for the function calling. Above user question will trigger 3 calls to `CurrentWeather` function (one for each city) and produce the final response. @@ -187,5 +187,5 @@ NOTE: The in-prompt registered functions are enabled by default for the duration This approach allows to dynamically chose different functions to be called based on the user input. -The https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/tool/FunctionCallWithPromptFunctionIT.java[FunctionCallWithPromptFunctionIT.java] integration test provides a complete example of how to register a function with the `AnthropicChatClient` and use it in a prompt request. +The https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/tool/FunctionCallWithPromptFunctionIT.java[FunctionCallWithPromptFunctionIT.java] integration test provides a complete example of how to register a function with the `AnthropicChatConnector` and use it in a prompt request. diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/azure-open-ai-chat-functions.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/azure-open-ai-chat-functions.adoc index 755355a98..9affe61d2 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/azure-open-ai-chat-functions.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/azure-open-ai-chat-functions.adoc @@ -2,7 +2,7 @@ Function calling lets developers create a description of a function in their code, then pass that description to a language model in a request. The response from the model includes the name of a function that matches the description and the arguments to call it with. -You can register custom Java functions with the `AzureOpenAiChatClient` and have the model intelligently choose to output a JSON object containing arguments to call one or many of the registered functions. +You can register custom Java functions with the `AzureOpenAiChatConnector` and have the model intelligently choose to output a JSON object containing arguments to call one or many of the registered functions. This allows you to connect the LLM capabilities with external tools and APIs. The Azure models are trained to detect when a function should be called and to respond with JSON that adheres to the function signature. @@ -16,7 +16,7 @@ In general, the custom functions need to provide a function `name`, `description As a developer, you need to implement a function that takes the function call arguments sent from the AI model, and respond with the result back to the model. Your function can in turn invoke other 3rd party services to provide the results. -Spring AI makes this as easy as defining a `@Bean` definition that returns a `java.util.Function` and supplying the bean name as an option when invoking the `ChatClient`. +Spring AI makes this as easy as defining a `@Bean` definition that returns a `java.util.Function` and supplying the bean name as an option when invoking the `ChatConnector`. Under the hood, Spring wraps your POJO (the function) with the appropriate adapter code that enables interaction with the AI Model, saving you from writing tedious boilerplate code. The basis of the underlying infrastructure is the link:https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallback.java[FunctionCallback.java] interface and the companion link:https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java[FunctionCallbackWrapper.java] utility class to simplify the implementation and registration of Java callback functions. @@ -70,7 +70,7 @@ We start with describing the most POJO friendly options. In this approach you define `@Beans` in your application context as you would any other Spring managed object. -Internally, Spring AI `ChatClient` will create an instance of a `FunctionCallbackWrapper` wrapper that adds the logic for it being invoked via the AI model. +Internally, Spring AI `ChatConnector` will create an instance of a `FunctionCallbackWrapper` wrapper that adds the logic for it being invoked via the AI model. The name of the `@Bean` is passed as a `ChatOption`. @@ -156,7 +156,7 @@ ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), logger.info("Response: {}", response); ---- -// NOTE: You can can have multiple functions registered in your `ChatClient` but only those enabled in the prompt request will be considered for the function calling. +// NOTE: You can can have multiple functions registered in your `ChatConnector` but only those enabled in the prompt request will be considered for the function calling. Above user question will trigger 3 calls to `CurrentWeather` function (one for each city) and the final response will be something like this: @@ -194,5 +194,5 @@ NOTE: The in-prompt registered functions are enabled by default for the duration This approach allows to dynamically chose different functions to be called based on the user input. -The https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithPromptFunctionIT.java[FunctionCallWithPromptFunctionIT.java] integration test provides a complete example of how to register a function with the `AzureOpenAiChatClient` and use it in a prompt request. +The https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithPromptFunctionIT.java[FunctionCallWithPromptFunctionIT.java] integration test provides a complete example of how to register a function with the `AzureOpenAiChatConnector` and use it in a prompt request. diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/mistralai-chat-functions.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/mistralai-chat-functions.adoc index eb1184795..e2d595368 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/mistralai-chat-functions.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/mistralai-chat-functions.adoc @@ -1,6 +1,6 @@ = Mistral AI Function Calling -You can register custom Java functions with the `MistralAiChatClient` and have the Mistral AI models intelligently choose to output a JSON object containing arguments to call one or many of the registered functions. +You can register custom Java functions with the `MistralAiChatConnector` and have the Mistral AI models intelligently choose to output a JSON object containing arguments to call one or many of the registered functions. This allows you to connect the LLM capabilities with external tools and APIs. The `open-mixtral-8x22b`, `mistral_small_latest`, and `mistral_large_latest` models are trained to detect when a function should be called and to respond with JSON that adheres to the function signature. @@ -15,7 +15,7 @@ The `description` helps the model to understand when to call the function. As a developer, you need to implement a function that takes the function call arguments sent from the AI model, and respond with the result back to the model. Your function can in turn invoke other 3rd party services to provide the results. -Spring AI makes this as easy as defining a `@Bean` definition that returns a `java.util.Function` and supplying the bean name as an option when invoking the `ChatClient`. +Spring AI makes this as easy as defining a `@Bean` definition that returns a `java.util.Function` and supplying the bean name as an option when invoking the `ChatConnector`. Under the hood, Spring wraps your POJO (the function) with the appropriate adapter code that enables interaction with the AI Model, saving you from writing tedious boilerplate code. The basis of the underlying infrastructure is the link:https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallback.java[FunctionCallback.java] interface and the companion link:https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java[FunctionCallbackWrapper.java] utility class to simplify the implementation and registration of Java callback functions. @@ -70,7 +70,7 @@ We start with describing the most POJO friendly options. In this approach you define `@Beans` in your application context as you would any other Spring managed object. -Internally, Spring AI `ChatClient` will create an instance of a `FunctionCallbackWrapper` wrapper that adds the logic for it being invoked via the AI model. +Internally, Spring AI `ChatConnector` will create an instance of a `FunctionCallbackWrapper` wrapper that adds the logic for it being invoked via the AI model. The name of the `@Bean` is passed as a `ChatOption`. @@ -139,7 +139,7 @@ static class Config { } ---- -It wraps the 3rd party `MockWeatherService` function and registers it as a `CurrentWeather` function with the `MistralAiChatClient`. +It wraps the 3rd party `MockWeatherService` function and registers it as a `CurrentWeather` function with the `MistralAiChatConnector`. It also provides a description (2) and an optional response converter (3) to convert the response into a text as expected by the model. NOTE: By default, the response converter does a JSON serialization of the Response object. @@ -162,7 +162,7 @@ ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), logger.info("Response: {}", response); ---- -// NOTE: You can can have multiple functions registered in your `ChatClient` but only those enabled in the prompt request will be considered for the function calling. +// NOTE: You can can have multiple functions registered in your `ChatConnector` but only those enabled in the prompt request will be considered for the function calling. Above user question will trigger 3 calls to `CurrentWeather` function (one for each city) and produce the final response. @@ -190,7 +190,7 @@ NOTE: The in-prompt registered functions are enabled by default for the duration This approach allows to dynamically chose different functions to be called based on the user input. -The https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusPromptIT.java[PaymentStatusPromptIT.java] integration test provides a complete example of how to register a function with the `MistralAiChatClient` and use it in a prompt request. +The https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusPromptIT.java[PaymentStatusPromptIT.java] integration test provides a complete example of how to register a function with the `MistralAiChatConnector` and use it in a prompt request. == Appendices diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/openai-chat-functions.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/openai-chat-functions.adoc index 0d85e488c..f10fb8413 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/openai-chat-functions.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/openai-chat-functions.adoc @@ -1,6 +1,6 @@ = Function Calling -You can register custom Java functions with the `OpenAiChatClient` and have the OpenAI model intelligently choose to output a JSON object containing arguments to call one or many of the registered functions. +You can register custom Java functions with the `OpenAiChatConnector` and have the OpenAI model intelligently choose to output a JSON object containing arguments to call one or many of the registered functions. This allows you to connect the LLM capabilities with external tools and APIs. The OpenAI models are trained to detect when a function should be called and to respond with JSON that adheres to the function signature. @@ -11,12 +11,12 @@ In general, the custom functions need to provide a function `name`, `descriptio As a developer, you need to implement a function that takes the function call arguments sent from the AI model, and respond with the result back to the model. Your function can in turn invoke other 3rd party services to provide the results. -Spring AI makes this as easy as defining a `@Bean` definition that returns a `java.util.Function` and supplying the bean name as an option when invoking the `ChatClient`. +Spring AI makes this as easy as defining a `@Bean` definition that returns a `java.util.Function` and supplying the bean name as an option when invoking the `ChatConnector`. Under the hood, Spring wraps your POJO (the function) with the appropriate adapter code that enables interaction with the AI Model, saving you from writing tedious boilerplate code. The basis of the underlying infrastructure is the link:https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallback.java[FunctionCallback.java] interface and the companion link:https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java[FunctionCallbackWrapper.java] utility class to simplify the implementation and registration of Java callback functions. -// Additionally, the Auto-Configuration provides a way to auto-register any Function beans definition as function calling candidates in the `ChatClient`. +// Additionally, the Auto-Configuration provides a way to auto-register any Function beans definition as function calling candidates in the `ChatConnector`. == How it works @@ -71,7 +71,7 @@ We start with describing the most POJO friendly options. In this approach you define `@Beans` in your application context as you would any other Spring managed object. -Internally, Spring AI `ChatClient` will create an instance of a `FunctionCallbackWrapper` wrapper that adds the logic for it being invoked via the AI model. +Internally, Spring AI `ChatConnector` will create an instance of a `FunctionCallbackWrapper` wrapper that adds the logic for it being invoked via the AI model. The name of the `@Bean` is passed as a `ChatOption`. @@ -136,7 +136,7 @@ static class Config { } ---- -It wraps the 3rd party `MockWeatherService` function and registers it as a `CurrentWeather` function with the `OpenAiChatClient`. +It wraps the 3rd party `MockWeatherService` function and registers it as a `CurrentWeather` function with the `OpenAiChatConnector`. It also provides a description (2) and an optional response converter (3) to convert the response into a text as expected by the model. NOTE: By default, the response converter does a JSON serialization of the Response object. @@ -159,7 +159,7 @@ ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), logger.info("Response: {}", response); ---- -// NOTE: You can can have multiple functions registered in your `ChatClient` but only those enabled in the prompt request will be considered for the function calling. +// NOTE: You can can have multiple functions registered in your `ChatConnector` but only those enabled in the prompt request will be considered for the function calling. Above user question will trigger 3 calls to `CurrentWeather` function (one for each city) and the final response will be something like this: @@ -197,11 +197,11 @@ NOTE: The in-prompt registered functions are enabled by default for the duration This approach allows to dynamically chose different functions to be called based on the user input. -The https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackInPromptIT.java[FunctionCallbackInPromptIT.java] integration test provides a complete example of how to register a function with the `OpenAiChatClient` and use it in a prompt request. +The https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackInPromptIT.java[FunctionCallbackInPromptIT.java] integration test provides a complete example of how to register a function with the `OpenAiChatConnector` and use it in a prompt request. // // === Register Functions with Default Options // -// You can programmatically register functions with the `OpenAiChatClient` using the `OpenAiChatOptions#withFunctionCallbacks`: +// You can programmatically register functions with the `OpenAiChatConnector` using the `OpenAiChatOptions#withFunctionCallbacks`: // // [source,java] // ---- @@ -215,7 +215,7 @@ The https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot // new MockWeatherService()))) // function code // .build(); // -// OpenAiChatClient chatClient = new OpenAiChatClient(openaiApi, defaultOptions); +// OpenAiChatConnector chatClient = new OpenAiChatConnector(openaiApi, defaultOptions); // // UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?"); // @@ -223,7 +223,7 @@ The https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot // OpenAiChatOptions.builder().withFunction("CurrentWeather").build())); // Enable the function // ---- // -// NOTE: Functions are registered when OpenAiChatClient is created, by you must enable in the Prompt the functions to be used in the request. +// NOTE: Functions are registered when OpenAiChatConnector is created, by you must enable in the Prompt the functions to be used in the request. == Appendices: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/vertexai-gemini-chat-functions.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/vertexai-gemini-chat-functions.adoc index a464ccf51..7d4b5ba21 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/vertexai-gemini-chat-functions.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/functions/vertexai-gemini-chat-functions.adoc @@ -6,7 +6,7 @@ The parallel function calling is gone as well. Function calling lets developers create a description of a function in their code, then pass that description to a language model in a request. The response from the model includes the name of a function that matches the description and the arguments to call it with. -You can register custom Java functions with the `VertexAiGeminiChatClient` and have the Gemini Pro model intelligently choose to output a JSON object containing arguments to call one or many of the registered functions. +You can register custom Java functions with the `VertexAiGeminiChatConnector` and have the Gemini Pro model intelligently choose to output a JSON object containing arguments to call one or many of the registered functions. This allows you to connect the LLM capabilities with external tools and APIs. The VertexAI Gemini Pro model is trained to detect when a function should be called and to respond with JSON that adheres to the function signature. @@ -18,12 +18,12 @@ In general, the custom functions need to provide a function `name`, `description As a developer, you need to implement a function that takes the function call arguments sent from the AI model, and respond with the result back to the model. Your function can in turn invoke other 3rd party services to provide the results. -Spring AI makes this as easy as defining a `@Bean` definition that returns a `java.util.Function` and supplying the bean name as an option when invoking the `ChatClient`. +Spring AI makes this as easy as defining a `@Bean` definition that returns a `java.util.Function` and supplying the bean name as an option when invoking the `ChatConnector`. Under the hood, Spring wraps your POJO (the function) with the appropriate adapter code that enables interaction with the AI Model, saving you from writing tedious boilerplate code. The basis of the underlying infrastructure is the link:https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallback.java[FunctionCallback.java] interface and the companion link:https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java[FunctionCallbackWrapper.java] utility class to simplify the implementation and registration of Java callback functions. -// Additionally, the Auto-Configuration provides a way to auto-register any Function beans definition as function calling candidates in the `ChatClient`. +// Additionally, the Auto-Configuration provides a way to auto-register any Function beans definition as function calling candidates in the `ChatConnector`. == How it works @@ -74,7 +74,7 @@ We start with describing the most POJO friendly options. In this approach you define `@Beans` in your application context as you would any other Spring managed object. -Internally, Spring AI `ChatClient` will create an instance of a `FunctionCallbackWrapper` wrapper that adds the logic for it being invoked via the AI model. +Internally, Spring AI `ChatConnector` will create an instance of a `FunctionCallbackWrapper` wrapper that adds the logic for it being invoked via the AI model. The name of the `@Bean` is passed as a `ChatOption`. @@ -139,7 +139,7 @@ static class Config { } ---- -It wraps the 3rd party `MockWeatherService` function and registers it as a `CurrentWeather` function with the `VertexAiGeminiChatClient`. +It wraps the 3rd party `MockWeatherService` function and registers it as a `CurrentWeather` function with the `VertexAiGeminiChatConnector`. It also provides a description (2) and sets the Schema type to Open API type (3). NOTE: The default response converter does a JSON serialization of the Response object. @@ -162,7 +162,7 @@ ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), logger.info("Response: {}", response); ---- -// NOTE: You can can have multiple functions registered in your `ChatClient` but only those enabled in the prompt request will be considered for the function calling. +// NOTE: You can can have multiple functions registered in your `ChatConnector` but only those enabled in the prompt request will be considered for the function calling. Above user question will trigger 3 calls to `CurrentWeather` function (one for each city) and the final response will be something like this: @@ -201,5 +201,5 @@ NOTE: The in-prompt registered functions are enabled by default for the duration This approach allows to dynamically chose different functions to be called based on the user input. -The https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/gemini/tool/FunctionCallWithPromptFunctionIT.java[FunctionCallWithPromptFunctionIT.java] integration test provides a complete example of how to register a function with the `VertexAiGeminiChatClient` and use it in a prompt request. +The https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/gemini/tool/FunctionCallWithPromptFunctionIT.java[FunctionCallWithPromptFunctionIT.java] integration test provides a complete example of how to register a function with the `VertexAiGeminiChatConnector` and use it in a prompt request. diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/mistralai-chat.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/mistralai-chat.adoc index a53638d7b..0ebddadd0 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/mistralai-chat.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/mistralai-chat.adoc @@ -103,7 +103,7 @@ The prefix `spring.ai.mistralai.chat` is the property prefix that lets you confi | spring.ai.mistralai.chat.options.functionCallbacks | MistralAI Tool Function Callbacks to register with the ChatClient. | - |==== -NOTE: You can override the common `spring.ai.mistralai.base-url` and `spring.ai.mistralai.api-key` for the `ChatClient` and `EmbeddingClient` implementations. +NOTE: You can override the common `spring.ai.mistralai.base-url` and `spring.ai.mistralai.api-key` for the `ChatConnector` and `EmbeddingClient` implementations. The `spring.ai.mistralai.chat.base-url` and `spring.ai.mistralai.chat.api-key` properties if set take precedence over the common properties. This is useful if you want to use different MistralAI accounts for different models and different model endpoints. @@ -153,7 +153,7 @@ spring.ai.mistralai.chat.options.temperature=0.7 TIP: replace the `api-key` with your OpenAI credentials. -This will create a `MistralAiChatClient` implementation that you can inject into your class. +This will create a `MistralAiChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. [source,java] @@ -183,7 +183,7 @@ public class ChatController { == Manual Configuration -The link:https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatClient.java[MistralAiChatClient] implements the `ChatClient` and `StreamingChatClient` and uses the <> to connect to the MistralAI service. +The link:https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatClient.java[MistralAiChatClient] implements the `ChatConnector` and `StreamingChatClient` and uses the <> to connect to the MistralAI service. Add the `spring-ai-mistral-ai` dependency to your project's Maven `pom.xml` file: @@ -206,7 +206,7 @@ dependencies { TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. -Next, create a `MistralAiChatClient` and use it for text generations: +Next, create a `MistralAiChatConnector` and use it for text generations: [source,java] ---- diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/ollama-chat.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/ollama-chat.adoc index de61f8851..45122b5aa 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/ollama-chat.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/ollama-chat.adoc @@ -1,7 +1,7 @@ = Ollama Chat With https://ollama.ai/[Ollama] you can run various Large Language Models (LLMs) locally and generate text from them. -Spring AI supports the Ollama text generation with `OllamaChatClient`. +Spring AI supports the Ollama text generation with `OllamaChatConnector`. == Prerequisites @@ -185,7 +185,7 @@ spring.ai.ollama.chat.options.temperature=0.7 TIP: replace the `base-url` with your Ollama server URL. -This will create a `OllamaChatClient` implementation that you can inject into your class. +This will create a `OllamaChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. [source,java] @@ -216,8 +216,8 @@ public class ChatController { == Manual Configuration -If you don't want to use the Spring Boot auto-configuration, you can manually configure the `OllamaChatClient` in your application. -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatClient.java[OllamaChatClient] implements the `ChatClient` and `StreamingChatClient` and uses the <> to connect to the Ollama service. +If you don't want to use the Spring Boot auto-configuration, you can manually configure the `OllamaChatConnector` in your application. +The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatClient.java[OllamaChatClient] implements the `ChatConnector` and `StreamingChatClient` and uses the <> to connect to the Ollama service. To use it add the `spring-ai-ollama` dependency to your project's Maven `pom.xml` file: @@ -243,7 +243,7 @@ TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Man TIP: The `spring-ai-ollama` dependency provides access also to the `OllamaEmbeddingClient`. For more information about the `OllamaEmbeddingClient` refer to the link:../embeddings/ollama-embeddings.html[Ollama Embedding Client] section. -Next, create an `OllamaChatClient` instance and use it to text generations requests: +Next, create an `OllamaChatConnector` instance and use it to text generations requests: [source,java] ---- @@ -274,7 +274,7 @@ image::ollama-chat-completion-api.jpg[OllamaApi Chat Completion API Diagram, 800 Here is a simple snippet showing how to use the API programmatically: -NOTE: The `OllamaApi` is low level api and is not recommended for direct use. Use the `OllamaChatClient` instead. +NOTE: The `OllamaApi` is low level api and is not recommended for direct use. Use the `OllamaChatConnector` instead. [source,java] ---- diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/openai-chat.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/openai-chat.adoc index 99fd64634..8b1f2173b 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/openai-chat.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/openai-chat.adoc @@ -107,7 +107,7 @@ The prefix `spring.ai.openai.chat` is the property prefix that lets you configur | spring.ai.openai.chat.options.functions | List of functions, identified by their names, to enable for function calling in a single prompt requests. Functions with those names must exist in the functionCallbacks registry. | - |==== -NOTE: You can override the common `spring.ai.openai.base-url` and `spring.ai.openai.api-key` for the `ChatClient` and `EmbeddingClient` implementations. +NOTE: You can override the common `spring.ai.openai.base-url` and `spring.ai.openai.api-key` for the `ChatConnector` and `EmbeddingClient` implementations. The `spring.ai.openai.chat.base-url` and `spring.ai.openai.chat.api-key` properties if set take precedence over the common properties. This is useful if you want to use different OpenAI accounts for different models and different model endpoints. @@ -209,7 +209,7 @@ spring.ai.openai.chat.options.temperature=0.7 TIP: replace the `api-key` with your OpenAI credentials. -This will create a `OpenAiChatClient` implementation that you can inject into your class. +This will create a `OpenAiChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. [source,java] @@ -239,7 +239,7 @@ public class ChatController { == Manual Configuration -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatClient.java[OpenAiChatClient] implements the `ChatClient` and `StreamingChatClient` and uses the <> to connect to the OpenAI service. +The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatClient.java[OpenAiChatClient] implements the `ChatConnector` and `StreamingChatClient` and uses the <> to connect to the OpenAI service. Add the `spring-ai-openai` dependency to your project's Maven `pom.xml` file: @@ -262,7 +262,7 @@ dependencies { TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. -Next, create a `OpenAiChatClient` and use it for text generations: +Next, create a `OpenAiChatConnector` and use it for text generations: [source,java] ---- diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/vertexai-gemini-chat.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/vertexai-gemini-chat.adoc index 3b4b8944e..9305e87b0 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/vertexai-gemini-chat.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/vertexai-gemini-chat.adoc @@ -150,7 +150,7 @@ spring.ai.vertex.ai.gemini.chat.options.temperature=0.5 TIP: replace the `api-key` with your VertexAI credentials. -This will create a `VertexAiGeminiChatClient` implementation that you can inject into your class. +This will create a `VertexAiGeminiChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. [source,java] @@ -180,7 +180,7 @@ public class ChatController { == Manual Configuration -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatClient.java[VertexAiGeminiChatClient] implements the `ChatClient` and uses the `VertexAI` to connect to the Vertex AI Gemini service. +The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatClient.java[VertexAiGeminiChatClient] implements the `ChatConnector` and uses the `VertexAI` to connect to the Vertex AI Gemini service. Add the `spring-ai-vertex-ai-gemini` dependency to your project's Maven `pom.xml` file: @@ -203,7 +203,7 @@ dependencies { TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. -Next, create a `VertexAiGeminiChatClient` and use it for text generations: +Next, create a `VertexAiGeminiChatConnector` and use it for text generations: [source,java] ---- diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/vertexai-palm2-chat.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/vertexai-palm2-chat.adoc index f67a467f0..74c17fc0e 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/vertexai-palm2-chat.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/vertexai-palm2-chat.adoc @@ -114,7 +114,7 @@ spring.ai.vertex.ai.chat.options.temperature=0.5 TIP: replace the `api-key` with your VertexAI credentials. -This will create a `VertexAiPaLm2ChatClient` implementation that you can inject into your class. +This will create a `VertexAiPaLm2ChatConnector` implementation that you can inject into your class. Here is an example of a simple `@Controller` class that uses the chat client for text generations. [source,java] @@ -144,7 +144,7 @@ public class ChatController { == Manual Configuration -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-openai/src/main/java/org/springframework/ai/vertexai/paml2/VertexAiPaLm2ChatClient.java[VertexAiPaLm2ChatClient] implements the `ChatClient` and uses the <> to connect to the VertexAI service. +The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-openai/src/main/java/org/springframework/ai/vertexai/paml2/VertexAiPaLm2ChatClient.java[VertexAiPaLm2ChatClient] implements the `ChatConnector` and uses the <> to connect to the VertexAI service. Add the `spring-ai-vertex-ai-palm2` dependency to your project's Maven `pom.xml` file: @@ -167,7 +167,7 @@ dependencies { TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. -Next, create a `VertexAiPaLm2ChatClient` and use it for text generations: +Next, create a `VertexAiPaLm2ChatConnector` and use it for text generations: [source,java] ---- diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/watsonx-ai-chat.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/watsonx-ai-chat.adoc index 1cc4445f4..0a58f548c 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/watsonx-ai-chat.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/watsonx-ai-chat.adoc @@ -1,7 +1,7 @@ = watsonx.ai Chat With https://dataplatform.cloud.ibm.com/docs/content/wsj/getting-started/overview-wx.html?context=wx&audience=wdp[watsonx.ai] you can run various Large Language Models (LLMs) locally and generate text from them. -Spring AI supports the watsonx.ai text generation with `WatsonxAiChatClient`. +Spring AI supports the watsonx.ai text generation with `WatsonxAiChatConnector`. == Prerequisites diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chatclient.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chatclient.adoc index 42f7857a5..50410e521 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chatclient.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chatclient.adoc @@ -47,7 +47,7 @@ public interface StreamingChatClient extends StreamingModelClient { == Available Implementations -The `ChatClient` and `StreamingChatClient` implementations are provided for the following Model providers: +The `ChatConnector` and `StreamingChatClient` implementations are provided for the following Model providers: image::spring-ai-chat-completions-clients.jpg[align="center", width="800px"] diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/azure-openai-embeddings.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/azure-openai-embeddings.adoc index 402e6f0c2..f06d51611 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/azure-openai-embeddings.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/azure-openai-embeddings.adoc @@ -155,7 +155,7 @@ dependencies { TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. -NOTE: The `spring-ai-azure-openai` dependency also provide the access to the `AzureOpenAiEmbeddingClient`. For more information about the `AzureOpenAiChatClient` refer to the link:../embeddings/azure-openai-embeddings.html[Azure OpenAI Embeddings] section. +NOTE: The `spring-ai-azure-openai` dependency also provide the access to the `AzureOpenAiEmbeddingClient`. For more information about the `AzureOpenAiChatConnector` refer to the link:../embeddings/azure-openai-embeddings.html[Azure OpenAI Embeddings] section. Next, create an `AzureOpenAiEmbeddingClient` instance and use it to compute the similarity between two input texts: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/mistralai-embeddings.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/mistralai-embeddings.adoc index 57d8c19db..632afa3b6 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/mistralai-embeddings.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/mistralai-embeddings.adoc @@ -94,7 +94,7 @@ The prefix `spring.ai.mistralai.embedding` is property prefix that configures th | spring.ai.mistralai.embedding.options.encodingFormat | The format to return the embeddings in. Can be either float or base64. | - |==== -NOTE: You can override the common `spring.ai.mistralai.base-url` and `spring.ai.mistralai.api-key` for the `ChatClient` and `EmbeddingClient` implementations. +NOTE: You can override the common `spring.ai.mistralai.base-url` and `spring.ai.mistralai.api-key` for the `ChatConnector` and `EmbeddingClient` implementations. The `spring.ai.mistralai.embedding.base-url` and `spring.ai.mistralai.embedding.api-key` properties if set take precedence over the common properties. Similarly, the `spring.ai.mistralai.embedding.base-url` and `spring.ai.mistralai.embedding.api-key` properties if set take precedence over the common properties. This is useful if you want to use different MistralAI accounts for different models and different model endpoints. @@ -175,8 +175,8 @@ dependencies { TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. -NOTE: The `spring-ai-mistral-ai` dependency provides access also to the `MistralAiChatClient`. -For more information about the `MistralAiChatClient` refer to the link:../chat/mistralai-chat.html[MistralAI Chat Client] section. +NOTE: The `spring-ai-mistral-ai` dependency provides access also to the `MistralAiChatConnector`. +For more information about the `MistralAiChatConnector` refer to the link:../chat/mistralai-chat.html[MistralAI Chat Client] section. Next, create an `MistralAiEmbeddingClient` instance and use it to compute the similarity between two input texts: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/ollama-embeddings.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/ollama-embeddings.adoc index 386051e71..2869bec36 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/ollama-embeddings.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/ollama-embeddings.adoc @@ -177,8 +177,8 @@ dependencies { TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. -NOTE: The `spring-ai-ollama` dependency provides access also to the `OllamaChatClient`. -For more information about the `OllamaChatClient` refer to the link:../chat/ollama-chat.html[Ollama Chat Client] section. +NOTE: The `spring-ai-ollama` dependency provides access also to the `OllamaChatConnector`. +For more information about the `OllamaChatConnector` refer to the link:../chat/ollama-chat.html[Ollama Chat Client] section. Next, create an `OllamaEmbeddingClient` instance and use it to compute the similarity between two input texts: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/openai-embeddings.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/openai-embeddings.adoc index 75a0d45f3..224278599 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/openai-embeddings.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/openai-embeddings.adoc @@ -97,7 +97,7 @@ The prefix `spring.ai.openai.embedding` is property prefix that configures the ` | spring.ai.openai.embedding.options.dimensions | The number of dimensions the resulting output embeddings should have. Only supported in `text-embedding-3` and later models. | - |==== -NOTE: You can override the common `spring.ai.openai.base-url` and `spring.ai.openai.api-key` for the `ChatClient` and `EmbeddingClient` implementations. +NOTE: You can override the common `spring.ai.openai.base-url` and `spring.ai.openai.api-key` for the `ChatConnector` and `EmbeddingClient` implementations. The `spring.ai.openai.embedding.base-url` and `spring.ai.openai.embedding.api-key` properties if set take precedence over the common properties. Similarly, the `spring.ai.openai.embedding.base-url` and `spring.ai.openai.embedding.api-key` properties if set take precedence over the common properties. This is useful if you want to use different OpenAI accounts for different models and different model endpoints. @@ -178,8 +178,8 @@ dependencies { TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. -NOTE: The `spring-ai-openai` dependency provides access also to the `OpenAiChatClient`. -For more information about the `OpenAiChatClient` refer to the link:../chat/openai-chat.html[OpenAI Chat Client] section. +NOTE: The `spring-ai-openai` dependency provides access also to the `OpenAiChatConnector`. +For more information about the `OpenAiChatConnector` refer to the link:../chat/openai-chat.html[OpenAI Chat Client] section. Next, create an `OpenAiEmbeddingClient` instance and use it to compute the similarity between two input texts: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/prompt.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/prompt.adoc index 96fab52f4..2de582f26 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/prompt.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/prompt.adoc @@ -11,7 +11,7 @@ Another analogy is a SQL statement that contain placeholders for certain express As Spring AI evolves, it will introduce higher levels of abstraction for interacting with AI models. The foundational classes described in this section can be likened to JDBC in terms of their role and functionality. -The `ChatClient` class, for instance, is analogous to the core JDBC library in the JDK. +The `ChatConnector` class, for instance, is analogous to the core JDBC library in the JDK. Building upon this, Spring AI can provide helper classes similar to `JdbcTemplate`, Spring Data Repositories, and eventually, more advanced constructs like ChatEngines and Agents that consider past interactions with the model. The structure of prompts has evolved over time within the AI field. @@ -24,7 +24,7 @@ OpenAI have introduced even more structure to prompts by categorizing multiple m === Prompt -It is common to use the `call` method of `ChatClient` that takes a `Prompt` instance and returns an `ChatResponse`. +It is common to use the `call` method of `ChatConnector` that takes a `Prompt` instance and returns an `ChatResponse`. The Prompt class functions as a container for an organized series of Message objects, with each one forming a segment of the overall prompt. Every Message embodies a unique role within the prompt, differing in its content and intent. diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/hana.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/hana.adoc index 182356e7c..5cf74ae93 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/hana.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/hana.adoc @@ -226,7 +226,7 @@ public class CricketWorldCupRepository implements HanaVectorRepositoryimage `ImageClient` implementations. Then `StabilityAiImageOptions` and `OpenAiImageOptions` provide the options specific to each model provider. All options classes are created via a fluent API builder all can be passed into the portable `ImageClient` API. These option data types are using in autoconfiguration/configuration properties for the `ImageClient` implementations. +* A new "portable options" design pattern. We wanted to provide as much portability in the `ChatConnector` as possible across different chat based AI Models. There is a common set of generation options and then those that are specific to a model provider. A sort of "duck typing" approach is used. `ModelOptions` in the model package is a marker interface indicating implementations of this class will provide the options for a model. See `ImageOptions`, a subinterface that defines portable options across all text->image `ImageClient` implementations. Then `StabilityAiImageOptions` and `OpenAiImageOptions` provide the options specific to each model provider. All options classes are created via a fluent API builder all can be passed into the portable `ImageClient` API. These option data types are using in autoconfiguration/configuration properties for the `ImageClient` implementations. === January 13, 2024 Update @@ -79,7 +79,7 @@ Merge SimplePersistentVectorStore and InMemoryVectorStore into SimpleVectorStore Refactor the Ollama client and related classes and package names -* Replace the org.springframework.ai.ollama.client.OllamaClient by org.springframework.ai.ollama.OllamaChatClient. +* Replace the org.springframework.ai.ollama.client.OllamaClient by org.springframework.ai.ollama.OllamaChatConnector. * The OllamaChatClient method signatures have changed. * Rename the org.springframework.ai.autoconfigure.ollama.OllamaProperties into org.springframework.ai.autoconfigure.ollama.OllamaChatProperties and change the suffix to: `spring.ai.ollama.chat`. Some of the properties have changed as well. diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfiguration.java index e94598a8d..5d1a6d0d1 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfiguration.java @@ -17,7 +17,7 @@ package org.springframework.ai.autoconfigure.anthropic; import java.util.List; -import org.springframework.ai.anthropic.AnthropicChatClient; +import org.springframework.ai.anthropic.AnthropicChatConnector; import org.springframework.ai.anthropic.api.AnthropicApi; import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration; import org.springframework.ai.model.function.FunctionCallback; @@ -57,7 +57,7 @@ public class AnthropicAutoConfiguration { @Bean @ConditionalOnMissingBean - public AnthropicChatClient anthropicChatClient(AnthropicApi anthropicApi, AnthropicChatProperties chatProperties, + public AnthropicChatConnector anthropicChatClient(AnthropicApi anthropicApi, AnthropicChatProperties chatProperties, RetryTemplate retryTemplate, FunctionCallbackContext functionCallbackContext, List toolFunctionCallbacks) { @@ -65,7 +65,7 @@ public class AnthropicAutoConfiguration { chatProperties.getOptions().getFunctionCallbacks().addAll(toolFunctionCallbacks); } - return new AnthropicChatClient(anthropicApi, chatProperties.getOptions(), retryTemplate, + return new AnthropicChatConnector(anthropicApi, chatProperties.getOptions(), retryTemplate, functionCallbackContext); } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicChatProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicChatProperties.java index d9cdc0565..17b9ea93f 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicChatProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicChatProperties.java @@ -15,7 +15,7 @@ */ package org.springframework.ai.autoconfigure.anthropic; -import org.springframework.ai.anthropic.AnthropicChatClient; +import org.springframework.ai.anthropic.AnthropicChatConnector; import org.springframework.ai.anthropic.AnthropicChatOptions; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; @@ -43,9 +43,9 @@ public class AnthropicChatProperties { */ @NestedConfigurationProperty private AnthropicChatOptions options = AnthropicChatOptions.builder() - .withModel(AnthropicChatClient.DEFAULT_MODEL_NAME) - .withMaxTokens(AnthropicChatClient.DEFAULT_MAX_TOKENS) - .withTemperature(AnthropicChatClient.DEFAULT_TEMPERATURE) + .withModel(AnthropicChatConnector.DEFAULT_MODEL_NAME) + .withMaxTokens(AnthropicChatConnector.DEFAULT_MAX_TOKENS) + .withTemperature(AnthropicChatConnector.DEFAULT_TEMPERATURE) .build(); public AnthropicChatOptions getOptions() { diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/azure/openai/AzureOpenAiAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/azure/openai/AzureOpenAiAutoConfiguration.java index a9b13e304..f994191c1 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/azure/openai/AzureOpenAiAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/azure/openai/AzureOpenAiAutoConfiguration.java @@ -22,7 +22,7 @@ import com.azure.ai.openai.OpenAIClientBuilder; import com.azure.core.credential.AzureKeyCredential; import com.azure.core.util.ClientOptions; -import org.springframework.ai.azure.openai.AzureOpenAiChatClient; +import org.springframework.ai.azure.openai.AzureOpenAiChatConnector; import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingClient; import org.springframework.ai.model.function.FunctionCallback; import org.springframework.ai.model.function.FunctionCallbackContext; @@ -37,7 +37,7 @@ import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; @AutoConfiguration -@ConditionalOnClass({ OpenAIClientBuilder.class, AzureOpenAiChatClient.class }) +@ConditionalOnClass({ OpenAIClientBuilder.class, AzureOpenAiChatConnector.class }) @EnableConfigurationProperties({ AzureOpenAiChatProperties.class, AzureOpenAiEmbeddingProperties.class, AzureOpenAiConnectionProperties.class }) public class AzureOpenAiAutoConfiguration { @@ -58,7 +58,7 @@ public class AzureOpenAiAutoConfiguration { @Bean @ConditionalOnProperty(prefix = AzureOpenAiChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true) - public AzureOpenAiChatClient azureOpenAiChatClient(OpenAIClient openAIClient, + public AzureOpenAiChatConnector azureOpenAiChatClient(OpenAIClient openAIClient, AzureOpenAiChatProperties chatProperties, List toolFunctionCallbacks, FunctionCallbackContext functionCallbackContext) { @@ -66,7 +66,7 @@ public class AzureOpenAiAutoConfiguration { chatProperties.getOptions().getFunctionCallbacks().addAll(toolFunctionCallbacks); } - AzureOpenAiChatClient azureOpenAiChatClient = new AzureOpenAiChatClient(openAIClient, + AzureOpenAiChatConnector azureOpenAiChatClient = new AzureOpenAiChatConnector(openAIClient, chatProperties.getOptions(), functionCallbackContext); return azureOpenAiChatClient; diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/anthropic/BedrockAnthropicChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/anthropic/BedrockAnthropicChatAutoConfiguration.java index 7b3d4d2d5..54cfbbd21 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/anthropic/BedrockAnthropicChatAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/anthropic/BedrockAnthropicChatAutoConfiguration.java @@ -18,7 +18,7 @@ package org.springframework.ai.autoconfigure.bedrock.anthropic; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; -import org.springframework.ai.bedrock.anthropic.BedrockAnthropicChatClient; +import org.springframework.ai.bedrock.anthropic.BedrockAnthropicChatConnector; import org.springframework.ai.bedrock.anthropic.api.AnthropicChatBedrockApi; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -59,9 +59,9 @@ public class BedrockAnthropicChatAutoConfiguration { @Bean @ConditionalOnBean(AnthropicChatBedrockApi.class) - public BedrockAnthropicChatClient anthropicChatClient(AnthropicChatBedrockApi anthropicApi, + public BedrockAnthropicChatConnector anthropicChatClient(AnthropicChatBedrockApi anthropicApi, BedrockAnthropicChatProperties properties) { - return new BedrockAnthropicChatClient(anthropicApi, properties.getOptions()); + return new BedrockAnthropicChatConnector(anthropicApi, properties.getOptions()); } } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/anthropic3/BedrockAnthropic3ChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/anthropic3/BedrockAnthropic3ChatAutoConfiguration.java index 60e5cdce6..70d985107 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/anthropic3/BedrockAnthropic3ChatAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/anthropic3/BedrockAnthropic3ChatAutoConfiguration.java @@ -18,7 +18,7 @@ package org.springframework.ai.autoconfigure.bedrock.anthropic3; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; -import org.springframework.ai.bedrock.anthropic3.BedrockAnthropic3ChatClient; +import org.springframework.ai.bedrock.anthropic3.BedrockAnthropic3ChatConnector; import org.springframework.ai.bedrock.anthropic3.api.Anthropic3ChatBedrockApi; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -59,9 +59,9 @@ public class BedrockAnthropic3ChatAutoConfiguration { @Bean @ConditionalOnBean(Anthropic3ChatBedrockApi.class) - public BedrockAnthropic3ChatClient anthropic3ChatClient(Anthropic3ChatBedrockApi anthropicApi, + public BedrockAnthropic3ChatConnector anthropic3ChatClient(Anthropic3ChatBedrockApi anthropicApi, BedrockAnthropic3ChatProperties properties) { - return new BedrockAnthropic3ChatClient(anthropicApi, properties.getOptions()); + return new BedrockAnthropic3ChatConnector(anthropicApi, properties.getOptions()); } } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereChatAutoConfiguration.java index 66b6d5e5e..b9d392c68 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereChatAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereChatAutoConfiguration.java @@ -18,7 +18,7 @@ package org.springframework.ai.autoconfigure.bedrock.cohere; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; -import org.springframework.ai.bedrock.cohere.BedrockCohereChatClient; +import org.springframework.ai.bedrock.cohere.BedrockCohereChatConnector; import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -57,10 +57,10 @@ public class BedrockCohereChatAutoConfiguration { @Bean @ConditionalOnBean(CohereChatBedrockApi.class) - public BedrockCohereChatClient cohereChatClient(CohereChatBedrockApi cohereChatApi, + public BedrockCohereChatConnector cohereChatClient(CohereChatBedrockApi cohereChatApi, BedrockCohereChatProperties properties) { - return new BedrockCohereChatClient(cohereChatApi, properties.getOptions()); + return new BedrockCohereChatConnector(cohereChatApi, properties.getOptions()); } } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/jurrasic2/BedrockAi21Jurassic2ChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/jurrasic2/BedrockAi21Jurassic2ChatAutoConfiguration.java index e8266a0e4..93acbafee 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/jurrasic2/BedrockAi21Jurassic2ChatAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/jurrasic2/BedrockAi21Jurassic2ChatAutoConfiguration.java @@ -19,7 +19,7 @@ package org.springframework.ai.autoconfigure.bedrock.jurrasic2; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; -import org.springframework.ai.bedrock.jurassic2.BedrockAi21Jurassic2ChatClient; +import org.springframework.ai.bedrock.jurassic2.BedrockAi21Jurassic2ChatConnector; import org.springframework.ai.bedrock.jurassic2.api.Ai21Jurassic2ChatBedrockApi; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -59,10 +59,10 @@ public class BedrockAi21Jurassic2ChatAutoConfiguration { @Bean @ConditionalOnBean(Ai21Jurassic2ChatBedrockApi.class) - public BedrockAi21Jurassic2ChatClient jurassic2ChatClient(Ai21Jurassic2ChatBedrockApi ai21Jurassic2ChatBedrockApi, - BedrockAi21Jurassic2ChatProperties properties) { + public BedrockAi21Jurassic2ChatConnector jurassic2ChatClient( + Ai21Jurassic2ChatBedrockApi ai21Jurassic2ChatBedrockApi, BedrockAi21Jurassic2ChatProperties properties) { - return BedrockAi21Jurassic2ChatClient.builder(ai21Jurassic2ChatBedrockApi) + return BedrockAi21Jurassic2ChatConnector.builder(ai21Jurassic2ChatBedrockApi) .withOptions(properties.getOptions()) .build(); } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/llama/BedrockLlamaChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/llama/BedrockLlamaChatAutoConfiguration.java index 9293acc84..aa13ec0de 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/llama/BedrockLlamaChatAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/llama/BedrockLlamaChatAutoConfiguration.java @@ -16,12 +16,12 @@ package org.springframework.ai.autoconfigure.bedrock.llama; import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.ai.bedrock.llama.BedrockLlamaChatConnector; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.regions.providers.AwsRegionProvider; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; -import org.springframework.ai.bedrock.llama.BedrockLlamaChatClient; import org.springframework.ai.bedrock.llama.api.LlamaChatBedrockApi; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -59,9 +59,10 @@ public class BedrockLlamaChatAutoConfiguration { @Bean @ConditionalOnBean(LlamaChatBedrockApi.class) - public BedrockLlamaChatClient llamaChatClient(LlamaChatBedrockApi llamaApi, BedrockLlamaChatProperties properties) { + public BedrockLlamaChatConnector llamaChatClient(LlamaChatBedrockApi llamaApi, + BedrockLlamaChatProperties properties) { - return new BedrockLlamaChatClient(llamaApi, properties.getOptions()); + return new BedrockLlamaChatConnector(llamaApi, properties.getOptions()); } } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfiguration.java index 67995b9e3..3fdd4b8d1 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfiguration.java @@ -18,7 +18,7 @@ package org.springframework.ai.autoconfigure.bedrock.titan; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; -import org.springframework.ai.bedrock.titan.BedrockTitanChatClient; +import org.springframework.ai.bedrock.titan.BedrockTitanChatConnector; import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -57,10 +57,10 @@ public class BedrockTitanChatAutoConfiguration { @Bean @ConditionalOnBean(TitanChatBedrockApi.class) - public BedrockTitanChatClient titanChatClient(TitanChatBedrockApi titanChatApi, + public BedrockTitanChatConnector titanChatClient(TitanChatBedrockApi titanChatApi, BedrockTitanChatProperties properties) { - return new BedrockTitanChatClient(titanChatApi, properties.getOptions()); + return new BedrockTitanChatConnector(titanChatApi, properties.getOptions()); } } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/huggingface/HuggingfaceChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/huggingface/HuggingfaceChatAutoConfiguration.java index 42c3b1e73..6bda83dfd 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/huggingface/HuggingfaceChatAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/huggingface/HuggingfaceChatAutoConfiguration.java @@ -15,7 +15,7 @@ */ package org.springframework.ai.autoconfigure.huggingface; -import org.springframework.ai.huggingface.HuggingfaceChatClient; +import org.springframework.ai.huggingface.HuggingfaceChatConnector; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -24,7 +24,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean; @AutoConfiguration -@ConditionalOnClass(HuggingfaceChatClient.class) +@ConditionalOnClass(HuggingfaceChatConnector.class) @EnableConfigurationProperties(HuggingfaceChatProperties.class) public class HuggingfaceChatAutoConfiguration { @@ -32,8 +32,8 @@ public class HuggingfaceChatAutoConfiguration { @ConditionalOnMissingBean @ConditionalOnProperty(prefix = HuggingfaceChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true) - public HuggingfaceChatClient huggingfaceChatClient(HuggingfaceChatProperties huggingfaceChatProperties) { - return new HuggingfaceChatClient(huggingfaceChatProperties.getApiKey(), huggingfaceChatProperties.getUrl()); + public HuggingfaceChatConnector huggingfaceChatClient(HuggingfaceChatProperties huggingfaceChatProperties) { + return new HuggingfaceChatConnector(huggingfaceChatProperties.getApiKey(), huggingfaceChatProperties.getUrl()); } } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/mistralai/MistralAiAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/mistralai/MistralAiAutoConfiguration.java index 1328f3488..a6480ec50 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/mistralai/MistralAiAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/mistralai/MistralAiAutoConfiguration.java @@ -18,7 +18,7 @@ package org.springframework.ai.autoconfigure.mistralai; import java.util.List; import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration; -import org.springframework.ai.mistralai.MistralAiChatClient; +import org.springframework.ai.mistralai.MistralAiChatConnector; import org.springframework.ai.mistralai.MistralAiEmbeddingClient; import org.springframework.ai.mistralai.api.MistralAiApi; import org.springframework.ai.model.function.FunctionCallback; @@ -69,7 +69,7 @@ public class MistralAiAutoConfiguration { @ConditionalOnMissingBean @ConditionalOnProperty(prefix = MistralAiChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true) - public MistralAiChatClient mistralAiChatClient(MistralAiCommonProperties commonProperties, + public MistralAiChatConnector mistralAiChatClient(MistralAiCommonProperties commonProperties, MistralAiChatProperties chatProperties, RestClient.Builder restClientBuilder, List toolFunctionCallbacks, FunctionCallbackContext functionCallbackContext, RetryTemplate retryTemplate, ResponseErrorHandler responseErrorHandler) { @@ -81,7 +81,7 @@ public class MistralAiAutoConfiguration { chatProperties.getOptions().getFunctionCallbacks().addAll(toolFunctionCallbacks); } - return new MistralAiChatClient(mistralAiApi, chatProperties.getOptions(), functionCallbackContext, + return new MistralAiChatConnector(mistralAiApi, chatProperties.getOptions(), functionCallbackContext, retryTemplate); } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java index 8b788e73b..776e52c7b 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java @@ -15,7 +15,7 @@ */ package org.springframework.ai.autoconfigure.ollama; -import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.ai.ollama.OllamaChatConnector; import org.springframework.ai.ollama.OllamaEmbeddingClient; import org.springframework.ai.ollama.api.OllamaApi; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -56,8 +56,8 @@ public class OllamaAutoConfiguration { @ConditionalOnMissingBean @ConditionalOnProperty(prefix = OllamaChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true) - public OllamaChatClient ollamaChatClient(OllamaApi ollamaApi, OllamaChatProperties properties) { - return new OllamaChatClient(ollamaApi, properties.getOptions()); + public OllamaChatConnector ollamaChatClient(OllamaApi ollamaApi, OllamaChatProperties properties) { + return new OllamaChatConnector(ollamaApi, properties.getOptions()); } @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java index 848456468..644f182bc 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java @@ -20,11 +20,8 @@ import java.util.List; import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration; import org.springframework.ai.model.function.FunctionCallback; import org.springframework.ai.model.function.FunctionCallbackContext; -import org.springframework.ai.openai.OpenAiAudioTranscriptionClient; -import org.springframework.ai.openai.OpenAiChatClient; -import org.springframework.ai.openai.OpenAiEmbeddingClient; -import org.springframework.ai.openai.OpenAiImageClient; -import org.springframework.ai.openai.OpenAiAudioSpeechClient; +import org.springframework.ai.openai.*; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.openai.api.OpenAiAudioApi; import org.springframework.ai.openai.api.OpenAiImageApi; @@ -57,7 +54,7 @@ public class OpenAiAutoConfiguration { @ConditionalOnMissingBean @ConditionalOnProperty(prefix = OpenAiChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true) - public OpenAiChatClient openAiChatClient(OpenAiConnectionProperties commonProperties, + public OpenAiChatConnector openAiChatClient(OpenAiConnectionProperties commonProperties, OpenAiChatProperties chatProperties, RestClient.Builder restClientBuilder, List toolFunctionCallbacks, FunctionCallbackContext functionCallbackContext, RetryTemplate retryTemplate, ResponseErrorHandler responseErrorHandler) { @@ -69,7 +66,7 @@ public class OpenAiAutoConfiguration { chatProperties.getOptions().getFunctionCallbacks().addAll(toolFunctionCallbacks); } - return new OpenAiChatClient(openAiApi, chatProperties.getOptions(), functionCallbackContext, retryTemplate); + return new OpenAiChatConnector(openAiApi, chatProperties.getOptions(), functionCallbackContext, retryTemplate); } @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiAutoConfiguration.java index 12dfb8134..0ac36e124 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiAutoConfiguration.java @@ -24,7 +24,7 @@ import com.google.cloud.vertexai.VertexAI; import org.springframework.ai.model.function.FunctionCallback; import org.springframework.ai.model.function.FunctionCallbackContext; import org.springframework.ai.model.function.FunctionCallbackWrapper.Builder.SchemaType; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatConnector; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -40,7 +40,7 @@ import org.springframework.util.StringUtils; * @author Christian Tzolov * @since 0.8.0 */ -@ConditionalOnClass({ VertexAI.class, VertexAiGeminiChatClient.class }) +@ConditionalOnClass({ VertexAI.class, VertexAiGeminiChatConnector.class }) @EnableConfigurationProperties({ VertexAiGeminiChatProperties.class, VertexAiGeminiConnectionProperties.class }) public class VertexAiGeminiAutoConfiguration { @@ -74,8 +74,9 @@ public class VertexAiGeminiAutoConfiguration { @Bean @ConditionalOnMissingBean - public VertexAiGeminiChatClient vertexAiGeminiChat(VertexAI vertexAi, VertexAiGeminiChatProperties chatProperties, - List toolFunctionCallbacks, ApplicationContext context) { + public VertexAiGeminiChatConnector vertexAiGeminiChat(VertexAI vertexAi, + VertexAiGeminiChatProperties chatProperties, List toolFunctionCallbacks, + ApplicationContext context) { FunctionCallbackContext functionCallbackContext = springAiFunctionManager(context); @@ -83,7 +84,7 @@ public class VertexAiGeminiAutoConfiguration { chatProperties.getOptions().getFunctionCallbacks().addAll(toolFunctionCallbacks); } - return new VertexAiGeminiChatClient(vertexAi, chatProperties.getOptions(), functionCallbackContext); + return new VertexAiGeminiChatConnector(vertexAi, chatProperties.getOptions(), functionCallbackContext); } /** diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiChatProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiChatProperties.java index 866f4f352..6825039a1 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiChatProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiChatProperties.java @@ -15,7 +15,7 @@ */ package org.springframework.ai.autoconfigure.vertexai.gemini; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatConnector; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -30,7 +30,7 @@ public class VertexAiGeminiChatProperties { public static final String CONFIG_PREFIX = "spring.ai.vertex.ai.gemini.chat"; - public static final String DEFAULT_MODEL = VertexAiGeminiChatClient.ChatModel.GEMINI_PRO_VISION.getValue(); + public static final String DEFAULT_MODEL = VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO_VISION.getValue(); /** * Vertex AI Gemini API generative options. diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2AutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2AutoConfiguration.java index c1ac9fa75..6005087b9 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2AutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2AutoConfiguration.java @@ -15,7 +15,7 @@ */ package org.springframework.ai.autoconfigure.vertexai.palm2; -import org.springframework.ai.vertexai.palm2.VertexAiPaLm2ChatClient; +import org.springframework.ai.vertexai.palm2.VertexAiPaLm2ChatConnector; import org.springframework.ai.vertexai.palm2.VertexAiPaLm2EmbeddingClient; import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -47,9 +47,9 @@ public class VertexAiPalm2AutoConfiguration { @ConditionalOnMissingBean @ConditionalOnProperty(prefix = VertexAiPlam2ChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true) - public VertexAiPaLm2ChatClient vertexAiChatClient(VertexAiPaLm2Api vertexAiApi, + public VertexAiPaLm2ChatConnector vertexAiChatClient(VertexAiPaLm2Api vertexAiApi, VertexAiPlam2ChatProperties chatProperties) { - return new VertexAiPaLm2ChatClient(vertexAiApi, chatProperties.getOptions()); + return new VertexAiPaLm2ChatConnector(vertexAiApi, chatProperties.getOptions()); } @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/watsonxai/WatsonxAiAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/watsonxai/WatsonxAiAutoConfiguration.java index ce651ee17..7ab0ea0ad 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/watsonxai/WatsonxAiAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/watsonxai/WatsonxAiAutoConfiguration.java @@ -15,7 +15,7 @@ */ package org.springframework.ai.autoconfigure.watsonxai; -import org.springframework.ai.watsonx.WatsonxAiChatClient; +import org.springframework.ai.watsonx.WatsonxAiChatConnector; import org.springframework.ai.watsonx.api.WatsonxAiApi; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -50,8 +50,8 @@ public class WatsonxAiAutoConfiguration { @Bean @ConditionalOnMissingBean - public WatsonxAiChatClient watsonxChatClient(WatsonxAiApi watsonxApi, WatsonxAiChatProperties chatProperties) { - return new WatsonxAiChatClient(watsonxApi, chatProperties.getOptions()); + public WatsonxAiChatConnector watsonxChatClient(WatsonxAiApi watsonxApi, WatsonxAiChatProperties chatProperties) { + return new WatsonxAiChatConnector(watsonxApi, chatProperties.getOptions()); } } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfigurationIT.java index 69e33a304..c0f51dd41 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfigurationIT.java @@ -22,9 +22,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.springframework.ai.anthropic.AnthropicChatConnector; import reactor.core.publisher.Flux; -import org.springframework.ai.anthropic.AnthropicChatClient; import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; @@ -50,8 +50,8 @@ public class AnthropicAutoConfigurationIT { @Test void generate() { contextRunner.run(context -> { - AnthropicChatClient chatClient = context.getBean(AnthropicChatClient.class); - String response = chatClient.call("Hello"); + AnthropicChatConnector chatClient = context.getBean(AnthropicChatConnector.class); + String response = chatClient.execute("Hello"); assertThat(response).isNotEmpty(); logger.info("Response: " + response); }); @@ -60,7 +60,7 @@ public class AnthropicAutoConfigurationIT { @Test void generateStreaming() { contextRunner.run(context -> { - AnthropicChatClient chatClient = context.getBean(AnthropicChatClient.class); + AnthropicChatConnector chatClient = context.getBean(AnthropicChatConnector.class); Flux responseFlux = chatClient.stream(new Prompt(new UserMessage("Hello"))); String response = responseFlux.collectList() diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicPropertiesTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicPropertiesTests.java index 0c2c6aae3..3d11b450f 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicPropertiesTests.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicPropertiesTests.java @@ -17,7 +17,7 @@ package org.springframework.ai.autoconfigure.anthropic; import org.junit.jupiter.api.Test; -import org.springframework.ai.anthropic.AnthropicChatClient; +import org.springframework.ai.anthropic.AnthropicChatConnector; import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; @@ -102,7 +102,7 @@ public class AnthropicPropertiesTests { RestClientAutoConfiguration.class, AnthropicAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AnthropicChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(AnthropicChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(AnthropicChatConnector.class)).isNotEmpty(); }); // Explicitly enable the chat auto-configuration. @@ -111,7 +111,7 @@ public class AnthropicPropertiesTests { RestClientAutoConfiguration.class, AnthropicAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AnthropicChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(AnthropicChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(AnthropicChatConnector.class)).isNotEmpty(); }); // Explicitly disable the chat auto-configuration. @@ -120,7 +120,7 @@ public class AnthropicPropertiesTests { RestClientAutoConfiguration.class, AnthropicAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AnthropicChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(AnthropicChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(AnthropicChatConnector.class)).isEmpty(); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/tool/FunctionCallWithFunctionBeanIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/tool/FunctionCallWithFunctionBeanIT.java index d170add72..5ec8fa185 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/tool/FunctionCallWithFunctionBeanIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/tool/FunctionCallWithFunctionBeanIT.java @@ -23,7 +23,7 @@ import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.ai.anthropic.AnthropicChatClient; +import org.springframework.ai.anthropic.AnthropicChatConnector; import org.springframework.ai.anthropic.AnthropicChatOptions; import org.springframework.ai.anthropic.api.AnthropicApi; import org.springframework.ai.autoconfigure.anthropic.AnthropicAutoConfiguration; @@ -61,19 +61,19 @@ class FunctionCallWithFunctionBeanIT { "spring.ai.anthropic.chat.options.model=" + AnthropicApi.ChatModel.CLAUDE_3_OPUS.getValue()) .run(context -> { - AnthropicChatClient chatClient = context.getBean(AnthropicChatClient.class); + AnthropicChatConnector chatClient = context.getBean(AnthropicChatConnector.class); var userMessage = new UserMessage( "What's the weather like in San Francisco, in Paris, France and in Tokyo, Japan? Return the temperature in Celsius."); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), + ChatResponse response = chatClient.execute(new Prompt(List.of(userMessage), AnthropicChatOptions.builder().withFunction("weatherFunction").build())); logger.info("Response: {}", response); assertThat(response.getResult().getOutput().getContent()).contains("30", "10", "15"); - response = chatClient.call(new Prompt(List.of(userMessage), + response = chatClient.execute(new Prompt(List.of(userMessage), AnthropicChatOptions.builder().withFunction("weatherFunction3").build())); logger.info("Response: {}", response); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/tool/FunctionCallWithPromptFunctionIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/tool/FunctionCallWithPromptFunctionIT.java index a9592cae7..76f5d1b4c 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/tool/FunctionCallWithPromptFunctionIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/tool/FunctionCallWithPromptFunctionIT.java @@ -22,7 +22,7 @@ import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.ai.anthropic.AnthropicChatClient; +import org.springframework.ai.anthropic.AnthropicChatConnector; import org.springframework.ai.anthropic.AnthropicChatOptions; import org.springframework.ai.anthropic.api.AnthropicApi; import org.springframework.ai.autoconfigure.anthropic.AnthropicAutoConfiguration; @@ -54,7 +54,7 @@ public class FunctionCallWithPromptFunctionIT { "spring.ai.anthropic.chat.options.model=" + AnthropicApi.ChatModel.CLAUDE_3_OPUS.getValue()) .run(context -> { - AnthropicChatClient chatClient = context.getBean(AnthropicChatClient.class); + AnthropicChatConnector chatClient = context.getBean(AnthropicChatConnector.class); UserMessage userMessage = new UserMessage( "What's the weather like in San Francisco, in Paris and in Tokyo? Return the temperature in Celsius."); @@ -66,7 +66,7 @@ public class FunctionCallWithPromptFunctionIT { .build())) .build(); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), promptOptions)); + ChatResponse response = chatClient.execute(new Prompt(List.of(userMessage), promptOptions)); logger.info("Response: {}", response); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/AzureOpenAiAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/AzureOpenAiAutoConfigurationIT.java index ce7075250..f1185b713 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/AzureOpenAiAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/AzureOpenAiAutoConfigurationIT.java @@ -25,7 +25,7 @@ import org.springframework.ai.chat.messages.AssistantMessage; import reactor.core.publisher.Flux; import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration; -import org.springframework.ai.azure.openai.AzureOpenAiChatClient; +import org.springframework.ai.azure.openai.AzureOpenAiChatConnector; import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingClient; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; @@ -77,8 +77,8 @@ public class AzureOpenAiAutoConfigurationIT { @Test public void chatCompletion() { contextRunner.run(context -> { - AzureOpenAiChatClient chatClient = context.getBean(AzureOpenAiChatClient.class); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage, systemMessage))); + AzureOpenAiChatConnector chatClient = context.getBean(AzureOpenAiChatConnector.class); + ChatResponse response = chatClient.execute(new Prompt(List.of(userMessage, systemMessage))); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); }); } @@ -87,7 +87,7 @@ public class AzureOpenAiAutoConfigurationIT { public void chatCompletionStreaming() { contextRunner.run(context -> { - AzureOpenAiChatClient chatClient = context.getBean(AzureOpenAiChatClient.class); + AzureOpenAiChatConnector chatClient = context.getBean(AzureOpenAiChatConnector.class); Flux response = chatClient.stream(new Prompt(List.of(userMessage, systemMessage))); @@ -127,17 +127,17 @@ public class AzureOpenAiAutoConfigurationIT { // Disable the chat auto-configuration. contextRunner.withPropertyValues("spring.ai.azure.openai.chat.enabled=false").run(context -> { - assertThat(context.getBeansOfType(AzureOpenAiChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(AzureOpenAiChatConnector.class)).isEmpty(); }); // The chat auto-configuration is enabled by default. contextRunner.run(context -> { - assertThat(context.getBeansOfType(AzureOpenAiChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(AzureOpenAiChatConnector.class)).isNotEmpty(); }); // Explicitly enable the chat auto-configuration. contextRunner.withPropertyValues("spring.ai.azure.openai.chat.enabled=true").run(context -> { - assertThat(context.getBeansOfType(AzureOpenAiChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(AzureOpenAiChatConnector.class)).isNotEmpty(); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithFunctionBeanIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithFunctionBeanIT.java index e8a7e2126..656c71586 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithFunctionBeanIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithFunctionBeanIT.java @@ -24,9 +24,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration; -import org.springframework.ai.azure.openai.AzureOpenAiChatClient; +import org.springframework.ai.azure.openai.AzureOpenAiChatConnector; import org.springframework.ai.azure.openai.AzureOpenAiChatOptions; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; @@ -57,19 +57,19 @@ class FunctionCallWithFunctionBeanIT { contextRunner.withPropertyValues("spring.ai.azure.openai.chat.options..deployment-name=gpt-4-0125-preview") .run(context -> { - ChatClient chatClient = context.getBean(AzureOpenAiChatClient.class); + ChatConnector chatConnector = context.getBean(AzureOpenAiChatConnector.class); UserMessage userMessage = new UserMessage( "What's the weather like in San Francisco, Paris and in Tokyo? Use Multi-turn function calling."); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), + ChatResponse response = chatConnector.execute(new Prompt(List.of(userMessage), AzureOpenAiChatOptions.builder().withFunction("weatherFunction").build())); logger.info("Response: {}", response); assertThat(response.getResult().getOutput().getContent()).contains("30", "10", "15"); - response = chatClient.call(new Prompt(List.of(userMessage), + response = chatConnector.execute(new Prompt(List.of(userMessage), AzureOpenAiChatOptions.builder().withFunction("weatherFunction3").build())); logger.info("Response: {}", response); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithFunctionWrapperIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithFunctionWrapperIT.java index 934b84cf1..90b1b075a 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithFunctionWrapperIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithFunctionWrapperIT.java @@ -23,7 +23,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration; -import org.springframework.ai.azure.openai.AzureOpenAiChatClient; +import org.springframework.ai.azure.openai.AzureOpenAiChatConnector; import org.springframework.ai.azure.openai.AzureOpenAiChatOptions; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.UserMessage; @@ -56,12 +56,12 @@ public class FunctionCallWithFunctionWrapperIT { contextRunner.withPropertyValues("spring.ai.azure.openai.chat.options.deployment-name=gpt-4-0125-preview") .run(context -> { - AzureOpenAiChatClient chatClient = context.getBean(AzureOpenAiChatClient.class); + AzureOpenAiChatConnector chatClient = context.getBean(AzureOpenAiChatConnector.class); UserMessage userMessage = new UserMessage( "What's the weather like in San Francisco, Paris and in Tokyo?"); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), + ChatResponse response = chatClient.execute(new Prompt(List.of(userMessage), AzureOpenAiChatOptions.builder().withFunction("WeatherInfo").build())); logger.info("Response: {}", response); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithPromptFunctionIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithPromptFunctionIT.java index 9bef922d2..e8c026e27 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithPromptFunctionIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/tool/FunctionCallWithPromptFunctionIT.java @@ -23,7 +23,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration; -import org.springframework.ai.azure.openai.AzureOpenAiChatClient; +import org.springframework.ai.azure.openai.AzureOpenAiChatConnector; import org.springframework.ai.azure.openai.AzureOpenAiChatOptions; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.UserMessage; @@ -52,7 +52,7 @@ public class FunctionCallWithPromptFunctionIT { contextRunner.withPropertyValues("spring.ai.azure.openai.chat.options.deployment-name=gpt-4-0125-preview") .run(context -> { - AzureOpenAiChatClient chatClient = context.getBean(AzureOpenAiChatClient.class); + AzureOpenAiChatConnector chatClient = context.getBean(AzureOpenAiChatConnector.class); UserMessage userMessage = new UserMessage( "What's the weather like in San Francisco, in Paris and in Tokyo? Use Multi-turn function calling."); @@ -64,7 +64,7 @@ public class FunctionCallWithPromptFunctionIT { .build())) .build(); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), promptOptions)); + ChatResponse response = chatClient.execute(new Prompt(List.of(userMessage), promptOptions)); logger.info("Response: {}", response); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/anthropic/BedrockAnthropicChatAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/anthropic/BedrockAnthropicChatAutoConfigurationIT.java index f8aca8b9a..19769c5f1 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/anthropic/BedrockAnthropicChatAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/anthropic/BedrockAnthropicChatAutoConfigurationIT.java @@ -21,12 +21,12 @@ import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.springframework.ai.bedrock.anthropic.BedrockAnthropicChatConnector; import org.springframework.ai.chat.messages.AssistantMessage; import reactor.core.publisher.Flux; import software.amazon.awssdk.regions.Region; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; -import org.springframework.ai.bedrock.anthropic.BedrockAnthropicChatClient; import org.springframework.ai.bedrock.anthropic.api.AnthropicChatBedrockApi.AnthropicChatModel; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; @@ -69,8 +69,8 @@ public class BedrockAnthropicChatAutoConfigurationIT { @Test public void chatCompletion() { contextRunner.run(context -> { - BedrockAnthropicChatClient anthropicChatClient = context.getBean(BedrockAnthropicChatClient.class); - ChatResponse response = anthropicChatClient.call(new Prompt(List.of(userMessage, systemMessage))); + BedrockAnthropicChatConnector anthropicChatClient = context.getBean(BedrockAnthropicChatConnector.class); + ChatResponse response = anthropicChatClient.execute(new Prompt(List.of(userMessage, systemMessage))); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); }); } @@ -79,7 +79,7 @@ public class BedrockAnthropicChatAutoConfigurationIT { public void chatCompletionStreaming() { contextRunner.run(context -> { - BedrockAnthropicChatClient anthropicChatClient = context.getBean(BedrockAnthropicChatClient.class); + BedrockAnthropicChatConnector anthropicChatClient = context.getBean(BedrockAnthropicChatConnector.class); Flux response = anthropicChatClient.stream(new Prompt(List.of(userMessage, systemMessage))); @@ -130,7 +130,7 @@ public class BedrockAnthropicChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockAnthropicChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockAnthropicChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(BedrockAnthropicChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(BedrockAnthropicChatConnector.class)).isEmpty(); }); // Explicitly enable the chat auto-configuration. @@ -138,7 +138,7 @@ public class BedrockAnthropicChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockAnthropicChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockAnthropicChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(BedrockAnthropicChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(BedrockAnthropicChatConnector.class)).isNotEmpty(); }); // Explicitly disable the chat auto-configuration. @@ -146,7 +146,7 @@ public class BedrockAnthropicChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockAnthropicChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockAnthropicChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(BedrockAnthropicChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(BedrockAnthropicChatConnector.class)).isEmpty(); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/anthropic3/BedrockAnthropic3ChatAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/anthropic3/BedrockAnthropic3ChatAutoConfigurationIT.java index 467fedc7e..a57c659c7 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/anthropic3/BedrockAnthropic3ChatAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/anthropic3/BedrockAnthropic3ChatAutoConfigurationIT.java @@ -21,12 +21,12 @@ import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.springframework.ai.bedrock.anthropic3.BedrockAnthropic3ChatConnector; import org.springframework.ai.chat.messages.AssistantMessage; import reactor.core.publisher.Flux; import software.amazon.awssdk.regions.Region; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; -import org.springframework.ai.bedrock.anthropic3.BedrockAnthropic3ChatClient; import org.springframework.ai.bedrock.anthropic3.api.Anthropic3ChatBedrockApi.AnthropicChatModel; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; @@ -69,8 +69,8 @@ public class BedrockAnthropic3ChatAutoConfigurationIT { @Test public void chatCompletion() { contextRunner.run(context -> { - BedrockAnthropic3ChatClient anthropicChatClient = context.getBean(BedrockAnthropic3ChatClient.class); - ChatResponse response = anthropicChatClient.call(new Prompt(List.of(userMessage, systemMessage))); + BedrockAnthropic3ChatConnector anthropicChatClient = context.getBean(BedrockAnthropic3ChatConnector.class); + ChatResponse response = anthropicChatClient.execute(new Prompt(List.of(userMessage, systemMessage))); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); }); } @@ -79,7 +79,7 @@ public class BedrockAnthropic3ChatAutoConfigurationIT { public void chatCompletionStreaming() { contextRunner.run(context -> { - BedrockAnthropic3ChatClient anthropicChatClient = context.getBean(BedrockAnthropic3ChatClient.class); + BedrockAnthropic3ChatConnector anthropicChatClient = context.getBean(BedrockAnthropic3ChatConnector.class); Flux response = anthropicChatClient.stream(new Prompt(List.of(userMessage, systemMessage))); @@ -130,7 +130,7 @@ public class BedrockAnthropic3ChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockAnthropic3ChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockAnthropic3ChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(BedrockAnthropic3ChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(BedrockAnthropic3ChatConnector.class)).isEmpty(); }); // Explicitly enable the chat auto-configuration. @@ -138,7 +138,7 @@ public class BedrockAnthropic3ChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockAnthropic3ChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockAnthropic3ChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(BedrockAnthropic3ChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(BedrockAnthropic3ChatConnector.class)).isNotEmpty(); }); // Explicitly disable the chat auto-configuration. @@ -146,7 +146,7 @@ public class BedrockAnthropic3ChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockAnthropic3ChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockAnthropic3ChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(BedrockAnthropic3ChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(BedrockAnthropic3ChatConnector.class)).isEmpty(); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereChatAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereChatAutoConfigurationIT.java index e515f6afd..3f0b5a244 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereChatAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereChatAutoConfigurationIT.java @@ -21,13 +21,13 @@ import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.springframework.ai.bedrock.cohere.BedrockCohereChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.AssistantMessage; import reactor.core.publisher.Flux; import software.amazon.awssdk.regions.Region; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; -import org.springframework.ai.bedrock.cohere.BedrockCohereChatClient; import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi.CohereChatModel; import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi.CohereChatRequest.ReturnLikelihoods; import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi.CohereChatRequest.Truncate; @@ -72,8 +72,8 @@ public class BedrockCohereChatAutoConfigurationIT { @Test public void chatCompletion() { contextRunner.run(context -> { - BedrockCohereChatClient cohereChatClient = context.getBean(BedrockCohereChatClient.class); - ChatResponse response = cohereChatClient.call(new Prompt(List.of(userMessage, systemMessage))); + BedrockCohereChatConnector cohereChatClient = context.getBean(BedrockCohereChatConnector.class); + ChatResponse response = cohereChatClient.execute(new Prompt(List.of(userMessage, systemMessage))); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); }); } @@ -82,7 +82,7 @@ public class BedrockCohereChatAutoConfigurationIT { public void chatCompletionStreaming() { contextRunner.run(context -> { - BedrockCohereChatClient cohereChatClient = context.getBean(BedrockCohereChatClient.class); + BedrockCohereChatConnector cohereChatClient = context.getBean(BedrockCohereChatConnector.class); Flux response = cohereChatClient.stream(new Prompt(List.of(userMessage, systemMessage))); @@ -146,7 +146,7 @@ public class BedrockCohereChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockCohereChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockCohereChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(BedrockCohereChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(BedrockCohereChatConnector.class)).isEmpty(); }); // Explicitly enable the chat auto-configuration. @@ -154,7 +154,7 @@ public class BedrockCohereChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockCohereChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockCohereChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(BedrockCohereChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(BedrockCohereChatConnector.class)).isNotEmpty(); }); // Explicitly disable the chat auto-configuration. @@ -162,7 +162,7 @@ public class BedrockCohereChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockCohereChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockCohereChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(BedrockCohereChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(BedrockCohereChatConnector.class)).isEmpty(); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/jurassic2/BedrockAi21Jurassic2ChatAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/jurassic2/BedrockAi21Jurassic2ChatAutoConfigurationIT.java index 057e46483..217693d53 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/jurassic2/BedrockAi21Jurassic2ChatAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/jurassic2/BedrockAi21Jurassic2ChatAutoConfigurationIT.java @@ -21,7 +21,7 @@ import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; import org.springframework.ai.autoconfigure.bedrock.jurrasic2.BedrockAi21Jurassic2ChatAutoConfiguration; import org.springframework.ai.autoconfigure.bedrock.jurrasic2.BedrockAi21Jurassic2ChatProperties; -import org.springframework.ai.bedrock.jurassic2.BedrockAi21Jurassic2ChatClient; +import org.springframework.ai.bedrock.jurassic2.BedrockAi21Jurassic2ChatConnector; import org.springframework.ai.bedrock.jurassic2.api.Ai21Jurassic2ChatBedrockApi; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.Message; @@ -69,9 +69,9 @@ public class BedrockAi21Jurassic2ChatAutoConfigurationIT { @Test public void chatCompletion() { contextRunner.run(context -> { - BedrockAi21Jurassic2ChatClient ai21Jurassic2ChatClient = context - .getBean(BedrockAi21Jurassic2ChatClient.class); - ChatResponse response = ai21Jurassic2ChatClient.call(new Prompt(List.of(userMessage, systemMessage))); + BedrockAi21Jurassic2ChatConnector ai21Jurassic2ChatClient = context + .getBean(BedrockAi21Jurassic2ChatConnector.class); + ChatResponse response = ai21Jurassic2ChatClient.execute(new Prompt(List.of(userMessage, systemMessage))); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); }); } @@ -111,7 +111,7 @@ public class BedrockAi21Jurassic2ChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockAi21Jurassic2ChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockAi21Jurassic2ChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(BedrockAi21Jurassic2ChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(BedrockAi21Jurassic2ChatConnector.class)).isEmpty(); }); // Explicitly enable the chat auto-configuration. @@ -119,7 +119,7 @@ public class BedrockAi21Jurassic2ChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockAi21Jurassic2ChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockAi21Jurassic2ChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(BedrockAi21Jurassic2ChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(BedrockAi21Jurassic2ChatConnector.class)).isNotEmpty(); }); // Explicitly disable the chat auto-configuration. @@ -127,7 +127,7 @@ public class BedrockAi21Jurassic2ChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockAi21Jurassic2ChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockAi21Jurassic2ChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(BedrockAi21Jurassic2ChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(BedrockAi21Jurassic2ChatConnector.class)).isEmpty(); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/llama/BedrockLlamaChatAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/llama/BedrockLlamaChatAutoConfigurationIT.java index 6ca69b655..8a54a129f 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/llama/BedrockLlamaChatAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/llama/BedrockLlamaChatAutoConfigurationIT.java @@ -21,13 +21,13 @@ import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.springframework.ai.bedrock.llama.BedrockLlamaChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.AssistantMessage; import reactor.core.publisher.Flux; import software.amazon.awssdk.regions.Region; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; -import org.springframework.ai.bedrock.llama.BedrockLlamaChatClient; import org.springframework.ai.bedrock.llama.api.LlamaChatBedrockApi.LlamaChatModel; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.prompt.Prompt; @@ -71,8 +71,8 @@ public class BedrockLlamaChatAutoConfigurationIT { @Test public void chatCompletion() { contextRunner.run(context -> { - BedrockLlamaChatClient llamaChatClient = context.getBean(BedrockLlamaChatClient.class); - ChatResponse response = llamaChatClient.call(new Prompt(List.of(userMessage, systemMessage))); + BedrockLlamaChatConnector llamaChatClient = context.getBean(BedrockLlamaChatConnector.class); + ChatResponse response = llamaChatClient.execute(new Prompt(List.of(userMessage, systemMessage))); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); }); } @@ -81,7 +81,7 @@ public class BedrockLlamaChatAutoConfigurationIT { public void chatCompletionStreaming() { contextRunner.run(context -> { - BedrockLlamaChatClient llamaChatClient = context.getBean(BedrockLlamaChatClient.class); + BedrockLlamaChatConnector llamaChatClient = context.getBean(BedrockLlamaChatConnector.class); Flux response = llamaChatClient.stream(new Prompt(List.of(userMessage, systemMessage))); @@ -133,7 +133,7 @@ public class BedrockLlamaChatAutoConfigurationIT { new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(BedrockLlamaChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockLlamaChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(BedrockLlamaChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(BedrockLlamaChatConnector.class)).isEmpty(); }); // Explicitly enable the chat auto-configuration. @@ -141,7 +141,7 @@ public class BedrockLlamaChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockLlamaChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockLlamaChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(BedrockLlamaChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(BedrockLlamaChatConnector.class)).isNotEmpty(); }); // Explicitly disable the chat auto-configuration. @@ -149,7 +149,7 @@ public class BedrockLlamaChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockLlamaChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockLlamaChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(BedrockLlamaChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(BedrockLlamaChatConnector.class)).isEmpty(); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfigurationIT.java index 93c654178..c8b813d14 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfigurationIT.java @@ -21,13 +21,13 @@ import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.springframework.ai.bedrock.titan.BedrockTitanChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.AssistantMessage; import reactor.core.publisher.Flux; import software.amazon.awssdk.regions.Region; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; -import org.springframework.ai.bedrock.titan.BedrockTitanChatClient; import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi.TitanChatModel; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.prompt.Prompt; @@ -70,8 +70,8 @@ public class BedrockTitanChatAutoConfigurationIT { @Test public void chatCompletion() { contextRunner.run(context -> { - BedrockTitanChatClient chatClient = context.getBean(BedrockTitanChatClient.class); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage, systemMessage))); + BedrockTitanChatConnector chatClient = context.getBean(BedrockTitanChatConnector.class); + ChatResponse response = chatClient.execute(new Prompt(List.of(userMessage, systemMessage))); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); }); } @@ -80,7 +80,7 @@ public class BedrockTitanChatAutoConfigurationIT { public void chatCompletionStreaming() { contextRunner.run(context -> { - BedrockTitanChatClient chatClient = context.getBean(BedrockTitanChatClient.class); + BedrockTitanChatConnector chatClient = context.getBean(BedrockTitanChatConnector.class); Flux response = chatClient.stream(new Prompt(List.of(userMessage, systemMessage))); @@ -137,7 +137,7 @@ public class BedrockTitanChatAutoConfigurationIT { new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(BedrockTitanChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockTitanChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(BedrockTitanChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(BedrockTitanChatConnector.class)).isEmpty(); }); // Explicitly enable the chat auto-configuration. @@ -145,7 +145,7 @@ public class BedrockTitanChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockTitanChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockTitanChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(BedrockTitanChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(BedrockTitanChatConnector.class)).isNotEmpty(); }); // Explicitly disable the chat auto-configuration. @@ -153,7 +153,7 @@ public class BedrockTitanChatAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(BedrockTitanChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockTitanChatProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(BedrockTitanChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(BedrockTitanChatConnector.class)).isEmpty(); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/MistralAiAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/MistralAiAutoConfigurationIT.java index 25816e8c0..c403d092c 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/MistralAiAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/MistralAiAutoConfigurationIT.java @@ -22,6 +22,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.springframework.ai.mistralai.MistralAiChatConnector; import reactor.core.publisher.Flux; import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration; @@ -29,7 +30,6 @@ import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.embedding.EmbeddingResponse; -import org.springframework.ai.mistralai.MistralAiChatClient; import org.springframework.ai.mistralai.MistralAiEmbeddingClient; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; @@ -54,8 +54,8 @@ public class MistralAiAutoConfigurationIT { @Test void generate() { contextRunner.run(context -> { - MistralAiChatClient client = context.getBean(MistralAiChatClient.class); - String response = client.call("Hello"); + MistralAiChatConnector client = context.getBean(MistralAiChatConnector.class); + String response = client.execute("Hello"); assertThat(response).isNotEmpty(); logger.info("Response: " + response); }); @@ -64,7 +64,7 @@ public class MistralAiAutoConfigurationIT { @Test void generateStreaming() { contextRunner.run(context -> { - MistralAiChatClient client = context.getBean(MistralAiChatClient.class); + MistralAiChatConnector client = context.getBean(MistralAiChatConnector.class); Flux responseFlux = client.stream(new Prompt(new UserMessage("Hello"))); String response = responseFlux.collectList().block().stream().map(chatResponse -> { return chatResponse.getResults().get(0).getOutput().getContent(); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusBeanIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusBeanIT.java index d4259f3ee..cdc2cab93 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusBeanIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusBeanIT.java @@ -30,7 +30,7 @@ import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.mistralai.MistralAiChatClient; +import org.springframework.ai.mistralai.MistralAiChatConnector; import org.springframework.ai.mistralai.MistralAiChatOptions; import org.springframework.ai.mistralai.api.MistralAiApi; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -60,10 +60,10 @@ class PaymentStatusBeanIT { .withPropertyValues("spring.ai.mistralai.chat.options.model=" + MistralAiApi.ChatModel.LARGE.getValue()) .run(context -> { - MistralAiChatClient chatClient = context.getBean(MistralAiChatClient.class); + MistralAiChatConnector chatClient = context.getBean(MistralAiChatConnector.class); ChatResponse response = chatClient - .call(new Prompt(List.of(new UserMessage("What's the status of my transaction with id T1001?")), + .execute(new Prompt(List.of(new UserMessage("What's the status of my transaction with id T1001?")), MistralAiChatOptions.builder() .withFunction("retrievePaymentStatus") .withFunction("retrievePaymentDate") diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusBeanOpenAiIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusBeanOpenAiIT.java index 15796f921..deb2d0c14 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusBeanOpenAiIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusBeanOpenAiIT.java @@ -31,7 +31,7 @@ import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.mistralai.api.MistralAiApi; -import org.springframework.ai.openai.OpenAiChatClient; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; @@ -43,7 +43,7 @@ import org.springframework.context.annotation.Description; import static org.assertj.core.api.Assertions.assertThat; /** - * Same test as {@link PaymentStatusBeanIT.java} but using {@link OpenAiChatClient} for + * Same test as {@link PaymentStatusBeanIT.java} but using {@link OpenAiChatConnector} for * Mistral AI Function Calling implementation. * * @author Christian Tzolov @@ -67,10 +67,10 @@ class PaymentStatusBeanOpenAiIT { .withPropertyValues("spring.ai.openai.chat.options.model=" + MistralAiApi.ChatModel.SMALL.getValue()) .run(context -> { - OpenAiChatClient chatClient = context.getBean(OpenAiChatClient.class); + OpenAiChatConnector chatClient = context.getBean(OpenAiChatConnector.class); ChatResponse response = chatClient - .call(new Prompt(List.of(new UserMessage("What's the status of my transaction with id T1001?")), + .execute(new Prompt(List.of(new UserMessage("What's the status of my transaction with id T1001?")), OpenAiChatOptions.builder() .withFunction("retrievePaymentStatus") .withFunction("retrievePaymentDate") diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusPromptIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusPromptIT.java index 58bd9e84c..63f55f3f0 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusPromptIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusPromptIT.java @@ -30,7 +30,7 @@ import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.mistralai.MistralAiChatClient; +import org.springframework.ai.mistralai.MistralAiChatConnector; import org.springframework.ai.mistralai.MistralAiChatOptions; import org.springframework.ai.mistralai.api.MistralAiApi; import org.springframework.ai.model.function.FunctionCallbackWrapper; @@ -71,7 +71,7 @@ public class PaymentStatusPromptIT { .withPropertyValues("spring.ai.mistralai.chat.options.model=" + MistralAiApi.ChatModel.SMALL.getValue()) .run(context -> { - MistralAiChatClient chatClient = context.getBean(MistralAiChatClient.class); + MistralAiChatConnector chatClient = context.getBean(MistralAiChatConnector.class); UserMessage userMessage = new UserMessage("What's the status of my transaction with id T1001?"); @@ -86,7 +86,7 @@ public class PaymentStatusPromptIT { .build())) .build(); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), promptOptions)); + ChatResponse response = chatClient.execute(new Prompt(List.of(userMessage), promptOptions)); logger.info("Response: {}", response); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/WeatherServicePromptIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/WeatherServicePromptIT.java index 6bf052f56..207cfd097 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/WeatherServicePromptIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/WeatherServicePromptIT.java @@ -33,7 +33,7 @@ import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.mistralai.MistralAiChatClient; +import org.springframework.ai.mistralai.MistralAiChatConnector; import org.springframework.ai.mistralai.MistralAiChatOptions; import org.springframework.ai.mistralai.api.MistralAiApi; import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionRequest.ToolChoice; @@ -64,7 +64,7 @@ public class WeatherServicePromptIT { .withPropertyValues("spring.ai.mistralai.chat.options.model=" + MistralAiApi.ChatModel.LARGE.getValue()) .run(context -> { - MistralAiChatClient chatClient = context.getBean(MistralAiChatClient.class); + MistralAiChatConnector chatClient = context.getBean(MistralAiChatConnector.class); UserMessage userMessage = new UserMessage("What's the weather like in Paris?"); // UserMessage userMessage = new UserMessage("What's the weather like in @@ -79,7 +79,7 @@ public class WeatherServicePromptIT { .build())) .build(); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), promptOptions)); + ChatResponse response = chatClient.execute(new Prompt(List.of(userMessage), promptOptions)); logger.info("Response: {}", response); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfigurationIT.java index affa26197..e796fba7b 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfigurationIT.java @@ -26,7 +26,7 @@ import org.junit.jupiter.api.Test; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.Generation; import org.springframework.ai.chat.messages.AssistantMessage; -import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.ai.ollama.OllamaChatConnector; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.SystemPromptTemplate; import org.springframework.ai.chat.messages.Message; @@ -104,8 +104,8 @@ public class OllamaChatAutoConfigurationIT { @Test public void chatCompletion() { contextRunner.run(context -> { - OllamaChatClient chatClient = context.getBean(OllamaChatClient.class); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage, systemMessage))); + OllamaChatConnector chatClient = context.getBean(OllamaChatConnector.class); + ChatResponse response = chatClient.execute(new Prompt(List.of(userMessage, systemMessage))); assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); }); } @@ -114,7 +114,7 @@ public class OllamaChatAutoConfigurationIT { public void chatCompletionStreaming() { contextRunner.run(context -> { - OllamaChatClient chatClient = context.getBean(OllamaChatClient.class); + OllamaChatConnector chatClient = context.getBean(OllamaChatConnector.class); Flux response = chatClient.stream(new Prompt(List.of(userMessage, systemMessage))); @@ -136,17 +136,17 @@ public class OllamaChatAutoConfigurationIT { void chatActivation() { contextRunner.withPropertyValues("spring.ai.ollama.chat.enabled=false").run(context -> { assertThat(context.getBeansOfType(OllamaChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(OllamaChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(OllamaChatConnector.class)).isEmpty(); }); contextRunner.run(context -> { assertThat(context.getBeansOfType(OllamaChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(OllamaChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(OllamaChatConnector.class)).isNotEmpty(); }); contextRunner.withPropertyValues("spring.ai.ollama.chat.enabled=true").run(context -> { assertThat(context.getBeansOfType(OllamaChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(OllamaChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(OllamaChatConnector.class)).isNotEmpty(); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfigurationIT.java index 44c2d7375..a5410ff7d 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfigurationIT.java @@ -27,18 +27,15 @@ import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; -import org.springframework.ai.openai.OpenAiImageClient; +import org.springframework.ai.openai.*; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import reactor.core.publisher.Flux; -import org.springframework.ai.openai.OpenAiAudioSpeechClient; import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.embedding.EmbeddingResponse; -import org.springframework.ai.openai.OpenAiAudioTranscriptionClient; -import org.springframework.ai.openai.OpenAiChatClient; -import org.springframework.ai.openai.OpenAiEmbeddingClient; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -58,8 +55,8 @@ public class OpenAiAutoConfigurationIT { @Test void generate() { contextRunner.run(context -> { - OpenAiChatClient client = context.getBean(OpenAiChatClient.class); - String response = client.call("Hello"); + OpenAiChatConnector client = context.getBean(OpenAiChatConnector.class); + String response = client.execute("Hello"); assertThat(response).isNotEmpty(); logger.info("Response: " + response); }); @@ -105,7 +102,7 @@ public class OpenAiAutoConfigurationIT { @Test void generateStreaming() { contextRunner.run(context -> { - OpenAiChatClient client = context.getBean(OpenAiChatClient.class); + OpenAiChatConnector client = context.getBean(OpenAiChatConnector.class); Flux responseFlux = client.stream(new Prompt(new UserMessage("Hello"))); String response = responseFlux.collectList().block().stream().map(chatResponse -> { return chatResponse.getResults().get(0).getOutput().getContent(); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiPropertiesTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiPropertiesTests.java index 10583ecd4..22ec69b08 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiPropertiesTests.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiPropertiesTests.java @@ -21,7 +21,7 @@ import org.skyscreamer.jsonassert.JSONCompareMode; import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration; import org.springframework.ai.model.ModelOptionsUtils; -import org.springframework.ai.openai.OpenAiChatClient; +import org.springframework.ai.openai.OpenAiChatConnector; import org.springframework.ai.openai.OpenAiEmbeddingClient; import org.springframework.ai.openai.OpenAiImageClient; import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.ResponseFormat; @@ -593,7 +593,7 @@ public class OpenAiPropertiesTests { RestClientAutoConfiguration.class, OpenAiAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(OpenAiChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(OpenAiChatConnector.class)).isEmpty(); }); new ApplicationContextRunner() @@ -602,7 +602,7 @@ public class OpenAiPropertiesTests { RestClientAutoConfiguration.class, OpenAiAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(OpenAiChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(OpenAiChatConnector.class)).isNotEmpty(); }); new ApplicationContextRunner() @@ -612,7 +612,7 @@ public class OpenAiPropertiesTests { RestClientAutoConfiguration.class, OpenAiAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(OpenAiChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(OpenAiChatConnector.class)).isNotEmpty(); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackInPromptIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackInPromptIT.java index 67770f6af..79c9cb51b 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackInPromptIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackInPromptIT.java @@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.ai.openai.OpenAiChatConnector; import reactor.core.publisher.Flux; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; @@ -32,7 +33,6 @@ import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.function.FunctionCallbackWrapper; -import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; @@ -54,7 +54,7 @@ public class FunctionCallbackInPromptIT { void functionCallTest() { contextRunner.withPropertyValues("spring.ai.openai.chat.options.model=gpt-4-turbo-preview").run(context -> { - OpenAiChatClient chatClient = context.getBean(OpenAiChatClient.class); + OpenAiChatConnector chatClient = context.getBean(OpenAiChatConnector.class); UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?"); @@ -66,7 +66,7 @@ public class FunctionCallbackInPromptIT { .build())) .build(); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), promptOptions)); + ChatResponse response = chatClient.execute(new Prompt(List.of(userMessage), promptOptions)); logger.info("Response: {}", response); @@ -79,7 +79,7 @@ public class FunctionCallbackInPromptIT { contextRunner.withPropertyValues("spring.ai.openai.chat.options.model=gpt-4-turbo-preview").run(context -> { - OpenAiChatClient chatClient = context.getBean(OpenAiChatClient.class); + OpenAiChatConnector chatClient = context.getBean(OpenAiChatConnector.class); UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?"); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackWithPlainFunctionBeanIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackWithPlainFunctionBeanIT.java index d5437a62f..d0844f60d 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackWithPlainFunctionBeanIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackWithPlainFunctionBeanIT.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.ai.openai.OpenAiChatConnector; import reactor.core.publisher.Flux; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; @@ -34,7 +35,6 @@ import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.function.FunctionCallingOptions; import org.springframework.ai.model.function.FunctionCallingOptionsBuilder.PortableFunctionCallingOptions; -import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; @@ -60,12 +60,12 @@ class FunctionCallbackWithPlainFunctionBeanIT { void functionCallTest() { contextRunner.withPropertyValues("spring.ai.openai.chat.options.model=gpt-4-turbo-preview").run(context -> { - OpenAiChatClient chatClient = context.getBean(OpenAiChatClient.class); + OpenAiChatConnector chatClient = context.getBean(OpenAiChatConnector.class); // Test weatherFunction UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?"); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), + ChatResponse response = chatClient.execute(new Prompt(List.of(userMessage), OpenAiChatOptions.builder().withFunction("weatherFunction").build())); logger.info("Response: {}", response); @@ -73,7 +73,7 @@ class FunctionCallbackWithPlainFunctionBeanIT { assertThat(response.getResult().getOutput().getContent()).contains("30", "10", "15"); // Test weatherFunctionTwo - response = chatClient.call(new Prompt(List.of(userMessage), + response = chatClient.execute(new Prompt(List.of(userMessage), OpenAiChatOptions.builder().withFunction("weatherFunctionTwo").build())); logger.info("Response: {}", response); @@ -87,7 +87,7 @@ class FunctionCallbackWithPlainFunctionBeanIT { void functionCallWithPortableFunctionCallingOptions() { contextRunner.withPropertyValues("spring.ai.openai.chat.options.model=gpt-4-turbo-preview").run(context -> { - OpenAiChatClient chatClient = context.getBean(OpenAiChatClient.class); + OpenAiChatConnector chatClient = context.getBean(OpenAiChatConnector.class); // Test weatherFunction UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?"); @@ -96,7 +96,7 @@ class FunctionCallbackWithPlainFunctionBeanIT { .withFunction("weatherFunction") .build(); - ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), functionOptions)); + ChatResponse response = chatClient.execute(new Prompt(List.of(userMessage), functionOptions)); logger.info("Response: {}", response); }); @@ -106,7 +106,7 @@ class FunctionCallbackWithPlainFunctionBeanIT { void streamFunctionCallTest() { contextRunner.withPropertyValues("spring.ai.openai.chat.options.model=gpt-4-turbo-preview").run(context -> { - OpenAiChatClient chatClient = context.getBean(OpenAiChatClient.class); + OpenAiChatConnector chatClient = context.getBean(OpenAiChatConnector.class); // Test weatherFunction UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?"); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackWrapperIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackWrapperIT.java index 44e2c3af7..f03ef598c 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackWrapperIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/tool/FunctionCallbackWrapperIT.java @@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.ai.openai.OpenAiChatConnector; import reactor.core.publisher.Flux; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; @@ -33,7 +34,6 @@ import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.function.FunctionCallbackWrapper; import org.springframework.ai.model.function.FunctionCallback; -import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; @@ -58,11 +58,11 @@ public class FunctionCallbackWrapperIT { void functionCallTest() { contextRunner.withPropertyValues("spring.ai.openai.chat.options.model=gpt-4-turbo-preview").run(context -> { - OpenAiChatClient chatClient = context.getBean(OpenAiChatClient.class); + OpenAiChatConnector chatClient = context.getBean(OpenAiChatConnector.class); UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?"); - ChatResponse response = chatClient.call( + ChatResponse response = chatClient.execute( new Prompt(List.of(userMessage), OpenAiChatOptions.builder().withFunction("WeatherInfo").build())); logger.info("Response: {}", response); @@ -76,7 +76,7 @@ public class FunctionCallbackWrapperIT { void streamFunctionCallTest() { contextRunner.withPropertyValues("spring.ai.openai.chat.options.model=gpt-4-turbo-preview").run(context -> { - OpenAiChatClient chatClient = context.getBean(OpenAiChatClient.class); + OpenAiChatConnector chatClient = context.getBean(OpenAiChatConnector.class); UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?"); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiAutoConfigurationIT.java index af0e77de9..955b43a1b 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiAutoConfigurationIT.java @@ -26,7 +26,7 @@ import reactor.core.publisher.Flux; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatConnector; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -46,8 +46,8 @@ public class VertexAiGeminiAutoConfigurationIT { @Test void generate() { contextRunner.run(context -> { - VertexAiGeminiChatClient client = context.getBean(VertexAiGeminiChatClient.class); - String response = client.call("Hello"); + VertexAiGeminiChatConnector client = context.getBean(VertexAiGeminiChatConnector.class); + String response = client.execute("Hello"); assertThat(response).isNotEmpty(); logger.info("Response: " + response); }); @@ -56,7 +56,7 @@ public class VertexAiGeminiAutoConfigurationIT { @Test void generateStreaming() { contextRunner.run(context -> { - VertexAiGeminiChatClient client = context.getBean(VertexAiGeminiChatClient.class); + VertexAiGeminiChatConnector client = context.getBean(VertexAiGeminiChatConnector.class); Flux responseFlux = client.stream(new Prompt(new UserMessage("Hello"))); String response = responseFlux.collectList().block().stream().map(chatResponse -> { return chatResponse.getResults().get(0).getOutput().getContent(); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/tool/FunctionCallWithFunctionBeanIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/tool/FunctionCallWithFunctionBeanIT.java index 908445675..028fd45c8 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/tool/FunctionCallWithFunctionBeanIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/tool/FunctionCallWithFunctionBeanIT.java @@ -28,7 +28,7 @@ import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatConnector; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -55,12 +55,12 @@ class FunctionCallWithFunctionBeanIT { void functionCallTest() { contextRunner.withPropertyValues("spring.ai.vertex.ai.gemini.chat.options.model=" - // + VertexAiGeminiChatClient.ChatModel.GEMINI_PRO.getValue()) - + VertexAiGeminiChatClient.ChatModel.GEMINI_PRO_1_5_PRO.getValue()) - // + VertexAiGeminiChatClient.ChatModel.GEMINI_PRO_1_5_FLASH.getValue()) + // + VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO.getValue()) + + VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO_1_5_PRO.getValue()) + // + VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO_1_5_FLASH.getValue()) .run(context -> { - VertexAiGeminiChatClient chatClient = context.getBean(VertexAiGeminiChatClient.class); + VertexAiGeminiChatConnector chatClient = context.getBean(VertexAiGeminiChatConnector.class); var systemMessage = new SystemMessage(""" Use Multi-turn function calling. @@ -72,9 +72,9 @@ class FunctionCallWithFunctionBeanIT { // Please let me know how many function calls you've preformed."); "What's the weather like in San Francisco, Paris and in Tokyo?"); - ChatResponse response = chatClient.call(new Prompt(List.of(systemMessage, userMessage), + ChatResponse response = chatClient.execute(new Prompt(List.of(systemMessage, userMessage), VertexAiGeminiChatOptions.builder().withFunction("weatherFunction").build())); - // ChatResponse response = chatClient.call(new + // ChatResponse response = chatConnector.call(new // Prompt(List.of(userMessage), // VertexAiGeminiChatOptions.builder().withFunction("weatherFunction").build())); @@ -84,7 +84,7 @@ class FunctionCallWithFunctionBeanIT { Thread.sleep(10000); - response = chatClient.call(new Prompt(List.of(systemMessage, userMessage), + response = chatClient.execute(new Prompt(List.of(systemMessage, userMessage), VertexAiGeminiChatOptions.builder().withFunction("weatherFunction3").build())); logger.info("Response: {}", response); @@ -92,7 +92,7 @@ class FunctionCallWithFunctionBeanIT { assertThat(response.getResult().getOutput().getContent()).contains("30", "10", "15"); response = chatClient - .call(new Prompt(List.of(systemMessage, userMessage), VertexAiGeminiChatOptions.builder().build())); + .execute(new Prompt(List.of(systemMessage, userMessage), VertexAiGeminiChatOptions.builder().build())); logger.info("Response: {}", response); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/tool/FunctionCallWithFunctionWrapperIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/tool/FunctionCallWithFunctionWrapperIT.java index cbad663c9..67df3f88e 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/tool/FunctionCallWithFunctionWrapperIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/tool/FunctionCallWithFunctionWrapperIT.java @@ -30,7 +30,7 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.function.FunctionCallback; import org.springframework.ai.model.function.FunctionCallbackWrapper; import org.springframework.ai.model.function.FunctionCallbackWrapper.Builder.SchemaType; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatConnector; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -55,10 +55,10 @@ public class FunctionCallWithFunctionWrapperIT { void functionCallTest() { contextRunner .withPropertyValues("spring.ai.vertex.ai.gemini.chat.options.model=" - + VertexAiGeminiChatClient.ChatModel.GEMINI_PRO.getValue()) + + VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO.getValue()) .run(context -> { - VertexAiGeminiChatClient chatClient = context.getBean(VertexAiGeminiChatClient.class); + VertexAiGeminiChatConnector chatClient = context.getBean(VertexAiGeminiChatConnector.class); var systemMessage = new SystemMessage(""" Use Multi-turn function calling. @@ -67,7 +67,7 @@ public class FunctionCallWithFunctionWrapperIT { """); var userMessage = new UserMessage("What's the weather like in San Francisco, Paris and in Tokyo?"); - ChatResponse response = chatClient.call(new Prompt(List.of(systemMessage, userMessage), + ChatResponse response = chatClient.execute(new Prompt(List.of(systemMessage, userMessage), VertexAiGeminiChatOptions.builder().withFunction("WeatherInfo").build())); logger.info("Response: {}", response); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/tool/FunctionCallWithPromptFunctionIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/tool/FunctionCallWithPromptFunctionIT.java index b654fb124..259732523 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/tool/FunctionCallWithPromptFunctionIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/gemini/tool/FunctionCallWithPromptFunctionIT.java @@ -29,7 +29,7 @@ import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.function.FunctionCallbackWrapper; import org.springframework.ai.model.function.FunctionCallbackWrapper.Builder.SchemaType; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatConnector; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -51,10 +51,10 @@ public class FunctionCallWithPromptFunctionIT { void functionCallTest() { contextRunner .withPropertyValues("spring.ai.vertex.ai.gemini.chat.options.model=" - + VertexAiGeminiChatClient.ChatModel.GEMINI_PRO.getValue()) + + VertexAiGeminiChatConnector.ChatModel.GEMINI_PRO.getValue()) .run(context -> { - VertexAiGeminiChatClient chatClient = context.getBean(VertexAiGeminiChatClient.class); + VertexAiGeminiChatConnector chatClient = context.getBean(VertexAiGeminiChatConnector.class); var systemMessage = new SystemMessage(""" Use Multi-turn function calling. @@ -72,7 +72,7 @@ public class FunctionCallWithPromptFunctionIT { .build())) .build(); - ChatResponse response = chatClient.call(new Prompt(List.of(systemMessage, userMessage), promptOptions)); + ChatResponse response = chatClient.execute(new Prompt(List.of(systemMessage, userMessage), promptOptions)); logger.info("Response: {}", response); @@ -80,7 +80,7 @@ public class FunctionCallWithPromptFunctionIT { // Verify that no function call is made. response = chatClient - .call(new Prompt(List.of(systemMessage, userMessage), VertexAiGeminiChatOptions.builder().build())); + .execute(new Prompt(List.of(systemMessage, userMessage), VertexAiGeminiChatOptions.builder().build())); logger.info("Response: {}", response); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPaLm2AutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPaLm2AutoConfigurationIT.java index 0ea8f663e..b7c079b06 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPaLm2AutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPaLm2AutoConfigurationIT.java @@ -23,7 +23,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.springframework.ai.embedding.EmbeddingResponse; -import org.springframework.ai.vertexai.palm2.VertexAiPaLm2ChatClient; +import org.springframework.ai.vertexai.palm2.VertexAiPaLm2ChatConnector; import org.springframework.ai.vertexai.palm2.VertexAiPaLm2EmbeddingClient; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; @@ -48,9 +48,9 @@ public class VertexAiPaLm2AutoConfigurationIT { @Test void generate() { contextRunner.run(context -> { - VertexAiPaLm2ChatClient client = context.getBean(VertexAiPaLm2ChatClient.class); + VertexAiPaLm2ChatConnector client = context.getBean(VertexAiPaLm2ChatConnector.class); - String response = client.call("Hello"); + String response = client.execute("Hello"); assertThat(response).isNotEmpty(); logger.info("Response: " + response); @@ -102,19 +102,19 @@ public class VertexAiPaLm2AutoConfigurationIT { // Disable the chat auto-configuration. contextRunner.withPropertyValues("spring.ai.vertex.ai.chat.enabled=false").run(context -> { assertThat(context.getBeansOfType(VertexAiPlam2ChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(VertexAiPaLm2ChatClient.class)).isEmpty(); + assertThat(context.getBeansOfType(VertexAiPaLm2ChatConnector.class)).isEmpty(); }); // The chat auto-configuration is enabled by default. contextRunner.run(context -> { assertThat(context.getBeansOfType(VertexAiPlam2ChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(VertexAiPaLm2ChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(VertexAiPaLm2ChatConnector.class)).isNotEmpty(); }); // Explicitly enable the chat auto-configuration. contextRunner.withPropertyValues("spring.ai.vertex.ai.chat.enabled=true").run(context -> { assertThat(context.getBeansOfType(VertexAiPlam2ChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(VertexAiPaLm2ChatClient.class)).isNotEmpty(); + assertThat(context.getBeansOfType(VertexAiPaLm2ChatConnector.class)).isNotEmpty(); }); } diff --git a/spring-ai-test/src/main/java/org/springframework/ai/evaluation/BasicEvaluationTest.java b/spring-ai-test/src/main/java/org/springframework/ai/evaluation/BasicEvaluationTest.java index bdc0750bd..9ac424dcf 100644 --- a/spring-ai-test/src/main/java/org/springframework/ai/evaluation/BasicEvaluationTest.java +++ b/spring-ai-test/src/main/java/org/springframework/ai/evaluation/BasicEvaluationTest.java @@ -17,7 +17,7 @@ package org.springframework.ai.evaluation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.PromptTemplate; @@ -38,7 +38,7 @@ public class BasicEvaluationTest { private static final Logger logger = LoggerFactory.getLogger(BasicEvaluationTest.class); @Autowired - protected ChatClient openAiChatClient; + protected ChatConnector openAiChatConnector; @Value("classpath:/prompts/spring/test/evaluation/qa-evaluator-accurate-answer.st") protected Resource qaEvaluatorAccurateAnswerResource; @@ -68,12 +68,12 @@ public class BasicEvaluationTest { } Message userMessage = userPromptTemplate.createMessage(); Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - String yesOrNo = openAiChatClient.call(prompt).getResult().getOutput().getContent(); + String yesOrNo = openAiChatConnector.execute(prompt).getResult().getOutput().getContent(); logger.info("Is Answer related to question: " + yesOrNo); if (yesOrNo.equalsIgnoreCase("no")) { SystemMessage notRelatedSystemMessage = new SystemMessage(qaEvaluatorNotRelatedResource); prompt = new Prompt(List.of(userMessage, notRelatedSystemMessage)); - String reasonForFailure = openAiChatClient.call(prompt).getResult().getOutput().getContent(); + String reasonForFailure = openAiChatConnector.execute(prompt).getResult().getOutput().getContent(); fail(reasonForFailure); } else { diff --git a/vector-stores/spring-ai-hanadb-store/src/test/java/org/springframework/ai/vectorstore/CricketWorldCupHanaController.java b/vector-stores/spring-ai-hanadb-store/src/test/java/org/springframework/ai/vectorstore/CricketWorldCupHanaController.java index ad3f954a7..2ef86212e 100644 --- a/vector-stores/spring-ai-hanadb-store/src/test/java/org/springframework/ai/vectorstore/CricketWorldCupHanaController.java +++ b/vector-stores/spring-ai-hanadb-store/src/test/java/org/springframework/ai/vectorstore/CricketWorldCupHanaController.java @@ -17,7 +17,7 @@ package org.springframework.ai.vectorstore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.connector.ChatConnector; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.SystemPromptTemplate; @@ -51,11 +51,11 @@ public class CricketWorldCupHanaController { private final VectorStore hanaCloudVectorStore; - private final ChatClient chatClient; + private final ChatConnector chatConnector; @Autowired - public CricketWorldCupHanaController(ChatClient chatClient, VectorStore hanaCloudVectorStore) { - this.chatClient = chatClient; + public CricketWorldCupHanaController(ChatConnector chatConnector, VectorStore hanaCloudVectorStore) { + this.chatConnector = chatConnector; this.hanaCloudVectorStore = hanaCloudVectorStore; } @@ -88,7 +88,7 @@ public class CricketWorldCupHanaController { var userMessage = new UserMessage(message); Prompt prompt = new Prompt(List.of(similarDocsMessage, userMessage)); - String generation = chatClient.call(prompt).getResult().getOutput().getContent(); + String generation = chatConnector.execute(prompt).getResult().getOutput().getContent(); logger.info("Generation: {}", generation); return Map.of("generation", generation); }