Added support for ChatGPT 3.5 Turbo

This commit is contained in:
Erik C. Thauvin 2023-12-18 14:14:08 -08:00
parent a10104dd9d
commit 356f62990d
5 changed files with 24 additions and 27 deletions

View file

@ -87,6 +87,7 @@ disabled-modules=mastodon
# gcloud config set project PROJECT_ID # gcloud config set project PROJECT_ID
# gcloud auth login LOGIN # gcloud auth login LOGIN
# gcloud auth application-default login # gcloud auth application-default login
#
#gemini-project-id= #gemini-project-id=
#gemini-location=us-west1 #gemini-location=us-west1
#gemini-max-tokens=1024 #gemini-max-tokens=1024

View file

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

View file

@ -34,10 +34,8 @@ package net.thauvin.erik.mobibot.modules
import net.thauvin.erik.mobibot.Constants import net.thauvin.erik.mobibot.Constants
import net.thauvin.erik.mobibot.Utils import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.sendMessage import net.thauvin.erik.mobibot.Utils.sendMessage
import org.apache.commons.text.WordUtils
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
import org.json.JSONWriter
import org.pircbotx.hooks.types.GenericMessageEvent import org.pircbotx.hooks.types.GenericMessageEvent
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -48,7 +46,7 @@ import java.net.http.HttpRequest
import java.net.http.HttpResponse import java.net.http.HttpResponse
class ChatGpt : AbstractModule() { class ChatGpt : AbstractModule() {
private val logger: Logger = LoggerFactory.getLogger(ChatGpt::class.java) val logger: Logger = LoggerFactory.getLogger(ChatGpt::class.java)
override val name = CHATGPT_NAME override val name = CHATGPT_NAME
@ -60,7 +58,7 @@ class ChatGpt : AbstractModule() {
properties.getOrDefault(MAX_TOKENS_PROP, "1024").toInt() properties.getOrDefault(MAX_TOKENS_PROP, "1024").toInt()
) )
if (answer.isNotBlank()) { if (answer.isNotBlank()) {
event.sendMessage(WordUtils.wrap(answer, 400)) event.sendMessage(answer)
} else { } else {
event.respond("$name is stumped.") event.respond("$name is stumped.")
} }
@ -95,7 +93,7 @@ class ChatGpt : AbstractModule() {
const val MAX_TOKENS_PROP = "chatgpt-max-tokens" const val MAX_TOKENS_PROP = "chatgpt-max-tokens"
// ChatGPT API URL // ChatGPT API URL
private const val API_URL = "https://api.openai.com/v1/completions" private const val API_URL = "https://api.openai.com/v1/chat/completions"
// ChatGPT command // ChatGPT command
private const val CHATGPT_CMD = "chatgpt" private const val CHATGPT_CMD = "chatgpt"
@ -105,7 +103,7 @@ class ChatGpt : AbstractModule() {
@Throws(ModuleException::class) @Throws(ModuleException::class)
fun chat(query: String, apiKey: String?, maxTokens: Int): String { fun chat(query: String, apiKey: String?, maxTokens: Int): String {
if (!apiKey.isNullOrEmpty()) { if (!apiKey.isNullOrEmpty()) {
val prompt = JSONWriter.valueToString("Q:$query\nA:") val content = query.replace("\"", "\\\"")
val request = HttpRequest.newBuilder() val request = HttpRequest.newBuilder()
.uri(URI.create(API_URL)) .uri(URI.create(API_URL))
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
@ -114,14 +112,15 @@ class ChatGpt : AbstractModule() {
.POST( .POST(
HttpRequest.BodyPublishers.ofString( HttpRequest.BodyPublishers.ofString(
"""{ """{
"model": "text-davinci-003", "model": "gpt-3.5-turbo-1106",
"prompt": $prompt, "max_tokens": $maxTokens,
"temperature": 0, "messages": [
"max_tokens": $maxTokens, {
"top_p": 1, "role": "user",
"frequency_penalty": 0, "content": "$content"
"presence_penalty": 0 }
}""".trimIndent() ]
}""".trimIndent()
) )
) )
.build() .build()
@ -131,7 +130,7 @@ class ChatGpt : AbstractModule() {
try { try {
val jsonResponse = JSONObject(response.body()) val jsonResponse = JSONObject(response.body())
val choices = jsonResponse.getJSONArray("choices") val choices = jsonResponse.getJSONArray("choices")
return choices.getJSONObject(0).getString("text").trim() return choices.getJSONObject(0).getJSONObject("message").getString("content").trim()
} catch (e: JSONException) { } catch (e: JSONException) {
throw ModuleException( throw ModuleException(
"$CHATGPT_CMD($query): JSON", "$CHATGPT_CMD($query): JSON",

View file

@ -1,16 +1,12 @@
package net.thauvin.erik.mobibot.modules package net.thauvin.erik.mobibot.modules
import com.google.auth.Credentials
import com.google.cloud.vertexai.VertexAI import com.google.cloud.vertexai.VertexAI
import com.google.cloud.vertexai.api.GenerateContentResponse
import com.google.cloud.vertexai.api.GenerationConfig import com.google.cloud.vertexai.api.GenerationConfig
import com.google.cloud.vertexai.generativeai.preview.ChatSession import com.google.cloud.vertexai.generativeai.preview.ChatSession
import com.google.cloud.vertexai.generativeai.preview.GenerativeModel import com.google.cloud.vertexai.generativeai.preview.GenerativeModel
import com.google.cloud.vertexai.generativeai.preview.ResponseHandler import com.google.cloud.vertexai.generativeai.preview.ResponseHandler
import net.thauvin.erik.mobibot.Utils import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.sendMessage import net.thauvin.erik.mobibot.Utils.sendMessage
import okio.IOException
import org.apache.commons.text.WordUtils
import org.pircbotx.hooks.types.GenericMessageEvent import org.pircbotx.hooks.types.GenericMessageEvent
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -86,7 +82,7 @@ class Gemini : AbstractModule() {
val session = ChatSession(model) val session = ChatSession(model)
val response = session.sendMessage(query) val response = session.sendMessage(query)
return ResponseHandler.getText(response); return ResponseHandler.getText(response)
} }
} catch (e: Exception) { } catch (e: Exception) {
throw ModuleException( throw ModuleException(
@ -96,7 +92,7 @@ class Gemini : AbstractModule() {
) )
} }
} else { } else {
throw ModuleException("${GEMINI_CMD}($query)", "No ${GEMINI_NAME} Project ID or Location specified.") throw ModuleException("${GEMINI_CMD}($query)", "No $GEMINI_NAME Project ID or Location specified.")
} }
} }
} }
@ -105,10 +101,10 @@ class Gemini : AbstractModule() {
commands.add(GEMINI_CMD) commands.add(GEMINI_CMD)
with(help) { with(help) {
add("To get answers from $name:") add("To get answers from $name:")
add(Utils.helpFormat("%c ${GEMINI_CMD} <query>")) add(Utils.helpFormat("%c $GEMINI_CMD <query>"))
add("For example:") add("For example:")
add(Utils.helpFormat("%c ${GEMINI_CMD} explain quantum computing in simple terms")) 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?")) add(Utils.helpFormat("%c $GEMINI_CMD how do I make an HTTP request in Javascript?"))
} }
initProperties(PROJECT_ID_PROP, LOCATION_PROPR, MAX_TOKENS_PROP) initProperties(PROJECT_ID_PROP, LOCATION_PROPR, MAX_TOKENS_PROP)
} }

View file

@ -54,11 +54,12 @@ class ChatGptTest : LocalProperties() {
assertThat( assertThat(
ChatGpt.chat("how do I make an HTTP request in Javascript?", apiKey, 100) ChatGpt.chat("how do I make an HTTP request in Javascript?", apiKey, 100)
).contains("XMLHttpRequest") ).contains("XMLHttpRequest")
assertThat( assertThat(
ChatGpt.chat("how do I encode a URL in java?", apiKey, 60) ChatGpt.chat("how do I encode a URL in java?", apiKey, 60)
).contains("URLEncoder") ).contains("URLEncoder")
assertFailure { ChatGpt.chat("1 liter to gallon", apiKey, 0) } assertFailure { ChatGpt.chat("1 liter to gallon", apiKey, -1) }
.isInstanceOf(ModuleException::class.java) .isInstanceOf(ModuleException::class.java)
} }
} }