Skip to content

Commit e5d3cfb

Browse files
ilayaperumalgleijendary
authored andcommitted
Update document for SearchRequest builder changes
Signed-off-by: leijendary <[email protected]>
1 parent 42b2fdb commit e5d3cfb

23 files changed

+203
-137
lines changed

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/advisors.adoc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
The Spring AI Advisors API provides a flexible and powerful way to intercept, modify, and enhance AI-driven interactions in your Spring applications.
66
By leveraging the Advisors API, developers can create more sophisticated, reusable, and maintainable AI components.
77

8-
The key benefits include encapsulating recurring Generative AI patterns, transforming data sent to and from Language Models (LLMs), and providing portability across various models and use cases.
8+
The key benefits include encapsulating recurring Generative AI patterns, transforming data sent to and from Large Language Models (LLMs), and providing portability across various models and use cases.
99

1010
You can configure existing advisors using the xref:api/chatclient.adoc#_advisor_configuration_in_chatclient[ChatClient API] as shown in the following example:
1111

@@ -14,7 +14,7 @@ You can configure existing advisors using the xref:api/chatclient.adoc#_advisor_
1414
var chatClient = ChatClient.builder(chatModel)
1515
.defaultAdvisors(
1616
new MessageChatMemoryAdvisor(chatMemory), // chat-memory advisor
17-
new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()) // RAG advisor
17+
new QuestionAnswerAdvisor(vectorStore) // RAG advisor
1818
)
1919
.build();
2020
@@ -31,6 +31,8 @@ It is recommend to register the advisors at build time using builder's `defaultA
3131

3232
Advisors also participate in the Observability stack, so you can view metrics and traces related to their execution.
3333

34+
xref:ROOT:api/retrieval-augmented-generation.adoc#_questionansweradvisor[Learn about Question Answer Advisor]
35+
3436
== Core Components
3537

3638
The API consists of `CallAroundAdvisor` and `CallAroundAdvisorChain` for non-streaming scenarios, and `StreamAroundAdvisor` and `StreamAroundAdvisorChain` for streaming scenarios.

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chatclient.adoc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ ChatClient.builder(chatModel)
355355
.prompt()
356356
.advisors(
357357
new MessageChatMemoryAdvisor(chatMemory),
358-
new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults())
358+
new QuestionAnswerAdvisor(vectorStore)
359359
)
360360
.user(userText)
361361
.call()
@@ -364,6 +364,8 @@ ChatClient.builder(chatModel)
364364

365365
In this configuration, the `MessageChatMemoryAdvisor` will be executed first, adding the conversation history to the prompt. Then, the `QuestionAnswerAdvisor` will perform its search based on the user's question and the added conversation history, potentially providing more relevant results.
366366

367+
xref:ROOT:api/retrieval-augmented-generation.adoc#_questionansweradvisor[Learn about Question Answer Advisor]
368+
367369
=== Retrieval Augmented Generation
368370

