diff --git a/.gitignore b/.gitignore
index 10f25a5..3219e57 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,4 +42,32 @@ replay_pid*
# jar exception
!package/**/*.jar
-!sample_code/jars/**/*.jar
\ No newline at end of file
+!sample_code/jars/**/*.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/README.md b/README.md
index e33cd03..e444922 100644
--- a/README.md
+++ b/README.md
@@ -1,64 +1,88 @@
-# IntelliJava-OpenaiAPI
-*IntelliJava V0.6.0*
+
+
+
-IntelliJava is the ultimate tool for Java developers looking to integrate with the latest language models and deep learning frameworks. The library provides a simple and intuitive API with convenient methods for sending text input to models like GPT-3 and DALL·E, and receiving generated text or images in return. With just a few lines of code, you can easily access the power of cutting-edge AI models to enhance your projects.
+
-The supported models in this version:
-- OpenAI: Access GPT-3 to generate text and DALL·E to generate images. OpenAI is preferred when you want quality results without tuning.
-- Cohere.ai: generate text; Cohere allows you to generate your language model to suit your specific needs.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Intelligent Java
+Intelligent java (IntelliJava) is the ultimate tool to integrate with the latest language models and deep learning frameworks using java. The library provides an intuitive functions for sending input to models like ChatGPT and DALL·E, and receiving generated text, speech or images. With just a few lines of code, you can easily access the power of cutting-edge AI models to enhance your projects.
+
+The supported models:
+- **OpenAI**: Access ChatGPT, GPT3 to generate text and DALL·E to generate images. OpenAI is preferred for quality results without tuning.
+- **Cohere.ai**: Generate text; Cohere allows you to custom your language model to suit your specific needs.
+- **Google AI**: Generate audio from text; Access DeepMind’s speech models.
# How to use
-1. Import the core jar file to your project or add the maven package (check Integration section).
-2. Add gson dependency using maven or the jar file (check dependencies section).
-3. Call the ``RemoteLanguageModel`` for the language models and ``RemoateImageModel`` for image generation.
+
+1. Add the maven dependency or import the core jar file (check the Integration section).
+2. Add Gson dependency if using the jar file; otherwise, it's handled by maven or Gradle.
+3. Call the ``RemoteLanguageModel`` for the language models, ``RemoteImageModel`` for image generation, ``RemoteSpeechModel`` for text to speech models, and ``Chatbot`` for ChatGPT.
## Integration
-The package released to [Maven Central Repository](https://central.sonatype.dev/artifact/io.github.barqawiz/intellijava.core/0.6.0).
+The package released to Maven Central Repository:
Maven:
```xml
io.github.barqawiz
intellijava.core
- 0.6.0
+ 0.8.2
```
Gradle:
```
-implementation group: 'io.github.barqawiz', name: 'intellijava.core', version: '0.6.0'
+implementation 'io.github.barqawiz:intellijava.core:0.8.2'
```
Gradle(Kotlin):
```
-implementation("io.github.barqawiz:intellijava.core:0.6.0")
+implementation("io.github.barqawiz:intellijava.core:0.8.2")
```
Jar download:
-[intellijava.jar](https://repo1.maven.org/maven2/io/github/barqawiz/intellijava.core/0.6.0/intellijava.core-0.6.0.jar).
-
-For ready integration: try the sample_code.
+[intellijava.jar](https://repo1.maven.org/maven2/io/github/barqawiz/intellijava.core/0.8.2/intellijava.core-0.8.2.jar).
## Code Example
**Language model code** (2 steps):
```java
-// 1- initiate the remote language model
+// 1- initiate the remote language model
String apiKey = "";
RemoteLanguageModel langModel = new RemoteLanguageModel(apiKey, "openai");
// 2- call generateText with any command !
-LanguageModelInput langInput = new LanguageModelInput.Builder("return a java code that says hello world")
- .setModel("text-davinci-002").setTemperature(0.7f).setMaxTokens(50).build();
+LanguageModelInput langInput = new LanguageModelInput.Builder("Summarize the plot of the 'Inception' movie in two sentences")
+ .setModel("text-davinci-003").setTemperature(0.7f).setMaxTokens(50).build();
String resValue = langModel.generateText(langInput);
```
-Output:
-``` System.out.println("Hello, World!");```
+Output:```Inception follows Dom Cobb, a professional thief, who is offered a chance at redemption in exchange for planting an idea in a target's mind. He must navigate a dangerous landscape of dream-sharing technology and battle his inner demons in order to complete the mission and find his way back to reality.```
+
+
+
**Image generation code** (2 steps):
```java
-// 1- initiate the remote image model
-RemoateImageModel imageModel = new RemoateImageModel(apiKey, "openai");
+// 1- initiate the remote image model
+RemoteImageModel imageModel = new RemoteImageModel(apiKey, "openai");
// 2- call generateImages with any command !
ImageModelInput imageInput = new ImageModelInput.Builder("teddy writing a blog in times square")
@@ -68,41 +92,68 @@ List images = imageModel.generateImages(imageInput);
Output:
-For full example check the code inside sample_code project.
+
-## Third-party dependencies
-The only dependencies is **GSON**.
+**Text to speech code** (2 steps):
+```java
+// 1- initiate the remote speech model
+RemoteSpeechModel model = new RemoteSpeechModel(apiKey, SpeechModels.google);
-For Maven:
+// 2- call generateEnglishText with any text
+Text2SpeechInput input = new Text2SpeechInput.Builder("Hi, I am Intelligent Java.").build();
+byte[] decodedAudio = model.generateEnglishText(input);
```
-
- com.google.code.gson
- gson
- 2.8.9
-
+Output:
+```Java
+// save temporary audio file for testing
+AudioHelper.saveTempAudio(decodedAudio);
```
-For Gradle:
-```
-dependencies {
- implementation 'com.google.code.gson:gson:2.8.9'
-}
+
+
+**ChatGPT code**:
+```java
+// 1- initiate the chat model.
+Chatbot bot = new Chatbot(apiKey, SupportedChatModels.openai);
+
+// 2- prepare the chat history by calling addMessage.
+String mode = "You are a helpful astronomy assistant.";
+ChatModelInput input = new ChatGPTInput.Builder(mode)
+ .addUserMessage("what is the space between moon and earth").build();
+
+// 3- call chat!
+List resValues = bot.chat(input);
```
+Output:``` The average distance between the Moon and the Earth is about 238,855 miles (384,400 kilometers). ```
+
+
+
+For full examples and ready integration try [the sample_code](https://github.com/Barqawiz/IntelliJava/tree/main/sample_code).
+
+## Third-party dependencies
+The only dependencies is **GSON**.
+*Required to add manually when using IntelliJava jar. However, if you imported this repo through Maven, it will handle the dependencies.*
For jar download:
-[gson download repo](https://search.maven.org/artifact/com.google.code.gson/gson/2.8.9/jar)
+[gson download repo](https://search.maven.org/artifact/com.google.code.gson/gson/2.10.1/jar)
+## Documentation
+- [Go to Java docs](https://intelligentnode.github.io/IntelliJava/javadocs/)
+- [Tutorial article](https://albarqawi.medium.com/intelligent-java-a-gateway-to-the-latest-ai-models-c08c09513672)
# Roadmap
Call for contributors:
-- [x] Add support to OpenAI Completion API.
+- [x] Add support to OpenAI Completion.
- [x] Add support to OpenAI DALL·E 2.
- [ ] Add support to other OpenAI functions.
- [x] Add support to cohere generate API.
- [ ] Add support to Google language models.
+- [x] Add support to Google speech models.
- [ ] Add support to Amazon language models.
+- [ ] Add support to Azure nlp models.
- [ ] Add support to Midjourney image generation.
-
+- [ ] Add support to WuDao 2.0 model.
+- [ ] Add support to Stable Diffusion.
# License
Apache License
@@ -120,5 +171,3 @@ Copyright 2023 Github.com/Barqawiz/IntelliJava
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-
-
diff --git a/core/com.intellijava.core/pom.xml b/core/com.intellijava.core/pom.xml
index 4ae96f6..039ebd2 100644
--- a/core/com.intellijava.core/pom.xml
+++ b/core/com.intellijava.core/pom.xml
@@ -6,7 +6,7 @@
io.github.barqawiz
intellijava.core
- 0.6.0
+ 0.8.2
Intellijava
IntelliJava allows java developers to easily integrate with the latest language models, image generation, and deep learning frameworks.
@@ -18,7 +18,7 @@
http://www.apache.org/licenses/LICENSE-2.0.txt
-
+
Ahmad Albarqawi
@@ -27,13 +27,13 @@
http://www.ahmadai.com
-
+
scm:git:git://github.com/Barqawiz/IntelliJava.git
scm:git:ssh://github.com:Barqawiz/IntelliJava.git
https://github.com/Barqawiz/IntelliJava
-
+
UTF-8
11
@@ -66,7 +66,7 @@
com.google.code.gson
gson
- 2.8.9
+ 2.10.1
@@ -112,10 +112,10 @@
maven-project-info-reports-plugin
3.0.0
-
+
-
+
@@ -152,7 +152,7 @@
attach-sources
-
+
jar-no-fork
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoateImageModel.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoteImageModel.java
similarity index 61%
rename from core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoateImageModel.java
rename to core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoteImageModel.java
index 8895d8b..24430ed 100644
--- a/core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoateImageModel.java
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoteImageModel.java
@@ -23,6 +23,7 @@
import com.intellijava.core.model.OpenaiImageResponse;
import com.intellijava.core.model.OpenaiImageResponse.Data;
+import com.intellijava.core.model.SupportedImageModels;
import com.intellijava.core.model.input.ImageModelInput;
import com.intellijava.core.wrappers.OpenAIWrapper;
@@ -30,37 +31,89 @@
*
* The RemoteImageModel class is used to generate images from text descriptions using an API key.
* It currently supports OpenAI only.
+ *
* The class uses the OpenAIWrapper to generate the images and returns a list of URLs for the generated images.
*
* @author github.com/Barqawiz
*/
-public class RemoateImageModel {
+public class RemoteImageModel {
- private String keyType;
+ private SupportedImageModels keyType;
private OpenAIWrapper openaiWrapper;
/**
*
* Constructor for creating a new RemoteImageModel object.
*
- * Creates an instance of the class and sets up the API key and the key type.
+ * Creates an instance of the class and set the API key value and type.
*
* @param keyValue the API key.
- * @param keyType support openai only.
+ * @param keyTypeString support openai only.
*
* @throws IllegalArgumentException if the keyType passed is not "openai".
*
*/
- public RemoateImageModel(String keyValue, String keyType) {
+ public RemoteImageModel(String keyValue, String keyTypeString) {
- if (keyType.isEmpty() || keyType.equals("openai")) {
- this.keyType = "openai";
- openaiWrapper = new OpenAIWrapper(keyValue);
+ if (keyTypeString.isEmpty()) {
+ keyTypeString = SupportedImageModels.openai.toString();
+ }
+
+ List supportedModels = this.getSupportedModels();
+
+ if (supportedModels.contains(keyTypeString)) {
+ this.initiate(keyValue, SupportedImageModels.valueOf(keyTypeString));
} else {
- throw new IllegalArgumentException("This version support openai keyType only");
+ String models = String.join(" - ", supportedModels);
+ throw new IllegalArgumentException("The received keyValue not supported. Send any model from: " + models);
}
}
+ /**
+ *
+ * Constructor for creating a new RemoteImageModel object.
+ *
+ * Creates an instance of the class and set the API key value and type.
+ *
+ * @param keyValue the API key.
+ * @param keyType the model type from SupportedImageModels enum.
+ */
+ public RemoteImageModel(String keyValue, SupportedImageModels keyType) {
+ initiate(keyValue, keyType);
+ }
+
+ /**
+ * Get the supported models names as array of string
+ *
+ * @return supportedModels
+ */
+ public List getSupportedModels() {
+ SupportedImageModels[] values = SupportedImageModels.values();
+ List enumValues = new ArrayList<>();
+
+ for (int i = 0; i < values.length; i++) {
+ enumValues.add(values[i].name());
+ }
+
+ return enumValues;
+ }
+
+ /**
+ * Common function to initiate the class from any constructor.
+ *
+ * @param keyValue the API key.
+ * @param keyType enum of supported models.
+ */
+ private void initiate(String keyValue, SupportedImageModels keyType) {
+ // set the model type
+ this.keyType = keyType;
+
+ // generate the related model
+ if (keyType.equals(SupportedImageModels.openai)) {
+ this.openaiWrapper = new OpenAIWrapper(keyValue);
+ }
+ }
+
/**
*
* Generates images from a given text description.
@@ -71,7 +124,7 @@ public RemoateImageModel(String keyValue, String keyType) {
*/
public List generateImages(ImageModelInput imageInput) throws IOException {
- if (this.keyType.equals("openai")) {
+ if (this.keyType == SupportedImageModels.openai) {
return this.generateOpenaiImage(imageInput.getPrompt(),
imageInput.getNumberOfImages(), imageInput.getImageSize());
} else {
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoteLanguageModel.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoteLanguageModel.java
index f2d8573..e76944c 100644
--- a/core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoteLanguageModel.java
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoteLanguageModel.java
@@ -21,7 +21,9 @@
import java.util.List;
import java.util.Map;
import com.intellijava.core.model.CohereLanguageResponse;
+import com.intellijava.core.model.CohereLanguageResponse.Generation;
import com.intellijava.core.model.OpenaiLanguageResponse;
+import com.intellijava.core.model.OpenaiLanguageResponse.Choice;
import com.intellijava.core.model.SupportedLangModels;
import com.intellijava.core.model.input.LanguageModelInput;
import com.intellijava.core.wrappers.CohereAIWrapper;
@@ -52,7 +54,7 @@ public class RemoteLanguageModel {
/**
* Constructor for the RemoteLanguageModel class.
*
- * Creates an instance of the class and sets up the key and the API type.
+ * Creates an instance of the class and set the API type and key.
*
* @param keyValue the API key.
* @param keyTypeString either openai (default) or cohere or send empty string
@@ -80,8 +82,8 @@ public RemoteLanguageModel(String keyValue, String keyTypeString) {
/**
* Constructor for the RemoteLanguageModel class.
*
- * Creates an instance of the class and sets up the API key and the enum key
- * type.
+ * Creates an instance of the class and set the API enum type and key.
+ *
*
* @param keyValue the API key.
* @param keyType enum version from the key type (SupportedModels).
@@ -131,8 +133,10 @@ private void initiate(String keyValue, SupportedLangModels keyType) {
*
* Call a remote large model to generate any text based on the received prompt.
*
- * @param langInput flexible builder for language model parameters.
+ * To support multiple response call the variation function generateMultiText.
*
+ * @param langInput flexible builder for language model parameters.
+ *
* @return string for the model response.
* @throws IOException if there is an error when connecting to the
* OpenAI API.
@@ -143,13 +147,44 @@ private void initiate(String keyValue, SupportedLangModels keyType) {
public String generateText(LanguageModelInput langInput) throws IOException {
if (this.keyType.equals(SupportedLangModels.openai)) {
- return this.generateOpenaiText(langInput.getModel(), langInput.getPrompt(), langInput.getTemperature(),
- langInput.getMaxTokens());
+ return this.generateOpenaiText(langInput.getModel(),
+ langInput.getPrompt(), langInput.getTemperature(),
+ langInput.getMaxTokens(), langInput.getNumberOfOutputs()).get(0);
+ } else if (this.keyType.equals(SupportedLangModels.cohere)) {
+ return this.generateCohereText(langInput.getModel(),
+ langInput.getPrompt(), langInput.getTemperature(),
+ langInput.getMaxTokens(), langInput.getNumberOfOutputs()).get(0);
+ } else {
+ throw new IllegalArgumentException("the keyType not supported");
+ }
+
+ }
+
+ /**
+ *
+ * Call a remote large model to generate any text based on the received prompt.
+ *
+ * @param langInput flexible builder for language model parameters.
+ *
+ * @return list of model responses.
+ * @throws IOException if there is an error when connecting to the
+ * OpenAI API.
+ * @throws IllegalArgumentException if the keyType passed in the constructor is
+ * not "openai".
+ *
+ */
+ public List generateMultiText(LanguageModelInput langInput) throws IOException {
+
+ if (this.keyType.equals(SupportedLangModels.openai)) {
+ return this.generateOpenaiText(langInput.getModel(),
+ langInput.getPrompt(), langInput.getTemperature(),
+ langInput.getMaxTokens(), langInput.getNumberOfOutputs());
} else if (this.keyType.equals(SupportedLangModels.cohere)) {
- return this.generateCohereText(langInput.getModel(), langInput.getPrompt(), langInput.getTemperature(),
- langInput.getMaxTokens());
+ return this.generateCohereText(langInput.getModel(),
+ langInput.getPrompt(), langInput.getTemperature(),
+ langInput.getMaxTokens(), langInput.getNumberOfOutputs());
} else {
- throw new IllegalArgumentException("This version support openai keyType only");
+ throw new IllegalArgumentException("the keyType not supported");
}
}
@@ -163,11 +198,13 @@ public String generateText(LanguageModelInput langInput) throws IOException {
* @param prompt text of the required action or the question.
* @param temperature higher values means more risks and creativity.
* @param maxTokens maximum size of the model input and output.
+ * @param numberOfOutputs number of model outputs.
* @return string model response.
* @throws IOException if there is an error when connecting to the OpenAI API.
*
*/
- private String generateOpenaiText(String model, String prompt, float temperature, int maxTokens)
+ private List generateOpenaiText(String model, String prompt, float temperature,
+ int maxTokens, int numberOfOutputs)
throws IOException {
if (model.equals(""))
@@ -178,10 +215,16 @@ private String generateOpenaiText(String model, String prompt, float temperature
params.put("prompt", prompt);
params.put("temperature", temperature);
params.put("max_tokens", maxTokens);
+ params.put("n", numberOfOutputs);
OpenaiLanguageResponse resModel = (OpenaiLanguageResponse) openaiWrapper.generateText(params);
- return resModel.getChoices().get(0).getText();
+ List outputs = new ArrayList<>();
+ for (Choice item : resModel.getChoices()) {
+ outputs.add(item.getText());
+ }
+
+ return outputs;
}
@@ -192,11 +235,13 @@ private String generateOpenaiText(String model, String prompt, float temperature
* @param prompt text of the required action or the question.
* @param temperature higher values means more risks and creativity.
* @param maxTokens maximum size of the model input and output.
+ * @param numberOfOutputs number of model outputs.
* @return string model response.
* @throws IOException if there is an error when connecting to the API.
*
*/
- private String generateCohereText(String model, String prompt, float temperature, int maxTokens)
+ private List generateCohereText(String model, String prompt, float temperature,
+ int maxTokens, int numberOfOutputs)
throws IOException {
if (model.equals(""))
@@ -207,10 +252,16 @@ private String generateCohereText(String model, String prompt, float temperature
params.put("prompt", prompt);
params.put("temperature", temperature);
params.put("max_tokens", maxTokens);
+ params.put("num_generations", numberOfOutputs);
CohereLanguageResponse resModel = (CohereLanguageResponse) cohereWrapper.generateText(params);
-
- return resModel.getGenerations().get(0).getText();
+
+ List outputs = new ArrayList<>();
+ for (Generation item: resModel.getGenerations()) {
+ outputs.add(item.getText());
+ }
+
+ return outputs;
}
}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoteSpeechModel.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoteSpeechModel.java
new file mode 100644
index 0000000..5813bd9
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/controller/RemoteSpeechModel.java
@@ -0,0 +1,296 @@
+/**
+ * Copyright 2023 Github.com/Barqawiz/IntelliJava
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellijava.core.controller;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import com.intellijava.core.model.AudioResponse;
+import com.intellijava.core.model.SpeechModels;
+import com.intellijava.core.model.input.Text2SpeechInput;
+import com.intellijava.core.model.input.Text2SpeechInput.Gender;
+import com.intellijava.core.utils.AudioHelper;
+import com.intellijava.core.wrappers.GoogleAIWrapper;
+
+/**
+ * RemoteSpeechModel class provides a remote speech model implementation.
+ * It generates speech from text using the Wrapper classes.
+ *
+ * This version support google speech models only.
+ *
+ * To use Google speech services:
+ * 1- Go to console.cloud.google.com.
+ * 2- Enable "Cloud Text-to-Speech API".
+ * 3- Generate API key from "Credentials" page.
+ *
+ * @author github.com/Barqawiz
+ */
+public class RemoteSpeechModel {
+
+ private SpeechModels keyType;
+ private GoogleAIWrapper wrapper;
+
+ /**
+ *
+ * Constructs a new RemoteSpeechModel object with the specified key value and key type string.
+ * If keyTypeString is empty, it is set to "google" by default.
+ *
+ * @param keyValue the API key value to use.
+ * @param keyTypeString the string representation of the key type.
+ */
+ public RemoteSpeechModel(String keyValue, String keyTypeString) {
+
+ if (keyTypeString.isEmpty()) {
+ keyTypeString = SpeechModels.google.toString();
+ }
+
+ List supportedModels = this.getSupportedModels();
+
+
+ if (supportedModels.contains(keyTypeString)) {
+ this.initiate(keyValue, SpeechModels.valueOf(keyTypeString));
+ } else {
+ String models = String.join(" - ", supportedModels);
+ throw new IllegalArgumentException("The received keyValue not supported. Send any model from: " + models);
+ }
+ }
+
+ /**
+ *
+ * Constructs a new RemoteSpeechModel object with the specified key value and key type.
+ *
+ * @param keyValue The API key value to use.
+ * @param keyType The SpeechModels enum value representing the key type.
+ */
+ public RemoteSpeechModel(String keyValue, SpeechModels keyType) {
+ this.initiate(keyValue, keyType);
+ }
+
+ /**
+ * Initiate the object with the specified key value and key type.
+ *
+ * @param keyValue the API key value to use.
+ * @param keyType the SpeechModels enum value representing the key type.
+ */
+ private void initiate(String keyValue, SpeechModels keyType) {
+
+ this.keyType = keyType;
+ wrapper = new GoogleAIWrapper(keyValue);
+ }
+
+ /**
+ * Get a list of supported key type models.
+ *
+ * @return list of the supported SpeechModels enum values.
+ */
+ public List getSupportedModels() {
+ SpeechModels[] values = SpeechModels.values();
+ List enumValues = new ArrayList<>();
+
+ for (int i = 0; i < values.length; i++) {
+ enumValues.add(values[i].name());
+ }
+
+ return enumValues;
+ }
+
+ /**
+ * Generates speech using advanced audio models.
+ *
+ * You can save the result byte to audio file using FileOutputStream("path/audio.mp3").
+ *
+ * @param input SpeechInput object containing the text and gender to use.
+ * @return byte array of the decoded audio content.
+ * @throws IOException in case of communication error.
+ */
+ public byte[] generateEnglishText(Text2SpeechInput input) throws IOException {
+
+ if (this.keyType == SpeechModels.google) {
+ return this.generateGoogleText(input.getText(), input.getGender(), "en-GB");
+ } else {
+ throw new IllegalArgumentException("the keyType not supported");
+ }
+ }
+
+
+ /**
+ * Generates speech using advanced audio models.
+ *
+ * You can save the result byte to audio file using FileOutputStream("path/audio.mp3").
+ *
+ * @param input SpeechInput object containing the text and gender to use.
+ * @return byte array of the decoded audio content.
+ * @throws IOException in case of communication error.
+ */
+ public byte[] generateMandarinText(Text2SpeechInput input) throws IOException {
+
+ if (this.keyType == SpeechModels.google) {
+ return this.generateGoogleText(input.getText(), input.getGender(), "cmn-CN");
+ } else {
+ throw new IllegalArgumentException("the keyType not supported");
+ }
+ }
+
+ /**
+ * Generates speech using advanced audio models.
+ *
+ * You can save the result byte to audio file using FileOutputStream("path/audio.mp3").
+ *
+ * @param input SpeechInput object containing the text and gender to use.
+ * @return byte array of the decoded audio content.
+ * @throws IOException in case of communication error.
+ */
+ public byte[] generateArabicText(Text2SpeechInput input) throws IOException {
+
+ if (this.keyType == SpeechModels.google) {
+ return this.generateGoogleText(input.getText(), input.getGender(), "ar-XA");
+ } else {
+ throw new IllegalArgumentException("the keyType not supported");
+ }
+ }
+
+
+ /**
+ * Generates speech using advanced audio models.
+ *
+ * You can save the result byte to audio file using FileOutputStream("path/audio.mp3").
+ *
+ * @param input SpeechInput object containing the text and gender to use.
+ * @return byte array of the decoded audio content.
+ * @throws IOException in case of communication error.
+ */
+ public byte[] generateTurkishText(Text2SpeechInput input) throws IOException {
+
+ if (this.keyType == SpeechModels.google) {
+ return this.generateGoogleText(input.getText(), input.getGender(), "tr-TR");
+ } else {
+ throw new IllegalArgumentException("the keyType not supported");
+ }
+ }
+
+ /**
+ * Generates speech using advanced audio models.
+ *
+ * You can save the result byte to audio file using FileOutputStream("path/audio.mp3").
+ *
+ * @param input SpeechInput object containing the text and gender to use.
+ * @param langCode the language code, make sure to use the right code for the model engine.
+ * @return byte array of the decoded audio content.
+ * @throws IOException in case of communication error.
+ */
+ public byte[] generateText(Text2SpeechInput input, String langCode) throws IOException {
+
+ if (this.keyType == SpeechModels.google) {
+ return this.generateGoogleText(input.getText(), input.getGender(), langCode);
+ } else {
+ throw new IllegalArgumentException("the keyType not supported");
+ }
+ }
+
+
+ /**
+ * Generates speech using advanced audio models.
+ *
+ * You can save the result byte to audio file using FileOutputStream("path/audio.mp3").
+ *
+ * @param input SpeechInput object containing the text and gender to use.
+ * @return byte array of the decoded audio content.
+ * @throws IOException in case of communication error.
+ */
+ public byte[] generateGermanText(Text2SpeechInput input) throws IOException {
+
+ if (this.keyType == SpeechModels.google) {
+ return this.generateGoogleText(input.getText(), input.getGender(), "de-de");
+ } else {
+ throw new IllegalArgumentException("the keyType not supported");
+ }
+ }
+
+ /**
+ * Generates speech from text using the Google Speech service API.
+ *
+ * @param text text to generate the speech.
+ * @param gender gender to use (male or female).
+ * @param language en-gb.
+ * @return
+ * @throws IOException in case of communication error.
+ */
+ private byte[] generateGoogleText(String text, Gender gender, String language) throws IOException {
+ byte[] decodedAudio = null;
+
+ Map params = new HashMap<>();
+ params.put("text", text);
+ params.put("languageCode", language);
+
+ language = language.toLowerCase();
+
+ if (language.equals("en-gb")) {
+ // English
+ if (gender == Gender.FEMALE) {
+ params.put("name", "en-GB-Standard-A");
+ params.put("ssmlGender", "FEMALE");
+ } else {
+ params.put("name", "en-GB-Standard-B");
+ params.put("ssmlGender", "MALE");
+ }
+ } else if (language.equals("tr-tr")) {
+ // Turkish
+ if (gender == Gender.FEMALE) {
+ params.put("name", "tr-TR-Standard-A");
+ params.put("ssmlGender", "FEMALE");
+ } else {
+ params.put("name", "tr-TR-Standard-B");
+ params.put("ssmlGender", "MALE");
+ }
+ } else if (language.equals("cmn-cn")) {
+ // Mandarin Chinese
+ if (gender == Gender.FEMALE) {
+ params.put("name", "cmn-CN-Standard-A");
+ params.put("ssmlGender", "FEMALE");
+ } else {
+ params.put("name", "cmn-CN-Standard-B");
+ params.put("ssmlGender", "MALE");
+ }
+ } else if (language.equals("de-de")) {
+ // German (Germany)
+ if (gender == Gender.FEMALE) {
+ params.put("name", "de-DE-Standard-A");
+ params.put("ssmlGender", "FEMALE");
+ } else {
+ params.put("name", "de-DE-Standard-B");
+ params.put("ssmlGender", "MALE");
+ }
+ } else if (language.equals("ar-xa")) {
+ // Arabic
+ if (gender == Gender.FEMALE) {
+ params.put("name", "ar-XA-Wavenet-A");
+ params.put("ssmlGender", "FEMALE");
+ } else {
+ params.put("name", "ar-XA-Standard-B");
+ params.put("ssmlGender", "MALE");
+ }
+ } else {
+ throw new IllegalArgumentException("Unsupported language code: " + language);
+ }
+
+ AudioResponse resModel = (AudioResponse) wrapper.generateSpeech(params);
+ decodedAudio = AudioHelper.decode(resModel.getAudioContent());
+
+ return decodedAudio;
+ }
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/function/Chatbot.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/function/Chatbot.java
new file mode 100644
index 0000000..bb90033
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/function/Chatbot.java
@@ -0,0 +1,165 @@
+package com.intellijava.core.function;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.intellijava.core.model.OpenaiChatResponse;
+import com.intellijava.core.model.OpenaiChatResponse.Choice;
+import com.intellijava.core.model.SupportedChatModels;
+import com.intellijava.core.model.input.ChatGPTInput;
+import com.intellijava.core.model.input.ChatModelInput;
+import com.intellijava.core.wrappers.OpenAIWrapper;
+
+/**
+ *
+ * Chatbot controller for most sophisticated AI chatbots.
+ *
+ * @author github.com/Barqawiz
+ *
+ */
+public class Chatbot {
+
+ private SupportedChatModels keyType;
+ private OpenAIWrapper openaiWrapper;
+
+ /**
+ *
+ * Constructor for the Chatbot class.
+ *
+ * Creates class instance and set the API type and key.
+ *
+ * @param keyValue the API key.
+ * @param keyTypeString either openai (default) or cohere or send empty string
+ * for default value.
+ *
+ * @throws IllegalArgumentException if the keyType passed is not "openai".
+ *
+ */
+ public Chatbot(String keyValue, String keyTypeString) {
+
+ if (keyTypeString.isEmpty()) {
+ keyTypeString = SupportedChatModels.openai.toString();
+ }
+
+ List supportedModels = this.getSupportedModels();
+
+ if (supportedModels.contains(keyTypeString)) {
+ this.initiate(keyValue, SupportedChatModels.valueOf(keyTypeString));
+ } else {
+ String models = String.join(" - ", supportedModels);
+ throw new IllegalArgumentException("The received keyValue not supported. Send any model from: " + models);
+ }
+ }
+
+ /**
+ * Constructor for the Chatbot class.
+ *
+ * Creates class instance and set the API enum type and key.
+ *
+ * @param keyValue the API key.
+ * @param keyType enum version from the key type (SupportedModels).
+ *
+ * @throws IllegalArgumentException if the keyType passed is not "openai".
+ *
+ */
+ public Chatbot(String keyValue, SupportedChatModels keyType) {
+ this.initiate(keyValue, keyType);
+ }
+
+ /**
+ * Get the supported models names as array of string
+ *
+ * @return supportedModels
+ */
+ public List getSupportedModels() {
+ SupportedChatModels[] values = SupportedChatModels.values();
+ List enumValues = new ArrayList<>();
+
+ for (int i = 0; i < values.length; i++) {
+ enumValues.add(values[i].name());
+ }
+
+ return enumValues;
+ }
+
+ /**
+ * Common function to initiate the class from any constructor.
+ *
+ * @param keyValue the API key.
+ * @param keyType enum version from the key type (SupportedModels).
+ */
+ private void initiate(String keyValue, SupportedChatModels keyType) {
+ // set the model type
+ this.keyType = keyType;
+
+ // generate the related model
+ if (keyType.equals(SupportedChatModels.openai)) {
+ this.openaiWrapper = new OpenAIWrapper(keyValue);
+ }
+ }
+
+ /**
+ *
+ * Call a chat model to generate response based on the received messages history.
+ *
+ * To support multiple response call the variation function generateMultiText.
+ *
+ * @param modelInput language model parameters.
+ *
+ * @return the model response.
+ *
+ * @throws IOException if there is an error when connecting to the chat model.
+ *
+ */
+ public List chat(ChatModelInput modelInput) throws IOException {
+
+ if (this.keyType.equals(SupportedChatModels.openai)) {
+ return this.chatGPT((ChatGPTInput) modelInput);
+ } else {
+ throw new IllegalArgumentException("the keyType not supported");
+ }
+ }
+
+
+ /**
+ *
+ * Call a chatGPT to generate response based on the received messages history.
+ *
+ * @param modelInput for chatGPT.
+ *
+ * @return string for the model response.
+ *
+ * @throws IOException if there is an error when connecting to the chatGPT.
+ */
+ private List chatGPT(ChatGPTInput modelInput) throws IOException {
+
+ Map params = new HashMap<>();
+ params.put("model", modelInput.getModel());
+ params.put("messages", modelInput.getMessages());
+ if (modelInput.getNumberOfOutputs() >= 0) {
+ params.put("n", modelInput.getNumberOfOutputs());
+ }
+
+ if (modelInput.getTemperature() >= 0) {
+ params.put("temperature", modelInput.getTemperature());
+ }
+
+ if (modelInput.getMaxTokens() >= 1) {
+ params.put("max_tokens", modelInput.getMaxTokens());
+ }
+
+ OpenaiChatResponse resModel = (OpenaiChatResponse) openaiWrapper.generateChatText(params);
+
+ List outputs = new ArrayList<>();
+ for (Choice item : resModel.getChoices()) {
+ outputs.add(item.getMessage().getContent());
+ }
+
+ return outputs;
+ }
+
+
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/AudioResponse.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/AudioResponse.java
new file mode 100644
index 0000000..cdcb43b
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/AudioResponse.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright 2023 Github.com/Barqawiz/IntelliJava
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellijava.core.model;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ *
+ * AudioResponse represents the response from the speech API that contains the audio content.
+ *
+ * @author github.com/Barqawiz
+ *
+ */
+public class AudioResponse extends BaseRemoteModel {
+
+ /**
+ * Default AudioResponse constructor.
+ */
+ public AudioResponse() {}
+
+ /**
+ * The audio content generated from a text.
+ */
+ @SerializedName("audioContent")
+ private String audioContent;
+
+ /**
+ * Gets the audio content generated from a text.
+ * @return audio content as a base64 string.
+ */
+ public String getAudioContent() {
+ return audioContent;
+ }
+
+ /**
+ * Sets the audio content generated from a text.
+ *
+ * @param audioContent audio content as a base64 string.
+ */
+ public void setAudioContent(String audioContent) {
+ this.audioContent = audioContent;
+ }
+
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/CohereLanguageResponse.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/CohereLanguageResponse.java
index da84320..e49bd5f 100644
--- a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/CohereLanguageResponse.java
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/CohereLanguageResponse.java
@@ -15,6 +15,13 @@ public class CohereLanguageResponse extends BaseRemoteModel{
private List generations;
private String prompt;
+ /**
+ * CohereLanguageResponse default constructor.
+ */
+ public CohereLanguageResponse() {
+
+ }
+
/**
*
* Generation is wrapper for the response
@@ -26,6 +33,13 @@ public static class Generation {
private String id;
private String text;
+ /**
+ * Generation default constructor.
+ */
+ public Generation() {
+
+ }
+
/**
* Get the unique identifier for the generation.
*
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/OpenaiChatResponse.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/OpenaiChatResponse.java
new file mode 100644
index 0000000..2f73829
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/OpenaiChatResponse.java
@@ -0,0 +1,306 @@
+package com.intellijava.core.model;
+
+import java.util.List;
+
+import com.intellijava.core.model.OpenaiLanguageResponse.Choice;
+import com.intellijava.core.model.OpenaiLanguageResponse.Usage;
+
+/**
+ *
+ * OpenaiChatResponse is a model class used to parse the response from the OpenAI ChatGPT API.
+ * choices, Usage and Message are nested classes.
+ *
+ * @author github.com/Barqawiz
+ */
+public class OpenaiChatResponse extends BaseRemoteModel {
+
+ private String object;
+ private long created;
+ private String model;
+ private Usage usage;
+ private List choices;
+
+ /**
+ * OpenaiChatResponse default constructor.
+ */
+ public OpenaiChatResponse() {
+
+ }
+
+ /**
+ * A nested class for the API response's choice represents the model output.
+ */
+ public static class Choice {
+ private Message message;
+ private String finish_reason;
+ private int index;
+
+ /**
+ * Choice default constructor.
+ */
+ public Choice() {
+
+ }
+
+ /**
+ * Gets the model message.
+ *
+ * @return message model response message.
+ */
+ public Message getMessage() {
+ return message;
+ }
+
+ /**
+ * Sets the model message.
+ *
+ * @param message model response message.
+ */
+ public void setMessage(Message message) {
+ this.message = message;
+ }
+
+ /**
+ * Gets the reason to end the message for validating missing response reasons.
+ *
+ * @return reason string.
+ */
+ public String getFinish_reason() {
+ return finish_reason;
+ }
+
+ /**
+ *
+ * Sets the reason to end the message text
+ *
+ * @param finish_reason string.
+ */
+ public void setFinish_reason(String finish_reason) {
+ this.finish_reason = finish_reason;
+ }
+
+ /**
+ * Gets the index property of the choice object
+ *
+ * @return the index of the choice object
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Sets the index property of the choice object
+ *
+ * @param index the index of the choice object
+ */
+ public void setIndex(int index) {
+ this.index = index;
+ }
+ }
+
+ /**
+ * Usage is a nested class that represents a Usage object returned in the API response.
+ */
+ public static class Usage {
+ private int prompt_tokens;
+ private int completion_tokens;
+ private int total_tokens;
+
+ /**
+ * Usage default constructor.
+ */
+ public Usage() {
+
+ }
+
+ /**
+ * Gets the prompt_tokens property
+ *
+ * @return the value of prompt_tokens property
+ */
+ public int getPrompt_tokens() {
+ return prompt_tokens;
+ }
+ /**
+ * Sets the prompt_tokens property
+ *
+ * @param prompt_tokens the new value of the prompt_tokens property
+ */
+ public void setPrompt_tokens(int prompt_tokens) {
+ this.prompt_tokens = prompt_tokens;
+ }
+ /**
+ * Gets the completion_tokens property
+ *
+ * @return the value of completion_tokens property
+ */
+ public int getCompletion_tokens() {
+ return completion_tokens;
+ }
+ /**
+ * Sets the completion_tokens property
+ *
+ * @param completion_tokens the new value of the completion_tokens property
+ */
+ public void setCompletion_tokens(int completion_tokens) {
+ this.completion_tokens = completion_tokens;
+ }
+ /**
+ * Gets the total_tokens property
+ *
+ * @return the value of total_tokens property
+ */
+ public int getTotal_tokens() {
+ return total_tokens;
+ }
+ /**
+ * Sets the total_tokens property
+ *
+ * @param total_tokens the new value of the total_tokens property
+ */
+ public void setTotal_tokens(int total_tokens) {
+ this.total_tokens = total_tokens;
+ }
+
+ }
+
+ /**
+ * Message represents a message exchanged in a chat session.
+ */
+ public static class Message {
+ private String role;
+ private String content;
+
+ /**
+ * Message default constructor.
+ */
+ public Message() {}
+
+ /**
+ * Gets the role of the sender of the message.
+ *
+ * @return the role of the sender of the message.
+ */
+ public String getRole() {
+ return role;
+ }
+
+ /**
+ * Sets the role of the sender of the message.
+ *
+ * @param role the role of the sender of the message.
+ */
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ /**
+ * Gets the content of the message.
+ *
+ * @return the content of the message.
+ */
+ public String getContent() {
+ return content;
+ }
+
+ /**
+ * Sets the content of the message.
+ *
+ * @param content the content of the message.
+ */
+ public void setContent(String content) {
+ this.content = content;
+ }
+ }
+
+ /**
+ * Gets the object type of the API response.
+ *
+ * @return the value of object property
+ */
+ public String getObject() {
+ return object;
+ }
+
+ /**
+ * Sets the object type of the API response.
+ *
+ * @param object the new value of the object property
+ */
+ public void setObject(String object) {
+ this.object = object;
+ }
+
+ /**
+ * Gets the timestamp for the API response.
+ *
+ * @return the value of created property
+ */
+ public long getCreated() {
+ return created;
+ }
+
+
+ /**
+ * Set the timestamp for the API response.
+ *
+ * @param created the timestamp when the API request was created.
+ */
+ public void setCreated(long created) {
+ this.created = created;
+ }
+
+ /**
+ * Gets the name of the language model
+ *
+ * @return the model id or name used to generate the API response
+ */
+ public String getModel() {
+ return model;
+ }
+
+ /**
+ * Setsthe name of the language model
+ *
+ * @param model the model id or name used to generate the API response
+ */
+ public void setModel(String model) {
+ this.model = model;
+ }
+
+ /**
+ * Gets the usage statistics for generating the API response.
+ *
+ * @return the usage object that contains usage statistics of the API request
+ */
+ public Usage getUsage() {
+ return usage;
+ }
+
+ /**
+ * Set the usage statistics for generating the API response.
+ *
+ * @param usage the usage object that contains usage statistics of the API request
+ */
+ public void setUsage(Usage usage) {
+ this.usage = usage;
+ }
+
+ /**
+ * Gets the choices property
+ *
+ * @return list of Choice objects that contain the generated completions and additional information
+ */
+ public List getChoices() {
+ return choices;
+ }
+
+ /**
+ * Sets the choices property
+ *
+ * @param choices list of Choice objects that contain the generated completions and additional information
+ */
+ public void setChoices(List choices) {
+ this.choices = choices;
+ }
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/OpenaiLanguageResponse.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/OpenaiLanguageResponse.java
index 23b904b..743900f 100644
--- a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/OpenaiLanguageResponse.java
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/OpenaiLanguageResponse.java
@@ -40,7 +40,7 @@ public OpenaiLanguageResponse() {
}
/**
- * A nested class that represents an choice object returned in the API response.
+ * A nested class for the API response's choice represents the model output.
*/
public static class Choice {
/**
@@ -59,7 +59,7 @@ public Choice() {
}
/**
- * Get the text property of the choice object
+ * Gets the text property of the choice object
*
* @return the text of the choice object
*/
@@ -75,7 +75,7 @@ public void setText(String text) {
this.text = text;
}
/**
- * Get the index property of the choice object
+ * Gets the index property of the choice object
*
* @return the index of the choice object
*/
@@ -91,7 +91,7 @@ public void setIndex(int index) {
this.index = index;
}
/**
- * Get the logprobs property of the choice object
+ * Gets the logprobs property of the choice object
*
* @return the logprobs of the choice object
*/
@@ -107,7 +107,7 @@ public void setLogprobs(Object logprobs) {
this.logprobs = logprobs;
}
/**
- * Get the finish_reason property of the choice object
+ * Gets the finish_reason property of the choice object
*
* @return the finish_reason of the choice object
*/
@@ -142,7 +142,7 @@ public Usage() {
}
/**
- * Get the prompt_tokens property
+ * Gets the prompt_tokens property
*
* @return the value of prompt_tokens property
*/
@@ -150,7 +150,7 @@ public int getPrompt_tokens() {
return prompt_tokens;
}
/**
- * Set the prompt_tokens property
+ * Sets the prompt_tokens property
*
* @param prompt_tokens the new value of the prompt_tokens property
*/
@@ -158,7 +158,7 @@ public void setPrompt_tokens(int prompt_tokens) {
this.prompt_tokens = prompt_tokens;
}
/**
- * Get the completion_tokens property
+ * Gets the completion_tokens property
*
* @return the value of completion_tokens property
*/
@@ -166,7 +166,7 @@ public int getCompletion_tokens() {
return completion_tokens;
}
/**
- * Set the completion_tokens property
+ * Sets the completion_tokens property
*
* @param completion_tokens the new value of the completion_tokens property
*/
@@ -174,7 +174,7 @@ public void setCompletion_tokens(int completion_tokens) {
this.completion_tokens = completion_tokens;
}
/**
- * Get the total_tokens property
+ * Gets the total_tokens property
*
* @return the value of total_tokens property
*/
@@ -182,7 +182,7 @@ public int getTotal_tokens() {
return total_tokens;
}
/**
- * Set the total_tokens property
+ * Sets the total_tokens property
*
* @param total_tokens the new value of the total_tokens property
*/
@@ -194,7 +194,7 @@ public void setTotal_tokens(int total_tokens) {
}
/**
- * Get the object property
+ * Gets the object type of the API response.
*
* @return the value of object property
*/
@@ -203,15 +203,16 @@ public String getObject() {
}
/**
- * Set the object property
+ * Sets the object type of the API response.
*
* @param object the new value of the object property
*/
public void setObject(String object) {
this.object = object;
}
+
/**
- * Get the created property
+ * Gets the timestamp for the API response.
*
* @return the value of created property
*/
@@ -220,7 +221,7 @@ public long getCreated() {
}
/**
- * Set the created property
+ * Sets the timestamp for the API response.
*
* @param created the timestamp when the API request was created.
*/
@@ -229,7 +230,7 @@ public void setCreated(long created) {
}
/**
- * Get the model name property
+ * Gets the name of the language model
*
* @return the model id or name used to generate the API response
*/
@@ -238,7 +239,7 @@ public String getModel() {
}
/**
- * Set the model name property
+ * Setsthe name of the language model
*
* @param model the model id or name used to generate the API response
*/
@@ -247,7 +248,7 @@ public void setModel(String model) {
}
/**
- * Get the choices property
+ * Gets the choices property
*
* @return list of Choice objects that contain the generated completions and additional information
*/
@@ -256,7 +257,7 @@ public List getChoices() {
}
/**
- * Set the choices property
+ * Sets the choices property
*
* @param choices list of Choice objects that contain the generated completions and additional information
*/
@@ -265,7 +266,7 @@ public void setChoices(List choices) {
}
/**
- * Get the usage property
+ * Gets the usage statistics for generating the API response.
*
* @return the usage object that contains usage statistics of the API request
*/
@@ -274,7 +275,7 @@ public Usage getUsage() {
}
/**
- * Set the usage property
+ * Sets the usage statistics for generating the API response.
*
* @param usage the usage object that contains usage statistics of the API request
*/
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/SpeechModels.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/SpeechModels.java
new file mode 100644
index 0000000..c2ae9ec
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/SpeechModels.java
@@ -0,0 +1,11 @@
+package com.intellijava.core.model;
+
+/**
+ * Supported speech models.
+ *
+ * @author github.com/Barqawiz
+ *
+ */
+public enum SpeechModels {
+ /** google model */google
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/SupportedChatModels.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/SupportedChatModels.java
new file mode 100644
index 0000000..2bcbb1a
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/SupportedChatModels.java
@@ -0,0 +1,11 @@
+package com.intellijava.core.model;
+
+/**
+ * Supported chat models.
+ *
+ * @author github.com/Barqawiz
+ *
+ */
+public enum SupportedChatModels {
+ /** openai model */openai
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/SupportedImageModels.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/SupportedImageModels.java
new file mode 100644
index 0000000..122d3d8
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/SupportedImageModels.java
@@ -0,0 +1,11 @@
+package com.intellijava.core.model;
+
+/**
+ *
+ * Supported Image Models.
+ *
+ * @author github.com/Barqawiz
+ */
+public enum SupportedImageModels {
+ /** openai model */openai
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ChatGPTInput.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ChatGPTInput.java
new file mode 100644
index 0000000..0096491
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ChatGPTInput.java
@@ -0,0 +1,320 @@
+package com.intellijava.core.model.input;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.intellijava.core.model.input.ChatGPTMessage.Role;
+
+/**
+ * ChatGPTInput contains a list of messages to continue the conversation with
+ * the chatbot.
+ *
+ * @author github.com/Barqawiz
+ *
+ */
+public class ChatGPTInput extends ChatModelInput {
+
+ private List messages = new ArrayList<>();
+ private String model = "gpt-3.5-turbo";
+ private float temperature = 1;
+ private int numberOfOutputs = 1;
+ private int maxTokens;
+
+ /**
+ * Create ChatGPT input object with the system instruction.
+ *
+ * Example of general system instruction: You are a helpful assistant.
+ *
+ * @param systemMessage the system instruction to define the chat mode/theme.
+ */
+ public ChatGPTInput(ChatGPTMessage systemMessage) {
+ if (systemMessage.isSystemRol()) {
+ messages.add(systemMessage);
+ } else {
+ throw new IllegalArgumentException(
+ "The input type should be system to define the chatbot theme or instructions.");
+ }
+ }
+
+
+ /**
+ * Create ChatGPT input object with the system instruction.
+ *
+ * Example of general system instruction: You are a helpful assistant.
+ *
+ * @param systemPrompt string input to define the chat mode/theme.
+ */
+ public ChatGPTInput(String systemPrompt) {
+ messages.add(new ChatGPTMessage(systemPrompt, Role.system));
+
+ }
+
+ /**
+ * Create ChatGPT input with the builder.
+ *
+ *
+ * @param system message
+ */
+ private ChatGPTInput(Builder builder) {
+ this.messages = builder.messages;
+ this.temperature = builder.temperature;
+ this.numberOfOutputs = builder.numberOfOutputs;
+ this.maxTokens = builder.maxTokens;
+ this.model = builder.model;
+ }
+
+ /**
+ *
+ * Builder class for ChatGPTInput.
+ *
+ */
+ public static class Builder {
+
+ private List messages = new ArrayList<>();
+ private String model = "gpt-3.5-turbo";
+ private float temperature = 1;
+ private int numberOfOutputs = 1;
+ private int maxTokens;
+
+ /**
+ * Builder for ChatGPTInput with the system or chatbot instructions.
+ *
+ * Example of general system instruction: You are a helpful assistant.
+ *
+ * @param systemMessage the system instruction to define the chat mode/theme.
+ */
+ public Builder(ChatGPTMessage systemMessage) {
+ if (systemMessage.isSystemRol()) {
+ messages.add(systemMessage);
+ } else {
+ throw new IllegalArgumentException(
+ "The input type should be system to define the chatbot theme or instructions.");
+ }
+ }
+
+ /**
+ * Builder for ChatGPTInput with the system or chatbot instructions.
+ *
+ * Example of general system instruction: You are a helpful assistant.
+ *
+ * @param systemPrompt string input to define the chat mode/theme.
+ */
+ public Builder(String systemPrompt) {
+ messages.add(new ChatGPTMessage(systemPrompt, Role.system));
+ }
+
+ /**
+ * Add the chat message.
+ *
+ * @param message (content and role)
+ *
+ * @return instance of Builder.
+ */
+ public Builder addMessage(ChatGPTMessage message) {
+ messages.add(message);
+ return this;
+ }
+
+ /**
+ * Sets the temperature.
+ *
+ * @param temperature higher values means more risks and creativity.
+ * @return instance of Builder.
+ */
+ public Builder setTemperature(float temperature) {
+ this.temperature = temperature;
+ return this;
+ }
+
+ /**
+ * Sets the numberOfOutputs
+ *
+ * @param numberOfOutputs number of model outputs, default value is 1.
+ *
+ * @return instance of Builder.
+ */
+ public Builder setNumberOfOutputs(int numberOfOutputs) {
+ this.numberOfOutputs = numberOfOutputs;
+ return this;
+ }
+
+ /**
+ * Sets the maxTokens.
+ *
+ * @param maxTokens maximum size of the model input and output.
+ * @return instance of Builder.
+ */
+ public Builder setMaxTokens(int maxTokens) {
+ this.maxTokens = maxTokens;
+ return this;
+ }
+
+ /**
+ * Add input message for your prompt.
+ *
+ * @param prompt model input with user role.
+ *
+ * @return instance of Builder.
+ */
+ public Builder addUserMessage(String prompt) {
+ messages.add(new ChatGPTMessage(prompt, Role.user));
+ return this;
+ }
+
+ /**
+ * Sets chatGPT model name, default is gpt-3.5-turbo.
+ *
+ * @param model the model name.
+ * @return instance of Builder.
+ */
+ public Builder setModel(String model) {
+ this.model = model;
+ return this;
+ }
+
+ /**
+ * Build the final ChatGPTInput object.
+ *
+ * @return final LanguageModelInput object.
+ */
+ public ChatGPTInput build() {
+ return new ChatGPTInput(this);
+ }
+ }
+
+ /**
+ * Add input message.
+ *
+ * Example of chat flow: system: You are a helpful assistant. user: Who won the
+ * world series in 2020? assistant: The Los Angeles Dodgers won the World Series
+ * in 2020. user: Where was it played?
+ *
+ * @param message chat input element with defined role.
+ */
+ public void addMessage(ChatGPTMessage message) {
+ messages.add(message);
+ }
+
+ /**
+ * Add input message for your prompt.
+ * @param prompt users input (query).
+ */
+ public void addUserMessage(String prompt) {
+ messages.add(new ChatGPTMessage(prompt, Role.user));
+ }
+
+ /**
+ * Remove all messages except the system message. To start new system, create a
+ * new object.
+ */
+ public void cleanMessages() {
+ if (messages.size() > 1) {
+ ChatGPTMessage firstMessage = messages.get(0);
+ messages.clear();
+ messages.add(firstMessage);
+ }
+ }
+
+ /**
+ * Delete last added message with the same message.getContent() and
+ * message.getRole().
+ *
+ * @param message The message to delete
+ * @return true if a message was deleted, false otherwise
+ */
+ public boolean deleteLastMessage(ChatGPTMessage message) {
+
+ for (int i = messages.size() - 1; i >= 0; i--) {
+ ChatGPTMessage currentMessage = messages.get(i);
+ if (currentMessage.getContent().equals(message.getContent())
+ && currentMessage.getRole() == message.getRole()) {
+ messages.remove(i);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Gets all messages.
+ *
+ * @return list of messages
+ */
+ public List getMessages() {
+ return messages;
+ }
+
+ /**
+ * Gets the temperature of the ChatGPTInput object.
+ *
+ * @return temperature.
+ */
+ public float getTemperature() {
+ return temperature;
+ }
+
+ /**
+ * Sets the temperature.
+ *
+ * @param temperature higher values means more risks and creativity.
+ */
+ public void setTemperature(float temperature) {
+ this.temperature = temperature;
+ }
+
+ /**
+ * Gets the number of model outputs.
+ *
+ * @return numberOfOutputs
+ */
+ public int getNumberOfOutputs() {
+ return numberOfOutputs;
+ }
+
+ /**
+ * Sets the numberOfOutputs.
+ *
+ * @param numberOfOutputs number of model outputs, default value is 1.
+ */
+ public void setNumberOfOutputs(int numberOfOutputs) {
+ this.numberOfOutputs = numberOfOutputs;
+ }
+
+ /**
+ * Gets the maxTokens.
+ *
+ * @return maxTokens
+ */
+ public int getMaxTokens() {
+ return maxTokens;
+ }
+
+ /**
+ * Sets the maxTokens.
+ *
+ * @param maxTokens maximum size of the model input and output.
+ */
+ public void setMaxTokens(int maxTokens) {
+ this.maxTokens = maxTokens;
+ }
+
+ /**
+ * Gets the model.
+ *
+ * @return model
+ */
+ public String getModel() {
+ return model;
+ }
+
+ /**
+ * Sets the model.
+ *
+ * @param model chatGPT model name, default is gpt-3.5-turbo.
+ */
+ public void setModel(String model) {
+ this.model = model;
+ }
+
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ChatGPTMessage.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ChatGPTMessage.java
new file mode 100644
index 0000000..1352f1c
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ChatGPTMessage.java
@@ -0,0 +1,99 @@
+package com.intellijava.core.model.input;
+
+/**
+ *
+ * ChatGPTMessage represent a message element for the chat.
+ *
+ * @author github.com/Barqawiz
+ *
+ */
+public class ChatGPTMessage extends ChatMessage {
+
+ private Role role;
+
+ /**
+ * ChatGPTMessage default constructor.
+ */
+ public ChatGPTMessage() {}
+
+ /**
+ * Initiate ChatGPTMessage with the mandatory parameters.
+ *
+ * @param content text input
+ * @param role system or user or assistant to define who sent the message.
+ *
+ */
+ public ChatGPTMessage(String content, Role role) {
+ setContent(content);
+ setRole(role);
+ }
+
+ /**
+ * get the input role.
+ * system : represents the instruction message.
+ * user : represents the end user message.
+ * assistant : represents the model message.
+ *
+ * @return system | user | assistant
+ */
+ public Role getRole() {
+ return role;
+ }
+
+ /**
+ * set the input role.
+ * system : represents the instruction message.
+ * user : represents the end user message.
+ * assistant : represents the model message.
+ *
+ * @param role system | user | assistant
+ */
+ public void setRole(Role role) {
+ this.role = role;
+ }
+
+ /**
+ * Sets the role for chatGPT instructions.
+ */
+ public void setSystemRol() {
+ this.role = Role.system;
+ }
+
+ /**
+ *
+ * Validate the current message role is system.
+ *
+ * @return true if system role.
+ */
+ public boolean isSystemRol() {
+ return this.role == Role.system;
+ }
+
+ /**
+ * Sets the role for the user message.
+ */
+ public void setUserRol() {
+ this.role = Role.user;
+ }
+
+ /**
+ * Sets the role for the model message.
+ */
+ public void setAssistantRol() {
+ this.role = Role.assistant;
+ }
+
+ /**
+ *
+ * Chat input roles.
+ *
+ * @author github.com/Barqawiz
+ *
+ */
+ public enum Role {
+ /** system role defines the chat mode or theme.*/system,
+ /** user role defines the end user message or query.*/user,
+ /** assistant role defines the chatbot response.*/assistant
+ }
+
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ChatMessage.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ChatMessage.java
new file mode 100644
index 0000000..ca0c8c6
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ChatMessage.java
@@ -0,0 +1,40 @@
+package com.intellijava.core.model.input;
+
+/**
+ *
+ * ChatInput represents an input element for chatbots.
+ *
+ * @author github.com/Barqawiz
+ *
+ */
+public class ChatMessage {
+
+ private String content;
+
+ /**
+ * ChatMessage default constructor.
+ */
+ public ChatMessage() {
+
+ }
+
+ /**
+ * Gets the text content.
+ *
+ * @return content string message.
+ */
+ public String getContent() {
+ return content;
+ }
+
+ /**
+ * Sets the text content.
+ *
+ * @param content string message.
+ */
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ChatModelInput.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ChatModelInput.java
new file mode 100644
index 0000000..e78d9e8
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ChatModelInput.java
@@ -0,0 +1,13 @@
+package com.intellijava.core.model.input;
+
+/**
+ * ChatModelInput abstract for any chat model input to inherit.
+ *
+ * @author github.com/Barqawiz
+ *
+ */
+public abstract class ChatModelInput {
+
+ /**ChatModelInput abstract constructor*/
+ public ChatModelInput() {}
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ImageModelInput.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ImageModelInput.java
index 86c604c..c8debee 100644
--- a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ImageModelInput.java
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/ImageModelInput.java
@@ -37,7 +37,25 @@ private ImageModelInput(Builder builder) {
this.numberOfImages = builder.numberOfImages;
this.imageSize = builder.imageSize;
}
+
+
/**
+ * ImageModelInput default constructor.
+ *
+ * @param prompt image generation text.
+ * @param numberOfImages number of generated images.
+ * @param imageSize size of the generated images, options are: 256x256, 512x512, or 1024x1024.
+ */
+ public ImageModelInput(String prompt, int numberOfImages, String imageSize) {
+ super();
+ this.prompt = prompt;
+ this.numberOfImages = numberOfImages;
+ this.imageSize = imageSize;
+ }
+
+
+
+ /**
*
* Builder class for ImageModelInput
*/
@@ -92,7 +110,7 @@ public ImageModelInput build() {
}
}
/**
- * Getter for prompt.
+ * Getter for prompt the text of the required action or the question.
* @return prompt
*/
public String getPrompt() {
@@ -114,5 +132,35 @@ public int getNumberOfImages() {
public String getImageSize() {
return imageSize;
}
+
+
+ /**
+ * Setter for prompt.
+ *
+ * @param prompt
+ */
+ public void setPrompt(String prompt) {
+ this.prompt = prompt;
+ }
+
+
+ /**
+ * Setter for numberOfImages.
+ * @param numberOfImages the number of the generated images.
+ */
+ public void setNumberOfImages(int numberOfImages) {
+ this.numberOfImages = numberOfImages;
+ }
+
+
+ /**
+ * Setter for imageSize.
+ *
+ * @param imageSize the size of the generated images, options are: 256x256, 512x512, or 1024x1024.
+ */
+ public void setImageSize(String imageSize) {
+ this.imageSize = imageSize;
+ }
+
}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/LanguageModelInput.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/LanguageModelInput.java
index 2c7834f..4783552 100644
--- a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/LanguageModelInput.java
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/LanguageModelInput.java
@@ -17,6 +17,7 @@ public class LanguageModelInput {
private String prompt;
private float temperature;
private int maxTokens;
+ private int numberOfOutputs = 1;
/**
* Private Constructor for the Builder.
@@ -27,8 +28,31 @@ private LanguageModelInput(Builder builder) {
this.prompt = builder.prompt;
this.temperature = builder.temperature;
this.maxTokens = builder.maxTokens;
+ this.numberOfOutputs = builder.numberOfOutputs;
}
+
+
/**
+ * LanguageModelInput default constructor.
+ *
+ * @param model name.
+ * @param prompt text.
+ * @param temperature model creativity between 0 and 1.
+ * @param maxTokens number of input and output tokens.
+ * @param numberOfOutputs number of generated text.
+ */
+ public LanguageModelInput(String model, String prompt, float temperature, int maxTokens, int numberOfOutputs) {
+ super();
+ this.model = model;
+ this.prompt = prompt;
+ this.temperature = temperature;
+ this.maxTokens = maxTokens;
+ this.numberOfOutputs = numberOfOutputs;
+ }
+
+
+
+ /**
*
* Builder class for LanguageModelInput.
*
@@ -38,6 +62,7 @@ public static class Builder {
private String prompt;
private float temperature;
private int maxTokens;
+ private int numberOfOutputs = 1;
/**
* Language input Constructor.
@@ -48,7 +73,7 @@ public Builder(String prompt) {
}
/**
- * Setter for model.
+ * Sets the model.
* @param model the model name.
*
* The largest OpenAI model is text-davinci-003.
@@ -62,7 +87,7 @@ public Builder setModel(String model) {
}
/**
- * Setter for prompt.
+ * Sets the prompt.
* @param prompt text of the required action or the question.
* @return instance of Builder.
*/
@@ -72,7 +97,7 @@ public Builder setPrompt(String prompt) {
}
/**
- * Setter for temperature.
+ * Sets the temperature.
* @param temperature higher values means more risks and creativity.
* @return instance of Builder.
*/
@@ -82,7 +107,7 @@ public Builder setTemperature(float temperature) {
}
/**
- * Setter for maxTokens
+ * Sets the maxTokens.
* @param maxTokens maximum size of the model input and output.
* @return instance of Builder
*/
@@ -90,6 +115,22 @@ public Builder setMaxTokens(int maxTokens) {
this.maxTokens = maxTokens;
return this;
}
+
+ /**
+ * Sets the numberOfOutputs
+ * @param numberOfOutputs number of model outputs, default value is 1.
+ *
+ * Cohere maximum value is five.
+ *
+ * @return instance of Builder
+ */
+ public Builder setNumberOfOutputs(int numberOfOutputs) {
+ if (this.numberOfOutputs < 0)
+ this.numberOfOutputs = 0;
+
+ this.numberOfOutputs = numberOfOutputs;
+ return this;
+ }
/**
* Build the final LanguageModelInput object.
@@ -100,7 +141,7 @@ public LanguageModelInput build() {
}
}
/**
- * Getter for model.
+ * Gets the model.
* @return model
*/
public String getModel() {
@@ -108,7 +149,7 @@ public String getModel() {
}
/**
- * Getter for prompt.
+ * Gets the prompt.
* @return prompt
*/
public String getPrompt() {
@@ -116,7 +157,7 @@ public String getPrompt() {
}
/**
- * Getter for temperature.
+ * Gets the temperature.
* @return temperature
*/
public float getTemperature() {
@@ -124,11 +165,67 @@ public float getTemperature() {
}
/**
- * Getter for maxTokens.
+ * Gets the maxTokens.
* @return maxTokens
*/
public int getMaxTokens() {
return maxTokens;
}
+
+ /**
+ * Gets the number of model outputs.
+ * @return numberOfOutputs
+ */
+ public int getNumberOfOutputs() {
+ return numberOfOutputs;
+ }
+
+ /**
+ * Sets the model.
+ *
+ * @param model
+ */
+ public void setModel(String model) {
+ this.model = model;
+ }
+
+
+ /**
+ * Sets the prompt.
+ *
+ * @param prompt
+ */
+ public void setPrompt(String prompt) {
+ this.prompt = prompt;
+ }
+
+
+ /**
+ * Sets the temperature.
+ *
+ * @param temperature higher values means more risks and creativity.
+ */
+ public void setTemperature(float temperature) {
+ this.temperature = temperature;
+ }
+
+ /**
+ * Sets the maxTokens.
+ *
+ * @param maxTokens maximum size of the model input and output.
+ */
+ public void setMaxTokens(int maxTokens) {
+ this.maxTokens = maxTokens;
+ }
+
+ /**
+ * Sets the numberOfOutputs.
+ *
+ * @param numberOfOutputs number of model outputs, default value is 1.
+ */
+ public void setNumberOfOutputs(int numberOfOutputs) {
+ this.numberOfOutputs = numberOfOutputs;
+ }
+
}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/Text2SpeechInput.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/Text2SpeechInput.java
new file mode 100644
index 0000000..20e75b1
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/model/input/Text2SpeechInput.java
@@ -0,0 +1,137 @@
+package com.intellijava.core.model.input;
+
+/**
+ * SpeechTextInput class represents the speech input with the provided text and gender.
+ *
+ * It also provides a Builder to create an instance with optional fields.
+ *
+ * @author github.com/Barqawiz
+ *
+ */
+public class Text2SpeechInput {
+
+ /**
+ * The text of the speech input.
+ */
+ private String text;
+
+ /**
+ * The gender of the speech input.
+ */
+ private Gender gender;
+
+ /**
+ * Constructor to create a new SpeechInput object with provided text and gender.
+ *
+ * @param text the text of the speech input.
+ * @param gender the gender of the speech input.
+ */
+ public Text2SpeechInput(String text, Gender gender) {
+ this.text = text;
+ this.gender = gender;
+ }
+
+ /**
+ * Constructor that creates a new SpeechInput object with a Builder.
+ *
+ * @param builder a Builder to create an instance of SpeechInput with optional fields.
+ */
+ private Text2SpeechInput(Builder builder) {
+ this.text = builder.text;
+ this.gender = builder.gender;
+ }
+
+ /**
+ * Builder class to create an instance of SpeechInput with optional fields.
+ */
+ public static class Builder {
+
+ /**
+ * The text of the speech input.
+ */
+ private String text;
+
+ /**
+ * The gender of the speech input.
+ * Default is FEMALE.
+ */
+ private Gender gender = Gender.FEMALE;
+
+ /**
+ * Constructor that creates a new Builder object with the provided text.
+ *
+ * @param text the text of the speech input.
+ */
+ public Builder(String text) {
+ this.text = text;
+ }
+
+ /**
+ * Setter for speech input text.
+ *
+ * @param text the text of the speech input.
+ * @return the current instance of the Builder.
+ */
+ public Builder setText(String text) {
+ this.text = text;
+ return this;
+ }
+
+ /**
+ * Setter for the speech input gender.
+ * @param gender the gender of the speech input.
+ * @return the current instance of the Builder.
+ */
+ public Builder setGender(Gender gender) {
+ this.gender = gender;
+ return this;
+ }
+
+ /**
+ * Build a new instance of SpeechInput with the values set in the Builder.
+ * @return a new instance of SpeechInput.
+ */
+ public Text2SpeechInput build() {
+ return new Text2SpeechInput(this);
+ }
+ }
+
+ /**
+ * Getter for speech text.
+ * @return the text of the speech input.
+ */
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Getter for the speech gender.
+ * @return the gender of the speech input.
+ */
+ public Gender getGender() {
+ return gender;
+ }
+
+ /**
+ * Setter for the speech text.
+ * @param text the text of the speech input.
+ */
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ /**
+ * Setter for the speech gender.
+ * @param gender the gender of the speech input.
+ */
+ public void setGender(Gender gender) {
+ this.gender = gender;
+ }
+
+ /**
+ * Enum for the speech input gender.
+ */
+ public enum Gender {
+ /** female voice */FEMALE, /** male voice */MALE;
+ }
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/utils/AudioHelper.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/utils/AudioHelper.java
new file mode 100644
index 0000000..f8cf2fa
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/utils/AudioHelper.java
@@ -0,0 +1,92 @@
+package com.intellijava.core.utils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Base64;
+
+/**
+ *
+ * AudioHelper is a class to process and test the generated audio from speech synthesis models.
+ *
+ * It is recommended to play the generated audio using a suitable java third-party audio library
+ * and use this class only to decode the base64 model output.
+ *
+ * @author github.com/Barqawiz
+ */
+public class AudioHelper {
+
+ private static String fileTempAudio = "temp/audio.mp3";
+
+ /**
+ * global AudioHelper variable to print the logs.
+ */
+ public static boolean isLog = true;
+
+ /**
+ * Default AudioHelper constructor.
+ */
+ public AudioHelper() {}
+
+ /**
+ *
+ * decode base64 audio string and convert to audio byte array.
+ *
+ * @param audioContent based64 format audio.
+ * @return audio byte array
+ */
+ public static byte[] decode(String audioContent) {
+ return Base64.getDecoder().decode(audioContent);
+ }
+
+ /**
+ *
+ * update the global location to save temporary audio files.
+ *
+ * @param fileTempAudio file path and name.
+ * @return status true or false.
+ */
+ public static boolean updateGlobalTempLocation(String fileTempAudio) {
+ boolean res = false;
+ if (fileTempAudio.endsWith(".mp3") || fileTempAudio.endsWith(".wav")) {
+ AudioHelper.fileTempAudio = fileTempAudio;
+ res = true;
+ } else if (isLog){
+ System.out.print("Unsupported audio format, send mp3 or wav");
+ }
+
+ return res;
+
+ }
+
+ /**
+ * save temporary audio files.
+ *
+ * This function created for testing purposes, it is recommended to use third party libraries for audio processing.
+ *
+ * @param decodedAudio audio byte format.
+ * @return saving status
+ */
+ public static boolean saveTempAudio(byte[] decodedAudio) {
+ boolean res = true;
+ try (FileOutputStream fos = new FileOutputStream(fileTempAudio)) {
+ fos.write(decodedAudio);
+ } catch (IOException e) {
+ res = false;
+ if (isLog) e.printStackTrace();
+ }
+ return res;
+ }
+
+ /**
+ * clean the temporary audio files.
+ */
+ public static void deleteTempAudio() {
+
+ File file = new File(fileTempAudio);
+ if (file.exists()) {
+ file.delete();
+ }
+
+ }
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/utils/ConnHelper.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/utils/ConnHelper.java
index 522d1a1..ce72beb 100644
--- a/core/com.intellijava.core/src/main/java/com/intellijava/core/utils/ConnHelper.java
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/utils/ConnHelper.java
@@ -108,5 +108,5 @@ public static String readStream(InputStream stream) throws IOException {
}
}
return result.toString();
- }
+ }
}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/CohereAIWrapper.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/CohereAIWrapper.java
index 9ca36fb..f9782fe 100644
--- a/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/CohereAIWrapper.java
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/CohereAIWrapper.java
@@ -15,6 +15,7 @@
/**
*
+ * Wrapper for the Cohere API models.
*
* @author github.com/Barqawiz
*
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/GoogleAIWrapper.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/GoogleAIWrapper.java
new file mode 100644
index 0000000..133f452
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/GoogleAIWrapper.java
@@ -0,0 +1,120 @@
+/**
+ * Copyright 2023 Github.com/Barqawiz/IntelliJava
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellijava.core.wrappers;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Map;
+import java.util.Scanner;
+import com.intellijava.core.model.AudioResponse;
+import com.intellijava.core.model.BaseRemoteModel;
+import com.intellijava.core.utils.Config2;
+import com.intellijava.core.utils.ConnHelper;
+import java.nio.charset.StandardCharsets;
+
+/**
+ *
+ * Wrapper for Google speech services.
+ *
+ * To use this wrapper:
+ * 1- Go to console.cloud.google.com.
+ * 2- Enable "Cloud Text-to-Speech API" from APIs Services.
+ * 3- Generate API key from APIs and services Credentials page.
+ *
+ * @author github.com/Barqawiz
+ *
+ */
+public class GoogleAIWrapper implements SpeechModelInterface {
+
+ private final String API_SPEECH_URL;
+ private String API_KEY;
+
+ /**
+ * Constructs a new GoogleAIWrapper object with the API key.
+ *
+ * @param apiKey the key generated from google console Credentials page
+ */
+ public GoogleAIWrapper(String apiKey) {
+ this.API_KEY = apiKey;
+ this.API_SPEECH_URL = Config2.getInstance().getProperty("url.google.base").
+ toString().replace("{1}",
+ Config2.getInstance().getProperty("url.google.speech.prefix"));
+ }
+
+ /**
+ * Generates speech from text using the Google speech service.
+ *
+ * @param params speech model input parameters.
+ * @return BaseRemoteModel
+ * @throws IOException in case of communication errors.
+ */
+ @Override
+ public BaseRemoteModel generateSpeech(Map params) throws IOException {
+
+ String url = API_SPEECH_URL + Config2.getInstance().getProperty("url.google.synthesize.postfix");
+ String json = getSynthesizeInput(params);
+
+ HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
+ connection.setRequestMethod("POST");
+ connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
+ connection.setRequestProperty("X-Goog-Api-Key", API_KEY);
+ connection.setDoOutput(true);
+
+ try (OutputStream outputStream = connection.getOutputStream()) {
+ outputStream.write(json.getBytes(StandardCharsets.UTF_8));
+ }
+
+ if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
+ String errorMessage = ConnHelper.getErrorMessage(connection);
+ throw new IOException(errorMessage);
+ }
+
+ // get the response and convert to model
+ AudioResponse resModel = ConnHelper.convertSteamToModel(connection.getInputStream(), AudioResponse.class);
+
+ return resModel;
+ }
+
+ /**
+ *
+ * Prepare the synthesize service input.
+ *
+ * @param params
+ * @return String
+ * @throws IOException
+ */
+ private String getSynthesizeInput(Map params) throws IOException {
+ String modelInput = "";
+
+ // read model input template
+ InputStream inputStream = getClass().getClassLoader().getResourceAsStream("google-synthesize-input.txt");
+ Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
+ modelInput = scanner.hasNext() ? scanner.next() : "";
+
+ // fill the details
+ String text = (String) params.get("text");
+ String languageCode = (String) params.get("languageCode");
+ String name = (String) params.get("name");
+ String ssmlGender = (String) params.get("ssmlGender");
+
+ modelInput = String.format(modelInput, text, languageCode, name, ssmlGender);
+
+ return modelInput;
+ }
+}
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/OpenAIWrapper.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/OpenAIWrapper.java
index eb5eb4d..bb3876d 100644
--- a/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/OpenAIWrapper.java
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/OpenAIWrapper.java
@@ -15,18 +15,15 @@
*/
package com.intellijava.core.wrappers;
+
import java.io.IOException;
-import java.io.InputStreamReader;
import java.io.OutputStream;
-import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
import java.util.Map;
-
-import com.google.gson.Gson;
import com.intellijava.core.model.BaseRemoteModel;
+import com.intellijava.core.model.OpenaiChatResponse;
import com.intellijava.core.model.OpenaiImageResponse;
import com.intellijava.core.model.OpenaiLanguageResponse;
import com.intellijava.core.utils.Config2;
@@ -58,10 +55,13 @@ public OpenAIWrapper(String apiKey) {
* Generate text from remote large language model based on the received prompt.
*
* @param params key and value for the API parameters
- * model the model name, example: text-davinci-002. For more details about GPT3 models: https://beta.openai.com/docs/models/gpt-3
+ * model the model name, example: text-davinci-002.
* prompt text of the required action or the question.
* temperature higher values means more risks and creativity.
* maxTokens maximum size of the model input and output.
+ *
+ * For more GPT3 models: https://beta.openai.com/docs/models/gpt-3
+ *
* @return BaseRemoteModel for model response
* @throws IOException if there is an error when connecting to the OpenAI API.
*/
@@ -70,7 +70,7 @@ public BaseRemoteModel generateText(Map params) throws IOExcepti
String url = API_BASE_URL + Config2.getInstance().getProperty("url.openai.completions");
String json = ConnHelper.convertMaptToJson(params);
-
+
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
@@ -91,6 +91,47 @@ public BaseRemoteModel generateText(Map params) throws IOExcepti
return resModel;
}
+ /**
+ *
+ * Generate text from remote large language model based on the chat history.
+ *
+ * @param params key and value for the API parameters
+ * model the model name, example: gpt-3.5-turbo.
+ * messages a dictionary of role and prompt.
+ * temperature higher values means more risks and creativity.
+ * maxTokens maximum size of the model input and output.
+ *
+ * For more GPT3 models: https://beta.openai.com/docs/models/gpt-3
+ *
+ * @return BaseRemoteModel for model response
+ * @throws IOException if there is an error when connecting to the OpenAI API.
+ */
+ public BaseRemoteModel generateChatText(Map params) throws IOException {
+
+ String url = API_BASE_URL + Config2.getInstance().getProperty("url.openai.chatgpt");
+
+ String json = ConnHelper.convertMaptToJson(params);
+
+ HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
+ connection.setRequestMethod("POST");
+ connection.setRequestProperty("Content-Type", "application/json");
+ connection.setRequestProperty("Authorization", "Bearer " + API_KEY);
+ connection.setDoOutput(true);
+
+ try (OutputStream outputStream = connection.getOutputStream()) {
+ outputStream.write(json.getBytes(StandardCharsets.UTF_8));
+ }
+
+ if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
+ String errorMessage = ConnHelper.getErrorMessage(connection);
+ throw new IOException(errorMessage);
+ }
+
+ // get the response and convert to model
+ OpenaiChatResponse resModel = ConnHelper.convertSteamToModel(connection.getInputStream(), OpenaiChatResponse.class);
+ return resModel;
+ }
+
/**
*
* Generate image from openai image model.
diff --git a/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/SpeechModelInterface.java b/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/SpeechModelInterface.java
new file mode 100644
index 0000000..48723c8
--- /dev/null
+++ b/core/com.intellijava.core/src/main/java/com/intellijava/core/wrappers/SpeechModelInterface.java
@@ -0,0 +1,24 @@
+package com.intellijava.core.wrappers;
+
+import java.io.IOException;
+import java.util.Map;
+
+import com.intellijava.core.model.BaseRemoteModel;
+
+/**
+ * SpeechModelInterface represent the standard methods for any speech model.
+ *
+ * @author github.com/Barqawiz
+ *
+ */
+public interface SpeechModelInterface {
+
+ /**
+ * Generate speech from text.
+ *
+ * @param params dictionary of speech model inputs.
+ * @return BaseRemoteModel
+ * @throws IOException in case of error.
+ */
+ public BaseRemoteModel generateSpeech(Map params) throws IOException;
+}
diff --git a/core/com.intellijava.core/src/main/resources/config.properties b/core/com.intellijava.core/src/main/resources/config.properties
index 5e0ff7f..9c3324e 100644
--- a/core/com.intellijava.core/src/main/resources/config.properties
+++ b/core/com.intellijava.core/src/main/resources/config.properties
@@ -1,8 +1,13 @@
url.openai.base=https://api.openai.com
url.openai.completions=/v1/completions
+url.openai.chatgpt=/v1/chat/completions
url.openai.imagegenerate=/v1/images/generations
url.openai.testkey=
url.cohere.base=https://api.cohere.ai
url.cohere.completions=/generate
url.cohere.version=2022-12-06
-url.cohere.testkey=
\ No newline at end of file
+url.cohere.testkey=
+url.google.base=https://{1}.googleapis.com/v1/
+url.google.speech.prefix=texttospeech
+url.google.synthesize.postfix=text:synthesize
+url.google.testkey=
\ No newline at end of file
diff --git a/core/com.intellijava.core/src/main/resources/google-synthesize-input.txt b/core/com.intellijava.core/src/main/resources/google-synthesize-input.txt
new file mode 100644
index 0000000..8b99a8f
--- /dev/null
+++ b/core/com.intellijava.core/src/main/resources/google-synthesize-input.txt
@@ -0,0 +1,13 @@
+{
+ "input":{
+ "text":"%s"
+ },
+ "voice":{
+ "languageCode":"%s",
+ "name":"%s",
+ "ssmlGender":"%s"
+ },
+ "audioConfig":{
+ "audioEncoding":"MP3"
+ }
+}
\ No newline at end of file
diff --git a/core/com.intellijava.core/src/test/java/com/intellijava/core/CohereModelConnectionTest.java b/core/com.intellijava.core/src/test/java/com/intellijava/core/CohereModelConnectionTest.java
index e1bbeb4..4e33574 100644
--- a/core/com.intellijava.core/src/test/java/com/intellijava/core/CohereModelConnectionTest.java
+++ b/core/com.intellijava.core/src/test/java/com/intellijava/core/CohereModelConnectionTest.java
@@ -15,6 +15,10 @@
import com.intellijava.core.utils.Config2;
import com.intellijava.core.wrappers.CohereAIWrapper;
+/**
+ *
+ * Unit test for Remote Language Model
+ */
public class CohereModelConnectionTest {
/**
diff --git a/core/com.intellijava.core/src/test/java/com/intellijava/core/GoogleSpeechTest.java b/core/com.intellijava.core/src/test/java/com/intellijava/core/GoogleSpeechTest.java
new file mode 100644
index 0000000..98a57e8
--- /dev/null
+++ b/core/com.intellijava.core/src/test/java/com/intellijava/core/GoogleSpeechTest.java
@@ -0,0 +1,122 @@
+package com.intellijava.core;
+
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import com.intellijava.core.controller.RemoteSpeechModel;
+import com.intellijava.core.model.AudioResponse;
+import com.intellijava.core.model.SpeechModels;
+import com.intellijava.core.model.input.Text2SpeechInput;
+import com.intellijava.core.model.input.Text2SpeechInput.Gender;
+import com.intellijava.core.utils.AudioHelper;
+import com.intellijava.core.utils.Config2;
+import com.intellijava.core.wrappers.GoogleAIWrapper;
+
+public class GoogleSpeechTest {
+
+ private final String apiKey = Config2.getInstance().getProperty("url.google.testkey");
+
+ @Test
+ public void testAudioConversion() {
+ String audioContent = "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";
+ byte[] decodedAudio = AudioHelper.decode(audioContent);
+ assert AudioHelper.saveTempAudio(decodedAudio) == true;
+ AudioHelper.deleteTempAudio();
+ }
+
+ @Test
+ public void testText2MaleSpeechWrapper() {
+
+ GoogleAIWrapper wrapper = new GoogleAIWrapper(apiKey);
+ try {
+ Map params = new HashMap<>();
+ params.put("text", "Hi, I am Intelligent Java.");
+ params.put("languageCode", "en-gb");
+ params.put("name", "en-GB-Standard-B");
+ params.put("ssmlGender", "MALE");
+
+ AudioResponse resModel = (AudioResponse) wrapper.generateSpeech(params);
+ assert resModel.getAudioContent().length() > 0;
+
+ byte[] decodedAudio = AudioHelper.decode(resModel.getAudioContent());
+ assert AudioHelper.saveTempAudio(decodedAudio) == true;
+ AudioHelper.deleteTempAudio();
+ } catch (IOException e) {
+ if (apiKey.isBlank()) {
+ System.out.print("testAudioWrapper set the API key to run the test case.");
+ } else {
+ fail("testAudioWrapper failed with exception: " + e.getMessage());
+ }
+ }
+ }
+
+ @Test
+ public void testText2FemaleSpeechWrapper() {
+
+ GoogleAIWrapper wrapper = new GoogleAIWrapper(apiKey);
+ try {
+ Map params = new HashMap<>();
+ params.put("text", "Hi, I am Intelligent Java.");
+ params.put("languageCode", "en-gb");
+ params.put("name", "en-GB-Standard-A");
+ params.put("ssmlGender", "FEMALE");
+
+ AudioResponse resModel = (AudioResponse) wrapper.generateSpeech(params);
+ assert resModel.getAudioContent().length() > 0;
+
+ byte[] decodedAudio = AudioHelper.decode(resModel.getAudioContent());
+ assert AudioHelper.saveTempAudio(decodedAudio) == true;
+ AudioHelper.deleteTempAudio();
+ } catch (IOException e) {
+ if (apiKey.isBlank()) {
+ System.out.print("testAudioWrapper set the API key to run the test case.");
+ } else {
+ fail("testAudioWrapper failed with exception: " + e.getMessage());
+ }
+ }
+ }
+
+ @Test
+ public void testText2FemaleRemoteSpeecModel() {
+ Text2SpeechInput input = new Text2SpeechInput.Builder("Hi, I am Intelligent Java.").
+ setGender(Gender.FEMALE).build();
+
+ RemoteSpeechModel model = new RemoteSpeechModel(apiKey, SpeechModels.google);
+
+ try {
+ byte[] decodedAudio = model.generateEnglishText(input);
+ assert AudioHelper.saveTempAudio(decodedAudio) == true;
+ AudioHelper.deleteTempAudio();
+ } catch (IOException e) {
+ if (apiKey.isBlank()) {
+ System.out.print("testRemoteSpeech set the API key to run the test case.");
+ } else {
+ fail("testRemoteSpeech failed with exception: " + e.getMessage());
+ }
+ }
+ }
+
+ @Test
+ public void testText2FemaleRemoteSpeecModel2() {
+ Text2SpeechInput input = new Text2SpeechInput("Hi, I am Intelligent Java.", Gender.MALE);
+
+ RemoteSpeechModel model = new RemoteSpeechModel(apiKey, SpeechModels.google);
+
+ try {
+ byte[] decodedAudio = model.generateEnglishText(input);
+ assert AudioHelper.saveTempAudio(decodedAudio) == true;
+ AudioHelper.deleteTempAudio();
+ } catch (IOException e) {
+ if (apiKey.isBlank()) {
+ System.out.print("testRemoteSpeech set the API key to run the test case.");
+ } else {
+ fail("testRemoteSpeech failed with exception: " + e.getMessage());
+ }
+ }
+ }
+}
diff --git a/core/com.intellijava.core/src/test/java/com/intellijava/core/OpenaiModelConnectionTest.java b/core/com.intellijava.core/src/test/java/com/intellijava/core/OpenaiModelConnectionTest.java
index e18743b..5864dbb 100644
--- a/core/com.intellijava.core/src/test/java/com/intellijava/core/OpenaiModelConnectionTest.java
+++ b/core/com.intellijava.core/src/test/java/com/intellijava/core/OpenaiModelConnectionTest.java
@@ -23,12 +23,19 @@
import java.util.List;
import java.util.Map;
import org.junit.Test;
-import com.intellijava.core.controller.RemoateImageModel;
+import com.intellijava.core.controller.RemoteImageModel;
import com.intellijava.core.controller.RemoteLanguageModel;
+import com.intellijava.core.function.Chatbot;
import com.intellijava.core.model.OpenaiImageResponse;
import com.intellijava.core.model.OpenaiImageResponse.Data;
+import com.intellijava.core.model.SupportedChatModels;
+import com.intellijava.core.model.SupportedLangModels;
+import com.intellijava.core.model.input.ChatGPTInput;
+import com.intellijava.core.model.input.ChatGPTMessage;
+import com.intellijava.core.model.input.ChatModelInput;
import com.intellijava.core.model.input.ImageModelInput;
import com.intellijava.core.model.input.LanguageModelInput;
+import com.intellijava.core.model.input.ChatGPTMessage.Role;
import com.intellijava.core.utils.Config2;
import com.intellijava.core.wrappers.OpenAIWrapper;
@@ -51,10 +58,10 @@ public void testOpenaiCompletionRemoteModel() {
try {
- RemoteLanguageModel wrapper = new RemoteLanguageModel(openaiKey, "openai");
+ RemoteLanguageModel wrapper = new RemoteLanguageModel(openaiKey, SupportedLangModels.openai);
LanguageModelInput input = new LanguageModelInput.Builder("return a java code that print hello world")
- .setModel("text-davinci-002").setTemperature(0.7f).setMaxTokens(50).build();
+ .setModel("text-davinci-003").setTemperature(0.7f).setMaxTokens(50).build();
if (openaiKey.isBlank()) return;
@@ -75,6 +82,37 @@ public void testOpenaiCompletionRemoteModel() {
}
}
+
+ @Test
+ public void testOpenaiMultiTextCompletionRemoteModel() {
+
+ try {
+
+ RemoteLanguageModel wrapper = new RemoteLanguageModel(openaiKey, "openai");
+
+ LanguageModelInput input = new LanguageModelInput.Builder("Summarize the plot of the 'Inception' movie in two sentences")
+ .setModel("text-davinci-003").setTemperature(0.7f)
+ .setMaxTokens(80).setNumberOfOutputs(2).build();
+
+ if (openaiKey.isBlank()) return;
+
+ List resValues = wrapper.generateMultiText(input);
+
+ for (String result : resValues)
+ System.out.print("- " + result);
+
+ assert resValues.size() == 2;
+
+ } catch (IOException e) {
+ if (openaiKey.isBlank()) {
+ System.out.print("testOpenaiCompletion: set the API key to run the test case.");
+ } else {
+ fail("Test case failed with exception: " + e.getMessage());
+ }
+
+ }
+ }
+
@Test
public void testImageWrapper() {
@@ -115,14 +153,14 @@ public void testImageWrapper() {
}
@Test
- public void testOpenaiImageRemoteModel() {
+ public void testOpenaiImageRemoteModel() {
// prepare the input parameters
String prompt = "teddy writing a blog in times square";
try {
- RemoateImageModel wrapper = new RemoateImageModel(openaiKey, "openai");
+ RemoteImageModel wrapper = new RemoteImageModel(openaiKey, "openai");
ImageModelInput input = new ImageModelInput.Builder(prompt)
.setNumberOfImages(2).setImageSize("1024x1024").build();
@@ -146,4 +184,56 @@ public void testOpenaiImageRemoteModel() {
}
}
+
+ @Test
+ public void testOpenaiChatGPTCase1() {
+
+ Chatbot bot = new Chatbot(openaiKey, SupportedChatModels.openai);
+ String mode = "You are a helpful astronomy assistant.";
+ ChatModelInput input = new ChatGPTInput.Builder(mode)
+ .addUserMessage("what is the space between moon and earth").build();
+ try {
+
+ List resValues = bot.chat(input);
+
+ for (String result : resValues)
+ System.out.print("- " + result);
+
+ } catch (IOException e) {
+ if (openaiKey.isBlank()) {
+ System.out.print("set the API key to run the test case.");
+ } else {
+ fail("Test case failed with exception: " + e.getMessage());
+ }
+ }
+
+ }
+
+ @Test
+ public void testOpenaiChatGPTCase2() {
+
+ Chatbot bot = new Chatbot(openaiKey, SupportedChatModels.openai);
+ String mode = "You are a helpful assistant.";
+ ChatModelInput input = new ChatGPTInput.Builder(mode)
+ .addMessage(new ChatGPTMessage("Who won the world series in 2020?", Role.user))
+ .addMessage(new ChatGPTMessage("The Los Angeles Dodgers won the World Series in 2020.", Role.assistant))
+ .addMessage(new ChatGPTMessage("Where was it played?", Role.user))
+ .setNumberOfOutputs(2)
+ .build();
+ try {
+
+ List resValues = bot.chat(input);
+
+ for (String result : resValues)
+ System.out.println("- " + result);
+
+ } catch (IOException e) {
+ if (openaiKey.isBlank()) {
+ System.out.print("set the API key to run the test case.");
+ } else {
+ fail("Test case failed with exception: " + e.getMessage());
+ }
+ }
+
+ }
}
diff --git a/core/com.intellijava.core/target/classes/config.properties b/core/com.intellijava.core/target/classes/config.properties
deleted file mode 100644
index 5e0ff7f..0000000
--- a/core/com.intellijava.core/target/classes/config.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-url.openai.base=https://api.openai.com
-url.openai.completions=/v1/completions
-url.openai.imagegenerate=/v1/images/generations
-url.openai.testkey=
-url.cohere.base=https://api.cohere.ai
-url.cohere.completions=/generate
-url.cohere.version=2022-12-06
-url.cohere.testkey=
\ No newline at end of file
diff --git a/core/com.intellijava.core/temp/icon.png b/core/com.intellijava.core/temp/icon.png
new file mode 100644
index 0000000..a13a985
Binary files /dev/null and b/core/com.intellijava.core/temp/icon.png differ
diff --git a/images/intelligent_java_header.png b/images/intelligent_java_header.png
new file mode 100644
index 0000000..baf29b2
Binary files /dev/null and b/images/intelligent_java_header.png differ
diff --git a/images/intelligent_java_header_footer.png b/images/intelligent_java_header_footer.png
new file mode 100644
index 0000000..2d27ac6
Binary files /dev/null and b/images/intelligent_java_header_footer.png differ
diff --git a/images/intelligent_java_icon.png b/images/intelligent_java_icon.png
new file mode 100644
index 0000000..5a4e62a
Binary files /dev/null and b/images/intelligent_java_icon.png differ
diff --git a/sample_code/.classpath b/sample_code/.classpath
index 1ff9255..8a7476c 100644
--- a/sample_code/.classpath
+++ b/sample_code/.classpath
@@ -7,7 +7,7 @@
-
-
+
+
diff --git a/sample_code/jars/gson-2.10.1.jar b/sample_code/jars/gson-2.10.1.jar
new file mode 100644
index 0000000..a88c5bd
Binary files /dev/null and b/sample_code/jars/gson-2.10.1.jar differ
diff --git a/sample_code/jars/gson-2.8.9.jar b/sample_code/jars/gson-2.8.9.jar
deleted file mode 100644
index 3351867..0000000
Binary files a/sample_code/jars/gson-2.8.9.jar and /dev/null differ
diff --git a/sample_code/jars/intellijava.core-0.6.0.jar b/sample_code/jars/intellijava.core-0.6.0.jar
deleted file mode 100644
index 2525d3c..0000000
Binary files a/sample_code/jars/intellijava.core-0.6.0.jar and /dev/null differ
diff --git a/sample_code/jars/intellijava.core-0.8.1.jar b/sample_code/jars/intellijava.core-0.8.1.jar
new file mode 100644
index 0000000..560fde0
Binary files /dev/null and b/sample_code/jars/intellijava.core-0.8.1.jar differ
diff --git a/sample_code/src/com/intelliJava/test/ChatGPTApp.java b/sample_code/src/com/intelliJava/test/ChatGPTApp.java
new file mode 100644
index 0000000..f440b62
--- /dev/null
+++ b/sample_code/src/com/intelliJava/test/ChatGPTApp.java
@@ -0,0 +1,74 @@
+package com.intelliJava.test;
+
+import java.io.IOException;
+import java.util.List;
+
+import com.intellijava.core.function.Chatbot;
+import com.intellijava.core.model.SupportedChatModels;
+import com.intellijava.core.model.input.ChatGPTInput;
+import com.intellijava.core.model.input.ChatGPTMessage;
+import com.intellijava.core.model.input.ChatModelInput;
+import com.intellijava.core.model.input.ChatGPTMessage.Role;
+
+public class ChatGPTApp {
+
+ public static void main(String[] args) {
+
+ System.out.println("Start calling the chat!");
+
+ // get the api key from https://openai.com/api/
+ // TODO: replace with your API key.
+ String apiKey = "";
+
+
+ try {
+
+ System.out.println("Try ChatGPT with one message:");
+ simpleChat(apiKey);
+
+ System.out.println("\n");
+
+ System.out.println("Try ChatGPT with history chat and multi outputs:");
+ historyChat(apiKey);
+
+ } catch (IOException e) {
+
+ e.printStackTrace();
+ }
+
+
+ }
+
+ private static void simpleChat(String apiKey) throws IOException {
+
+ Chatbot bot = new Chatbot(apiKey, SupportedChatModels.openai);
+ String mode = "You are a helpful astronomy assistant.";
+
+ ChatModelInput input = new ChatGPTInput.Builder(mode)
+ .addUserMessage("what is the space between moon and earth")
+ .build();
+
+ List resValues = bot.chat(input);
+
+ for (String result : resValues)
+ System.out.println("- " + result);
+
+ }
+
+ private static void historyChat(String apiKey) throws IOException {
+
+ Chatbot bot = new Chatbot(apiKey, SupportedChatModels.openai);
+ String mode = "You are a helpful assistant.";
+ ChatModelInput input = new ChatGPTInput.Builder(mode)
+ .addMessage(new ChatGPTMessage("Who won the world series in 2020?", Role.user))
+ .addMessage(new ChatGPTMessage("The Los Angeles Dodgers won the World Series in 2020.", Role.assistant))
+ .addMessage(new ChatGPTMessage("Where was it played?", Role.user))
+ .setNumberOfOutputs(2)
+ .build();
+
+ List resValues = bot.chat(input);
+
+ for (String result : resValues)
+ System.out.println("- " + result);
+ }
+}
diff --git a/sample_code/src/com/intelliJava/test/GoogleApp.java b/sample_code/src/com/intelliJava/test/GoogleApp.java
new file mode 100644
index 0000000..3e6b8ae
--- /dev/null
+++ b/sample_code/src/com/intelliJava/test/GoogleApp.java
@@ -0,0 +1,89 @@
+package com.intelliJava.test;
+
+
+import java.io.IOException;
+import com.intellijava.core.controller.RemoteSpeechModel;
+import com.intellijava.core.model.SpeechModels;
+import com.intellijava.core.model.input.Text2SpeechInput;
+import com.intellijava.core.model.input.Text2SpeechInput.Gender;
+import com.intellijava.core.utils.AudioHelper;
+
+public class GoogleApp {
+
+ public static void main(String[] args) {
+
+ System.out.println("Start calling the API!");
+
+ // get the api key from https://console.cloud.google.com/
+ // TODO: replace with your API key.
+ String apiKey = "";
+
+ /********************************/
+ /** 1- Call the language model **/
+ /********************************/
+ try {
+
+ tryGoogleSpeechModel(apiKey);
+
+ System.out.print("Check the temp forlder for the generated audio.");
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Generate speech from text using google API.
+ *
+ * To use this model:
+ * 1- Go to console.cloud.google.com.
+ * 2- Enable "Cloud Text-to-Speech API" from APIs Services.
+ * 3- Generate API key from APIs and services Credentials page.
+ *
+ * @param apiKey
+ * @throws IOException
+ */
+ private static void tryGoogleSpeechModel(String apiKey) throws IOException {
+
+
+ RemoteSpeechModel model = new RemoteSpeechModel(apiKey, SpeechModels.google);
+
+ Text2SpeechInput input = new Text2SpeechInput.Builder("Hi, I am Intelligent Java.").build();
+
+ // get the audio bytes
+ // you can play it using libraries like javafx
+ byte[] decodedAudio = model.generateEnglishText(input);
+
+ // save temporary audio file
+ AudioHelper.saveTempAudio(decodedAudio);
+
+ }
+
+ /**
+ * Generate speech from text using google API.
+ *
+ * To use this model:
+ * 1- Go to console.cloud.google.com.
+ * 2- Enable "Cloud Text-to-Speech API" from APIs Services.
+ * 3- Generate API key from APIs and services Credentials page.
+ *
+ * @param apiKey
+ * @throws IOException
+ */
+ private static void tryGermanSpeechModel(String apiKey) throws IOException {
+
+
+ RemoteSpeechModel model = new RemoteSpeechModel(apiKey, SpeechModels.google);
+
+ Text2SpeechInput input = new Text2SpeechInput.Builder("Hallo, ich bin Intelligent Java.").build();
+
+ // get the audio bytes
+ // you can play it using libraries like javafx
+ byte[] decodedAudio = model.generateGermanText(input);
+
+ // save temporary audio file
+ AudioHelper.saveTempAudio(decodedAudio);
+
+ }
+
+}
diff --git a/sample_code/src/com/intelliJava/test/OpenaiApp.java b/sample_code/src/com/intelliJava/test/OpenaiApp.java
index 966d805..7c97444 100644
--- a/sample_code/src/com/intelliJava/test/OpenaiApp.java
+++ b/sample_code/src/com/intelliJava/test/OpenaiApp.java
@@ -17,7 +17,7 @@
import java.io.IOException;
import java.util.List;
-import com.intellijava.core.controller.RemoateImageModel;
+import com.intellijava.core.controller.RemoteImageModel;
import com.intellijava.core.controller.RemoteLanguageModel;
import com.intellijava.core.model.input.ImageModelInput;
import com.intellijava.core.model.input.LanguageModelInput;
@@ -60,20 +60,37 @@ private static void tryTheLanguageModel(String apiKey) throws IOException {
// initiate the remote language model wrapper with openai details
RemoteLanguageModel langModel = new RemoteLanguageModel(apiKey, "openai");
- // prepare the input parameters - change the prompt to any text like "write a
- // funny short story"
- LanguageModelInput langInput = new LanguageModelInput.Builder("return a java code that says hello world")
- .setModel("text-davinci-002").setTemperature(0.7f).setMaxTokens(50).build();
+ // prepare the input parameters - change the prompt to any text
+ LanguageModelInput langInput = new LanguageModelInput.Builder("Summarize the plot of the 'Inception' movie in two sentences")
+ .setModel("text-davinci-003").setTemperature(0.7f).setMaxTokens(80).build();
+
String resValue = langModel.generateText(langInput);
// print language model output
System.out.println("Language model output:\n" + resValue);
}
+
+ private static void tryTheLanguageModelMultiText(String apiKey) throws IOException {
+ // initiate the remote language model wrapper with openai details
+ RemoteLanguageModel langModel = new RemoteLanguageModel(apiKey, "openai");
+
+ // prepare the input parameters - change the prompt to any text
+ LanguageModelInput langInput = new LanguageModelInput.Builder("Summarize the plot of the 'Inception' movie in two sentences")
+ .setModel("text-davinci-003").setTemperature(0.7f)
+ .setMaxTokens(80).setNumberOfOutputs(2).build();
+
+
+ List resValues = langModel.generateMultiText(langInput);
+
+ // print language model output
+ for (String result : resValues)
+ System.out.print("- " + result);
+ }
private static void tryTheImageModel(String apiKey) throws IOException {
// initiate the remote image model wrapper
- RemoateImageModel imageModel = new RemoateImageModel(apiKey, "openai");
+ RemoteImageModel imageModel = new RemoteImageModel(apiKey, "openai");
// prepare the input parameters
ImageModelInput imageInput = new ImageModelInput.Builder("teddy writing a blog in times square")
diff --git a/sample_code/temp/audio.mp3 b/sample_code/temp/audio.mp3
new file mode 100644
index 0000000..9e74970
Binary files /dev/null and b/sample_code/temp/audio.mp3 differ