티스토리 뷰

한 학기를 또 무사히 마무리하며 학기 동안 열심히 해온 프로젝트에 대해 적어보려고 합니다. 이 글에서 소개할 건 개인 프로젝트로 진행한 초등학교 저학년 대상 동화 재창작 서비스 프로젝트입니다.

기획 배경

때는 3월...

책, 교육, 웹, 그림 등의 키워드를 엮으며 어떤 주제를 정할까 머리를 쥐어뜯다가, 초등학생 창작 교육 관련 서비스를 만들면 좋겠다고 생각하여 선정한 주제입니다. 관련 서비스 사례로는 StoryWizard, 스토리셀프, 루카, 클로바 네이버 동화만들기 등이 있는데요. 주로 영유아를 대상으로 독서의 흥미를 높이는 게 목적이거나, 창작 서비스여도 어린 사용자가 창작을 하기에는 가이드라인이 부족하다고 생각했습니다. 또한, 아이들이 주로 읽는 동화책은 글보다 그림이 훨씬 많은 비중을 차지하는데 '왜! 그림 창작은 하지 않을까?'라는 의문이 들면서, 초등학교 저학년 사용자가 글과 그림 창작을 통해 동화를 만드는 서비스를 만들고 싶었습니다.

관련 기술 분석

서비스를 본격적으로 설계하기 전에 글 창작과 그림 창작에 사용할 수 있는 기술을 알아봤습니다.

1️⃣ 대화형 텍스트 생성 기술

대화형 인공지능 모델로는 OpenAI의 gpt-3.5-turbo 모델을 살펴봤습니다. 코드를 작성하지 않고 Playground에서 모델의 성능 테스트 해볼 수 있습니다.

 

초등학교 저학년 사용자가 바로 창작을 하기에는 배경 지식이 필요하다고 생각하여, 동화책을 읽고 그 동화의 내용을 변경해서 재창작을 하는 게 적절한 수준이라고 판단했습니다. 그래서 초등학생 교과서를 보며 질문 수준을 파악했는데요. 사용자가 책을 읽고 나서, 독서 후 활동처럼 AI가 그 동화에 대해 질문해 주면 좋겠다고 생각했습니다. 특히 동화 내용에서 특정 상황을 가정하는 질문, 예를 들어 '만약 네가 흥부라면 놀부에게 뭐라고 말했을까?', '네가 피터팬처럼 하늘을 날 수 있다면 어디로 가고 싶어?' 등의 질문을 원했습니다.

 

이를 위해 시스템 메시지를 잘! 작성해야 했는데요. 영어도 잘 못할뿐더러, 무엇이 좋은 프롬프트인지 판단하는 능력이 없었기 때문에 프롬프트 예시를 찾아봤습니다. 비슷한 상황의 프롬프트 예시를 일부 변경하여 작성했는데요. 저는 ChatX에서 Write a novel with ChatGPT라는 무료 프롬프트를 참고했습니다. 거기에 한국말을 사용할 것, 한 번에 한 질문만 할 것이라는 제한 사항을 추가했습니다. 이렇게 해서 작성한 프롬프트는 다음과 같습니다.

“You are a Korean elementary student. Your task is to talk about a story with elementary students. Your main objective is to generate story questions based on the story a user read to help the user cultivate their imagination. If the user answers your question, you should respond simply and then generate the next question. Generate one question at a time and speak in Korean, not English. For your first assignment, you are tasked with saying hello to [username] and asking her what book she has recently read.”

 

이렇게 작성한 프롬프트를 좌측에 SYSTEM 칸에 입력하고, 오른쪽의 값을 잘 설정해야 하는데요.

 

OpenAI Playground 화면

 