369371
Refer to the xref:_retrieval_augmented_generation[Retrieval Augmented Generation] guide.
@@ -431,7 +433,7 @@ public class CustomerSupportAssistant {
431433
""")
432434
.defaultAdvisors(
433435
new MessageChatMemoryAdvisor(chatMemory), // CHAT MEMORY
434-
new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()), // RAG
436+
new QuestionAnswerAdvisor(vectorStore), // RAG
435437
new SimpleLoggerAdvisor())
436438
.defaultFunctions("getBookingDetails", "changeBooking", "cancelBooking") // FUNCTION CALLING
437439
.build();
@@ -450,7 +452,7 @@ public class CustomerSupportAssistant {
450452
}
451453
----
452454

453-
455+
xref:ROOT:api/retrieval-augmented-generation.adoc#_questionansweradvisor[Learn about Question Answer Advisor]
454456

455457
=== Logging
456458

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/retrieval-augmented-generation.adoc

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,36 @@ Assuming you have already loaded data into a `VectorStore`, you can perform Retr
2626
----
2727
ChatResponse response = ChatClient.builder(chatModel)
2828
.build().prompt()
29-
.advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
29+
.advisors(new QuestionAnswerAdvisor(vectorStore)
3030
.user(userText)
3131
.call()
3232
.chatResponse();
3333
----
3434

35-
In this example, the `SearchRequest.defaults()` will perform a similarity search over all documents in the Vector Database.
35+
In this example, the `QuestionAnswerAdvisor` will perform a similarity search over all documents in the Vector Database.
3636
To restrict the types of documents that are searched, the `SearchRequest` takes an SQL like filter expression that is portable across all `VectorStores`.
3737

38+
This filter expression can be configured when creating the `QuestionAnswerAdvisor` and hence will always apply to all `ChatClient` requests or it can be provided at runtime per request.
39+
40+
Here is how to create an instance of `QuestionAnswerAdvisor` where the threshold is `0.8` and to return the top `6` reulsts.
41+
42+
43+
[source,java]
44+
----
45+
var qaAdvisor = new QuestionAnswerAdvisor(this.vectorStore,
46+
SearchRequest.builder().similarityThreshold(0.8d).topK(6).build());
47+
----
48+
49+
50+
3851
==== Dynamic Filter Expressions
3952

4053
Update the `SearchRequest` filter expression at runtime using the `FILTER_EXPRESSION` advisor context parameter:
4154

4255
[source,java]
4356
----
4457
ChatClient chatClient = ChatClient.builder(chatModel)
45-
.defaultAdvisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
58+
.defaultAdvisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.builder().build()))
4659
.build();
4760
4861
// Update filter expression at runtime

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/testing.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ void testEvaluation() {
7575
7676
ChatResponse response = ChatClient.builder(chatModel)
7777
.build().prompt()
78-
.advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
78+
.advisors(new QuestionAnswerAdvisor(vectorStore))
7979
.user(userText)
8080
.call()
8181
.chatResponse();

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,69 @@ and the related `SearchRequest` builder:
4444
```java
4545
public class SearchRequest {
4646

47-
public final String query;
48-
private int topK = 4;
49-
private double similarityThreshold = SIMILARITY_THRESHOLD_ALL;
50-
private Filter.Expression filterExpression;
47+
public static final double SIMILARITY_THRESHOLD_ACCEPT_ALL = 0.0;
48+
49+
public static final int DEFAULT_TOP_K = 4;
50+
51+
private String query = "";
5152

52-
public static SearchRequest query(String query) { return new SearchRequest(query); }
53+
private int topK = DEFAULT_TOP_K;
5354

54-
private SearchRequest(String query) { this.query = query; }
55+
private double similarityThreshold = SIMILARITY_THRESHOLD_ACCEPT_ALL;
56+
57+
@Nullable
58+
private Filter.Expression filterExpression;
5559

56-
public SearchRequest topK(int topK) {...}
57-
public SearchRequest similarityThreshold(double threshold) {...}
58-
public SearchRequest similarityThresholdAll() {...}
59-
public SearchRequest filterExpression(Filter.Expression expression) {...}
60-
public SearchRequest filterExpression(String textExpression) {...}
60+
public static Builder from(SearchRequest originalSearchRequest) {
61+
return builder().query(originalSearchRequest.getQuery())
62+
.topK(originalSearchRequest.getTopK())
63+
.similarityThreshold(originalSearchRequest.getSimilarityThreshold())
64+
.filterExpression(originalSearchRequest.getFilterExpression());
65+
}
66+
67+
public static class Builder {
68+
69+
private final SearchRequest searchRequest = new SearchRequest();
70+
71+
public Builder query(String query) {
72+
Assert.notNull(query, "Query can not be null.");
73+
this.searchRequest.query = query;
74+
return this;
75+
}
76+
77+
public Builder topK(int topK) {
78+
Assert.isTrue(topK >= 0, "TopK should be positive.");
79+
this.searchRequest.topK = topK;
80+
return this;
81+
}
82+
83+
public Builder similarityThreshold(double threshold) {
84+
Assert.isTrue(threshold >= 0 && threshold <= 1, "Similarity threshold must be in [0,1] range.");
85+
this.searchRequest.similarityThreshold = threshold;
86+
return this;
87+
}
88+
89+
public Builder similarityThresholdAll() {
90+
this.searchRequest.similarityThreshold = 0.0;
91+
return this;
92+
}
93+
94+
public Builder filterExpression(@Nullable Filter.Expression expression) {
95+
this.searchRequest.filterExpression = expression;
96+
return this;
97+
}
98+
99+
public Builder filterExpression(@Nullable String textExpression) {
100+
this.searchRequest.filterExpression = (textExpression != null)
101+
? new FilterExpressionTextParser().parse(textExpression) : null;
102+
return this;
103+
}
104+
105+
public SearchRequest build() {
106+
return this.searchRequest;
107+
}
108+
109+
}
61110

62111
public String getQuery() {...}
63112
public int getTopK() {...}

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/apache-cassandra.adoc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,17 @@ And retrieve documents similar to a query:
142142
[source,java]
143143
----
144144
List<Document> results = vectorStore.similaritySearch(
145-
SearchRequest.query("Spring").topK(5));
145+
SearchRequest.builder().query("Spring").topK(5).build());
146146
----
147147

148148
You can also limit results based on a similarity threshold:
149149

150150
[source,java]
151151
----
152152
List<Document> results = vectorStore.similaritySearch(
153-
SearchRequest.query("Spring")
153+
SearchRequest.builder().query("Spring")
154154
.topK(5)
155-
.similarityThreshold(0.5d));
155+
.similarityThreshold(0.5d).build());
156156
----
157157

158158
=== Advanced Configuration
@@ -192,9 +192,9 @@ For example, you can use either the text expression language:
192192
[source,java]
193193
----
194194
vectorStore.similaritySearch(
195-
SearchRequest.query("The World")
195+
SearchRequest.builder().query("The World")
196196
.topK(5)
197-
.filterExpression("country in ['UK', 'NL'] && year >= 2020"));
197+
.filterExpression("country in ['UK', 'NL'] && year >= 2020").build());
198198
----
199199

200200
or programmatically using the expression DSL:
@@ -208,9 +208,9 @@ Filter.Expression f = new FilterExpressionBuilder()
208208
).build();
209209
210210
vectorStore.similaritySearch(
211-
SearchRequest.query("The World")
211+
SearchRequest.builder().query("The World")
212212
.topK(5)
213-
.filterExpression(f));
213+
.filterExpression(f).build());
214214
----
215215

216216
The portable filter expressions get automatically converted into link:https://cassandra.apache.org/doc/latest/cassandra/developing/cql/index.html[CQL queries].

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/azure-cosmos-db.adoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public class DemoApplication implements CommandLineRunner {
6969
Document document1 = new Document(UUID.randomUUID().toString(), "Sample content1", Map.of("key1", "value1"));
7070
Document document2 = new Document(UUID.randomUUID().toString(), "Sample content2", Map.of("key2", "value2"));
7171
this.vectorStore.add(List.of(document1, document2));
72-
List<Document> results = this.vectorStore.similaritySearch(SearchRequest.query("Sample content").topK(1));
72+
List<Document> results = this.vectorStore.similaritySearch(SearchRequest.builder().query("Sample content").topK(1).build());
7373

7474
log.info("Search results: {}", results);
7575

@@ -139,9 +139,9 @@ Document document2 = new Document("2", "A document about the Netherlands", this.
139139
vectorStore.add(List.of(document1, document2));
140140
141141
FilterExpressionBuilder builder = new FilterExpressionBuilder();
142-
List<Document> results = vectorStore.similaritySearch(SearchRequest.query("The World")
142+
List<Document> results = vectorStore.similaritySearch(SearchRequest.builder().query("The World")
143143
.topK(10)
144-
.filterExpression((this.builder.in("country", "UK", "NL")).build()));
144+
.filterExpression((this.builder.in("country", "UK", "NL")).build()).build());
145145
----
146146

147147
== Setting up Azure Cosmos DB Vector Store without Auto Configuration
@@ -192,7 +192,7 @@ public class DemoApplication implements CommandLineRunner {
192192
Document document2 = new Document(UUID.randomUUID().toString(), "Sample content2", Map.of("key2", "value2"));
193193
this.vectorStore.add(List.of(document1, document2));
194194

195-
List<Document> results = this.vectorStore.similaritySearch(SearchRequest.query("Sample content").topK(1));
195+
List<Document> results = this.vectorStore.similaritySearch(SearchRequest.builder().query("Sample content").topK(1).build());
196196
log.info("Search results: {}", results);
197197
}
198198

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/azure.adoc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ And finally, retrieve documents similar to a query:
169169
[source,java]
170170
----
171171
List<Document> results = vectorStore.similaritySearch(
172-
SearchRequest
172+
SearchRequest.builder()
173173
.query("Spring")
174-
.topK(5));
174+
.topK(5).build());
175175
----
176176

177177
If all goes well, you should retrieve the document containing the text "Spring AI rocks!!".
@@ -185,11 +185,11 @@ For example, you can use either the text expression language:
185185
[source,java]
186186
----
187187
vectorStore.similaritySearch(
188-
SearchRequest
188+
SearchRequest.builder()
189189
.query("The World")
190190
.topK(TOP_K)
191191
.similarityThreshold(SIMILARITY_THRESHOLD)
192-
.filterExpression("country in ['UK', 'NL'] && year >= 2020"));
192+
.filterExpression("country in ['UK', 'NL'] && year >= 2020").build());
193193
----
194194

195195
or programmatically using the expression DSL:
@@ -199,13 +199,13 @@ or programmatically using the expression DSL:
199199
FilterExpressionBuilder b = new FilterExpressionBuilder();
200200
201201
vectorStore.similaritySearch(
202-
SearchRequest
202+
SearchRequest.builder()
203203
.query("The World")
204204
.topK(TOP_K)
205205
.similarityThreshold(SIMILARITY_THRESHOLD)
206206
.filterExpression(b.and(
207207
b.in("country", "UK", "NL"),
208-
b.gte("year", 2020)).build()));
208+
b.gte("year", 2020)).build()).build());
209209
----
210210

211211
The portable filter expressions get automatically converted into the proprietary Azure Search link:https://learn.microsoft.com/en-us/azure/search/search-query-odata-filter[OData filters]. For example, the following portable filter expression:

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/chroma.adoc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ List <Document> documents = List.of(
101101
vectorStore.add(documents);
102102
103103
// Retrieve documents similar to a query
104-
List<Document> results = this.vectorStore.similaritySearch(SearchRequest.query("Spring").topK(5));
104+
List<Document> results = this.vectorStore.similaritySearch(SearchRequest.builder().query("Spring").topK(5).build());
105105
----
106106

107107
=== Configuration properties
@@ -137,11 +137,11 @@ For example, you can use either the text expression language:
137137
[source,java]
138138
----
139139
vectorStore.similaritySearch(
140-
SearchRequest.defaults()
141-
.queryString("The World")
140+
SearchRequest.builder()
141+
.query("The World")
142142
.topK(TOP_K)
143143
.similarityThreshold(SIMILARITY_THRESHOLD)
144-
.filterExpression("author in ['john', 'jill'] && article_type == 'blog'"));
144+
.filterExpression("author in ['john', 'jill'] && article_type == 'blog'").build());
145145
----
146146

147147
or programmatically using the `Filter.Expression` DSL:
@@ -150,13 +150,13 @@ or programmatically using the `Filter.Expression` DSL:
150150
----
151151
FilterExpressionBuilder b = new FilterExpressionBuilder();
152152
153-
vectorStore.similaritySearch(SearchRequest.defaults()
154-
.queryString("The World")
153+
vectorStore.similaritySearch(SearchRequest.builder()
154+
.query("The World")
155155
.topK(TOP_K)
156156
.similarityThreshold(SIMILARITY_THRESHOLD)
157157
.filterExpression(b.and(
158158
b.in("john", "jill"),
159-
b.eq("article_type", "blog")).build()));
159+
b.eq("article_type", "blog")).build()).build());
160160
----
161161

162162
NOTE: Those (portable) filter expressions get automatically converted into the proprietary Chroma `where` link:https://docs.trychroma.com/usage-guide#using-where-filters[filter expressions].

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/elasticsearch.adoc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ List <Document> documents = List.of(
9898
vectorStore.add(documents);
9999
100100
// Retrieve documents similar to a query
101-
List<Document> results = this.vectorStore.similaritySearch(SearchRequest.query("Spring").topK(5));
101+
List<Document> results = this.vectorStore.similaritySearch(SearchRequest.builder().query("Spring").topK(5).build());
102102
----
103103

104104
[[elasticsearchvector-properties]]
@@ -171,11 +171,11 @@ For example, you can use either the text expression language:
171171

172172
[source,java]
173173
----
174-
vectorStore.similaritySearch(SearchRequest.defaults()
175-
.queryString("The World")
174+
vectorStore.similaritySearch(SearchRequest.builder()
175+
.query("The World")
176176
.topK(TOP_K)
177177
.similarityThreshold(SIMILARITY_THRESHOLD)
178-
.filterExpression("author in ['john', 'jill'] && 'article_type' == 'blog'"));
178+
.filterExpression("author in ['john', 'jill'] && 'article_type' == 'blog'").build());
179179
----
180180

181181
or programmatically using the `Filter.Expression` DSL:
@@ -184,13 +184,13 @@ or programmatically using the `Filter.Expression` DSL:
184184
----
185185
FilterExpressionBuilder b = new FilterExpressionBuilder();
186186
187-
vectorStore.similaritySearch(SearchRequest.defaults()
188-
.queryString("The World")
187+
vectorStore.similaritySearch(SearchRequest.builder()
188+
.query("The World")
189189
.topK(TOP_K)
190190
.similarityThreshold(SIMILARITY_THRESHOLD)
191191
.filterExpression(b.and(
192192
b.in("author", "john", "jill"),
193-
b.eq("article_type", "blog")).build()));
193+
b.eq("article_type", "blog")).build()).build());
194194
----
195195

196196
NOTE: Those (portable) filter expressions get automatically converted into the proprietary Elasticsearch link:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html[Query string query].

0 commit comments

Comments
 (0)