v1.2.8 premium diet generation endpoint
This commit is contained in:
parent
7a6dd693cb
commit
e3182c210c
@ -11,7 +11,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "com.aitrainer"
|
||||
version = "1.2.7"
|
||||
version = "1.2.8"
|
||||
java.sourceCompatibility = JavaVersion.VERSION_17
|
||||
|
||||
repositories {
|
||||
|
5
data/db/update_1_2_8.sql
Normal file
5
data/db/update_1_2_8.sql
Normal file
@ -0,0 +1,5 @@
|
||||
START TRANSACTION;
|
||||
|
||||
UPDATE configuration set config_value = "1.2.8", date_change=CURRENT_DATE WHERE config_key = "db_version";
|
||||
|
||||
COMMIT;
|
@ -1,11 +1,24 @@
|
||||
package com.aitrainer.api.controller.diet
|
||||
|
||||
import com.aallam.openai.api.BetaOpenAI
|
||||
import com.aallam.openai.api.chat.ChatMessage
|
||||
import com.aallam.openai.api.chat.ChatRole
|
||||
import com.aitrainer.api.model.OpenAIChat
|
||||
import com.aitrainer.api.model.diet.Diet
|
||||
import com.aitrainer.api.openai.OpenAIService
|
||||
import com.aitrainer.api.repository.diet.DietRepository
|
||||
import com.google.gson.Gson
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.*
|
||||
|
||||
@RestController
|
||||
@ -58,4 +71,56 @@ class DietController(private val dietRepository: DietRepository) {
|
||||
return if (list.isEmpty()) ResponseEntity.notFound().build() else
|
||||
ResponseEntity.ok().body(list)
|
||||
}
|
||||
|
||||
@OptIn(BetaOpenAI::class, DelicateCoroutinesApi::class)
|
||||
@PostMapping("/diet/generate_premium/{dietUserId}", produces = [MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8"])
|
||||
fun generatePremiumDiet(@PathVariable dietUserId: Long, @RequestBody input: String, @Value("\${openai.key}") openaiKey: String): ResponseEntity<*> {
|
||||
val systemMsg = ChatMessage(
|
||||
role = ChatRole.System,
|
||||
content = "Te egy táplálkozási szakértő vagy"
|
||||
)
|
||||
val userMsg = ChatMessage(
|
||||
role = ChatRole.User,
|
||||
content = input
|
||||
)
|
||||
val listMessages: MutableList<ChatMessage> = mutableListOf()
|
||||
listMessages.add(systemMsg)
|
||||
listMessages.add(userMsg)
|
||||
val gson = Gson()
|
||||
val messages = gson.toJson(listMessages)
|
||||
|
||||
val openai = OpenAIChat(
|
||||
messages = messages,
|
||||
modelName = "gpt-4",
|
||||
temperature = 0.9
|
||||
)
|
||||
|
||||
var result: String? = null
|
||||
val openAIService = OpenAIService(openaiKey, openai.modelName, openai.temperature)
|
||||
val deferred = GlobalScope.async {
|
||||
println(openai.messages)
|
||||
openAIService.chatCompletion(openai.messages)
|
||||
}
|
||||
runBlocking {
|
||||
try {
|
||||
result = deferred.await().toString()
|
||||
} catch (exception: Exception) {
|
||||
println("Timeout for diet generation $dietUserId")
|
||||
}
|
||||
|
||||
}
|
||||
if ( result == null ) {
|
||||
return ResponseEntity.badRequest().build<String>()
|
||||
}
|
||||
val now = LocalDateTime.now()
|
||||
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
|
||||
val todayString = now.format(formatter)
|
||||
val diet: Diet = Diet(
|
||||
dietUserId = dietUserId,
|
||||
dietText = result!!,
|
||||
startDate = todayString,
|
||||
premium = 1
|
||||
)
|
||||
return ResponseEntity.ok().body(dietRepository.save(diet))
|
||||
}
|
||||
}
|
@ -30,7 +30,7 @@ class OpenAIService(@Value("\${openai.key}") private val openaiKey: String, priv
|
||||
val config = OpenAIConfig(
|
||||
token = openaiKey,
|
||||
logLevel = LogLevel.All,
|
||||
timeout = Timeout(socket = 300.seconds)
|
||||
timeout = Timeout(socket = 600.seconds)
|
||||
)
|
||||
openAI = OpenAI(config)
|
||||
modelId = ModelId(modelName)
|
||||
|
@ -16,7 +16,7 @@ logging.config=classpath:logback-spring.xml
|
||||
logging.file=logs
|
||||
|
||||
# if the database structure has been changed, increment this version number
|
||||
application.version=1.2.7
|
||||
application.version=1.2.8
|
||||
|
||||
jwt.secret=aitrainer
|
||||
|
||||
|
@ -14,7 +14,7 @@ logging.config=classpath:logback-spring.xml
|
||||
logging.file=logs
|
||||
|
||||
# if the database structue has been changed, increment this version number
|
||||
application.version=1.2.7
|
||||
application.version=1.2.8
|
||||
|
||||
jwt.secret=aitrainer
|
||||
|
||||
|
@ -1,7 +0,0 @@
|
||||
#spring.config.activate.on-profile=dev,test,prod,prodtest
|
||||
spring.config.use-legacy-processing = true
|
||||
## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
|
||||
spring.datasource.url = jdbc:mysql://192.168.100.98:3306/diet4you?serverTimezone=CET&useSSL=false&characterEncoding=UTF-8&allowMultiQueries=true
|
||||
spring.datasource.username = aitrainer
|
||||
spring.datasource.password = ENC(WZplPYr8WmrLHshesY4T6oXplK3MlUVJ)
|
||||
spring.http.encoding.charset=UTF-8
|
@ -14,7 +14,7 @@ logging.config=classpath:logback-spring.xml
|
||||
logging.file=logs
|
||||
|
||||
# if the database structue has been changed, increment this version number
|
||||
application.version=1.2.7
|
||||
application.version=1.2.8
|
||||
|
||||
jwt.secret=aitrainer
|
||||
|
||||
|
@ -1,14 +0,0 @@
|
||||
spring.config.activate.on-profile=testmac
|
||||
spring.config.use-legacy-processing = true
|
||||
## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
|
||||
#spring.datasource.url = jdbc:mysql://localhost:3306/aitrainer?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
|
||||
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/aitrainer2?serverTimezone=CET&useSSL=false&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&allowMultiQueries=true
|
||||
spring.datasource.username = root
|
||||
spring.datasource.password = ENC(WZplPYr8WmrLHshesY4T6oXplK3MlUVJ)
|
||||
|
||||
|
||||
## Hibernate Properties
|
||||
|
||||
|
||||
# The SQL dialect makes Hibernate generate better SQL for the chosen database
|
||||
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect
|
@ -17,7 +17,7 @@ logging.config=classpath:logback-spring.xml
|
||||
logging.file=logs
|
||||
|
||||
# if the database structure has been changed, increment this version number
|
||||
application.version=1.2.7
|
||||
application.version=1.2.8
|
||||
|
||||
jwt.secret=aitrainer
|
||||
|
||||
|
@ -3,7 +3,6 @@ package com.aitrainer.api.test.diet
|
||||
import com.aitrainer.api.model.diet.Diet
|
||||
import com.aitrainer.api.model.diet.DietMeal
|
||||
import com.aitrainer.api.repository.diet.DietRepository
|
||||
import com.aitrainer.api.repository.diet.MealRepository
|
||||
import com.aitrainer.api.test.Tokenizer
|
||||
import com.google.gson.Gson
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
@ -158,14 +157,49 @@ class DietTest {
|
||||
.andExpect(jsonPath("$.premium").value(1))
|
||||
.andReturn()
|
||||
|
||||
val gson2= Gson()
|
||||
val newDietJson2 = mvcResult2.response.contentAsString
|
||||
val newDiet2 = gson.fromJson(newDietJson, Diet::class.java)
|
||||
val newDiet2 = gson.fromJson(newDietJson2, Diet::class.java)
|
||||
|
||||
dietRepository.delete(newDiet)
|
||||
dietRepository.delete(newDiet2)
|
||||
}
|
||||
|
||||
//@Test
|
||||
fun `generate premium diet successfully`() {
|
||||
|
||||
val input = "Készíts egy személyre szabott heti étrendet ezekkel a paraméterekkel:\n" +
|
||||
"Férfi, 50 éves, 120kg, 170 magas, célja fogyás.\n" +
|
||||
"- Speciális étrend: ketogén\n" +
|
||||
"- Allergiák: olajos magvak\n" +
|
||||
"- Preferált ételek: magyar konyha\n" +
|
||||
"- Ezek az ételek nem szerepelhetnek az étrendben: főzelékek\n" +
|
||||
"- napi kalóriacél: 2100 kCal\n" +
|
||||
"- Étel frekvencia: reggeli, ebéd, uzsonna, vacsora\n" +
|
||||
"- Ebéd és vacsora megegyezik. \n" +
|
||||
"- ne legyen ismétlődés az ételeknél\n" +
|
||||
"\n" +
|
||||
"A választ ebben a formátumban add meg:\n" +
|
||||
"{ \"DIET\": [\n" +
|
||||
"{\"nameDay\": enum<monday, tuesday, wednesday...>\n" +
|
||||
"\"mealTime\":enum<breakfast, lunch+dinner, snack>\n" +
|
||||
"\"meals\":[<mealNames in Hungarian>],\n" +
|
||||
"\"quantities\":[<quantities for each mealName in gramms>],\n" +
|
||||
"\"calories\":[<calorie values for each mealName>],\n" +
|
||||
"}, \"sumCal\":double\n" +
|
||||
"]}"
|
||||
|
||||
mockMvc.perform(
|
||||
MockMvcRequestBuilders.post("/api/diet/generate_premium/2")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "Bearer $authToken")
|
||||
.content(input)
|
||||
)
|
||||
.andExpect(status().isOk)
|
||||
.andExpect(jsonPath("$.dietUserId").value(2))
|
||||
.andExpect(jsonPath("$.premium").value(1))
|
||||
|
||||
}
|
||||
|
||||
private fun toJson(obj: Any): String {
|
||||
return Gson().toJson(obj)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user