2017-12-28 36 views
0

현재 amazon lex에서 대화방을 수행하고 있습니다. 그러나 어쨌든 그것을 시도하고 응답 카드 질문에 도달 할 때마다 프롬프트 질문이 중복 된 시간에 게시됩니다. 어떻게 한 번만 프롬프트하게 만들지, 아니면 Slack의 문제일까요?슬랙에 다중 프롬프트 응답 카드

import json 
import datetime 
import time 
import os 
import dateutil.parser 
import logging 
import urllib.request 

logger = logging.getLogger() 
logger.setLevel(logging.DEBUG) 

# --- Helpers that build all of the responses --- 


def elicit_slot(session_attributes, intent_name, slots, slot_to_elicit, message): 
    return { 
     'sessionAttributes': session_attributes, 
     'dialogAction': { 
      'type': 'ElicitSlot', 
      'intentName': intent_name, 
      'slots': slots, 
      'slotToElicit': slot_to_elicit, 
      'message': message 
     } 
    } 


def confirm_intent(session_attributes, intent_name, slots, message): 
    return { 
     'sessionAttributes': session_attributes, 
     'dialogAction': { 
      'type': 'ConfirmIntent', 
      'intentName': intent_name, 
      'slots': slots, 
      'message': message 
     } 
    } 


def close(session_attributes, fulfillment_state, message): 
    response = { 
     'sessionAttributes': session_attributes, 
     'dialogAction': { 
      'type': 'Close', 
      'fulfillmentState': fulfillment_state, 
      'message': message 
     } 
    } 

    return response 

def delegate(session_attributes, slots): 
    return { 
     'sessionAttributes': session_attributes, 
     'dialogAction': { 
      'type': 'Delegate', 
      'slots': slots 
     } 
    } 

# --- Helper Functions --- 

def safe_int(n): 
    """ 
    Safely convert n value to int. 
    """ 
    if n is not None: 
     return int(n) 
    return n 


def try_ex(func): 
    """ 
    Call passed in function in try block. If KeyError is encountered return None. 
    This function is intended to be used to safely access dictionary. 

    Note that this function would have negative impact on performance. 
    """ 

    try: 
     return func() 
    except KeyError: 
     return None 

def calculate_age(birthday, combine): 
    today = datetime.date.today() 
    birthdate = datetime.datetime.strptime(birthday, '%Y-%m-%d') 
    age = today.year - birthdate.year - ((today.month, today.day) < (birthdate.month, birthdate.day)) 
    age = age + 1 

    age2 = age + 10 

    request = urllib.request.Request('https://insuranceproject-ae18a.firebaseio.com/%d/%s.json' % (age, combine[0].replace(' ', ''))) 
    response = urllib.request.urlopen(request) 
    str_response = response.read() 
    info = json.loads(str_response.decode("utf-8")) 

    request = urllib.request.Request('https://insuranceproject-ae18a.firebaseio.com/%d/%s.json' % (age2, combine[0].replace(' ', ''))) 
    response = urllib.request.urlopen(request) 
    str_response = response.read() 
    info2 = json.loads(str_response.decode("utf-8"))  

    abc = [info, str(age), info2] 

    return abc 

def cash_outlay(abc): 
    age = int(abc[1]) 
    if (age <= 40): 
     awl = 300 
    elif(age <= 70): 
     awl = 600 
    else: 
     awl = 900 

    premium = int(abc[0]) 
    if (premium > awl): 
     cash_outlay = premium - awl 
     say = " Since your premium is more than your AWL (Additional Withdrawal Limit), u only need to pay the remaining which is $" + str(cash_outlay) 
    else: 
     cash_outlay = 0 
     say = " Since your premium is less than AWL (Additional Withdrawal Limit), everything is settled by Medisave" 

    return say 

