너겟 요금제를 사용하면서, 간단하게 내 생활에 맞는 요금제를 추려볼 수 있을까?를 고민 하던중 두가지 방법이 떠올랐다.
- 내 일별 데이터 사용량과 월별 데이터 사용량을 뽑아서 현재 요금제에 직접 비교해 맞춰본다.
- 내 일별 데이터 사용량과 월별 데이터 사용량을 뽑아서 아!~몰랑. GPT 네가 좀 추천해줘!
역시 올드한 개발자라서 1번이기는 한데, 그러면 너무 재미 없으니 2번으로 하기로 하고, 사전 준비를 한다.
지난번 Langchain4J 연동과 같이 프로젝트에 아래 라이브러리 의존성을 추가하고 작업을 시작해 본다. ( 이미 있으니 간단히 적어본다. )
우선 ChatGPT에서 API 신청을 하고 API-KEY를 받아둔다.
이후, 이전 포스트와 같이 아래 작업들을 순차적으로 진행한다.
implementation("dev.langchain4j:langchain4j-open-ai-spring-boot-starter:${버전}")
implementation("dev.langchain4j:langchain4j-spring-boot-starter:${버전}")
빌드를 하고 yaml 파일에 설정을 넣어둔다.
langchain4j:
open-ai:
chat-model:
api-key: ""
model-name: "gpt-3.5-turbo"
log-requests: true
log-responses: true
max-retries: 1
이렇게 하면 기본 세팅은 된 듯 하고, 문서를 보다보니 어노테이션 방식과 코드 방식 모두 가능해 보였다.
이렇게 코드로 해도 되고,
@Bean
fun recommendedPlanAgent(chatLanguageModel: ChatLanguageModel): RecommendedPlanAgentService {
return AiServices.builder(RecommendedPlanAgentService::class.java)
.chatLanguageModel(chatLanguageModel)
.chatMemory(MessageWindowChatMemory.builder().maxMessages(1).build())
.build()
}
이렇게 @AiService 를 지정해서 해도 된다.
@AiService
interface RecommendedPlanAgentService {
...
}
각자 선호하는 스타일로 하면 되고, 우선 가볍게 파일럿 테스트를 해보는 거니까 어노테이션으로 진행해 보자.
@AiService: 애플리케이션 시작시 @AiService로 주석 처리된 모든 인터페이스를 찾아서 빈으로 등록.( stater 에 포함 )
음.. 응?! 음...
우선 @SystemMessage에 데이터 요금제를 넣어두면 될 듯한데 간단하게 넣어 볼까?
@SystemMessage(
value = [
"""
ChatGPT 는 통신사의 대리점 직원으로 고객이 사용중인 월 평균 데이터량을 보고 고객에게 알맞은 통신사 요금제를 추천해야 한다.
조건은 다음과 같습다:
- 데이터 사용량이 1GB 이하이면 '29요금제'를 추천.
- 데이터 사용량이 1GB 이상이고, 5GB 이하이면 '39요금제'를 추천.
- 데이터 사용량이 5GB 이상이고, 50GB 이하이면 '49요금제'를 추천.
- 데이터 사용량이 50GB를 초과하면 '59요금제'를 추천.
실제 분석단계에서는 좀 더 자세한 설명을 해주면 좋겠음. 월평균 사용량과 일평균 사용량을 분석하여 설명해주고, 최근 사용량의 상태를 확인해서 위의 요금제를 대입해서 추천을 하되,
추천 이유는 고객을 생각하는 마음으로 데이터를 분석하여 정성것 표기해야 합니다.
모든 응답은 JSON 형태로 반환하며, 다음 키를 포함해야 합니다:
- recommendPlan: 추천 요금제
- recommendReasons: 추천 이유
"""
]
)
좋아 이렇게 넣어보면 될 듯 하고,
@SystemMessage: LangChain4j에서 사용되는 핵심 어노테이션으로, AI 모델의 초기 컨텍스트와 동작을 정의하는 데 사용되고, 이 어노테이션은 LLM과의 대화에서 시스템 메시지를 통해 AI의 역할, 어조, 행동 방침 등을 설정한다.
그럼 이제 유저메시지와 결과를 지정해야 하는군.
@Tool(
name = "recommendPlan",
value = []
)
@UserMessage("고객이 사용한 월평균 데이터 {{text}} 한글로 답변하며, 월평균, 일평균 사용량을 분석해서 자세하게 알려준다.")
fun recommend(@V("text") text: String): RecommendPlanResponse
@Tool의 적용은 천천히 해보고, 우선 @UserMessage를 이렇게 하면 되겠군.
@UserMessage: 사용자 입력을 AI 모델에 전달하기 위해 사용되는 어노테이션이다. AI와의 대화에서 사용자의 의도, 질문, 요청 등을 캡처하고 전달하는 역할을 합니다.
음.. 좀 더 잘쓰면 답변도 좋을 듯 한데... 이건 기본 요금제데이터(@SystemMessage)와 전달된 사용자의 사용량 정보(@V("text"))에 따라 다를 듯 하니 우선은 저렇게 넘어가보는 것으로.
@V: 메서드의 Arg 를 직접 대화에서 사용할 수 있도록 만드는 데 사용된다. 이는 LangChain4j가 AI 모델과의 상호작용에서 매개변수 데이터를 동적으로 삽입하거나 관리하는 데 유용함.
음.. 그럼 역시 @V 값이 중요도가 높겠군.. 역시 테스트니 고민없이 넘어가고, 결과로 나올 RecommendPlanResponse 를 만들어 보자.
data class RecommendPlanResponse(
/** 추천요금제 */
val recommendPlan: String? = null,
/** 추천요금제 추천 설명 */
val recommendReasons: String? = null,
)
속성이 null 이 될 수도 있으니, 대충 null 기본으로 해서 만들어 두고 시작.
자 이제 사용자의 데이터를 가상으로 만들어서 보내봐야 겠다. 사용자의 데이터를 지정해보자. ( Fake 다 AI야!! ㅎㅎ )
우선 Service 하나를 만들어서 이렇게 보내보자.
@Service
class RecommendedPlanApiService(
private val recommendedPlanService: RecommendedPlanAgentService
) {
fun getRecommendPlan(): RecommendPlaRes {
val monthlyAvg = """
현재 사용자는 현재 '29요금제'를 사용중인데, 월평균 데이터 사용량은
6월에 500MB 사용하고,
7월에 1094MB 사용하고,
8월에 416MB 사용하고,
9월에 515MB 사용하고 있어,
그리고,
최근 한달의 일평균 10MB 인데 주말에 20MB를 사용중이다.
고객의 연령대는 30대이며, 주로 텍스트를 이용한 메신저를 이용한다.
"""
val response = recommendedPlanAgentService.recommend(monthlyAvg)
return RecommendPlaRes.toModel(response)
}
...
}
유저 데이터로 사용될 정보를 간단하게 작성해보았다.
자 그럼 간단하게 테스트용 컨트롤러를 만들어서 apidocs에 올려보자. ( 물론 단위 테스트는 통과한 상태.. )
코드를 이용한 방식과 어노테이션 방식 두개를 테스트 중이라 두개가 나온다. ㅡㅡ;;
by-annotation을 실행해 보자. 결과가 나온다.
결과는 이랬다. 음.. 요금제 데이터와 사용자 데이터 사용량 정보가 좀 더 상세하면 답변도 조금 더 좋지 않을까 생각해 본다.
그럼 이제 데이터를 수정해볼까?
fun getRecommendPlan(): RecommendPlaRes {
val monthlyAvg = """
현재 사용자는 30대의 연령대로, '29요금제'를 사용중인데, 월 데이터 사용량은 아래와 같습니다.
---
6월에 1500MB 사용하고,
7월에 2094MB 사용하고,
8월에 4016MB 사용하고,
9월에 4015MB 사용하고 있습니다.
그리고,
최근 한달의 일평균 400MB 인데 주말에 500MB 로 사용중입니다.
"""
val response = recommendedPlanAgentService.recommend(monthlyAvg)
return RecommendPlaRes.toModel(response)
}
사용하는 '29요금제'는 제공량 1GB 이하이지만, 월 평균 3GB 넘도록 수정하고 일평균과 주말 평균값도 높여 보았다.
아래 처럼 메시지 내용도 조금 변경해본다.
@Tool(
name = "recommendPlan",
value = []
)
@UserMessage(
"""
고객이 사용한 월, 일, 증가율 데이터 {{text}} 를 분석하여 한글로 분석한 내용을 기반으로 추천 요금제와 상세한 추천 이유를 제공한다.
"""
)
fun recommend(@V("text") text: String): RecommendPlanResponse
결과를 보면.
생각보다 잘 정리해주는 듯 하다.
확실이 input 이 좋아야 output이 좋은거 같고.. 어차피 코어레벨의 AI 엔진을 만드는게 아니면, 제일 중요한건 역시 프롬프트 같다는 생각이다.
이제 실제 데이터로 진행해봐야 겠다.