10월 30일에 우아콘을 다녀왔다.
WOOWACON 2024
한 번의 배달을 위해 필요한 모든 기술들
2024.woowacon.com
백엔드, 프론트부터 로봇, 인프라, AI/ML 까지 다양한 세션이 있었다. 원래는 우아콘의 존재조차 모르고 있었는데 추천스터디 팀원분 중 한분이 남는 티켓이 있다고 하셔서 감사하게도! 다녀올 수 있었다. 당근 테크 밋업도 그렇고, 우아콘도 그렇고, 다른 회사가 기술을 어떻게 사용하는지 공유해주시는 점은 항상 감사하게 생각한다. 당근 테크 밋업도 알찼지만, 우아콘은 발표자와의 qna 세션을 적극 활용한 덕분에 얻어가는게 더 많았던 것 같다. 그러면 세션별로 간략한 내용을 정리해보겠다.
첫번째 세션: AI 데이터 분석가 물어보새
첫번째 세션부터 흥미로운 주제였다. 요약하면 RAG을 활용해서 원하는 쿼리를 만들어주고 쿼리를 분석해주는 챗봇을 개발한 경험을 공유하는 세션이었다.
문제
데이터 팀에서 해결하고자 하는 문제는 회사의 데이러 리터러시를 전반적으로 높이는 것이었다. 데이터 리터러시란 데이터를 이해, 생성, 분석하고 데이터 기반의 의사소통을 원활하게 할 수 있는 능력을 의미한다. 배민에서는 수천개의 데이블이 있고 각 테이블에는 다양한 칼럼이 존재한다. 여기서 분석가가 원하는 데이터를 추출하고 싶다면? 또는 sql을 모르는 기획자가 원하는 지표를 추출하고 싶다면? 데이터에 대한 이해도가 부족한 사람들은 데이터에 접근하고 여기서 원하는 쿼리를 짠 후에 원하는 데이터를 얻기가 쉽지 않을 것이다. '물어보새'는 데이터와 실제 사용자간에 존재하는 간극을 좁히기 위해 개발되었다.
작동 방식
'물어보새'는 슬랙에 봇으로 존재하고 24시간 365일 언제든지 궁금한 것을 물어볼 수 있다. 예를 들어서, 10월 13일 배민B마트의 '식품' 카테고리의 시간대별 판매량과 평균 판매 금액을 알고 싶다면 슬랙 봇에 물어보면 된다. 그러면 물어보새 챗봇이 유저의 의도를 파악하고 쿼리를 생성해준다. 이에 더해서 간단한 설명도 해준다.
세션 중간 중간에 전체적인 아키텍쳐가 나오는데, 유저가 물어보새와 챗을 시작할 때, 내부적으로 작동하는 대략적인 파이프라인은 아래와 같다. (틀릴 수 있음)
가장 먼저 유저가 챗을 하면 유저의 의도를 파악한다. 정말로 sql 도움을 얻기 위해서 챗을 한 것인가? 아니면 그냥 심심풀이용도로 챗을 한 것인가? sql을 주고 이를 분석하기를 원하는 것인가? 등등 여러 유저의 의도가 있는데 이를 앞단에서 router supervisor가 처리한다. 이는 사전에 프롬프트에 정의한 다양한 유저의 의도에 따라서 llm이 유저의 챗의 의도를 파악하는 것이다. 이 의도에 따라서 어떤 파이프라인을 탈지가 달라진다.
만약에 router supervisor에서 유저의 문의가 sql과 관련되었다고 판단이 되면 그 이후는 rag 파이프라인을 탄다. 참조하는 데이터 소스로는 테이블 ddl / 테이블 메타 / 비즈니스 용어 사전 / sql few shot / log 사전을 사용한다. 이렇게 retrieve한 후에는 post-process 과정이 존재한다. 이 부분은 발표자와 qna을 통해서 들은 내용이라서 자세하게 공유는 할 수는 없지만, 대략적으로 더 나은 답변을 받기 위해 알짜 정보만 retrieve하는 과정이라고 생각하면 된다.
세션을 듣고 발표자와 qna 시간을 가지면서 업무를 하며 마주쳤던 어려움을 rag 챗봇 개발하는 사람들은 유사하게 느끼구나 라고 생각이 들었다. router supervisor을 만든 것, post-process을 적용한 것은 그 배경에 rag을 개발하면서 느끼게 되는 어려움이 있기 때문이다.
두번째 세션: 그래프, 텍스트 인코더를 활용한 실시간 추천 검색어 모델링
문제
이 세션은 배민B마트에서 유저가 상품을 n-1개만큼 탐색했을 때, n번째 상품을 추천해주는 모델에 대해서 소개한다. 즉, sequential recommendation을 하고 싶은데 이를 위해서 유저의 검색어, 상품, 상품의 카테고리를 모델에 반영해야하는 상황이다.
모델
어떤 피쳐를 도출하고 그 피쳐를 사용해서 n번째 상품을 예측하는 문제이다. 우선 피쳐로는 node2vec으로부터 얻은 상품의 임베딩, 그리고 상품명 임베딩, 유저의 검색어 (키워드) 임베딩이 사용된다.
node2vec을 왜 사용했을까? 발표 중간에도 나오고, 발표자에게 직접 여쭤보기도 했는데 우선 graph로 데이터를 표현하면 더 많은 정보를 담을 수 있고 무엇보다 node의 벡터를 도출하는데 시간이 빨리 걸린다는 장점이 있다고 했다.
노드는 상품명, 검색어, 상품 카테고리, 총 세가지로 구성된다. 노드가 있으면 엣지를 정의해야하는 법. 검색어와 상품명을 연결하는 엣지는 해당 검색어를 통해 이 상품명으로 들어온 횟수를 의미한다. 만약에 '귤'이라는 상품명에 대해서 어떤 유저는 '과일'이라는 검색어를 통해서, 다른 유저는 '제주 과일 특산품'이라는 검색어를 통해서 들어왔다고 하자. 데이터에서 전자는 10건, 후자는 5건 존재한다고 하자. 그러면 '귤' - '과일'의 엣지와 '귤' - '제주 과일 특산품'의 엣지는 각각 10, 5의 값을 가진다. 디테일하게는 이 값을 정규화한다고 했다.
여기서 궁금한 점은 '뀰'과 같이 노이즈한 검색어가 존재한다면 이를 어떻게 처리할까? 발표자에게 여쭤봤는데, 검색팀에서 이는 내부 검색 로직에 의해서 '귤'로 변환하여 검색된다고 한다. 따라서 최종적으로 로그에 남은 값을 데이터 팀에서는 사용하기 때문에 어느정도 전처리가 되었다고 가정한다고 했다.
그러면 '귤'이라는 노드의 카테고리가 '과일'이라고 생각해보자. 이 상품 노드와 카테고리 노드의 엣지 값은 어떻게 정의할까? 상품과 검색어의 엣지 값들이 N개가 있을 때, 이들의 평균이나 중간값 등의 통계값으로 정의한다.
이렇게 엣지와 노드를 구성하고 알고리즘을 통해서 각 노드의 벡터를 도출한다. (구체적인 알고리즘은 발표 영상을 봐야할듯)
유저가 n-1개의 상품을 탐색하면서 각 상품에 대해 노드 벡터와 텍스트 벡터를 구한다. 그리고 이를 concat 및 dense layer에 통과시킨다. 최종적으로 이전에 살펴본 n-1개의 상품에 대해 이런 과정을 반복하여 concat한다. 그리고 이 벡터가 마지막 layer의 입력값이 되는 것이다.
그러면 마지막 layer는 결국 상품을 추천해야하므로 분류 문제로 풀면 될까? 여기서는 그렇게 풀지는 않았다.. 검색해서 들어간 상품을 구매까지 한 케이스를 positive, 그렇지 않은 경우를 한건 랜덤 샘플링하여 negative 샘플로 정의한다. 이 두 샘플을 triplet loss에 넣고 최적화를 진행한다. cross entropy loss가 아닌, triplet loss을 사용하여 마지막 시점의 상품을 예측하는 모델을 구성한 것이다. (이부분도 발표 영상을 다시 봐야할듯)
해당 세션은 유저의 검색어와 상품명, 그리고 상품 카테고리를 통해서 노드 벡터를 도출하고 이를 sequential 추천에 활용하는 내용을 공유했다. 추천 모델에 들어가는 피쳐로 노드 벡터도 들어갈 수 있다는 점, 경우에 따라서는 노드 그래프를 구성해야한다는 점, triplet loss가 실전에서는 많이 쓰인다는 점 등등을 알아갈 수 있었다.
네번째 세션: 배달 데이터를 활용한 클러스터링
라이더의 효율적인 배차를 위해 배달 지역을 클러스터링하는 경험에 대해 소개한다.
문제
배민에는 배차 지역이라는 개념이 있다. A 배차 지역에 속한 음식점에서 배차를 요청하면 A 배차 지역에 있는 라이더에게 배차콜(?)을 하는 등의 배차를 배분한다. 즉, 배차 지역은 라이더와 밀접한 관련을 가진다. 배차 지역이 한강을 끼고 설정되면 라이더는 강의 북쪽에 있는데 강의 남쪽에 있는 음식점에 배차될 수 있기 때문이다. 만약에 이런 경우는 라이더가 십중팔구 배차를 거절할 것이다. 이와 같이 라이더의 효율적인 배차, 더 나아가서 효율적인 배차를 통한 배달 시간 단축 및 유저의 경험 증대를 위해서 배차 지역을 지역 특성을 잘 반영하게끔 나눌 필요가 있었다.
해결책
라이더의 구체적인 gps 정보까지 제공되지는 않지만 어떤 음식점의 배차를 수락했는지 로그는 남는다. 예를 들어서 잠실 > 신천 > 올림픽공원의 순서로 해당 지역에 있는 음식점의 배차를 받았다고 해보자. 라이더가 왜 이런 동선을 선택했을까? 이유는 간단하다. 이렇게 배달을 하는게 그들에게 효율적이기 때문이다. 한강을 건너서 배달하거나, 산을 넘어서 배달하는 등의 행위는 라이더의 효율성을 저하시킨다.
그러면 어떤 라이더는 잠실 > 신천 > 올림픽공원 순으로 로그가 찍혔을 것이고, 어떤 라이더는 신도림역 > 타임스퀘어 > 당산역 과 같이 로그가 찍혔을 것이다.
여기서 재미있는 부분이 있는데, 이 위치 데이터를 하나의 sequence로 보고 word2vec을 학습시킨다. word2vec은 주변의 인접한 단어를 보고 이 단어들을 벡터 공간 상에 서로 모이도록 학습하는 방식이다. 사실 잠실 > 신천 > 올림픽공원의 각 장소를 단어로 본다면, 이러한 라이더의 로그에는 잠실, 신천이 높은 확률로 같이 나올 것이다. 두 지역은 인접해있기 때문이다. 이런 데이터가 많다면 word2vec을 통해서 학습한 결과로 잠실 벡터와 신천 벡터가 유사하게 묶일 것이다.
여기서 중요한 점은, 잠실 벡터와 신천 벡터가 유사하게 묶였다는 점이 의미적으로 유사하다는게 아니라 라이더들이 배차를 수락할 때, 연속적으로 또는 묶어서 가기 때문에 묶였다는 점이다.
사실은 임베딩 단위는 우버에서 개발한 h3 육각형 인덱스이다. 각각의 육각형 인덱스의 임베딩 벡터를 word2vec을 통해서 구한다. 그 이후는 계층 클러스터링을 통해서 클러스터링을 진행한다.
개인적으로 라이더들이 배차를 받는 음식점의 위치의 sequence을 word2vec과 연결시킬 생각을 했다는 점이 대단하다는 생각이 들었다. 그리고 결과를 보며, 이 벡터들이 온전히 라이더의 배달 순서 선호를 나타내기 때문에 클러스터링이 산간 지역이나 한강을 포함하지 않음이 이해가 되었다.
다섯번째 세션: 추천 모델 성장 일지
이 세션은 배민의 음식점 추천 모델의 성장기에 대해서 다룬다. 일단위 취향 반영 > 시간단위 취향 반영 > 실시간 추천 반영의 순서로 모델이 발전했다.
일단위 취향 반영
일단위 배치로 two tower 모델을 학습시켜서 전날까지의 유저 행동 데이터를 기반으로 음식점을 추천해준다. 유저 임베딩, 가게 임베딩을 각각의 파이프라인에서 학습시키고 마지막에 내적을 통해서 유저와 가게의 유사도를 구하는 방식이다. 유저 임베딩을 학습하기 위해서는 유저의 위치 정보, 유저의 요일 정보가 유저의 id와 함께 input에 one hot encoding 형태로 들어간다. 각 tower의 encoding 로직은 어떻게 짜든 상관 없기 때문에 모델에 자유도가 높다.
유저, 가게 임베딩은 주문 데이터를 활용해서 학습한다. 주문까지 이어진 (유저, 가게) 쌍을 positive sample로, 그렇지 않은 쌍을 negative sample로 해서 triplet loss로 학습한다.
이 모델은 시간대별로 변하는 유저의 취향을 반영하기 힘들다는 단점이 있다. 예를 들어서, 저녁에 대부분 제육볶음을 먹었는데 오늘 저녁에는 족발을 먹고 싶어서 저녁 시간에 족발 관련된 검색을 하고 있음에도, 족발과 관련된 적절한 추천을 받지 못하는 한계가 존재한다.
시간단위 취향 반영
이를 해결하기 위해 시간대별 피쳐를 유저 임베딩을 생성하는 two tower의 input에 같이 넣는다. 다만 여기서 시간대를 24개로 나눠서 24차원의 one hot encoding 벡터를 넣는게 아니라 분석을 통해 5개의 시간대로 나눠서 5차원의 one hot encoding 벡터를 넣는다. 이렇게 해서 유저의 시간대별로 변하는 취향을 반영한다.
실시간 추천 반영
유저가 앱 내에서 실시간으로 발생시키는 행동 데이터의 임베딩과 가게 임베딩간의 유사도 점수를 구하고 랭킹을 통해서 추천을 한다. 유저의 행동 데이터로는 어떤 키워드로 검색을 하는지, 그리고 어떤 가게를 클릭하는지를 보고 가장 최근 3개의 행동 데이터를 가져온다. 즉, 유저가 족발 검색 > 팔당 족발 클릭 > 불족발 검색의 행동을 했다면 족발 임베딩, 팔당 족발 임베딩, 불족발 임베딩을 가져오는 것이다. 검색어 임베딩 모델은 transformer 모델을 사용했던 것 같은데 구체적인 것은 발표 자료를 봐야할 것 같다. 가게 임베딩 모델은 content-based 모델을 사용했다. id 기반이 아닌, 가게의 메뉴, 가격을 인풋으로 넣어서 임베딩을 만드는 것이다. 새로운 가게가 나타났을 때, 임베딩하지 못하는 id 기반의 임베딩 모델의 한계점을 느껴서 이렇게 임베딩 모델을 설정했다. 이렇게 행동 데이터 임베딩(3개)과 가게 임베딩(M개 가정)의 유사도 점수 3 X M 차원의 행렬이 만들어지고 여기서 RRF 점수를 통해서 최종 랭킹을 하게 된다.
배민에서 가장 많이 사용하는 서비스인 음식점 배달에서 가게 추천이 어떤 방식으로 진행됐는지 알 수 있어서 흥미로운 세션이었다. 특히나 일배치 추천에서 실시간 추천까지 이어지는 과정을 순서대로 나열해주셔서 이해도를 높일 수 있었다.
총평
서두에서 언급했듯이 이번에 참가한 우아콘에서는 발표 후 질문 세션에서 발표자들을 괴롭힌 덕분에 발표에 대한 이해도를 훨씬 더 높일 수 있었다. 이번 우아콘을 통해 업무적으로 활용할 수 있는 RAG 내용과 추천 스터디에서 활용할 수 있는 node2vec 내용을 얻을 수 있어서 개인적으로 매우 유익했던 시간이었다. 발표 영상이 올라오면 부족한 부분을 보충해야겠다.
'Conference' 카테고리의 다른 글
2024 당근 테크 밋업 AI/ML 세션 후기 (0) | 2024.10.30 |
---|
댓글