From b457b0e24597b5f993d4ca5f81b2999d58f70f11 Mon Sep 17 00:00:00 2001 From: grog Date: Thu, 16 Nov 2023 12:07:09 -0800 Subject: [PATCH] Novel AI service (basic tts only) --- .../java/org/myrobotlab/service/NovelAI.java | 110 ++++++++++++++++++ .../service/config/NovelAIConfig.java | 18 +++ .../myrobotlab/service/meta/NovelAIMeta.java | 33 ++++++ src/main/resources/resource/NovelAI.png | Bin 0 -> 8982 bytes .../WebGui/app/service/js/NovelAIGui.js | 58 +++++++++ .../WebGui/app/service/views/NovelAIGui.html | 67 +++++++++++ 6 files changed, 286 insertions(+) create mode 100644 src/main/java/org/myrobotlab/service/NovelAI.java create mode 100644 src/main/java/org/myrobotlab/service/config/NovelAIConfig.java create mode 100644 src/main/java/org/myrobotlab/service/meta/NovelAIMeta.java create mode 100644 src/main/resources/resource/NovelAI.png create mode 100644 src/main/resources/resource/WebGui/app/service/js/NovelAIGui.js create mode 100644 src/main/resources/resource/WebGui/app/service/views/NovelAIGui.html diff --git a/src/main/java/org/myrobotlab/service/NovelAI.java b/src/main/java/org/myrobotlab/service/NovelAI.java new file mode 100644 index 0000000000..e7581d980a --- /dev/null +++ b/src/main/java/org/myrobotlab/service/NovelAI.java @@ -0,0 +1,110 @@ +package org.myrobotlab.service; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +import org.myrobotlab.io.FileIO; +import org.myrobotlab.logging.Level; +import org.myrobotlab.logging.LoggerFactory; +import org.myrobotlab.logging.LoggingFactory; +import org.myrobotlab.service.abstracts.AbstractSpeechSynthesis; +import org.myrobotlab.service.config.NovelAIConfig; +import org.myrobotlab.service.data.AudioData; +import org.slf4j.Logger; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + +public class NovelAI extends AbstractSpeechSynthesis { + + private static final long serialVersionUID = 1L; + + public final static Logger log = LoggerFactory.getLogger(NovelAI.class); + + private transient OkHttpClient client = new OkHttpClient(); + + public NovelAI(String n, String id) { + super(n, id); + client = new OkHttpClient(); + } + + /** + * The methods apply and getConfig can be used, if more complex configuration + * handling is needed. By default, the framework takes care of most of it, + * including subscription handling. + * + *
+  @Override
+  public ServiceConfig apply(ServiceConfig c) {
+    super.apply(c)
+    return c;
+  }
+  
+  @Override
+  public ServiceConfig getConfig() {
+    super.getConfig()
+    return config;
+  }
+   * 
+ **/ + + public static void main(String[] args) { + try { + + LoggingFactory.init(Level.INFO); + + Runtime.start("novelai", "NovelAI"); + Runtime.start("webgui", "WebGui"); + + } catch (Exception e) { + log.error("main threw", e); + } + } + + @Override + public AudioData generateAudioData(AudioData audioData, String toSpeak) throws Exception { + + String baseUrl = "https://api.novelai.net/ai/generate-voice?voice=-1&seed=" + config.voice + "&opus=false&version=v2&text="; + String encodedText = URLEncoder.encode(toSpeak, StandardCharsets.UTF_8.toString()); + String url = baseUrl + encodedText; + + Request request = new Request.Builder().url(url).build(); + + try { + Response response = client.newCall(request).execute(); + + if (response.isSuccessful()) { + ResponseBody responseBody = response.body(); + if (responseBody != null) { + byte[] bytes = responseBody.bytes(); + FileIO.toFile(audioData.getFileName(), bytes); + } + } else { + error("request failed with code: " + response.code()); + } + } catch (Exception e) { + error(e); + } + return audioData; + } + + @Override + public void loadVoices() throws Exception { + addVoice("Aini", "female", "en", "Aini"); + addVoice("Ligeia", "female", "en", "Ligeia"); + addVoice("Orea", "female", "en", "Orea"); + addVoice("Claea", "female", "en", "Claea"); + addVoice("Lim", "female", "en", "Lim"); + addVoice("Aurae", "female", "en", "Aurae"); + addVoice("Naia", "female", "en", "Naia"); + + addVoice("Aulon", "male", "en", "Aulon"); + addVoice("Elei", "male", "en", "Elei"); + addVoice("Ogma", "male", "en", "Ogma"); + addVoice("Raid", "male", "en", "Raid"); + addVoice("Pega", "male", "en", "Pega"); + addVoice("Lam", "male", "en", "Lam"); + } +} diff --git a/src/main/java/org/myrobotlab/service/config/NovelAIConfig.java b/src/main/java/org/myrobotlab/service/config/NovelAIConfig.java new file mode 100644 index 0000000000..d881e47714 --- /dev/null +++ b/src/main/java/org/myrobotlab/service/config/NovelAIConfig.java @@ -0,0 +1,18 @@ +package org.myrobotlab.service.config; + +import org.myrobotlab.framework.Plan; + +public class NovelAIConfig extends SpeechSynthesisConfig { + + + public NovelAIConfig() { + voice = "Aini"; + } + + @Override + public Plan getDefault(Plan plan, String name) { + super.getDefault(plan, name); + return plan; + } + +} diff --git a/src/main/java/org/myrobotlab/service/meta/NovelAIMeta.java b/src/main/java/org/myrobotlab/service/meta/NovelAIMeta.java new file mode 100644 index 0000000000..f94e15d086 --- /dev/null +++ b/src/main/java/org/myrobotlab/service/meta/NovelAIMeta.java @@ -0,0 +1,33 @@ +package org.myrobotlab.service.meta; + +import org.myrobotlab.logging.LoggerFactory; +import org.myrobotlab.service.meta.abstracts.MetaData; +import org.slf4j.Logger; + +public class NovelAIMeta extends MetaData { + private static final long serialVersionUID = 1L; + public final static Logger log = LoggerFactory.getLogger(NovelAIMeta.class); + + /** + * This class is contains all the meta data details of a service. It's peers, + * dependencies, and all other meta data related to the service. + * + */ + public NovelAIMeta() { + + // add a cool description + addDescription("service to interface with NovelAI"); + + // false will prevent it being seen in the ui + setAvailable(true); + + // add it to one or many categories + addCategory("speech"); + + // add a sponsor to this service + // the person who will do maintenance + // setSponsor("GroG"); + + } + +} diff --git a/src/main/resources/resource/NovelAI.png b/src/main/resources/resource/NovelAI.png new file mode 100644 index 0000000000000000000000000000000000000000..d82b4fdd81ef86272f43a173be23d2fda40f66b4 GIT binary patch literal 8982 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/resource/WebGui/app/service/js/NovelAIGui.js b/src/main/resources/resource/WebGui/app/service/js/NovelAIGui.js new file mode 100644 index 0000000000..bdd8a1714c --- /dev/null +++ b/src/main/resources/resource/WebGui/app/service/js/NovelAIGui.js @@ -0,0 +1,58 @@ +angular.module('mrlapp.service.NovelAIGui', []).controller('NovelAIGuiCtrl', ['peer', '$scope', 'mrl', '$uibModal', function(peer, $scope, mrl, $uibModal) { + console.info('NovelAIGuiCtrl') + var _self = this + var msg = this.msg + $scope.autoClear = true + $scope.textArea = false + $scope.spoken = '' + + // new selected voice "container" - since it comes from a map next leaves are + // key & value ... value contains the entire voice selected + $scope.newVoice = { + selected: null + } + + this.updateState = function(service) { + $scope.service = service + if (service.voice) { + $scope.newVoice.selected = { + 'key': service.voice.name, + 'value': service.voice + } + } + $scope.$apply() + } + + this.onMsg = function(inMsg) { + let data = inMsg.data[0] + switch (inMsg.method) { + case 'onState': + _self.updateState(data) + break + case 'onStartSpeaking': + $scope.spoken = data + $scope.$apply() + break + default: + console.error("ERROR - unhandled method " + $scope.name + " " + inMsg.method) + break + } + } + + $scope.speak = function(text) { + msg.send("speak", text) + + if ($scope.autoClear) { + $scope.text = '' + } + } + + $scope.setVoice = function(text) { + console.log($scope.service.voice.name) + msg.send("setVoice", text.name) + } + + msg.subscribe('publishStartSpeaking') + msg.subscribe(this) +} +]) diff --git a/src/main/resources/resource/WebGui/app/service/views/NovelAIGui.html b/src/main/resources/resource/WebGui/app/service/views/NovelAIGui.html new file mode 100644 index 0000000000..7e5fe0e471 --- /dev/null +++ b/src/main/resources/resource/WebGui/app/service/views/NovelAIGui.html @@ -0,0 +1,67 @@ +
+
+

{{spoken}}

+
+
+
+
+ + + + + + + + +
+ + NovelAI requires AWS Keys + + mute + +
+ + + +
+
+ +