Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions experimental/agentic/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-experimental</artifactId>
<version>8.0.0-SNAPSHOT</version>
</parent>
<artifactId>serverlessworkflow-experimental-agentic</artifactId>
<name>ServelessWorkflow:: Experimental:: Agentic</name>
<dependencies>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-experimental-lambda</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-agentic</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.expressions.agentic;

import io.serverlessworkflow.impl.WorkflowModelFactory;
import io.serverlessworkflow.impl.expressions.func.JavaExpressionFactory;

public class AgenticExpressionFactory extends JavaExpressionFactory {

private final WorkflowModelFactory modelFactory = new AgenticModelFactory();

@Override
public WorkflowModelFactory modelFactory() {
return modelFactory;
}

public int priority() {
return DEFAULT_PRIORITY - 1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.expressions.agentic;

import dev.langchain4j.agentic.cognisphere.Cognisphere;
import dev.langchain4j.agentic.cognisphere.ResultWithCognisphere;
import io.serverlessworkflow.impl.WorkflowModel;
import io.serverlessworkflow.impl.expressions.func.JavaModel;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;

class AgenticModel extends JavaModel {

private final Cognisphere cognisphere;

AgenticModel(Object object, Cognisphere cognisphere) {
super(object);
this.cognisphere = cognisphere;
}

@Override
public Collection<WorkflowModel> asCollection() {
return object instanceof Collection value
? new AgenticModelCollection(value, cognisphere)
: Collections.emptyList();
}

@Override
public <T> Optional<T> as(Class<T> clazz) {
if (Cognisphere.class.isAssignableFrom(clazz)) {
return Optional.of(clazz.cast(cognisphere));
} else if (ResultWithCognisphere.class.isAssignableFrom(clazz)) {
return Optional.of(clazz.cast(new ResultWithCognisphere<>(cognisphere, object)));
} else {
return super.as(clazz);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.expressions.agentic;

import dev.langchain4j.agentic.cognisphere.Cognisphere;
import dev.langchain4j.agentic.cognisphere.ResultWithCognisphere;
import io.serverlessworkflow.impl.WorkflowModel;
import io.serverlessworkflow.impl.expressions.func.JavaModelCollection;
import java.util.Collection;
import java.util.Optional;

class AgenticModelCollection extends JavaModelCollection {

private final Cognisphere cognisphere;

AgenticModelCollection(Collection<?> object, Cognisphere cognisphere) {
super(object);
this.cognisphere = cognisphere;
}

AgenticModelCollection(Cognisphere cognisphere) {
this.cognisphere = cognisphere;
}

@Override
protected WorkflowModel nextItem(Object obj) {
return new AgenticModel(obj, cognisphere);
}

@Override
public <T> Optional<T> as(Class<T> clazz) {
if (Cognisphere.class.isAssignableFrom(clazz)) {
return Optional.of(clazz.cast(cognisphere));
} else if (ResultWithCognisphere.class.isAssignableFrom(clazz)) {
return Optional.of(clazz.cast(new ResultWithCognisphere<>(cognisphere, object)));
} else {
return super.as(clazz);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.expressions.agentic;

import dev.langchain4j.agentic.cognisphere.Cognisphere;
import dev.langchain4j.agentic.cognisphere.CognisphereRegistry;
import io.cloudevents.CloudEvent;
import io.cloudevents.CloudEventData;
import io.serverlessworkflow.impl.WorkflowModel;
import io.serverlessworkflow.impl.WorkflowModelCollection;
import io.serverlessworkflow.impl.WorkflowModelFactory;
import java.time.OffsetDateTime;
import java.util.Map;

class AgenticModelFactory implements WorkflowModelFactory {
private final Cognisphere cognisphere = CognisphereRegistry.createEphemeralCognisphere();

private final AgenticModel TrueModel = new AgenticModel(Boolean.TRUE, cognisphere);
private final AgenticModel FalseModel = new AgenticModel(Boolean.FALSE, cognisphere);
private final AgenticModel NullModel = new AgenticModel(null, cognisphere);

@Override
public WorkflowModel combine(Map<String, WorkflowModel> workflowVariables) {
return new AgenticModel(workflowVariables, cognisphere);
}

@Override
public WorkflowModelCollection createCollection() {
return new AgenticModelCollection(cognisphere);
}

@Override
public WorkflowModel from(boolean value) {
return value ? TrueModel : FalseModel;
}

@Override
public WorkflowModel from(Number value) {
return new AgenticModel(value, cognisphere);
}

@Override
public WorkflowModel from(String value) {
return new AgenticModel(value, cognisphere);
}

@Override
public WorkflowModel from(CloudEvent ce) {
return new AgenticModel(ce, cognisphere);
}

@Override
public WorkflowModel from(CloudEventData ce) {
return new AgenticModel(ce, cognisphere);
}

@Override
public WorkflowModel from(OffsetDateTime value) {
return new AgenticModel(value, cognisphere);
}

@Override
public WorkflowModel from(Map<String, Object> map) {
cognisphere.writeStates(map);
return new AgenticModel(map, cognisphere);
}

@Override
public WorkflowModel fromNull() {
return NullModel;
}

@Override
public WorkflowModel fromOther(Object value) {
return new AgenticModel(value, cognisphere);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.serverlessworkflow.impl.expressions.agentic.AgenticExpressionFactory
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ protected JavaForExecutorBuilder(

protected Optional<WorkflowFilter> buildWhileFilter() {
if (task instanceof ForTaskFunction taskFunctions) {
LoopPredicateIndex whilePred = taskFunctions.getWhilePredicate();
final LoopPredicateIndex whilePred = taskFunctions.getWhilePredicate();
Optional<Class<?>> modelClass = taskFunctions.getModelClass();
String varName = task.getFor().getEach();
String indexName = task.getFor().getAt();
if (whilePred != null) {
Expand All @@ -54,7 +55,7 @@ protected Optional<WorkflowFilter> buildWhileFilter() {
.modelFactory()
.from(
whilePred.test(
n.asJavaObject(),
JavaFuncUtils.convert(n, modelClass),
item,
(Integer) safeObject(t.variables().get(indexName))));
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,37 @@
package io.serverlessworkflow.impl.executors.func;

import io.serverlessworkflow.impl.WorkflowModel;
import java.util.Optional;

public class JavaFuncUtils {

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

static <T> T convertT(WorkflowModel model, Optional<Class<T>> inputClass) {
return inputClass
.map(
c ->
model
.as(c)
.orElseThrow(
() ->
new IllegalArgumentException(
"Model " + model + " cannot be converted to type " + c)))
.orElseGet(() -> (T) model.asJavaObject());
}

static Object convert(WorkflowModel model, Optional<Class<?>> inputClass) {
return inputClass.isPresent()
? model
.as(inputClass.orElseThrow())
.orElseThrow(
() ->
new IllegalArgumentException(
"Model " + model + " cannot be converted to type " + inputClass))
: model.asJavaObject();
}

private JavaFuncUtils() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,35 @@
import io.serverlessworkflow.impl.WorkflowModelFactory;
import io.serverlessworkflow.impl.executors.CallableTask;
import io.serverlessworkflow.impl.resources.ResourceLoader;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

public class JavaFunctionCallExecutor implements CallableTask<CallJava.CallJavaFunction> {
public class JavaFunctionCallExecutor<T, V>
implements CallableTask<CallJava.CallJavaFunction<T, V>> {

private Function function;
private Function<T, V> function;
private Optional<Class<T>> inputClass;

static String fromInt(Integer integer) {
return Integer.toString(integer);
}

public void init(
CallJava.CallJavaFunction task,
CallJava.CallJavaFunction<T, V> task,
Workflow workflow,
WorkflowApplication application,
ResourceLoader loader) {
function = task.function();
inputClass = task.inputClass();
}

@Override
public CompletableFuture<WorkflowModel> apply(
WorkflowContext workflowContext, TaskContext taskContext, WorkflowModel input) {
WorkflowModelFactory modelFactory = workflowContext.definition().application().modelFactory();
return CompletableFuture.completedFuture(
modelFactory.fromAny(function.apply(input.asJavaObject())));
modelFactory.fromAny(function.apply(JavaFuncUtils.convertT(input, inputClass))));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,11 @@
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

class JavaModel implements WorkflowModel {
public class JavaModel implements WorkflowModel {

private Object object;
protected final Object object;

static final JavaModel TrueModel = new JavaModel(Boolean.TRUE);
static final JavaModel FalseModel = new JavaModel(Boolean.FALSE);
static final JavaModel NullModel = new JavaModel(null);

JavaModel(Object object) {
protected JavaModel(Object object) {
this.object = asJavaObject(object);
}

Expand Down
Loading
Loading