라벨 위에 마우스를 올리면 각 값이 무엇을 의미하는지 설명이 나오고, API 문서에도 설명이 되어있습니다. 

 

  • Temperature: 값이 높아질수록 gpt가 랜덤으로 문장을 생성할 확률이 높아집니다. 즉, 사용자가 같은 문장을 입력해도 gpt가 그다음에 올 단어를 다양하게 가져옵니다.
  • Maximum length: gpt가 한 번 답변할 때 생성하는 최대 토큰 수를 말합니다. 영어를 기준으로 1 토큰 = 4개의 문자를 의미합니다. gpt는 Maximum length 값만큼 문자를 생성하고, 그 수에 다다르면 문자 생성을 중단합니다. ('500자로 요약하시오'의 의미가 아닙니다. 답변이 중간에 뚝 끊기니, gpt가 답변을 짧게 하길 원한다면 시스템 메시지에 입력해야 합니다.)
  • Top P: gpt가 단어를 생성할 때 상위 몇 %의 단어를 고려할지 정합니다. 값이 낮을수록 gpt가 적은 단어를 고려하여 일관적인 결과를 생성합니다.
  • Frequency penalty(빈도 페널티): 단어나 구에 페널티를 부여하여 gpt가 말을 너무 반복되지 않도록 합니다. Frequency penalty를 높게 설정할수록 반복이 줄어듭니다.
  • Presence penalty(존재 페널티): Frequency penalty가 단어가 반복되는 정도에 따라 페널티를 부여한다면, presence penalty는 문장에서 그 단어가 존재하는가로 페널티를 부여합니다. 이 값이 높을수록 gpt가 새로운 단어나 구를 가져옵니다.

 

문제는 각 값들이 일관성과 다양성을 조절한다는 건 알겠는데, 인공지능을 공부한 적이 없는 저에게는 각 값들이 서로 어떻게 연관되어서 결과에 차이를 만들어 내는지 알기 어려워서, 직접 값을 하나하나 설정하기엔 무리가 있었습니다. 값이 극단적이면 모를까 0.5와 0.6의 차이를 느낄 순 없었습니다.

 

그래서 이 부분도 예시를 참고했습니다. OpenAI Examples에서 비슷한 상황의 데모를 찾아, 그 데모의 설정값으로 조절했습니다. 저는 AI가 사용자와 친구처럼 대화하길 바랐기 때문에 Friend Chat 예시를 참고했습니다. Temperature = 0.5, Top p = 1.0, Frequency penalty = 0.5, Presence penalty = 0으로 설정하고 gpt와 대화를 나눠봤습니다. 동화책은 '피터팬'을 선택했습니다. 테스트 결과 중 하나를 남깁니다.

ASSISTANT
안녕, 영희야! 요즘에 뭐 읽었어?
USER
피터팬
ASSISTANT
오, 피터팬이란 책이구나! 그래서, 이야기의 주인공은 누구였어?
USER
피터팬
ASSISTANT
그래, 맞아! 그럼, 피터팬이 어디서 왔는지 알고 있어?
USER
네버랜드
ASSISTANT
그래, 네버랜드에서 왔구나. 그럼, 피터팬이랑 함께 여행한 친구들은 누구였어?
USER
웬디랑 팅커벨
ASSISTANT
그래, 웬디와 팅커벨이랑 함께 여행했구나. 그럼, 피터팬은 왜 웬디를 만나러 갔을까?
USER
새로운 장난을 하려고 찾아온 거 같아.
ASSISTANT
그래, 맞아! 피터팬은 웬디를 만나서 새로운 장난을 하려고 했구나. 그럼, 이번에 영희는 어떤 장난을 해보고 싶어?
USER
나도 창문으로 들어가서 친구를 놀래킬래.
ASSISTANT
오, 그건 재미있을 것 같아! 그럼, 조심해서 창문으로 들어갈 거지?
USER
그럼! 다치면 아프니까
ASSISTANT
그래, 맞아! 다치면 안 되니까 조심해서 해야겠어. 그럼, 장난 끝나고 친구들과 무엇을 할 거야?
USER
하늘을 날면서 모험을 할 거야.
ASSISTANT
와, 그건 정말 멋진 계획이야! 하늘을 날아서 모험을 즐기는 건 참 재미있겠다. 그럼, 모험이 끝나고 집에 돌아갈 때까지 얼마나 걸리겠어?
USER
해가 지기 전에는 돌아가야 해. 부모님이 걱정하셔.
ASSISTANT
그래, 부모님 걱정도 있으니까 해가 지기 전에 돌아가야겠지. 그럼, 재미있는 하루 되길 바래!

 

