Skip to content

Commit 231c792

Browse files
committed
add llm tools to execute code
1 parent e37c4d6 commit 231c792

File tree

33 files changed

+1601
-109
lines changed

33 files changed

+1601
-109
lines changed

LICENSE

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -175,17 +175,6 @@
175175

176176
END OF TERMS AND CONDITIONS
177177

178-
APPENDIX: How to apply the Apache License to your work.
179-
180-
To apply the Apache License to your work, attach the following
181-
boilerplate notice, with the fields enclosed by brackets "[]"
182-
replaced with your own identifying information. (Don't include
183-
the brackets!) The text should be enclosed in the appropriate
184-
comment syntax for the file format. We also recommend that a
185-
file or class name and description of purpose be included on the
186-
same "printed page" as the copyright notice for easier
187-
identification within third-party archives.
188-
189178
Copyright 2025 Fu Cheng
190179

191180
Licensed under the Apache License, Version 2.0 (the "License");

container-image-generator/container-images/java/base-21/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ ADD ./app/Main.java /app/src/main/java/Main.java
55

66
WORKDIR /app
77

8-
RUN mvn compile exec:java
8+
RUN mvn -Dexec.mainClass=Main compile exec:java
99

1010
FROM maven:3.9.9-eclipse-temurin-21
1111
COPY --from=build /root/.m2 /root/.m2

container-image-generator/container-images/java/base-21/app/pom.xml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.javaaidev.llmcodeexecutor</groupId>
88
<artifactId>generate-app</artifactId>
9-
<version>0.1.0</version>
9+
<version>0.2.0</version>
1010

1111
<properties>
1212
<java.version>21</java.version>
@@ -56,9 +56,6 @@
5656
</goals>
5757
</execution>
5858
</executions>
59-
<configuration>
60-
<mainClass>Main</mainClass>
61-
</configuration>
6259
</plugin>
6360
</plugins>
6461
</build>
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[project]
22
name = "llm-code-executor"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
requires-python = ">=3.12"
55
dependencies = [
6-
"numpy",
7-
"pandas",
8-
"seaborn",
9-
"tabulate",
10-
"sympy"
6+
"numpy",
7+
"pandas",
8+
"seaborn",
9+
"tabulate",
10+
"sympy"
1111

1212
]

container-image-generator/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>com.javaaidev.llmcodeexecutor</groupId>
88
<artifactId>llm-code-executor</artifactId>
9-
<version>0.1.0</version>
9+
<version>0.2.0</version>
1010
</parent>
1111

1212
<artifactId>container-image-generator</artifactId>

