Skip to content

Commit e644bf7

Browse files
sobychackomarkpollack
authored andcommitted
Add Azure Search user-agent, test OpenAI client header
* Adding test to verify the user-agent header in the Azure OpenAi chat client * Adding the user-agent header to the search client in Azure vector store
1 parent 035036c commit e644bf7

File tree

2 files changed

+45
-7
lines changed

2 files changed

+45
-7
lines changed

spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/azure/AzureVectorStoreAutoConfiguration.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.ai.autoconfigure.vectorstore.azure;
1818

1919
import com.azure.core.credential.AzureKeyCredential;
20+
import com.azure.core.util.ClientOptions;
2021
import com.azure.search.documents.indexes.SearchIndexClient;
2122
import com.azure.search.documents.indexes.SearchIndexClientBuilder;
2223

@@ -47,11 +48,16 @@
4748
@ConditionalOnProperty(prefix = "spring.ai.vectorstore.azure", value = { "url", "api-key", "index-name" })
4849
public class AzureVectorStoreAutoConfiguration {
4950

51+
private final static String APPLICATION_ID = "spring-ai";
52+
5053
@Bean
5154
@ConditionalOnMissingBean
5255
public SearchIndexClient searchIndexClient(AzureVectorStoreProperties properties) {
56+
ClientOptions clientOptions = new ClientOptions();
57+
clientOptions.setApplicationId(APPLICATION_ID);
5358
return new SearchIndexClientBuilder().endpoint(properties.getUrl())
5459
.credential(new AzureKeyCredential(properties.getApiKey()))
60+
.clientOptions(clientOptions)
5561
.buildClient();
5662
}
5763

spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/azure/AzureOpenAiAutoConfigurationIT.java

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 - 2024 the original author or authors.
2+
* Copyright 2023-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,8 +33,20 @@
3333
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
3434
import org.springframework.core.io.ClassPathResource;
3535
import org.springframework.core.io.Resource;
36+
import org.springframework.util.ReflectionUtils;
37+
38+
import com.azure.ai.openai.OpenAIClient;
39+
import com.azure.ai.openai.implementation.OpenAIClientImpl;
40+
import com.azure.core.http.HttpHeader;
41+
import com.azure.core.http.HttpHeaderName;
42+
import com.azure.core.http.HttpMethod;
43+
import com.azure.core.http.HttpPipeline;
44+
import com.azure.core.http.HttpRequest;
45+
import com.azure.core.http.HttpResponse;
3646
import reactor.core.publisher.Flux;
3747

48+
import java.lang.reflect.Field;
49+
import java.net.URI;
3850
import java.util.List;
3951
import java.util.Map;
4052
import java.util.stream.Collectors;
@@ -44,11 +56,12 @@
4456
/**
4557
* @author Christian Tzolov
4658
* @author Piotr Olaszewski
59+
* @author Soby Chacko
4760
* @since 0.8.0
4861
*/
4962
@EnabledIfEnvironmentVariable(named = "AZURE_OPENAI_API_KEY", matches = ".+")
5063
@EnabledIfEnvironmentVariable(named = "AZURE_OPENAI_ENDPOINT", matches = ".+")
51-
public class AzureOpenAiAutoConfigurationIT {
64+
class AzureOpenAiAutoConfigurationIT {
5265

5366
private static String CHAT_MODEL_NAME = "gpt-4o";
5467

@@ -79,7 +92,7 @@ public class AzureOpenAiAutoConfigurationIT {
7992
"Tell me about 3 famous pirates from the Golden Age of Piracy and why they did.");
8093

8194
@Test
82-
public void chatCompletion() {
95+
void chatCompletion() {
8396
contextRunner.run(context -> {
8497
AzureOpenAiChatModel chatModel = context.getBean(AzureOpenAiChatModel.class);
8598
ChatResponse response = chatModel.call(new Prompt(List.of(userMessage, systemMessage)));
@@ -88,7 +101,26 @@ public void chatCompletion() {
88101
}
89102

90103
@Test
91-
public void chatCompletionStreaming() {
104+
void httpRequestContainsUserAgentHeader() {
105+
contextRunner.run(context -> {
106+
OpenAIClient openAIClient = context.getBean(OpenAIClient.class);
107+
Field serviceClientField = ReflectionUtils.findField(OpenAIClient.class, "serviceClient");
108+
assertThat(serviceClientField).isNotNull();
109+
ReflectionUtils.makeAccessible(serviceClientField);
110+
OpenAIClientImpl oaci = (OpenAIClientImpl) ReflectionUtils.getField(serviceClientField, openAIClient);
111+
assertThat(oaci).isNotNull();
112+
HttpPipeline httpPipeline = oaci.getHttpPipeline();
113+
HttpResponse httpResponse = httpPipeline
114+
.send(new HttpRequest(HttpMethod.POST, new URI(System.getenv("AZURE_OPENAI_ENDPOINT")).toURL()))
115+
.block();
116+
assertThat(httpResponse).isNotNull();
117+
HttpHeader httpHeader = httpResponse.getRequest().getHeaders().get(HttpHeaderName.USER_AGENT);
118+
assertThat(httpHeader.getValue().startsWith("spring-ai azsdk-java-azure-ai-openai/")).isTrue();
119+
});
120+
}
121+
122+
@Test
123+
void chatCompletionStreaming() {
92124
contextRunner.run(context -> {
93125

94126
AzureOpenAiChatModel chatModel = context.getBean(AzureOpenAiChatModel.class);
@@ -140,7 +172,7 @@ void transcribe() {
140172
}
141173

142174
@Test
143-
public void chatActivation() {
175+
void chatActivation() {
144176

145177
// Disable the chat auto-configuration.
146178
contextRunner.withPropertyValues("spring.ai.azure.openai.chat.enabled=false").run(context -> {
@@ -159,7 +191,7 @@ public void chatActivation() {
159191
}
160192

161193
@Test
162-
public void embeddingActivation() {
194+
void embeddingActivation() {
163195

164196
// Disable the embedding auto-configuration.
165197
contextRunner.withPropertyValues("spring.ai.azure.openai.embedding.enabled=false").run(context -> {
@@ -178,7 +210,7 @@ public void embeddingActivation() {
178210
}
179211

180212
@Test
181-
public void audioTranscriptionActivation() {
213+
void audioTranscriptionActivation() {
182214

183215
// Disable the transcription auto-configuration.
184216
contextRunner.withPropertyValues("spring.ai.azure.openai.audio.transcription.enabled=false").run(context -> {

0 commit comments

Comments
 (0)