15
15
*/
16
16
package io .serverlessworkflow .fluent .agentic .langchain4j ;
17
17
18
+ import static io .serverlessworkflow .fluent .agentic .AgentWorkflowBuilder .workflow ;
19
+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newAstrologyAgent ;
20
+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newAudienceEditor ;
21
+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newCreativeWriter ;
22
+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newFoodExpert ;
23
+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newMovieExpert ;
24
+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newStyleEditor ;
25
+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newStyleScorer ;
26
+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newSummaryStory ;
27
+ import static io .serverlessworkflow .fluent .agentic .langchain4j .Agents .*;
18
28
import static io .serverlessworkflow .fluent .agentic .langchain4j .Agents .AudienceEditor ;
19
29
import static io .serverlessworkflow .fluent .agentic .langchain4j .Agents .CreativeWriter ;
20
30
import static io .serverlessworkflow .fluent .agentic .langchain4j .Agents .StyleEditor ;
21
31
import static io .serverlessworkflow .fluent .agentic .langchain4j .Models .BASE_MODEL ;
32
+ import static org .junit .jupiter .api .Assertions .assertEquals ;
33
+ import static org .junit .jupiter .api .Assertions .assertNotNull ;
22
34
import static org .mockito .ArgumentMatchers .any ;
23
35
import static org .mockito .ArgumentMatchers .eq ;
24
36
import static org .mockito .Mockito .spy ;
25
37
import static org .mockito .Mockito .verify ;
26
38
27
- import dev .langchain4j .agentic .AgenticServices ;
28
39
import dev .langchain4j .agentic .UntypedAgent ;
40
+ import dev .langchain4j .agentic .scope .AgenticScope ;
29
41
import dev .langchain4j .agentic .workflow .WorkflowAgentsBuilder ;
42
+ import io .serverlessworkflow .fluent .agentic .AgenticServices ;
43
+ import io .serverlessworkflow .fluent .agentic .AgentsUtils ;
44
+ import java .util .List ;
30
45
import java .util .Map ;
46
+ import java .util .function .Function ;
47
+ import java .util .function .Predicate ;
48
+ import java .util .stream .IntStream ;
31
49
import org .junit .jupiter .api .Test ;
32
50
33
51
public class WorkflowAgentsIT {
@@ -38,21 +56,21 @@ void sequential_agents_tests() {
38
56
39
57
CreativeWriter creativeWriter =
40
58
spy (
41
- AgenticServices .agentBuilder (CreativeWriter .class )
59
+ dev . langchain4j . agentic . AgenticServices .agentBuilder (CreativeWriter .class )
42
60
.chatModel (BASE_MODEL )
43
61
.outputName ("story" )
44
62
.build ());
45
63
46
64
AudienceEditor audienceEditor =
47
65
spy (
48
- AgenticServices .agentBuilder (AudienceEditor .class )
66
+ dev . langchain4j . agentic . AgenticServices .agentBuilder (AudienceEditor .class )
49
67
.chatModel (BASE_MODEL )
50
68
.outputName ("story" )
51
69
.build ());
52
70
53
71
StyleEditor styleEditor =
54
72
spy (
55
- AgenticServices .agentBuilder (StyleEditor .class )
73
+ dev . langchain4j . agentic . AgenticServices .agentBuilder (StyleEditor .class )
56
74
.chatModel (BASE_MODEL )
57
75
.outputName ("story" )
58
76
.build ());
@@ -77,4 +95,123 @@ void sequential_agents_tests() {
77
95
verify (audienceEditor ).editStory (any (), eq ("young adults" ));
78
96
verify (styleEditor ).editStory (any (), eq ("fantasy" ));
79
97
}
98
+
99
+ @ Test
100
+ public void sequenceHelperTest () {
101
+ var creativeWriter = newCreativeWriter ();
102
+ var audienceEditor = newAudienceEditor ();
103
+ var styleEditor = newStyleEditor ();
104
+
105
+ AgentsUtils .NovelCreator novelCreator =
106
+ io .serverlessworkflow .fluent .agentic .AgenticServices .of (AgentsUtils .NovelCreator .class )
107
+ .flow (workflow ("seqFlow" ).sequence (creativeWriter , audienceEditor , styleEditor ))
108
+ .build ();
109
+
110
+ String story = novelCreator .createNovel ("dragons and wizards" , "young adults" , "fantasy" );
111
+ assertNotNull (story );
112
+ }
113
+
114
+ @ Test
115
+ public void agentAndSequenceHelperTest () {
116
+ var creativeWriter = newCreativeWriter ();
117
+ var audienceEditor = newAudienceEditor ();
118
+ var styleEditor = newStyleEditor ();
119
+
120
+ AgentsUtils .NovelCreator novelCreator =
121
+ io .serverlessworkflow .fluent .agentic .AgenticServices .of (AgentsUtils .NovelCreator .class )
122
+ .flow (workflow ("seqFlow" ).agent (creativeWriter ).sequence (audienceEditor , styleEditor ))
123
+ .build ();
124
+
125
+ String story = novelCreator .createNovel ("dragons and wizards" , "young adults" , "fantasy" );
126
+ assertNotNull (story );
127
+ }
128
+
129
+ @ Test
130
+ public void agentAndSequenceAndAgentHelperTest () {
131
+ var creativeWriter = newCreativeWriter ();
132
+ var audienceEditor = newAudienceEditor ();
133
+ var styleEditor = newStyleEditor ();
134
+ var summaryStory = newSummaryStory ();
135
+
136
+ AgentsUtils .NovelCreator novelCreator =
137
+ io .serverlessworkflow .fluent .agentic .AgenticServices .of (AgentsUtils .NovelCreator .class )
138
+ .flow (
139
+ workflow ("seqFlow" )
140
+ .agent (creativeWriter )
141
+ .sequence (audienceEditor , styleEditor )
142
+ .agent (summaryStory ))
143
+ .build ();
144
+
145
+ String story = novelCreator .createNovel ("dragons and wizards" , "young adults" , "fantasy" );
146
+ assertNotNull (story );
147
+ }
148
+
149
+ @ Test
150
+ public void parallelWorkflow () {
151
+ var foodExpert = newFoodExpert ();
152
+ var movieExpert = newMovieExpert ();
153
+
154
+ Function <AgenticScope , List <EveningPlan >> planEvening =
155
+ input -> {
156
+ List <String > movies = (List <String >) input .readState ("movies" );
157
+ List <String > meals = (List <String >) input .readState ("meals" );
158
+
159
+ int max = Math .min (movies .size (), meals .size ());
160
+ return IntStream .range (0 , max )
161
+ .mapToObj (i -> new EveningPlan (movies .get (i ), meals .get (i )))
162
+ .toList ();
163
+ };
164
+
165
+ EveningPlannerAgent eveningPlannerAgent =
166
+ AgenticServices .of (EveningPlannerAgent .class )
167
+ .flow (workflow ("parallelFlow" ).parallel (foodExpert , movieExpert ).outputAs (planEvening ))
168
+ .build ();
169
+ List <EveningPlan > result = eveningPlannerAgent .plan ("romantic" );
170
+ assertEquals (3 , result .size ());
171
+ }
172
+
173
+ @ Test
174
+ public void loopTest () {
175
+ var creativeWriter = newCreativeWriter ();
176
+ var scorer = newStyleScorer ();
177
+ var editor = newStyleEditor ();
178
+
179
+ Predicate <AgenticScope > until = s -> s .readState ("score" , 0.0 ) >= 0.8 ;
180
+
181
+ StyledWriter styledWriter =
182
+ AgenticServices .of (StyledWriter .class )
183
+ .flow (workflow ("loopFlow" ).agent (creativeWriter ).loop (until , scorer , editor ))
184
+ .build ();
185
+
186
+ String story = styledWriter .writeStoryWithStyle ("dragons and wizards" , "fantasy" );
187
+ assertNotNull (story );
188
+ }
189
+
190
+ @ Test
191
+ public void humanInTheLoop () {
192
+ var astrologyAgent = newAstrologyAgent ();
193
+
194
+ var askSign =
195
+ new Function <AgenticScope , AgenticScope >() {
196
+ @ Override
197
+ public AgenticScope apply (AgenticScope holder ) {
198
+ System .out .println ("What's your star sign?" );
199
+ // var sign = System.console().readLine();
200
+ holder .writeState ("sign" , "piscis" );
201
+ return holder ;
202
+ }
203
+ };
204
+
205
+ String result =
206
+ AgenticServices .of (Agents .HoroscopeAgent .class )
207
+ .flow (
208
+ workflow ("humanInTheLoop" )
209
+ .inputFrom (askSign )
210
+ // .tasks(tasks -> tasks.callFn(fn(askSign))) // TODO should work too
211
+ .agent (astrologyAgent ))
212
+ .build ()
213
+ .invoke ("My name is Mario. What is my horoscope?" );
214
+
215
+ assertNotNull (result );
216
+ }
80
217
}
0 commit comments