사전 빌드된 에이전트는 일반 사용 사례용으로 Dialogflow CX에서 제공하는 에이전트 모음입니다. 이러한 에이전트는 대화를 빌드하기 위한 기반을 구축하는 데 사용할 수 있습니다. Dialogflow CX에서 통신, 금융 서비스, 의료, 소매업, 여행 등 다양한 업계에서 널리 사용되고 있는 사용 사례를 찾을 수 있습니다. 생성형 사전 빌드된 에이전트는 제한적인 액세스 권한으로 사용할 수 있으며, 생성형 기능을 사용하여 구현된 일반적인 사용 사례를 보여줍니다.
사전 빌드된 에이전트에는 사용 사례의 인텐트와 항목이 포함되지만 예시 경로 그룹과 fulfillment(해당하는 경우)를 수정해야 합니다.
제한사항
다음과 같은 제한사항이 적용됩니다.
- 사전 빌드된 에이전트는 현재 영어(en)만 지원합니다.
사전 빌드된 에이전트 가져오기
프로젝트에 사전 빌드된 에이전트를 가져오려면 다음 안내를 따르세요.
- Dialogflow CX 콘솔로 이동합니다.
- 사전 빌드된 에이전트를 가져올 프로젝트를 클릭합니다.
- 사전 빌드된 에이전트 사용을 클릭합니다.
- 원하는 에이전트를 클릭하고 가져오기를 클릭합니다.
- 원하는 위치를 선택하고 만들기를 클릭합니다.
- 테스트를 시작하고 맞춤설정합니다.
가져온 사전 빌드된 에이전트 맞춤설정
- 시뮬레이터로 에이전트를 테스트하여 사용자가 무엇을 달성할 수 있는지 알아봅니다.
- 왼쪽 창에서 관리 탭을 클릭한 다음 테스트 사례를 클릭하여 범위 및 예시 스크립트를 확인합니다. 자세한 내용은 테스트 사례 문서를 참조하세요.
- 사용 사례와 관련 없는 모든 흐름을 삭제합니다.
- 에이전트 대화 및 커스텀 항목을 수정하여 비즈니스 니즈를 충족합니다.
- 웹훅 소스 코드가 있으면 웹훅 코드 수정을 참조하세요.
웹훅 코드 수정
웹훅을 활용하여 사전 빌드된 에이전트를 선택합니다. 원래 웹훅 소스 코드는 Node.js를 사용하며 Google의 내부 Cloud Functions 프로젝트에서 호스팅됩니다.
자체 Cloud Functions 프로젝트에서 이 코드를 사용 및 수정하려면 다음 안내를 따르세요.
- Dialogflow CX 콘솔로 이동합니다.
- 사전 빌드된 에이전트를 가져올 프로젝트를 클릭합니다.
- 사전 빌드된 에이전트 사용을 클릭합니다.
원하는 에이전트를 클릭한 후 문서 링크를 클릭하여 이 문서의 사전 빌드된 에이전트 섹션으로 이동합니다.
사전 빌드된 에이전트의 웹훅 하위 섹션을 참조하여 소스 코드를 복사합니다.
Google Cloud Console로 이동하여 왼쪽 패널에서 Cloud Functions를 선택합니다.
소스 코드를 가져올 프로젝트를 클릭합니다.
함수 만들기를 클릭합니다. 자세한 내용은 Cloud 함수 만들기 문서를 참조하세요.
소스 코드 섹션에서 인라인 편집기를 선택하고 복사된 소스 코드를 붙여넣습니다.
소스를 클릭한 후 수정을 클릭하여 비즈니스 규칙에 따라 로직을 변경합니다. 완료되면 배포를 클릭합니다.
트리거를 클릭하고 트리거 URL을 복사합니다.
관리 > 웹훅으로 이동하고 웹훅을 선택하여 새 URL을 붙여넣을 에이전트의 트리거 URL을 바꿉니다. 웹훅 URL 라벨이 지정된 필드에 트리거 URL을 붙여넣습니다. 저장을 클릭합니다.
웹훅 문서를 사용하여 fulfillment를 테스트합니다.
금융 서비스 에이전트
이 템플릿을 통해 최종 사용자의 카드 사용을 지원하고 애플리케이션 상태를 확인하며 의심스러운 청구를 조사할 수 있습니다.
샘플 발화
- I'd like to make a payment towards my balance.
- I lost my card and need a new one.
- I want to report some suspicious activity on my checking account.
- What is my auto loan application status?
- What are the different annual fees on your business credit cards?
웹훅
Cloud Functions 웹훅은 다음 작업을 수행합니다.
- 최종 사용자의 신원 확인
- 잔액, 대출 상태 및 신용카드 기능 정보 제공
- 결제 금액 및 날짜 확인을 비롯한 모의 샘플 결제
- 영업시간 관리
package.json
{ "name": "sample-http", "version": "0.0.1" }
index.js
/** * Responds to any HTTP request. * * @param {!express:Request} req HTTP request context. * @param {!express:Response} res HTTP response context. */ exports.cxPrebuiltAgentsFinServ = (req, res) => { console.log('Cloud Function:', 'Invoked cloud function from Dialogflow CX'); let tag = req.body.fulfillmentInfo.tag; if (!!tag) { switch (tag) { // BEGIN validateAccount case 'validateAccount': console.log(tag + ' was triggered.'); let card_last_four = req.body.sessionInfo.parameters.card_last_four; let card_verified; // card validation only fails if card number is 0000 if (card_last_four == '0000') { card_verified = 'false'; } else { card_verified = 'true'; } res.status(200).send( {sessionInfo: {parameters: {card_verified: card_verified}}}); console.log(' verified: ' + card_verified); break; // BEGIN getAccountInfo case 'getAccountInfo': console.log(tag + ' was triggered.'); let current_balance; let last_statement_balance; let minimum_due; // Random current balance between 1 and 1000 current_balance = Math.floor(Math.random() * 1000); // Last statement balance is 70% of current balance last_statement_balance = Math.floor(current_balance * 0.7); // Minimum due is 25% of last statement balance minimum_due = Math.floor(last_statement_balance * 0.25); res.status(200).send({ sessionInfo: { parameters: { current_balance: current_balance, last_statement_balance: last_statement_balance, minimum_due: minimum_due } } }); console.log( 'current balance: ' + current_balance + ' last statement balance: ' + last_statement_balance); break; // BEGIN getPaymentSource case 'getPaymentSource': console.log(tag + ' was triggered.'); // static array of account names let account_names = ['National Checking Account', 'My Checking', 'Personal Checking']; // random array value for account names let account_index = Math.floor(Math.random() * account_names.length); let selected_account = account_names[account_index]; res.status(200).send( {sessionInfo: {parameters: {selected_account: selected_account}}}); console.log(' selected account: ' + selected_account); break; // BEGIN submitPayment case 'submitPayment': console.log(tag + ' was triggered.'); let card_digits = String(req.body.sessionInfo.parameters.card_last_four); let payment_status; // When first digit of card_digits is 9 the transaction fails if (card_digits[0] == '9') { payment_status = 'fail'; } else { payment_status = 'success'; } res.status(200).send( {sessionInfo: {parameters: {payment_status: payment_status}}}); console.log(' verified: ' + card_verified); break; // BEGIN validatePaymentAmount case 'validatePaymentAmount': console.log(tag + ' was triggered.'); // get payment amount let payment_amount = Number(req.body.sessionInfo.parameters.other_amount); let current_balance_temp = req.body.sessionInfo.parameters.current_balance; let amount_valid; payment_amount = Number(payment_amount); console.log( `payment_amount: ` + payment_amount + ` current balance: ` + current_balance_temp); // confirm payment amount is a positive value less than or equal to the // current balance if (payment_amount > 0) { if (payment_amount <= current_balance_temp) { amount_valid = true; } else { amount_valid = false; } } else { amount_valid = false; } res.status(200).send( {sessionInfo: {parameters: {amount_valid: amount_valid}}}); console.log('payment status: ' + payment_status); break; // BEGIN validatePaymentDate case 'validatePaymentDate': console.log(tag + ' was triggered.'); // get payment date let payment_date_raw = req.body.sessionInfo.parameters.payment_date; // set payment date in date object format. subtract one from month // because month is indexed to 0. let payment_year = payment_date_raw.year; let payment_month = payment_date_raw.month - 1; let payment_day = payment_date_raw.day; console.log( 'Payment - Year: ' + payment_year + ' Month ' + payment_month + ' Day: ' + payment_day); // set today's date let today = new Date(); let this_year = today.getFullYear(); let this_month = today.getMonth(); let this_day = today.getDate(); console.log( 'Today - Year: ' + this_year + ' Month ' + this_month + ' Day: ' + this_day); let payment_date_valid; // check if the payment date is after today if (payment_year > this_year) { payment_date_valid = true; console.log('Future year'); } else if (payment_year == this_year && payment_month > this_month) { payment_date_valid = true; console.log('Future month'); } else if ( payment_year == this_year && payment_month == this_month && payment_day >= this_day) { payment_date_valid = true; console.log('Today or later this month'); } else { payment_date_valid = false; } res.status(200).send({ sessionInfo: {parameters: {payment_date_valid: payment_date_valid}} }); console.log('payment date valid: ' + payment_date_valid); break; // BEGIN checkInHours case 'checkInHours': console.log(tag + ' was triggered.'); // check if we are currently in hours let currentDate = new Date(); console.log('current time is ' + currentDate); let currentHour = currentDate.getHours(); console.log('current hour is ' + currentHour); if (currentHour >= 8 && currentHour <= 20) { in_hours = 'true'; console.log('currently in hours'); } else { in_hours = 'false'; console.log('currently out of hours'); } res.status(200).send({sessionInfo: {parameters: {in_hours: in_hours}}}); break; // BEGIN getRetryCount case 'getRetryCount': console.log(tag + ' was triggered.'); // increment the current retry counter let retry_count = req.body.sessionInfo.parameters.retry_count; retry_count = retry_count + 1; res.status(200).send( {sessionInfo: {parameters: {retry_count: retry_count}}}); break; // BEGIN getLoanStatus case 'getLoanStatus': console.log(tag + ' was triggered.'); let loan_reference = String(req.body.sessionInfo.parameters.loan_reference); let loan_type = loan_reference[0]; let loan_status = loan_reference[1]; let loan_found = 'true'; console.log('loan ref is ' + loan_reference); console.log('type is ' + loan_type); console.log('status is ' + loan_status); // mock loan not found if (loan_reference[0] == '0') { loan_found = 'false'; } // mock loan found if ((loan_type != 'auto') && (loan_type != 'home')) { if (loan_reference[0] > '5') { loan_type = 'home'; } else { loan_type = 'auto'; } } res.status(200).send({ sessionInfo: { parameters: { loan_type: loan_type, loan_status: loan_status, loan_found: loan_found } } }); break; // BEGIN validateTransactionDate case 'validateTransactionDate': console.log(tag + ' was triggered.'); // get date queried let date_queried_raw = req.body.sessionInfo.parameters.date_queried; // set date queried in date object format. subtract one from month // because month is indexed to 0. date_queried = new Date( date_queried_raw.year, date_queried_raw.month - 1, date_queried_raw.day); console.log(date_queried + ' is the date im looking for.'); let date_valid; let date_now = new Date(); // check if the payment date is after today if (date_queried > date_now) { date_valid = 'false'; } else { date_valid = 'true'; } res.status(200).send( {sessionInfo: {parameters: {date_valid: date_valid}}}); break; // BEGIN lookupTransactions case 'lookupTransactions': console.log(tag + ' was triggered.'); // select a random retailer from the retailers array let retailers = [ 'Dior', 'Walmart', 'Target', 'Costco', 'Macy\'s', 'Bed Bath & Beyond', 'Amazon', 'Walgreens', 'Home Depot', 'Best Buy', 'Kohl\'s' ]; let randomRetail = Math.floor(Math.random() * retailers.length); console.log('random retail value ' + randomRetail); let retailer_queried = retailers[randomRetail]; // Alter the transaction amount let amount_queried = Number(req.body.sessionInfo.parameters.amount_queried.amount); let transaction_value = Number(amount_queried); let randomAdjust = Math.floor(Math.random() * 5); randomAdjust = Number(randomAdjust / 100); let adjustment = Number(amount_queried * randomAdjust); let randomMath = Math.floor(Math.random() * 1); if (randomMath < 1) { transaction_value = Number(transaction_value - adjustment).toFixed(2); } else if (randomMath = 1) { transaction_value = Number(transaction_value + adjustment).toFixed(2); } if (amount_queried < 1000) { transaction_found = 'true'; } else { transaction_found = 'false'; } res.status(200).send({ sessionInfo: { parameters: { retailer_queried: retailer_queried, transaction_value: transaction_value, transaction_found: transaction_found } } }); break; // BEGIN lookupCardFeatures case 'lookupCardFeatures': console.log(tag + ' was triggered.'); // setup arrays for card features let interestRate = [ '14.5% APR', '0% APR in year 1 and then increases to 25% APR in year 2', '10% APR in year 1 and then increases to 20% APR in year 2', '18% APR' ]; let annualFee = [ '$0 annual fee for year 1 and then increases to $90 in year 2', '$70 annual fee starting in year 1', '$15 annual fee for year 1 and then increases to $80 in year 2', '$50 annual fee starting in year 1' ]; let cashBackRate = ['1%', '3%', '6%', '2%', '5%', '4%']; let pointsBonus = ['50,000', '25,000', '10,000', '100,000', '75,000']; // setup card one features let cardOneRandomInterest = Math.floor(Math.random() * interestRate.length); let card_one_interest = interestRate[cardOneRandomInterest]; let cardOneRandomFee = Math.floor(Math.random() * annualFee.length); let card_one_fee = annualFee[cardOneRandomFee]; let cardOneRandomCashback = Math.floor(Math.random() * cashBackRate.length); let card_one_cashback = cashBackRate[cardOneRandomCashback]; let cardOneRandomPoints = Math.floor(Math.random() * pointsBonus.length); let card_one_points = pointsBonus[cardOneRandomPoints]; // setup card two features let cardTwoRandomInterest = Math.floor(Math.random() * interestRate.length); let card_two_interest = interestRate[cardTwoRandomInterest]; let cardTwoRandomFee = Math.floor(Math.random() * annualFee.length); let card_two_fee = annualFee[cardTwoRandomFee]; let cardTwoRandomCashback = Math.floor(Math.random() * cashBackRate.length); let card_two_cashback = cashBackRate[cardTwoRandomCashback]; let cardTwoRandomPoints = Math.floor(Math.random() * pointsBonus.length); let card_two_points = pointsBonus[cardTwoRandomPoints]; res.status(200).send({ sessionInfo: { parameters: { card_one_interest: card_one_interest, card_one_fee: card_one_fee, card_one_cashback: card_one_cashback, card_one_points: card_one_points, card_two_interest: card_two_interest, card_two_fee: card_two_fee, card_two_cashback: card_two_cashback, card_two_points: card_two_points } } }); break; default: console.log('default case called'); res.status(200).end(); break; } } };
Healthcare 에이전트
이 템플릿을 사용하면 최종 사용자가 클레임과 혜택을 확인하고 의사를 찾을 수 있습니다.
샘플 발화
- What is coinsurance?
- Can you help me find a doctor?
- I'm not feeling well.
- What is my deductible?
주문 및 계정 관리 에이전트
이 템플릿을 사용하면 최종 사용자가 제품을 구매 또는 반품하고 주문을 추적하며 적립 포인트, 주소, 비밀번호와 같은 계정 설정을 관리할 수 있습니다.
샘플 발화
- I haven't received my order, where is it?
- I want to get a new phone.
- I forgot my password.
- Can you tell me how many points I have?
- I moved and need to update my address.
결제 처리 에이전트
이 템플릿을 사용하면 최종 사용자가 2개월 할부 결제 처리를 설정하거나 결제 마감일을 연장할 수 있습니다.
샘플 발화
- My account was suspended.
- I won't get paid on time to pay my bill.
- I need to extend my due date.
- I lost my job due to covid-19.
웹훅
이 Cloud Functions 웹훅은 다음 작업을 수행합니다.
- 샘플 결제액 및 최대 연장 날짜를 제공합니다.
- 총 잔액과 최초 결제 할부 결제 금액 간의 차액을 기준으로 두 번째 결제 할부를 계산합니다.
- 요청한 연장 날짜가 최대 연장 날짜를 초과하지 않는지 확인합니다.
package.json
{ "name": "sample-http", "version": "0.0.1", "dependencies": { "moment": "2.27.0" } }
index.js
const moment = require('moment'); function getRandomAmount(min, max) { return Math.random() * (max - min) + min; } function formatCurrency(amount) { return Number(amount).toFixed(2); } function formatUserDate(dateObject) { if (!dateObject) { console.log('dateObject error. dateObject passed to formatUserDate is:', dateObject); console.log('dateObject requires day, month, year properties:'); // return false if the dates are not valid // returning false prevents the if/else block from running, which causes the function to crash. return false; } console.log('formatUserDate date set.'); const { day, year, month } = dateObject; return `${year}-${month}-${day}`; } /** * Responds to any HTTP request. * * @param {!express:Request} req HTTP request context. * @param {!express:Response} res HTTP response context. */ exports.cxPrebuiltAgentsPaymentArrangement = (req, res) => { var tag = req.body.fulfillmentInfo.tag; var first_payment; var amount_due_1; //var adjust_due_date; var max_date_1; var maxDate1; var max_date_2; var maxDate2; var current_due_date; var max_extension_date; var maxExtensionDate; var amount_due; var payment_amount_2; var dateFromUser; var valid_payment; var valid_date; if (!!tag) { switch (tag) { //Initialize Dynamic parameters case 'setDynamicParams': console.log(tag + ' was triggered.'); max_date_1 = moment().add(15, 'days').calendar(); max_date_2 = moment().add(25, 'days').calendar(); current_due_date = moment().add(10, 'days').calendar(); max_extension_date = moment().add(30, 'days').calendar(); amount_due = formatCurrency(getRandomAmount(200, 400)); res.status(200).send({ sessionInfo: { parameters: { max_date_1: max_date_1, max_date_2: max_date_2, current_due_date: current_due_date, max_extension_date: max_extension_date, amount_due: amount_due, } } }); break; //Initialize Static parameters case 'setStaticParams': console.log(tag + ' was triggered.'); user_id = req.body.sessionInfo.parameters.user_id; if (user_id == '1001') { max_date_1 = "2021-01-15"; max_date_2 = "2021-01-30"; current_due_date = "2021-01-01"; max_extension_date = "2021-02-15"; amount_due = '225.00'; } else if (user_id == '2002') { max_date_1 = "2021-03-15"; max_date_2 = "2021-03-30"; current_due_date = "2021-03-01"; max_extension_date = "2021-04-15"; amount_due = '333.00'; } else if (user_id == '3003') { max_date_1 = "2021-05-15"; max_date_2 = "2021-05-30"; current_due_date = "2021-05-01"; max_extension_date = "2021-06-15"; amount_due = '189.00'; } else { max_date_1 = moment().add(15, 'days').calendar(); max_date_2 = moment().add(25, 'days').calendar(); current_due_date = moment().add(10, 'days').calendar(); max_extension_date = moment().add(30, 'days').calendar(); amount_due = formatCurrency(getRandomAmount(200, 400)); } res.status(200).send({ sessionInfo: { parameters: { max_date_1: max_date_1, max_date_2: max_date_2, current_due_date: current_due_date, max_extension_date: max_extension_date, amount_due: formatCurrency(amount_due), } } }); break; //Automatically set second payment based on first payment amount case 'secondPayment': console.log(tag + ' was triggered.'); first_payment = req.body.sessionInfo.parameters.payment_amount_1.amount; amount_due_1 = req.body.sessionInfo.parameters.amount_due; payment_amount_2 = formatCurrency(amount_due_1 - formatCurrency(first_payment)); res.status(200).send({ sessionInfo: { parameters: { payment_amount_2: payment_amount_2 } } }); break; //BEGIN validatePayment case 'validatePayment': console.log(tag + ' was triggered.'); first_payment = req.body.sessionInfo.parameters.payment_amount_1.amount; amount_due_1 = req.body.sessionInfo.parameters.amount_due; if ((formatCurrency(first_payment) >= '100.00') && (formatCurrency(first_payment) < amount_due_1)) { valid_payment = "True"; } else { valid_payment = "False" } res.status(200).send({ sessionInfo: { parameters: { valid_payment: valid_payment, } } }); break; //BEGIN validateDate case 'validateDate': // Log when the cloud function for the validateDate tag is triggered console.log(tag + ' was triggered.'); // Log ALL of the session parameters passed to the cloud function console.log('validateDate sessionInfo parameters', req.body.sessionInfo.parameters); // Log ONLY max_extension_date and adjust_due_date values from session parameters. console.log('sessionInfo >>> max_extension_date', req.body.sessionInfo.parameters.max_extension_date); console.log('sessionInfo >>> adjust_due_date', req.body.sessionInfo.parameters.adjust_due_date); // If the formatUserDate function succeeds running, then the date will be a string formatted as yyyy-mm-dd. // If the session params dateObject is not formatted correctly the formatUserDate function returns the boolean value false. // formatUserDate returns false to prevent the Moment function from running (see 3 conditions below). dateFromUser = formatUserDate(req.body.sessionInfo.parameters.adjust_due_date); maxExtensionDate = req.body.sessionInfo.parameters.max_extension_date; // Set valid_date to false. We do this so the cloud function does not crash and always returns a value to Dialogflow CX valid_date = "False" // Only set valid_date to true when // 1) dateFromUser is a date string and not set to false by the formatUserDate function // 2) maxExtensionDate is string and not set to false by the formatUserDate function // 3) if Moment determines the dateFromUser is before maxExtensionDate if (dateFromUser && maxExtensionDate && moment(dateFromUser).isSameOrBefore(maxExtensionDate)) { valid_date = "True"; } res.status(200).send({ sessionInfo: { parameters: { valid_date: valid_date, // You will see the debug property in the Dialogflow CX UI // if formatUserDate failed for eitehr date you will // see 'false' in the UI. // Otherwise, you will see the string formatted date debug: {dateFromUser, maxExtensionDate} } } }); break; case 'validateDate1': // Log when the cloud function for the validateDate tag is triggered console.log(tag + ' was triggered.'); // Log ALL of the session parameters passed to the cloud function console.log('validateDate sessionInfo parameters', req.body.sessionInfo.parameters); // Log ONLY max_date_1 and payment_date_1 values from session parameters. console.log('sessionInfo >>> max_date_1', req.body.sessionInfo.parameters.max_date_1); console.log('sessionInfo >>> payment_date_1', req.body.sessionInfo.parameters.payment_date_1); // If the formatUserDate function succeeds running, then the date will be a string formatted as yyyy-mm-dd. // If the session params dateObject is not fomatted correctly the formatUserDate function returns the boolean value false. // formatUserDate returns false to prevent the Moment function from running (see 3 conditions below). dateFromUser = formatUserDate(req.body.sessionInfo.parameters.payment_date_1); //maxExtensionDate = formatUserDate(req.body.sessionInfo.parameters.max_extension_date); maxDate1 = req.body.sessionInfo.parameters.max_date_1; // Set valid_date to false. We do this so the cloud function does not crash and always returns a value to Dialogflow CX valid_date = "False" // Only set valid_date to true when // 1) dateFromUser is a date string and not set to false by the formatUserDate function // 2) maxExtensionDate is string and not set to false by the formatUserDate function // 3) if Moment determines the dateFromUser is before maxExtensionDate if (dateFromUser && maxDate1 && moment(dateFromUser).isSameOrBefore(maxDate1)) { valid_date = "True"; } res.status(200).send({ sessionInfo: { parameters: { valid_date: valid_date, // You will see the debug property in the Dialogflow CX UI // if formatUserDate failed for eitehr date you will // see 'false' in the UI. // Otherwise, you will see the string formatted date debug: {dateFromUser, maxDate1} } } }); break; case 'validateDate2': // Log when the cloud function for the validateDate tag is triggered console.log(tag + ' was triggered.'); // Log ALL of the session parameters passed to the cloud function console.log('validateDate sessionInfo parameters', req.body.sessionInfo.parameters); // Log ONLY max_date_2 and payment_date_2 values from session parameters. console.log('sessionInfo >>> max_extension_date', req.body.sessionInfo.parameters.max_date_2); console.log('sessionInfo >>> adjust_due_date', req.body.sessionInfo.parameters.payment_date_2); // If the formatUserDate function succeeds running, then the date will be a string formatted as yyyy-mm-dd. // If the session params dateObject is not fomatted correctly the formatUserDate function returns the boolean value false. // formatUserDate returns false to prevent the Moment function from running (see 3 conditions below). dateFromUser = formatUserDate(req.body.sessionInfo.parameters.payment_date_2); //maxExtensionDate = formatUserDate(req.body.sessionInfo.parameters.max_extension_date); maxDate2 = req.body.sessionInfo.parameters.max_date_2; // Set valid_date to false. We do this so the cloud function does not crash and always returns a value to Dialogflow CX valid_date = "False" // Only set valid_date to true when // 1) dateFromUser is a date string and not set to false by the formatUserDate function // 2) maxExtensionDate is string and not set to false by the formatUserDate function // 3) if Moment determines the dateFromUser is before maxExtensionDate if (dateFromUser && maxDate2 && moment(dateFromUser).isSameOrBefore(maxDate2)) { valid_date = "True"; } res.status(200).send({ sessionInfo: { parameters: { valid_date: valid_date, // You will see the debug property in the Dialogflow CX UI // if formatUserDate failed for eitehr date you will // see 'false' in the UI. // Otherwise, you will see the string formatted date debug: {dateFromUser, maxDate2} } } }); break; default: break; } } };
스몰 토크 에이전트
이 템플릿은 간단한 질문으로 에이전트를 맞춤설정하고 개인화하는 데 도움이 됩니다.
샘플 발화
- What's up?
- Who are you?
- Today is my birthday.
- Sorry.
- What do you mean?
통신 에이전트
이 템플릿을 사용하면 최종 사용자가 청구 및 요금제 관련 질문을 해결하고 문제를 해결하고 여행 및 크루즈 요금제를 추가할 수 있습니다.
샘플 발화
- How can I save money on my bill?
- My texts aren't going through.
- How much more will I pay if I upgrade to Plan A?
- I need data coverage for a trip I'm going on to Jamaica.
웹훅
Cloud Functions 웹훅은 다음 작업을 수행합니다.
- 여행 위치와 기간을 기준으로 요금제 비용 비교
- 최종 사용자의 전화번호를 기준으로 결제 이상 식별
package.json
{ "name": "sample-http", "version": "0.0.1", "dependencies": { "moment": "2.24.0" } }
helpers.js
// Get the current month, first day of current month and last month values // based on today's date module.exports = { get_date_details: function (bill_state) { const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; let today = new Date() let first_month_name = monthNames[today.getMonth()] let firstDay = new Date(today.getFullYear(), today.getMonth(), 1); let first_day_str = first_month_name + ' 0' + firstDay.getDate() + ', ' + firstDay.getFullYear() let last_month_name = monthNames[today.getMonth() - 1] let last_month_first_day_str = last_month_name + ' 0' + firstDay.getDate() + ', ' + firstDay.getFullYear() let second_last_month_name = monthNames[today.getMonth() - 2] if (bill_state.toString() == 'current') { return [first_month_name, first_day_str, last_month_name] } else { return [last_month_name, last_month_first_day_str, second_last_month_name] } } }
index.js
/** * Responds to any HTTP request. * * @param {!express:Request} req HTTP request context. * @param {!express:Response} res HTTP response context. */ const helpers = require('./helpers.js') exports.cxPrebuiltAgentsTelecom = (req, res) => { console.log('Cloud Function:', 'Invoked cloud function from Dialogflow CX'); let tag = req.body.fulfillmentInfo.tag; if (!!tag) { switch (tag) { //BEGIN detectCustomerAnomaly case 'detectCustomerAnomaly': console.log(tag + ' was triggered.'); let phone_number = req.body.sessionInfo.parameters.phone_number; let bill_month = req.body.sessionInfo.parameters.bill_state; let parameters = req.body.sessionInfo.parameters; let bill_amount; let product_line; let anomaly_detect = "false" let purchase = "The Godfather" let purchase_amount = 9.99 let total_bill_amount = 64.33 let bill_without_purchase = 54.34 let updated_parameters = {} let [month_name, first_of_month, last_month_name] = helpers.get_date_details(bill_month) console.log(month_name, first_of_month, last_month_name) // Getting the month name based on the bill state - current or previous // For example, if the current month is December, we get the values as // December, December 1st, November // Only 999999 will have anomaly detection if (phone_number.toString() == '999999') { anomaly_detect = "true" product_line = "phone" purchase = "device protection" updated_parameters["product_line"] = product_line updated_parameters["bill_month"] = month_name updated_parameters["last_month"] = last_month_name } // If bill hike amount is given - we just add it to the total bill if ('bill_amount' in parameters) { bill_amount = parameters['bill_amount'] purchase_amount = bill_amount['amount'] total_bill_amount = 54.34 + purchase_amount } // Adding the updated session parameters to the new parameters json updated_parameters["anomaly_detect"] = anomaly_detect updated_parameters["purchase"] = purchase updated_parameters["purchase_amount"] = purchase_amount updated_parameters["bill_without_purchase"] = bill_without_purchase updated_parameters["total_bill"] = total_bill_amount updated_parameters["first_month"] = first_of_month res.status(200).send({ sessionInfo: { parameters: updated_parameters } }); break; // BEGIN validatePhoneLine case 'validatePhoneLine': console.log(tag + ' was triggered.'); let phone = req.body.sessionInfo.parameters.phone_number; let phone_line_verified; let line_index; let domestic_coverage; let covered_lines = ['5555555555', '5105105100', '1231231234', '9999999999']; // Loop over the covered lines array covered_lines.forEach((line, index) => { // For each phone line in the array, check if the last 4 digits are // included in the string. when true, update the line_index variable if (line.includes(phone)) { line_index = index; console.log('This is the index ' + line_index); } }); // Only 9999 will fail; if (line_index === 3) { phone_line_verified = 'false'; } else { phone_line_verified = 'true'; } // Only 1234 will have domestic coverage. if (line_index === 2) { domestic_coverage = 'true'; } else { domestic_coverage = 'false'; } res.status(200).send({ sessionInfo: { parameters: { phone_line_verified: phone_line_verified, domestic_coverage: domestic_coverage } } }); break; // BEGIN cruisePlanCoverage case 'cruisePlanCoverage': console.log(tag + ' was triggered.'); let port = req.body.sessionInfo.parameters.destination; let port_is_covered; // Sample list of covered cruise ports. let covered_ports = [ 'mexico', 'canada', 'anguilla', ]; if (covered_ports.includes(port.toLowerCase())) { port_is_covered = 'true'; } else { port_is_covered = 'false'; } res.status(200).send( { sessionInfo: { parameters: { port_is_covered: port_is_covered } } }); break; // BEGIN internationalCoverage case 'internationalCoverage': console.log(tag + ' was triggered.'); let destination = req.body.sessionInfo.parameters.destination; let coverage; // Sample list of covered international monthly destinations. let covered_by_monthly = [ 'anguilla', 'australia', 'brazil', 'canada', 'chile', 'england', 'france', 'india', 'japan', 'mexico', 'russia', 'singapore', ]; // Sample list of covered international daily destinations. let covered_by_daily = [ 'anguilla', 'australia', 'brazil', 'canada', 'chile', 'england', 'france', 'india', 'japan', 'mexico', 'singapore' ]; if (covered_by_monthly.includes(destination.toLowerCase()) && covered_by_daily.includes(destination.toLowerCase())) { coverage = 'both'; } else if ( covered_by_monthly.includes(destination.toLowerCase()) && !covered_by_daily.includes(destination.toLowerCase())) { coverage = 'monthly_only'; } else if ( !covered_by_monthly.includes(destination.toLowerCase()) && !covered_by_daily.includes(destination.toLowerCase())) { coverage = 'neither'; } else { // This should never happen, because covered_by_daily is a subset of // covered_by_monthly coverage = 'daily_only'; } res.status(200).send({ sessionInfo: { parameters: { coverage: coverage } } }); break; // BEGIN cheapestPlan case 'cheapestPlan': console.log(tag + ' was triggered.'); let trip_duration = req.body.sessionInfo.parameters.trip_duration; let monthly_cost; let daily_cost; let suggested_plan; // Can only suggest cheapest if both are valid for location. // When trip is longer than 30 days, calculate per-month cost (example $ // amounts). Suggest monthly plan. if (trip_duration > 30) { monthly_cost = (Math.floor(trip_duration / 30)) * 70; daily_cost = trip_duration * 10; suggested_plan = 'monthly'; } // When trip is <= 30 days, but greater than 6 days, calculate monthly // plan cost and daily plan cost. Suggest monthly b/c it is the cheaper // one. else if (trip_duration <= 30 && trip_duration > 6) { monthly_cost = 70; daily_cost = trip_duration * 10; suggested_plan = 'monthly'; } // When trip is <= 6 days, calculate daily plan cost. Suggest daily // plan. else if (trip_duration <= 6 && trip_duration > 0) { monthly_cost = (Math.floor(trip_duration / 30)) * 70; daily_cost = trip_duration * 10; suggested_plan = 'daily'; } else { // This should never happen b/c trip_duration would have to be // negative suggested_plan = 'null'; } res.status(200).send({ sessionInfo: { parameters: { monthly_cost: monthly_cost, daily_cost: daily_cost, suggested_plan: suggested_plan } } }); break; default: console.log('default case called'); res.status(200).end(); break; } } };
여행: 수하물 클레임 에이전트
이 템플릿을 사용하면 최종 사용자가 분실되거나 지연되거나 손상된 수하물에 관한 클레임 상태를 만들거나 확인할 수 있습니다.
샘플 발화
- Can you help me file a claim for the bag you lost?
- I'd like to know the status of my damaged bag claim.
- When will my luggage arrive?
웹훅
이 Cloud Functions 웹훅은 다음 작업을 수행합니다.
- 사용자 및 항공편 세부정보 확인
- 클레임 ID를 생성하고 클레임 정보를 반환합니다.
package.json
{ "name": "sample-http", "version": "0.0.1", "dependencies": { "moment": "2.27.0" } }
index.js
const moment = require('moment') /** * Responds to any HTTP request. * * @param {!express:Request} req HTTP request context. * @param {!express:Response} res HTTP response context. */ exports.cxPrebuiltAgentsClaimStatus = (req, res) => { let tag = req.body.fulfillmentInfo.tag; let passenger_last_name; if (!!tag) { switch (tag) { // Check Claim Status tag // Validates that the claim ID is 'REF123456' // And that the last name is 'Garcia' // Sends back a static status message case 'claimStatus': console.log(tag + ' was triggered.') let claim_id = req.body.sessionInfo.parameters.claim_id; passenger_last_name = req.body.sessionInfo.parameters.passenger_last_name; let claim_status; if (claim_id == 'REF123456' && passenger_last_name == "Garcia") { claim_status = 'valid'; } else { claim_status = 'invalid'; } let claim_status_message = 'Your lost bag claim is being processed and you should receive payment to your account ending in 6873 within 5-7 business days. ' res.status(200).send({ sessionInfo: { parameters: { claim_status: claim_status, claim_status_message: claim_status_message } } }); break; // Case to submit a new claim and generate a confirmation ID // Validates that the flight number = AJ143, last name = Garcia // and reference id = 1234567890123 // Ideally you would include better logic, this is just an example of a working webhook case 'submitClaim': console.log(tag + ' was triggered.') // Currently not using these two parameters but just an example let claim_type = req.body.sessionInfo.parameters.claim_type; let passenger_flight_date = req.body.sessionInfo.parameters.passenger_flight_date; // Calculate qualifying rebate amount for delayed bags let rebate_amount = 0 if (claim_type == 'delayed') { let date_difference = Math.abs(moment(passenger_flight_date).diff(moment(), 'days')); // Cap the qualifying days at 5 let rebate_qual_days = Math.min(date_difference, 5) // An example of giving $50 per day of delay rebate_amount = rebate_qual_days * 50 } // These parameters are being checked let passenger_flight_number= req.body.sessionInfo.parameters.passenger_flight_number; passenger_last_name= req.body.sessionInfo.parameters.passenger_last_name; let passenger_reference_id= req.body.sessionInfo.parameters.passenger_reference_id; let claim_confirmation_id; if (passenger_flight_number == 'AJ143' && passenger_last_name == 'Garcia' && passenger_reference_id == '1234567890123') { claim_filed = true; // Generate random 6 digit number to return const rand_id = Math.floor(100000 + Math.random() * 900000) claim_confirmation_id = 'REF' + rand_id.toString() } else { claim_filed = false; } res.status(200).send({ sessionInfo: { parameters: { claim_filed: claim_filed, claim_confirmation_id: claim_confirmation_id, rebate_amount: rebate_amount } } }); break; // This is the case to verify form parameters that get updated throughout the conversation case 'verifyParameters': // Capture newly updated form parameters console.log(tag + ' was triggered.') let params = req.body.pageInfo.formInfo.parameterInfo let paramToValidate = {name: '', value: ''} // Only validate the form parameter if it was just collected for (let param of params) { if (param.justCollected == true) { console.log('Received parameter: ', param) paramToValidate = param; } } // Validate Passenger Reference ID // Must == '1234567890123' in order to continue if (paramToValidate.displayName == 'passenger_reference_id') { if (paramToValidate.value != '1234567890123') { paramToValidate.state = 'INVALID' } else { paramToValidate.state = 'VALID' } } // Validate Flight Date // Must be on or before current date if (paramToValidate.displayName == 'passenger_flight_date') { let flight_date = paramToValidate.value let now = moment() if ((moment(flight_date) <= now)) { paramToValidate.state = 'VALID' } else { paramToValidate.state = 'INVALID' } } res.status(200).send({ pageInfo: { formInfo: { parameterInfo: [paramToValidate] } } }); break; default: break; } } };
여행: 렌터카 에이전트
이 템플릿을 사용하면 최종 사용자가 새로운 렌터카 예약을 시작할 수 있습니다.
샘플 발화
- I need to reserve a van.
- Hi, I'm traveling to LA for the weekend and I need to rent a car while I'm down there.
- I need help booking an SUV.
여행: 항공편 정보 에이전트
이 템플릿을 사용하면 최종 사용자가 티켓을 예약 및 변경하고 항공편 정보를 찾고 환불을 요청할 수 있습니다.
샘플 발화
- My flight XX4597 needs to be changed. Can you help me?
- Can you help me find out the new departure time for my flight.
- What about the credit on my account from my cancelled flight?
- Can you book my flight to San Francisco next month?
- Book SFO 10am to MIA on August 10th, 2020 one way.