Skip to content

Commit

Permalink
Messages under five characters are not translated, updated sys-prompt…
Browse files Browse the repository at this point in the history
…, edited messages, updated readme and added basic information command
  • Loading branch information
Kim committed Nov 17, 2024
1 parent 6c7e776 commit 49339fe
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 46 deletions.
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ From now on with minecraft 1.20.6 minecraft/spigot etc. use Java 21!


## Features
- Real-time translation of player messages.
- Configurable translation settings.
- Real-time translation of all player messages (longer than five characters).
- Configurable settings.
- Easy integration with Ollama API.
- Support for local hosting of translation models.
- (ONLY) Support for local hosting of translation models (for now).
- Quick setup and minimal configuration.


Expand Down Expand Up @@ -47,7 +47,7 @@ ollama:

cooldown:
enabled: true
milliseconds: 2000
milliseconds: 1000
message: §cPlease wait...

translation:
Expand All @@ -59,16 +59,18 @@ translation:
```
## Usage
0. Start ollama and download the model of choice
1. Install the plugin in your Spigot Minecraft server's plugins directory.
2. Configure the `options.yml` file according to your preferences.
3. Restart/Reload the server to apply the changes.
4. Players' messages will now be automatically translated as per the configured settings.


## Note
The bigger the model the better the outcome, mistral showed to be very good but sometimes it is acting weird, llama3:8b (instruct-fp16) was amazing.
Please note that LLM/SLM require (a significant amount of) memory, with a minimum of 5-8 GB for small and 15-30 GB for middle-sized models or even more.
You don't need a 30gb (file size) model if llama3:8b for example produces a good outcome then it is alright, I tested mistral and llama3 so test it yourself.
- ALL messages (longer than five characters) are translated, also native ones, so this plugin is really only for servers with a mixed-language player-base.
- The bigger the model the better the outcome, mistral showed to be very good but sometimes it is acting weird, llama3:8b (instruct-fp16) was very good but still not like a native speaker.
- Please note that LLM/SLM require (a significant amount of) memory, with a minimum of 5-8 GB for small and 15-30 GB for middle-sized models or even more.
- You don't need a 30gb (file size) model if llama3:8b for example produces a good outcome then it is alright, I tested mistral and llama3 so test it yourself.


## Disclaimer
Expand Down
89 changes: 57 additions & 32 deletions src/main/java/de/liebki/Start.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
package de.liebki;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

import de.liebki.utils.Config;
import de.liebki.utils.InfoCommand;
import de.liebki.utils.MessageUtils;
import de.liebki.utils.Pair;
import io.github.amithkoujalgi.ollama4j.core.OllamaAPI;
import io.github.amithkoujalgi.ollama4j.core.models.OllamaResult;
import io.github.amithkoujalgi.ollama4j.core.utils.OptionsBuilder;
import io.github.amithkoujalgi.ollama4j.core.utils.PromptBuilder;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandExecutor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.plugin.java.JavaPlugin;

import io.github.amithkoujalgi.ollama4j.core.OllamaAPI;
import io.github.amithkoujalgi.ollama4j.core.models.OllamaResult;
import io.github.amithkoujalgi.ollama4j.core.utils.OptionsBuilder;
import io.github.amithkoujalgi.ollama4j.core.utils.PromptBuilder;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

public class Start extends JavaPlugin implements Listener {
public class Start extends JavaPlugin implements Listener, CommandExecutor {

private final String TRANSLATOR_PROMPT = "Translate the original user message you get from any language to %TARGETLANGUAGE% without commenting or mentioning the source of translation. You can correct grammatical errors but dont alter the text too much and dont tell if you changed it. Avoid speaking with the user besides the translation, as everything is for someone else and not you, you focus on translating.";
private final String PREFIX = "&f[&9OT&f]&r ";
private final String TRANSLATOR_PROMPT = "Translate the user message you get from it's language to %TARGETLANGUAGE% without commenting or mentioning the source of translation. You can correct grammatical errors but dont alter the text too much and dont tell if you changed it. Avoid speaking with the user besides the translation, as everything is for someone else and not you, you focus on translating. Just translate the message, no comment, no code, no formatting just the translation.";

private Config config;
private OllamaAPI ollamaAPI;
Expand All @@ -34,10 +40,21 @@ public void onPlayerChat(AsyncPlayerChatEvent event) {
String msgContent = event.getMessage();
UUID playerId = player.getUniqueId();

if(msgContent.length() < 5) {
String rawAnswerString = (String) config.get("translation.broadcastmessage");
rawAnswerString = rawAnswerString.replace("%TRANSLATION%", msgContent);

rawAnswerString = rawAnswerString.replace("%PLAYER%", player.getDisplayName());
Bukkit.broadcastMessage(MessageUtils.ColorConvert(rawAnswerString));

event.setCancelled(true);
return;
}

if ((Boolean) config.get("cooldown.enabled")) {
if (hasCooldown(playerId)) {
event.setCancelled(true);
player.sendMessage(cPlease wait..");
player.sendMessage(MessageUtils.ColorConvert(PREFIX + "&cPlease wait before chatting.."));
return;
}

Expand Down Expand Up @@ -73,7 +90,8 @@ public void onPlayerChat(AsyncPlayerChatEvent event) {
event.setCancelled(true);

if ((Boolean) config.get("translation.notify")) {
player.sendMessage((String) config.get("translation.cancelmessage"));
String message = (String) config.get("translation.cancelmessage");
player.sendMessage(MessageUtils.ColorConvert(PREFIX + message));
}
}
}
Expand All @@ -94,7 +112,7 @@ private void handleResponse(Pair<String, Player> response) {
rawAnswerString = rawAnswerString.replace("%TRANSLATION%", message);
rawAnswerString = rawAnswerString.replace("%PLAYER%", receiver.getDisplayName());

Bukkit.broadcastMessage(rawAnswerString);
Bukkit.broadcastMessage(MessageUtils.ColorConvert(rawAnswerString));
}

}
Expand All @@ -114,43 +132,50 @@ private void cleanExpiredCooldowns() {

@Override
public void onEnable() {
config = new Config("plugins/ollamatranslator", "options.yml", this);
File configFile = new File("plugins/ollamatranslator/options.yml");

if (!config.check("configexists")) {
if (!configFile.exists()) {
config = new Config("plugins/ollamatranslator", "options.yml", this);

config.set("donottouch.configexists", true);
if (!config.check("configexists")) {
config.set("donottouch.configexists", true);

config.set("ollama.secondstimeout", 20);
config.set("ollama.modelname", "mistral:instruct");
config.set("ollama.apiaddress", "http://localhost:11434/");
config.set("ollama.secondstimeout", 20);
config.set("ollama.modelname", "mistral:instruct");
config.set("ollama.apiaddress", "http://localhost:11434/");

config.set("cooldown.enabled", true);
config.set("cooldown.miliseconds", 1000);
config.set("cooldown.message", "§cPlease wait..");
config.set("cooldown.enabled", true);
config.set("cooldown.miliseconds", 1000);
config.set("cooldown.message", "&cPlease wait..");

config.set("translation.canceloriginalmessage", true);
config.set("translation.notify", true);
config.set("translation.cancelmessage", "§7Your message is in translation, please wait..");
config.set("translation.canceloriginalmessage", true);
config.set("translation.notify", true);
config.set("translation.cancelmessage", "&7Your message is going to be translated, please wait..");

config.set("translation.targetlanguage", "english");
config.set("translation.broadcastmessage", "§r%PLAYER% §r: §r§b%TRANSLATION%");
config.set("translation.targetlanguage", "english");
config.set("translation.broadcastmessage", "&r%PLAYER% &r: &r&b%TRANSLATION%");

config.saveConfig();
config.saveConfig();
}
} else {
config = new Config("plugins/ollamatranslator", "options.yml", this);
}

ollamaAPI = new OllamaAPI((String) config.get("ollama.apiaddress"));
ollamaAPI.setRequestTimeoutSeconds((Integer) config.get("ollama.secondstimeout"));

getServer().getPluginManager().registerEvents(this, this);
getServer().getScheduler().runTaskTimer(this, this::cleanExpiredCooldowns, 0, 20 * 60);
getServer().getScheduler().runTaskTimer(this, this::cleanExpiredCooldowns, 0, 20 * 5);

cooldown = (Integer) config.get("cooldown.miliseconds");
Bukkit.getConsoleSender().sendMessage("§4ollama-translator powering on");
Bukkit.getConsoleSender().sendMessage("§4OT: ollama-translator powering on");

this.getCommand("ollamatranslator").setExecutor(new InfoCommand());
}

@Override
public void onDisable() {
Bukkit.getConsoleSender().sendMessage(4ollama-translator powering off");
Bukkit.getConsoleSender().sendMessage(4OT: ollama-translator powering off");
}

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package de.liebki;

import java.io.File;
import java.io.IOException;
package de.liebki.utils;

import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;

import java.io.File;
import java.io.IOException;

public class Config<T> {

private File file;
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/de/liebki/utils/InfoCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package de.liebki.utils;

import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

public class InfoCommand implements CommandExecutor {

@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (sender instanceof Player) {
Player player = (Player) sender;
player.sendMessage(MessageUtils.ColorConvert("&4ollama-translator &f- &bThis plugin helps to translate all messages for all users!"));
}

return true;
}

}
10 changes: 10 additions & 0 deletions src/main/java/de/liebki/utils/MessageUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package de.liebki.utils;

public class MessageUtils {

public static String ColorConvert(String input) {
String output = input.replace("&", "§");
return output;
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package de.liebki;
package de.liebki.utils;

public class Pair<A, B> {

Expand Down
8 changes: 6 additions & 2 deletions src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
name: OllamaTranslator
main: de.liebki.Start
version: 1.0.0
version: 1.0.1
api-version: "1.16"
commands:
commands:
ollamatranslator:
description: Shows info message
usage: /<command>
aliases: [ot, translator]

0 comments on commit 49339fe

Please sign in to comment.