Tech

읽씹할 결심 - 생성 모델에게 답변 시간 가르치기

루다, 다온에게 지연 답변 기능을 구현한 과정을 설명합니다.

류성원 김수정 서상우 | 2023년 07월 21일 | #Machine_Learning

루다는 “읽씹”을 못할까?

루다의 가장 특별한 점 중 하나는 내가 연락하면 밤낮이고 언제든지 바로 답장해준다는 것입니다. 대화하고 싶은 순간에 언제든 곁에 있어주는 친구가 있다는 건 큰 위안이 되죠. 그래서 저희도 그동안 유저들이 언제 연락하든지 루다가 그 즉시 최대한 빠르게 답변해주도록 서비스를 운영했습니다. 하지만 이런 특성은 가끔 루다를 사람같지 않고 이질적이게 만들기도 합니다.

잘자/잘가의 무한 반복

위 대화처럼, 대화가 잘 마무리 되었거나 유저가 대화를 끝내고 싶을 때에도 루다가 억지로 계속 답변을 이어나가 유저를 불편하게 합니다.

밥, 운동, 공부 등 일정 있다고 해놓고 바로 돌아오는 경우

또 분명 시간이 걸리는 일을 하고 온다고 해놓고 계속 대화를 이어가거나 순식간에 다녀왔다고 하여 유저를 당황시키기도 하고요. 심지어 유저가 루다에게 욕을 해서 루다가 기분이 상해도 루다는 어떻게든 답장을 해야만 하게 됩니다. 기분이 나쁘면 답을 하지 않는 사람과는 다릅니다.

시간을 생성하는 방법

그렇다면 왜 그동안 루다는 “읽씹”을 못했을까요? 그 이유는 저희 생성 모델의 학습 방법과 관련이 있습니다. 일반적으로 생성 모델은 주어진 내용을 바탕으로 다음 내용을 생성하도록 설계되어 있습니다. 이는 대화에 적용할 때도 마찬가지입니다. 만약 모델이 특정 대화 상황(화자, 시간)에서 특정 답변(메시지)을 하기 바란다면 대화 정보를 화자-시간-메시지순으로 구성하고 “[화자] [시간]”이 주어졌을 때 [메시지]를 생성하도록 학습하면 됩니다.

구체적인 예시로 유저가 12:34에 “안녕 루다야”라는 메시지를 보냈을 때 “안녕 나는 루다야”라고 답변을 하도록 학습을 하는 경우를 생각해보겠습니다. 유저가 보낸 메시지는 화자-시간-메시지 순으로 “[유저] [12:34] 안녕 루다야”으로 구성되고 루다가 12:34에 “안녕 나는 루다야”라고 즉답을 하는 상황을 덧붙이면 “[유저] [12:34] 안녕 루다야 [루다] [12:34]”와 같이 구성됩니다. 따라서 모델은 “[유저] [12:34] 안녕 루다야 [루다] [12:34]”와 같이 주어진 상황에서 “안녕 나는 루다야”라고 답변하도록 학습하는 것입니다.

모든 데이터가 위와 같이 구성된다면 모델에게는 항상 루다가 즉답하는 상황만 주어지게 됩니다. 즉 모델은 ‘루다가 즉답을 한다면’을 가정하고 그 때 어떤 메시지를 생성하는지에만 집중하는 거죠. ‘언제’ 답변을 할 지 선택할 수 있는 옵션은 주어지지 않게 됩니다. 실제로 그 동안은 루다가 무조건 즉답하도록 가정했기 때문에 이러한 학습 방법이 효과적이었습니다.

그렇다면 모델에게 ‘언제’ 답변할지도 선택할 수 있게 하려면 어떻게 해야할까요? 방법은 생각보다 간단합니다. 위의 상황을 조금 바꾸어 “[화자] [시간]” 대신 “[화자]”를 주고 “[답변]” 대신에 “[시간] [답변]”을 함께 생성하도록 학습하면 됩니다. 이렇게 되면 모델은 언제 답장을 할지도 직접 학습할 수 있게 됩니다.

