Compare commits

..

No commits in common. "c60531f6170ed701ac742986cb8c5e13a6b823ea" and "3cbe44c1c08c6f317d1ddabc07adee8eedb5cfc6" have entirely different histories.

20 changed files with 177 additions and 116 deletions

1
.gitignore vendored
View file

@ -60,4 +60,3 @@ local.properties
logs
mobibot.properties
out
/target/

View file

@ -2,12 +2,12 @@
<library name="bld">
<CLASSES>
<root url="file://$PROJECT_DIR$/lib/bld" />
<root url="jar://$USER_HOME$/.bld/dist/bld-2.1.0.jar!/" />
<root url="jar://$USER_HOME$/.bld/dist/bld-2.0.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$PROJECT_DIR$/lib/bld" />
<root url="jar://$USER_HOME$/.bld/dist/bld-2.1.0-sources.jar!/" />
<root url="jar://$USER_HOME$/.bld/dist/bld-2.0.1-sources.jar!/" />
</SOURCES>
<excluded>
<root url="jar://$PROJECT_DIR$/lib/bld/bld-wrapper.jar!/" />

View file

@ -7,7 +7,7 @@
<SOURCES>
<root url="file://$PROJECT_DIR$/lib/compile" />
</SOURCES>
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="true" />
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="true" type="SOURCES" />
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="false" />
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="false" type="SOURCES" />
</library>
</component>

View file

@ -8,7 +8,7 @@
<SOURCES>
<root url="file://$PROJECT_DIR$/lib/runtime" />
</SOURCES>
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="true" />
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="true" type="SOURCES" />
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="false" />
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="false" type="SOURCES" />
</library>
</component>

View file

@ -8,7 +8,7 @@
<SOURCES>
<root url="file://$PROJECT_DIR$/lib/test" />
</SOURCES>
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="true" />
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="true" type="SOURCES" />
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="false" />
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="false" type="SOURCES" />
</library>
</component>

View file

