spring-ai
spring-ai copied to clipboard
RetrievalAugmentationAdvisor doesn't seem to be compatible with Azure AI Search
trafficstars
Bug description I put test execution files like logs and junit-result files into an Azure AI Search vectorstore but the question "Analyze the test execution of testsuite 2450228." gives me an exception:
2025-04-25T16:47:39.098+02:00[0;39m [32m INFO[0;39m [35m17264[0;39m [2m--- [ai] [ ai-advisor-2] [0;39m[36mc.i.iste.ai.genai.ChatConfiguration [0;39m [2m:[0;39m >>> [Retrieval] Extracted testSuiteId: 2450228
[2m2025-04-25T16:47:39.143+02:00[0;39m [32m INFO[0;39m [35m17264[0;39m [2m--- [ai] [ ai-advisor-2] [0;39m[36mc.i.iste.ai.genai.ChatConfiguration [0;39m [2m:[0;39m >>> [Retrieval] Applying filter for testSuiteId: 2450228
[2m2025-04-25T16:47:39.719+02:00[0;39m [31mERROR[0;39m [35m17264[0;39m [2m--- [ai] [ ai-advisor-2] [0;39m[36mc.a.c.i.MethodHandleReflectiveInvoker [0;39m [2m:[0;39m Missing required property/properties: message
[2m2025-04-25T16:47:39.719+02:00[0;39m [33m WARN[0;39m [35m17264[0;39m [2m--- [ai] [ ai-advisor-2] [0;39m[36mc.a.c.i.s.HttpResponseBodyDecoder [0;39m [2m:[0;39m Failed to deserialize the error entity.
java.lang.IllegalStateException: Missing required property/properties: message
[2m2025-04-25T16:47:39.720+02:00[0;39m [31mERROR[0;39m [35m17264[0;39m [2m--- [ai] [ ai-advisor-2] [0;39m[36mc.a.s.d.implementation.util.Utility [0;39m [2m:[0;39m Status code 400, "{"error":{"code":"","message":"Invalid expression: Could not find a property named 'meta_testSuiteId' on type 'search.document'.\r\nParameter name: $filter"}}"
[2m2025-04-25T16:47:39.722+02:00[0;39m [31mERROR[0;39m [35m17264[0;39m [2m--- [ai] [oundedElastic-5] [0;39m[36mo.s.ai.chat.model.MessageAggregator [0;39m [2m:[0;39m Aggregation Error
java.lang.IllegalStateException: Stream processing failed
at org.springframework.ai.chat.client.advisor.api.BaseAdvisor.lambda$aroundStream$1(BaseAdvisor.java:68) ~[spring-ai-client-chat-1.0.0-M7.jar:1.0.0-M7]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94) ~[reactor-core-3.7.4.jar:3.7.4]
at reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:134) ~[reactor-core-3.7.4.jar:3.7.4]
at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onError(MonoFlatMapMany.java:205) ~[reactor-core-3.7.4.jar:3.7.4]
at reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:134) ~[reactor-core-3.7.4.jar:3.7.4]
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114) ~[reactor-core-3.7.4.jar:3.7.4]
at reactor.core.publisher.FluxSubscribeOnValue$ScheduledScalar.run(FluxSubscribeOnValue.java:181) ~[reactor-core-3.7.4.jar:3.7.4]
at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:68) ~[reactor-core-3.7.4.jar:3.7.4]
at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:28) ~[reactor-core-3.7.4.jar:3.7.4]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) ~[na:na]
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
Caused by: java.util.concurrent.CompletionException: com.azure.core.exception.HttpResponseException: Status code 400, "{"error":{"code":"","message":"Invalid expression: Could not find a property named 'meta_testSuiteId' on type 'search.document'.\r\nParameter name: $filter"}}"
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1770) ~[na:na]
at io.micrometer.context.ContextSnapshot.lambda$wrap$0(ContextSnapshot.java:91) ~[context-propagation-1.1.2.jar:1.1.2]
... 3 common frames omitted
Caused by: com.azure.core.exception.HttpResponseException: Status code 400, "{"error":{"code":"","message":"Invalid expression: Could not find a property named 'meta_testSuiteId' on type 'search.document'.\r\nParameter name: $filter"}}"
at com.azure.core.implementation.http.rest.RestProxyBase.instantiateUnexpectedException(RestProxyBase.java:381) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.implementation.http.rest.SyncRestProxy.ensureExpectedStatus(SyncRestProxy.java:133) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.implementation.http.rest.SyncRestProxy.handleRestReturnType(SyncRestProxy.java:211) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.implementation.http.rest.SyncRestProxy.invoke(SyncRestProxy.java:86) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.implementation.http.rest.RestProxyBase.invoke(RestProxyBase.java:124) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.http.rest.RestProxy.invoke(RestProxy.java:95) ~[azure-core-1.55.3.jar:1.55.3]
at jdk.proxy2/jdk.proxy2.$Proxy135.searchPostSync(Unknown Source) ~[na:na]
at com.azure.search.documents.implementation.DocumentsImpl.searchPostWithResponse(DocumentsImpl.java:618) ~[azure-search-documents-11.6.1.jar:11.6.1]
at com.azure.search.documents.SearchClient.lambda$search$4(SearchClient.java:808) ~[azure-search-documents-11.6.1.jar:11.6.1]
at com.azure.search.documents.implementation.util.Utility.executeRestCallWithExceptionHandling(Utility.java:192) ~[azure-search-documents-11.6.1.jar:11.6.1]
at com.azure.search.documents.SearchClient.search(SearchClient.java:807) ~[azure-search-documents-11.6.1.jar:11.6.1]
at com.azure.search.documents.SearchClient.lambda$search$2(SearchClient.java:794) ~[azure-search-documents-11.6.1.jar:11.6.1]
at com.azure.search.documents.SearchClient.lambda$search$3(SearchClient.java:795) ~[azure-search-documents-11.6.1.jar:11.6.1]
at com.azure.search.documents.util.SearchPagedIterable.lambda$new$0(SearchPagedIterable.java:62) ~[azure-search-documents-11.6.1.jar:11.6.1]
at com.azure.core.util.paging.ContinuablePagedByIteratorBase.requestPage(ContinuablePagedByIteratorBase.java:104) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.util.paging.ContinuablePagedByItemIterable$ContinuablePagedByItemIterator.<init>(ContinuablePagedByItemIterable.java:83) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.util.paging.ContinuablePagedByItemIterable.iterator(ContinuablePagedByItemIterable.java:58) ~[azure-core-1.55.3.jar:1.55.3]
at java.base/java.lang.Iterable.spliterator(Iterable.java:101) ~[na:na]
at com.azure.core.util.paging.ContinuablePagedIterable.stream(ContinuablePagedIterable.java:85) ~[azure-core-1.55.3.jar:1.55.3]
at org.springframework.ai.vectorstore.azure.AzureVectorStore.doSimilaritySearch(AzureVectorStore.java:236) ~[spring-ai-azure-store-1.0.0-M7.jar:1.0.0-M7]
at org.springframework.ai.vectorstore.observation.AbstractObservationVectorStore.lambda$similaritySearch$7(AbstractObservationVectorStore.java:126) ~[spring-ai-vector-store-1.0.0-M7.jar:1.0.0-M7]
at io.micrometer.observation.Observation.observe(Observation.java:564) ~[micrometer-observation-1.14.5.jar:1.14.5]
at org.springframework.ai.vectorstore.observation.AbstractObservationVectorStore.similaritySearch(AbstractObservationVectorStore.java:125) ~[spring-ai-vector-store-1.0.0-M7.jar:1.0.0-M7]
at com.intershop.iste.ai.genai.ChatConfiguration.lambda$0(ChatConfiguration.java:224) ~[main/:na]
at org.springframework.ai.rag.advisor.RetrievalAugmentationAdvisor.getDocumentsForQuery(RetrievalAugmentationAdvisor.java:147) ~[spring-ai-rag-1.0.0-M7.jar:1.0.0-M7]
at org.springframework.ai.rag.advisor.RetrievalAugmentationAdvisor.lambda$before$0(RetrievalAugmentationAdvisor.java:124) ~[spring-ai-rag-1.0.0-M7.jar:1.0.0-M7]
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) ~[na:na]
... 4 common frames omitted
Caused by: java.io.IOException: java.lang.IllegalStateException: Missing required property/properties: message
at com.azure.core.implementation.ReflectionSerializable.deserializeAsJsonSerializable(ReflectionSerializable.java:164) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.implementation.serializer.HttpResponseBodyDecoder.deserialize(HttpResponseBodyDecoder.java:169) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.implementation.serializer.HttpResponseBodyDecoder.deserializeBody(HttpResponseBodyDecoder.java:150) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.implementation.serializer.HttpResponseBodyDecoder.decodeByteArray(HttpResponseBodyDecoder.java:67) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.implementation.serializer.HttpResponseDecoder$HttpDecodedResponse.getDecodedBody(HttpResponseDecoder.java:93) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.implementation.http.rest.SyncRestProxy.ensureExpectedStatus(SyncRestProxy.java:131) ~[azure-core-1.55.3.jar:1.55.3]
... 29 common frames omitted
Caused by: java.lang.IllegalStateException: Missing required property/properties: message
at com.azure.search.documents.implementation.models.SearchError.lambda$fromJson$1(SearchError.java:122) ~[azure-search-documents-11.6.1.jar:11.6.1]
at com.azure.json.JsonReader.readMapOrObject(JsonReader.java:554) ~[azure-json-1.5.0.jar:1.5.0]
at com.azure.json.JsonReader.readObject(JsonReader.java:458) ~[azure-json-1.5.0.jar:1.5.0]
at com.azure.search.documents.implementation.models.SearchError.fromJson(SearchError.java:88) ~[azure-search-documents-11.6.1.jar:11.6.1]
at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:733) ~[na:na]
at com.azure.core.implementation.MethodHandleReflectiveInvoker.invokeStatic(MethodHandleReflectiveInvoker.java:26) ~[azure-core-1.55.3.jar:1.55.3]
at com.azure.core.implementation.ReflectionSerializable.deserializeAsJsonSerializable(ReflectionSerializable.java:159) ~[azure-core-1.55.3.jar:1.55.3]
... 34 common frames omitted
[2m2025-04-25T16:47:39.724+02:00[0;39m [31mERROR[0;39m [35m17264[0;39m [2m--- [ai] [oundedElastic-5] [0;39m[36mo.s.ai.chat.model.MessageAggregator [0;39m [2m:[0;39m Aggregation Error
Environment Please provide as many details as possible: Spring AI version, Java version, which vector store you use if any, etc
Steps to reproduce Here is my code for evaluation:
@Bean
AzureVectorStore vectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel)
{
var vectorStore = AzureVectorStore.builder(searchIndexClient, embeddingModel)
.filterMetadataFields(
List.of(AzureVectorStore.MetadataField.int64("testSuiteId")));
vectorStore.indexName("test-execution-logs");
return vectorStore.build();
}
@Bean
RetrievalAugmentationAdvisor retrievalAugmentationAdvisor(AzureVectorStore vectorStore)
{
ContextualQueryAugmenter queryAugmenter = ContextualQueryAugmenter.builder().allowEmptyContext(true).build();
return RetrievalAugmentationAdvisor.builder().documentRetriever(query -> {
log.info(">>> [Retrieval] Incoming user query: " + query.text());
String userQueryText = query.text();
Long extractedTestSuiteId = null;
// 1. Testsuite-ID aus der Query extrahieren (Beispiel mit Regex)
Matcher matcher = TEST_SUITE_ID_PATTERN.matcher(userQueryText);
if (matcher.find())
{
try
{
extractedTestSuiteId = Long.parseLong(matcher.group(1)); // Gruppe 1 enthält die Ziffern
log.info(">>> [Retrieval] Extracted testSuiteId: {}", extractedTestSuiteId);
}
catch(NumberFormatException e)
{
log.warn(">>> [Retrieval] Found potential ID pattern but failed to parse as Long: {}",
matcher.group(1));
}
}
// 2. SearchRequest erstellen
SearchRequest.Builder requestBuilder = SearchRequest.builder()
.query(userQueryText)
.topK(5)
.similarityThreshold(0.50);
// 3. Filter hinzufügen, WENN eine ID extrahiert wurde
if (extractedTestSuiteId != null)
{
var filterExpressionBuilder = new FilterExpressionBuilder();
//Expression expression = filterExpressionBuilder.eq("testSuiteId", extractedTestSuiteId).build();
var expression = "testSuiteId == " + extractedTestSuiteId;
requestBuilder = requestBuilder.filterExpression(expression);
log.info(">>> [Retrieval] Applying filter for testSuiteId: {}", extractedTestSuiteId);
}
else
{
log.info(">>> [Retrieval] No testSuiteId found in query, performing broad similarity search.");
}
SearchRequest request = requestBuilder.build();
// 4. Suche mit dem (potenziell gefilterten) Request durchführen
List<Document> docs = vectorStore.similaritySearch(request); // Direkter Aufruf am vectorStore
// Logging der Ergebnisse (optional verbessert)
if (docs.isEmpty())
{
log.info(">>> [Retrieval] No documents found for the query and filter criteria.");
}
else
{
log.info(">>> [Retrieval] Retrieved {} documents:", docs.size());
docs.forEach(doc -> {
// Log auch Metadaten, um zu prüfen, ob der Filter funktionierte
log.info(" - [ID: {}, MetaTS: {}, File: {}] Snippet: {}", doc.getId(),
doc.getMetadata().get("testSuiteId"), // Zeigt die ID des gefundenen Dokuments
doc.getMetadata().get("fileName"),
doc.getText().substring(0, Math.min(doc.getText().length(), 100)).replace('\n', ' ')
+ "...");
});
}
return docs; // Gibt die gefilterten oder ungefilterten Dokumente zurück
}).queryAugmenter(queryAugmenter).build();
}
@Bean
ChatClient chatClient(ChatMemory chatMemory, AzureOpenAiChatModel azureOpenAiChatModel,
RetrievalAugmentationAdvisor retrievalAugmentationAdvisor)
{
ChatClient.Builder builder = ChatClient.builder(azureOpenAiChatModel);
// @formatter:off
return builder
.defaultAdvisors(
// Chat memory helps us keep context when using the chatbot for up to 10 previous messages.
retrievalAugmentationAdvisor,
new MessageChatMemoryAdvisor(chatMemory, DEFAULT_CHAT_MEMORY_CONVERSATION_ID, 10), // CHAT MEMORY
new SimpleLoggerAdvisor()
)
.defaultSystem(getSystemPrompt())
//.defaultTools(isteAiDataProvider)
//.defaultFunctions("getTestSuites", "getStrackTraceOverview")
.build();
// @formatter:on
}
1.0.0-M7 is used:
ext {
springAiVersion = '1.0.0-M7'
vaadinVersion = '24.6.6'
viritinVersion = '2.13.0'
springCloudVersion = '2024.0.1'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
mavenBom "org.springframework.ai:spring-ai-bom:${springAiVersion}"
mavenBom "com.vaadin:vaadin-bom:$vaadinVersion"
}
}
dependencies {
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-actuator'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-hateoas'
implementation('com.vaadin:vaadin-spring-boot-starter')
implementation group: 'com.vaadin', name: 'vaadin-lumo-theme', version: "${vaadinVersion}"
implementation group: 'in.virit', name: 'viritin', version: "${viritinVersion}"
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-jdbc'
implementation(group: 'org.springframework.ai', name: 'spring-ai-starter-model-azure-openai')
implementation group: 'org.springframework.ai', name: 'spring-ai-autoconfigure-model-azure-openai'
implementation group: 'org.springframework.ai', name: 'spring-ai-starter-vector-store-azure'
implementation group: 'org.springframework.ai', name: 'spring-ai-autoconfigure-vector-store-azure'
implementation group: 'org.springframework.ai', name: 'spring-ai-rag'
implementation group: 'org.springframework.ai', name: 'spring-ai-azure-store'
implementation group: 'com.azure', name: 'azure-core-http-okhttp', version: "1.12.10"
Expected behavior I get an evaluation of the testexecution.