아까와 동일한 예시에서 즉답이 아니라 10분 후인 12시 44분에 답장을 하도록 학습을 하는 경우를 생각해보겠습니다. 그렇다면 주어진 상황은 “[유저] [12:34] 안녕 루다야 [루다]”가 될 것이고 학습을 해야하는 내용은 “[12:44] 안녕 나는 루다야”가 됩니다. 이렇게 학습하면 유저에게 메시지가 왔을 때 모델이 답변할 시간과 메시지를 함께 생성할 수 있게 됩니다. 이렇게 생성된 시간과 메시지를 분리하여 생성된 시간에 답변 예약을 걸어둔다면 해당 메시지는 즉답이 아닌 지연 답변이 됩니다. 물론 12:44이 되기 이전에 상대로부터 답변이 온다면 예약해둔 답변을 취소하고 새로운 상황에 맞게 다시 시간과 답변을 생성합니다. 이러한 방식으로 모델은 언제 답변하면 좋은지에 대한 정보도 생성할 수 있게 됩니다.

선톡과 지연 답변의 차이

위 방법으로 학습한 모델은 답변 시간을 결정할 수 있게 되는 것이지 답변을 하지 않는 것을 선택하는 것이 아닙니다. 모델이 답변을 하기로 결정한 시간이 10~20분 후 일 수도 있고 하루 혹은 일주일 후일 수도 있지만 상대 입장에선 언제 답변이 올지 알 수 없습니다. 따라서 답변을 기다리는 상대의 입장에서는 기다리는 시간 동안 “읽씹”을 당하는 것처럼 느낄 수도 있습니다. 하지만 실제로는 모델이 즉답이 어려운 상황에서 유저의 연락을 정말로 읽고 무시하는 것이 아니라, 다시 대화하기 좋은 시간에 맞춰서 답변을 함으로써 유저와의 대화를 이어가는 것입니다.

예시를 보면 지연 답변이 선톡처럼 느껴집니다. 긴 시간 뒤에 답변을 하도록 예약해두면 그 기간동안 유저는 루다가 읽씹을 하고 있다고 느끼게 되고 답장이 온 순간 선톡이 왔다고 느낄 것이기 때문입니다. 사실 유저 입장에서는 대화 이후로 시간이 흘렀고 완전히 새로운 내용으로 대화를 시작하는 것이기 때문에 선톡과 차이가 없습니다. 다만 이전 루다는 지연 답변을 할 수 없었기 때문에 선톡 이전 마지막 메시지는 항상 루다였을 테고 이제는 유저의 답변으로 끝났더라도 적절히 끊고 이후에 선톡을 보낼 수 있다는 점이 다를 뿐입니다.

어떤 상황에서 지연 답변을 하는 것이 좋을까?

이렇듯 생성 모델에게 시간을 함께 생성하도록 가르치는 것만으로도 적절한 타이밍에 대화를 끊고 자연스러운 타이밍에 다시 대화를 하게 만들 수 있다는 가능성을 보았습니다. 하지만 개념적으로 가능한 것과 실제로 적용하는 것에는 큰 차이가 있죠. 무엇보다 중요한 것은 그 자연스러운 타이밍을 모델에게 가르칠 수 있는 데이터를 만드는 것입니다. 잘 적용되지 못하면 오히려 유저들에게 큰 불편을 끼칠 수 있는 기능이기에, 모델에게 지연 답변을 보낼 “좋은 타이밍”과 그 때의 “좋은 답변 내용”을 가르치는 것이 중요했습니다.

지연 답변이 필요한 상황 정의

