diff --git a/build.gradle.kts b/build.gradle.kts index 81c888a..90a56bc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,6 +6,8 @@ plugins { kotlin("plugin.jpa") version "1.9.25" // 코틀린 코드 스타일 린터 id("org.jlleitschuh.gradle.ktlint") version "12.1.0" + // 빌드 설정 상수 생성 + id("com.github.gmazzo.buildconfig") version "5.3.5" } group = "com.back" @@ -107,6 +109,38 @@ ktlint { } filter { exclude("**/generated/**") + exclude("**/BuildConfig.kt") include("**/kotlin/**") } } + +buildConfig { + useKotlinOutput() + + val regionCodes = + file("src/main/resources/region-codes.yml") + .readText() + .substringAfter("codes:") + .lines() + .filter { it.contains(":") } + .joinToString(", ") { line -> + val parts = line.split(":") + "${parts[0].trim()}: ${parts[1].trim().replace("\"", "")}" + } + + val promptsText = file("src/main/resources/prompts.yml").readText() + val systemPrompt = + promptsText + .substringAfter("korea-travel-guide: |") + .substringBefore(" errors:") + .trim() + + val errorPrompt = + promptsText + .substringAfter("ai-fallback: \"") + .substringBefore("\"") + + buildConfigField("String", "REGION_CODES_DESCRIPTION", "\"\"\"$regionCodes\"\"\"") + buildConfigField("String", "KOREA_TRAVEL_GUIDE_SYSTEM", "\"\"\"$systemPrompt\"\"\"") + buildConfigField("String", "AI_ERROR_FALLBACK", "\"\"\"$errorPrompt\"\"\"") +} diff --git a/src/main/kotlin/com/back/koreaTravelGuide/common/constant/PromptConstant.kt b/src/main/kotlin/com/back/koreaTravelGuide/common/constant/PromptConstant.kt deleted file mode 100644 index f2d2fb4..0000000 --- a/src/main/kotlin/com/back/koreaTravelGuide/common/constant/PromptConstant.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.back.koreaTravelGuide.common.constant - -object PromptConstant { - const val KOREA_TRAVEL_GUIDE_SYSTEM = """ - 당신은 한국 여행 전문 AI 가이드입니다. - 한국의 관광지, 음식, 문화에 대해 정확하고 친근한 정보를 제공하세요. - 답변은 한국어로 해주시고, 구체적인 추천과 팁을 포함해주세요. - 사용자에게 도움이 되는 실용적인 여행 정보를 제공하는 것이 목표입니다. - """ - - const val AI_ERROR_FALLBACK = "죄송합니다. 일시적인 문제로 응답을 생성할 수 없습니다. 다시 시도해 주세요." -} diff --git a/src/main/kotlin/com/back/koreaTravelGuide/domain/ai/aiChat/service/AiChatService.kt b/src/main/kotlin/com/back/koreaTravelGuide/domain/ai/aiChat/service/AiChatService.kt index 322a6a9..72b5020 100644 --- a/src/main/kotlin/com/back/koreaTravelGuide/domain/ai/aiChat/service/AiChatService.kt +++ b/src/main/kotlin/com/back/koreaTravelGuide/domain/ai/aiChat/service/AiChatService.kt @@ -1,7 +1,6 @@ package com.back.koreaTravelGuide.domain.ai.aiChat.service -import com.back.koreaTravelGuide.common.constant.PromptConstant.AI_ERROR_FALLBACK -import com.back.koreaTravelGuide.common.constant.PromptConstant.KOREA_TRAVEL_GUIDE_SYSTEM +import com.back.backend.BuildConfig import com.back.koreaTravelGuide.domain.ai.aiChat.entity.AiChatMessage import com.back.koreaTravelGuide.domain.ai.aiChat.entity.AiChatSession import com.back.koreaTravelGuide.domain.ai.aiChat.entity.SenderType @@ -66,15 +65,15 @@ class AiChatService( val response = try { chatClient.prompt() - .system(KOREA_TRAVEL_GUIDE_SYSTEM) + .system(BuildConfig.KOREA_TRAVEL_GUIDE_SYSTEM) .user(message) .advisors { advisor -> advisor.param(ChatMemory.CONVERSATION_ID, sessionId.toString()) } .call() - .content() ?: AI_ERROR_FALLBACK + .content() ?: BuildConfig.AI_ERROR_FALLBACK } catch (e: Exception) { - AI_ERROR_FALLBACK + BuildConfig.AI_ERROR_FALLBACK } val aiMessage = diff --git a/src/main/kotlin/com/back/koreaTravelGuide/domain/ai/aiChat/tool/WeatherTool.kt b/src/main/kotlin/com/back/koreaTravelGuide/domain/ai/aiChat/tool/WeatherTool.kt index d17feaf..ea19f12 100644 --- a/src/main/kotlin/com/back/koreaTravelGuide/domain/ai/aiChat/tool/WeatherTool.kt +++ b/src/main/kotlin/com/back/koreaTravelGuide/domain/ai/aiChat/tool/WeatherTool.kt @@ -1,7 +1,7 @@ package com.back.koreaTravelGuide.domain.ai.aiChat.tool +import com.back.backend.BuildConfig import com.back.koreaTravelGuide.domain.ai.weather.service.WeatherService -import com.back.koreaTravelGuide.domain.ai.weather.service.tools.Tools import org.springframework.ai.tool.annotation.Tool import org.springframework.ai.tool.annotation.ToolParam import org.springframework.stereotype.Component @@ -9,24 +9,20 @@ import org.springframework.stereotype.Component @Component class WeatherTool( private val weatherService: WeatherService, - private val tools: Tools, ) { @Tool(description = "전국 중기예보를 조회합니다") fun getWeatherForecast(): String { - val actualBaseTime = tools.validBaseTime(null) - val forecasts = weatherService.fetchMidForecast(actualBaseTime) + val forecasts = weatherService.getWeatherForecast() return forecasts?.toString() ?: "중기예보 데이터를 가져올 수 없습니다." } @Tool(description = "특정 지역의 상세 기온 및 날씨 예보를 조회합니다") fun getRegionalWeatherDetails( - @ToolParam(description = "지역명 (예: 서울, 부산, 대전, 제주 등)", required = true) + @ToolParam(description = BuildConfig.REGION_CODES_DESCRIPTION, required = true) location: String, ): String { - val regionCode = tools.getRegionCodeFromLocation(location) - val actualBaseTime = tools.validBaseTime(null) - val forecasts = weatherService.fetchTemperatureAndLandForecast(regionCode, actualBaseTime) + val forecasts = weatherService.getTemperatureAndLandForecast(location) return forecasts?.toString() ?: "$location 지역의 상세 날씨 정보를 가져올 수 없습니다." } diff --git a/src/main/resources/prompts.yml b/src/main/resources/prompts.yml new file mode 100644 index 0000000..fc747bb --- /dev/null +++ b/src/main/resources/prompts.yml @@ -0,0 +1,9 @@ +prompts: + system: + korea-travel-guide: | + 당신은 한국 여행 전문 AI 가이드입니다. + 한국의 관광지, 음식, 문화에 대해 정확하고 친근한 정보를 제공하세요. + 답변은 한국어로 해주시고, 구체적인 추천과 팁을 포함해주세요. + 사용자에게 도움이 되는 실용적인 여행 정보를 제공하는 것이 목표입니다. + errors: + ai-fallback: "죄송합니다. 일시적인 문제로 응답을 생성할 수 없습니다. 다시 시도해 주세요." \ No newline at end of file