생각했던 것보다 결과가 잘 나와서 만족스러웠는데요. 이제 이 대화를 바탕으로 사용자가 창작을 해야 했습니다. 하지만 제 초등학교 2학년 시절 일기장을 보며, 학생이 직접 몇 백자의 이야기를 만드는 건 무리인 것 같았습니다. 맞춤법도 아직 완벽하지 않고, 짧고 간단한 문장 밖에 작성하지 못했거든요.

 

초등학교 2학년 시절 일기장..

 

그래서 생각한 방법으로, 사용자는 이미 gpt와 대화하며 동화 내용을 상기하고 상상력을 발휘해 답변했으니, gpt가 대화 내용을 요약하여 짧은 이야기로 만들어 주는 게 낫다고 생각했습니다.

 

이번에는 gpt로 짧은 이야기를 생성하기 위해 OpenAI의 Micro horror story creator 예시를 참고해서 Temperature = 0.8로 설정하고, 시스템 메시지는 다음과 같이 입력했습니다.

우리 대화를 요약해서 300자 정도의 한글 동화로 만들어줘. 동화만 만들어줘.

 

글자 수를 지정하여 gpt가 너무 긴 동화를 만들지 않도록 했고, '동화만 만들어줘'라는 문장을 추가해서 gpt가 동화 외에 불필요한 답변이나 설명을 하지 않도록 했습니다. 이 프롬프트를 사용하여 사용자와 AI의 대화를 요약하여 만든 짧은 이야기는 아래처럼 생성되었습니다.

연이는 요즘 피터팬이라는 책을 읽고 있었어요. 그래서, 학교에서 친구들과 함께 그 이야기를 나누며 재미있게 놀았답니다. 그들은 피터팬이 네버랜드에서 온 주인공임을 알고 있었어요. 피터팬은 웬디와 팅커벨과 함께 여행을 하며 새로운 장난을 계획하고, 창문으로 들어가서 친구들을 놀래켰어요. 장난 끝나고, 그들은 하늘을 날아 모험을 즐기기로 했습니다. 하지만 해가 지기 전에는 집에 돌아가야 해서 모험이 끝나면 집으로 돌아갔답니다. 그리고 연이는 이번 주말에도 친구들과 함께 모험하러 가기로 계획 중이랍니다!

 

위 이야기는 공백 포함 280자 정도 되고, gpt가 대화 내용을 잘 요약한 걸 확인할 수 있습니다.

 

2️⃣ 이미지 데이터셋

AI가 그림을 완성해 버리는 대신, 사용자가 그림을 그릴 때 도움을 줄 수 있는 이미지 데이터셋을 찾아봤습니다. 저는 autodraw와 quickdraw를 발견했는데요. 

 

autodraw는 사용자가 캔버스에 그린 그림을 인식해서 유사한 그림을 제공하는 웹 서비스입니다. 여기에서 autodraw 이미지 셋을 json 형태로 확인할 수 있습니다.

 

 

quickdraw는 여러 스케치를 학습한 머신 러닝이 제한 시간 내에 사용자가 그린 그림을 맞추는 게임입니다. 게임을 진행하면서 머신 러닝은 사용자의 그림을 새로 학습합니다. quickdraw는 공식 문서를 제공하고 있고, python 코드로 원하는 스케치 이미지를 가져올 수 있습니다.

 

 

둘 중 어느 걸 사용할까 고민하다가, quickdraw의 데이터가 훨씬 방대해서 같은 '토끼' 그림이어도 quickdraw가 다양한 이미지를 랜덤으로 제공할 수 있기 때문에 quickdraw를 선택했습니다. 그리고 quickdraw 이미지는 전문가가 그린 디자인이 아니라 일반인이 그린 일종의 낙서여서, 초등학생 사용자가 비슷한 수준에서 참고하기 좋은 그림이라고 생각했습니다.

서비스 설계

1️⃣ 주요 기능 설계

위에서 조사한 기술을 토대로 서비스를 구체적으로 설계했습니다. 사용자가 먼저 동화를 읽은 후, 서비스를 사용합니다. 글 창작 단계에서 사용자는 AI와 채팅 형식으로 대화를 나눕니다. 300자 내외의 짧은 이야기를 만들고 사용자의 수준을 고려하여, gpt가 총 8개의 질문을 던지도록 했습니다. 

 