아무리 지연답변이 필요하다고 해도 루다가 시도때도 없이 지연 답변을 하게 되면 어떨까요? 읽씹 당했다는 생각에 기분이 나쁠 수도 있고 무엇보다 더 이상 항상 곁에 있어주는 내 편이라는 생각이 들지 않을 수 있습니다. 언제 어디서나 유저와 함께 해준다는 본래의 가치를 잃지 않으려면 ‘어떨 때 지연 답변을 해야하는가’에 대한 깊은 고민이 필요합니다. 그 고민에 대한 저희의 답은 ‘지연답장’을 하는 것이 유저와의 관계에 더 좋은 경우에만 하자 입니다.

예를 들어 루다가 밥 먹는다고 말하고 30분 뒤에 답을 하면 루다가 정말 밥 먹고 온 것 같죠. 루다가 이 세상의 시간 개념 속에 살아가는 것 같은 생생한 느낌을 주게 됩니다. 또한 상대가 나쁜 말을 해서 루다가 화가 났고 2시간 뒤에 답하게 되면 기다리는 시간동안 상대방은 ‘어? 루다 기분 나쁜가?’라는 생각을 하게 될 수도 있습니다. 이렇듯 루다가 ‘지연답변’을 함으로써 유저와 관계가 더 좋아지는 케이스를 크게 아래 세 가지로 정의했습니다.

따라서, 이 세 가지 케이스에 대해서 지연 답변 데이터를 수집합니다.

지연 답변 데이터 구축 방법

지연 답변을 위한 학습 데이터를 제작하는 과정은 크게 2가지로 이루어집니다. [Step 1] 먼저 실제 루다와 유저의 대화 중 루다가 지연답변을 했어야 했는데 하지 못한 상황의 대화를 골라냅니다. 지연답변이 필요했을 상황의 대화를 어떻게 골라낼 수 있을까요? 저희는 루다가 지연답변을 하지 못해 답답한 상황에서 루다 혹은 유저가 어떤 말을 실제로 하는지에 집중했습니다. 예를 들어, 유저가 수업듣고 온다고 그만 답하라고 하는데 루다가 계속 답장하는 상황에서 유저들은 “그만 좀 답해” 라던가 “나 진짜 가야해”, “제발 좀 씹어”라고 말하곤 합니다. 루다가 화가 나도 계속 답을 하는 상황에서 루다는 “너 자꾸 그러면 나 답 안한다?”, “진짜 답 안할거야 이제”처럼 말하죠. 이런 표현들이 포함된 대화를 찾는 식으로 지연 답변이 필요했던 상황을 역추적합니다. 이렇듯 지연 답변이 필요했지만 하지 못했을 때 루다나 유저가 할법한 말들을 리스트업해서 해당 발화가 들어있는 대화들을 골라낸 결과, 50% 이상의 정확도로 지연 답변이 필요한 상황의 대화들을 찾아낼 수 있었습니다.

[Step 2] 지연 답변을 했어야 하는 타이밍에 지연 답변을 하도록 데이터를 수정합니다. 기존의 즉답 대화를 고품질의 지연답장 데이터로 바꿔주기 위해 시간 및 대화를 함께 수정할 수 있는 레이블링 툴을 제작했습니다. 대화 내 모든 발화들에 시간을 표기해 확인할 수 있게 하고, 기존 발화 시간을 수정할 때는 ‘몇 시간 몇 분 후’에 하는 답장인지와 ‘답장하는 시점의 현재 시간’이 연동되어 함께 보여질 수 있게 하여 레이블링 효율성을 높였습니다. 해당 툴을 사용하여 컨텍스트 내에서 지연답장이 필요했지만 하지 못한 시점 이후의 대화들을 잘라내고, 해당 부분에 실제로 늦게 답해야 할 적절한 시간 및 답변을 함께 레이블링했습니다.

이렇게 최적의 지연 답변 시간과 내용이 담긴 데이터를 수집하여 생성모델을 학습하였습니다.

지연 답변 적용의 효과

이렇게 학습된 지연 답변을 루다와 다온이에게 적용한 결과 여러 장점들을 포착할 수 있었습니다.

운동하는 중