def generate_rec_plan(ward_type, compensation, period, limit): 
    if(ward_type == 'Private' and period == '4' and limit == 'Yes'): 
     plan_type = 'AXA Shield Plan A' 
     link = 'https://www.axa.com.sg/our-solutions/personal/health/axa-shield' 
    elif(ward_type == 'Private' and period == '4' and limit == 'No'): 
     plan_type = 'PRUshield A Premier' 
     link = 'https://www.prudential.com.sg/en/our-solutions/products/prushield/' 
    elif(ward_type == 'Private' and period == '3' and limit == 'Yes'): 
     plan_type = 'Supreme Health P Plus' 
     link = 'https://www.greateasternlife.com/sg/en/personal-insurance/find-the-right-plan/protect-myself-and-my-family/health-protection/supremehealth.html' 
    elif(ward_type == 'Private' and period == '3' and limit == 'No'): 
     plan_type = 'My Shield Plan 1' 
     link = 'https://www.aviva.com.sg/en/insurance/life-and-health/my-shield/' 
    elif(ward_type == 'Private' and period == '2'): 
     plan_type = 'Preferred' 
     link = 'https://www.income.com.sg/insurance/health-insurance/enhanced-incomeshield' 
    elif(ward_type == 'Private' and period == '1'): 
     plan_type = 'AIA Health Shield Gold Max A' 
     link = 'https://www.aia.com.sg/en/our-products/medical-protection/aia-healthshield-gold-max.html' 
    elif(ward_type == 'A ward' and period == '4' and limit == 'Yes'): 
     plan_type = 'PRUshield A Plus' 
     link = 'https://www.prudential.com.sg/en/our-solutions/products/prushield/' 
    elif(ward_type == 'A ward' and period == '4' and limit == 'No'): 
     plan_type = 'AXA Shield Plan B' 
     link = 'https://www.axa.com.sg/our-solutions/personal/health/axa-shield' 
    elif(ward_type == 'A ward' and period == '3'): 
     plan_type = 'Supreme Health A Plus' 
     link = 'https://www.greateasternlife.com/sg/en/personal-insurance/find-the-right-plan/protect-myself-and-my-family/health-protection/supremehealth.html' 
    elif(ward_type == 'A ward' and period == '2'): 
     plan_type = 'AIA Health Shield Gold Max B' 
     link = 'https://www.aia.com.sg/en/our-products/medical-protection/aia-healthshield-gold-max.html' 
    elif(ward_type == 'A ward' and period == '1' and limit == 'Yes'): 
     plan_type = 'MyShield Plan 2' 
     link = 'https://www.aviva.com.sg/en/insurance/life-and-health/my-shield/' 
    elif(ward_type == 'A ward' and period == '1' and limit == 'No'): 
     plan_type = 'Advantage' 
     link = 'https://www.income.com.sg/insurance/health-insurance/enhanced-incomeshield' 
    elif(ward_type == 'B1 ward' and compensation == 'As Charged' and (period == '4' or period == '3')): 
     plan_type = 'Supreme Health B Plus' 
     link = 'https://www.greateasternlife.com/sg/en/personal-insurance/find-the-right-plan/protect-myself-and-my-family/health-protection/supremehealth.html' 
    elif(ward_type == 'B1 ward' and compensation == 'As Charged' and period == '2'): 
     plan_type = 'AIA Health Shield Gold Max B Lite' 
     link = 'https://www.aia.com.sg/en/our-products/medical-protection/aia-healthshield-gold-max.html' 
    elif(ward_type == 'B1 ward' and compensation == 'As Charged' and period == '1' and limit == 'Yes'): 
     plan_type = 'My Shield Plan 3' 
     link = 'https://www.aviva.com.sg/en/insurance/life-and-health/my-shield/' 
    elif(ward_type == 'B1 ward' and compensation == 'As Charged' and period == '1' and limit == 'No'): 
     plan_type = 'Basic - SG' 
     link = 'https://www.income.com.sg/insurance/health-insurance/enhanced-incomeshield' 
    elif(ward_type == 'B1 ward' and compensation == 'Limits'): 
     plan_type = 'AXA Standard Plan' 
     link = 'https://www.axa.com.sg/our-solutions/personal/health/axa-shield' 
    elif(ward_type == 'B2 or C ward' and compensation == 'As Charged'): 
     plan_type = 'Enhanced C - SG' 
     link = 'https://www.income.com.sg/insurance/health-insurance/enhanced-incomeshield' 
    elif(ward_type == 'B2 or C ward' and compensation == 'Limits'): 
     plan_type = 'Medishield Life' 
     link = 'https://www.moh.gov.sg/content/moh_web/medishield-life/about-medishield-life/medishield-life-benefits.html' 
    combine = [plan_type, link] 

    return combine 

def isvalid_date(date): 
    try: 
     dateutil.parser.parse(date) 
     return True 
    except ValueError: 
     return False 

def isvalid_nationality(nationality): 
    nationality_types = ['Singapore Citizen', 'Permanent Resident', 'Foreigner'] 
    return nationality in nationality_types 

def isvalid_compensation(compensation): 
    compensations = ['Limits', 'As Charged'] 
    return compensation in compensations 

def isvalid_period(period): 
    periods = [1, 2, 3, 4] 
    return int(period) in periods 

def isvalid_limit(limit): 
    limits = ['Yes', 'No'] 
    return limit in limits 