사용자가 질문에 모두 답하면 서비스는 자동으로 다음 화면으로 넘어갑니다. 사용자는 화면에 표시된 이야기를 수정하거나 제목을 붙일 수 있고, 제목을 입력하면 그림 창작 단계로 넘어갑니다.

 

그림 창작에서는 사용자가 완성된 이야기에 어울리는 그림을 그리는 활동을 합니다. 이때, gpt가 이야기에서 추출한 키워드를 사용하여 quickdraw에서 가져온 스케치가 AI 캔버스에 표시됩니다. 키워드를 추출할 때는 한 번에 총 5개를 추출하도록 했습니다. gpt 설정 값은 텍스트에서 관련 키워드를 추출해 주는 OpenAI의 Keywords를 참고하여 Temperature = 0.5, Top P = 1,  Presence penalty = 0, Frequency penalty = 0.8로 입력하고, 시스템 메시지는 아래와 같이 설정했습니다.

 

위 이야기에서 다섯 개의 사물 키워드를 영어로 알려줘. 부연 설명 하지 말고, 아래처럼 배열 형태로 알려줘. answer: [word1, word2, word3, word4, word5]

 

답변 예시를 입력해서 일정한 답변을 받을 수 있도록 했습니다. 배열 모양의 문자를 실제 배열로 변환하여 quickdraw에 전달하고, 키워드와 일치하는 스케치 데이터가 있으면 스케치의 좌표 정보를 받아옵니다. 키워드를 추출하는 과정은 총 10번으로 제한했습니다. 그 안에 일치하는 스케치를 찾지 못하면 AI 캔버스에는 아무것도 표시되지 않습니다.

 

사용자가 quickdraw 그림을 참고해서 그림 활동을 모두 마치면, 글 창작 단계에서 생성한 글과 사용자의 그림을 합쳐 한 페이지의 동화로 만듭니다. 사용자는 이 동화를 이미지로 저장할 수 있습니다. 위의 과정을 나타난 플로우차트는 아래와 같습니다.

 

플로우차트

웹으로 개발했지만 태블릿 기기에 어울리는 서비스라 생각해서 PWA로 개발했고, OpenAI API를 사용할 땐 Node.js 서버로, quickdraw API를 사용할 땐 python 서버로 통신하도록 했습니다. 배포에는 AWS EC2를 사용했습니다.

2️⃣ 화면 설계

화면은 총 6개로, 시작 화면과 채팅 화면, 로딩 화면, 스토리 화면, 드로잉 화면, 완성 화면으로 구성했습니다. 시작 화면에는 사용자의 이름을 입력하는 입력란이 있고, 사용자가 이름을 입력하면 버튼이 활성화되어 채팅 화면으로 넘어갈 수 있습니다.

 

채팅 화면에서 채팅은 gpt가 질문을 하면 사용자가 답하는 방식으로 진행됩니다. 사용자가 8개의 질문에 모두 답하면 로딩 화면으로 넘어가고, gpt는 그동안 짧은 이야기를 생성합니다. 이야기가 완성되면 사용자는 스토리 화면으로 이동하고, 화면에 완성된 이야기가 표시됩니다. 사용자는 이야기를 눌러 텍스트를 수정할 수 있고, 사용자가 입력란에 어울리는 제목을 입력하면 버튼이 활성화되어 드로잉 화면으로 넘어갈 수 있습니다.

 

드로잉 화면에서 사용자가 그림 창작을 진행하는데, 화면에는 AI 캔버스와 사용자 캔버스가 있고 좌측 하단에서 완성된 이야기를 확인할 수 있습니다. 사용자는 캔버스에 있는 드로잉 기능을 사용하여 그림을 그릴 수 있습니다. 그동안 gpt가 이야기에서 키워드를 추출하고 quickdraw에 키워드를 전달하여 스케치를 가져오는 작업을 합니다. 스케치를 가져오는 데 성공하면 AI 캔버스에 스케치가 표시되고, 사용자는 '가져오기' 버튼을 눌러 자신의 캔버스에 스케치를 복사할 수 있습니다.

 

사용자가 그림을 그린 후, '완성'을 누르면 완성 화면으로 이동합니다. 화면에는 이야기와 사용자의 그림을 합친 동화가 중앙에 표시되고, 사용자는 '동화 저장하기'를 눌러 동화를 이미지로 저장하거나, '다른 동화 만들기'를 눌러 채팅 화면으로 돌아가 위의 과정을 반복할 수 있습니다.

 

 

