Skip to content

Commit

Permalink
Added Response Formatter as Boolean
Browse files Browse the repository at this point in the history
Updated System Prompt to generate Responses with Format Variables if provided by tool

Updated Docker File
Updated Example Docker Compose
Updated Example Dot ENV

Removed Old ResponseFormatter
  • Loading branch information
ZeyoYT committed May 30, 2024
1 parent 06ca3e2 commit cf33c4d
Show file tree
Hide file tree
Showing 13 changed files with 98 additions and 50 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ OLLAMA_PORT=11434
OLLAMA_MODEL=MODEL_NAME_HERE
OLLAMA_EMBEDDING_MODEL=EMBEDDING_MODEL_NAME_HERE
OLLAMA_CHAT_MEMORY_UPTO=NUMBER
OLLAMA_TIMEOUT_SECONDS=NUMBER

# User Info
DEV_ID=YOUR_DISCORD_ID_HERE
Expand Down
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ ARG OLLAMA_EMBEDDING_MODEL
ENV OLLAMA_EMBEDDING_MODEL=${OLLAMA_EMBEDDING_MODEL}
ARG OLLAMA_CHAT_MEMORY_UPTO
ENV OLLAMA_CHAT_MEMORY_UPTO=${OLLAMA_CHAT_MEMORY_UPTO:-1}
ARG OLLAMA_TIMEOUT_SECONDS
ENV OLLAMA_TIMEOUT_SECONDS=${OLLAMA_TIMEOUT_SECONDS:-60}

ARG DEV_ID
ENV DEV_ID=${DEV_ID}
Expand All @@ -37,6 +39,7 @@ RUN echo "TOKEN=$TOKEN" > .env \
&& echo "OLLAMA_MODEL=$OLLAMA_MODEL" >> .env \
&& echo "OLLAMA_EMBEDDING_MODEL=$OLLAMA_EMBEDDING_MODEL" >> .env \
&& echo "OLLAMA_CHAT_MEMORY_UPTO=$OLLAMA_CHAT_MEMORY_UPTO" >> .env \
&& echo "OLLAMA_TIMEOUT_SECONDS=$OLLAMA_TIMEOUT_SECONDS" >> .env \
&& echo "DEV_ID=$DEV_ID" >> .env

