-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Javet: Integrate as code execution engine #43
base: main
Are you sure you want to change the base?
Changes from all commits
20a2f24
9e01596
c36b62e
836dda2
0e59751
031f620
034b053
cd7d761
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>dev.langchain4j</groupId> | ||
<artifactId>langchain4j-community</artifactId> | ||
<version>1.0.0-alpha2-SNAPSHOT</version> | ||
<relativePath>../../pom.xml</relativePath> | ||
</parent> | ||
|
||
<artifactId>langchain4j-community-code-execution-engine-javet</artifactId> | ||
<packaging>jar</packaging> | ||
|
||
<name>LangChain4j :: Community :: Integration :: Javet</name> | ||
|
||
<properties> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
<javet.engine.version>4.0.0</javet.engine.version> | ||
</properties> | ||
|
||
<dependencies> | ||
|
||
<dependency> | ||
<groupId>dev.langchain4j</groupId> | ||
<artifactId>langchain4j-core</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
|
||
<!-- Linux and Windows (x86_64) --> | ||
<dependency> | ||
<groupId>com.caoccao.javet</groupId> | ||
<artifactId>javet</artifactId> | ||
<version>${javet.engine.version}</version> | ||
</dependency> | ||
|
||
<!-- Linux (arm64) --> | ||
<dependency> | ||
<groupId>com.caoccao.javet</groupId> | ||
<artifactId>javet-linux-arm64</artifactId> | ||
<version>${javet.engine.version}</version> | ||
</dependency> | ||
|
||
<!-- Mac OS (x86_64 and arm64) --> | ||
<dependency> | ||
<groupId>com.caoccao.javet</groupId> | ||
<artifactId>javet-macos</artifactId> | ||
<version>${javet.engine.version}</version> | ||
</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> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Looks like this dependency is not necessary |
||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.assertj</groupId> | ||
<artifactId>assertj-core</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.mockito</groupId> | ||
<artifactId>mockito-core</artifactId> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Looks like this dependency is not necessary |
||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.mockito</groupId> | ||
<artifactId>mockito-junit-jupiter</artifactId> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Looks like this dependency is not necessary |
||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>dev.langchain4j</groupId> | ||
<artifactId>langchain4j</artifactId> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Looks like this dependency is not necessary |
||
<version>${project.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>dev.langchain4j</groupId> | ||
<artifactId>langchain4j-code-execution-engine-graalvm-polyglot</artifactId> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Looks like this dependency is not necessary |
||
<version>${project.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.tinylog</groupId> | ||
<artifactId>tinylog-impl</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.tinylog</groupId> | ||
<artifactId>slf4j-tinylog</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
</dependencies> | ||
|
||
</project> |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,39 @@ | ||||||
package dev.langchain4j.community.agent; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please move it to |
||||||
|
||||||
import com.caoccao.javet.exceptions.JavetException; | ||||||
import com.caoccao.javet.interop.V8Runtime; | ||||||
import com.caoccao.javet.interop.engine.IJavetEnginePool; | ||||||
import com.caoccao.javet.interop.engine.JavetEngineConfig; | ||||||
import com.caoccao.javet.interop.engine.JavetEnginePool; | ||||||
import com.caoccao.javet.values.V8Value; | ||||||
import dev.langchain4j.code.CodeExecutionEngine; | ||||||
|
||||||
public class V8JavaScriptExecutionEngine implements CodeExecutionEngine { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
WDYT? |
||||||
|
||||||
private final IJavetEnginePool<V8Runtime> javetEnginePool; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this pool does not close properly. |
||||||
|
||||||
public V8JavaScriptExecutionEngine() { | ||||||
this(createDefaultConfig()); | ||||||
} | ||||||
|
||||||
public V8JavaScriptExecutionEngine(JavetEngineConfig config) { | ||||||
javetEnginePool = new JavetEnginePool<>(config); | ||||||
} | ||||||
|
||||||
@Override | ||||||
public String execute(final String code) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
try (V8Value v8Value = | ||||||
javetEnginePool.getEngine().getV8Runtime().getExecutor(code).execute()) { | ||||||
return v8Value.asString(); | ||||||
} catch (JavetException e) { | ||||||
throw new RuntimeException("Execution failed", e); | ||||||
} | ||||||
} | ||||||
|
||||||
private static JavetEngineConfig createDefaultConfig() { | ||||||
JavetEngineConfig config = new JavetEngineConfig(); | ||||||
config.setPoolMaxSize(20); | ||||||
config.setPoolMinSize(10); | ||||||
return config; | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,24 @@ | ||||||
package dev.langchain4j.community.agent; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please move it to |
||||||
|
||||||
import dev.langchain4j.agent.tool.P; | ||||||
import dev.langchain4j.agent.tool.Tool; | ||||||
import dev.langchain4j.code.CodeExecutionEngine; | ||||||
|
||||||
public class V8JavaScriptExecutionTool { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
private final CodeExecutionEngine engine; | ||||||
|
||||||
public V8JavaScriptExecutionTool() { | ||||||
this(new V8JavaScriptExecutionEngine()); | ||||||
} | ||||||
|
||||||
public V8JavaScriptExecutionTool(CodeExecutionEngine engine) { | ||||||
this.engine = engine; | ||||||
} | ||||||
|
||||||
@Tool("MUST be used for accurate calculations: math, sorting, filtering, aggregating, string processing, etc") | ||||||
public String executeJavaScriptCode( | ||||||
@P("JavaScript code to execute, result MUST be returned by the code") String code) { | ||||||
return engine.execute(code); | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package dev.langchain4j.community.agent; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Please always use the same |
||
|
||
import dev.langchain4j.code.CodeExecutionEngine; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.concurrent.*; | ||
import org.junit.jupiter.api.Test; | ||
|
||
class V8JavaScriptExecutionEngineTest { | ||
|
||
CodeExecutionEngine engine = new V8JavaScriptExecutionEngine(); | ||
|
||
@Test | ||
void should_execute_code() { | ||
|
||
String code = | ||
""" | ||
function fibonacci(n) { | ||
if (n <= 1) return n; | ||
return fibonacci(n - 1) + fibonacci(n - 2); | ||
} | ||
|
||
fibonacci(10) | ||
"""; | ||
|
||
String result = engine.execute(code); | ||
|
||
assertThat(result).isEqualTo("55"); | ||
} | ||
|
||
@Test | ||
void testV8RuntimeThreadSafety() throws InterruptedException, ExecutionException { | ||
|
||
V8JavaScriptExecutionEngine engine = new V8JavaScriptExecutionEngine(); | ||
|
||
String code = "'Hello from thread ' + this.threadId"; | ||
|
||
int threadCount = 10; | ||
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(threadCount); | ||
|
||
List<Callable<String>> tasks = new ArrayList<>(); | ||
for (int i = 0; i < threadCount; i++) { | ||
final int threadId = i; | ||
tasks.add(() -> { | ||
try { | ||
// Each thread executes the JavaScript code | ||
return engine.execute(code.replace("this.threadId", Integer.toString(threadId))); | ||
} catch (RuntimeException e) { | ||
return "Execution failed for thread " + threadId + ": " + e.getMessage(); | ||
} | ||
}); | ||
} | ||
|
||
List<Future<String>> results = executor.invokeAll(tasks); | ||
executor.shutdown(); | ||
executor.awaitTermination(1, TimeUnit.MINUTES); | ||
|
||
for (int i = 0; i < threadCount; i++) { | ||
String result = results.get(i).get(); | ||
assertEquals("Hello from thread " + i, result, "Unexpected result in thread " + i); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,6 +66,7 @@ | |
|
||
<!-- Integration of web search engine --> | ||
<module>web-search-engines/langchain4j-community-web-search-engine-searxng</module> | ||
<module>code-execution-engines/langchain4j-code-execution-engine-javet</module> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like the directory name is not correctly. (Missing |
||
|
||
<!-- Spring Boot Starters --> | ||
<module>spring-boot-starters</module> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.