Skip to content

Commit

Permalink
New System Prompt, improved math tool json by combining similar tools…
Browse files Browse the repository at this point in the history
… into one schema
  • Loading branch information
ZeyoYT committed May 11, 2024
1 parent 4d05868 commit d7a8542
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 129 deletions.
13 changes: 13 additions & 0 deletions .idea/material_theme_project_new.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ dependencies {
implementation group: 'io.github.cdimascio', name: 'java-dotenv', version: '5.2.2'
implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.5.6'
implementation group: 'dev.langchain4j', name: 'langchain4j-ollama', version: '0.30.0'
implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.12.0'
implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '5.0.0-alpha.14'
implementation group: 'joda-time', name: 'joda-time', version: '2.12.7'
implementation group: 'org.jsoup', name: 'jsoup', version: '1.17.2'

implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.0'

implementation 'dev.langchain4j:langchain4j-easy-rag:0.30.0'

Expand Down
7 changes: 5 additions & 2 deletions src/main/java/me/ailama/commands/AiCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ public void handleCommand(SlashCommandInteractionEvent event) {
getTooledAssistant(modelOption)
.answer(queryOption);

System.out.println(response);

ObjectMapper mapper = new ObjectMapper();

String temp = Pattern.compile("(?<=\":\").*(?=\")").matcher(response).replaceAll(x -> x.group().replace("\"", "_QUOTE_") );
Expand All @@ -112,7 +114,7 @@ public void handleCommand(SlashCommandInteractionEvent event) {
Tool tooled = mapper.readValue(temp, Tool.class);

if(!tooled.tooled) {
response = String.join("\n", tooled.response);
response = String.join("\n\n", tooled.response);
}
else
{
Expand Down Expand Up @@ -152,7 +154,8 @@ public void sendMessage(SlashCommandInteractionEvent event, String response) {
{
event.getHook().sendMessage(response).queue();
}
}

System.out.println(AiLama.getInstance().getElapsedTime());
}

}
209 changes: 122 additions & 87 deletions src/main/java/me/ailama/handler/commandhandler/OllamaManager.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package me.ailama.handler.commandhandler;

import com.fasterxml.jackson.databind.util.JSONPObject;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
Expand All @@ -16,7 +15,6 @@
import me.ailama.config.Config;
import me.ailama.handler.JsonBuilder.JsonArray;
import me.ailama.handler.JsonBuilder.JsonObject;
import me.ailama.handler.annotations.ResponseFormatter;
import me.ailama.handler.annotations.Tool;
import me.ailama.handler.interfaces.Assistant;
import me.ailama.main.AiLama;
Expand All @@ -25,7 +23,6 @@
import me.ailama.tools.MathTools;
import me.ailama.tools.TimeTools;
import me.ailama.tools.UtilityTools;
import org.apache.commons.lang3.StringEscapeUtils;
import org.jetbrains.annotations.NotNull;
import org.jsoup.Jsoup;

Expand Down Expand Up @@ -127,35 +124,31 @@ public JsonArray getFinalJson() {
argument.add("name",toolAnnotation.arguments()[i].name())
.add("type",toolAnnotation.arguments()[i].Type());

if(toolAnnotation.arguments()[i].required() || toolAnnotation.arguments()[i].noNull()) {
if(toolAnnotation.arguments()[i].description() != null && !toolAnnotation.arguments()[i].description().isEmpty()) {
argument.add("description",toolAnnotation.arguments()[i].description());
}

StringBuilder description = getStringBuilder(toolAnnotation, i);
if(toolAnnotation.arguments()[i].required()) {
argument.add("required",true);
}
else
{
argument.add("required",false);
}

argument.add("description",description.toString().trim());
if(toolAnnotation.arguments()[i].noNull()) {
argument.add("no_null",true);
}
else
{
argument.add("no_null",false);
}

argumentJsonObjects.add(argument);
}

arguments.objects(argumentJsonObjects);
object.add("arguments",arguments);

JsonObject responseFormatterObject = new JsonObject();

// add response formatter
ResponseFormatter responseFormatter = toolAnnotation.responseFormatter();

responseFormatterObject.add("response_order",responseFormatter.responseOrder());
responseFormatterObject.add("response_variables",responseFormatter.responseVariables());

if(responseFormatter.isPreFormatted()) {
responseFormatterObject.add("pre_formatted_response",responseFormatter.preFormattedResponse());
}
else {
responseFormatterObject.add("pre_formatted_response","");
}

object.add("response_formatter",responseFormatterObject);
}

// Add the tool object to the array
Expand Down Expand Up @@ -251,77 +244,115 @@ public Assistant getTooledAssistant(String modelOption) {

assistant = createAssistantX(modelOption)
.systemMessageProvider(x ->
// String.format("""
// You are a helpful AI assistant, you have a score, which can either be good or bad,
// you need to maintain a good score to be helpful, if you don't maintain a good score then you will be considered unhelpful.
//
// you will try to answer the users need as best as you can and only in JSON format, else you will be given a bad score.
//
// any of the tools description listed below match the specific needs of the query then use the tool to answer the query,
// the tools description is as specific as possible, so don't assume that the tool can be used for anything else.
//
// finally if a tool is matched then give response using following schema:
//
// {
// "tooled": true,
// "name": "tool_name",
// "arguments": {
// "argument_name": "value",
// ...
// },
// "reason": "detailed_reason_for_using_tool",
// "match_percentage": Number
// }
//
// the tool_name is the name of the tool that you are using, the arguments are the arguments that you are passing to the tool.
//
// following are the rules for tools:
// if the tool description does not specify the user's needs then don't respond using a tool else you will be given a bad score.
// if you don't pass the required arguments to the tool then you will be given a bad score.
// if you pass a null value to a argument that specified NOT_NULL in its description then you will be given a bad score.
// if you don't respect the arguments data type and description, you will be given a bad score.
// if the tool has response_formatter then use it, else you will be given a bad score.
// if the tool's response_formatter has a pre_formatted_response then use it, else you will be given a bad score.
// don't add any other variables not defined in the response_variables, else you will be given a bad score.
// don't use the tool if user asked specifically for not using tools, else you will be given a bad score.
// the reason should not exceed 200 characters, and if it does, you will be given a bad score.
//
// and if you don't follow the schema, you will be given a bad score, but if you follow the schema, you will be given a good score.
//
// if you don't find a tool that match the requirements of the user then respond to the user normally,
// and also make the response to be encoded for the JSON format or you will be given a bad score,
// and use the following schema:
//
// {
// "tooled": false,
// "response": [
// "paragraph",
// "paragraph",
// ...
// ]
// }
//
// in the above schema, the response is an array of paragraphs that you want to respond to the user, minimum of 1 paragraph.
// each new paragraph should be a new string in the array.
// between each paragraph, there should be '\\n'.
//
// %s
// """,tools)

//todo improve this prompt

String.format("""
You are a helpful AI assistant, you have a score, which can either be good or bad,
you need to maintain a good score to be helpful, if you don't maintain a good score then you will be considered unhelpful.
you will try to answer the users need as best as you can and only in JSON format, else you will be given a bad score.
any of the tools description listed below match the specific needs of the query then use the tool to answer the query,
the tools description is as specific as possible, so don't assume that the tool can be used for anything else.
finally if a tool is matched then give response using following schema:
{
"tooled": true,
"name": "tool_name",
"arguments": {
"argument_name": "value",
...
},
"response_formatter": "response_format",
"reason": "detailed_reason_for_using_tool",
"match_percentage": Number
}
the tool_name is the name of the tool that you are using, the arguments are the arguments that you are passing to the tool.
the response_formatter is the format of the response, here add your response and add '({n})' where the response from the tool will be placed.
the response_formatter can contains both, the before or after response text, like "The answer for 2 + 2 is ({response_variable})".
following are the rules for tools:
if the tool description does not specify the user's needs then don't respond using a tool else you will be given a bad score.
if you don't pass the required arguments to the tool then you will be given a bad score.
if you pass a null value to a argument that specified NOT_NULL in its description then you will be given a bad score.
if you don't respect the arguments data type, you will be given a bad score.
if you don't respect the arguments description, you will be given a bad score.
if the match_percentage is more than 85 then use the tool, else you will be given a bad score.
if the tool has response_formatter then use it, else you will be given a bad score.
if the tool's response_formatter has a pre_formatted_response then use it, else you will be given a bad score.
the tool's response_formatter has a response_order, this is the order of the response variables, and you must respect it, else you will be given a bad score.
the tool's response_formatter has a response_variables, this is the variables that you will use in the response_formatter, and you must respect it, else you will be given a bad score.
the tool's response_formatter must not exceed 200 characters, and if it does, you will be given a bad score.
the tool's response_variables contains the only variables that you can use in the response_formatter, and you must respect it, else you will be given a bad score.
don't add any other variables not defined in the response_variables, else you will be given a bad score.
don't use the tool if user asked specifically for not using tools, else you will be given a bad score.
the reason should not exceed 200 characters, and if it does, you will be given a bad score.
and if you don't follow the schema, you will be given a bad score, but if you follow the schema, you will be given a good score.
if you don't find a tool that match the requirements of the user then respond to the user normally,
and also make the response to be encoded for the JSON format or you will be given a bad score,
and use the following schema:
{
"tooled": false,
"response": [
"paragraph",
"paragraph",
...
]
}
in the above schema, the response is an array of paragraphs that you want to respond to the user, minimum of 1 paragraph.
each new paragraph should be a new string in the array.
between each paragraph, there should be '\\n'.
%s
""",tools)
You are a helpful AI Assistant, you will try to answer the user's needs as best as you can and only in JSON format.
you have access to a set of tools that may help you give accurate responses to the user.
if you find a tool that matches the user's query then use the tool to answer the query.
If a tool is matched then give response using the following schema:
{
"tooled": true,
"name": "tool_name",
"arguments": {
"argument_name": "value",
...
},
"reason": "detailed_reason_for_using_tool",
"match_percentage": Number
}
the tool_name is the name of the tool that you are using, the arguments are the arguments that you are passing to the tool.
the tool's description is as specific as possible, so don't assume that the tool can be used for anything else.
if you don't find a tool that matches the requirements of the user then respond to the user using the following schema:
{
"tooled": false,
"response": [
"paragraph",
"paragraph",
...
]
}
each paragraph must be 200 characters or less
in the above schema, the response is an array of paragraphs that you want to respond to the user, minimum of 1 paragraph.
each new paragraph should be a new string in the array.
%s
""", tools)
)
.build();

System.out.println(tools);

return assistant;
}

// write a hello world function

// Returns a custom Assistant that uses the provided model, allowing for more customization
public AiServices<Assistant> createAssistantX(String modelName) {

Expand All @@ -338,6 +369,10 @@ public AiServices<Assistant> createAssistantX(String modelName) {
.chatLanguageModel(ollama);
}

// Hello World



// Just a Simple Response
public Assistant createAssistant(String modelName) {

Expand Down
Loading

0 comments on commit d7a8542

Please sign in to comment.