In Russia alone, KFC opens more than 100 restaurants every year (imagine worldwide numbers), and all these restaurants need staff. Working in fast-food restaurants is popular among young people; many seek this kind of work temporarily. And all of them send their CVs to KFC.

Because of this KFC gets more than 15,000 applications every month and needs to process them. But imagine how many HR employees they would need to call all the applicants? Factor in that most applicants are underage or that they don’t need the job anymore and it looks like a waste of time and money spent on HR.

This is why KFC asked Voximplant for help. And the solution was obvious: we created a robot that called all the applicants and asked them a simple question, "Do you want to work for KFC?". If they say yes, the robot asks for some additional information, about their age/documents/desired work hours and more, and passes the information to an HR manager who is ready to employ them.

The results were astounding. The robot processes the applications 10 times faster than a human, filters 37% of candidates as irrelevant, and HR managers increase their conversion by 11%.

Today I want to talk to you about how to create such a robot for your own purposes.

Actually, it's not as hard as it may seem. Let's create a simple robot like the one KFC uses, right now.

The task will be simple: call all the candidates from a call list, greet them, ask them if they want to work for us, recognize their answer, and connect to a call-center specialist depending on their answer.

Let's log into the Voximplant platformcreate an application, and start with a scenario. First, we need to import speech recognition and speech synthesis modules, declare necessary constants and start writing our logic.

require(Modules.ASR);
require(Modules.Player);

const callerid = '7xxxxxxxxxx';
const operator = '7xxxxxxxxxx';
let data;
let callCandidate, callOperator;
let asr;

We can pass all the necessary input to the scenario in the VoxEngine.customData field. For our example, let's use the following JSON format: { "phone" : "7xxxxxxxxxx", "name": "John" }.

At scenario start, we parse the JSON from customData and initiate a call from callerid to data.phone and connect the event handlers:

VoxEngine.addEventListener( AppEvents.Started, async e => {
 data = JSON.parse( VoxEngine.customData() );
  // Start a call from callerid to data.phone
 callCandidate = VoxEngine.callPSTN( data.phone, callerid );

 // Add event listeners
 callCandidate.addEventListener( CallEvents.Connected, callCandidate_connected_handler );
 callCandidate.addEventListener( CallEvents.Disconnected, callCandidate_disconnected_handler );
 callCandidate.addEventListener( CallEvents.Failed, callCandidate_failed_handler );
});

When our candidate answers the call, we create a Player to synthesize speech, set some text (use your imagination), and play it to our candidate. We can integrate 3rd-party voices, so let's use one from Yandex:

function callCandidate_connected_handler( e ) {
 // Create a text-to-speech player
 const text = `Здравствуйте ${data.name}. Хотите работать?`;
 const language = VoiceList.Yandex.Neural.ru_RU_alena;
 const player = VoxEngine.createTTSPlayer( text, language );

 // Start playback and connect an event listener after
 player.sendMediaTo( callCandidate );
 player.addEventListener( PlayerEvents.PlaybackFinished, playbackFinishedHandler );
};

When the playback finishes, we need to process the candidate's answer. For our example, let's integrate a voice recognition profile from Tinkoff:

function playbackFinishedHandler() {
 // Create an ASR for speech recognition
 const asrProfile = ASRProfileList.Tinkoff.ru_RU;
 asr = VoxEngine.createASR( { profile: asrProfile } );

 // Wait for the human’s response and add an event listener
 // which will trigger after speech recognition
 callCandidate.sendMediaTo( asr );
 asr.addEventListener( ASREvents.Result, asrResultHandler );
}

Now the candidate's answer is recorded and transcribed to text. We can process the result as we need. As a simple way, if the candidate's answer has the keyword "no" in it, let's just record it to our data object and hang up (you may want another logic).

If the candidate's answer has the word "yes", let's also record this to our data object's field and connect it to an operator:

async function asrResultHandler( answer ) {
 // Disable event listener
 asr.removeEventListener( ASREvents.Result );

 // The answer is written into text field
 // we can proceed the result as we want
 if( answer.text.includes( 'no' ) ) {

   // Update the data object
   data.wantsToWork = 'no';

   // Hang up ( Triggers the callCandidate_disconnected_handler )
   callCandidate.hangup();
 }
 else if ( answer.text.includes( 'yes' ) ) {
   data.wantsToWork = 'yes';

   // Call the operator function
   startOperatorCall();
 }
 else {
   callCandidate.hangup();
 }
}

function startOperatorCall() {
 const callOperator = VoxEngine.callPSTN( operator, callerid );

 // Unite two calls into one
 VoxEngine.sendMediaBetween( callCandidate, callOperator );

 // Connect event handler
 callOperator.addEventListener( CallEvents.Connected, () => {
   Logger.write( 'Подключились к оператору' );
 });
 callOperator.addEventListener( CallEvents.Disconnected, async () => {
   callCandidate.hangup();
 });
 callOperator.addEventListener( CallEvents.Failed, async () => {
   callCandidate.hangup();
 });
}

All that we need to process now is the session's termination. For example, if the call attempt was successful, we send the result object (with candidates' answers) via an HTTP request, and terminate our session. If the call attempt was not successful, just terminate the session.

// The call was successful
async function callCandidate_disconnected_handler( e ) {
 const url = 'https://servicename';

 // Send the data object via a POST http request to specific url
 await Net.httpRequestAsync( url, { method: 'POST', postData: JSON.stringify(data) } );

 // Terminate session
 VoxEngine.terminate();
};

// The call was not successful
function callCandidate_failed_handler( e ) {
 VoxEngine.terminate();
};

Voila. Now we have a primitive robot who accepts a call list, calls every candidate, and asks them if they want to work for us. Then it writes their answer in text form to the database and connects to an HR manager if the candidate wants to work.

This was a simple example. Next you can extend your robot's logic, create complex dialogs and algorithms, connect your candidates to different departments depending on their answer, or collect any additional information you want. It has no limits, only your imagination!

I hope this explanation was useful, and I hope you all find a great team and develop a productive business!