Compare commits
3 Commits
a602d30901
...
57fc7f2533
| Author | SHA1 | Date | |
|---|---|---|---|
|
57fc7f2533
|
|||
|
840ad468e3
|
|||
|
796271443c
|
8
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
8
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="JavadocReference" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="REPORT_INACCESSIBLE" value="false" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
package me.zacharias.chat.core;
|
package me.zacharias.chat.core;
|
||||||
|
|
||||||
import me.zacharias.chat.core.memory.AddMemoryFunction;
|
import me.zacharias.chat.core.memory.*;
|
||||||
import me.zacharias.chat.core.memory.GetMemoryFunction;
|
|
||||||
import me.zacharias.chat.core.memory.RemoveMemoryFunction;
|
|
||||||
import me.zacharias.chat.ollama.*;
|
import me.zacharias.chat.ollama.*;
|
||||||
import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException;
|
import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException;
|
||||||
import me.zacharias.chat.plugin.Plugin;
|
import me.zacharias.chat.plugin.Plugin;
|
||||||
@@ -14,6 +12,7 @@ import org.json.JSONObject;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -53,7 +52,7 @@ public class Core {
|
|||||||
/**
|
/**
|
||||||
* The IP of the Ollama API.
|
* The IP of the Ollama API.
|
||||||
*/
|
*/
|
||||||
private String ollamaIP = "localhost";//"192.168.5.184";
|
private String ollamaIP = "192.168.5.178";//"192.168.5.184";
|
||||||
/**
|
/**
|
||||||
* The port of the Ollama API.
|
* The port of the Ollama API.
|
||||||
*/
|
*/
|
||||||
@@ -79,7 +78,7 @@ public class Core {
|
|||||||
static {
|
static {
|
||||||
String data;
|
String data;
|
||||||
|
|
||||||
if(System.getenv("AI-CHAT-DEBUG") != null) {
|
if(System.getenv("AI_CHAT_DEBUG") != null) {
|
||||||
data = "./data";
|
data = "./data";
|
||||||
}
|
}
|
||||||
else if(System.getProperty("os.name").toLowerCase().contains("windows")) {
|
else if(System.getProperty("os.name").toLowerCase().contains("windows")) {
|
||||||
@@ -169,8 +168,14 @@ public class Core {
|
|||||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||||
scheduler.shutdownNow();
|
scheduler.shutdownNow();
|
||||||
try {
|
try {
|
||||||
logWriter.flush();
|
try {
|
||||||
logWriter.close();
|
logWriter.flush();
|
||||||
|
logWriter.close();
|
||||||
|
}catch (IOException ignore)
|
||||||
|
{
|
||||||
|
// This exception is kinda expected. Since it can often occur that the logWriter is already closed
|
||||||
|
System.out.println("Failed to flush log file, but that is not a problem.");
|
||||||
|
}
|
||||||
|
|
||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd_HH-mm-ss");
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd_HH-mm-ss");
|
||||||
@@ -227,6 +232,8 @@ public class Core {
|
|||||||
addTool(new AddMemoryFunction(), Source.CORE);
|
addTool(new AddMemoryFunction(), Source.CORE);
|
||||||
addTool(new RemoveMemoryFunction(), Source.CORE);
|
addTool(new RemoveMemoryFunction(), Source.CORE);
|
||||||
addTool(new GetMemoryFunction(), Source.CORE);
|
addTool(new GetMemoryFunction(), Source.CORE);
|
||||||
|
addTool(new GetMemoriesFunction(), Source.CORE);
|
||||||
|
addTool(new GetMemoryIdentitiesFunction(), Source.CORE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new IllegalArgumentException("Ollama object is already set");
|
throw new IllegalArgumentException("Ollama object is already set");
|
||||||
@@ -323,8 +330,10 @@ public class Core {
|
|||||||
|
|
||||||
String ollamaObjectString = ollamaObject.toString();
|
String ollamaObjectString = ollamaObject.toString();
|
||||||
|
|
||||||
|
ollamaObjectString = ollamaObjectString.replace("\n", "\\n");
|
||||||
|
|
||||||
try(DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
|
try(DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
|
||||||
wr.writeBytes(ollamaObjectString);
|
wr.write(ollamaObjectString.getBytes(StandardCharsets.UTF_8));
|
||||||
wr.flush();
|
wr.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,6 +350,17 @@ public class Core {
|
|||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
response.append(line); // Adds every line to response till the end of file.
|
response.append(line); // Adds every line to response till the end of file.
|
||||||
}
|
}
|
||||||
|
}catch (Exception ex)
|
||||||
|
{
|
||||||
|
// If the server returns an error, we read the error stream instead
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()))) {
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
response.append(line);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("Error reading error stream: " + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||||
@@ -382,7 +402,7 @@ public class Core {
|
|||||||
if(jsonObject.has("function"))
|
if(jsonObject.has("function"))
|
||||||
{
|
{
|
||||||
JSONObject function = jsonObject.getJSONObject("function");
|
JSONObject function = jsonObject.getJSONObject("function");
|
||||||
List<Pair<OllamaFunctionTool, String>> functions = funtionTools.stream().filter(func -> func.getKey().name().equalsIgnoreCase(function.getString("name"))).toList();
|
List<Pair<OllamaFunctionTool, String>> functions = funtionTools.stream().filter(func -> (func.getKey().name()+func.getValue()).equalsIgnoreCase(function.getString("name"))).toList();
|
||||||
|
|
||||||
if(functions.isEmpty()) {
|
if(functions.isEmpty()) {
|
||||||
ollamaObject.addMessage(new OllamaToolError("Function '"+function.getString("name")+"' does not exist"));
|
ollamaObject.addMessage(new OllamaToolError("Function '"+function.getString("name")+"' does not exist"));
|
||||||
@@ -404,7 +424,7 @@ public class Core {
|
|||||||
try {
|
try {
|
||||||
OllamaToolRespnce function1 = func.function(argumentArrayList.toArray(new OllamaFunctionArgument[0]));
|
OllamaToolRespnce function1 = func.function(argumentArrayList.toArray(new OllamaFunctionArgument[0]));
|
||||||
ollamaObject.addMessage(function1);
|
ollamaObject.addMessage(function1);
|
||||||
printMessageHandler.printMessage((supportColor?"\u001b[34m":"")+"Call "+func.name() + (printMessageHandler.color()?"\u001b[0m":""));
|
printMessageHandler.printMessage((supportColor?"\u001b[34m":"")+"Call "+func.name() + (supportColor?"\u001b[0m":""));
|
||||||
writeLog("Successfully function call " + func.name() + " output: " + function1.getResponse());
|
writeLog("Successfully function call " + func.name() + " output: " + function1.getResponse());
|
||||||
} catch (OllamaToolErrorException e) {
|
} catch (OllamaToolErrorException e) {
|
||||||
ollamaObject.addMessage(new OllamaToolError(e.getMessage()));
|
ollamaObject.addMessage(new OllamaToolError(e.getMessage()));
|
||||||
@@ -427,11 +447,12 @@ public class Core {
|
|||||||
* @param responce the Ollama response
|
* @param responce the Ollama response
|
||||||
*/
|
*/
|
||||||
private void checkIfResponceMessage(JSONObject responce) {
|
private void checkIfResponceMessage(JSONObject responce) {
|
||||||
if(responce.getJSONObject("message").has("content") && !responce.getJSONObject("message").getString("content").isBlank())
|
String message = responce.getJSONObject("message").getString("content");
|
||||||
|
if(responce.getJSONObject("message").has("content") && !message.isBlank())
|
||||||
{
|
{
|
||||||
printMessageHandler.printMessage((supportColor?"\u001b[32m":"")+responce.getJSONObject("message").getString("content")+(supportColor?"\u001b[0m":""));
|
printMessageHandler.printMessage((supportColor?"\u001b[32m":"")+(LaunchOptions.getInstance().isShowFullMessage()? message : message.replaceAll("(?s)<think>.*?</think>", "")) +(supportColor?"\u001b[0m":""));
|
||||||
writeLog("Response content: "+responce.getJSONObject("message").getString("content"));
|
writeLog("Response content: "+ message);
|
||||||
ollamaObject.addMessage(new OllamaMessage(OllamaMessageRole.ASSISTANT, responce.getJSONObject("message").getString("content")));
|
ollamaObject.addMessage(new OllamaMessage(OllamaMessageRole.ASSISTANT, message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,8 +489,8 @@ public class Core {
|
|||||||
{
|
{
|
||||||
throw new PluginLoadingException("Plugin does not contain a plugin.json file", file.getName());
|
throw new PluginLoadingException("Plugin does not contain a plugin.json file", file.getName());
|
||||||
}
|
}
|
||||||
JSONObject pluginJson = new JSONObject(new String(fs.getPath("/plugin.json").toFile().readAllBytes()));
|
//JSONObject pluginJson = new JSONObject(new String(fs.getPath("/plugin.json").toFile().readAllBytes()));
|
||||||
Plugin plugin = loader.loadPlugin(pluginJson, fs);
|
//Plugin plugin = loader.loadPlugin(pluginJson, fs);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public class LaunchOptions {
|
|||||||
private boolean serverMode;
|
private boolean serverMode;
|
||||||
private boolean serverCredentialsEnabled;
|
private boolean serverCredentialsEnabled;
|
||||||
private boolean notDisplay = true;
|
private boolean notDisplay = true;
|
||||||
|
private boolean showFullMessage = false;
|
||||||
private int port = 39075;
|
private int port = 39075;
|
||||||
private String redirectOutput;
|
private String redirectOutput;
|
||||||
private String serverCredentials;
|
private String serverCredentials;
|
||||||
@@ -160,4 +161,20 @@ public class LaunchOptions {
|
|||||||
public void setNotDisplay(boolean notDisplay) {
|
public void setNotDisplay(boolean notDisplay) {
|
||||||
this.notDisplay = notDisplay;
|
this.notDisplay = notDisplay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets if the full message should be shown in the display.
|
||||||
|
* @return a boolean indicating if the full message should be shown.
|
||||||
|
*/
|
||||||
|
public boolean isShowFullMessage() {
|
||||||
|
return showFullMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets if the full message should be shown in the display.
|
||||||
|
* @param showFullMessage a boolean indicating if the full message should be shown.
|
||||||
|
*/
|
||||||
|
public void setShowFullMessage(boolean showFullMessage) {
|
||||||
|
this.showFullMessage = showFullMessage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import me.zacharias.chat.core.Core;
|
|||||||
import org.intellij.lang.annotations.MagicConstant;
|
import org.intellij.lang.annotations.MagicConstant;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.FileSystems;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,19 +20,25 @@ 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
|
* 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 directory;
|
private final File/*System*/ directory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance as well as setting the {@link #instance} to this new one
|
* Creates a new instance as well as setting the {@link #instance} to this new one
|
||||||
* @param baseDirectory the directory to be used as base directory
|
* @param baseDirectory the directory to be used as base directory
|
||||||
*/
|
*/
|
||||||
public FileHandler(@MagicConstant(valuesFromClass = FileHandlerLocation.class) String baseDirectory) {
|
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();
|
||||||
|
|
||||||
directory = new File(baseDirectory);
|
instance = this;
|
||||||
if(!directory.exists())
|
}catch (Exception ex)
|
||||||
directory.mkdirs();
|
{
|
||||||
|
throw new FileHandlerException("Failed to create FileHandler instance with base directory \"" + baseDirectory + "\"");
|
||||||
instance = this;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public class AddMemoryFunction extends OllamaFunctionTool {
|
|||||||
public OllamaPerameter parameters() {
|
public OllamaPerameter parameters() {
|
||||||
return OllamaPerameter.builder()
|
return OllamaPerameter.builder()
|
||||||
.addProperty("memory", OllamaPerameter.OllamaPerameterBuilder.Type.STRING, "The memory to remember", true)
|
.addProperty("memory", OllamaPerameter.OllamaPerameterBuilder.Type.STRING, "The memory to remember", true)
|
||||||
|
.addProperty("identity", OllamaPerameter.OllamaPerameterBuilder.Type.STRING, "The identity of the memory to remember", true)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,8 +39,25 @@ public class AddMemoryFunction extends OllamaFunctionTool {
|
|||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
throw new OllamaToolErrorException(name(), "Missing memory argument");
|
throw new OllamaToolErrorException(name(), "Missing memory argument");
|
||||||
}
|
}
|
||||||
String value = (String) args[0].value();
|
|
||||||
memory.addMemory(value);
|
String memory = null;
|
||||||
return new OllamaToolRespnce(name(), "Added "+value+" to the memory");
|
String identity = null;
|
||||||
|
|
||||||
|
for(OllamaFunctionArgument arg : args) {
|
||||||
|
if (arg.argument().equals("memory")) {
|
||||||
|
memory = (String) arg.value();
|
||||||
|
} else if (arg.argument().equals("identity")) {
|
||||||
|
identity = (String) arg.value();
|
||||||
|
} else {
|
||||||
|
throw new OllamaToolErrorException(name(), "Unknown argument: " + arg.argument());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memory == null || identity == null) {
|
||||||
|
throw new OllamaToolErrorException(name(), "Missing memory or identity argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.memory.addMemory(identity, memory);
|
||||||
|
return new OllamaToolRespnce(name(), "Added "+identity+" to the memory");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package me.zacharias.chat.core.memory;
|
package me.zacharias.chat.core.memory;
|
||||||
|
|
||||||
|
import me.zacharias.chat.core.Core;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ public class CoreMemory {
|
|||||||
/**
|
/**
|
||||||
* The singleton instance of CoreMemory.
|
* The singleton instance of CoreMemory.
|
||||||
*/
|
*/
|
||||||
private static CoreMemory instance = new CoreMemory("./cache/CoreMemory.json");
|
private static final CoreMemory instance = new CoreMemory(Core.DATA + "/CoreMemory.json");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the singleton instance of CoreMemory.
|
* Gets the singleton instance of CoreMemory.
|
||||||
@@ -38,16 +39,7 @@ public class CoreMemory {
|
|||||||
while ((buffer = br.readLine()) != null) {
|
while ((buffer = br.readLine()) != null) {
|
||||||
data.append(buffer);
|
data.append(buffer);
|
||||||
}
|
}
|
||||||
JSONArray jsonArray = new JSONArray(data.toString());
|
memory = new JSONObject(data.toString());
|
||||||
for(Object obj : jsonArray) {
|
|
||||||
if(obj instanceof String str) {
|
|
||||||
memory.add(str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memory.add(obj.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}catch (Exception e) {
|
}catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -63,18 +55,14 @@ public class CoreMemory {
|
|||||||
f.delete();
|
f.delete();
|
||||||
}
|
}
|
||||||
f.createNewFile();
|
f.createNewFile();
|
||||||
|
|
||||||
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
|
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
|
||||||
JSONArray jsonArray = new JSONArray();
|
|
||||||
|
|
||||||
for(String str : memory) {
|
bw.write(memory.toString());
|
||||||
jsonArray.put(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
bw.write(jsonArray.toString());
|
|
||||||
|
|
||||||
bw.close();
|
bw.close();
|
||||||
}catch (Exception e) {
|
}catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -83,7 +71,7 @@ public class CoreMemory {
|
|||||||
/**
|
/**
|
||||||
* The memory.
|
* The memory.
|
||||||
*/
|
*/
|
||||||
private ArrayList<String> memory = new ArrayList<>();
|
private JSONObject memory = new JSONObject();
|
||||||
/**
|
/**
|
||||||
* The file to store the memory in.
|
* The file to store the memory in.
|
||||||
*/
|
*/
|
||||||
@@ -91,25 +79,50 @@ public class CoreMemory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the memory.
|
* Gets the memory.
|
||||||
* @return The memory
|
* @return A list of memory identifies/names
|
||||||
*/
|
*/
|
||||||
public ArrayList<String> getMemory() {
|
public String[] getMemoriesIdentity() {
|
||||||
return memory;
|
return memory.keySet().toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMemory(String name) {
|
||||||
|
return memory.optString(name, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the memory.
|
* Sets the memory.
|
||||||
|
* @param name The name/identity of the memory
|
||||||
* @param memory The memory
|
* @param memory The memory
|
||||||
*/
|
*/
|
||||||
public void addMemory(String memory) {
|
public void addMemory(String name, String memory) {
|
||||||
this.memory.add(memory);
|
this.memory.put(name, memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the memory.
|
* Removes the memory.
|
||||||
* @param memory The memory to remove
|
* @param name The memory to remove
|
||||||
*/
|
*/
|
||||||
public void removeMemory(String memory) {
|
public void removeMemory(String name) {
|
||||||
this.memory.remove(memory);
|
this.memory.remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all memories as a JSON string.
|
||||||
|
* @return A JSON string of all memories
|
||||||
|
*/
|
||||||
|
public String getMemories() {
|
||||||
|
ArrayList<String> memories = new ArrayList<>();
|
||||||
|
for (String key : memory.keySet()) {
|
||||||
|
memories.add(key + ": " + memory.getString(key));
|
||||||
|
}
|
||||||
|
return new JSONArray(memories).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getMemoriesArray() {
|
||||||
|
ArrayList<String> memories = new ArrayList<>();
|
||||||
|
for (String key : memory.keySet()) {
|
||||||
|
memories.add(key + ": " + memory.getString(key));
|
||||||
|
}
|
||||||
|
return memories;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package me.zacharias.chat.core.memory;
|
||||||
|
|
||||||
|
import me.zacharias.chat.ollama.OllamaFunctionArgument;
|
||||||
|
import me.zacharias.chat.ollama.OllamaFunctionTool;
|
||||||
|
import me.zacharias.chat.ollama.OllamaPerameter;
|
||||||
|
import me.zacharias.chat.ollama.OllamaToolRespnce;
|
||||||
|
|
||||||
|
public class GetMemoriesFunction extends OllamaFunctionTool {
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "get_memories";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return "Retrieves all the memories.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OllamaPerameter parameters() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OllamaToolRespnce function(OllamaFunctionArgument... args) {
|
||||||
|
return new OllamaToolRespnce(name(), CoreMemory.getInstance().getMemories());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,16 +24,18 @@ public class GetMemoryFunction extends OllamaFunctionTool {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String description() {
|
public String description() {
|
||||||
return "Retrieves all the memory's";
|
return "Retrieves the memory for a given identity.";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OllamaPerameter parameters() {
|
public OllamaPerameter parameters() {
|
||||||
return null;
|
return OllamaPerameter.builder()
|
||||||
|
.addProperty("identity", OllamaPerameter.OllamaPerameterBuilder.Type.STRING, "The identity of the memory to retrieve", true)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OllamaToolRespnce function(OllamaFunctionArgument... args) {
|
public OllamaToolRespnce function(OllamaFunctionArgument... args) {
|
||||||
return new OllamaToolRespnce(name(), new JSONObject().put("memory_items", new JSONArray(memory.getMemory())).toString());
|
return new OllamaToolRespnce(name(), memory.getMemory((String) (args[0].value())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package me.zacharias.chat.core.memory;
|
||||||
|
|
||||||
|
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 org.json.JSONArray;
|
||||||
|
|
||||||
|
public class GetMemoryIdentitiesFunction extends OllamaFunctionTool {
|
||||||
|
CoreMemory memory = CoreMemory.getInstance();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "get_memory_identities";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return "Retrieves all the memory identities.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OllamaPerameter parameters() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OllamaToolRespnce function(OllamaFunctionArgument... args) {
|
||||||
|
return new OllamaToolRespnce(this.name(), new JSONArray(memory.getMemoriesIdentity()).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,7 +29,7 @@ public class RemoveMemoryFunction extends OllamaFunctionTool {
|
|||||||
@Override
|
@Override
|
||||||
public OllamaPerameter parameters() {
|
public OllamaPerameter parameters() {
|
||||||
return OllamaPerameter.builder()
|
return OllamaPerameter.builder()
|
||||||
.addProperty("memory", OllamaPerameter.OllamaPerameterBuilder.Type.STRING, "The memory to forget", true)
|
.addProperty("identity", OllamaPerameter.OllamaPerameterBuilder.Type.STRING, "The identity of the memory to forget", true)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public class OllamaMessage {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
json.put("role", role.getRole());
|
json.put("role", role.getRole());
|
||||||
json.put("content", content);
|
json.put("content", content.replace("\n", "\\n"));
|
||||||
return json.toString();
|
return json.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package me.zacharias.chat.ollama.utils;
|
||||||
|
|
||||||
|
import me.zacharias.chat.ollama.OllamaMessage;
|
||||||
|
import me.zacharias.chat.ollama.OllamaMessageRole;
|
||||||
|
|
||||||
|
public class SystemMessage extends OllamaMessage {
|
||||||
|
/**
|
||||||
|
* Creates a new instance of OllamaMessage.
|
||||||
|
*
|
||||||
|
* @param systemMessage The content of the message
|
||||||
|
*/
|
||||||
|
public SystemMessage(String systemMessage) {
|
||||||
|
super(OllamaMessageRole.SYSTEM, systemMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,9 @@ version = '1.0-SNAPSHOT'
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":Core")
|
implementation project(":Core")
|
||||||
implementation project(":MALAPITool")
|
implementation project(":MALAPITool")
|
||||||
|
implementation project(":GeniusAPI")
|
||||||
implementation project(":API")
|
implementation project(":API")
|
||||||
|
implementation project(":WikipediaTool")
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ import me.zacharias.chat.core.files.FileHandlerLocation;
|
|||||||
import me.zacharias.chat.core.memory.CoreMemory;
|
import me.zacharias.chat.core.memory.CoreMemory;
|
||||||
import me.zacharias.chat.mal.api.MALAPITool;
|
import me.zacharias.chat.mal.api.MALAPITool;
|
||||||
import me.zacharias.chat.ollama.*;
|
import me.zacharias.chat.ollama.*;
|
||||||
|
import me.zacharias.chat.ollama.utils.SystemMessage;
|
||||||
|
import me.zacharias.neuro.dock.genius.GeniusTools;
|
||||||
|
import me.zacharias.neuro.dock.wikipedia.WikipediaTool;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@@ -51,13 +54,17 @@ public class Display {
|
|||||||
.keep_alive(10)
|
.keep_alive(10)
|
||||||
//.stream(false)
|
//.stream(false)
|
||||||
//.addFileTools(FileHandlerLocation.DATA_FILES)
|
//.addFileTools(FileHandlerLocation.DATA_FILES)
|
||||||
|
.addMessages(new SystemMessage("You need to emulate feelings and emotions."))
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
core.enablePlugins(Core.PLUGIN_DIRECTORY);
|
core.enablePlugins(Core.PLUGIN_DIRECTORY);
|
||||||
|
|
||||||
core.addTool(new TimeTool(), Core.Source.INTERNAL);
|
core.addTool(new TimeTool(), Core.Source.INTERNAL);
|
||||||
//core.addTool(new PythonRunner(core), Core.Source.INTERNAL);
|
// TODO: Well Docker failes when luanched.... Fuck
|
||||||
|
// core.addTool(new PythonRunner(core), Core.Source.INTERNAL);
|
||||||
core.addTools(new MALAPITool().getOllamaTools());
|
core.addTools(new MALAPITool().getOllamaTools());
|
||||||
|
core.addTools(new GeniusTools().getGeniusTools());
|
||||||
|
core.addTools(new WikipediaTool().getWikipediaToolsInstance());
|
||||||
|
|
||||||
APIApplication.start();
|
APIApplication.start();
|
||||||
|
|
||||||
@@ -98,9 +105,12 @@ public class Display {
|
|||||||
case "help":
|
case "help":
|
||||||
System.out.print("""
|
System.out.print("""
|
||||||
Available commands:
|
Available commands:
|
||||||
/help Prints this help message.
|
/help Prints this help message.
|
||||||
/bye Exits the program.
|
/bye Exits the program.
|
||||||
/write Flushes the current log stream to file.
|
/write Flushes the current log stream to file.
|
||||||
|
/list Lists all available tools.
|
||||||
|
/working Prints the current working directories.
|
||||||
|
/peek Peeks the current memory.
|
||||||
""");
|
""");
|
||||||
break;
|
break;
|
||||||
case "bye":
|
case "bye":
|
||||||
@@ -114,7 +124,7 @@ public class Display {
|
|||||||
case "peek":
|
case "peek":
|
||||||
CoreMemory coreMemory = CoreMemory.getInstance();
|
CoreMemory coreMemory = CoreMemory.getInstance();
|
||||||
StringBuilder buffer = new StringBuilder("[");
|
StringBuilder buffer = new StringBuilder("[");
|
||||||
ArrayList<String> memory = new ArrayList<>(coreMemory.getMemory());
|
ArrayList<String> memory = new ArrayList<>(coreMemory.getMemoriesArray());
|
||||||
for(int i = 0; i < memory.size(); i++) {
|
for(int i = 0; i < memory.size(); i++) {
|
||||||
String mem = memory.get(i);
|
String mem = memory.get(i);
|
||||||
buffer.append("\"").append(mem).append("\"");
|
buffer.append("\"").append(mem).append("\"");
|
||||||
@@ -126,6 +136,29 @@ public class Display {
|
|||||||
writeLog("Memory peek: "+buffer.toString());
|
writeLog("Memory peek: "+buffer.toString());
|
||||||
System.out.println(buffer.toString());
|
System.out.println(buffer.toString());
|
||||||
break;
|
break;
|
||||||
|
case "list":
|
||||||
|
writeLog("Tools installed in this instance");
|
||||||
|
|
||||||
|
for(Pair<OllamaFunctionTool, String> funtion : core.getFuntionTools()) {
|
||||||
|
StringBuilder args = new StringBuilder();
|
||||||
|
OllamaPerameter perameter = funtion.getKey().parameters();
|
||||||
|
if (perameter != null) {
|
||||||
|
JSONObject obj = perameter.getProperties();
|
||||||
|
for (String name : obj.keySet()) {
|
||||||
|
args.append(args.toString().isBlank() ? "" : ", ").append(obj.getJSONObject(name).getString("type")).append(Arrays.stream(perameter.getRequired()).anyMatch(str -> str.equalsIgnoreCase(name)) ? "" : "?").append(" ").append(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("> Function: " + funtion.getKey().name() + "(" + args + ") [" + funtion.getValue() + "]");
|
||||||
|
writeLog("Function: " + funtion.getKey().name() + "(" + args + ") [" + funtion.getValue() + "]");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "working":
|
||||||
|
System.out.println("Working directories:\n" +
|
||||||
|
" Data: " + Core.DATA_DIR.getAbsolutePath() + "\n" +
|
||||||
|
" DateFiles: " + FileHandlerLocation.DATA_FILES + "\n" +
|
||||||
|
" Plugins: " + Core.PLUGIN_DIRECTORY.getAbsolutePath());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
System.out.println("Unknown command: " + message);
|
System.out.println("Unknown command: " + message);
|
||||||
}
|
}
|
||||||
|
|||||||
24
GeniusAPI/build.gradle
Normal file
24
GeniusAPI/build.gradle
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
}
|
||||||
|
|
||||||
|
group = 'me.zacharias'
|
||||||
|
version = '1.0-SNAPSHOT'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation platform('org.junit:junit-bom:5.10.0')
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||||
|
|
||||||
|
implementation "org.jsoup:jsoup:1.20.1"
|
||||||
|
implementation 'io.github.classgraph:classgraph:4.8.158'
|
||||||
|
|
||||||
|
implementation project(":Core")
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package me.zacharias.neuro.dock.genius;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface GeniusEndpoint {
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package me.zacharias.neuro.dock.genius;
|
||||||
|
|
||||||
|
import me.zacharias.chat.ollama.OllamaFunctionTool;
|
||||||
|
|
||||||
|
public abstract class GeniusEndpointTool extends OllamaFunctionTool {
|
||||||
|
protected GeniusTools geniusToolsInstance;
|
||||||
|
|
||||||
|
public GeniusEndpointTool(GeniusTools geniusTools) {
|
||||||
|
super();
|
||||||
|
this.geniusToolsInstance = geniusTools;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
package me.zacharias.neuro.dock.genius;
|
||||||
|
|
||||||
|
import com.google.common.reflect.ClassPath;
|
||||||
|
import io.github.classgraph.ClassGraph;
|
||||||
|
import io.github.classgraph.ClassInfo;
|
||||||
|
import io.github.classgraph.ClassInfoList;
|
||||||
|
import io.github.classgraph.ScanResult;
|
||||||
|
import me.zacharias.chat.core.Core;
|
||||||
|
import me.zacharias.chat.ollama.OllamaFunctionTool;
|
||||||
|
import me.zacharias.chat.ollama.OllamaFunctionTools;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class GeniusTools {
|
||||||
|
|
||||||
|
public final String Client_ID;
|
||||||
|
public final String Client_Secret;
|
||||||
|
public final String Access_Token;
|
||||||
|
public final String BaseURL = "https://api.genius.com";
|
||||||
|
public final OllamaFunctionTools GeniusTools;
|
||||||
|
public final File CacheFile = new File(Core.DATA_DIR + "/genius_cache.json");
|
||||||
|
public JSONObject CacheData;
|
||||||
|
|
||||||
|
public GeniusTools() {
|
||||||
|
super();
|
||||||
|
try {
|
||||||
|
JSONObject obj = new JSONObject(Files.readString(Path.of(Core.DATA_DIR + "/geniusapi.json")));
|
||||||
|
this.Client_ID = obj.getString("client_id");
|
||||||
|
this.Client_Secret = obj.getString("client_secret");
|
||||||
|
this.Access_Token = obj.getString("access_token");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(CacheFile.exists()) {
|
||||||
|
try{
|
||||||
|
CacheData = new JSONObject(Files.readString(CacheFile.toPath()));
|
||||||
|
}catch (IOException ex)
|
||||||
|
{
|
||||||
|
ex.printStackTrace();
|
||||||
|
if(CacheData == null)
|
||||||
|
CacheData = new JSONObject();
|
||||||
|
CacheFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CacheData = new JSONObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||||
|
try {
|
||||||
|
Files.writeString(CacheFile.toPath(), CacheData.toString());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
OllamaFunctionTools.OllamaFunctionToolsBuilder builder = new OllamaFunctionTools.OllamaFunctionToolsBuilder();
|
||||||
|
|
||||||
|
try(ScanResult scanResult = new ClassGraph().enableAllInfo().acceptPackages("me.zacharias.neuro.dock.genius.endpoints").scan()) {
|
||||||
|
ClassInfoList endpoints = scanResult.getClassesWithAnnotation(GeniusEndpoint.class.getName());
|
||||||
|
for (ClassInfo classInfo : endpoints) {
|
||||||
|
Class<?> clazz = classInfo.loadClass();
|
||||||
|
if (OllamaFunctionTool.class.isAssignableFrom(clazz)) {
|
||||||
|
//System.out.println("Found endpoint: " + clazz.getName() + " With constructor: " + clazz.getDeclaredConstructors().f.getName() + " and arguments: " + Arrays.toString(clazz.getDeclaredConstructor().getParameterTypes()));
|
||||||
|
GeniusEndpointTool tool = (GeniusEndpointTool) clazz.getDeclaredConstructor(GeniusTools.class).newInstance(this);
|
||||||
|
builder.addTool(tool, Core.Source.INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.GeniusTools = builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public OllamaFunctionTools getGeniusTools() {
|
||||||
|
return this.GeniusTools;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject getGeniusEndpoint(String endpoint, Map<String, String> params) {
|
||||||
|
try {
|
||||||
|
URL url = new URL(this.BaseURL + endpoint + "?" + ParameterStringBuilder.getParamsString(params));
|
||||||
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||||
|
conn.setRequestMethod("GET");
|
||||||
|
conn.setRequestProperty("Authorization", "Bearer " + this.Access_Token);
|
||||||
|
conn.setRequestProperty("Accept", "application/json");
|
||||||
|
|
||||||
|
if (conn.getResponseCode() != 200) {
|
||||||
|
throw new IOException("Failed to connect to Genius API: " + conn.getResponseCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||||
|
String inputLine;
|
||||||
|
StringBuilder response = new StringBuilder();
|
||||||
|
|
||||||
|
while ((inputLine = in.readLine()) != null) {
|
||||||
|
response.append(inputLine);
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
return new JSONObject(response.toString());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String hasCache(int song_id) {
|
||||||
|
if(CacheData.has(Integer.toString(song_id)))
|
||||||
|
return CacheData.getString(Integer.toString(song_id));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cacheLyrics(int song_id, String lyrics) {
|
||||||
|
CacheData.put(Integer.toString(song_id), lyrics);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package me.zacharias.neuro.dock.genius;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ParameterStringBuilder {
|
||||||
|
public static String getParamsString(Map<String, String> params)
|
||||||
|
throws UnsupportedEncodingException {
|
||||||
|
if(params == null)
|
||||||
|
return "";
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||||
|
result.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8));
|
||||||
|
result.append("=");
|
||||||
|
result.append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
|
||||||
|
result.append("&");
|
||||||
|
}
|
||||||
|
|
||||||
|
String resultString = result.toString();
|
||||||
|
return !resultString.isEmpty()
|
||||||
|
? resultString.substring(0, resultString.length() - 1)
|
||||||
|
: resultString;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package me.zacharias.neuro.dock.genius.endpoints;
|
||||||
|
|
||||||
|
import me.zacharias.chat.ollama.OllamaFunctionArgument;
|
||||||
|
import me.zacharias.chat.ollama.OllamaPerameter;
|
||||||
|
import me.zacharias.chat.ollama.OllamaToolRespnce;
|
||||||
|
import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException;
|
||||||
|
import me.zacharias.neuro.dock.genius.GeniusEndpoint;
|
||||||
|
import me.zacharias.neuro.dock.genius.GeniusEndpointTool;
|
||||||
|
import me.zacharias.neuro.dock.genius.GeniusTools;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static me.zacharias.chat.ollama.OllamaPerameter.OllamaPerameterBuilder.Type.STRING;
|
||||||
|
|
||||||
|
@GeniusEndpoint
|
||||||
|
public class FindSong extends GeniusEndpointTool {
|
||||||
|
public FindSong(GeniusTools geniusTools) {
|
||||||
|
super(geniusTools);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "findsong";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return "Finds a song by title from the Genius API.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OllamaPerameter parameters() {
|
||||||
|
return OllamaPerameter.builder()
|
||||||
|
.addProperty("title", STRING, "The title, artitst, and song_id of the song to find.", true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OllamaToolRespnce function(OllamaFunctionArgument... args) {
|
||||||
|
String title = (String) args[0].value();
|
||||||
|
if (title == null || title.isEmpty()) {
|
||||||
|
throw new OllamaToolErrorException(this.name(), "Title cannot be null or empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject response = this.geniusToolsInstance.getGeniusEndpoint("/search", Map.of("q", title));
|
||||||
|
|
||||||
|
JSONArray responseData = new JSONArray();
|
||||||
|
|
||||||
|
for(Object obj : response.getJSONObject("response").getJSONArray("hits")) {
|
||||||
|
if(obj instanceof JSONObject songResult) {
|
||||||
|
JSONObject song = songResult.getJSONObject("result");
|
||||||
|
JSONObject songData = new JSONObject();
|
||||||
|
songData.put("title", song.getString("title"));
|
||||||
|
songData.put("artist", song.getString("artist_names"));
|
||||||
|
songData.put("id", song.getInt("id"));
|
||||||
|
responseData.put(songData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseData.isEmpty()) {
|
||||||
|
throw new OllamaToolErrorException(this.name(), "No songs found for the given title.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OllamaToolRespnce(this.name(), responseData.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package me.zacharias.neuro.dock.genius.endpoints;
|
||||||
|
|
||||||
|
import me.zacharias.chat.ollama.OllamaFunctionArgument;
|
||||||
|
import me.zacharias.chat.ollama.OllamaPerameter;
|
||||||
|
import me.zacharias.chat.ollama.OllamaToolRespnce;
|
||||||
|
import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException;
|
||||||
|
import me.zacharias.neuro.dock.genius.GeniusEndpoint;
|
||||||
|
import me.zacharias.neuro.dock.genius.GeniusEndpointTool;
|
||||||
|
import me.zacharias.neuro.dock.genius.GeniusTools;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.jsoup.nodes.Node;
|
||||||
|
import org.jsoup.nodes.TextNode;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static me.zacharias.chat.core.Core.writeLog;
|
||||||
|
|
||||||
|
@GeniusEndpoint
|
||||||
|
public class GetLyrics extends GeniusEndpointTool {
|
||||||
|
public GetLyrics(GeniusTools geniusTools) {
|
||||||
|
super(geniusTools);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "get_lyrics";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return "Gets the lyrics of a song by its ID from the Genius API.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OllamaPerameter parameters() {
|
||||||
|
return OllamaPerameter.builder()
|
||||||
|
.addProperty("song_id", OllamaPerameter.OllamaPerameterBuilder.Type.INT, "The ID of the song to get lyrics for.", true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OllamaToolRespnce function(OllamaFunctionArgument... args) {
|
||||||
|
|
||||||
|
String lyricsStr = geniusToolsInstance.hasCache((int) args[0].value());
|
||||||
|
|
||||||
|
if(lyricsStr != null)
|
||||||
|
{
|
||||||
|
// If we have a cached response, return it
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject obj = geniusToolsInstance.getGeniusEndpoint("/songs/" + args[0].value(), null);
|
||||||
|
|
||||||
|
String lyrics_path = obj.getJSONObject("response").getJSONObject("song").getString("url");
|
||||||
|
try {
|
||||||
|
Document doc = Jsoup.connect(lyrics_path)
|
||||||
|
.userAgent("Mozilla/5.0")
|
||||||
|
.get();
|
||||||
|
|
||||||
|
writeLog("Fetching lyrics from: " + lyrics_path);
|
||||||
|
|
||||||
|
Elements containers = doc.select("div[data-lyrics-container=true]");
|
||||||
|
|
||||||
|
StringBuilder lyrics = new StringBuilder();
|
||||||
|
|
||||||
|
for (Element container : containers) {
|
||||||
|
for(Node n : container.childNodes())
|
||||||
|
{
|
||||||
|
if(n instanceof Element e) {
|
||||||
|
if (e.attribute("data-exclude-from-selection") != null && e.attr("data-exclude-from-selection").equals("true")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if(e.tagName().equalsIgnoreCase("br"))
|
||||||
|
{
|
||||||
|
lyrics.append("\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//System.out.println(container.tagName());
|
||||||
|
String s = e.text();
|
||||||
|
lyrics.append(s.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(n instanceof TextNode tn)
|
||||||
|
{
|
||||||
|
String s = tn.text();
|
||||||
|
if (!s.isBlank()) {
|
||||||
|
lyrics.append(s.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
geniusToolsInstance.cacheLyrics((int) args[0].value(), lyrics.toString());
|
||||||
|
|
||||||
|
return new OllamaToolRespnce(this.name(), lyrics.toString().trim());
|
||||||
|
}catch (Exception ex)
|
||||||
|
{
|
||||||
|
ex.printStackTrace();
|
||||||
|
throw new OllamaToolErrorException(this.name(), "Failed to fetch lyrics.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
60
GeniusAPI/src/test/java/LyricsFetch.java
Normal file
60
GeniusAPI/src/test/java/LyricsFetch.java
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.jsoup.nodes.Node;
|
||||||
|
import org.jsoup.nodes.TextNode;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import javax.swing.text.html.HTML;
|
||||||
|
import java.util.regex.MatchResult;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static me.zacharias.chat.core.Core.writeLog;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
|
public class LyricsFetch {
|
||||||
|
Pattern pattern = Pattern.compile("(?i)\\[(verse.*)|(chorus.*)|(bridge.*)|(outro.*)|(intro.*)]");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFetchLyrics() throws Exception {
|
||||||
|
Document doc = Jsoup.connect("https://genius.com/Neuro-sama-life-lyrics")
|
||||||
|
.userAgent("Mozilla/5.0")
|
||||||
|
.get();
|
||||||
|
|
||||||
|
Elements containers = doc.select("div[data-lyrics-container=true]");
|
||||||
|
|
||||||
|
StringBuilder lyrics = new StringBuilder();
|
||||||
|
|
||||||
|
for (Element container : containers) {
|
||||||
|
for(Node n : container.childNodes())
|
||||||
|
{
|
||||||
|
if(n instanceof Element e) {
|
||||||
|
if (e.attribute("data-exclude-from-selection") != null && e.attr("data-exclude-from-selection").equals("true")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if(e.tagName().equalsIgnoreCase("br"))
|
||||||
|
{
|
||||||
|
lyrics.append("\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.out.println(container.tagName());
|
||||||
|
String s = e.text();
|
||||||
|
lyrics.append(s.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(n instanceof TextNode tn)
|
||||||
|
{
|
||||||
|
String s = tn.text();
|
||||||
|
if (!s.isBlank()) {
|
||||||
|
lyrics.append(s.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(lyrics.toString());
|
||||||
|
assertNotNull(lyrics.toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@ import java.util.Map;
|
|||||||
public class ParameterStringBuilder {
|
public class ParameterStringBuilder {
|
||||||
public static String getParamsString(Map<String, String> params)
|
public static String getParamsString(Map<String, String> params)
|
||||||
throws UnsupportedEncodingException {
|
throws UnsupportedEncodingException {
|
||||||
|
if(params == null)
|
||||||
|
return "";
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
|
|
||||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||||
|
|||||||
23
WikipediaTool/build.gradle
Normal file
23
WikipediaTool/build.gradle
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
}
|
||||||
|
|
||||||
|
group = 'me.zacharias'
|
||||||
|
version = '1.0-SNAPSHOT'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation platform('org.junit:junit-bom:5.10.0')
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||||
|
|
||||||
|
implementation("io.github.fastily:jwiki:1.11.0")
|
||||||
|
|
||||||
|
implementation project(":Core")
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package me.zacharias.neuro.dock.wikipedia;
|
||||||
|
|
||||||
|
import io.github.fastily.jwiki.core.Wiki;
|
||||||
|
import me.zacharias.chat.ollama.OllamaFunctionArgument;
|
||||||
|
import me.zacharias.chat.ollama.OllamaFunctionTool;
|
||||||
|
import me.zacharias.chat.ollama.OllamaPerameter;
|
||||||
|
import me.zacharias.chat.ollama.OllamaToolRespnce;
|
||||||
|
|
||||||
|
public class GetWikiPageText extends OllamaFunctionTool {
|
||||||
|
Wiki wiki = WikipediaTool.wiki;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "get_wiki_page_text";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return "Gets the text of a Wikipedia page by its title.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OllamaPerameter parameters() {
|
||||||
|
return OllamaPerameter.builder()
|
||||||
|
.addProperty("title", OllamaPerameter.OllamaPerameterBuilder.Type.STRING, "The title of the Wikipedia page to retrieve text from.", true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OllamaToolRespnce function(OllamaFunctionArgument... args) {
|
||||||
|
return new OllamaToolRespnce(name(), wiki.getPageText((String) args[0].value()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package me.zacharias.neuro.dock.wikipedia;
|
||||||
|
|
||||||
|
import io.github.fastily.jwiki.core.Wiki;
|
||||||
|
import me.zacharias.chat.core.Core;
|
||||||
|
import me.zacharias.chat.ollama.OllamaFunctionTools;
|
||||||
|
|
||||||
|
public class WikipediaTool {
|
||||||
|
private OllamaFunctionTools wikipediaToolsInstance;
|
||||||
|
|
||||||
|
public static Wiki wiki = new Wiki.Builder()
|
||||||
|
//.withDomain("en.wikipedia.org")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public WikipediaTool() {
|
||||||
|
this.wikipediaToolsInstance = OllamaFunctionTools.builder()
|
||||||
|
.addTool(new GetWikiPageText(), Core.Source.INTERNAL)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public OllamaFunctionTools getWikipediaToolsInstance() {
|
||||||
|
return wikipediaToolsInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,6 +59,7 @@ public class Launcher {
|
|||||||
-o --output Redirects the API Server output to another file
|
-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
|
-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
|
||||||
|
-f --full-message Shows the models <think>...</think> block in the output
|
||||||
--api Provides API docs
|
--api Provides API docs
|
||||||
""");
|
""");
|
||||||
return;
|
return;
|
||||||
@@ -71,6 +72,10 @@ public class Launcher {
|
|||||||
{
|
{
|
||||||
options.setLoadOld(false);
|
options.setLoadOld(false);
|
||||||
}
|
}
|
||||||
|
case "-f", "--full-message" ->
|
||||||
|
{
|
||||||
|
options.setShowFullMessage(true);
|
||||||
|
}
|
||||||
|
|
||||||
default -> {
|
default -> {
|
||||||
System.out.println("Unknown option: " + arg+"\nUse --help for help");
|
System.out.println("Unknown option: " + arg+"\nUse --help for help");
|
||||||
|
|||||||
@@ -2,4 +2,6 @@ rootProject.name = 'AI-test'
|
|||||||
include 'API', 'Core', 'Display', 'launcher'
|
include 'API', 'Core', 'Display', 'launcher'
|
||||||
|
|
||||||
|
|
||||||
include 'MALAPITool'
|
include 'MALAPITool'
|
||||||
|
include 'GeniusAPI'
|
||||||
|
include 'WikipediaTool'
|
||||||
Reference in New Issue
Block a user