diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3a83431..f3c17f3 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -7,7 +7,7 @@
-
+
\ No newline at end of file
diff --git a/API/src/main/java/me/zacharias/chat/api/controllers/Tool.java b/API/src/main/java/me/zacharias/chat/api/controllers/Tool.java
index d025833..e890f6b 100644
--- a/API/src/main/java/me/zacharias/chat/api/controllers/Tool.java
+++ b/API/src/main/java/me/zacharias/chat/api/controllers/Tool.java
@@ -34,7 +34,7 @@ public class Tool {
}
return ResponseEntity.ok(new NewToolResponse(request.getName(), request.getDescription(), arguments));
} else {
- return ResponseEntity.status(400).body("Tool already exists");
+ return ResponseEntity.badRequest().body("Tool already exists");
}
}
}
diff --git a/Core/src/main/java/me/zacharias/chat/core/files/FileHandler.java b/Core/src/main/java/me/zacharias/chat/core/files/FileHandler.java
index 54deed2..f9cd9df 100644
--- a/Core/src/main/java/me/zacharias/chat/core/files/FileHandler.java
+++ b/Core/src/main/java/me/zacharias/chat/core/files/FileHandler.java
@@ -1,11 +1,16 @@
package me.zacharias.chat.core.files;
import me.zacharias.chat.core.Core;
+import me.zacharias.chat.core.Pair;
+import me.zacharias.chat.core.files.tools.ReadFileTool;
+import me.zacharias.chat.ollama.OllamaTool;
import org.intellij.lang.annotations.MagicConstant;
import java.io.*;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.util.ArrayList;
import java.util.Arrays;
/**
@@ -20,7 +25,7 @@ public class FileHandler {
/**
* The directory used as base for this instance of {@link FileHandler}. This is where all files that can be read or writen will be located
*/
- private final File/*System*/ directory;
+ private final Path/*System*/ root;
/**
* Creates a new instance as well as setting the {@link #instance} to this new one
@@ -28,19 +33,41 @@ public class FileHandler {
*/
public FileHandler(@MagicConstant(valuesFromClass = FileHandlerLocation.class) String baseDirectory) {
try {
- FileSystem fs = FileSystems.newFileSystem(new File(baseDirectory).toPath());
- //fs.getPath()
- directory = new File(baseDirectory);
- if (!directory.exists())
- directory.mkdirs();
+ root = Path.of(baseDirectory).toAbsolutePath().normalize();
+ if (!root.toFile().exists()) {
+ root.toFile().mkdirs();
+ }
instance = this;
}catch (Exception ex)
{
+ ex.printStackTrace();
throw new FileHandlerException("Failed to create FileHandler instance with base directory \"" + baseDirectory + "\"");
}
}
+ public static FileHandler getInstance() {
+ return instance;
+ }
+
+ /**
+ * Returns a list of all {@link me.zacharias.chat.ollama.OllamaTool}'s this module adds
+ * @return
+ */
+ public static ArrayList> getTools() {
+ ArrayList> tools = new ArrayList<>();
+
+ tools.add(new Pair<>(new ReadFileTool(), Core.Source.INTERNAL));
+
+ return tools;
+ }
+
+ public Path resolve(String relative) throws IOException{
+ Path p = root.resolve(relative).normalize();
+ if (!p.startsWith(root)) throw new IOException("Access denied");
+ return p;
+ }
+
/**
*
* @param filename
@@ -48,11 +75,12 @@ public class FileHandler {
* @throws FileHandlerException
*/
public String readFile(String filename) throws FileHandlerException {
- if(filename.contains(".."))
- {
- throw new FileHandlerException("File \"" + filename + "\" tries to retrace path");
+ File file = null;
+ try {
+ file = resolve(filename).toFile();
+ } catch (IOException e) {
+ throw new FileHandlerException("Illegal restricted path");
}
- File file = new File(directory, filename);
if(file.exists())
{
try{
@@ -82,4 +110,13 @@ public class FileHandler {
}
throw new FileHandlerException("Cant find file \""+filename+"\"");
}
+
+ /**
+ * Provides a relative path from {@link FileHandler#root} to file
+ * @param file the file to be relativised
+ * @return the relative path from {@link FileHandler#root} to file
+ */
+ public String path(File file) {
+ return root.relativize(file.toPath()).toString();
+ }
}
diff --git a/Core/src/main/java/me/zacharias/chat/core/files/tools/ReadFileTool.java b/Core/src/main/java/me/zacharias/chat/core/files/tools/ReadFileTool.java
new file mode 100644
index 0000000..9b46c37
--- /dev/null
+++ b/Core/src/main/java/me/zacharias/chat/core/files/tools/ReadFileTool.java
@@ -0,0 +1,77 @@
+package me.zacharias.chat.core.files.tools;
+
+import me.zacharias.chat.core.files.FileHandler;
+import me.zacharias.chat.ollama.OllamaFunctionArgument;
+import me.zacharias.chat.ollama.OllamaFunctionTool;
+import me.zacharias.chat.ollama.OllamaPerameter;
+import me.zacharias.chat.ollama.OllamaToolRespnce;
+import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException;
+
+import java.io.*;
+import java.nio.file.Path;
+
+public class ReadFileTool extends OllamaFunctionTool {
+ FileHandler fs = FileHandler.getInstance();
+ @Override
+ public String name() {
+ return "read_file";
+ }
+
+ @Override
+ public String description() {
+ return "Reads the file of path or null if that file dosent exists";
+ }
+
+ @Override
+ public OllamaPerameter parameters() {
+ return OllamaPerameter.builder()
+ .addProperty("file_path", OllamaPerameter.OllamaPerameterBuilder.Type.STRING, "The path to the file to be read")
+ .build();
+ }
+
+ @Override
+ public OllamaToolRespnce function(OllamaFunctionArgument... args) {
+ String orgPath = null;
+ for (OllamaFunctionArgument arg : args) {
+ if(arg.argument().equals("file_path")) {
+ orgPath = (String) arg.value();
+ }
+ }
+
+ if(orgPath == null) {
+ throw new OllamaToolErrorException(this.name(), "Missing required argument 'file_path'");
+ }
+
+ Path filePath = null;
+
+ try{
+ filePath = fs.resolve(orgPath);
+ }
+ catch (IOException ex) {
+ throw new OllamaToolErrorException(this.name(), ex);
+ }
+
+ File file = filePath.toFile();
+ if(!file.exists()) {
+ throw new OllamaToolErrorException(this.name(), "File does not exist: " + fs.path(file));
+ }
+
+ BufferedReader br = null;
+ try{
+ br = new BufferedReader(new FileReader(file));
+ }catch (FileNotFoundException ex) {
+ throw new OllamaToolErrorException(this.name(), "File not found: " + fs.path(file));
+ }
+ StringBuilder sb = new StringBuilder();
+ String tmp = null;
+ try {
+ while ((tmp = br.readLine()) != null) {
+ sb.append(tmp).append("\n");
+ }
+ }
+ catch (IOException e) {
+ throw new OllamaToolErrorException(this.name(), "Error reading file: " + fs.path(file));
+ }
+ return new OllamaToolRespnce(this.name(), sb.toString());
+ }
+}
diff --git a/Core/src/main/java/me/zacharias/chat/ollama/OllamaObject.java b/Core/src/main/java/me/zacharias/chat/ollama/OllamaObject.java
index 6b99b2b..a375741 100644
--- a/Core/src/main/java/me/zacharias/chat/ollama/OllamaObject.java
+++ b/Core/src/main/java/me/zacharias/chat/ollama/OllamaObject.java
@@ -416,7 +416,8 @@ public class OllamaObject {
* @param tools The tools to add
* @return The {@link OllamaObjectBuilder}
*/
- public OllamaObjectBuilder addTools(Pair... tools) {
+ @SafeVarargs
+ public final OllamaObjectBuilder addTools(Pair... tools) {
this.tools.addAll(List.of(tools));
return this;
}
@@ -453,11 +454,10 @@ public class OllamaObject {
public OllamaObjectBuilder addFileTools(@MagicConstant(valuesFromClass = FileHandlerLocation.class) String baseDirectory)
{
- FileHandler fileHandler = new FileHandler(baseDirectory);
+ new FileHandler(baseDirectory);
- if(false);
-
- throw new IllegalArgumentException("FileHandler is not supported yet!");
+ //throw new IllegalArgumentException("FileHandler is not supported yet!");
+ return addTools(FileHandler.getTools());
}
/**
diff --git a/Core/src/main/java/me/zacharias/chat/ollama/exceptions/OllamaToolErrorException.java b/Core/src/main/java/me/zacharias/chat/ollama/exceptions/OllamaToolErrorException.java
index d90e470..abfb846 100644
--- a/Core/src/main/java/me/zacharias/chat/ollama/exceptions/OllamaToolErrorException.java
+++ b/Core/src/main/java/me/zacharias/chat/ollama/exceptions/OllamaToolErrorException.java
@@ -27,6 +27,10 @@ public class OllamaToolErrorException extends RuntimeException {
this.tool = tool;
this.error = error;
}
+
+ public OllamaToolErrorException(String tool, Exception ex) {
+ this(tool, ex.getMessage());
+ }
/**
* Gets the tool that caused the error.
diff --git a/Display/src/main/java/me/zacharias/chat/display/Display.java b/Display/src/main/java/me/zacharias/chat/display/Display.java
index a153c56..081c3d0 100644
--- a/Display/src/main/java/me/zacharias/chat/display/Display.java
+++ b/Display/src/main/java/me/zacharias/chat/display/Display.java
@@ -50,10 +50,10 @@ public class Display {
{
core.setOllamaObject/*NoMemory*/(OllamaObject.builder()
- .setModel("llama3.2")
+ .setModel("llama3.1:8b")
.keep_alive(10)
//.stream(false)
- //.addFileTools(FileHandlerLocation.DATA_FILES)
+ .addFileTools(FileHandlerLocation.DATA_FILES)
.addMessages(new SystemMessage("You need to emulate feelings and emotions."))
.build());
@@ -61,13 +61,12 @@ public class Display {
core.addTool(new TimeTool(), Core.Source.INTERNAL);
// TODO: Well Docker failes when luanched.... Fuck
- PythonRunner pythonRunner = new PythonRunner(core);
- core.addTool(pythonRunner, Core.Source.INTERNAL);
- //core.addTools(new MALAPITool().getOllamaTools());
- //core.addTools(new GeniusTools().getGeniusTools());
- //core.addTools(new WikipediaTool().getWikipediaToolsInstance());
+ core.addTool(new PythonRunner(core), Core.Source.INTERNAL);
+ core.addTools(new MALAPITool().getOllamaTools());
+ core.addTools(new GeniusTools().getGeniusTools());
+ core.addTools(new WikipediaTool().getWikipediaToolsInstance());
- APIApplication.start();
+ //APIApplication.start();
//core.getOllamaObject().addMessage(new OllamaMessage(OllamaMessageRole.SYSTEM, "Have a nice tone and use formal wording"));
diff --git a/Display/src/main/java/me/zacharias/chat/display/PythonRunner.java b/Display/src/main/java/me/zacharias/chat/display/PythonRunner.java
index 7b42026..cbeef69 100644
--- a/Display/src/main/java/me/zacharias/chat/display/PythonRunner.java
+++ b/Display/src/main/java/me/zacharias/chat/display/PythonRunner.java
@@ -100,7 +100,21 @@ public class PythonRunner extends OllamaFunctionTool {
continue;
}
- outputBuffers.getOrDefault(containerId, new StringBuilder()).append(data.optString("text", ""));
+ outputBuffers.compute(containerId, (k, buf) -> {
+ if(buf == null) {
+ buf = new StringBuilder();
+ }
+ buf.append(data.optString("text", ""));
+ buf.append(System.lineSeparator());
+ return buf;
+ });
+ out.write(new JSONObject().put("container_id", containerId).toString());
+ out.newLine();
+ out.flush();
+ out.close();
+ in.close();
+ socket.close();
+ continue;
}
List> list = core.getFuntionTools().stream().filter(funtionTool -> funtionTool.getKey().name().equalsIgnoreCase(toolName)).toList();
@@ -155,7 +169,6 @@ public class PythonRunner extends OllamaFunctionTool {
.maxConnections(10)
.connectionTimeout(Duration.ofSeconds(100))
.responseTimeout(Duration.ofSeconds(100))
- .sslConfig(config.getSSLConfig())
.build();
DockerHttpClient.Request ping = DockerHttpClient.Request.builder()
@@ -343,15 +356,17 @@ public class PythonRunner extends OllamaFunctionTool {
File f = new File("./pythonFiles", "external_tools.py");
String containerId = dockerClient.createContainerCmd("archlinux")
- .withCmd("/bin/bash","./cmd.sh")
+ .withCmd("/bin/bash","/cmd.sh")
.withHostConfig(HostConfig.newHostConfig()
.withExtraHosts("host.docker.internal:host-gateway"))
.exec().getId();
+ outputBuffers.put(containerId, new StringBuilder());
+
try {
String external_tools = generateExternalTools(containerId);
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
- bw.write(external_tools.replace("\\n", "\n"));
+ bw.write(external_tools/*.replace("\\n", "\n").replace("\\!n", "\\n")*/);
bw.flush();
bw.close();
}catch(IOException e) {}
@@ -369,8 +384,8 @@ public class PythonRunner extends OllamaFunctionTool {
pacman --noconfirm -S python python-pip > /dev/null
mkdir pythonRun > /dev/null
python -m venv ./pythonRun > /dev/null
- cp external_tools.py ./pythonRun > /dev/null
- cp\s""")
+ cp /external_tools.py ./pythonRun > /dev/null
+ cp\s/""")
.append(name).append("""
\s./pythonRun > /dev/null
cd pythonRun > /dev/null
@@ -389,7 +404,6 @@ public class PythonRunner extends OllamaFunctionTool {
cmd.append("python ").append(name);//.append(" exit");
- pythonArgs.add("-c");
pythonArgs.add(cmd.toString());
StringBuilder fullCmd = new StringBuilder();
@@ -424,32 +438,16 @@ public class PythonRunner extends OllamaFunctionTool {
dockerClient.startContainerCmd(containerId).exec();
- GetContainerLog log = new GetContainerLog(dockerClient, containerId);
+ dockerClient.waitContainerCmd(containerId).start().awaitCompletion();
- List logs = new ArrayList<>();
+ String output = outputBuffers.remove(containerId).toString();
- do {
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- logs.addAll(log.getDockerLogs());
- }
- while (isRunning(containerId));
+ dockerClient.removeContainerCmd(containerId).exec();
- StringBuilder output = new StringBuilder();
-
- for (String s : logs) {
- output.append(s).append("\n");
- }
-
- //writeLog("Result from python: " + output.toString());
-
- return new OllamaToolRespnce(name(), output.toString());
+ return new OllamaToolRespnce(name(), output.isEmpty() ? "Code ran successfully with no output" : output);
}
catch (Exception e) {
- throw new OllamaToolErrorException(name(), "Docker unavalible");
+ throw new OllamaToolErrorException(name(), "Docker unavailable");
}
}
@@ -488,15 +486,24 @@ public class PythonRunner extends OllamaFunctionTool {
boolean first = true;
try {
- for (String argName : tool.parameters().getProperties().keySet()) {
+ for(String argName : tool.parameters().getRequired())
+ {
args.add(argName);
if (!first) {
code.append(", ");
}
code.append(argName);
- if (Arrays.stream(tool.parameters().getRequired()).noneMatch(required -> required.equals(argName))) {
- code.append("=None");
+ first = false;
+ }
+
+ for (String argName : tool.parameters().getProperties().keySet()) {
+ if(Arrays.asList(tool.parameters().getRequired()).contains(argName)) continue;
+
+ args.add(argName);
+ if (!first) {
+ code.append(", ");
}
+ code.append(argName).append("=None");
first = false;
}
}catch (Exception e) {}
@@ -526,69 +533,4 @@ public class PythonRunner extends OllamaFunctionTool {
return code.toString();
}
-
- /**
- * Checks if a Docker Container is running
- * @param containerId The ID of the Container
- * @return a boolean weather it's running or not
- */
- public boolean isRunning(String containerId)
- {
- InspectContainerResponse cmd = dockerClient.inspectContainerCmd(containerId).exec();
- return Boolean.TRUE.equals(cmd.getState().getRunning());
- }
-
- /**
- * A Helper class to get the logs from a docker container.
- */
- public class GetContainerLog {
- private DockerClient dockerClient;
- private String containerId;
- private int lastLogTime;
-
- private static String nameOfLogger = "dockertest.PrintContainerLog";
- private static Logger myLogger = Logger.getLogger(nameOfLogger);
-
- /**
- * Creates a new instance of {@link GetContainerLog}
- * @param dockerClient The DockerClient instance
- * @param containerId The container id
- */
- public GetContainerLog(DockerClient dockerClient, String containerId) {
- this.dockerClient = dockerClient;
- this.containerId = containerId;
- this.lastLogTime = (int) (System.currentTimeMillis() / 1000);
- }
-
- /**
- * Gets the logs of the container.
- * @return The logs of the container
- */
- public List getDockerLogs() {
-
- final List logs = new ArrayList<>();
-
- LogContainerCmd logContainerCmd = dockerClient.logContainerCmd(containerId);
- logContainerCmd.withStdOut(true).withStdErr(true);
- logContainerCmd.withSince(lastLogTime); // UNIX timestamp (integer) to filter logs. Specifying a timestamp will only output log-entries since that timestamp.
- // logContainerCmd.withTail(4); // get only the last 4 log entries
-
- logContainerCmd.withTimestamps(true);
-
- try {
- logContainerCmd.exec(new ResultCallback.Adapter() {
- @Override
- public void onNext(Frame item) {
- logs.add(new String(item.getPayload()).trim());
- }
- }).awaitCompletion();
- } catch (InterruptedException e) {
- myLogger.severe("Interrupted Exception!" + e.getMessage());
- }
-
- lastLogTime = (int) (System.currentTimeMillis() / 1000) + 5; // assumes at least a 5 second wait between calls to getDockerLogs
-
- return logs;
- }
- }
}
diff --git a/GeniusAPI/build.gradle b/GeniusAPI/build.gradle
index 3250df5..e4d6d31 100644
--- a/GeniusAPI/build.gradle
+++ b/GeniusAPI/build.gradle
@@ -14,7 +14,7 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter'
implementation "org.jsoup:jsoup:1.20.1"
- implementation 'io.github.classgraph:classgraph:4.8.158'
+ implementation 'io.github.classgraph:classgraph:4.8.184'
implementation project(":Core")
}
diff --git a/MALAPITool/build.gradle b/MALAPITool/build.gradle
index d93b3a7..cb0882f 100644
--- a/MALAPITool/build.gradle
+++ b/MALAPITool/build.gradle
@@ -15,7 +15,7 @@ dependencies {
implementation project(":Core")
- implementation 'io.github.classgraph:classgraph:4.8.158'
+ implementation 'io.github.classgraph:classgraph:4.8.184'
}
test {
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..02f59c4
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,2 @@
+# This is used in sub-project that dosent explicitly require the API sub-project to only include if thay shuld be included project wide.
+useAPI = true
\ No newline at end of file
diff --git a/launcher/build.gradle b/launcher/build.gradle
index 4d73288..b799b87 100644
--- a/launcher/build.gradle
+++ b/launcher/build.gradle
@@ -7,7 +7,6 @@ version = '1.0-SNAPSHOT'
dependencies {
implementation project(":Display")
- implementation project(":API")
implementation project(":Core")
}
diff --git a/launcher/src/main/java/me/zacharias/chat/launcher/Launcher.java b/launcher/src/main/java/me/zacharias/chat/launcher/Launcher.java
index df5ee42..1269157 100644
--- a/launcher/src/main/java/me/zacharias/chat/launcher/Launcher.java
+++ b/launcher/src/main/java/me/zacharias/chat/launcher/Launcher.java
@@ -1,7 +1,6 @@
package me.zacharias.chat.launcher;
//import me.zacharias.chat.api.APIApplication;
-import me.zacharias.chat.api.APIApplication;
import me.zacharias.chat.core.LaunchOptions;
import me.zacharias.chat.display.Display;
@@ -93,7 +92,8 @@ public class Launcher {
if (options.isServerMode()) {
System.out.println("Starting in API mode...");
try {
- APIApplication.start();
+ Class> clazz = Class.forName("me.zacharias.chat.api.APIApplication");
+ clazz.getMethod("start").invoke(null);
}catch (Exception e)
{
System.out.println("Failed to start API server: " + e.getMessage());