def build_validation_result(isvalid, violated_slot, message_content): 
    return { 
     'isValid': isvalid, 
     'violatedSlot': violated_slot, 
     'message': {'contentType': 'PlainText', 'content': message_content} 
    }  

def validate_insurance_plan(slots): 
    birthday = try_ex(lambda: slots['birth']) 
    nationality = try_ex(lambda: slots['nation']) 
    isp = try_ex(lambda: slots['isp']) 
    ward_type = try_ex(lambda: slots['ward']) 
    compensation = try_ex(lambda: slots['compensation']) 
    period = try_ex(lambda: slots['period']) 
    limit = try_ex(lambda: slots['limits'])  

    if birthday: 
     if not isvalid_date(birthday): 
      return build_validation_result(
       False, 
       'birth', 
       'I did not understand your birthdate. When were you born?' 
       ) 
     if datetime.datetime.strptime(birthday, '%Y-%m-%d').date() > datetime.date.today(): 
      return build_validation_result(
       False, 
       'birth', 
       'You are not even born yet, how is this possible. Please tell me your correct birthdate.' 
       ) 

    if nationality and not isvalid_nationality(nationality): 
     return build_validation_result(
      False, 
      'nation', 
      'Sorry but the stated nationality does not exist, please choose from ones stated [Singapore Citizen, Permanent Resident, Foreigner]' 
     ) 

    if compensation and not isvalid_compensation(compensation): 
     return build_validation_result(
      False, 
      'compensation', 
      'Sorry but that plan does not exist, please choose either a plan with "As Charged" coverage or a plan with "Limits".' 
      ) 

    if period and not isvalid_period(period): 
     return build_validation_result(
      False, 
      'period', 
      'Please choose a number between 1-4' 
     ) 

    if limit and not isvalid_limit(limit): 
     return build_validation_result(
      False, 
      'limits', 
      'Please answer Yes/No, it"s that simple.' 
     ) 

    return {'isValid': True} 


""" --- Functions that control the bot's behavior --- """ 
def introduction(intent_request): 

    session_attributes = intent_request['sessionAttributes'] if intent_request['sessionAttributes'] is not None else {} 

    return close(
     session_attributes, 
     'Fulfilled', 
     { 
      'contentType': 'PlainText', 
      'content': 'Hey there! Try asking me "Which integrated Shield Plan is right for me?" to find out your recommended Insurance Plan!' 
     } 
    ) 


