diff --git a/advisors/spring-ai-advisors/pom.xml b/advisors/spring-ai-advisors/pom.xml
new file mode 100644
index 000000000..75402280d
--- /dev/null
+++ b/advisors/spring-ai-advisors/pom.xml
@@ -0,0 +1,100 @@
+
+
+
+
+ 4.0.0
+
+ org.springframework.ai
+ spring-ai
+ 1.0.0-SNAPSHOT
+ ../../pom.xml
+
+ spring-ai-advisors
+ jar
+ Spring AI Advisors
+ Chat client advisors for Spring AI
+ https://github.com/spring-projects/spring-ai
+
+
+ https://github.com/spring-projects/spring-ai
+ git://github.com/spring-projects/spring-ai.git
+ git@github.com:spring-projects/spring-ai.git
+
+
+
+ 17
+ 17
+
+
+
+
+
+ org.springframework.ai
+ spring-ai-core
+ ${project.parent.version}
+
+
+
+ org.springframework.ai
+ spring-ai-vector-store
+ ${project.parent.version}
+
+
+
+
+ org.springframework
+ spring-context
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+ io.projectreactor
+ reactor-core
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ true
+
+
+
+ org.jetbrains.kotlin
+ kotlin-reflect
+ true
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ com.fasterxml.jackson.module
+ jackson-module-kotlin
+ test
+
+
+
+
diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/client/advisor/QuestionAnswerAdvisor.java b/advisors/spring-ai-advisors/src/main/java/org/springframework/ai/chat/client/advisor/QuestionAnswerAdvisor.java
similarity index 100%
rename from spring-ai-core/src/main/java/org/springframework/ai/chat/client/advisor/QuestionAnswerAdvisor.java
rename to advisors/spring-ai-advisors/src/main/java/org/springframework/ai/chat/client/advisor/QuestionAnswerAdvisor.java
diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/client/advisor/VectorStoreChatMemoryAdvisor.java b/advisors/spring-ai-advisors/src/main/java/org/springframework/ai/chat/client/advisor/VectorStoreChatMemoryAdvisor.java
similarity index 100%
rename from spring-ai-core/src/main/java/org/springframework/ai/chat/client/advisor/VectorStoreChatMemoryAdvisor.java
rename to advisors/spring-ai-advisors/src/main/java/org/springframework/ai/chat/client/advisor/VectorStoreChatMemoryAdvisor.java
diff --git a/advisors/spring-ai-advisors/src/main/java/org/springframework/ai/chat/client/advisor/package-info.java b/advisors/spring-ai-advisors/src/main/java/org/springframework/ai/chat/client/advisor/package-info.java
new file mode 100644
index 000000000..66e95c047
--- /dev/null
+++ b/advisors/spring-ai-advisors/src/main/java/org/springframework/ai/chat/client/advisor/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+/**
+ * Spring AI chat client advisors package.
+ */
+@NonNullApi
+@NonNullFields
+package org.springframework.ai.chat.client.advisor;
+
+import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
diff --git a/spring-ai-core/src/test/java/org/springframework/ai/chat/client/advisor/QuestionAnswerAdvisorTests.java b/advisors/spring-ai-advisors/src/test/java/org/springframework/ai/chat/client/advisor/QuestionAnswerAdvisorTests.java
similarity index 80%
rename from spring-ai-core/src/test/java/org/springframework/ai/chat/client/advisor/QuestionAnswerAdvisorTests.java
rename to advisors/spring-ai-advisors/src/test/java/org/springframework/ai/chat/client/advisor/QuestionAnswerAdvisorTests.java
index 220479c5c..048d35475 100644
--- a/spring-ai-core/src/test/java/org/springframework/ai/chat/client/advisor/QuestionAnswerAdvisorTests.java
+++ b/advisors/spring-ai-advisors/src/test/java/org/springframework/ai/chat/client/advisor/QuestionAnswerAdvisorTests.java
@@ -20,6 +20,7 @@ import java.time.Duration;
import java.util.List;
import java.util.Map;
+import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
@@ -128,19 +129,19 @@ public class QuestionAnswerAdvisorTests {
//formatter:on
// Ensure the metadata is correctly copied over
- assertThat(response.getMetadata().getModel()).isEqualTo("model1");
- assertThat(response.getMetadata().getId()).isEqualTo("678");
- assertThat(response.getMetadata().getRateLimit().getRequestsLimit()).isEqualTo(5L);
- assertThat(response.getMetadata().getRateLimit().getRequestsRemaining()).isEqualTo(6L);
- assertThat(response.getMetadata().getRateLimit().getRequestsReset()).isEqualTo(Duration.ofSeconds(7));
- assertThat(response.getMetadata().getRateLimit().getTokensLimit()).isEqualTo(8L);
- assertThat(response.getMetadata().getRateLimit().getTokensRemaining()).isEqualTo(8L);
- assertThat(response.getMetadata().getRateLimit().getTokensReset()).isEqualTo(Duration.ofSeconds(9));
- assertThat(response.getMetadata().getUsage().getPromptTokens()).isEqualTo(6L);
- assertThat(response.getMetadata().getUsage().getCompletionTokens()).isEqualTo(7L);
- assertThat(response.getMetadata().getUsage().getTotalTokens()).isEqualTo(6L + 7L);
- assertThat(response.getMetadata().get("key6").toString()).isEqualTo("value6");
- assertThat(response.getMetadata().get("key1").toString()).isEqualTo("value1");
+ Assertions.assertThat(response.getMetadata().getModel()).isEqualTo("model1");
+ Assertions.assertThat(response.getMetadata().getId()).isEqualTo("678");
+ Assertions.assertThat(response.getMetadata().getRateLimit().getRequestsLimit()).isEqualTo(5L);
+ Assertions.assertThat(response.getMetadata().getRateLimit().getRequestsRemaining()).isEqualTo(6L);
+ Assertions.assertThat(response.getMetadata().getRateLimit().getRequestsReset()).isEqualTo(Duration.ofSeconds(7));
+ Assertions.assertThat(response.getMetadata().getRateLimit().getTokensLimit()).isEqualTo(8L);
+ Assertions.assertThat(response.getMetadata().getRateLimit().getTokensRemaining()).isEqualTo(8L);
+ Assertions.assertThat(response.getMetadata().getRateLimit().getTokensReset()).isEqualTo(Duration.ofSeconds(9));
+ Assertions.assertThat(response.getMetadata().getUsage().getPromptTokens()).isEqualTo(6L);
+ Assertions.assertThat(response.getMetadata().getUsage().getCompletionTokens()).isEqualTo(7L);
+ Assertions.assertThat(response.getMetadata().getUsage().getTotalTokens()).isEqualTo(6L + 7L);
+ Assertions.assertThat(response.getMetadata().get("key6").toString()).isEqualTo("value6");
+ Assertions.assertThat(response.getMetadata().get("key1").toString()).isEqualTo("value1");
String content = response.getResult().getOutput().getText();
@@ -171,9 +172,9 @@ public class QuestionAnswerAdvisorTests {
the user that you can't answer the question.
""");
- assertThat(this.vectorSearchCaptor.getValue().getFilterExpression()).isEqualTo(new FilterExpressionBuilder().eq("type", "Spring").build());
- assertThat(this.vectorSearchCaptor.getValue().getSimilarityThreshold()).isEqualTo(0.99d);
- assertThat(this.vectorSearchCaptor.getValue().getTopK()).isEqualTo(6);
+ Assertions.assertThat(this.vectorSearchCaptor.getValue().getFilterExpression()).isEqualTo(new FilterExpressionBuilder().eq("type", "Spring").build());
+ Assertions.assertThat(this.vectorSearchCaptor.getValue().getSimilarityThreshold()).isEqualTo(0.99d);
+ Assertions.assertThat(this.vectorSearchCaptor.getValue().getTopK()).isEqualTo(6);
}
@Test
@@ -201,7 +202,7 @@ public class QuestionAnswerAdvisorTests {
var userPrompt = this.promptCaptor.getValue().getInstructions().get(0).getText();
assertThat(userPrompt).doesNotContain(userTextTemplate);
assertThat(userPrompt).contains(expectedQuery);
- assertThat(this.vectorSearchCaptor.getValue().getQuery()).isEqualTo(expectedQuery);
+ Assertions.assertThat(this.vectorSearchCaptor.getValue().getQuery()).isEqualTo(expectedQuery);
}
@Test
@@ -230,7 +231,7 @@ public class QuestionAnswerAdvisorTests {
var userPrompt = this.promptCaptor.getValue().getInstructions().get(0).getText();
assertThat(userPrompt).doesNotContain(userTextTemplate);
assertThat(userPrompt).contains(expectedQuery);
- assertThat(this.vectorSearchCaptor.getValue().getQuery()).isEqualTo(expectedQuery);
+ Assertions.assertThat(this.vectorSearchCaptor.getValue().getQuery()).isEqualTo(expectedQuery);
}
}
diff --git a/pom.xml b/pom.xml
index 794633983..5e69fa184 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,6 +37,7 @@
spring-ai-model
spring-ai-test
spring-ai-vector-store
+ advisors/spring-ai-advisors
auto-configurations/common/spring-ai-autoconfigure-retry
diff --git a/vector-stores/spring-ai-pgvector-store/pom.xml b/vector-stores/spring-ai-pgvector-store/pom.xml
index 3afcdcdbd..8df1a966d 100644
--- a/vector-stores/spring-ai-pgvector-store/pom.xml
+++ b/vector-stores/spring-ai-pgvector-store/pom.xml
@@ -48,6 +48,13 @@
${project.parent.version}
+
+ org.springframework.ai
+ spring-ai-advisors
+ ${project.parent.version}
+
+
+
com.zaxxer
HikariCP