이전 글에 이어서 사용자의 선호도를 입력받아 카드를 추천해주는 추천시스템을 이용하여 사용자가 챗봇 페이지에서 요구사항을 입력하고 카드를 추천 받을 수 있도록 페이지를 구현해주었다.
이전 글의 추천시스템에서는 터미널에서 사용자 입력을 받아 추천이 실행이 되었다면 이제는 챗봇 페이지에서 입력창에 사용자의 선호도를 입력하고 카드를 추천받을 수 있도록 하기 위함이다.
먼저 기본적으로 추천에 사용되는 시스템은 이전 글에서 구현했던 코드를 그대로 사용했다.
(자세한 코드가 궁금하다면 이전 글 참고)
https://hyunh404.tistory.com/3
[finchatbot] 카드 추천 시스템
이전에 작성했던 임베딩 과정을 통해 얻은 파일을 이용해 사용자의 선호도에 맞는 카드 상품을 추천해주는 코드 파일을 작성했다. 추천시스템을 만들기 위해 임베딩한 파일인 embedded_card_data.csv
hyunh404.tistory.com
먼저 html과 css, javascript를 사용하여 페이지 모양과 디자인을 구성해 주었다. 챗봇으로 만들기 위해서 최대한 챗봇 느낌이 나도록 디자인을 구성해보았다. 이 부분은 크게 어려운 게 없어서 body 코드와 css코드만 올려두겠다.
(html body의 main 전체코드)
<main>
<div class = "chat-container" >
<div class = "chat-header" > finchatbot </div>
<div class = "chat-body" id = "chatBody" >
<div class = "chat-message" > 원하시는 카드 혜택을 입력해주시면 맞춤 카드를 추천해드릴게요. </div>
<div class = "chat-message" >
<form method = "POST" >
<label for = "user_preference" > 선호하는 카드의 혜택을 입력하세요: </label>
<input type = "text" id = "user_preference" name = "user_preference" >
<input type = "submit" value = "추천 카드 찾기" >
</form>
</div>
<div class = "chat-message" >
<h2> 사용자 입력: </h2>
<p> {{ user_input }} </p>
</div>
<div class = "chat-message" >
<h1> 추천 카드 상품: {{ recommendation }} </h1>
</div>
</div>
</div>
</main>
(css 전체 코드)
.chat-container {
max-width: 100%;
margin: 20px auto;
height: 80vh;
border: 1px solid #ccc;
border-radius: 5px;
overflow: hidden;
overflow-y: auto;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.chat-header {
background-color: #2991ff;
color: white;
padding: 10px;
text-align: center;
}
.chat-body {
height: 80vh;
padding: 10px;
overflow-y: auto;
max-height: 300px;
display: flex;
flex-direction: column;
}
.chat-message {
background-color: #ddd;
padding: 8px;
border-radius: 5px;
float: left;
margin-bottom: 10px;
}
.options {
text-align: center;
margin-top: 20px;
display: flex;
justify-content: center;
}
.options button {
margin: 0 10px;
padding: 8px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
________________________________________________________________________________________________
페이지의 틀을 구현한 후에 본격적으로 flask파일을 이용해 동적인 페이지를 구현하였다.
먼저 추천시스템을 구현하였을 때 사용했던 것처럼 라이브러리들을 정의해주고 flask를 실행하기 ㅜ이한 라이브러리만 추가적으로 정의해주었다. (첫줄에 있는 코드가 flask 실행을 위한 코드)
from flask import Flask , render_template , request
import pandas as pd
from transformers import BertTokenizer , BertModel
import torch
from sklearn . metrics . pairwise import cosine_similarity
다음으로 추천시스템과 동일한 코드를 사용하여 사용자의 입력에 대한 문장을 임베딩하고 파일에서 데이터를 불러와 유사도를 계산해 카드를 추천하는 방식이므로 따로 코드를 올려놓지는 않겠다. 만약 코드가 궁금하다면 위의 링크에도 있는 이전 글에서 확인 가능하다.
추천시스템 코드를 작성한 이후에는 이제 html파일을 불러와서 실행을 시켜야한다. 만들어놓은 recomcard.html파일을 flask에서 불러와서 실행할 수 있도록 코드를 작성해주었다.
app = Flask ( __name__ )
@ app . route ( '/' )
def index ():
return render_template ( 'recomcard.html' )
html이 성공적으로 불러와지는 것을 확인한 후에 사용자 입력창에서 flask로 입력 내용을 전달받을 수 있도록 하는 코드도 작성해주었다. 이 단계에서 사용자의 입력을 받고 응답을 임베딩하여 유사도를 계산하는 과정이 이루어진다. 따라서 유사도 계산이 완료되면 추천된 카드가 recomcard.html을 통해 사용자에게 보여지게 된다.
@ app . route ( '/get_recommendation' , methods =[ 'POST' ])
def get_recommendation ():
if request . method == 'POST' :
user_preference = request . form [ 'user_preference' ]
# 사용자 응답을 임베딩
user_embedding = embed_user_response ([ user_preference ])
# embedded_card_data.csv 파일을 불러와 카드 혜택의 임베딩값을 저장
card_data = pd . read_csv ( 'C:/finchatbot/embedded_card_data.csv' )
# 유사도 계산 및 추천
best_match = None
highest_similarity = 0.0
for index , row in card_data . iterrows ():
card_embedding = embed_card_benefits ([ row [ 'embedding' ]])
similarity = calculate_similarity ( card_embedding , user_embedding )
if similarity > highest_similarity :
highest_similarity = similarity
best_match = row [ '카드명' ]
return render_template ( 'recomcard.html' , recommendation = best_match , user_input = user_preference )
if __name__ == '__main__' :
app . run ( debug = True )
이 코드를 작성한 후에는 html파일에도 버튼을 눌렀을때 실행이 되도록하기 위해 코드를 수정해주어야한다. 위에 올렸던 코드에서 필요한 코드를 추가해 다시 올려놓겠다. 추가된 코드는 알아보기 쉽도록 주석으로 '추가'라고 덧붙여 놓았다.
<main>
<div class = "chat-container" >
<div class = "chat-header" > finchatbot </div>
<div class = "chat-body" id = "chatBody" >
<div class = "chat-message" > 원하시는 카드 혜택을 입력해주시면 맞춤 카드를 추천해드릴게요. </div>
<div class = "chat-message" >
<form method = "POST" action = "/get_recommendation" > <!--추가-->
<label for = "user_preference" > 선호하는 카드의 혜택을 입력하세요: </label>
<input type = "text" id = "user_preference" name = "user_preference" >
<input type = "submit" value = "추천 카드 찾기" >
</form>
</div>
<div class = "chat-message" >
{% if user_input %} <!--추가-->
<h2> 사용자 입력: </h2>
<p> {{ user_input }} </p>
{% endif %} <!--추가-->
</div>
<div class = "chat-message" >
{% if recommendation %} <!--추가-->
<h1> 추천 카드 상품: {{ recommendation }} </h1>
{% endif %} <!--추가-->
</div>
</div>
</div>
</main>
_______________________________________________________________________________________________
html까지 코드를 수정해주고 난 후에는 이제 추천 시스템을 챗봇으로 구현하는 과정이 완료되었다. 이해를 위해 실제 실행화면을 첨부해두겠다.
챗봇으로 구현하여 사용자 입력을 해주고 카드를 추천받는 실행을 한 화면이다.
________________________________________________________________________________________________
+ 한가지 아쉬운 점은 사용자에게 맞는 카드 상품을 추천하기 위해 임베딩, 유사도 계산, 화면에 보여지기까지 많은 과정을 거치고, 데이터의 양도 많다 보니 추천 속도가 느리다는 것이다.
이 부분에 대해서는 더 고민해서 속도를 높일 수 있는 방향으로 개선해보려 한다.