From 45f53a59846af1e793d6fc39802c7bb60f9974f9 Mon Sep 17 00:00:00 2001 From: Tran Ngoc Nhan Date: Fri, 10 Oct 2025 00:32:15 +0700 Subject: [PATCH 1/2] Remove obsolete semicolon Signed-off-by: Tran Ngoc Nhan --- .../spring/AsyncMcpAnnotationProviders.java | 4 +-- .../spring/SyncMcpAnnotationProviders.java | 6 ++-- .../ai/deepseek/DeepSeekChatOptions.java | 2 +- .../modules/ROOT/pages/api/vectordbs.adoc | 32 +++++++++---------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/mcp/mcp-annotations-spring/src/main/java/org/springframework/ai/mcp/annotation/spring/AsyncMcpAnnotationProviders.java b/mcp/mcp-annotations-spring/src/main/java/org/springframework/ai/mcp/annotation/spring/AsyncMcpAnnotationProviders.java index 9aff9b0d4a4..a5279fb5508 100644 --- a/mcp/mcp-annotations-spring/src/main/java/org/springframework/ai/mcp/annotation/spring/AsyncMcpAnnotationProviders.java +++ b/mcp/mcp-annotations-spring/src/main/java/org/springframework/ai/mcp/annotation/spring/AsyncMcpAnnotationProviders.java @@ -246,7 +246,7 @@ protected Method[] doGetClassMethods(Object bean) { return AnnotationProviderUtil.beanMethods(bean); } - }; + } private final static class SpringAiAsyncStatelessMcpCompleteProvider extends AsyncStatelessMcpCompleteProvider { @@ -259,7 +259,7 @@ protected Method[] doGetClassMethods(Object bean) { return AnnotationProviderUtil.beanMethods(bean); } - }; + } // PROMPT private final static class SpringAiAsyncPromptProvider extends AsyncMcpPromptProvider { diff --git a/mcp/mcp-annotations-spring/src/main/java/org/springframework/ai/mcp/annotation/spring/SyncMcpAnnotationProviders.java b/mcp/mcp-annotations-spring/src/main/java/org/springframework/ai/mcp/annotation/spring/SyncMcpAnnotationProviders.java index 8491e86d918..8bfd7b6ba15 100644 --- a/mcp/mcp-annotations-spring/src/main/java/org/springframework/ai/mcp/annotation/spring/SyncMcpAnnotationProviders.java +++ b/mcp/mcp-annotations-spring/src/main/java/org/springframework/ai/mcp/annotation/spring/SyncMcpAnnotationProviders.java @@ -162,7 +162,7 @@ protected Method[] doGetClassMethods(Object bean) { return AnnotationProviderUtil.beanMethods(bean); } - }; + } private final static class SpringAiSyncStatelessMcpCompleteProvider extends SyncStatelessMcpCompleteProvider { @@ -175,7 +175,7 @@ protected Method[] doGetClassMethods(Object bean) { return AnnotationProviderUtil.beanMethods(bean); } - }; + } // TOOL private final static class SpringAiSyncToolProvider extends SyncMcpToolProvider { @@ -216,7 +216,7 @@ protected Method[] doGetClassMethods(Object bean) { return AnnotationProviderUtil.beanMethods(bean); } - }; + } private final static class SpringAiSyncStatelessPromptProvider extends SyncStatelessMcpPromptProvider { diff --git a/models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/DeepSeekChatOptions.java b/models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/DeepSeekChatOptions.java index b9c7a3d4962..6fb55b10a5d 100644 --- a/models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/DeepSeekChatOptions.java +++ b/models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/DeepSeekChatOptions.java @@ -143,7 +143,7 @@ public class DeepSeekChatOptions implements ToolCallingChatOptions { private Set toolNames = new HashSet<>(); @JsonIgnore - private Map toolContext = new HashMap<>();; + private Map toolContext = new HashMap<>(); public static Builder builder() { return new Builder(); diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc index 10bb7828331..86d827d814d 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc @@ -59,7 +59,7 @@ public interface VectorStore extends DocumentWriter, VectorStoreRetriever { void delete(Filter.Expression filterExpression); - default void delete(String filterExpression) { ... }; + default void delete(String filterExpression) { ... } default Optional getNativeClient() { return Optional.empty(); @@ -448,7 +448,7 @@ SearchRequest request = SearchRequest.builder() .topK(5) // Return top 5 results .similarityThreshold(0.7) // Only return results with similarity score >= 0.7 .build(); - + List filteredDocuments = retriever.similaritySearch(request); ``` @@ -463,11 +463,11 @@ Using the separate interfaces allows you to clearly define which components need @Service class DocumentIndexer { private final VectorStore vectorStore; - + DocumentIndexer(VectorStore vectorStore) { this.vectorStore = vectorStore; } - + public void indexDocuments(List documents) { vectorStore.add(documents); } @@ -477,11 +477,11 @@ class DocumentIndexer { @Service class DocumentRetriever { private final VectorStoreRetriever retriever; - + DocumentRetriever(VectorStoreRetriever retriever) { this.retriever = retriever; } - + public List findSimilar(String query) { return retriever.similaritySearch(query); } @@ -508,24 +508,24 @@ You can use `VectorStoreRetriever` directly when you only need to perform simila ```java @Service public class DocumentRetrievalService { - + private final VectorStoreRetriever retriever; - + public DocumentRetrievalService(VectorStoreRetriever retriever) { this.retriever = retriever; } - + public List findSimilarDocuments(String query) { return retriever.similaritySearch(query); } - + public List findSimilarDocumentsWithFilters(String query, String country) { SearchRequest request = SearchRequest.builder() .query(query) .topK(5) .filterExpression("country == '" + country + "'") .build(); - + return retriever.similaritySearch(request); } } @@ -540,24 +540,24 @@ The `VectorStoreRetriever` interface is particularly useful in RAG applications, ```java @Service public class RagService { - + private final VectorStoreRetriever retriever; private final ChatModel chatModel; - + public RagService(VectorStoreRetriever retriever, ChatModel chatModel) { this.retriever = retriever; this.chatModel = chatModel; } - + public String generateResponse(String userQuery) { // Retrieve relevant documents List relevantDocs = retriever.similaritySearch(userQuery); - + // Extract content from documents to use as context String context = relevantDocs.stream() .map(Document::getContent) .collect(Collectors.joining("\n\n")); - + // Generate response using the retrieved context String prompt = "Context information:\n" + context + "\n\nUser query: " + userQuery; return chatModel.generate(prompt); From a0e28d6e95b52a52cbc3ebd532a27ce9f1577845 Mon Sep 17 00:00:00 2001 From: Tran Ngoc Nhan Date: Fri, 10 Oct 2025 00:37:06 +0700 Subject: [PATCH 2/2] Convert to ascii doc Signed-off-by: Tran Ngoc Nhan --- .../modules/ROOT/pages/api/vectordbs.adoc | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc index 86d827d814d..e0291fec9cf 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc @@ -28,7 +28,8 @@ Spring AI offers an abstracted API for interacting with vector databases through Spring AI provides a read-only interface called `VectorStoreRetriever` that exposes only the document retrieval functionality: -```java +[source,java] +---- @FunctionalInterface public interface VectorStoreRetriever { @@ -38,7 +39,7 @@ public interface VectorStoreRetriever { return this.similaritySearch(SearchRequest.builder().query(query).build()); } } -``` +---- This functional interface is designed for use cases where you only need to retrieve documents from a vector store without performing any mutation operations. It follows the principle of least privilege by exposing only the necessary functionality for document retrieval. @@ -46,7 +47,8 @@ This functional interface is designed for use cases where you only need to retri The `VectorStore` interface extends `VectorStoreRetriever` and adds mutation capabilities: -```java +[source,java] +---- public interface VectorStore extends DocumentWriter, VectorStoreRetriever { default String getName() { @@ -65,13 +67,14 @@ public interface VectorStore extends DocumentWriter, VectorStoreRetriever { return Optional.empty(); } } -``` +---- The `VectorStore` interface combines both read and write operations, allowing you to add, delete, and search for documents in a vector database. === SearchRequest Builder -```java +[source,java] +---- public class SearchRequest { public static final double SIMILARITY_THRESHOLD_ACCEPT_ALL = 0.0; @@ -144,7 +147,7 @@ public class SearchRequest { public Filter.Expression getFilterExpression() {...} } -``` +---- To insert data into the vector database, encapsulate it within a `Document` object. The `Document` class encapsulates content from a data source, such as a PDF or Word document, and includes text represented as a string. @@ -417,7 +420,8 @@ The general usage of loading data into a vector store is something you would do Given a `String` reference to a source file that represents a JSON file with data we want to load into the vector database, we use Spring AI's `JsonReader` to load specific fields in the JSON, which splits them up into small pieces and then passes those small pieces to the vector store implementation. The `VectorStore` implementation computes the embeddings and stores the JSON and the embedding in the vector database: -```java +[source,java] +---- @Autowired VectorStore vectorStore; @@ -427,7 +431,7 @@ void load(String sourceFile) { List documents = jsonReader.get(); this.vectorStore.add(documents); } -``` +---- === Reading from a Vector Store @@ -435,7 +439,8 @@ Later, when a user question is passed into the AI model, a similarity search is For read-only operations, you can use either the `VectorStore` interface or the more focused `VectorStoreRetriever` interface: -```java +[source,java] +---- @Autowired VectorStoreRetriever retriever; // Could also use VectorStore here @@ -450,7 +455,7 @@ SearchRequest request = SearchRequest.builder() .build(); List filteredDocuments = retriever.similaritySearch(request); -``` +---- Additional options can be passed into the `similaritySearch` method to define how many documents to retrieve and a threshold of the similarity search. @@ -458,7 +463,8 @@ Additional options can be passed into the `similaritySearch` method to define ho Using the separate interfaces allows you to clearly define which components need write access and which only need read access: -```java +[source,java] +---- // Write operations in a service that needs full access @Service class DocumentIndexer { @@ -486,7 +492,7 @@ class DocumentRetriever { return retriever.similaritySearch(query); } } -``` +---- This separation of concerns helps create more maintainable and secure applications by limiting access to mutation operations only to components that truly need them. @@ -505,7 +511,8 @@ The `VectorStoreRetriever` interface provides a read-only view of a vector store You can use `VectorStoreRetriever` directly when you only need to perform similarity searches: -```java +[source,java] +---- @Service public class DocumentRetrievalService { @@ -529,7 +536,7 @@ public class DocumentRetrievalService { return retriever.similaritySearch(request); } } -``` +---- In this example, the service only depends on the `VectorStoreRetriever` interface, making it clear that it only performs retrieval operations and doesn't modify the vector store. @@ -537,7 +544,8 @@ In this example, the service only depends on the `VectorStoreRetriever` interfac The `VectorStoreRetriever` interface is particularly useful in RAG applications, where you need to retrieve relevant documents to provide context for an AI model: -```java +[source,java] +---- @Service public class RagService { @@ -563,7 +571,7 @@ public class RagService { return chatModel.generate(prompt); } } -``` +---- This pattern allows for a clean separation between the retrieval component and the generation component in RAG applications.