슬롯에서 소수를 다루기

소개



얼마 전 Alexa 스킬, 두근두근 연비 계산을 발표하고 그 중 소수점을 포함한 수치를 스킬 안에서 취급했습니다.
미국에서는 빌드 인 슬롯의 AMAZON.NUMBER에서 취득할 수 있으므로, 일본에서도 취할 수 있다고 생각하면・・・아직 할 수 없었습니다.
그럼 일본의 경우 어떻게 하면 좋을까?
개발에 있어서 여러가지 조사했습니다만, 의외와 소수를 취급하는 것이 되지 않았으므로, 정리해 보려고 생각합니다.

이미 정해진 숫자 얻기



발화되는 수치가 한정되어 있어, 복수의 선택사항 중에서 소수를 선택하는 경우입니다.
이 경우에는 매우 간단하며 사용자 정의 슬롯을 작성하여 해결할 수 있습니다.
포인트는 여러가지 말이 있기 때문에, 그것에 대응할 수 있도록 동의어를 많이 추가해 두는 것입니다.


이것을 인텐트 안에서 slot로 설정하면 얻을 수 있게 됩니다.
이때 백엔드의 코드는 다음과 같이 하면 OK입니다.

sample.js
//この例はsampleIntentにsampleSlotというものが入っている場合のコード

const sampleHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'sampleIntent'
               && handlerInput.requestEnvelope.request.intent.slots.sampleSlot.value !== undefined //値が取れている。
               && this.event.request.intent.slots.sampleSlot.resolutions.resolutionsPerAuthority[0].status.code == 'ER_SUCCESS_MATCH' //選択肢の数値がvalue候補に含まれる
    },
    handle(handlerInput) {
        const slots = handlerInput.requestEnvelope.request.intent.slots;
        //今回はIDを取得しているため、IDで取得
        let num = slots.sampleSlot.resolutions.resolutionsPerAuthority[0].values[0].value.id
        const speechText = '取得出来た値は' + num + 'です'

        return handlerInput.responseBuilder
            .speak(speechText)
            .getResponse();
    }
};

포인트는 resolutions.resolutionsPerAuthority[0]을 사용하고 있는 곳입니다.
slots.sampleslots.value 를 사용하면(자), 인식한 캐릭터 라인을 그대로 취해 버리기 때문에, 이 수치를 사용해 계산하는 경우는 에러가 될 우려가 있습니다.

모든 소수에 해당합니다 (단, 조건 있음)



이쪽이 본명. 다음에 어떤 수치가 와도 취할 수 있도록 하는 설계 방법입니다.

○대화 모델 설계
우선은 실제로 스킬에서 사용한 샘플 발화를 소개합니다.

보시다시피 알 수 있듯이 [정수 값] 점 [소수 값] 형태로 슬롯을 정수, 소수로 나눕니다.
조금 귀찮지만, 이렇게하지 않으면 가치가 없습니다.
그리고 소수점은 "점"이라고 표기합니다. 기호는 NG입니다.

그리고 각 값의 슬롯 타입이지만 다음과 같습니다.



정수 값은 AMAZON.NUMBER로, 소수는 AMAZON.FOUR_DEGIT_NUMBER로 얻습니다.

조건이 있다는 것은, FOUR_DEGIT_NUMBER로 취득하기 때문에, 소수점 4위까지밖에 취할 수 없다고 하는 것입니다.

○소수 처리
lambda측에서는 어떻게 처리를 하는지, 실제의 두근두근 연비 계산의 처리의 일부를 예로 합니다
값으로서 주행 거리의 정수치와 소수치를 취득할 수 있었다고 합니다. 이 때 수치로서 취득하려고 하면, 코드는 이하와 같습니다

sample2.js
//calcurateProcess
const startCalcurateOrder = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest'
            && handlerInput.requestEnvelope.request.intent.name === 'calcurateIntent'

    },
    handle(handlerInput) {
        console.log("in startCalcurateOrder")
        const slots = handlerInput.requestEnvelope.request.intent.slots;
        if (slots.mileage.value !== undefined && slots.mileage.value > 0 && slots.mileage.value !== '?' ) {
            //まず小数点の計算をする
            var mileageDemi = parseFloat(0);
            if (slots.demical.value !== undefined) {
                mileageDemi = parseFloat(slots.demical.value) / (10 ** (String(slots.demical.value).length))
                console.log('距離: %f', mileageDemi)
            }
            //小数点以下を含む、発話された数値に変換する
            var mileageValue = parseFloat(slots.mileage.value) + mileageDemi
            var result = (mileageValue).toFixed(2) //小数第3位で四捨五入している

            console.log(mileageValue)

            var speechText = "走行距離は" + result + "キロメートルです。"

            return handlerInput.responseBuilder
                .speak(speechText)
                .getResponse();
        }
    }
};

소수치는 실제로 들어가지 않을 가능성도 있습니다. 정수의 경우라도 처리할 수 있도록, 정수치가 들어가 있는지 판단해, 그 위에 소수치의 확인, 처리를 실시하도록(듯이) 했습니다.

사이고에게



스킬 내에서 소수를 다루는 것은 별로 없을 수 있습니다. 그래도 사용하고 싶을 때는 이 방법이 베스트가 아닐까 생각합니다.
다만, 이 방법에도 일부 문제가 있어, 1개의 인텐트에 2개의 소수치를 포함한 값을 가지고 있으면, 소수치의 슬롯이 잘못해 다른 한쪽의 소수치의 슬롯에는 말해 버린다고 한다 버그도 발견했습니다.
두근두근 연비 계산에서는 수치 뒤에 단위를 말하지 않고 발화했을 때에 이 증상이 있었습니다.
이 근처는 아마존 씨에게 개선해 줄 필요가 있을 것 같습니다.

좋은 웹페이지 즐겨찾기