Skip to content

Commit d7701a5

Browse files
authored
Merge pull request #682 from fjtirado/agentic_core
Agentic core
2 parents 99d6a61 + 7045ef7 commit d7701a5

File tree

27 files changed

+490
-57
lines changed

27 files changed

+490
-57
lines changed

experimental/agentic/pom.xml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>io.serverlessworkflow</groupId>
6+
<artifactId>serverlessworkflow-experimental</artifactId>
7+
<version>8.0.0-SNAPSHOT</version>
8+
</parent>
9+
<artifactId>serverlessworkflow-experimental-agentic</artifactId>
10+
<name>ServelessWorkflow:: Experimental:: Agentic</name>
11+
<dependencies>
12+
<dependency>
13+
<groupId>io.serverlessworkflow</groupId>
14+
<artifactId>serverlessworkflow-experimental-lambda</artifactId>
15+
</dependency>
16+
<dependency>
17+
<groupId>dev.langchain4j</groupId>
18+
<artifactId>langchain4j-agentic</artifactId>
19+
</dependency>
20+
<dependency>
21+
<groupId>org.junit.jupiter</groupId>
22+
<artifactId>junit-jupiter-api</artifactId>
23+
<scope>test</scope>
24+
</dependency>
25+
<dependency>
26+
<groupId>org.junit.jupiter</groupId>
27+
<artifactId>junit-jupiter-engine</artifactId>
28+
<scope>test</scope>
29+
</dependency>
30+
<dependency>
31+
<groupId>org.junit.jupiter</groupId>
32+
<artifactId>junit-jupiter-params</artifactId>
33+
<scope>test</scope>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.assertj</groupId>
37+
<artifactId>assertj-core</artifactId>
38+
<scope>test</scope>
39+
</dependency>
40+
<dependency>
41+
<groupId>ch.qos.logback</groupId>
42+
<artifactId>logback-classic</artifactId>
43+
<scope>test</scope>
44+
</dependency>
45+
</dependencies>
46+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.impl.expressions.agentic;
17+
18+
import io.serverlessworkflow.impl.WorkflowModelFactory;
19+
import io.serverlessworkflow.impl.expressions.func.JavaExpressionFactory;
20+
21+
public class AgenticExpressionFactory extends JavaExpressionFactory {
22+
23+
private final WorkflowModelFactory modelFactory = new AgenticModelFactory();
24+
25+
@Override
26+
public WorkflowModelFactory modelFactory() {
27+
return modelFactory;
28+
}
29+
30+
public int priority() {
31+
return DEFAULT_PRIORITY - 1;
32+
}
33+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.impl.expressions.agentic;
17+
18+
import dev.langchain4j.agentic.cognisphere.Cognisphere;
19+
import dev.langchain4j.agentic.cognisphere.ResultWithCognisphere;
20+
import io.serverlessworkflow.impl.WorkflowModel;
21+
import io.serverlessworkflow.impl.expressions.func.JavaModel;
22+
import java.util.Collection;
23+
import java.util.Collections;
24+
import java.util.Optional;
25+
26+
class AgenticModel extends JavaModel {
27+
28+
private final Cognisphere cognisphere;
29+
30+
AgenticModel(Object object, Cognisphere cognisphere) {
31+
super(object);
32+
this.cognisphere = cognisphere;
33+
}
34+
35+
@Override
36+
public Collection<WorkflowModel> asCollection() {
37+
return object instanceof Collection value
38+
? new AgenticModelCollection(value, cognisphere)
39+
: Collections.emptyList();
40+
}
41+
42+
@Override
43+
public <T> Optional<T> as(Class<T> clazz) {
44+
if (Cognisphere.class.isAssignableFrom(clazz)) {
45+
return Optional.of(clazz.cast(cognisphere));
46+
} else if (ResultWithCognisphere.class.isAssignableFrom(clazz)) {
47+
return Optional.of(clazz.cast(new ResultWithCognisphere<>(cognisphere, object)));
48+
} else {
49+
return super.as(clazz);
50+
}
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.impl.expressions.agentic;
17+
18+
import dev.langchain4j.agentic.cognisphere.Cognisphere;
19+
import dev.langchain4j.agentic.cognisphere.ResultWithCognisphere;
20+
import io.serverlessworkflow.impl.WorkflowModel;
21+
import io.serverlessworkflow.impl.expressions.func.JavaModelCollection;
22+
import java.util.Collection;
23+
import java.util.Optional;
24+
25+
class AgenticModelCollection extends JavaModelCollection {
26+
27+
private final Cognisphere cognisphere;
28+
29+
AgenticModelCollection(Collection<?> object, Cognisphere cognisphere) {
30+
super(object);
31+
this.cognisphere = cognisphere;
32+
}
33+
34+
AgenticModelCollection(Cognisphere cognisphere) {
35+
this.cognisphere = cognisphere;
36+
}
37+
38+
@Override
39+
protected WorkflowModel nextItem(Object obj) {
40+
return new AgenticModel(obj, cognisphere);
41+
}
42+
43+
@Override
44+
public <T> Optional<T> as(Class<T> clazz) {
45+
if (Cognisphere.class.isAssignableFrom(clazz)) {
46+
return Optional.of(clazz.cast(cognisphere));
47+
} else if (ResultWithCognisphere.class.isAssignableFrom(clazz)) {
48+
return Optional.of(clazz.cast(new ResultWithCognisphere<>(cognisphere, object)));
49+
} else {
50+
return super.as(clazz);
51+
}
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.impl.expressions.agentic;
17+
18+
import dev.langchain4j.agentic.cognisphere.Cognisphere;
19+
import dev.langchain4j.agentic.cognisphere.CognisphereRegistry;
20+
import io.cloudevents.CloudEvent;
21+
import io.cloudevents.CloudEventData;
22+
import io.serverlessworkflow.impl.WorkflowModel;
23+
import io.serverlessworkflow.impl.WorkflowModelCollection;
24+
import io.serverlessworkflow.impl.WorkflowModelFactory;
25+
import java.time.OffsetDateTime;
26+
import java.util.Map;
27+
28+
class AgenticModelFactory implements WorkflowModelFactory {
29+
private final Cognisphere cognisphere = CognisphereRegistry.createEphemeralCognisphere();
30+
31+
private final AgenticModel TrueModel = new AgenticModel(Boolean.TRUE, cognisphere);
32+
private final AgenticModel FalseModel = new AgenticModel(Boolean.FALSE, cognisphere);
33+
private final AgenticModel NullModel = new AgenticModel(null, cognisphere);
34+
35+
@Override
36+
public WorkflowModel combine(Map<String, WorkflowModel> workflowVariables) {
37+
return new AgenticModel(workflowVariables, cognisphere);
38+
}
39+
40+
@Override
41+
public WorkflowModelCollection createCollection() {
42+
return new AgenticModelCollection(cognisphere);
43+
}
44+
45+
@Override
46+
public WorkflowModel from(boolean value) {
47+
return value ? TrueModel : FalseModel;
48+
}
49+
50+
@Override
51+
public WorkflowModel from(Number value) {
52+
return new AgenticModel(value, cognisphere);
53+
}
54+
55+
@Override
56+
public WorkflowModel from(String value) {
57+
return new AgenticModel(value, cognisphere);
58+
}
59+
60+
@Override
61+
public WorkflowModel from(CloudEvent ce) {
62+
return new AgenticModel(ce, cognisphere);
63+
}
64+
65+
@Override
66+
public WorkflowModel from(CloudEventData ce) {
67+
return new AgenticModel(ce, cognisphere);
68+
}
69+
70+
@Override
71+
public WorkflowModel from(OffsetDateTime value) {
72+
return new AgenticModel(value, cognisphere);
73+
}
74+
75+
@Override
76+
public WorkflowModel from(Map<String, Object> map) {
77+
cognisphere.writeStates(map);
78+
return new AgenticModel(map, cognisphere);
79+
}
80+
81+
@Override
82+
public WorkflowModel fromNull() {
83+
return NullModel;
84+
}
85+
86+
@Override
87+
public WorkflowModel fromOther(Object value) {
88+
return new AgenticModel(value, cognisphere);
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
io.serverlessworkflow.impl.expressions.agentic.AgenticExpressionFactory

experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ protected JavaForExecutorBuilder(
4343

4444
protected Optional<WorkflowFilter> buildWhileFilter() {
4545
if (task instanceof ForTaskFunction taskFunctions) {
46-
LoopPredicateIndex whilePred = taskFunctions.getWhilePredicate();
46+
final LoopPredicateIndex whilePred = taskFunctions.getWhilePredicate();
47+
Optional<Class<?>> modelClass = taskFunctions.getModelClass();
4748
String varName = task.getFor().getEach();
4849
String indexName = task.getFor().getAt();
4950
if (whilePred != null) {
@@ -54,7 +55,7 @@ protected Optional<WorkflowFilter> buildWhileFilter() {
5455
.modelFactory()
5556
.from(
5657
whilePred.test(
57-
n.asJavaObject(),
58+
JavaFuncUtils.convert(n, modelClass),
5859
item,
5960
(Integer) safeObject(t.variables().get(indexName))));
6061
});

experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFuncUtils.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,37 @@
1616
package io.serverlessworkflow.impl.executors.func;
1717

1818
import io.serverlessworkflow.impl.WorkflowModel;
19+
import java.util.Optional;
1920

2021
public class JavaFuncUtils {
2122

2223
static Object safeObject(Object obj) {
2324
return obj instanceof WorkflowModel model ? model.asJavaObject() : obj;
2425
}
2526

27+
static <T> T convertT(WorkflowModel model, Optional<Class<T>> inputClass) {
28+
return inputClass
29+
.map(
30+
c ->
31+
model
32+
.as(c)
33+
.orElseThrow(
34+
() ->
35+
new IllegalArgumentException(
36+
"Model " + model + " cannot be converted to type " + c)))
37+
.orElseGet(() -> (T) model.asJavaObject());
38+
}
39+
40+
static Object convert(WorkflowModel model, Optional<Class<?>> inputClass) {
41+
return inputClass.isPresent()
42+
? model
43+
.as(inputClass.orElseThrow())
44+
.orElseThrow(
45+
() ->
46+
new IllegalArgumentException(
47+
"Model " + model + " cannot be converted to type " + inputClass))
48+
: model.asJavaObject();
49+
}
50+
2651
private JavaFuncUtils() {}
2752
}

experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFunctionCallExecutor.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,35 @@
2525
import io.serverlessworkflow.impl.WorkflowModelFactory;
2626
import io.serverlessworkflow.impl.executors.CallableTask;
2727
import io.serverlessworkflow.impl.resources.ResourceLoader;
28+
import java.util.Optional;
2829
import java.util.concurrent.CompletableFuture;
2930
import java.util.function.Function;
3031

31-
public class JavaFunctionCallExecutor implements CallableTask<CallJava.CallJavaFunction> {
32+
public class JavaFunctionCallExecutor<T, V>
33+
implements CallableTask<CallJava.CallJavaFunction<T, V>> {
3234

33-
private Function function;
35+
private Function<T, V> function;
36+
private Optional<Class<T>> inputClass;
37+
38+
static String fromInt(Integer integer) {
39+
return Integer.toString(integer);
40+
}
3441

3542
public void init(
36-
CallJava.CallJavaFunction task,
43+
CallJava.CallJavaFunction<T, V> task,
3744
Workflow workflow,
3845
WorkflowApplication application,
3946
ResourceLoader loader) {
4047
function = task.function();
48+
inputClass = task.inputClass();
4149
}
4250

4351
@Override
4452
public CompletableFuture<WorkflowModel> apply(
4553
WorkflowContext workflowContext, TaskContext taskContext, WorkflowModel input) {
4654
WorkflowModelFactory modelFactory = workflowContext.definition().application().modelFactory();
4755
return CompletableFuture.completedFuture(
48-
modelFactory.fromAny(function.apply(input.asJavaObject())));
56+
modelFactory.fromAny(function.apply(JavaFuncUtils.convertT(input, inputClass))));
4957
}
5058

5159
@Override

experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModel.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,11 @@
2626
import java.util.function.BiConsumer;
2727
import java.util.stream.Collectors;
2828

29-
class JavaModel implements WorkflowModel {
29+
public class JavaModel implements WorkflowModel {
3030

31-
private Object object;
31+
protected final Object object;
3232

33-
static final JavaModel TrueModel = new JavaModel(Boolean.TRUE);
34-
static final JavaModel FalseModel = new JavaModel(Boolean.FALSE);
35-
static final JavaModel NullModel = new JavaModel(null);
36-
37-
JavaModel(Object object) {
33+
protected JavaModel(Object object) {
3834
this.object = asJavaObject(object);
3935
}
4036

0 commit comments

Comments
 (0)