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