Skip to content

Commit ef0e7bc

Browse files
committed
add streaming support
1 parent b51b237 commit ef0e7bc

File tree

4 files changed

+84
-33
lines changed

4 files changed

+84
-33
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
<parent>
77
<groupId>org.springframework.boot</groupId>
88
<artifactId>spring-boot-starter-parent</artifactId>
9-
<version>3.4.1</version>
9+
<version>3.4.3</version>
1010
<relativePath/>
1111
</parent>
1212
<groupId>io.github.javaaidev</groupId>
1313
<artifactId>native-simple-ai-agent</artifactId>
1414
<version>0.0.1-SNAPSHOT</version>
15-
<name>native-simple-ai-agent</name>
15+
<name>Simple AI Agent</name>
1616
<description>Simple AI agent</description>
1717
<properties>
1818
<java.version>21</java.version>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.javaaidev.agent;
2+
3+
import com.javaaidev.chatagent.model.ChatRequest;
4+
import com.javaaidev.chatagent.model.TextContentPart;
5+
import com.javaaidev.chatagent.model.ThreadAssistantMessage;
6+
import com.javaaidev.chatagent.model.ThreadUserMessage;
7+
import java.util.List;
8+
import java.util.stream.Stream;
9+
import org.springframework.ai.chat.messages.AssistantMessage;
10+
import org.springframework.ai.chat.messages.Message;
11+
import org.springframework.ai.chat.messages.UserMessage;
12+
13+
public abstract class AbstractChatAgentController {
14+
15+
public static final String SYSTEM_TEXT = """
16+
You are a chef who is proficient in various cuisines. Please answer users' questions about cooking.
17+
For other unrelated inputs, simply tell the user that you don't know.
18+
""";
19+
20+
21+
protected List<Message> chatRequestToMessages(ChatRequest request) {
22+
return request.messages().stream().flatMap(message -> {
23+
if (message instanceof ThreadUserMessage userMessage) {
24+
return userMessage.content().stream().map(part -> {
25+
if (part instanceof TextContentPart(String text)) {
26+
return new UserMessage(text);
27+
}
28+
return null;
29+
});
30+
} else if (message instanceof ThreadAssistantMessage assistantMessage) {
31+
return assistantMessage.content().stream().map(part -> {
32+
if (part instanceof TextContentPart(String text)) {
33+
return new AssistantMessage(text);
34+
}
35+
return null;
36+
});
37+
}
38+
return Stream.<Message>of();
39+
}).toList();
40+
}
41+
}
Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,37 @@
11
package com.javaaidev.agent;
22

33
import com.javaaidev.chatagent.model.ChatRequest;
4-
import com.javaaidev.chatagent.model.ChatResponse;
5-
import com.javaaidev.chatagent.model.TextContentPart;
6-
import com.javaaidev.chatagent.model.ThreadAssistantMessage;
7-
import com.javaaidev.chatagent.model.ThreadUserMessage;
8-
import java.util.List;
9-
import java.util.stream.Stream;
104
import org.springframework.ai.chat.client.ChatClient;
11-
import org.springframework.ai.chat.messages.AssistantMessage;
125
import org.springframework.ai.chat.messages.Message;
13-
import org.springframework.ai.chat.messages.UserMessage;
6+
import org.springframework.http.codec.ServerSentEvent;
147
import org.springframework.web.bind.annotation.PostMapping;
158
import org.springframework.web.bind.annotation.RequestBody;
169
import org.springframework.web.bind.annotation.RequestMapping;
1710
import org.springframework.web.bind.annotation.RestController;
11+
import reactor.core.publisher.Flux;
1812

1913
@RestController
2014
@RequestMapping("/chat")
21-
public class ChatAgentController {
15+
public class ChatAgentController extends AbstractChatAgentController {
2216

23-
private static final String SYSTEM_TEXT = "You are a chef who is proficient in various cuisines. Please answer users' questions about cooking.";
2417
private final ChatClient chatClient;
2518

2619
public ChatAgentController(ChatClient.Builder builder) {
2720
chatClient = builder.build();
2821
}
2922

3023
@PostMapping
31-
public ChatResponse chat(@RequestBody ChatRequest request) {
24+
public Flux<ServerSentEvent<String>> chat(@RequestBody ChatRequest request) {
3225
if (request == null) {
33-
return new ChatResponse(List.of());
26+
return Flux.empty();
3427
}
35-
var messages = request.messages().stream().flatMap(message -> {
36-
if (message instanceof ThreadUserMessage userMessage) {
37-
return userMessage.content().stream().map(part -> {
38-
if (part instanceof TextContentPart(String text)) {
39-
return new UserMessage(text);
40-
}
41-
return null;
42-
});
43-
} else if (message instanceof ThreadAssistantMessage assistantMessage) {
44-
return assistantMessage.content().stream().map(part -> {
45-
if (part instanceof TextContentPart(String text)) {
46-
return new AssistantMessage(text);
47-
}
48-
return null;
49-
});
50-
}
51-
return Stream.of();
52-
}).toList();
28+
var messages = chatRequestToMessages(request);
5329
var output = chatClient.prompt().system(SYSTEM_TEXT)
5430
.messages(messages.toArray(new Message[0]))
5531
.call()
5632
.content();
57-
return new ChatResponse(List.of(new TextContentPart(output)));
33+
return Flux.just(ServerSentEvent.<String>builder()
34+
.data("#" + output + "#")
35+
.build());
5836
}
5937
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.javaaidev.agent;
2+
3+
import com.javaaidev.chatagent.model.ChatRequest;
4+
import org.springframework.ai.chat.client.ChatClient;
5+
import org.springframework.ai.chat.messages.Message;
6+
import org.springframework.http.codec.ServerSentEvent;
7+
import org.springframework.web.bind.annotation.PostMapping;
8+
import org.springframework.web.bind.annotation.RequestBody;
9+
import org.springframework.web.bind.annotation.RequestMapping;
10+
import org.springframework.web.bind.annotation.RestController;
11+
import reactor.core.publisher.Flux;
12+
13+
@RestController
14+
@RequestMapping("/chat_streaming")
15+
public class ChatAgentStreamingController extends AbstractChatAgentController {
16+
17+
private final ChatClient chatClient;
18+
19+
public ChatAgentStreamingController(ChatClient.Builder builder) {
20+
chatClient = builder.build();
21+
}
22+
23+
@PostMapping
24+
public Flux<ServerSentEvent<String>> chatStreaming(@RequestBody ChatRequest request) {
25+
var messages = chatRequestToMessages(request);
26+
return chatClient.prompt().system(SYSTEM_TEXT).messages(messages.toArray(new Message[0]))
27+
.stream().content()
28+
.map(output -> ServerSentEvent.<String>builder()
29+
.data("#" + output + "#")
30+
.build());
31+
}
32+
}

0 commit comments

Comments
 (0)