Skip to content

Commit

Permalink
Removing chatgpt lib so we can see what's actually going on
Browse files Browse the repository at this point in the history
  • Loading branch information
jottinger committed Feb 26, 2024
1 parent 8e58510 commit d219571
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 28 deletions.
6 changes: 1 addition & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -540,11 +540,7 @@
<artifactId>xz</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>io.github.umutayb</groupId>
<artifactId>gpt-utilities</artifactId>
<version>0.1.4</version>
</dependency>

</dependencies>

<properties>
Expand Down
66 changes: 56 additions & 10 deletions src/main/kotlin/javabot/dao/ChatGPTDao.kt
Original file line number Diff line number Diff line change
@@ -1,27 +1,73 @@
package javabot.dao

import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.google.inject.Inject
import com.google.inject.Singleton
import gpt.api.GPT
import gpt.models.Message
import gpt.models.MessageModel
import io.dropwizard.util.Duration
import javabot.JavabotConfig
import javabot.operations.throttle.BotRateLimiter
import javabot.service.HttpService

@Singleton
class ChatGPTDao @Inject constructor(val javabotConfig: JavabotConfig) {
data class GPTMessageContainer(
val messages: List<GPTMessage>,
val model: String = "gpt-4",
val temperature: Double = 0.7
)

data class GPTMessage(val content: String, val role: String = "user")

class GPTResponse(
@JsonProperty("id") val id: String,
@JsonProperty("object") val completion: String,
@JsonProperty("created") val created: Long,
@JsonProperty("model") val model: String,
@JsonProperty("choices") val choices: List<GPTChoice>,
@JsonProperty("usage") val usage: GPTUsage
)

class GPTUsage(
@JsonProperty("prompt_tokens") val promptTokens: Int,
@JsonProperty("completion_tokens") val completionTokens: Int,
@JsonProperty("total_tokens") val totalTokens: Int
)

class GPTChoice(
@JsonProperty("message") val message: GPTChoiceMessage,
@JsonProperty("index") val index: Int,
@JsonProperty("finish_reason") val finishReason: String
)

data class GPTChoiceMessage(
@JsonProperty("content") val content: String,
@JsonProperty("role") val role: String
)

@Singleton
class ChatGPTDao
@Inject
constructor(
private val javabotConfig: JavabotConfig,
private val httpService: HttpService,
) {
private var limiter: BotRateLimiter =
BotRateLimiter(javabotConfig.chatGptLimit(), Duration.days(1).toMilliseconds())

fun sendPromptToChatGPT(prompt: String): String? {
val mapper = ObjectMapper()
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
return if (javabotConfig.chatGptKey().isNotEmpty() && limiter.tryAcquire()) {
val model = "gpt-4"
val gpt = GPT(javabotConfig.chatGptKey())
val messageModel = MessageModel(model, listOf(Message("user", prompt)))
val messageResponse = gpt.sendMessage(messageModel)
return messageResponse.choices[0].message.content
val data =
httpService.post(
"https://api.openai.com/v1/chat/completions",
emptyMap(),
mapOf("Authorization" to "Bearer ${javabotConfig.chatGptKey()}"),
emptyMap(),
GPTMessageContainer(listOf(GPTMessage(prompt)))
)
val response = mapper.readValue(data, GPTResponse::class.java)
return response.choices.first().message.content
} else {
// no chatGPT key? No chatGPT attempt.
null
Expand Down
14 changes: 9 additions & 5 deletions src/main/kotlin/javabot/operations/ChatGPTOperation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@ constructor(bot: Javabot, adminDao: AdminDao, var chatGPTDao: ChatGPTDao) :
val uuid = UUID.randomUUID()
val query = message.substringAfter("gpt ")
val prompt =
"""Someone is asking "$query".
"""Someone is asking '$query'.
Restrict your answer to being applicable to the Java Virtual Machine,
and limit the response's length as if it were to be posted on Twitter,
but without hashtags or other such twitter-like features;
if the answer does not contain constructive information for Java programming,
respond ONLY with \"$uuid-not applicable\" and no other text"""
respond ONLY with "$uuid-not applicable" and no other text"""
.trimIndent()
val result = chatGPTDao.sendPromptToChatGPT(prompt)
if (!result.isNullOrEmpty() && !result.lowercase().contains(uuid.toString())) {
responses.add(Message(event, result.toString()))
try {
val result = chatGPTDao.sendPromptToChatGPT(prompt)
if (!result.isNullOrEmpty() && !result.lowercase().contains(uuid.toString())) {
responses.add(Message(event, result.toString()))
}
} catch (e: Throwable) {
Javabot.LOG.info("exception", e)
}
}
return responses
Expand Down
50 changes: 42 additions & 8 deletions src/main/kotlin/javabot/service/HttpService.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package javabot.service

import com.fasterxml.jackson.databind.ObjectMapper
import com.google.inject.Singleton
import java.time.Duration
import java.util.concurrent.TimeUnit
import okhttp3.Headers.Companion.toHeaders
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody

class HttpServiceException(message: String = "No message") : Exception(message)

Expand Down Expand Up @@ -63,26 +66,57 @@ class HttpService {
params: Map<String, String> = emptyMap(),
headers: Map<String, String> = emptyMap(),
options: Map<HTTP_OPTIONS, Duration> = emptyMap()
): String = request(url, params, headers, options, "get", null)

fun post(
url: String,
params: Map<String, String> = emptyMap(),
headers: Map<String, String> = emptyMap(),
options: Map<HTTP_OPTIONS, Duration> = emptyMap(),
body: Any? = null
): String = request(url, params, headers, options, "post", body)

fun request(
url: String,
params: Map<String, String> = emptyMap(),
headers: Map<String, String> = emptyMap(),
options: Map<HTTP_OPTIONS, Duration> = emptyMap(),
method: String = "get",
body: Any? = null
): String {
val httpUrl = url.toHttpUrl()
val builder = httpUrl.newBuilder()
params.forEach { builder.addQueryParameter(it.key, it.value) }
val request = Request.Builder().url(builder.build()).headers(headers.toHeaders()).build()
val requestBuilder = Request.Builder().url(builder.build()).headers(headers.toHeaders())
when (method) {
"get" -> requestBuilder.get()
"post" -> {
val mapper = ObjectMapper()
val bodyContent = mapper.writeValueAsString(body)
requestBuilder.post(
bodyContent.toRequestBody("application/json; chartset=utf-8".toMediaType())
)
}

else ->
throw IllegalArgumentException("method type $method not supported by HttpService")
}
val request = requestBuilder.build()
// if options aren't empty, build a local copy of the request.
// otherwise, use the global client options as is.
if (!options.isEmpty()) {
val localRequest = client.newBuilder()
if (options.isNotEmpty()) {
val localRequest = client.newBuilder()

options.forEach { action -> action.key.apply(localRequest, action.value) }
options.forEach { action -> action.key.apply(localRequest, action.value) }

localRequest.build()
} else {
client
}
localRequest.build()
} else {
client
}
.newCall(request)
.execute()
.use { response ->
println(response)
if (response.isSuccessful) {
return (response.body?.string() ?: throw HttpServiceException())
} else {
Expand Down

0 comments on commit d219571

Please sign in to comment.