def insurance_bot(intent_request): 

    birthday = try_ex(lambda: intent_request['currentIntent']['slots']['birth']) 
    nationality = try_ex(lambda: intent_request['currentIntent']['slots']['nation']) 
    isp = try_ex(lambda: intent_request['currentIntent']['slots']['isp']) 
    ward_type = try_ex(lambda: intent_request['currentIntent']['slots']['ward']) 
    compensation = try_ex(lambda: intent_request['currentIntent']['slots']['compensation']) 
    period = try_ex(lambda: intent_request['currentIntent']['slots']['period']) 
    limit = try_ex(lambda: intent_request['currentIntent']['slots']['limits']) 

    session_attributes = intent_request['sessionAttributes'] if intent_request['sessionAttributes'] is not None else {} 

    last_confirmed_insurance = try_ex(lambda: session_attributes['lastConfirmedInsurance']) 
    if last_confirmed_insurance: 
     last_confirmed_insurance = json.loads(last_confirmed_insurance) 
    confirmation_context = try_ex(lambda: session_attributes['confirmationContext']) 

    # Load confirmation history and track the current reservation. 
    insurance = json.dumps({ 
     'birth': birthday, 
     'nation': nationality, 
     'isp': isp, 
     'ward': ward_type, 
     'compensation': compensation, 
     'period': period, 
     'limits': limit 
    }) 

    session_attributes['currentInsurance'] = insurance 

    if intent_request['invocationSource'] == 'DialogCodeHook': 
     # Validate any slots which have been specified. If any are invalid, re-elicit for their value 
     validation_result = validate_insurance_plan(intent_request['currentIntent']['slots']) 
     if not validation_result['isValid']: 
      slots = intent_request['currentIntent']['slots'] 
      slots[validation_result['violatedSlot']] = None 

      return elicit_slot(
       session_attributes, 
       intent_request['currentIntent']['name'], 
       slots, 
       validation_result['violatedSlot'], 
       validation_result['message'] 
      ) 

     #If user is foreigner, straight away end chat 
     if nationality == 'Foreigner': 

      try_ex(lambda: session_attributes.pop('currentInsurance')) 
      session_attributes['lastConfirmedInsurance'] = insurance    

      return close(
       session_attributes, 
       'Fulfilled', 
       { 
        'contentType': 'PlainText', 
        'content': 'I am sorry but foreigners currently cannot apply for an insurance plan in Sg.' 
        + ' It it still under development ' 
        + 'so look out for it in the future! Thank you and have a nice day!' 
       } 
      ) 

     #Getting recommended plan, age and premium info 
     if birthday and ward_type and compensation and period and limit: 
      plan = generate_rec_plan(ward_type, compensation, period, limit) 
      session_attributes['recPlan'] = plan[0] 
      session_attributes['planLink'] = plan[1] 

      info = calculate_age(birthday, plan) 
      session_attributes['premium'] = info[0] 
      session_attributes['age'] = info[1] 
      session_attributes['age2'] = info[2] 

      outlay = cash_outlay(info) 
      session_attributes['cashOutlay'] = outlay 
     else: 
      try_ex(lambda: session_attributes.pop('recPlan')) 
      try_ex(lambda: session_attributes.pop('planLink')) 
      try_ex(lambda: session_attributes.pop('premium')) 
      try_ex(lambda: session_attributes.pop('age')) 
      try_ex(lambda: session_attributes.pop('age2')) 
      try_ex(lambda: session_attributes.pop('cashOutlay')) 

     session_attributes['currentInsurance'] = insurance 
     return delegate(session_attributes, intent_request['currentIntent']['slots']) 

    # Booking the hotel. In a real application, this would likely involve a call to a backend service. 
    logger.debug('InsurPlan under={}'.format(insurance)) 

    try_ex(lambda: session_attributes.pop('currentInsurance')) 
    session_attributes['lastConfirmedInsurance'] = insurance 

    return close(
     session_attributes, 
     'Fulfilled', 
     { 
      'contentType': 'PlainText', 
      'content': 'Your recommended plan would be ' + session_attributes['recPlan'] 
      + '! And since you are ' + session_attributes['age'] 
      + ' next year, you will be given a premium of about $' + session_attributes['premium'] 
      + '. ' 
      + session_attributes['cashOutlay'] 
      + '. But in 10 years, your premium will be $' + session_attributes['age2'] 
      + '. If you want to know more about this insurance plan, you can go to ' 
      + session_attributes['planLink'] + ' for more details!' 
     } 
    ) 


# --- Intents --- 


def dispatch(intent_request): 
    """ 
    Called when the user specifies an intent for this bot. 
    """ 

    logger.debug('dispatch userId={}, intentName={}'.format(intent_request['userId'], intent_request['currentIntent']['name'])) 
    intent_name = intent_request['currentIntent']['name'] 

    # Dispatch to your bot's intent handlers 
    if intent_name == 'InsurePlan': 
     return insurance_bot(intent_request) 
    elif intent_name == 'Intro': 
     return introduction(intent_request) 

    raise Exception('Intent with name ' + intent_name + ' not supported') 


# --- Main handler --- 

def lambda_handler(event, context): 

    return dispatch(event) 

enter image description here

: 여기

enter image description here

enter image description here

는 AWS (λ)에 렉스 아무것도에 응답 카드 AWS 람다 그러나, 내가 한 설정에 사용되는 내 코드입니다
+0

입력에 의해 어떤 의도가 취소되는지에 따라 달라집니다. 자세한 내용은 로그를 확인하십시오. – sid8491

+0

나는 당신이 여기에서 말하려고하는 것을 정말로 이해하지 못한다. 그래서 그것이 중복 된 시간을 촉발시키는 이유는 하나 이상의 의도가 있기 때문인가? –

+0

아니요,이 입력 카드에 대해 동일한 의도가 호출되어이 응답 카드가 생성되었다고 말할 수 있습니다. CloudWatch 로그에서 다른 입력을 확인하여 프로세스가 어떻게 진행되고 있는지 확인해야합니다. – sid8491

답변

0

InsurePlan의 의도는 isp 인 것처럼 보입니다.은 필요에 따라 확인한 것이므로 의도가 호출 될 때 isp에 대한 슬롯 값이 충족되지 않고 해당 메시지가 프롬프트 메시지 (응답 카드)로 표시되는지 확인합니다.

슬롯 isp의 선택을 취소하고 DialogCodeHook의 값을 확인하고 필요한 경우 ElicitSlot을 제공해야합니다. 그리고 콘솔 대신 코드에서 응답 카드를 제공하여 사용자 정의가 가능하도록하십시오.

희망이 있습니다.