# Add WHITELISTED_USERS to .env if provided
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ services:
- DEV_ID=<YOUR_DISCORD_ID>
# Optional Parameters :-
# Write inside single quotes and the user ids separated by commas, if you dont want to use this feature, just write '' (empty string enclosed by single quotes)
- OLLAMA_TIMEOUT_SECONDS=<OLLAMA_TIMEOUT_SECONDS>
- WHITELISTED_USERS='<user_id1>,<user_id2>,<user_id3> ... <user_idN>'
- SEARXNG_URL=<YOUR_SEARXNG_URL>
- SEARXNG_PORT=<YOUR_SEARXNG_PORT>
Expand Down
19 changes: 17 additions & 2 deletions src/main/java/me/ailama/commands/AiCommand.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package me.ailama.commands;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import me.ailama.handler.commandhandler.OllamaManager;
import me.ailama.handler.commandhandler.SearXNGManager;
Expand All @@ -15,7 +16,11 @@
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import net.dv8tion.jda.api.utils.data.DataObject;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -111,7 +116,7 @@ public void handleCommand(SlashCommandInteractionEvent event) {
{
// generate normal response based on the query if the url option is not provided or the web option is not provided
if(isTooledQuery) {
response = OllamaManager.getInstance().getTooledAssistant(modelOption, userId, null).answer(queryOption.replaceFirst(".", ""));
response = OllamaManager.getInstance().getTooledAssistant(modelOption, userId, null).answer(queryOption.replaceFirst(".", "") + "\n\n" + "user_id:" + userId);
}
else
{
Expand Down Expand Up @@ -145,7 +150,17 @@ public void handleCommand(SlashCommandInteractionEvent event) {
}
else
{
response = OllamaManager.getInstance().executeTool(tooled.name, tooled.parameters.values().toArray()).toString();
// if tooled.response contains a string that has ({response}) in it, replace it with the result of the tool
if(tooled.response != null && tooled.response.length > 0) {

System.out.println(Arrays.toString(tooled.response));
response = String.join("\n\n", tooled.response).replace("({response})", OllamaManager.getInstance().executeTool(tooled.name, tooled.parameters.values().toArray()).toString());

}
else
{
response = OllamaManager.getInstance().executeTool(tooled.name, tooled.parameters.values().toArray()).toString();
}
}
}
}
Expand Down
24 changes: 10 additions & 14 deletions src/main/java/me/ailama/handler/JsonBuilder/JsonObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,16 @@ public JsonObject bool(String key, boolean value) {
}

public JsonObject add(String key, Object value) {
if(value instanceof String) {
string(key, (String) value);
} else if(value instanceof Number) {
number(key, (Number) value);
} else if(value instanceof Boolean) {
bool(key, (Boolean) value);
} else if(value instanceof List) {
array(key, (List<?>) value);
} else if(value instanceof JsonArray) {
array(key, (JsonArray) value);
} else if(value instanceof JsonObject) {
object(key, (JsonObject) value);
} else if (value == null) {
nullKey(key);
switch (value) {
case String s -> string(key, s);
case Number number -> number(key, number);
case Boolean b -> bool(key, b);
case List<?> list -> array(key, list);
case JsonArray jsonArray -> array(key, jsonArray);
case JsonObject jsonObject -> object(key, jsonObject);
case null -> nullKey(key);
default -> {
}
}

return this;
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/me/ailama/handler/annotations/Parameter.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package me.ailama.handler.annotations;

import java.util.LinkedHashMap;

public @interface Parameter {
String name();
String Type();
Expand Down
15 changes: 0 additions & 15 deletions src/main/java/me/ailama/handler/annotations/ResponseFormatter.java

This file was deleted.

2 changes: 1 addition & 1 deletion src/main/java/me/ailama/handler/annotations/Tool.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@

boolean rawResponse() default false;

ResponseFormatter responseFormatter() default @ResponseFormatter(responseOrder = {}, responseVariables = {}, preFormattedResponse = "", isPreFormatted = false, isResponseOrder = false);
boolean responseFormatter() default false;
}
38 changes: 30 additions & 8 deletions src/main/java/me/ailama/handler/commandhandler/OllamaManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

Expand Down Expand Up @@ -146,11 +147,17 @@ public JsonArray getFinalJson() {
object.add("required_parameters",requiredParameters);
}

// response formatter
if(toolAnnotation.responseFormatter()) {

object.add("response_formatter","({response})");

}

// Add the tool object to the array
toolJsonObjects.add(object);
});


return toolJsonArray.objects(toolJsonObjects);
}

Expand Down Expand Up @@ -359,9 +366,21 @@ public Assistant getTooledAssistant(String modelOption, String userID, List<Docu
"argument_name": "value",
...
},
"response": [
"paragraph",
"paragraph",
...
],
"reason": "detailed_reason_for_using_tool",
"match_percentage": Number
}
A Response Formatter may be provided for the tool, its used for formatting the response of the tool,
the response formatter will contain of response variables, return a response like :-
"response": [
".. text .. ({response_variable}) ...",
...
]
There are some rules when using a tool :-
- The response must have tooled true, which means you are using a tool to answer the user's query.
Expand All @@ -373,16 +392,22 @@ public Assistant getTooledAssistant(String modelOption, String userID, List<Docu
- the tools description is as specific as possible, so don't assume that the tool can be used for anything else.
- if the tool description does not specify the user's needs then don't respond using a tool.
- you must provide parameters that are defined in the required parameters list.
- you would be provided with a user id, you can only use it for passing it to parameter as a value.
There are some rules for parameters of the tools :-
- the parameter description is as specific as possible, so don't assume that the argument can be used for anything else.
- the parameter name must be same as the one provided in the tools list.
- Respect the order of parameters.
- don't create any new parameter that are not defined in the tools parameters list.
A NotNull argument does not mean that argument is required, it means that the argument cannot be a `null` value.
if you break any of the rules you will be considered unhelpful
There are some rules for the response array if response_formatter is not null:-
- there must be at least 1 paragraph in the response array.
- a paragraph must not exceed 50 words.
- after each paragraph there must be a \\n character
when a tool provides you with a response formatter, you must use it to format the response of the tool like :-
user: "what is the time?"
response: "The time is ({response})"
if a tool does not match the users requirements then respond using the following schema
Expand All @@ -396,10 +421,7 @@ public Assistant getTooledAssistant(String modelOption, String userID, List<Docu
"rule": "which_rule_used_to_not_use_tool"
}
there are also some rules for the no tool schema, and those are :-
- there must be at least 1 paragraph in the response array.
- a paragraph must not exceed 50 words.
- after each paragraph there must be a \\n character
if you break any of the rules you will be considered unhelpful
the available tools are listed below in json format :-
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/me/ailama/handler/models/Tool.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import java.util.HashMap;
import java.util.LinkedHashMap;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Tool {

public boolean tooled;
public boolean rawResponse;
public String name;

public HashMap<String, Object> parameters;
public LinkedHashMap<String, Object> parameters;

public String[] response;
}
11 changes: 10 additions & 1 deletion src/main/java/me/ailama/tools/ApiTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.google.gson.JsonParser;
import me.ailama.handler.annotations.Parameter;
import me.ailama.handler.annotations.Tool;
import me.ailama.handler.commandhandler.OllamaManager;
import me.ailama.main.Main;
import net.dv8tion.jda.api.utils.data.DataObject;
import okhttp3.*;
Expand All @@ -19,7 +20,7 @@ public class ApiTools {
@Parameter(name = "amount", Type = "double", description = "Amount to convert"),
@Parameter(name = "currency1", Type = "string", description = "Currency to convert from, Like INR"),
@Parameter(name = "currency2", Type = "string", description = "Currency to convert to, Like USD")
})
}, responseFormatter = true)
public String currencyRate(Double amount, String currency1, String currency2) {
final double finalRate = Double.parseDouble(getRates(currency1.toLowerCase(),currency2.toLowerCase()));
final double conv = finalRate * amount;
Expand Down Expand Up @@ -101,6 +102,14 @@ public String callGetApi(String rawResponse) {
}
}