container-image-generator/src/main/kotlin/com/javaaidev/llmcodeexecutor/containerimagegenerator/ContainerImageGeneratorCli.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class ReusableOptions {
2323
@Command(
2424
name = "llm-code-executor",
2525
mixinStandardHelpOptions = true,
26-
version = ["0.1.0"],
26+
version = ["0.2.0"],
2727
description = ["Generate container image for LLM code execution"],
2828
scope = CommandLine.ScopeType.INHERIT,
2929
subcommands = [

container-image-generator/src/main/resources/templates/java/pom.xml.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.javaaidev.llmcodeexecutor</groupId>
88
<artifactId>generate-app</artifactId>
9-
<version>0.1.0</version>
9+
<version>0.2.0</version>
1010

1111
<properties>
1212
<java.version>{{javaVersion}}</java.version>

container-image-generator/src/main/resources/templates/python/pyproject.toml.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "llm-code-executor"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
requires-python = ">={{pythonVersion}}"
55
dependencies = [
66
{{#each dependencies}}"{{.}}"{{#unless @last}},{{/unless}}

core/pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>com.javaaidev.llmcodeexecutor</groupId>
88
<artifactId>llm-code-executor</artifactId>
9-
<version>0.1.0</version>
9+
<version>0.2.0</version>
1010
</parent>
1111

1212
<artifactId>core</artifactId>
@@ -35,6 +35,11 @@
3535
</build>
3636

3737
<dependencies>
38+
<dependency>
39+
<groupId>com.javaaidev.llmcodeexecutor</groupId>
40+
<artifactId>code-executor-model</artifactId>
41+
<version>0.2.0</version>
42+
</dependency>
3843
<dependency>
3944
<groupId>com.github.docker-java</groupId>
4045
<artifactId>docker-java-core</artifactId>

core/src/main/kotlin/com/javaaidev/llmcodeexecutor/core/LLMCodeExecutor.kt renamed to core/src/main/kotlin/com/javaaidev/llmcodeexecutor/executor/core/LLMCodeExecutor.kt

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.javaaidev.llmcodeexecutor.core
1+
package com.javaaidev.llmcodeexecutor.executor.core
22

33
import com.github.dockerjava.api.async.ResultCallback
44
import com.github.dockerjava.api.exception.NotModifiedException
@@ -7,6 +7,10 @@ import com.github.dockerjava.core.DefaultDockerClientConfig
77
import com.github.dockerjava.core.DockerClientConfig
88
import com.github.dockerjava.core.DockerClientImpl
99
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient
10+
import com.javaaidev.llmcodeexecutor.executor.model.CopiedFile
11+
import com.javaaidev.llmcodeexecutor.executor.model.ExecuteCodeParameters
12+
import com.javaaidev.llmcodeexecutor.executor.model.ExecuteCodeReturnType
13+
import com.javaaidev.llmcodeexecutor.executor.model.LoadedFile
1014
import org.slf4j.LoggerFactory
1115
import java.io.Closeable
1216
import java.nio.file.Files
@@ -34,33 +38,14 @@ data class CodeExecutorConfig(
3438
val containerOutputDirectory: String? = null,
3539
)
3640

37-
data class CodeExecutionRequest(
38-
val code: String,
39-
val outputFileCollectionConfig: OutputFileCollectionConfig? = null,
40-
)
41-
42-
data class OutputFileCollectionConfig(
43-
val loadFiles: Boolean? = false,
44-
val copyFiles: Boolean? = false,
45-
val copiedFilesPath: String? = null,
46-
val includedFilePattern: String? = null,
47-
)
48-
49-
data class OutputFileContent(
50-
val mimeType: String,
51-
val data: String,
52-
)
53-
54-
data class CopiedFile(
55-
val path: String,
56-
)
41+
fun ExecuteCodeParameters.withDefaultIncludedFilePattern(includedFilePattern: String?) {
42+
this.outputFileCollectionConfig?.let { config ->
43+
if (config.includedFilePattern == null) {
44+
config.includedFilePattern = includedFilePattern
45+
}
46+
}
47+
}
5748

58-
data class CodeExecutionResponse(
59-
val output: String,
60-
val error: String? = null,
61-
val loadedFiles: List<OutputFileContent>? = null,
62-
val copiedFiles: List<CopiedFile>? = null,
63-
)
6449

6550
/**
6651
* Execute code for LLM
@@ -81,9 +66,13 @@ class LLMCodeExecutor(
8166
.build()
8267
private val dockerClient = DockerClientImpl.getInstance(dockerClientConfig, httpClient)
8368

84-
fun execute(request: CodeExecutionRequest): CodeExecutionResponse {
85-
pullImage()
69+
init {
70+
logger.info("Use docker client connecting to {}", dockerClientConfig.dockerHost)
71+
}
8672

73+
fun execute(request: ExecuteCodeParameters): ExecuteCodeReturnType {
74+
logger.info("Starting to run code: {}", request)
75+
pullImage()
8776
val cmd = dockerClient.createContainerCmd(config.containerImage)
8877
config.volumes?.let { volumes ->
8978
cmd.withVolumes(volumes.map { Volume(it) })
@@ -155,7 +144,7 @@ class LLMCodeExecutor(
155144
// ignore
156145
}
157146
val copiedFiles = mutableListOf<CopiedFile>()
158-
val loadedFiles = mutableListOf<OutputFileContent>()
147+
val loadedFiles = mutableListOf<LoadedFile>()
159148
request.outputFileCollectionConfig?.let { collectionConfig ->
160149
if (config.containerOutputDirectory != null && (collectionConfig.loadFiles == true || collectionConfig.copyFiles == true)) {
161150
val response = dockerClient.inspectContainerCmd(containerId).exec()
@@ -179,14 +168,14 @@ class LLMCodeExecutor(
179168
val mimeType = Files.probeContentType(path)
180169
if (mimeType.startsWith("text/")) {
181170
loadedFiles.add(
182-
OutputFileContent(
171+
LoadedFile(
183172
mimeType,
184173
Files.readString(path)
185174
)
186175
)
187176
} else {
188177
loadedFiles.add(
189-
OutputFileContent(
178+
LoadedFile(
190179
mimeType,
191180
Base64.getMimeEncoder()
192181
.encodeToString(Files.readAllBytes(path))
@@ -201,15 +190,21 @@ class LLMCodeExecutor(
201190

202191
dockerClient.removeContainerCmd(containerId).exec()
203192
logger.info("Container removed {}", containerId)
204-
return CodeExecutionResponse(
193+
return ExecuteCodeReturnType(
205194
outputBuilder.toString(),
206195
errorBuilder.toString(),
207196
loadedFiles,
208197
copiedFiles
209-
)
198+
).also { logger.info("Code execution result: {}", it) }
210199
}
211200

212201
private fun pullImage() {
202+
val existingImages =
203+
dockerClient.listImagesCmd().withReferenceFilter(config.containerImage).exec()
204+
if (existingImages.isNotEmpty()) {
205+
logger.info("Image exists, skip pulling")
206+
return
207+
}
213208
logger.info("Start pulling image {}", config.containerImage)
214209
val pullImageCountDownLatch = CountDownLatch(1)
215210
dockerClient.pullImageCmd(config.containerImage)

executor-model/pom.xml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
7+
<parent>
8+
<groupId>com.javaaidev.llmcodeexecutor</groupId>
9+
<artifactId>llm-code-executor</artifactId>
10+
<version>0.2.0</version>
11+
</parent>
12+
13+
14+
<groupId>com.javaaidev.llmcodeexecutor</groupId>
15+
<artifactId>code-executor-model</artifactId>
16+
<version>0.2.0</version>
17+
<packaging>jar</packaging>
18+
19+
<name>ExecuteCode</name>
20+
<description>Execute code</description>
21+
22+
<properties>
23+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
24+
<maven.compiler.source>1.8</maven.compiler.source>
25+
<maven.compiler.target>1.8</maven.compiler.target>
26+
</properties>
27+
28+
<dependencies>
29+
<dependency>
30+
<groupId>com.javaaidev.easyllmtools</groupId>
31+
<artifactId>llm-tool-spec</artifactId>
32+
<version>0.1.8</version>
33+
</dependency>
34+
</dependencies>
35+
36+
<build>
37+
<sourceDirectory>src/main/java</sourceDirectory>
38+
<plugins>
39+
<plugin>
40+
<groupId>org.apache.maven.plugins</groupId>
41+
<artifactId>maven-compiler-plugin</artifactId>
42+
<version>3.11.0</version>
43+
<configuration>
44+
<source>${maven.compiler.source}</source>
45+
<target>${maven.compiler.target}</target>
46+
</configuration>
47+
</plugin>
48+
</plugins>
49+
</build>
50+
</project>

0 commit comments

Comments
 (0)