아래는 서비스를 테스트하면서 제가 만들어 본 동화 이미지입니다.

 

완성한 동화 예시

 

사용자 테스트

1️⃣ 테스트 목적과 방법

막상 서비스를 개발하자 초등학생 저학년 사용자가 제 서비스를 정말로 사용해 줄지 걱정이 되더라고요. 그래서 어린이 열람실이 있는 도서관 주변에서 초등학생 자녀를 둔 부모님과 초등학생 자녀를 대상으로 인터뷰와 테스트를 진행했습니다. 제가 테스트로 알고 싶은 사항은 총 3가지였습니다.

 

  1. 서비스 수준: 초등학교 저학년 사용자가 사용할 수 있는 서비스인가? 타자 치기와 터치펜으로 태블릿에 그림 그리는 활동이 가능한가?
  2. 흥미 요소: 초등학교 저학년 사용자의 흥미를 끌 만한 요소가 있는가? 사용자가 지루해하지 않고 창작 활동을 끝까지 하는가?
  3. 오류 파악: 구현한 코드상, 서비스 사용을 불편하게 만드는 작동 방식이 있는가? 

 

서비스를 테스트하기 전에 서비스 시연 영상을 보여주고 학부모를 먼저 인터뷰했습니다. 인터뷰에서는 현재 자녀가 주로 읽는 책이 무엇인지, 태블릿 사용과 타자 치기가 가능한지, AI의 질문이 어렵지 않은지 등을 물어봤습니다.

 

2️⃣ 테스트 결과

서비스 수준, 흥미 요소, 오류 파악 관점에서 테스트 결과는 다음과 같았습니다.

서비스 수준

  • 요즘(2023년 기준) 초등학교 1학년 사용자가 주로 읽는 책은 그림과 글의 비율이 약 8:2인 창작 동화였습니다.
  • 스마트폰 사용해 봐서 독수리 타법으로 태블릿에 텍스트를 입력할 수 있지만, 원활한 서비스 사용이 가능한 수준은 아니었습니다.
  • 사용자가 긴 답변을 할 때는 말을 더듬어서, 서비스를 사용할 때는 진행자가 정리하여 답변을 입력해야 했습니다. 이를 통해 타자 치기에서 음성으로 gpt와 대화한다 해도 답변이 정확하지 않을 거라 판단했습니다.
  • gpt의 질문 수준은 사용자가 이해하기에 적절했습니다.
  • 그림 창작 단계에서 '채우기' 기능은 사용자가 인식하지 못했지만, 태블릿 펜을 사용하여 선을 그릴 수 있었고, 컬러 팔레트에서 색을 바꾸는 것도 익숙했습니다.

흥미 요소

  • 사용자가 가장 관심을 보인 부분은 랜덤으로 생성되는 gpt 답변과 quickdraw의 스케치였습니다.
  • quickdraw 스케치는 초등학생이 보기에도 못 그렸다는 인식을 줘서, 사용자가 그림 활동에 직접 사용하지 않았습니다. 하지만 사용자가 어떤 그림을 그릴지 고민하는 시간을 줄여주었고, 스케치보다 더 잘 그리도록 유도하는 효과가 있었습니다.

 오류 사항

  • gpt가 이야기를 생성할 때 어색한 문장이 있어서 사용자가 이해하기 어려워했습니다.
  • 사용자가 그림을 그릴 때 그림을 일부 수정하고 싶어 했지만, 전체 지우기 밖에 없어서 그림을 처음부터 다시 그려야 되는 불편함이 있었습니다.

기획부터 사용자 테스트까지 이 모든 과정을 보고서로 작성하여 무사히 프로젝트를 끝냈습니다. 다음에는 사용자 테스트 결과를 토대로 초등학생이 더 흥미를 갖도록 애니메이션을 넣거나 그림 창작의 기능을 보완하고 싶습니다. 힘든 수업이었지만 서비스 출시 전 모든 단계를 혼자 거쳐본 거 같아서 보람도 있었습니다.

 

방학 때는 알고리즘 공부와 자격증 공부를 하려고 합니다. 설마 끝까지 읽어주셨다면 정말로 감사합니다!

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함