@Tool(name = "ai", description = "Simple AI to respond to messages", parameters = {
@Parameter(name = "message", Type = "string", description = "Message to respond to"),
@Parameter(name = "user_id", Type = "string", description = "User ID")
})
public String ai(String message, String userId) {
return OllamaManager.getInstance().createAssistant(null, userId).chat(userId, message);
}

public static boolean isJSONValid(String jsonInString ) {
try {
final ObjectMapper mapper = new ObjectMapper();
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/me/ailama/tools/MathTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

public class MathTools {

@Tool(name = "basicMathOperations", description = "only does Addition (+), Subtraction (-), Multiplication (*), Division (/), Modulus (%), Power (^)", parameters = {
@Tool(name = "basicMathOperations", description = "only does Addition, Subtraction, Multiplication, Division, Modulus, Power", parameters = {
@Parameter(name = "a", Type = "number"),
@Parameter(name = "b", Type = "number"),
@Parameter(name = "operation_symbol", Type = "string")
})
@Parameter(name = "operation_symbol", Type = "STRING{+,-,*,/,%,^}")
}, responseFormatter = true)
public String basicMathOperations(Number a, Number b, String operation) {
return switch (operation) {
case "+" -> add(a, b);
Expand Down Expand Up @@ -46,10 +46,10 @@ public String power(Number a, Number b) {
return String.valueOf(Math.pow(a.doubleValue(), b.doubleValue()));
}

@Tool(name = "squareOrCube", description = "Square or cube of a number, symbols are square_root and cube_root", parameters = {
@Tool(name = "squareOrCube", description = "Square or cube root of a number", parameters = {
@Parameter(name = "a", Type = "number"),
@Parameter(name = "operation_symbol", Type = "string")
})
@Parameter(name = "operation_symbol", Type = "STRING{square_root,cube_root}")
}, responseFormatter = true)
public String squareOrCube(Number a, String operation) {
return switch (operation) {
case "square_root" -> sqrt(a);
Expand Down
16 changes: 15 additions & 1 deletion src/main/java/me/ailama/tools/UtilityTools.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package me.ailama.tools;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import me.ailama.handler.annotations.Parameter;
import me.ailama.handler.annotations.Tool;
import me.ailama.handler.commandhandler.OllamaManager;
Expand All @@ -22,6 +26,16 @@ public boolean isValidURL(String url) {

@Tool(name = "toolsJson", description = "Get all the tools available to use")
public String toolsJson() {
return OllamaManager.getInstance().getFinalJson().build();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonElement jsonElement = JsonParser.parseString(OllamaManager.getInstance().getFinalJson().build());

return gson.toJson(jsonElement);
}

@Tool(name = "testTool", description = "Test the tool", parameters = {
@Parameter(name = "fruitName", Type = "string")
}, responseFormatter = true)
public String testTool(String resp) {
return resp;
}
}

0 comments on commit cf33c4d

Please sign in to comment.