Amazon Web Services 한국 블로그

Amazon Lex V2의 Dialog Action을 통해 챗봇에 다양한 비지니스 로직 구현하기

지난 2021년 9월 Amazon Lex의 한국어 지원이 시작되었습니다. AWS 한국 블로그 에서는 이 소식과 함께 Amazon Lex의 사용방법에 대해 블로그로 전달해드렸는데요. 이번 글에서는Amazon Lex를 좀 더 확장성 있게 사용할 수 있도록 AWS Lambda와 연동하여 비지니스 로직을 추가하는 방법을 소개합니다.

Amazon Lex Chatbot(챗봇)이란?

Amazon Lex는 대화형 인터페이스를 애플리케이션에 설계, 구축, 테스트, 배포하기 위해 고급 자연어 모델을 사용하는 완전관리형 인공 지능(AI) 서비스입니다. Amazon Lex 챗봇은 연속적인 대화를 주고받을 수 있는 기능을 제공합니다. 의도가 파악되면 해당 의도를 이행하는 데 필요한 정보가 사용자에게 표시됩니다. 예를 들어,  Chatbot에서 사용할 될 Intents(의도)는 예약한 호텔을 검색해주는 searchHotel과 호텔을 예약해주는 BookHotel 입니다.

Chatbot을 처음 만드시는 분들은 이전 블로그에서 소개된 내용과 링크된 동영상을 참고하시면 어렵지 않게 만들 수 있는데요. AWS Sample 내 Chatbot 실습 가이드를 참고하시면, 더욱 쉽게 실습해 보실 수 있습니다.

AWS Lambda 연동하기

Chatbot이 완성되면, 좀 더 다양한 대화형 비지니스 로직을 구현하기 위해 AWS Lambda와 연동해보겠습니다. 우리가 사용할 아키텍처는 다음과 같습니다.

사용자가 발화를 할 때마다 Amazon Lex는 Lambda 함수를 호출합니다. AWS Lambda에서는 Amazon DynamoDB에 저장된 고객 예약정보를 질의하고, 결과를 반환합니다. 이때 GraphQL API를 사용합니다.  물론 Amazon DynamoDB API를 사용하셔도 되고 REST API를 사용하셔도 됩니다만, 이 글에서는 GraphQL API를 사용했습니다.  AWS Lambda에서는 질의 결과에 따라 적합한 동작을 취할 수 있도록 Amazon Lex에게 다음 조치를 포함한 응답 결과(Response)를 전달합니다. 이 ‘다음 조치’에 해당하는 것을 바로 Amazon Lex 의 Dialog Action을 사용합니다.

Amazon Lex콘솔에서 AWS Lambda를 연동하기 위해서는 옵션을 선택해야합니다.

첫번째 옵션은 각각의 사용자 발화 마다 AWS Lambda를 호출하기 위한 것입니다. 이 호출의 목적은 사용자 발화의 validation체크입니다. AWS Lambda가 호출될 때 Request가 전달되는데, 요청(Request) 의 invocationSourceDialogCodeHook으로 셋팅되어 전달됩니다. 이 옵션은 AWS  관리 콘솔에서 Amazon Lex -> Bot -> Intent  화면에 자리하고 있습니다.

두번째 옵션은 모든 slot(슬롯)이 다 찼을 때 AWS Lambda를 호출하기 위한 것입니다. 이 옵션은 사용자가 Intents에 필요한 모든 정보를 입력 했을 때(필수 슬롯이 찼을 때) AWS Lambda가 호출되어 검색 결과를 반환하는 용도로 사용됩니다. AWS Lambda로 전달되는 요청(Request)의 invocationSourceFulfillmentCodeHook으로 셋팅되어 전달됩니다.

이 옵션은 AWS Console에서 Amazon Lex -> Bot -> Intent->Fulfillment 화면에 자리하고 있습니다.

Chatbot에 2가지 옵션이 선택이 되었다면 사용자 발화 마다 연결된 AWS Lambda 함수를 호출합니다.

예제 Chatbot 시나리오

이제 실행 할 예제 Chatbot의 시나리오를 살펴보겠습니다.

시나리오1 :

  • 예약된 호텔을 검색하기 위해서는 예약할 때 사용된 고객 이름이 필요합니다. (아래그림 2번)
  • 예약한 도시의 이름이 필요합니다. (3번)
  • 이 두가지 정보와 일치하는 예약 정보가 데이타베이스에 있다면 해당 값을 조회하여 예약 정보(호텔 이름)을 알려주고 있습니다. (4번)

