diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..0a43fc3 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +AI-test \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/src/main/java/me/zacharias/chat/api/APIEndpoints.java b/API/src/main/java/me/zacharias/chat/api/APIEndpoints.java index 7063d63..80a4aaf 100644 --- a/API/src/main/java/me/zacharias/chat/api/APIEndpoints.java +++ b/API/src/main/java/me/zacharias/chat/api/APIEndpoints.java @@ -1,12 +1,28 @@ package me.zacharias.chat.api; +/** + * API Endpoints + * see API Docs + */ public enum APIEndpoints { // API request endpoints + /** + * Requests a tool to be added to the environment + */ ADD_TOOL, + /** + * Requests a query to be executed on the environment + */ QUERY, // API response endpoints + /** + * Response to a tool request containing the Ollama response + */ RESPONSE, + /** + * Response to use a tool defined by the API Client + */ USE_TOOL, } diff --git a/API/src/main/java/me/zacharias/chat/api/APIServer.java b/API/src/main/java/me/zacharias/chat/api/APIServer.java index 5e8b91e..478aadb 100644 --- a/API/src/main/java/me/zacharias/chat/api/APIServer.java +++ b/API/src/main/java/me/zacharias/chat/api/APIServer.java @@ -15,11 +15,29 @@ import java.util.ArrayList; import java.util.Date; import java.util.Scanner; +/** + * The API server.
+ * This class is responsible for handling the server socket and the clients for the API.
+ * It also handles the output redirection and the message printing.
+ * And the Registration of Tools on the {@link Core} object. + */ public class APIServer { + /** + * The list of clients connected to the server. + */ ArrayList clientsList = new ArrayList<>(); + /** + * The server socket. + */ ServerSocket serverSocket; + /** + * The output stream for the server. + */ PrintStream dataOut; - + + /** + * The message handler for the server. + */ PrintMessageHandler printMessageHandler = new PrintMessageHandler() { @Override public void printMessage(String message) { @@ -40,11 +58,14 @@ public class APIServer { return false; } }; - + + /** + * The core object for the server. + */ Core core = new Core(printMessageHandler); /** - * Options foir this is expected to be passed thru the {@link LaunchOptions#instance} object.
+ * Options for this is expected to be passed through the {@link LaunchOptions#instance} object.
* Used objects:
* - {@link LaunchOptions#autoAccept}
* - {@link LaunchOptions#redirectOutput}
@@ -58,12 +79,15 @@ public class APIServer { core.setOllamaObject(OllamaObject.builder() .setModel("llama3-AI") .keep_alive(10) - .stream(false) + //.stream(false) .build()); - if (!Paths.get(redirectedOutput).toFile().getParentFile().exists()) { + if (redirectedOutput != null && !Paths.get(redirectedOutput).toFile().getParentFile().exists()) { System.out.println("Failed to be able to open the redirected output file due to missing directory"); } + else { + redirectedOutput = "./out.txt"; + } File f = new File(redirectedOutput); @@ -121,6 +145,19 @@ public class APIServer { System.exit(1); return; } + + System.out.println("Redirecting output to [" + redirectedOutput + "]"); + System.out.println("Starting server on port [" + port + "]"); + + try{ + serverSocket = new ServerSocket(port); + + } + catch(Exception e){ + System.out.println("Failed to start server on port [" + port + "]"); + System.exit(1); + return; + } //serverSocket = new ServerSocket(port); } diff --git a/API/src/main/java/me/zacharias/chat/api/Client.java b/API/src/main/java/me/zacharias/chat/api/Client.java index 878bb0e..c22bc23 100644 --- a/API/src/main/java/me/zacharias/chat/api/Client.java +++ b/API/src/main/java/me/zacharias/chat/api/Client.java @@ -4,16 +4,28 @@ import java.io.BufferedWriter; import java.io.OutputStreamWriter; import java.net.Socket; +/** + * The client object for the API server. + */ public class Client { - + + /** + * The socket for the client. + */ Socket socket; - + + /** + * Creates a new client object. + * @param socket the socket for the client. + */ public Client(Socket socket) { this.socket = socket; } /** * Returnes true unless if the method failes + * @param message the message to send to the client. + * @return true if the message was sent successfully, false otherwise. */ public boolean sendMessage(String message) { try(BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) { diff --git a/Core/src/main/java/me/zacharias/chat/core/Core.java b/Core/src/main/java/me/zacharias/chat/core/Core.java index 548c0b0..a5aa706 100644 --- a/Core/src/main/java/me/zacharias/chat/core/Core.java +++ b/Core/src/main/java/me/zacharias/chat/core/Core.java @@ -5,6 +5,7 @@ import me.zacharias.chat.core.memory.GetMemoryFunction; import me.zacharias.chat.core.memory.RemoveMemoryFunction; import me.zacharias.chat.ollama.*; import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException; +import org.intellij.lang.annotations.MagicConstant; import org.json.JSONArray; import org.json.JSONObject; @@ -18,19 +19,52 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +/** + * The Main class for the System, responsible for managing the OllamaObject, tools, and the Ollama API. + */ public class Core { + /** + * The file to write the logs to. + */ private static File logFile = new File("./logs/latest.log"); + /** + * The writer to write the logs to. + */ private static BufferedWriter logWriter; + /** + * The scheduler to schedule the log flushing. + */ private ScheduledExecutorService scheduler; - + + /** + * The OllamaObject to use. + */ private OllamaObject ollamaObject; - private ArrayList> funtionTools = new ArrayList<>(); - + /** + * The list of tools to use. + */ + private ArrayList> funtionTools = new ArrayList<>(); + + /** + * The IP of the Ollama API. + */ private String ollamaIP = "localhost";//"192.168.5.184"; + /** + * The port of the Ollama API. + */ private int ollamaPort = 11434; + /** + * The URL of the Ollama API. + */ private URL url; - + + /** + * The PrintMessageHandler to use. + */ private final PrintMessageHandler printMessageHandler; + /** + * If color is supported by the PrintMessageHandler. + */ private boolean supportColor; { @@ -125,24 +159,28 @@ public class Core { } })); } - + + /** + * Creates a new instance of Core with the provided PrintMessageHandler + * @param printMessageHandler The PrintMessageHandler to use as the default Output + */ public Core(PrintMessageHandler printMessageHandler) { this.printMessageHandler = printMessageHandler; supportColor = printMessageHandler.color(); } /** - * Sets the {@link ollamaObject} object to the provided argument, - * Aslo adds the memory base system. see {@link Core#setOllamaObjectNoMemory} if you don't want to add memory functions - * @param ollamaObject + * Sets the {@link #ollamaObject} object to the provided argument, + * Also adds the memory base system. see {@link Core#setOllamaObjectNoMemory} if you don't want to add memory functions + * @param ollamaObject The OllamaObject to use */ public void setOllamaObject(OllamaObject ollamaObject) { if(this.ollamaObject == null) { this.ollamaObject = ollamaObject; - addTool(new AddMemoryFunction(), "Core"); - addTool(new RemoveMemoryFunction(), "Core"); - addTool(new GetMemoryFunction(), "Core"); + addTool(new AddMemoryFunction(), Source.CORE); + addTool(new RemoveMemoryFunction(), Source.CORE); + addTool(new GetMemoryFunction(), Source.CORE); } else { throw new IllegalArgumentException("Ollama object is already set"); @@ -150,9 +188,9 @@ public class Core { } /** - * Sets the {@link Core#ollamaObject} object to the provided argument, - * Dose not add the base system for memory. see {@link Core#setOllamaObject} if you want to add memory function - * @param ollamaObject + * Sets the {@link #ollamaObject} object to the provided argument, + * Dose not add the base system for memory. see {@link #setOllamaObject} if you want to add memory function + * @param ollamaObject The OllamaObject to use */ public void setOllamaObjectNoMemory(OllamaObject ollamaObject) { if(this.ollamaObject == null) { @@ -162,30 +200,56 @@ public class Core { throw new IllegalArgumentException("Ollama object is already set"); } } - - public void addTool(OllamaFuntionTool funtionTool, String source) { + + /** + * Adds a new tool to the System + * @param funtionTool The tool to add + * @param source The source of the tool + */ + public void addTool(OllamaFunctionTool funtionTool, @MagicConstant(valuesFromClass = Core.Source.class) String source) { funtionTools.add(new Pair<>(funtionTool, source)); ollamaObject.addTool(funtionTool); } - - public ArrayList> getFuntionTools() { + + /** + * Gets the list of tools added to the System + * @return The list of tools added to the System compressed as Pairs of the tool and the source + */ + public ArrayList> getFuntionTools() { return funtionTools; } - + + /** + * Gets the Ollama Object + * @return The Ollama Object + */ public OllamaObject getOllamaObject() { return ollamaObject; } - - public void addFuntionTool(OllamaFuntionTool funtionTool) { + + /** + * Adds a new tool to the System + * @deprecated Use {@link Core#addTool(OllamaFunctionTool, String)} instead + * @param funtionTool The tool to add + */ + @Deprecated + public void addFuntionTool(OllamaFunctionTool funtionTool) { funtionTools.add(new Pair<>(funtionTool, "External")); } - + + /** + * Flushes the log file + */ public static void flushLog() { try { logWriter.flush(); }catch (IOException e) {} } - + + /** + * Sends the OllamaObject to Ollama + * @return The response from Ollama + */ public JSONObject qurryOllama() { try { @@ -230,7 +294,12 @@ public class Core { throw new RuntimeException(e); } } - + + /** + * Handles the response from Ollama + * By Processing the response, handles Function Calls, Logs relevant information, Appends information to the OllamaObject, Prints messages to the User. + * @param responce The response from Ollama + */ public void handleResponce(JSONObject responce) { //System.out.println("Responce: "+responce); @@ -248,7 +317,7 @@ public class Core { if(jsonObject.has("function")) { JSONObject function = jsonObject.getJSONObject("function"); - List> functions = funtionTools.stream().filter(func -> func.getKey().name().equalsIgnoreCase(function.getString("name"))).toList(); + List> functions = funtionTools.stream().filter(func -> func.getKey().name().equalsIgnoreCase(function.getString("name"))).toList(); if(functions.isEmpty()) { ollamaObject.addMessage(new OllamaToolError("Function '"+function.getString("name")+"' does not exist")); @@ -257,7 +326,7 @@ public class Core { } else { - OllamaFuntionTool func = functions.getFirst().getKey(); + OllamaFunctionTool func = functions.getFirst().getKey(); ArrayList argumentArrayList = new ArrayList<>(); @@ -287,7 +356,11 @@ public class Core { else checkIfResponceMessage(responce); } } - + + /** + * Checks if the response contains a message and if so, prints it to the user + * @param responce the Ollama response + */ private void checkIfResponceMessage(JSONObject responce) { if(responce.getJSONObject("message").has("content") && !responce.getJSONObject("message").getString("content").isBlank()) { @@ -296,7 +369,11 @@ public class Core { ollamaObject.addMessage(new OllamaMessage(OllamaMessageRole.ASSISTANT, responce.getJSONObject("message").getString("content"))); } } - + + /** + * Writes a message to the log file + * @param message The message to write + */ public static void writeLog(String message) { try { @@ -307,4 +384,36 @@ public class Core { throw new RuntimeException(e); } } + + /** + * Represents the source of a tool. + *

+ * This is intended for use with {@link Core#addTool(OllamaFunctionTool, String)} + * to indicate the module from which a tool originates. + */ + public static class Source { + /** + * Represents an external tool that is not derived from the Core. + * Instead, it belongs to an internally defined system or module within the project/program. + */ + public static final String EXTERNAL = "External"; + + /** + * Represents an internally defined tool that is part of the Core system. + * This is meant for tools that are strictly part of the Core and should not be used for definitions outside of it. + */ + public static final String CORE = "Core"; + + /** + * Represents a tool defined through an API system. + * These tools are more dynamic, as they originate from fully external sources using the API. + */ + public static final String API = "Api"; + + /** + * Represents an internally defined tool that is derived from Core Components but not the Core itself. + * This is used for tools that are part of the Core Components, such as internal modules, but do not belong directly to the Core. + */ + public static final String INTERNAL = "Internal"; + } } diff --git a/Core/src/main/java/me/zacharias/chat/core/LaunchOptions.java b/Core/src/main/java/me/zacharias/chat/core/LaunchOptions.java index 4cba05e..9ca20f1 100644 --- a/Core/src/main/java/me/zacharias/chat/core/LaunchOptions.java +++ b/Core/src/main/java/me/zacharias/chat/core/LaunchOptions.java @@ -1,8 +1,16 @@ package me.zacharias.chat.core; +/** + * The Configuration class, where arguments are stored and retrieved. This is used to configure the running of the program from the Launcher. + */ public class LaunchOptions { private static LaunchOptions instance = new LaunchOptions(); - + + /** + * Gets the singleton instance of the LaunchOptions class. + * Meant to be used to get or set ant option. + * @return The singleton instance of the LaunchOptions class. + */ public static LaunchOptions getInstance() { return instance; } @@ -12,47 +20,92 @@ public class LaunchOptions { private boolean serverMode; private int port = 39075; private String redirectOutput; - + + /** + * Sets the singleton instance of the LaunchOptions class. + * Used to reset the LaunchOptions to their default values. + * @param instance The instance to set. + */ public static void setInstance(LaunchOptions instance) { LaunchOptions.instance = instance; } - + + /** + * Retries if old messages should be loaded. + * @return a boolean indicating if old messages should be loaded. + */ public boolean isLoadOld() { return loadOld; } - + + /** + * Sets if old messages should be loaded. + * @param loadOld a boolean indicating if old messages should be loaded. + */ public void setLoadOld(boolean loadOld) { this.loadOld = loadOld; } - + + /** + * Gets if the program should automatically accept prompts. + * @return a boolean indicating if the program should automatically accept prompts. + */ public boolean isAutoAccept() { return autoAccept; } - + + /** + * Sets if the program should automatically accept prompts. + * @param autoAccept a boolean indicating if the program should automatically accept prompts. + */ public void setAutoAccept(boolean autoAccept) { this.autoAccept = autoAccept; } - + + /** + * Gets the port number that the API server should use. + * @return the port number that the API server should use. + */ public int getPort() { return port; } - + + /** + * Sets the port number that the API server should use. + * @param port the port number that the API server should use. + */ public void setPort(int port) { this.port = port; } - + + /** + * Gets the file path that the program should redirect output to. + * @return the file path that the program should redirect output to. + */ public String getRedirectOutput() { return redirectOutput; } - + + /** + * Sets the file path that the program should redirect output to. + * @param redirectOutput the file path that the program should redirect output to. + */ public void setRedirectOutput(String redirectOutput) { this.redirectOutput = redirectOutput; } - + + /** + * Gets if the program is running in API server mode. + * @return a boolean indicating if the program is running in API server mode. + */ public boolean isServerMode() { return serverMode; } - + + /** + * Sets if the program is running in API server mode. + * @param serverMode a boolean indicating if the program is running in API server mode. + */ public void setServerMode(boolean serverMode) { this.serverMode = serverMode; } diff --git a/Core/src/main/java/me/zacharias/chat/core/Pair.java b/Core/src/main/java/me/zacharias/chat/core/Pair.java index bce5b34..e6b222d 100644 --- a/Core/src/main/java/me/zacharias/chat/core/Pair.java +++ b/Core/src/main/java/me/zacharias/chat/core/Pair.java @@ -1,26 +1,58 @@ package me.zacharias.chat.core; +/** + * A simple Pair class. + * @param The key type + * @param The value type + */ public class Pair { + /** + * The key of the pair. + */ private K key; + /** + * The value of the pair. + */ private V value; - + + /** + * Creates a new instance of Pair. + * @param key The key of the pair + * @param value The value of the pair + */ public Pair(K key, V value) { this.key = key; this.value = value; } - + + /** + * Gets the key of the pair. + * @return The key of the pair + */ public K getKey() { return key; } - + + /** + * Gets the value of the pair. + * @return The value of the pair + */ public V getValue() { return value; } - + + /** + * Sets the key of the pair. + * @param key The key of the pair + */ public void setKey(K key) { this.key = key; } - + + /** + * Sets the value of the pair. + * @param value The value of the pair + */ public void setValue(V value) { this.value = value; } diff --git a/Core/src/main/java/me/zacharias/chat/core/PrintMessageHandler.java b/Core/src/main/java/me/zacharias/chat/core/PrintMessageHandler.java index 43ff002..ebedc19 100644 --- a/Core/src/main/java/me/zacharias/chat/core/PrintMessageHandler.java +++ b/Core/src/main/java/me/zacharias/chat/core/PrintMessageHandler.java @@ -1,6 +1,21 @@ package me.zacharias.chat.core; +/** + * Represents a PrintMessageHandler. + * This is used by the Core to print messages to the user or API Clients. + */ public interface PrintMessageHandler { + /** + * Handles the printing of a message. + * This is meant to output the message to the user or API Client. + * @param message The message to be printed. + */ void printMessage(String message); + + /** + * Gets if color is supported by the PrintMessageHandler. + * This uses ANSI escape codes to color the output. + * @return a boolean indicating if color is supported by the PrintMessageHandler. + */ boolean color(); } diff --git a/Core/src/main/java/me/zacharias/chat/core/memory/AddMemoryFunction.java b/Core/src/main/java/me/zacharias/chat/core/memory/AddMemoryFunction.java index 6e39915..05573c9 100644 --- a/Core/src/main/java/me/zacharias/chat/core/memory/AddMemoryFunction.java +++ b/Core/src/main/java/me/zacharias/chat/core/memory/AddMemoryFunction.java @@ -1,13 +1,19 @@ package me.zacharias.chat.core.memory; import me.zacharias.chat.ollama.OllamaFunctionArgument; -import me.zacharias.chat.ollama.OllamaFuntionTool; +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 org.json.JSONArray; -public class AddMemoryFunction extends OllamaFuntionTool { +/** + * Provides the add_memory function.
+ * This function adds a string to the memory. + */ +public class AddMemoryFunction extends OllamaFunctionTool { + /** + * The CoreMemory instance. + */ CoreMemory memory = CoreMemory.getInstance(); @Override @@ -32,7 +38,7 @@ public class AddMemoryFunction extends OllamaFuntionTool { if (args.length == 0) { throw new OllamaToolErrorException(name(), "Missing memory argument"); } - String value = (String) args[0].getValue(); + String value = (String) args[0].value(); memory.addMemory(value); return new OllamaToolRespnce(name(), "Added "+value+" to the memory"); } diff --git a/Core/src/main/java/me/zacharias/chat/core/memory/CoreMemory.java b/Core/src/main/java/me/zacharias/chat/core/memory/CoreMemory.java index d628bc3..0cfd809 100644 --- a/Core/src/main/java/me/zacharias/chat/core/memory/CoreMemory.java +++ b/Core/src/main/java/me/zacharias/chat/core/memory/CoreMemory.java @@ -6,13 +6,28 @@ import org.json.JSONObject; import java.io.*; import java.util.ArrayList; +/** + * CoreMemory is a class that provides a way to store and retrieve strings from a file.
+ * This is meant to be used as a way to store and retrieve strings from a file. + */ public class CoreMemory { + /** + * The singleton instance of CoreMemory. + */ private static CoreMemory instance = new CoreMemory("./cache/CoreMemory.json"); - + + /** + * Gets the singleton instance of CoreMemory. + * @return The singleton instance of CoreMemory + */ public static CoreMemory getInstance() { return instance; } - + + /** + * Creates a new instance of CoreMemory. + * @param memoryFile The file to store the memory in + */ public CoreMemory(String memoryFile) { File f = new File(memoryFile); if (f.exists()) { @@ -64,18 +79,36 @@ public class CoreMemory { } }); } - + + /** + * The memory. + */ private ArrayList memory = new ArrayList<>(); + /** + * The file to store the memory in. + */ private final String memoryFile; - + + /** + * Gets the memory. + * @return The memory + */ public ArrayList getMemory() { return memory; } - + + /** + * Sets the memory. + * @param memory The memory + */ public void addMemory(String memory) { this.memory.add(memory); } - + + /** + * Removes the memory. + * @param memory The memory to remove + */ public void removeMemory(String memory) { this.memory.remove(memory); } diff --git a/Core/src/main/java/me/zacharias/chat/core/memory/GetMemoryFunction.java b/Core/src/main/java/me/zacharias/chat/core/memory/GetMemoryFunction.java index 80c13c2..7c32a03 100644 --- a/Core/src/main/java/me/zacharias/chat/core/memory/GetMemoryFunction.java +++ b/Core/src/main/java/me/zacharias/chat/core/memory/GetMemoryFunction.java @@ -1,12 +1,18 @@ package me.zacharias.chat.core.memory; import me.zacharias.chat.ollama.OllamaFunctionArgument; -import me.zacharias.chat.ollama.OllamaFuntionTool; +import me.zacharias.chat.ollama.OllamaFunctionTool; import me.zacharias.chat.ollama.OllamaPerameter; import me.zacharias.chat.ollama.OllamaToolRespnce; -import org.json.JSONArray; -public class GetMemoryFunction extends OllamaFuntionTool { +/** + * Provides the get_memory function.
+ * This function retrives all the memory. + */ +public class GetMemoryFunction extends OllamaFunctionTool { + /** + * The CoreMemory instance. + */ CoreMemory memory = CoreMemory.getInstance(); @Override diff --git a/Core/src/main/java/me/zacharias/chat/core/memory/RemoveMemoryFunction.java b/Core/src/main/java/me/zacharias/chat/core/memory/RemoveMemoryFunction.java index 4fe9b1b..42dac7a 100644 --- a/Core/src/main/java/me/zacharias/chat/core/memory/RemoveMemoryFunction.java +++ b/Core/src/main/java/me/zacharias/chat/core/memory/RemoveMemoryFunction.java @@ -1,12 +1,19 @@ package me.zacharias.chat.core.memory; import me.zacharias.chat.ollama.OllamaFunctionArgument; -import me.zacharias.chat.ollama.OllamaFuntionTool; +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; -public class RemoveMemoryFunction extends OllamaFuntionTool { +/** + * Provides the remove_memory function.
+ * This function removes a value from the memory. + */ +public class RemoveMemoryFunction extends OllamaFunctionTool { + /** + * The CoreMemory instance. + */ CoreMemory memory = CoreMemory.getInstance(); @Override @@ -31,7 +38,7 @@ public class RemoveMemoryFunction extends OllamaFuntionTool { if (args.length == 0) { throw new OllamaToolErrorException(name(), "Missing memory argument"); } - String value = (String) args[0].getValue(); + String value = (String) args[0].value(); memory.removeMemory(value); return new OllamaToolRespnce(name(), "Removed "+value+" to the memory"); } diff --git a/Core/src/main/java/me/zacharias/chat/ollama/OllamaFunctionArgument.java b/Core/src/main/java/me/zacharias/chat/ollama/OllamaFunctionArgument.java index 5b852a6..add4a05 100644 --- a/Core/src/main/java/me/zacharias/chat/ollama/OllamaFunctionArgument.java +++ b/Core/src/main/java/me/zacharias/chat/ollama/OllamaFunctionArgument.java @@ -1,19 +1,40 @@ package me.zacharias.chat.ollama; -public class OllamaFunctionArgument { - private final String argument; - private final Object value; - - public OllamaFunctionArgument(String argument, Object value) { - this.argument = argument; - this.value = value; +/** + * Represents an argument passed to a tool. + * + * @param argument The argument name + * @param value The argument value + */ +public record OllamaFunctionArgument(String argument, Object value) { + /** + * Creates a new instance of OllamaFunctionArgument.
+ * This is used by Ollama to pass arguments to a tool. + * + * @param argument The argument name + * @param value The argument value + */ + public OllamaFunctionArgument { } - - public String getArgument() { + + /** + * Gets the argument name + * + * @return The argument name + */ + @Override + public String argument() { return argument; } - - public Object getValue() { + + /** + * Gets the argument value.
+ * This needs to be cast to the correct type by the tool itself + * + * @return The argument value + */ + @Override + public Object value() { return value; } } diff --git a/Core/src/main/java/me/zacharias/chat/ollama/OllamaFunctionTool.java b/Core/src/main/java/me/zacharias/chat/ollama/OllamaFunctionTool.java new file mode 100644 index 0000000..147f424 --- /dev/null +++ b/Core/src/main/java/me/zacharias/chat/ollama/OllamaFunctionTool.java @@ -0,0 +1,59 @@ +package me.zacharias.chat.ollama; + +import me.zacharias.chat.core.Core; +import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException; +import org.json.JSONObject; + +/** + * Represents a tool that can be called by Ollama. + */ +public abstract class OllamaFunctionTool implements OllamaTool { + + @Override + public String toString() { + JSONObject ret = new JSONObject(); + ret.put("tool", "function"); + + JSONObject function = new JSONObject(); + function.put("name", name()); + function.put("description", description()); + function.put("parameters", (parameters() == null? + new JSONObject() : new JSONObject(parameters().toString()))); + + ret.put("function", function); + + return ret.toString(); + } + + /** + * The name of the tool + * This is used by Ollama to know what the tool is + * @return The name of the tool + */ + abstract public String name(); + + /** + * The description of the tool + * This is used by Ollama to know what the tool does + * @return The description of the tool + */ + abstract public String description(); + + /** + * The parameters of the tool + * This is used by Ollama to know what parameters the tool takes + * If null, the tool does not take any parameters + * @return The parameters of the tool or null if the tool does not take any parameters + */ + abstract public OllamaPerameter parameters(); + + /** + * The function of the tool.
+ * This is used by Ollama to call the tool.
+ * Throw {@link OllamaToolErrorException} if the tool encounters an error instead of normal exceptions. The {@link OllamaToolErrorException} gets handled more gracefully by {@link Core#handleResponce(JSONObject)} + * @param args The arguments to pass to the tool, if any + * @return The response from the tool + * @throws OllamaToolErrorException If the tool encounters an error + */ + abstract public OllamaToolRespnce function(OllamaFunctionArgument... args); +} diff --git a/Core/src/main/java/me/zacharias/chat/ollama/OllamaFuntionTool.java b/Core/src/main/java/me/zacharias/chat/ollama/OllamaFuntionTool.java deleted file mode 100644 index 6675034..0000000 --- a/Core/src/main/java/me/zacharias/chat/ollama/OllamaFuntionTool.java +++ /dev/null @@ -1,28 +0,0 @@ -package me.zacharias.chat.ollama; - -import org.json.JSONObject; - -public abstract class OllamaFuntionTool implements OllamaTool { - - @Override - public String toString() { - JSONObject ret = new JSONObject(); - ret.put("tool", "function"); - - JSONObject function = new JSONObject(); - function.put("name", name()); - function.put("description", description()); - function.put("parameters", (parameters() == null? - new JSONObject() : new JSONObject(parameters().toString()))); - - ret.put("function", function); - - return ret.toString(); - } - - abstract public String name(); - abstract public String description(); - abstract public OllamaPerameter parameters(); - - abstract public OllamaToolRespnce function(OllamaFunctionArgument... args); -} diff --git a/Core/src/main/java/me/zacharias/chat/ollama/OllamaMessage.java b/Core/src/main/java/me/zacharias/chat/ollama/OllamaMessage.java index d48ecbd..959d41e 100644 --- a/Core/src/main/java/me/zacharias/chat/ollama/OllamaMessage.java +++ b/Core/src/main/java/me/zacharias/chat/ollama/OllamaMessage.java @@ -2,10 +2,24 @@ package me.zacharias.chat.ollama; import org.json.JSONObject; +/** + * Represents a message sent by a Tool, Assistant(Ollama), or User. + */ public class OllamaMessage { + /** + * The role of the message. + */ OllamaMessageRole role; + /** + * The content of the message. + */ String content; - + + /** + * Creates a new instance of OllamaMessage. + * @param role The role of the message + * @param content The content of the message + */ public OllamaMessage(OllamaMessageRole role, String content) { this.role = role; this.content = content; diff --git a/Core/src/main/java/me/zacharias/chat/ollama/OllamaMessageRole.java b/Core/src/main/java/me/zacharias/chat/ollama/OllamaMessageRole.java index c24109f..b4be62c 100644 --- a/Core/src/main/java/me/zacharias/chat/ollama/OllamaMessageRole.java +++ b/Core/src/main/java/me/zacharias/chat/ollama/OllamaMessageRole.java @@ -1,21 +1,53 @@ package me.zacharias.chat.ollama; +/** + * Represents the role of a message. + * This is used by Ollama to determine the role of a message. + */ public enum OllamaMessageRole { + /** + * Represents a user message. + */ USER("user"), + /** + * Represents an assistant message. + */ ASSISTANT("assistant"), + /** + * Represents a tool message + */ TOOL("tool"), + /** + * Represents a system message. + */ SYSTEM("system"); - + + /** + * The role of the message. + */ private String role; - + + /** + * Creates a new instance of OllamaMessageRole. + * @param role The role of the message + */ OllamaMessageRole(String role) { this.role = role; } - + + /** + * Gets the role of the message. + * @return The role of the message + */ public String getRole() { return role; } - + + /** + * Gets the role of the message from a string. + * @param role The role of the message as a string + * @return The role of the message + */ public static OllamaMessageRole fromRole(String role) { for(OllamaMessageRole roleRole : values()) { if(roleRole.role.equals(role.toLowerCase())) diff --git a/Core/src/main/java/me/zacharias/chat/ollama/OllamaMessageToolCall.java b/Core/src/main/java/me/zacharias/chat/ollama/OllamaMessageToolCall.java index 6165dac..b75e9af 100644 --- a/Core/src/main/java/me/zacharias/chat/ollama/OllamaMessageToolCall.java +++ b/Core/src/main/java/me/zacharias/chat/ollama/OllamaMessageToolCall.java @@ -3,10 +3,22 @@ package me.zacharias.chat.ollama; import org.json.JSONArray; import org.json.JSONObject; +/** + * Represents a message sent by a Tool. + */ public class OllamaMessageToolCall extends OllamaMessage{ - + + /** + * The tool calls in the message + */ private JSONArray tool_calls; - + + /** + * Creates a new instance of OllamaMessage + * @param role The role of the message + * @param content The content of the message + * @param tool_calls The tool calls in the message + */ public OllamaMessageToolCall(OllamaMessageRole role, String content, JSONArray tool_calls) { super(role, content); this.tool_calls = tool_calls; 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 061f0cf..8d54531 100644 --- a/Core/src/main/java/me/zacharias/chat/ollama/OllamaObject.java +++ b/Core/src/main/java/me/zacharias/chat/ollama/OllamaObject.java @@ -1,5 +1,6 @@ package me.zacharias.chat.ollama; +import me.zacharias.chat.core.Core; import me.zacharias.chat.core.LaunchOptions; import org.json.JSONArray; import org.json.JSONObject; @@ -12,15 +13,53 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +/** + * Represents an Ollama Object. + * This is used to represent the state of the Ollama Object. + * This is used by the Core to store the state of the Ollama Object. + * This is used by the API to send the state of the Ollama Object to the client. + * @see Core#setOllamaObject(OllamaObject) + */ public class OllamaObject { + /** + * The model of the Ollama Object. + */ String model; + /** + * The messages of the Ollama Object. + */ ArrayList messages; + /** + * The tools of the Ollama Object. + */ ArrayList tools; + /** + * The format of the Ollama Object. + */ JSONObject format; + /** + * The options of the Ollama Object. + */ Map options; + /** + * If the Ollama Object is streamed. + */ boolean stream; + /** + * The keep alive of the Ollama Object. + */ String keep_alive; - + + /** + * Creates a new instance of OllamaObject. + * @param model The model of the Ollama Object. see {@link OllamaObject#model} + * @param messages The messages of the Ollama Object. see {@link OllamaObject#messages} + * @param tools The tools of the Ollama Object. see {@link OllamaObject#tools} + * @param format The format of the Ollama Object. see {@link OllamaObject#format} + * @param options The options of the Ollama Object. see {@link OllamaObject#options} + * @param stream If the Ollama Object is streamed. see {@link OllamaObject#stream} + * @param keep_alive The keep alive of the Ollama Object. see {@link OllamaObject#keep_alive} + */ private OllamaObject(String model, ArrayList messages, ArrayList tools, JSONObject format, Map options, boolean stream, String keep_alive) { this.model = model; this.messages = messages; @@ -59,39 +98,75 @@ public class OllamaObject { } } } - + + /** + * Gets the model of the Ollama Object. + * @return The model of the Ollama Object + */ public String getModel() { return model; } - + + /** + * Gets the messages + * @return The messages + */ public ArrayList getMessages() { return messages; } - + + /** + * Gets the tools + * @return The tools + */ public ArrayList getTools() { return tools; } - + + /** + * Adds a tool to the Ollama Object + * @param tool The tool to add + */ public void addTool(OllamaTool tool) { tools.add(tool); } - + + /** + * Gets the format of the Ollama Object. + * @return The format of the Ollama Object + */ public JSONObject getFormat() { return format; } - + + /** + * Gets the options of the Ollama Object. + * @return The options of the Ollama Object + */ public Map getOptions() { return options; } - + + /** + * Gets if the Ollama Object is streamed. + * @return If the Ollama Object is streamed + */ public boolean isStream() { return stream; } - + + /** + * Gets the keep alive of the Ollama Object. + * @return The keep alive of the Ollama Object + */ public String getKeep_alive() { return keep_alive; } - + + /** + * Adds a message to the Ollama Object + * @param message The message to add + */ public void addMessage(OllamaMessage message) { messages.add(message); } @@ -119,83 +194,182 @@ public class OllamaObject { json.put("keep_alive", keep_alive); return json.toString(); } - + + /** + * Creates a new instance of OllamaObjectBuilder. + * @return The {@link OllamaObjectBuilder} + */ public static OllamaObjectBuilder builder() { return new OllamaObjectBuilder(); } - + + /** + * Represents a builder for OllamaObject. + */ public static class OllamaObjectBuilder { + /** + * The model of the Ollama Object. + */ String model; + /** + * The messages of the Ollama Object. + */ ArrayList messages = new ArrayList<>(); + /** + * The tools of the Ollama Object. + */ ArrayList tools = new ArrayList<>(); + /** + * The format of the Ollama Object. + */ JSONObject format; + /** + * The options of the Ollama Object. + */ Map options = new HashMap<>(); - boolean stream; + /** + * If the Ollama Object is streamed. + */ + boolean stream = false; + /** + * The keep alive of the Ollama Object. + */ String keep_alive; - + + /** + * Creates a new instance of {@link OllamaObjectBuilder}. + */ public OllamaObjectBuilder() {} - + + /** + * Sets the format of the Ollama Object as a JSON schema. + * @param format The format of the Ollama Object as a JSON schema + * @return The {@link OllamaObjectBuilder} + */ public OllamaObjectBuilder format(String format) { this.format = new JSONObject(format); return this; } - + + /** + * Sets the options of the Ollama Object. + * @param options The options of the Ollama Object + * @return The {@link OllamaObjectBuilder} + */ public OllamaObjectBuilder options(Map options) { this.options.putAll(options); return this; } - + + /** + * Sets an option of the Ollama Object. + * @param key The key of the option + * @param value The value of the option + * @return The {@link OllamaObjectBuilder} + */ public OllamaObjectBuilder option(String key, String value) { this.options.put(key, value); return this; } - + + /** + * Sets if the Ollama Object is streamed. + * @param stream If the Ollama Object is streamed + * @deprecated This should be false due to being broken in the current version of this system + * @return The {@link OllamaObjectBuilder} + */ + @Deprecated public OllamaObjectBuilder stream(boolean stream) { this.stream = stream; return this; } - + + /** + * Sets the keep alive of the Ollama Object.
+ * This is a string formated as "minutes"m or "hours"h or "days"d + * @param keep_alive The keep alive of the Ollama Object + * @return The {@link OllamaObjectBuilder} + */ public OllamaObjectBuilder keep_alive(String keep_alive) { this.keep_alive = keep_alive; return this; } - + + /** + * Sets the keep alive of the Ollama Object.
+ * @param minutes The keep alive of the Ollama Object in minutes + * @return The {@link OllamaObjectBuilder} + */ public OllamaObjectBuilder keep_alive(int minutes) { this.keep_alive = minutes+"m"; return this; } - - public OllamaObjectBuilder addTool(OllamaTool tools) { - this.tools.add(tools); + + /** + * Adds a tool to the Ollama Object + * @param tool The tool to add + * @return The {@link OllamaObjectBuilder} + */ + public OllamaObjectBuilder addTool(OllamaTool tool) { + this.tools.add(tool); return this; } - + + /** + * Adds tools to the Ollama Object + * @param tools The tools to add + * @return The {@link OllamaObjectBuilder} + */ public OllamaObjectBuilder addTools(ArrayList tools) { this.tools.addAll(tools); return this; } - + + /** + * Adds tools to the Ollama Object + * @param tools The tools to add + * @return The {@link OllamaObjectBuilder} + */ public OllamaObjectBuilder addTools(OllamaTool... tools) { this.tools.addAll(List.of(tools)); return this; } - + + /** + * Adds messages to the Ollama Object + * @param messages The messages to add + * @return The {@link OllamaObjectBuilder} + */ public OllamaObjectBuilder addMessages(OllamaMessage... messages) { this.messages.addAll(List.of(messages)); return this; } - + + /** + * Adds a message to the Ollama Object + * @param messages The message to add + * @return The {@link OllamaObjectBuilder} + */ public OllamaObjectBuilder addMessage(OllamaMessage messages) { this.messages.add(messages); return this; } - + + /** + * Sets the model of the Ollama Object + * @param model The model of the Ollama Object + * @return The {@link OllamaObjectBuilder} + */ public OllamaObjectBuilder setModel(String model) { this.model = model; return this; } - + + /** + * Builds the {@link OllamaObject} + * @return The {@link OllamaObject} + */ public OllamaObject build() { return new OllamaObject(model, messages, tools, format, options, stream, keep_alive); } diff --git a/Core/src/main/java/me/zacharias/chat/ollama/OllamaPerameter.java b/Core/src/main/java/me/zacharias/chat/ollama/OllamaPerameter.java index 9d10a03..c560cf4 100644 --- a/Core/src/main/java/me/zacharias/chat/ollama/OllamaPerameter.java +++ b/Core/src/main/java/me/zacharias/chat/ollama/OllamaPerameter.java @@ -6,12 +6,22 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +/** + * Represents the parameters of a tool. + * This is used by Ollama to determine the parameters of a tool. + */ public class OllamaPerameter { - + + /** + * Creates a new instance of {@link OllamaPerameter}. + * @param properties The properties of the parameters + * @param required The required parameters + */ private OllamaPerameter(JSONObject properties, String[] required) { this.properties = properties; this.required = required; }; + @Override public String toString() { JSONObject json = new JSONObject(); @@ -22,26 +32,60 @@ public class OllamaPerameter { return json.toString(); } - + + /** + * the properties of the parameters + */ JSONObject properties; + /** + * the required parameters + */ String[] required; - + + /** + * Gets the properties of the {@link OllamaPerameter} + * @return The properties of the {@link OllamaPerameter} + */ public JSONObject getProperties() { return properties; } - + + /** + * Gets the required parameters of the {@link OllamaPerameter} + * @return The required parameters of the {@link OllamaPerameter} + */ public String[] getRequired() { return required; } - + + /** + * Creates a new instance of {@link OllamaPerameterBuilder}. + * @return The {@link OllamaPerameterBuilder} + */ public static OllamaPerameterBuilder builder() { return new OllamaPerameterBuilder(); } - + + /** + * Represents a builder for {@link OllamaPerameter}. + */ public static class OllamaPerameterBuilder { + /** + * The properties of the parameters. + */ Map propertyMap = new HashMap<>(); + /** + * The required parameters. + */ ArrayList required = new ArrayList<>(); - + + /** + * Creates a new instance of {@link OllamaPerameterBuilder}. + * @param name The name of the parameter + * @param type The type of the parameter + * @param description The description of the parameter + * @return The {@link OllamaPerameterBuilder} + */ public OllamaPerameterBuilder addProperty(String name, Type type, String description) { if(name == null || type == null || description == null) { return this; @@ -49,7 +93,15 @@ public class OllamaPerameter { propertyMap.put(name, new Property(type.getType(), description)); return this; } - + + /** + * Creates a new instance of {@link OllamaPerameterBuilder}. + * @param name The name of the parameter + * @param type The type of the parameter + * @param description The description of the parameter + * @param required The required state of the parameter + * @return The {@link OllamaPerameterBuilder} + */ public OllamaPerameterBuilder addProperty(String name, Type type, String description, boolean required) { if(name == null || type == null || description == null) { return this; @@ -58,17 +110,31 @@ public class OllamaPerameter { this.required.add(name); return this; } - + + /** + * Creates a new instance of {@link OllamaPerameterBuilder}. + * @param name The name of the parameter + * @return The {@link OllamaPerameterBuilder} + */ public OllamaPerameterBuilder required(String name) { required.add(name); return this; } - + + /** + * Removes a property from the parameters. + * @param name The name of the property to remove + * @return The {@link OllamaPerameterBuilder} + */ public OllamaPerameterBuilder removeProperty(String name) { propertyMap.remove(name); return this; } - + + /** + * Builds the {@link OllamaPerameter} + * @return The {@link OllamaPerameter} + */ public OllamaPerameter build() { JSONObject properties = new JSONObject(); for(String name : propertyMap.keySet()) { @@ -76,11 +142,25 @@ public class OllamaPerameter { } return new OllamaPerameter(properties, required.toArray(new String[0])); } - + + /** + * Represents a property of a parameter. + */ private class Property { + /** + * The type of the property. + */ String type; + /** + * The description of the property. + */ String description; - + + /** + * Creates a new instance of {@link Property}. + * @param type The type of the property + * @param description The description of the property + */ public Property(String type, String description) { this.type = type; this.description = description; @@ -96,18 +176,41 @@ public class OllamaPerameter { return json.toString(); } } - + + /** + * Represents the type of parameter. + */ public enum Type { + /** + * Represents a string parameter. + */ STRING("string"), + /** + * Represents an integer parameter. + */ INT("int"), + /** + * Represents a boolean parameter. + */ BOOLEAN("boolean"); + /** + * The type of the parameter. + */ private String type; - + + /** + * Gets the type of the parameter. + * @return The type of the parameter + */ public String getType() { return type; } - + + /** + * Creates a new instance of {@link Type}. + * @param type The type of the parameter + */ Type(String type) { this.type = type; } diff --git a/Core/src/main/java/me/zacharias/chat/ollama/OllamaTool.java b/Core/src/main/java/me/zacharias/chat/ollama/OllamaTool.java index 8108488..77eb96f 100644 --- a/Core/src/main/java/me/zacharias/chat/ollama/OllamaTool.java +++ b/Core/src/main/java/me/zacharias/chat/ollama/OllamaTool.java @@ -1,5 +1,7 @@ package me.zacharias.chat.ollama; - +/** + * Represents a tool. + */ public interface OllamaTool { } diff --git a/Core/src/main/java/me/zacharias/chat/ollama/OllamaToolError.java b/Core/src/main/java/me/zacharias/chat/ollama/OllamaToolError.java index 6e06efd..3723877 100644 --- a/Core/src/main/java/me/zacharias/chat/ollama/OllamaToolError.java +++ b/Core/src/main/java/me/zacharias/chat/ollama/OllamaToolError.java @@ -2,13 +2,29 @@ package me.zacharias.chat.ollama; import org.json.JSONObject; +/** + * Represents an error from a tool.
+ * This is used by a tool to indicate to Ollama that an error occurred. + */ public class OllamaToolError extends OllamaMessage { + /** + * The error from the tool. + */ String error; + + /** + * Creates a new instance of OllamaToolError. + * @param error The error from the tool + */ public OllamaToolError(String error) { super(OllamaMessageRole.TOOL, new JSONObject().put("error", error).toString()); this.error = error; } - + + /** + * Gets the error from the tool. + * @return The error from the tool + */ public String getError() { return error; } diff --git a/Core/src/main/java/me/zacharias/chat/ollama/OllamaToolRespnce.java b/Core/src/main/java/me/zacharias/chat/ollama/OllamaToolRespnce.java index bd79568..8e4afef 100644 --- a/Core/src/main/java/me/zacharias/chat/ollama/OllamaToolRespnce.java +++ b/Core/src/main/java/me/zacharias/chat/ollama/OllamaToolRespnce.java @@ -2,19 +2,42 @@ package me.zacharias.chat.ollama; import org.json.JSONObject; +/** + * Represents a response from a tool. + */ public class OllamaToolRespnce extends OllamaMessage { + /** + * The tool that responded. + */ private final String tool; + /** + * The response from the tool. + */ private final String response; + + /** + * Creates a new instance of {@link OllamaToolRespnce}. + * @param tool The tool that responded + * @param response The response from the tool + */ public OllamaToolRespnce(String tool, String response) { super(OllamaMessageRole.TOOL, new JSONObject().put("tool", tool).put("result", response).toString()); this.tool = tool; this.response = response; } - + + /** + * Gets the tool that responded. + * @return The tool that responded + */ public String getTool() { return tool; } - + + /** + * Gets the response from the tool. + * @return The response from the tool + */ public String getResponse() { return response; } 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 9a1fe0d..d90e470 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 @@ -1,18 +1,45 @@ package me.zacharias.chat.ollama.exceptions; +import me.zacharias.chat.core.Core; +import org.json.JSONObject; + +/** + * Represents an error from a tool.
+ * This is used internally by tools instead of {@link Exception}, to then be handled gracefully by {@link Core#handleResponce(JSONObject)} + */ public class OllamaToolErrorException extends RuntimeException { + /** + * The tool that caused the error. + */ private final String tool; + /** + * The error from the tool. + */ private final String error; + + /** + * Creates a new instance of OllamaToolErrorException. + * @param tool The tool that caused the error + * @param error The error from the tool + */ public OllamaToolErrorException(String tool, String error) { super(tool + ": " + error); this.tool = tool; this.error = error; } - + + /** + * Gets the tool that caused the error. + * @return The tool that caused the error + */ public String getTool() { return tool; } - + + /** + * Gets the error from the tool. + * @return The error from the tool + */ public String getError() { return 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 3b852c0..f57ccb0 100644 --- a/Display/src/main/java/me/zacharias/chat/display/Display.java +++ b/Display/src/main/java/me/zacharias/chat/display/Display.java @@ -11,8 +11,16 @@ import java.util.*; import static me.zacharias.chat.core.Core.writeLog; +/** + * The main class of the Display.
+ * This is the main class for running as a Terminal application.
+ * Somewhat meant to be used as a Debug tool for testing your API. + */ public class Display { - + + /** + * The Core instance. + */ Core core = new Core(new PrintMessageHandler() { @Override public void printMessage(String message) { @@ -24,25 +32,29 @@ public class Display { return true; } }); - + + /** + * Creates a new instance of Display.
+ * This Creates the OllamaObject and adds the tools to it. as well as handles the display of the messages. and the input from the user. + */ public Display() { core.setOllamaObject(OllamaObject.builder() .setModel("llama3-AI") .keep_alive(10) - .stream(false) + //.stream(false) .build()); - core.addTool(new TimeTool(), "Internal"); - core.addTool(new PythonRunner(core), "Internal"); + core.addTool(new TimeTool(), Core.Source.EXTERNAL); + core.addTool(new PythonRunner(core), Core.Source.INTERNAL); writeLog("Creating base OllamaObject with model: "+core.getOllamaObject().getModel()); System.out.println("Installed tools"); writeLog("Tools installed in this instance"); - for(Pair funtion : core.getFuntionTools()) + for(Pair funtion : core.getFuntionTools()) { StringBuilder args = new StringBuilder(); OllamaPerameter perameter = funtion.getKey().parameters(); 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 11b13f9..ce074e2 100644 --- a/Display/src/main/java/me/zacharias/chat/display/PythonRunner.java +++ b/Display/src/main/java/me/zacharias/chat/display/PythonRunner.java @@ -10,7 +10,6 @@ import me.zacharias.chat.core.Core; import me.zacharias.chat.core.Pair; import me.zacharias.chat.ollama.*; import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException; -import org.apache.http.conn.HttpHostConnectException; import org.json.JSONArray; import org.json.JSONObject; @@ -26,11 +25,30 @@ import java.util.logging.Logger; import static me.zacharias.chat.core.Core.writeLog; -public class PythonRunner extends OllamaFuntionTool { - DockerClient dockerClient; - Core core; - - ServerSocket serverSocket; +/** + * A tool that runs python code. + * This is a wrapper around a docker container. + * This is partly meant as a proof of concept, but also as a way to run python code while keeping the executed code in a secure environment. + */ +public class PythonRunner extends OllamaFunctionTool { + /** + * The DockerClient instance. + */ + private DockerClient dockerClient; + /** + * The Core instance. + */ + private Core core; + + /** + * The ServerSocket instance. + */ + private ServerSocket serverSocket; + + /** + * Creates a new instance of PythonRunner. + * @param core The Core instance + */ public PythonRunner(Core core) { this.core = core; @@ -49,7 +67,7 @@ public class PythonRunner extends OllamaFuntionTool { try { JSONObject data = new JSONObject(inputLine); - List> list = core.getFuntionTools().stream().filter(funtionTool -> funtionTool.getKey().name().equalsIgnoreCase(data.optString("function", ""))).toList(); + List> list = core.getFuntionTools().stream().filter(funtionTool -> funtionTool.getKey().name().equalsIgnoreCase(data.optString("function", ""))).toList(); if (list.isEmpty()) { out.write(new JSONObject().put("error", "Function dose't exist").toString()); @@ -79,7 +97,7 @@ public class PythonRunner extends OllamaFuntionTool { } catch (Exception e) { } } catch (Exception e) { - + } } }); @@ -128,15 +146,15 @@ public class PythonRunner extends OllamaFuntionTool { for(OllamaFunctionArgument arg : args) { - if(arg.getArgument().equals("name")) + if(arg.argument().equals("name")) { - name = (String) arg.getValue(); + name = (String) arg.value(); if(!name.endsWith(".py")) { name += ".py"; } - } else if (arg.getArgument().equals("code")) { - code = (String) arg.getValue(); + } else if (arg.argument().equals("code")) { + code = (String) arg.value(); } } @@ -144,7 +162,7 @@ public class PythonRunner extends OllamaFuntionTool { { try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); - byte[] encodedhash = digest.digest(String.valueOf(args[0].getValue()).getBytes(StandardCharsets.UTF_8)); + byte[] encodedhash = digest.digest(String.valueOf(args[0].value()).getBytes(StandardCharsets.UTF_8)); StringBuffer hexString = new StringBuffer(); for(byte b : encodedhash) { @@ -221,7 +239,12 @@ public class PythonRunner extends OllamaFuntionTool { throw new OllamaToolErrorException(name(), "Docker unavalible"); } } - + + /** + * Generates the external_tools.py file.
+ * This is meant to provide the python code with all ExternalTools defined in the OllamaObject. + * @return The generated external_tools.py file + */ private String generateExternalTools() { StringBuilder code = new StringBuilder(); @@ -243,9 +266,9 @@ public class PythonRunner extends OllamaFuntionTool { """); - for(Pair funtionTool : core.getFuntionTools()) + for(Pair funtionTool : core.getFuntionTools()) { - OllamaFuntionTool tool = funtionTool.getKey(); + OllamaFunctionTool tool = funtionTool.getKey(); String name = tool.name(); @@ -293,7 +316,10 @@ public class PythonRunner extends OllamaFuntionTool { return code.toString(); } - + + /** + * A Helper class to get the logs from a docker container. + */ public class GetContainerLog { private DockerClient dockerClient; private String containerId; @@ -301,13 +327,22 @@ public class PythonRunner extends OllamaFuntionTool { 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<>(); diff --git a/Display/src/main/java/me/zacharias/chat/display/TimeTool.java b/Display/src/main/java/me/zacharias/chat/display/TimeTool.java index edb7c71..8d365a3 100644 --- a/Display/src/main/java/me/zacharias/chat/display/TimeTool.java +++ b/Display/src/main/java/me/zacharias/chat/display/TimeTool.java @@ -1,13 +1,17 @@ package me.zacharias.chat.display; import me.zacharias.chat.ollama.OllamaFunctionArgument; -import me.zacharias.chat.ollama.OllamaFuntionTool; +import me.zacharias.chat.ollama.OllamaFunctionTool; import me.zacharias.chat.ollama.OllamaPerameter; import me.zacharias.chat.ollama.OllamaToolRespnce; import java.util.Date; -public class TimeTool extends OllamaFuntionTool { +/** + * A tool that returns the current date. + * This gives Ollama the ability to get the current date. + */ +public class TimeTool extends OllamaFunctionTool { @Override public OllamaToolRespnce function(OllamaFunctionArgument... arguments) { diff --git a/build.gradle b/build.gradle index 7bfaa0b..da829b0 100644 --- a/build.gradle +++ b/build.gradle @@ -20,5 +20,21 @@ subprojects { dependencies { implementation("org.json:json:20250107") implementation("com.github.docker-java:docker-java:3.4.1") + implementation("org.jetbrains:annotations:23.1.0") + } + + task sourcesJar(type: Jar, dependsOn: classes) { + archiveClassifier = 'sources' + from sourceSets.main.allSource + } + + task javadocJar(type: Jar, dependsOn: javadoc) { + archiveClassifier = 'javadoc' + from javadoc.destinationDir + } + + artifacts { + archives sourcesJar + archives javadocJar } } \ No newline at end of file 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 1964e52..4cac132 100644 --- a/launcher/src/main/java/me/zacharias/chat/launcher/Launcher.java +++ b/launcher/src/main/java/me/zacharias/chat/launcher/Launcher.java @@ -4,7 +4,17 @@ import me.zacharias.chat.api.APIServer; import me.zacharias.chat.core.LaunchOptions; import me.zacharias.chat.display.Display; +/** + * The launcher for AI_chat.
+ * This is the main class of the application and is responsible for handling the command line arguments. + */ public class Launcher { + /** + * The Entry point of the application.
+ * This is the main method of the application and is responsible for handling the command line arguments. + * and adding them to the LaunchOptions instance. + * @param args The command line arguments passed from JVM + */ public static void main(String[] args) { LaunchOptions options = LaunchOptions.getInstance(); @@ -42,10 +52,10 @@ public class Launcher { Launch options for AI_chat -h --help Provides this help message -s --server Starts the application as API server - -p --port Provides the port number that the API server shuld use, defaults to 39075 + -p --port Provides the port number that the API server should use, defaults to 39075 -o --output Redirects the API Server output to another file -y Auto accepts to prompts, used for a seamless run. Not recomended when running as Display - -d --dontloadOld Don't load old messages + -d --dontLoadOld Don't load old messages --api Provides API docs """); return;