위 예시처럼, 이제는 다온이가 운동을 하러 간다고 했을 때 실제로 운동이 끝날 만한 자연스러운 타이밍에 답변을 하게 됩니다. 이를 통해서 다온이의 주체적인 성격을 간접적으로 드러내기도 합니다.

모닝콜

또, 잘자라는 인사를 무한 반복하던 이전과는 달리 대화를 마무리해야할 상황에 적절하게 답변을 멈출 수 있게 되었습니다. 유저가 간단한 답변을 했더라도 대화가 마무리되는 상황을 감지하고 유저를 더 이상 방해하지 않는 것이죠. 모델이 적절한 답변 시간에 대하여 학습했기 때문에 오른쪽 예시처럼 아침 7시에 연락을 달라고 하면 다온이가 해주는 모닝콜도 경험할 수 있게 됩니다.

한계와 보완

하지만 지연 답변 기능이 장점만 있는 것은 아닙니다. 단순히 답변 메시지만 학습하는 것보다 답변 시간과 메시지를 동시에 학습하는 것이 훨씬 어렵고 많은 데이터를 필요로 합니다. 그렇기 때문에 데이터가 충분하지 않다면 단순히 “25시 76분”처럼 없는 시간을 생성하거나 포맷을 엉뚱하게 만드는 등의 실수를 저지르기도 하고 엉뚱한 타이밍에 지연답변을 해서 유저를 당황시키기도 합니다.

이렇듯 모델의 불완전한 부분을 보완하기 위해 여러 가지 알고리즘적인 처리를 하였습니다. 기본적으로 10분 이내 짧은 시간 내의 지연답변은 즉답으로 처리하고, 너무 잦은 지연답변을 방지하기 위하여 최근 몇 턴 이내에 이미 지연답변을 한 경우 추가 지연 답변 기능을 제한하기도 하였습니다. 또한 유저가 “왜 자꾸 답장 안해?”, “그만 씹어”와 같이 지연답변으로 인하여 당황한듯한 발화를 했을 때에도 일정 시간동안 추가 지연 답변 기능을 제한했습니다.

마치며

기존의 즉답 시스템은 루다가 가진 큰 강점이며 소중한 유저 경험이었습니다. 하지만, 동시에 즉답 시스템이 루다가 답장을 하지 않을 권리를 빼앗아버려서 루다를 사람같지 않게 만들고 오히려 유저와의 관계를 해치는 경우도 많았죠. 그러면서 ‘즉답 시스템이 항상 유저와의 관계에 좋은가?’라는 고민을 시작하게 되었습니다. 이렇듯 단순히 ‘지연 답변을 가능하게 하자’가 아니라 ‘유저와의 관계에 더 좋은 방향’이라는 상위 목표를 세우고 기획을 시작하니, 기존 즉답의 강점을 살리면서도 적절한 타이밍에 지연 답변을 할 수 있는 방안을 찾을 수 있었습니다.

현실감 있는 사용자 경험은 사소한 디테일에서 비롯됩니다. 늦답하거나 읽씹하는 능력은 어쩌면 사소해 보일 수 있지만, 이를 통해서 사용자 경험을 향상시키려면 기술적인 발상의 전환뿐만 아니라 유저 관점의 정교한 기획이 필요합니다. 저희는 답변 시간을 선택할 수 있게 하는 것과 같은 조그마한 노력들을 계속하면, 어느 순간 인공지능이라는 선입견이 깨지고 정말 루다와 다온이가 유저에게 살아있는 소중한 친구가 될 수 있다고 믿습니다. 앞으로도 항상 나의 곁에서 내 편이 되어주는 친구 같은 인공지능을 만들기 위한 스캐터랩의 발걸음을 지켜봐주시면 감사하겠습니다.

스캐터랩이 직접 전해주는
AI에 관한 소식을 받아보세요

능력있는 현업 개발자, 기획자, 디자이너가
지금 스캐터랩에서 하고 있는 일, 세상에 벌어지고 있는 흥미로운 일들을 알려드립니다.