시나리오2 :

  • 만약 예약한 고객 이름과 동일한 이름의 예약이 있다면 추가로 고객의 전화번호를 확인합니다. (2번)
  • 고객 이름과 전화번호는 각각 사용자 발화 시 마다 데이타베이스에 등록된 정보와 일치 여부를 확인하게 되고 일치하는 정보가 없다면 다시 말씀 해달라고 요청합니다.(3번)
  • 도시명의 경우 사용자가 발화한 도시명을 올바르게 인식했는지 확인하는 절차가 포함되어있습니다. (5번)
  • 사용자가 발화한 도시명에 예약된 호텔 정보가 없다면 호텔 예약을 다시 하도록 유도합니다.(7번)

Amazon Lex V2의 Dialog Action 사용하기

Amazon Lex는 AWS Lambda에 요청(Request)을 보내고 결과값을 응답 결과(Response)로 받습니다. Amazon Lex V2에서의 Request, Response Format은 개발자 안내서에서 확인 가능합니다.

여기서 주목 해야할 것은 Response Format 중 Dialog Action입니다. 이 Dialog Action값을 받은Amazon Lex는 Dialog Action의 타입에 따라 다음 조치를 취할 수 있도록 사용자 발화를 유도하게 됩니다.

각 타입 별로 역할과 샘플 코드, 그리고 시나리오에서 사용된 Dialog Action이 어떤 것인지 살펴보겠습니다.

Close — 더이상 사용자의 발화가 필요 없을 때 사용합니다. 보통 FulfillmentCodeHook가 불렸을 경우 사용하면 됩니다. 시나리오1의 4번에 해당합니다. Response은 다음과 같이 구성하시면 됩니다.

return {
    sessionState: {
      sessionAttributes,
      dialogAction: {
        type: "Close",
      },
      intent: {
        confirmationState: "Confirmed",
        name: intent,
        state: fulfillmentState,
      },
    },
    messages: [
      {
        contentType: "PlainText",
        content: messageText,
      },
    ],
  };
};

ConfirmIntent — 사용자가 예 혹은 아니요 의 대답을 유도할 때 사용합니다. (시나리오1의 3번, 시나리오2의 5번) 사용자의 대답(예 혹은 아니요)은 다시 AWS Lambda함수로 전달됩니다. (Request의 sessionState.intent.confirmationState로 “Confirmed” 혹은 “Denied”가 셋팅되어 전달됩니다.)

return {
    sessionState: {
      sessionAttributes,
      dialogAction: {
        type: "ConfirmIntent",
      },
      intent: {
        name: intentName,
        slots,
      },
    },
    messages: [
      {
        contentType: "PlainText",
        content: messageText,
      },
    ],
  };

Delegate — AWS Lex에게 동작을 위임하는 경우에 사용합니다. 이 Dialog Action을 전달받은 Amazon Lex는 콘솔의 Chatbot 구성에 따라 다음 동작을 하게 됩니다. (시나리오1의 1번2번, 시나리오2의 1번, 3번, 6번)

return {
    sessionState: {
      activeContexts: activeContexts,
      intent: intent,
      sessionAttributes: sessionAttributes,
      dialogAction: {
        type: "Delegate",
      },
    },
  };

ElicitIntent — 사용자에게 다른 Intents가 포함된 발화를 할 것이라고 Chatbot에게 알려줄 때 사용합니다. (시나리오2의 7번)

return {
    sessionState: {
      sessionAttributes,
      dialogAction: {
        type: "ElicitIntent",
      },
    },
    messages: [
      {
        contentType: "PlainText",
        content: messageText,
      },
    ],
  };

ElicitSlot — 사용자가 해당 Slot을 발화하도록 유도합니다. (시나리오2의 2번, 3번) 예를 들어 사용자이름이 2개이상일때 구분하기 위해 전화번호 Slot을 발화하도록 유도합니다. 참고로 전화번호는 필수 Slot이 아닙니다. 그래서 Dialog ActionslotToElicit값으로 전화번호 Slot을 담아 보내면 전화번호를 말하도록 사용자 발화를 요구할 수 있습니다.

return {
    sessionState: {
      sessionAttributes,
      dialogAction: {
        type: "ElicitSlot",
        slotToElicit,
      },
      intent: {
        name: intentName,
        slots,
      },
    },
    messages: [
      {
        contentType: "PlainText",
        content: message,
      },
    ],
  };

위에서 설명 드린 시나리오 그림에 Dialog Action타입을 추가 해보면 다음과 같습니다.

이상으로 Amazon Lex V2 를 기반으로 AWS Lambda함수의 응답 결과 중, Dialog Action의 종류와 사용방법에 대해 설명을 드렸습니다. Dialog Action을 이해하는 것은 여러분의 Chatbot에 다양한 확인용 비지니스 로직을 추가하기 위해 반드시 필요한 과정입니다.

이 글에서 사용된 Chatbot(BlogBot)과 AWS Lamdba코드 (nodejs)는 AWS Samples에 업로드 되어 있습니다.

– 정창호, AWS 솔루션즈 아키텍트