Refactor OpenAI integration and enhance ChatService

Removed the old OpenAIService and integrated a new version with additional DTOs and a RestTemplate configuration. The `ChatServiceImpl` now makes use of the OpenAI API for generating responses. Jackson Kotlin module support added for JSON deserialization.
This commit is contained in:
sku 2024-09-18 09:14:18 +02:00
parent 74dd3a5f85
commit 5a367a339c
10 changed files with 98 additions and 22 deletions

View File

@ -2,7 +2,6 @@
<configuration default="false" name="MainApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
<envs>
<env name="CLIENT_SECRET" value="notARealSecret" />
<env name="OPENAI_API_TOKEN" value="notARealSecret" />
</envs>
<module name="routing.server.main" />
<option name="SPRING_BOOT_MAIN_CLASS" value="de.hbt.routing.MainApplication" />

View File

@ -13,4 +13,5 @@ dependencies {
kapt(libs.mapstruct.processor)
implementation(libs.bundles.spring.boot.security)
implementation ("com.fasterxml.jackson.module:jackson-module-kotlin:2.17.+")
}

View File

@ -0,0 +1,36 @@
package de.hbt.routing.configuration
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.HttpRequest
import org.springframework.http.client.ClientHttpRequestExecution
import org.springframework.http.client.ClientHttpRequestInterceptor
import org.springframework.web.client.RestTemplate
@Configuration
open class OpenAIRestTemplateConfig(@Value("\${openai.api.token}") private val apiKey: String) {
@Bean
@Qualifier("openaiRestTemplate")
open fun openaiRestTemplate(): RestTemplate {
val restTemplate = RestTemplate()
restTemplate.interceptors.add(ClientHttpRequestInterceptor { request: HttpRequest, body: ByteArray?, execution: ClientHttpRequestExecution ->
request.headers.add("Authorization", "Bearer $apiKey")
execution.execute(request, body!!)
})
return restTemplate
}
@Bean
open fun jacksonObjectMapper(): ObjectMapper {
return ObjectMapper().apply {
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
registerKotlinModule()
}
}
}

View File

@ -0,0 +1,31 @@
package de.hbt.routing.openai
import de.hbt.routing.openai.dto.ChatRequest
import de.hbt.routing.openai.dto.ChatResponse
import mu.KotlinLogging
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate
@Service
class OpenAIService(@Qualifier("openaiRestTemplate") private val restTemplate: RestTemplate) {
fun chat(prompt: String): String {
// create a request
val request = ChatRequest("gpt-3.5-turbo", prompt)
// call the API
val response = restTemplate.postForObject("https://api.openai.com/v1/chat/completions", request, ChatResponse::class.java)
if (response?.choices == null || response.choices.isEmpty()) {
return "No response"
}
// return the first response
return response.choices.first().message.content
}
companion object {
private val log = KotlinLogging.logger {}
}
}

View File

@ -0,0 +1,7 @@
package de.hbt.routing.openai.dto
data class ChatRequest(val model: String, val n: Int, val temperature: Double, val messages: MutableList<Message?>) {
constructor(model: String, prompt: String) : this(model, 1, 0.0, ArrayList<Message?>()) {
messages.add(Message("user", prompt))
}
}

View File

@ -0,0 +1,6 @@
package de.hbt.routing.openai.dto
import lombok.Builder
import lombok.extern.jackson.Jacksonized
data class ChatResponse(val choices: List<Choice>)

View File

@ -0,0 +1,6 @@
package de.hbt.routing.openai.dto
import lombok.Builder
import lombok.extern.jackson.Jacksonized
data class Choice(val index: Int, val message: Message)

View File

@ -0,0 +1,6 @@
package de.hbt.routing.openai.dto
import lombok.Builder
import lombok.extern.jackson.Jacksonized
data class Message(val role: String, val content: String)

View File

@ -1,18 +1,19 @@
package de.hbt.routing.service
import de.hbt.routing.openai.OpenAIService
import de.hbt.routing.service.helper.ConversationCache
import org.springframework.stereotype.Service
import java.util.*
@Service
class ChatServiceImpl(private val conversationCache: ConversationCache) : ChatService {
class ChatServiceImpl(private val conversationCache: ConversationCache, private val openAIService: OpenAIService) : ChatService {
override fun processPrompt(requestId: String, prompt: String): ChatService.Response {
val uuid = requestId.ifBlank { UUID.randomUUID().toString() }
val mockResponse = "This is a mock response for prompt: $prompt"
val response = ChatService.Response(uuid, mockResponse)
val openAIResponse = openAIService.chat(prompt)
val response = ChatService.Response(uuid, openAIResponse)
conversationCache.addToConversation(uuid, ConversationCache.PromptAndAnswer(prompt, mockResponse))
conversationCache.addToConversation(uuid, ConversationCache.PromptAndAnswer(prompt, openAIResponse))
return response
}

View File

@ -1,17 +0,0 @@
package de.hbt.routing.service
import de.hbt.routing.property.ServiceProperties
import mu.KotlinLogging
import org.springframework.stereotype.Service
@Service
class OpenAIService(private val serviceProperties: ServiceProperties) {
fun call() {
log.info("Hallo, ich rufe bei OpenAI an")
}
companion object {
private val log = KotlinLogging.logger {}
}
}