@ -1,8 +1,8 @@
# mobibot
[![License (3-Clause BSD)](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
[![Kotlin](https://img.shields.io/badge/kotlin-2.0.20-7f52ff.svg)](https://kotlinlang.org)
[![bld](https://img.shields.io/badge/2.1.0-FA9052?label=bld&labelColor=2392FF)](https://rife2.com/bld)
[![Kotlin](https://img.shields.io/badge/kotlin-2.0.10-7f52ff.svg)](https://kotlinlang.org)
[![bld](https://img.shields.io/badge/2.0.1-FA9052?label=bld&labelColor=2392FF)](https://rife2.com/bld)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=ethauvin_mobibot&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=ethauvin_mobibot)
[![GitHub CI](https://github.com/ethauvin/mobibot/actions/workflows/bld.yml/badge.svg)](https://github.com/ethauvin/mobibot/actions/workflows/bld.yml)
[![CircleCI](https://circleci.com/gh/ethauvin/mobibot/tree/master.svg?style=shield)](https://circleci.com/gh/ethauvin/mobibot/tree/master)

View file

@ -71,6 +71,9 @@
<ID>ReturnCount:Addons.kt$Addons$fun help(channel: String, topic: String, event: GenericMessageEvent): Boolean</ID>
<ID>ReturnCount:ExceptionSanitizer.kt$ExceptionSanitizer$fun ModuleException.sanitize(vararg sanitize: String): ModuleException</ID>
<ID>ReturnCount:Seen.kt$Seen$override fun commandResponse(channel: String, args: String, event: GenericMessageEvent)</ID>
<ID>SwallowedException:GoogleSearchTest.kt$GoogleSearchTest$e: ModuleException</ID>
<ID>SwallowedException:StockQuoteTest.kt$StockQuoteTest$e: ModuleException</ID>
<ID>SwallowedException:WolframAlphaTest.kt$WolframAlphaTest$e: ModuleException</ID>
<ID>ThrowsCount:ChatGpt.kt$ChatGpt.Companion$@JvmStatic @Throws(ModuleException::class) fun chat(query: String, apiKey: String?, maxTokens: Int): String</ID>
<ID>ThrowsCount:GoogleSearch.kt$GoogleSearch.Companion$@JvmStatic @Throws(ModuleException::class) fun searchGoogle( query: String, apiKey: String?, cseKey: String?, quotaUser: String = ReleaseInfo.PROJECT ): List&lt;Message&gt;</ID>
<ID>ThrowsCount:Joke.kt$Joke.Companion$@JvmStatic @Throws(ModuleException::class) fun randomJoke(): List&lt;Message&gt;</ID>
@ -79,9 +82,7 @@
<ID>ThrowsCount:StockQuote.kt$StockQuote.Companion$@Throws(ModuleException::class) private fun getJsonResponse(response: String, debugMessage: String): JSONObject</ID>
<ID>ThrowsCount:Weather2.kt$Weather2.Companion$@JvmStatic @Throws(ModuleException::class) fun getWeather(query: String, apiKey: String?): List&lt;Message&gt;</ID>
<ID>ThrowsCount:WolframAlpha.kt$WolframAlpha.Companion$@JvmStatic @Throws(ModuleException::class) fun queryWolfram(query: String, units: String = IMPERIAL, appId: String?): String</ID>
<ID>TooGenericExceptionCaught:ChatGpt2.kt$ChatGpt2.Companion$e: Exception</ID>
<ID>TooGenericExceptionCaught:Gemini.kt$Gemini.Companion$e: Exception</ID>
<ID>TooGenericExceptionCaught:Gemini2.kt$Gemini2.Companion$e: Exception</ID>
<ID>TooGenericExceptionCaught:StockQuote.kt$StockQuote.Companion$e: NullPointerException</ID>
<ID>TooGenericExceptionCaught:Weather2.kt$Weather2.Companion$e: NullPointerException</ID>
<ID>TooManyFunctions:EntryLink.kt$EntryLink : Serializable</ID>
@ -93,7 +94,6 @@
<ID>WildcardImport:FeedMgrTest.kt$import assertk.assertions.*</ID>
<ID>WildcardImport:FeedReaderTest.kt$import assertk.assertions.*</ID>
<ID>WildcardImport:FeedsManager.kt$import com.rometools.rome.feed.synd.*</ID>
<ID>WildcardImport:Gemini2Test.kt$import assertk.assertions.*</ID>
<ID>WildcardImport:GeminiTest.kt$import assertk.assertions.*</ID>
<ID>WildcardImport:GoogleSearchTest.kt$import assertk.assertions.*</ID>
<ID>WildcardImport:JokeTest.kt$import assertk.assertions.*</ID>

Binary file not shown.

View file

@ -1,10 +1,10 @@
bld.downloadExtensionJavadoc=false
bld.downloadExtensionSources=true
bld.downloadLocation=
bld.extension-detekt=com.uwyn.rife2:bld-detekt:0.9.7
bld.extension-gv=com.uwyn.rife2:bld-generated-version:0.9.9
bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.8
bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.0.1
bld.extension-detekt=com.uwyn.rife2:bld-detekt:0.9.5
bld.extension-gv=com.uwyn.rife2:bld-generated-version:0.9.8
bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.7
bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.0.0
bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES
bld.sourceDirectories=
bld.version=2.1.0
bld.version=2.0.1

50
pom.xml
View file

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>net.thauvin.erik.mobibot</groupId>
<artifactId>mobibot</artifactId>
<version>0.8.0-rc+20240908192921</version>
<version>0.8.0-rc+20240809180718</version>
<name>mobibot</name>
<description></description>
<url></url>
@ -18,7 +18,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.17.0</version>
<version>3.16.0</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -51,28 +51,34 @@
<version>33.2.1-jre</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-vertexai</artifactId>
<version>1.7.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>2.0.20</version>
<version>2.0.10</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-common</artifactId>
<version>2.0.20</version>
<version>2.0.10</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk7</artifactId>
<version>2.0.20</version>
<version>2.0.10</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>2.0.20</version>
<version>2.0.10</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -90,49 +96,25 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.16</version>
<version>2.0.15</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.24.0</version>
<version>2.23.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.24.0</version>
<version>2.23.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>2.24.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>0.34.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-google-ai-gemini</artifactId>
<version>0.34.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-core</artifactId>
<version>0.34.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>0.34.0</version>
<version>2.23.1</version>
<scope>compile</scope>
</dependency>
<dependency>

View file

@ -45,6 +45,7 @@ disabled-modules=mastodon
# Automatically post links to Mastodon
#mastodon-auto-post=true
#
# Get Exchange Rate API key from: https://www.exchangerate-api.com/
#
@ -74,13 +75,19 @@ disabled-modules=mastodon
#wolfram-units=imperial
#
# Get ChatGPT/OpenAI API key from: https://platform.openai.com/api-keys
# ChatGPT/OpenAI API key from: https://beta.openai.com/account/api-keys
#
#chatgpt-api-key=
#chatgpt-max-tokens=1024
#
# Get Google Gemini API key from https://ai.google.dev/gemini-api/docs/api-key
# Set a Vertex AI Gemini API project in Google Cloud:
# https://cloud.google.com/vertex-ai/docs/generative-ai/start/quickstarts/quickstart-multimodal
# Don't forget to:
# gcloud config set project PROJECT_ID
# gcloud auth login LOGIN
# gcloud auth application-default login
#
#gemini-api-key=
#gemini-project-id=
#gemini-location=us-west1
#gemini-max-tokens=1024

View file

@ -77,20 +77,20 @@ public class MobibotBuild extends Project {
new Repository("https://jitpack.io"),
SONATYPE_SNAPSHOTS_LEGACY);
var log4j = version(2, 24, 0);
var kotlin = version(2, 0, 20);
var langchain = version(0, 34, 0);
var log4j = version(2, 23, 1);
var kotlin = version(2, 0, 10);
scope(compile)
// PircBotX
.include(dependency("com.github.pircbotx", "pircbotx", "2.3.1"))
// Commons (mostly for PircBotX)
.include(dependency("org.apache.commons", "commons-lang3", "3.17.0"))
.include(dependency("org.apache.commons", "commons-lang3", "3.16.0"))
.include(dependency("org.apache.commons", "commons-text", "1.12.0"))
.include(dependency("commons-codec", "commons-codec", "1.17.1"))
.include(dependency("commons-net", "commons-net", "3.11.1"))
// Google
.include(dependency("com.google.code.gson", "gson", "2.11.0"))
.include(dependency("com.google.guava", "guava", "33.2.1-jre"))
.include(dependency("com.google.cloud", "google-cloud-vertexai", "1.7.0"))
// Kotlin
.include(dependency("org.jetbrains.kotlin", "kotlin-stdlib", kotlin))
.include(dependency("org.jetbrains.kotlin", "kotlin-stdlib-common", kotlin))
@ -99,15 +99,10 @@ public class MobibotBuild extends Project {
.include(dependency("org.jetbrains.kotlinx", "kotlinx-coroutines-core", "1.8.1"))
.include(dependency("org.jetbrains.kotlinx", "kotlinx-cli-jvm", "0.3.6"))
// Logging
.include(dependency("org.slf4j", "slf4j-api", "2.0.16"))
.include(dependency("org.slf4j", "slf4j-api", "2.0.15"))
.include(dependency("org.apache.logging.log4j", "log4j-api", log4j))
.include(dependency("org.apache.logging.log4j", "log4j-core", log4j))
.include(dependency("org.apache.logging.log4j", "log4j-slf4j2-impl", log4j))
// LangChain4J
.include(dependency("dev.langchain4j", "langchain4j-open-ai", langchain))
.include(dependency("dev.langchain4j", "langchain4j-google-ai-gemini", langchain))
.include(dependency("dev.langchain4j", "langchain4j-core", langchain))
.include(dependency("dev.langchain4j", "langchain4j", langchain))
// Misc.
.include(dependency("com.rometools", "rome", "2.1.0"))
.include(dependency("com.squareup.okhttp3", "okhttp", "4.12.0"))
@ -123,8 +118,8 @@ public class MobibotBuild extends Project {
scope(test)
.include(dependency("com.willowtreeapps.assertk", "assertk-jvm", version(0, 28, 1)))
.include(dependency("org.jetbrains.kotlin", "kotlin-test-junit5", kotlin))
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 11, 0)))
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 11, 0)));
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 10, 3)))
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 10, 3)));
List<String> jars = new ArrayList<>();
runtimeClasspathJars().forEach(f -> jars.add("./lib/" + f.getName()));

View file

@ -396,11 +396,11 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
// Load the modules
addons.add(Calc())
addons.add(ChatGpt2())
addons.add(ChatGpt())
addons.add(CryptoPrices())
addons.add(CurrencyConverter())
addons.add(Dice())
addons.add(Gemini2())
addons.add(Gemini())
addons.add(GoogleSearch())
addons.add(Info(tell, seen))
addons.add(Joke())

View file

@ -14,12 +14,12 @@ import java.time.ZoneId
*/
object ReleaseInfo {
const val PROJECT = "mobibot"
const val VERSION = "0.8.0-rc+20240908190240"
const val VERSION = "0.8.0-rc+20240712110931"
@JvmField
@Suppress("MagicNumber")
val BUILD_DATE: LocalDateTime = LocalDateTime.ofInstant(
Instant.ofEpochMilli(1725847361020L), ZoneId.systemDefault()
Instant.ofEpochMilli(1720807771484L), ZoneId.systemDefault()
)
const val WEBSITE = "https://mobitopia.org/mobibot/"

View file

@ -31,16 +31,23 @@
package net.thauvin.erik.mobibot.modules
import dev.langchain4j.model.openai.OpenAiChatModel
import dev.langchain4j.model.openai.OpenAiChatModelName
import net.thauvin.erik.mobibot.Constants
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.sendMessage
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import org.pircbotx.hooks.types.GenericMessageEvent
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.IOException
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
class ChatGpt2 : AbstractModule() {
val logger: Logger = LoggerFactory.getLogger(ChatGpt2::class.java)
class ChatGpt : AbstractModule() {
val logger: Logger = LoggerFactory.getLogger(ChatGpt::class.java)
override val name = CHATGPT_NAME
@ -86,6 +93,9 @@ class ChatGpt2 : AbstractModule() {
*/
const val MAX_TOKENS_PROP = "chatgpt-max-tokens"
// ChatGPT API URL
private const val API_URL = "https://api.openai.com/v1/chat/completions"
// ChatGPT command
private const val CHATGPT_CMD = "chatgpt"
@ -93,15 +103,48 @@ class ChatGpt2 : AbstractModule() {
@Throws(ModuleException::class)
fun chat(query: String, apiKey: String?, maxTokens: Int): String {
if (!apiKey.isNullOrEmpty()) {
try {
val model = OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName(OpenAiChatModelName.GPT_4_O)
.maxTokens(maxTokens)
.build()
val jsonObject = JSONObject()
jsonObject.put("model", "gpt-3.5-turbo-1106")
jsonObject.put("max_tokens", maxTokens)
val message = JSONObject()
message.put("role", "user")
message.put("content", query)
val messages = JSONArray()
messages.put(message)
jsonObject.put("messages", messages)
return model.generate(query)
} catch (e: Exception) {
val request = HttpRequest.newBuilder()
.uri(URI.create(API_URL))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer $apiKey")
.header("User-Agent", Constants.USER_AGENT)
.POST(HttpRequest.BodyPublishers.ofString(jsonObject.toString()))
.build()
try {
val response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString())
if (response.statusCode() == 200) {
try {
val jsonResponse = JSONObject(response.body())
val choices = jsonResponse.getJSONArray("choices")
return choices.getJSONObject(0).getJSONObject("message").getString("content").trim()
} catch (e: JSONException) {
throw ModuleException(
"$CHATGPT_CMD($query): JSON",
"A JSON error has occurred while conversing with $CHATGPT_NAME.",
e
)
}
} else {
if (response.statusCode() == 429) {
throw ModuleException(
"$CHATGPT_CMD($query): Rate limit reached",
"Rate limit reached. Please try again later."
)
} else {
throw IOException("HTTP Status Code: " + response.statusCode())
}
}
} catch (e: IOException) {
throw ModuleException(
"$CHATGPT_CMD($query): IO",
"An IO error has occurred while conversing with $CHATGPT_NAME.",

View file

@ -217,6 +217,6 @@ class CurrencyConverter : AbstractModule() {
init {
commands.add(CURRENCY_CMD)
initProperties(API_KEY_PROP)
loadSymbols(properties[ChatGpt2.API_KEY_PROP])
loadSymbols(properties[ChatGpt.API_KEY_PROP])
}
}

View file

@ -31,7 +31,12 @@
package net.thauvin.erik.mobibot.modules
import dev.langchain4j.model.googleai.GoogleAiGeminiChatModel
import com.google.cloud.vertexai.VertexAI
import com.google.cloud.vertexai.api.GenerationConfig
import com.google.cloud.vertexai.api.HarmCategory
import com.google.cloud.vertexai.api.SafetySetting
import com.google.cloud.vertexai.generativeai.GenerativeModel
import com.google.cloud.vertexai.generativeai.ResponseHandler
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.sendMessage
import org.pircbotx.hooks.types.GenericMessageEvent
@ -40,8 +45,8 @@ import org.slf4j.LoggerFactory
import java.util.*
class Gemini2 : AbstractModule() {
private val logger: Logger = LoggerFactory.getLogger(Gemini2::class.java)
class Gemini : AbstractModule() {
private val logger: Logger = LoggerFactory.getLogger(Gemini::class.java)
override val name = GEMINI_NAME
@ -50,7 +55,8 @@ class Gemini2 : AbstractModule() {
try {
val answer = chat(
args.trim(),
properties[GEMINI_API_KEY],
properties[PROJECT_ID_PROP],
properties[LOCATION_PROP],
properties.getOrDefault(MAX_TOKENS_PROP, "1024").toInt()
)
if (!answer.isNullOrEmpty()) {
@ -76,12 +82,17 @@ class Gemini2 : AbstractModule() {
const val GEMINI_NAME = "Gemini"
/**
* The API key
* The Google cloud project ID property.
*/
const val GEMINI_API_KEY = "gemini-api-key"
const val PROJECT_ID_PROP = "gemini-project-id"
/**
* The max number of output tokens property.
* The Vertex AI location property.
*/
const val LOCATION_PROP = "gemini-location"
/**
* The max number of tokens property.
*/
const val MAX_TOKENS_PROP = "gemini-max-tokens"
@ -92,18 +103,40 @@ class Gemini2 : AbstractModule() {
@Throws(ModuleException::class)
fun chat(
query: String,
apiKey: String?,
maxTokens: Int
projectId: String?,
location: String?,
maxToken: Int
): String? {
if (!apiKey.isNullOrEmpty()) {
if (!projectId.isNullOrEmpty() && !location.isNullOrEmpty()) {
try {
val gemini = GoogleAiGeminiChatModel.builder()
.apiKey(apiKey)
.modelName("gemini-1.5-flash")
.maxOutputTokens(maxTokens)
.build()
VertexAI(projectId, location).use { vertexAI ->
val generationConfig = GenerationConfig.newBuilder().setMaxOutputTokens(maxToken).build()
val safetySettings = listOf(
SafetySetting.newBuilder()
.setCategory(HarmCategory.HARM_CATEGORY_HATE_SPEECH)
.setThreshold(SafetySetting.HarmBlockThreshold.BLOCK_LOW_AND_ABOVE)
.build(),
SafetySetting.newBuilder()
.setCategory(HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT)
.setThreshold(SafetySetting.HarmBlockThreshold.BLOCK_LOW_AND_ABOVE)
.build(),
SafetySetting.newBuilder()
.setCategory(HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT)
.setThreshold(SafetySetting.HarmBlockThreshold.BLOCK_LOW_AND_ABOVE)
.build(),
SafetySetting.newBuilder()
.setCategory(HarmCategory.HARM_CATEGORY_HARASSMENT)
.setThreshold(SafetySetting.HarmBlockThreshold.BLOCK_LOW_AND_ABOVE)
.build()
)
val model = GenerativeModel.Builder().setModelName("gemini-1.5-flash-001")
.setGenerationConfig(generationConfig)
.setVertexAi(vertexAI).build()
.withSafetySettings(safetySettings)
return gemini.generate(query)
val response = model.generateContent(query)
return ResponseHandler.getText(response)
}
} catch (e: Exception) {
throw ModuleException(
"$GEMINI_CMD($query): IO",
@ -126,6 +159,7 @@ class Gemini2 : AbstractModule() {
add(Utils.helpFormat("%c $GEMINI_CMD explain quantum computing in simple terms"))
add(Utils.helpFormat("%c $GEMINI_CMD how do I make an HTTP request in Javascript?"))
}
initProperties(GEMINI_API_KEY, MAX_TOKENS_PROP)
initProperties(PROJECT_ID_PROP, LOCATION_PROP, MAX_TOKENS_PROP)
}
}

View file

@ -39,10 +39,10 @@ import net.thauvin.erik.mobibot.DisableOnCi
import net.thauvin.erik.mobibot.LocalProperties
import kotlin.test.Test
class ChatGpt2Test : LocalProperties() {
class ChatGptTest : LocalProperties() {
@Test
fun testApiKey() {
assertFailure { ChatGpt2.chat("1 gallon to liter", "", 0) }
assertFailure { ChatGpt.chat("1 gallon to liter", "", 0) }
.isInstanceOf(ModuleException::class.java)
.hasNoCause()
}
@ -51,7 +51,7 @@ class ChatGpt2Test : LocalProperties() {
fun testChatOnCoverage() {
if (System.getenv("CI") == null || System.getenv("COVERAGE_JDK") != null) {
assertThat(
ChatGpt2.chat("how do I encode a URL in java?", getProperty(ChatGpt2.API_KEY_PROP), 60)
ChatGpt.chat("how do I encode a URL in java?", getProperty(ChatGpt.API_KEY_PROP), 60)
).contains("URLEncoder")
}
}
@ -59,12 +59,12 @@ class ChatGpt2Test : LocalProperties() {
@Test
@DisableOnCi
fun testChat() {
val apiKey = getProperty(ChatGpt2.API_KEY_PROP)
val apiKey = getProperty(ChatGpt.API_KEY_PROP)
assertThat(
ChatGpt2.chat("how do I make an HTTP request in Javascript?", apiKey, 200)
ChatGpt.chat("how do I make an HTTP request in Javascript?", apiKey, 100)
).contains("XMLHttpRequest")
assertFailure { ChatGpt2.chat("1 liter to gallon", apiKey, -1) }
assertFailure { ChatGpt.chat("1 liter to gallon", apiKey, -1) }
.isInstanceOf(ModuleException::class.java)
}
}

View file

@ -37,10 +37,10 @@ import net.thauvin.erik.mobibot.DisableOnCi
import net.thauvin.erik.mobibot.LocalProperties
import kotlin.test.Test
class Gemini2Test : LocalProperties() {
class GeminiTest : LocalProperties() {
@Test
fun testApiKey() {
assertFailure { Gemini2.chat("1 gallon to liter", "", 0) }
assertFailure { Gemini.chat("1 gallon to liter", "", "", 1024) }
.isInstanceOf(ModuleException::class.java)
.hasNoCause()
}
@ -48,18 +48,19 @@ class Gemini2Test : LocalProperties() {
@Test
@DisableOnCi
fun chatPrompt() {
val apiKey = getProperty(Gemini2.GEMINI_API_KEY)
val maxTokens = getProperty(Gemini2.MAX_TOKENS_PROP).toInt()
val projectId = getProperty(Gemini.PROJECT_ID_PROP)
val location = getProperty(Gemini.LOCATION_PROP)
val maxTokens = getProperty(Gemini.MAX_TOKENS_PROP).toInt()
assertThat(
Gemini2.chat("how do I make an HTTP request in Javascript?", apiKey, maxTokens)
Gemini.chat("how do I make an HTTP request in Javascript?", projectId, location, maxTokens)
).isNotNull().contains("XMLHttpRequest")
assertThat(
Gemini2.chat("how do I encode a URL in java?", apiKey, 60)
Gemini.chat("how do I encode a URL in java?", projectId, location, 60)
).isNotNull().contains("URLEncoder")
assertFailure { Gemini2.chat("1 liter to gallon", "foo", 40) }
assertFailure { Gemini.chat("1 liter to gallon", projectId, "blah", 40) }
.isInstanceOf(ModuleException::class.java)
}
}

View file

@ -38,10 +38,10 @@
<li><a href="https://commons.apache.org/proper/commons-net/">Apache Commons Net</a></li>
<li><a href="https://github.com/ethauvin/cryptoprice">CryptoPrice</a></li>
<li><a href="https://www.objecthunter.net/exp4j/">exp4j</a></li>
<li><a href="https://github.com/googleapis/google-cloud-java/tree/main/java-vertexai">Google Vertex AI</a></li>
<li><a href="https://github.com/ethauvin/jokeapi">JokeAPI</a></li>
<li><a href="https://jsoup.org/">jsoup</a></li>
<li><a href="https://github.com/Kotlin/kotlinx-cli">kotlinx-cli</a></li>
<li><a href="https://docs.langchain4j.dev/">LangChain4J</a></li>
<li><a href="https://square.github.io/okhttp/">OkHttp</a></li>
<li><a href="https://bitbucket.org/aksinghnet/owm-japis">OWM JAPIs</a></li>
<li><a href="https://github.com/ethauvin/pinboard-poster">Pinboard Poster</a></li>