Skip to content

Commit 7f1570d

Browse files
committed
Update javadoc for message package and docs for Gemini Multimodal support
1 parent c5d9ae3 commit 7f1570d

File tree

11 files changed

+73
-22
lines changed

11 files changed

+73
-22
lines changed

models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ static List<Part> messageToGeminiParts(Message message, String systemContext) {
333333

334334
List<Part> parts = new ArrayList<>(List.of(textPart));
335335

336-
List<Part> mediaParts = userMessage.getMediaData()
336+
List<Part> mediaParts = userMessage.getMedia()
337337
.stream()
338338
.map(mediaData -> PartMaker.fromMimeTypeAndData(mediaData.getMimeType().toString(),
339339
mediaData.getData()))

models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatClientIT.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import org.springframework.ai.chat.ChatResponse;
2929
import org.springframework.ai.chat.Generation;
3030
import org.springframework.ai.chat.messages.AssistantMessage;
31-
import org.springframework.ai.chat.messages.MediaData;
31+
import org.springframework.ai.chat.messages.Media;
3232
import org.springframework.ai.chat.messages.Message;
3333
import org.springframework.ai.chat.messages.UserMessage;
3434
import org.springframework.ai.chat.prompt.Prompt;
@@ -189,7 +189,7 @@ void multiModalityTest() throws IOException {
189189
byte[] data = new ClassPathResource("/vertex.test.png").getContentAsByteArray();
190190

191191
var userMessage = new UserMessage("Explain what do you see o this picture?",
192-
List.of(new MediaData(MimeTypeUtils.IMAGE_PNG, data)));
192+
List.of(new Media(MimeTypeUtils.IMAGE_PNG, data)));
193193

194194
ChatResponse response = client.call(new Prompt(List.of(userMessage)));
195195

@@ -208,7 +208,7 @@ void multiModalityTest() throws IOException {
208208
// "https://storage.googleapis.com/github-repo/img/gemini/multimodality_usecases_overview/banana-apple.jpg";
209209

210210
// userMessage = new UserMessage("Explain what do you see o this picture?",
211-
// List.of(new MediaData(MimeTypeDetector.getMimeType(imageUrl), imageUrl)));
211+
// List.of(new Media(MimeTypeDetector.getMimeType(imageUrl), imageUrl)));
212212
// response = client.call(new Prompt(List.of(userMessage)));
213213

214214
// assertThat(response.getResult().getOutput().getContent()).contains("bananas",

spring-ai-core/src/main/java/org/springframework/ai/chat/messages/AbstractMessage.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,20 @@
2727
import org.springframework.util.Assert;
2828
import org.springframework.util.StreamUtils;
2929

30+
/**
31+
* The AbstractMessage class is an abstract implementation of the Message interface. It
32+
* provides a base implementation for message content, media attachments, properties, and
33+
* message type.
34+
*
35+
* @see Message
36+
*/
3037
public abstract class AbstractMessage implements Message {
3138

3239
protected final MessageType messageType;
3340

3441
protected final String textContent;
3542

36-
protected final List<MediaData> mediaData;
43+
protected final List<Media> mediaData;
3744

3845
/**
3946
* Additional options for the message to influence the response, not a generative map.
@@ -46,18 +53,17 @@ protected AbstractMessage(MessageType messageType, String content) {
4653

4754
protected AbstractMessage(MessageType messageType, String content, Map<String, Object> messageProperties) {
4855
Assert.notNull(messageType, "Message type must not be null");
49-
// Assert.notNull(content, "Content must not be null");
5056
this.messageType = messageType;
5157
this.textContent = content;
5258
this.mediaData = new ArrayList<>();
5359
this.properties = messageProperties;
5460
}
5561

56-
protected AbstractMessage(MessageType messageType, String textContent, List<MediaData> mediaData) {
62+
protected AbstractMessage(MessageType messageType, String textContent, List<Media> mediaData) {
5763
this(messageType, textContent, mediaData, Map.of());
5864
}
5965

60-
protected AbstractMessage(MessageType messageType, String textContent, List<MediaData> mediaData,
66+
protected AbstractMessage(MessageType messageType, String textContent, List<Media> mediaData,
6167
Map<String, Object> messageProperties) {
6268

6369
Assert.notNull(messageType, "Message type must not be null");
@@ -97,7 +103,7 @@ public String getContent() {
97103
}
98104

99105
@Override
100-
public List<MediaData> getMediaData() {
106+
public List<Media> getMedia() {
101107
return this.mediaData;
102108
}
103109

spring-ai-core/src/main/java/org/springframework/ai/chat/messages/ChatMessage.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818
import java.util.Map;
1919

20+
/**
21+
* Represents a chat message in a chat application.
22+
*
23+
*/
2024
public class ChatMessage extends AbstractMessage {
2125

2226
public ChatMessage(String role, String content) {

spring-ai-core/src/main/java/org/springframework/ai/chat/messages/FunctionMessage.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818
import java.util.Map;
1919

20+
/**
21+
* The FunctionMessage class represents a message with a function content in a chat
22+
* application.
23+
*/
2024
public class FunctionMessage extends AbstractMessage {
2125

2226
public FunctionMessage(String content) {

spring-ai-core/src/main/java/org/springframework/ai/chat/messages/MediaData.java renamed to spring-ai-core/src/main/java/org/springframework/ai/chat/messages/Media.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,22 @@
1919
import org.springframework.util.MimeType;
2020

2121
/**
22+
* The Media class represents the data and metadata of a media attachment in a message. It
23+
* consists of a MIME type and the raw data.
24+
*
25+
* This class is used as a parameter in the constructor of the UserMessage class.
26+
*
2227
* @author Christian Tzolov
28+
* @since 0.8.1
2329
*/
24-
public class MediaData {
30+
public class Media {
2531

2632
private final MimeType mimeType;
2733

2834
private final Object data;
2935

30-
public MediaData(MimeType mimeType, Object data) {
36+
public Media(MimeType mimeType, Object data) {
3137
Assert.notNull(mimeType, "MimeType must not be null");
32-
// Assert.notNull(data, "Data must not be null");
3338
this.mimeType = mimeType;
3439
this.data = data;
3540
}

spring-ai-core/src/main/java/org/springframework/ai/chat/messages/Message.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,19 @@
1818
import java.util.List;
1919
import java.util.Map;
2020

21+
/**
22+
* The Message interface represents a message that can be sent or received in a chat
23+
* application. Messages can have content, media attachments, properties, and message
24+
* types.
25+
*
26+
* @see Media
27+
* @see MessageType
28+
*/
2129
public interface Message {
2230

2331
String getContent();
2432

25-
List<MediaData> getMediaData();
33+
List<Media> getMedia();
2634

2735
Map<String, Object> getProperties();
2836

spring-ai-core/src/main/java/org/springframework/ai/chat/messages/MessageType.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
*/
1616
package org.springframework.ai.chat.messages;
1717

18+
/**
19+
* The MessageType enum represents the type of a message in a chat application. It can be
20+
* one of the following: USER, ASSISTANT, SYSTEM, FUNCTION.
21+
*/
1822
public enum MessageType {
1923

2024
USER("user"),

spring-ai-core/src/main/java/org/springframework/ai/chat/messages/UserMessage.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ public UserMessage(Resource resource) {
3434
super(MessageType.USER, resource);
3535
}
3636

37-
public UserMessage(String textContent, List<MediaData> mediaDataList) {
38-
super(MessageType.USER, textContent, mediaDataList);
37+
public UserMessage(String textContent, List<Media> mediaList) {
38+
super(MessageType.USER, textContent, mediaList);
3939
}
4040

4141
@Override

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/clients/vertexai-gemini-chat.adoc

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,26 @@ You can register custom Java functions with the VertexAiGeminiChatClient and hav
107107
This is a powerful technique to connect the LLM capabilities with external tools and APIs.
108108
Read more about xref:api/clients/functions/vertexai-gemini-chat-functions.adoc[Vertex AI Gemini Function Calling].
109109

110+
=== Multimodal Example
111+
Multimodality refers to a model's ability to simultaneously understand and process information from various sources, including text, images, audio, and other data formats. This paradigm represents a significant advancement in AI models.
112+
113+
Google's Gemini AI models support this capability by comprehending and integrating text, code, audio, images, and video. For more details, refer to the blog post [Introducing Gemini](https://blog.google/technology/ai/google-gemini-ai/#introducing-gemini).
114+
115+
Spring AI's `Message` interface supports multimodal AI models by introducing the Media type.
116+
This type contains data and information about media attachments in messages, using Spring's `org.springframework.util.MimeType` and a `java.lang.Object` for the raw media data.
117+
118+
Below is a simple code example extracted from [VertexAiGeminiChatClientIT.java](https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatClientIT.java), demonstrating the combination of user text with an image.
119+
120+
121+
[source,java]
122+
----
123+
byte[] data = new ClassPathResource("/vertex-test.png").getContentAsByteArray();
124+
125+
var userMessage = new UserMessage("Explain what do you see o this picture?",
126+
List.of(new Media(MimeTypeUtils.IMAGE_PNG, data)));
127+
128+
ChatResponse response = chatClient.call(new Prompt(List.of(userMessage)));
129+
----
110130

111131
=== Sample Controller (Auto-configuration)
112132

@@ -195,6 +215,3 @@ ChatResponse response = chatClient.call(
195215
The `VertexAiGeminiChatOptions` provides the configuration information for the chat requests.
196216
The `VertexAiGeminiChatOptions.Builder` is fluent options builder.
197217

198-
=== Multi-modal
199-
200-
https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatClientIT.java[VertexAiGeminiChatClientIT.java]

0 commit comments

Comments
 (0)