<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[cogint.ai]]></title><description><![CDATA[A blog exploring AI in voice, vision, and human communications]]></description><link>https://cogint.ai/</link><image><url>https://cogint.ai/favicon.png</url><title>cogint.ai</title><link>https://cogint.ai/</link></image><generator>Ghost 1.26</generator><lastBuildDate>Wed, 25 Mar 2026 21:25:53 GMT</lastBuildDate><atom:link href="https://cogint.ai/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Improving Dialogflow Phone Calls by Adding Noise]]></title><description><![CDATA[How to add filler noise (aka comfort noise) and ambient noises to Dialogflow voicebots for the phone to improve the user experience.]]></description><link>https://cogint.ai/dialogflow-adding-noise/</link><guid isPermaLink="false">5e47e95f19179907b8df4e3a</guid><category><![CDATA[dialogflow]]></category><category><![CDATA[voicebot]]></category><category><![CDATA[guide]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Tue, 10 Mar 2020 11:15:00 GMT</pubDate><media:content url="https://cogint.ai/content/images/2020/03/Depositphotos_12301680_l-2015-cropped.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2020/03/Depositphotos_12301680_l-2015-cropped.jpg" alt="Improving Dialogflow Phone Calls by Adding Noise"><p>Generally technology has advanced to remove noise and make audio clearer with a higher signal to noise ratio. While this makes sense in most contexts, various forms of noise have become part of the user experience when making a phone call. Dialogflow is largely made for a smartphones and smart speakers  environment, so subtleties of the phone medium can be lost. Have you ever notice how a phone call is never truely silent? There’s a reason for that. Fortunately, it isn’t too difficult to add noise to a Diaogflow voicebot for the phone.</p>
<p>In this post I will cover how to add two kinds of noise:</p>
<ul>
<li>Filler noise - using noises to mask silent periods, and</li>
<li>Ambient noise - background noise to simulate a specific environment</li>
</ul>
<p>Read-on for details and examples.</p>
<h1 id="fillernoise">Filler Noise</h1>
<p>Let’s look at filler noise first, which is generally easier.</p>
<h2 id="whyaddfillernoise">Why add filler noise?</h2>
<p>We usually try to avoid noise, so why would we want to add it to our bot?</p>
<h3 id="absolutesilenceisbad">Absolute silence is bad</h3>
<p>User’s don’t like to hear silence on the phone. One byproduct of the original analog phone system is that users would always hear some electrostatic background noise. This noise eventually became a feature as users became used to interpreting that this noise meant they were connected, even if the other party wasn’t talking. When Voice over IP (VoIP) systems came about, <a href="https://en.wikipedia.org/wiki/Comfort_noise">comfort noise</a> was actually engineered into the call. Most VoIP systems actually inject artificially generated comfort noise into a call that would otherwise be perfectly silent when someone isn’t speaking.</p>
<h3 id="noiseisanonverbalformofcommunication">Noise is a non-verbal form of communication</h3>
<p>Smart speakers generally have LED indicators that tell the user the device heard them and is processing. This visual indicator provides functions as a subtle feedback mechanism, letting the user know the device is doing something. However, if you hook that same virtual assistant up to a phone call, you lose that visual indicator and are limited to audio signals. Furthermore, phone assistants are trying to mimic human agents. Humans often need time to think or respond to prompts. They respond instantly, even if with a speech disfluency - i.e. “uh, ok - let me check that”.</p>
<p>Oftentimes users also hear some background call center noise or the agent typing in between interactions which also functions as a type of comfort noise to let the user know the line is still connected.</p>
<h2 id="usingssmltofakeadelaywithnoise">Using SSML to fake a delay with noise</h2>
<p>Inserting sounds inside of a response is easy using the <code>&lt;audio&gt;</code> method in SSML. Google <a href="https://developers.google.com/assistant/actions/reference/ssml#audio">supports several properties</a> for when to start and stop the clip.  I find the <code>repeatDur</code> property the easiest to use since it won’t exceed the value you enter and will repeat the audio clip if your clip happens to be shorter.</p>
<h3 id="findingfillersounds">Finding filler sounds</h3>
<p>You will also need to find some sound files or record your own. You could record some noises at an agent desk or you could look for some recordings online. Google actually has a filterable library of sounds you can find, listen to, and link to here: <a href="https://developers.google.com/assistant/tools/sound-library">https://developers.google.com/assistant/tools/sound-library</a><br>
Amazon has a <a href="https://developer.amazon.com/en-US/docs/alexa/custom-skills/ask-soundlibrary.html">massive sound library for Alexa Skills</a>, but their terms limit use to Alexa apps.<br>
There is also a <a href="https://www.youtube.com/audiolibrary/soundeffects">free sound library on YouTube</a>. Make sure to read their usage terms.</p>
<p>Let's start with a typing noise, which isn't uncommon to hear when calling an agent:</p>
<p><audio controls><source src="https://actions.google.com/sounds/v1/office/keyboard_typing_fast_far.ogg" type="audio/ogg"><br>
Your browser does not support the audio tag.<br>
</audio></p>
<p>Note it doesn't sound very loud and shouldn't, so you may need to turn your speakers up.</p>
<h3 id="examplebot">Example bot</h3>
<p>As a simple example, let’s make a bot that does simple multiplication. I called it <code>math.multiply</code> with some training phrases:<br>
<img src="https://cogint.ai/content/images/2020/03/1---bot-training.png" alt="Improving Dialogflow Phone Calls by Adding Noise"></p>
<p>With 2 parameters:<br>
<img src="https://cogint.ai/content/images/2020/03/2---parameters.png" alt="Improving Dialogflow Phone Calls by Adding Noise"></p>
<h3 id="fulfillmentexample">Fulfillment example</h3>
<p>Now let’s show how we can make our agent add a pause with some background noise. My complete fulfilment code looks like this:</p>
<pre><code>const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
 
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
 
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) =&gt; {
  const agent = new WebhookClient({ request, response });
  console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
  console.log('Dialogflow Request body: ' + JSON.stringify(request.body));

  function multiply(agent) {
    const number1 = agent.parameters.number1;
    const number2 = agent.parameters.number2;
    const answer = number1 * number2;
    
    const max = 5;
    const min = 2;
    const duration = Math.random() * (max - min) + min;
    
    agent.add(`
       &lt;speak&gt; ${number1} multiplied by ${number2}. 
         &lt;audio repeatDur=&quot;${duration} s&quot; src= &quot;https://actions.google.com/sounds/v1/office/keyboard_typing_fast_close.ogg&quot;&gt;
           &lt;desc&gt;keyboard typing&lt;/desc&gt;
         &lt;/audio&gt;
         That comes to ${answer}.
       &lt;/speak&gt;`);
  }
  
  // Run the proper function handler based on the matched Dialogflow intent name
  let intentMap = new Map();
  intentMap.set('math.multiply', multiply);
  agent.handleRequest(intentMap);
});
</code></pre>
<p>This is mostly Dialogflow’s standard fulfillment example code except for the <code>multiply</code> function. You can see here I just set a random time between a min and max to pause for 2 to 5 seconds.</p>
<h2 id="hearsomefillernoise">Hear some filler noise</h2>
<p>You can try this below without dialing in.<br>
Just ask it something like:</p>
<blockquote>
<p>what is 431 times 31234?</p>
</blockquote>
<iframe width="800" height="730" allow="microphone;" src="https://console.dialogflow.com/api-client/demo/embedded/8dde093a-1480-44f8-bcb4-f514eb650a38"></iframe>
<p>Make sure to hit the audio button to hear the response.</p>
<h1 id="ambientbackgroundnoise">Ambient background noise</h1>
<p>Even if you aren’t running an <a href="https://www.vox.com/2015/7/15/8965393/asmr-video-youtube-autonomous-sensory-meridian-response">ASMR</a> phone service, ambient background noise can give your phonebot a distinctive, life-like experience.</p>
<h2 id="whyambientnoise">Why ambient noise?</h2>
<p>If you were calling a busy coffee shop, if a live person picked up (assuming they don’t have a fancy noise cancelling microphone) you would hear some background noise. So long as the background noise isn’t too loud or distracting, this ambience can make the experience seem more authentic.</p>
<h2 id="findingbackgroundnoises">Finding Background Noises</h2>
<p>Dialogflow actually includes a number of these ambiances in the Google Assistant sound library: <a href="https://developers.google.com/assistant/tools/sound-library/ambiences">https://developers.google.com/assistant/tools/sound-library/ambiences</a></p>
<p>Of course if you can always record one yourself in a real environment.</p>
<h2 id="addingcontinuousbackgroundnoise">Adding Continuous Background Noise</h2>
<p>As we showed earlier, adding noise within a prompt is simple, but how do you add in ambient background noises?</p>
<p>Dialogflow does not really give a way to do this out of the box. It plays a prompt and waits for a response. Dialogflow won’t generate noise while it is waiting. The only option is to do this from your telephony platform or RTC-Bot Gateway. Usually this will look something like this:<br>
<img src="https://cogint.ai/content/images/2020/03/3---mixing-background-noise.png" alt="Improving Dialogflow Phone Calls by Adding Noise"></p>
<h6 id="usingconferencingtomixinambientaudio">Using conferencing to mix in ambient audio</h6>
<p>You need some kind of mixer that will combine the Dialogflow audio stream with the ambient noise. Often this can be implemented via a conference bridge. Dialogflow’s speech to text  is pretty good at ignoring background noise, but it is always best to send it a clean signal if possible so send the media direct from the caller to Dialogflow without the ambient noise mixed in if you can.</p>
<p>Dialogflow’s Phone Gateway will not do this by itself, but some of the third party options let you do mixing/conferencing in their platform. If you are using the <a href="https://cogint.ai/3-methods-for-connecting-a-phone-call-to-dialogflow/#method2forwardcallstodialogflowphonegateway">call forwarding approach</a>, you can always mix the audio in a conference bridge before forwarding the call to the Dialogflow Phone Gateway.</p>
<p>I added the coffee shop noise to the Math-bot above as an example.<br>
Here is the background noise:<br>
<audio controls> <source src="https://actions.google.com/sounds/v1/ambiences/coffee_shop.ogg" type="audio/ogg"><br>
Your browser does not support the audio tag.<br>
</audio></p>
<p>And here is a recording of a call where I ask it some questions:<br>
<audio controls><source src="https://cogint.ai/ambient_noise_example.mp3" type="audio/mp3"><br>
Your browser does not support the audio tag.<br>
</audio></p>
<p>I happened to use Voximplant to build this example. You can see the code for it <a href="https://gist.github.com/chadwallacehart/d88e3fd94b50d3afd86f18f990dfa63d">here</a>.</p>
<h2 id="makesomenoise">Make Some Noise</h2>
<p>Noise isn’t always bad. Used effectively, it will actually make your calls seem less like a bot and more like a human on the other end. Used creatively, it can help enhance a businesses brand and make the phone experience unique.</p>
<p>Let me know how you make use of various noises in your phonebots in the comments below.</p>
<hr>
<h3 id="abouttheauthor">About the Author</h3>
<p>Chad Hart is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and strategy advisory helping to advance the communications industry. In addition, recently he co-authored a study on <a href="https://krankygeek.com/research">AI in RTC</a> and organizes <a href="https://krankygeek.com">events</a> / <a href="https://www.youtube.com/watch?v=P38cd3GLn74&amp;list=PL4_h-ulX5eNfaM0QM5r-PewWaY_zgLH7b">YouTube series</a> covering that topic.</p>
<hr>
<h3 id="remembertosubscribefornewpostnotificationsandfollowcogintai">Remember to <a href="https://cogint.ai/subscribe/">subscribe</a> for new post notifications and follow <a href="https://twitter.com/cogintai">@cogintai</a>.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes]]></title><description><![CDATA[Review and guide on building an interactive, speech-based conversational / voicebot IVR using  Amazon Lex and Amazon Connect]]></description><link>https://cogint.ai/conversational-ivr-with-amazons-lex-and-connect/</link><guid isPermaLink="false">5e0d29ea19179907b8df4e1b</guid><category><![CDATA[voicebot]]></category><category><![CDATA[guide]]></category><dc:creator><![CDATA[Binoy Chemmagate]]></dc:creator><pubDate>Fri, 03 Jan 2020 11:59:00 GMT</pubDate><media:content url="https://cogint.ai/content/images/2020/01/Depositphotos_82899872_l-2015.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2020/01/Depositphotos_82899872_l-2015.jpg" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"><p>Voicebot usage with smart phones and smart speakers is growing like a storm. Bots in general are making their way to more customer-support use cases, but it is still pretty rare to hear a voicebot on a customer support phone call. Amazon is one of the major tech giants looking to change this with a combination of some of their recent capabilities.</p>
<p>In this blog, I will show you how to build a voicebot for your business using a combination of Amazon's bot and contact center services - Amazon Lex and Amazon Connect.</p>
<h1 id="introductiontoamazonlexandconnect">Introduction to Amazon Lex and Connect</h1>
<p>Lex is Amazon’s Natural Language Understanding (NLU) service for bots. It includes an Automatic Speech Recognition (ASR) - aka Speech-to-Text (STT) - option so it can handle voice in addition to text.  Since it is an AWS service, it incorporates Amazon’s usual scalability and pay-as-you-go model that developers and developers of all sizes have come to depend on.</p>
<p>Amazon Connect is a Contact Center as a Service (CCaaS) that can be set up in a few minutes. Rather than building a call center from scratch or purchasing expensive software, Amazon Connect provides tools to make provisioning a call center easy. Connect includes a phone number for incoming and outgoing calls with tools for provisioning agents quickly from a dashboard.</p>
<p>Taken in combination, AWS and Lex can be used to build a Conversational IVR. The advantage of AWS combo over the existing solutions is that you can connect your Lex bot to the dial-in number without a 3rd party service. This reduces many complexities such as setting up a telephony interface between the dial-in number and the bot, reduces latency (given the Lex bot and Amazon Connect are in the same AWS region), making changes and publishing is faster.</p>
<h1 id="architecture">Architecture</h1>
<p>When you are building a conversational IVR voicebot, you need 3 main components.</p>
<ol>
<li>Bot engine</li>
<li>Telephony infrastructure - to handle calls</li>
<li>RTC-bot gateway - to connect the bot to the telephony system</li>
</ol>
<p>Amazon Lex acts as the voicebot in our case. Amazon Connect provides the dial-in number for the voicebot. Fortunately, we don’t have to look further for a RTC-bot gateway since Amazon Connect can connect directly to the Amazon Lex based voicebots. You can check this <a href="https://docs.aws.amazon.com/connect/latest/adminguide/amazon-lex.html">documentation</a> for more details.</p>
<p><img src="https://cogint.ai/content/images/2020/01/architecture.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<h1 id="pricing">Pricing</h1>
<p>The pricing is split between Lex and Connect since you need both services:</p>
<table>
<thead>
<tr>
<th><strong>Amazon Lex</strong></th>
<th><strong>Price in USD</strong>*</th>
</tr>
</thead>
<tbody>
<tr>
<td>  Speech request</td>
<td>$0.004 / request</td>
</tr>
<tr>
<td>  Text request</td>
<td>$0.00075 / request</td>
</tr>
<tr>
<td><strong>Amazon Connect</strong></td>
<td> </td>
</tr>
<tr>
<td>  Phone number (U.S. East)</td>
<td>$0.03 per day</td>
</tr>
<tr>
<td>  Inbound usage (U.S. East)      </td>
<td>$0.0022 per minute</td>
</tr>
</tbody>
</table>
<h6 id="amazonconnectandlexpricingsnapshotasof2019dec30th">*Amazon Connect and Lex pricing snapshot as of 2019 Dec 30th.</h6>
<p>Let’s say you have a smaller call center with 10,000 calls a month, with an average call duration of 3 minutes. Assuming a split of 50%, 40%, 10% for the bot, customer and silence respectivley in each call, we can calculate the total cost for Amazon Lex and Connect. For each call, on average we are sending 5 speech requests to Lex.</p>
<table>
<thead>
<tr>
<th>Billable item</th>
<th>Unit Price  </th>
<th>Unit</th>
<th style="text-align:right">Units</th>
<th style="text-align:right">Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lex speech requests</td>
<td>$0.0040</td>
<td>/request</td>
<td style="text-align:right">50,000</td>
<td style="text-align:right">200.00</td>
</tr>
<tr>
<td>Amazon Connect - Phone number  </td>
<td>$0.0300</td>
<td>/day</td>
<td style="text-align:right">20</td>
<td style="text-align:right">0.60</td>
</tr>
<tr>
<td>Connect - Inbound usage</td>
<td>$0.0022</td>
<td>/minute</td>
<td style="text-align:right">30,000</td>
<td style="text-align:right">66.00</td>
</tr>
<tr>
<td>-------------------------------------------</td>
<td>--------------</td>
<td>------------</td>
<td style="text-align:right">----------</td>
<td style="text-align:right">------------</td>
</tr>
<tr>
<td><em><strong>Total</strong></em></td>
<td><em><strong>$0.0089</strong></em></td>
<td><em><strong>/minute</strong></em></td>
<td style="text-align:right">     <em><strong>30,000</strong></em></td>
<td style="text-align:right">  <em><strong>$266.60</strong></em></td>
</tr>
</tbody>
</table>
<p>Your total cost is around $267, given you are not using any monitoring or storage functionality. That comes to less than a tenth of a cent, much less than competitive voicebot telephony options.</p>
<h1 id="howtoguide">How to Guide</h1>
<h2 id="creatingavoicebotusinglex">Creating a Voicebot using Lex</h2>
<p>Assuming you have an AWS (Amazon Web Services) account already, all you have to do is to click on Amazon Lex service. If this is your first bot then choose <em>Get Started</em>, otherwise, click create. Lex offers few templates for building bots, I will choose <em>Custom Bot</em> so you can build any bot you wish.</p>
<p><img src="https://cogint.ai/content/images/2020/01/lex---create-your-bot.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<p>I have named the bot <em>RestaurantBot</em> since this is a bot intended to make reservations for a restaurant. The default language is US English and you can choose male or female voices and type sample texts to hear the voice samples. The session time out defines how long you would like the bot to keep the context of the conversation when the customer goes silent. Here I have chosen 1 minute as that’s kind of ideal for a restaurant reservation. If you would like to measure the sentiment of the customer conversations, then click <em>Yes</em>. The <a href="https://docs.aws.amazon.com/lex/latest/dg/security_iam_service-with-iam.html">IAM role</a> is automatically created and you can opt for <a href="https://docs.aws.amazon.com/lex/latest/dg/data-protection.html">COPPA</a> based on your preference.</p>
<p><img src="https://cogint.ai/content/images/2020/01/Bot-creation-general-settings.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"><br>
Click on <em>Create</em> and the first screen is about creating an intent.</p>
<h3 id="botterminology">Bot terminology</h3>
<p>Before we go too far, let’s review some terminology. When you are building/training with bots using Dialogflow, Amazon Lex or any other virtual assistants, you need to be familiar with some basic Natural Language Processing (NLP) concepts:</p>
<ul>
<li><strong>Intents</strong> - The intention or goal of the customer. A customer booking a table can be an intent e.g. <em>BookMyTable</em></li>
<li><strong>Utterances</strong> - These are the spoken phrases by the customer to invoke an intent. This could be any phrase for reservation e.g. Can I have a table for two? I am looking for a dinner reservation, etc.</li>
<li><strong>Slots</strong> - The essential information needed for the voicebot to fulfill a customer request. This could be the date or time or the number of people, etc.</li>
<li><strong>Fulfillment</strong> - This is the action you want the voicebot to perform when the essential information is available. This can be two things, a response to the customer saying the reservation was successful or failure and a message to the restaurant for booking the slot.</li>
</ul>
<p>There is plenty of <a href="https://docs.aws.amazon.com/lex/latest/dg/how-it-works.html">documentation</a> out there that explains these in more detail.</p>
<h3 id="creatinganintent">Creating an Intent</h3>
<p>Click on <em>Create intent</em> and give a unique and identifiable intention/goal name. Here I have chosen <em>BookMyTable</em>.<br>
<img src="https://cogint.ai/content/images/2020/01/Lex---create-intent.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<p>Click <em>Add</em> and that's it. Good job - you have created your first intent!</p>
<p>Now you will add a sample utterance for the bot so it can relate the phrases to the intent you just created.</p>
<h3 id="addingsampleutterances">Adding sample utterances</h3>
<p>Type in the common spoken phrases you would use while making table reservations. I am using the following samples.</p>
<p><img src="https://cogint.ai/content/images/2020/01/Lex---sample-utterances.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"><br>
One advantage of using Lex is that you can also invoke a <a href="https://docs.aws.amazon.com/lambda/index.html">Lambda</a> function for processing the customer inputs. I will talk about some use cases of using Lambda functions briefly in the last section. Now that you have trained the intent with some utterances, the next step is adding slots.</p>
<h3 id="addingslots">Adding slots</h3>
<p>Slots make sure the bot has all the information needed from the customer to perform an action or lead to the fulfillment of a request. For making a restaurant reservation, you probably need 4 essential slots.</p>
<ol>
<li>Name of the customer</li>
<li>Date of the reservation</li>
<li>Time of the reservation</li>
<li>Number of people</li>
</ol>
<p>The customer might already give some of this information and you can add the slots within the <em>Sample utterances</em> to catch them early so that the bot need not ask those questions again.</p>
<p><img src="https://cogint.ai/content/images/2020/01/Lex---slots.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<p>We can make each slot name mandatory or optional depending on the bot you are building. The slot type will define the input type expected from the customer. The prompts are like utterances from the bot to receive customer input. I have made all the slots as mandatory since a restaurant would require all that information to confirm a reservation unless the customer has table preference or food allergies, etc.</p>
<p>We can add a confirmation prompt after adding the slots. This will repeat the reservation details and confirm with the customer. I am reading out the customer inputs using the slot names we defined earlier.</p>
<p><img src="https://cogint.ai/content/images/2020/01/Lex---confirmation-prompt.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<h3 id="addingfulfillment">Adding fulfillment</h3>
<p>Fulfillment lets you send the reservation details (if everything goes well) to your restaurant’s booking system by invoking Lambda functions or return the parameters to the customer. The Lambda function can come in handy when you want to check the reservation against the availability of tables or opening hours, etc. This bot can start another conversation with the customer with alternative options.</p>
<p>The conversation ends with adding a response and <strong>saving</strong> the intent. You can add your favorite greeting here.</p>
<p><img src="https://cogint.ai/content/images/2020/01/Lex---confirmation-prompt-1.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<h3 id="buildtestandpublish">Build, Test and Publish</h3>
<p>Click on the “Build” button on the top right corner and this would show all the errors and these errors are self-explanatory so you can easily debug the errors. Once you confirm the build and if the build is successful, you will get a message shown below.<br>
<img src="https://cogint.ai/content/images/2020/01/Lex---build-successful.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<p>To test the bot, start by entering one of the spoken phrases you have added as utterances and continue the conversation.<br>
<img src="https://cogint.ai/content/images/2020/01/Lex---testing.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<p>Once you get the correct responses, you can now publish the bot by clicking <em>Publish</em> and this bot will be available for other AWS services to access. Do not forget to create an alias name for Amazon Connect to identify this bot among other bots you created. You have completed building a basic bot, great job!</p>
<p>Now let’s add a dial-in interface for it.</p>
<h2 id="addingadialinnumberforyourbotwithconnect">Adding a dial-in number for your bot with Connect</h2>
<p>We will use Amazon Connect to add a phone number than can dial into the bot.  Start by selecting the Amazon Connect service from AWS services and choose <em>Get Started</em> or <em>Add Instance</em> if you already have an Amazon Connect Instance. You can give a unique name for the instance and click <em>Next Step</em> as the default configurations would be good enough for our use case. You finish by clicking <em>Create instance</em> and it might take a while for the instance to be ready.</p>
<h3 id="addingyourlexbottocontactflows">Adding your Lex bot to contact flows</h3>
<p>Go back to your Amazon Connect service panel in AWS services (NOT the Amazon Connect instance URL) and click on the instance name and select the <em>Contact flows</em>. The contact flow defines the customer experience from start to end. We want the customer to talk to our bot instead of a real agent so we need to add the bot to the contact flow.</p>
<p>Select the Lex bot from the drop-down menu and click <em>Add Lex Bot</em>. Make sure you create the Lex bot and Amazon Connect in the same AWS regions to avoid delays.</p>
<p><img src="https://cogint.ai/content/images/2020/01/Connect---add-Lex.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<h3 id="setupyouramazonconnectinstance">Setup your Amazon Connect Instance</h3>
<p>Login to your Amazon Connect instance (e.g. 	<a href="https://chemmagate.awsapps.com/connect/login">https://chemmagate.awsapps.com/connect/login</a>) as Admin and click on Routing on the side panel and select <em>Contact Flows</em>. We are going to create a new contact flow for the bot as we want the customer input. Do not forget to give a name to your contact flow. Drag the <em>Get customer input</em> block under <em>Interact</em> onto the designer and connect it to the <em>Entry point</em> block.</p>
<p><img src="https://cogint.ai/content/images/2020/01/Connect---contact-flow-setup.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<p>Click on the <em>Get Customer Input</em> block and Choose <em>Text-to-speech or chat text</em>. You will add greetings to your customer here in this text box.<br>
<img src="https://cogint.ai/content/images/2020/01/Connect---get-customer-input.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<p>Choose Amazon Lex and select your bot from the list. Also, add the intent you created and save it. We can keep the alias as <code>$LATEST</code> as long as you do not have multiple versions of your bot.</p>
<p><img src="https://cogint.ai/content/images/2020/01/Connect---set-alias.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<p>You can add a block <em>Disconnect/Hang up</em> block so that your bot disconnects the call after it fulfils the intent. Press <em>Publish</em> to make this flow available to use (this is important).<br>
<img src="https://cogint.ai/content/images/2020/01/Connect---disconnect-block.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<h3 id="assigninganumbertothecontactflow">Assigning a number to the contact flow</h3>
<p>We will now claim a number for the contact flow we just created. Click on Routing on the side panel and select <em>Phone Numbers</em>. Choose <em>Claim a number</em> and choose the country and the number you would like to use. Select the contact flow you just created and click <em>Save</em>.</p>
<p><img src="https://cogint.ai/content/images/2020/01/Connect---phone-number.png" alt="Build a Conversational IVR with Amazon’s Lex and Connect in 45 minutes"></p>
<p>Call the number and ask “Can I have a table for Friday?” (or the utterances you created) and see how your bot responds. It might say “sorry, I could not understand, can you please repeat that”. After a few tries, it will eventually work 😀</p>
<p>Congratulations, you made a basic voicebot-based conversational IVR!</p>
<h1 id="recapconclusions">Recap &amp; Conclusions</h1>
<p>The whole process took me about 45 minutes as I had some previous experience with Amazon Connect so that part took the least amount of time in this setup. I had some hiccups while publishing the bot as it is very strict about the syntax and slot types. Of course this is a simple example and a real bot would need a lot more work.</p>
<h2 id="prosandconsoftheawsapproach">Pros and Cons of the AWS approach</h2>
<p>There are some advantages and limitations to the AWS approach:</p>
<h3 id="advantages">Advantages</h3>
<ol>
<li>Dial-in number to voicebot works seamlessly so you don’t have to do any telephony interface tricks</li>
<li>Very easy to transfer the call to a human agent with Amazon Connect capabilities.</li>
<li>Lambda functions enhance your bot’s skills tremendously as it can invoke notifications such as SMS, email or integrate with 3rd party systems</li>
<li>Use DTMF or Amazon Lex for accepting input from the customer, unlike other systems which can only process one input type (DTMF or voice commands) at a time</li>
<li>Easily integrate Amazon Lex with Facebook apps, Kik, Slack or Twilio SMS</li>
</ol>
<h3 id="limitations">Limitations</h3>
<ol>
<li>Training utterances was more cumbersome than I expected - I had to provide many sample utterances to get the bot to pick up a variety of phrases for an intent.</li>
<li>Confidence percentages are not exposed in the Lex GUI, so it is difficult to tell when you need to do more training for an intent</li>
<li>There is no built-in small talk (like Dialogflow), so you need to train it to do everything</li>
<li>The bot can go in a loop of asking the same question and annoy the user sometimes, which is again the lack of training</li>
<li>Amazon Connect configurations can be complex for a telephony system beginner.</li>
</ol>
<h2 id="scorecard">Scorecard</h2>
<p>Looking at the scorecard Chad used in <a href="https://cogint.ai/tag/voicebot/">his previous voicebot IVR posts</a>, Amazon Lex powered with Amazon Connect is a good fit for most voicebot IVR features.</p>
<table>
<thead>
<tr>
<th><strong>Requirements</strong></th>
<th><strong>Amazon Lex with Connect</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Call Transfer</td>
<td>Yes</td>
</tr>
<tr>
<td>Recording</td>
<td>Yes</td>
</tr>
<tr>
<td>Playback interruption      </td>
<td>No - cannot be set from Lex console</td>
</tr>
<tr>
<td>No activity detection</td>
<td>Yes - session timeout</td>
</tr>
<tr>
<td>DTMF detection</td>
<td>Yes</td>
</tr>
<tr>
<td>SMS</td>
<td>Yes - with Lambda functions or channels</td>
</tr>
</tbody>
</table>
<p> <br>
Amazon Connect offers typical dial-in telephony capabilities like transfer and record. When a feature isn't there, Amazon does provide some flexibility to extend functionaly with AWS Lambda functions with nice features like  built in storage.</p>
<hr>
<h3 id="abouttheauthor">About the Author</h3>
<p><a href="https://www.linkedin.com/in/binoychemmagate/">Binoy Chemmagate</a> is a product manager with 9+ years of experience in the ICT industry. He started his ICT career with Nokia as a standardization engineer and standardization bodies such as IETF and W3C have recognized his work on Web transport protocols. He has co-authored publications and patents in real-time communication and machine to machine communication fields. He has been an invited speaker at international WebRTC conferences around the world. In his free time, he is involved in product development coaching in the local startup ecosystem.</p>
<hr>
<h3 id="remembertosubscribefornewpostnotificationsandfollowcogintai">Remember to <a href="https://cogint.ai/subscribe/">subscribe</a> for new post notifications and follow <a href="https://twitter.com/cogintai">@cogintai</a>.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[AudioCodes Voice.AI Gateway Review]]></title><description><![CDATA[A review of AudioCodes' Voice.AI Gateway for connecting SIP and phone calls to speech and bot services. Review of the product and tests connecting to Dialogflow.]]></description><link>https://cogint.ai/audiocodes-voice-ai-gateway-review/</link><guid isPermaLink="false">5def0aa519179907b8df4e04</guid><category><![CDATA[voicebot]]></category><category><![CDATA[dialogflow]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Tue, 10 Dec 2019 11:55:00 GMT</pubDate><media:content url="https://cogint.ai/content/images/2019/12/Depositphotos_86748052_l-2015.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2019/12/Depositphotos_86748052_l-2015.jpg" alt="AudioCodes Voice.AI Gateway Review"><p>My last several posts have looked at the use of voice-enabled bots – aka voicebots – for use in Interactive Voice Response (IVR) and other telephony applications. This post is a review of another voicebot telephony connectivity option - the Voice.AI Gateway from AudioCodes. If you want to connect a voicebot to a phone network, then you need an RTC-Bot Gateway. AudioCodes was one of the first VoIP gateway infrastructure vendors more than 20 years ago and the Voice.AI gateway continues this gateway tradition. Instead of connecting disparate network technologies, this time they are connecting to various AI platforms for speech processing and bot interaction.</p>
<h1 id="voiceaigatewayapproach">Voice.AI Gateway Approach</h1>
<p>The <a href="https://www.audiocodes.com/solutions-products/solutions/audiocodes-voiceai/voiceai-gateway">AudioCodes Voice.AI gateway</a> has some unique qualities compared to other RTC-bot gateway solutions on the market. You can see some of the differences in the marketing image from their <a href="https://www.audiocodes.com/solutions-products/solutions/audiocodes-voiceai/voiceai-gateway">product page</a> below:<br>
<img src="https://cogint.ai/content/images/2019/12/voiceai-gateway-diagram.png/resize?w=1200" alt="AudioCodes Voice.AI Gateway Review"></p>
<h6 id="diagramprovidedbyaudiocodescogintaiverifiedazuretexttospeechgoogletexttospeechdialogflowandawspollyinthisreview">Diagram provided by AudioCodes. cogint.ai verified Azure Text-to-Speech, Google Text-to-Speech, Dialogflow, and AWS Polly in this review.</h6>
<p>Notably, it is offered as a managed service that is designed to connect to a wide variety of existing telephony networks and interfaces with speech and bot APIs from various cloud providers.</p>
<h2 id="telephonyinfrastructure">Telephony Infrastructure</h2>
<p>AudioCodes Voice.AI Gateway is based on its Session Border Controller (SBC) product. If you haven’t dealt with VoIP infrastructure that’s probably a new term. Session Border Controllers act as traffic controllers and transformers for VoIP traffic. Prior to some of the technologies that have now become standard with WebRTC, they also helped to deal with some of the firewall and NAT traversal issues and still do for most <a href="https://en.wikipedia.org/wiki/Session_Initiation_Protocol">SIP networks</a>. They help to mediate signaling differences, even within a standard protocol like SIP, and help with media conversion where needed. Since SBCs are essentially a gateway device, it is somewhat natural to expand on the number of things that can be connected to the gateway. This is what AudioCodes has done with AI-based speech and bot services.</p>
<p>The SBC-core of the Voice.AI gateway means it has many telephony connectivity options for SIP networks and some WebRTC-based devices. It can be used to connect with older Enterprise and Contact Center SIP infrastructure in addition to modern SIP trunks for inbound and outbound calling. I am not sure if this works in conjunction with the AI capabilities, but SBC typically have excellent high availability options, with the ability to keep a call connected even in the face of a catastrophic software failure.</p>
<h2 id="managedservice">Managed Service</h2>
<p>Unlike all the other RTC-Bot gateways I have reviewed, the Voice.AI Gateway is a managed service. This means AudioCodes handles all the setup, configuration, and infrastructure maintenance. If you want to make an adjustment, you need to ask AudioCodes to do it. This could be good or bad depending on your preferences. If you aren’t sure what you are doing or don’t have the staff to maintain a gateway, AudioCodes makes things easy. However, if you are type of organization that likes to tinker and improve yourself, then you’ll have to live with interacting with another party for your project with minimal documentation and tools to see what is happening behind their blackbox.</p>
<p>AudioCodes prefers to run their managed service in Azure though they support AWS too. They say they can also deploy this in a customer’s own cloud environment, which may be required in sensitive applications where routing customer outside of the enterprise’s direct control is not allowed due to privacy concerns or regulatory requirements.</p>
<h2 id="multiplatform">Multi-platform</h2>
<p>The Voice.AI gateway connects to many difference speech and bot services. AudioCodes has stated this includes:</p>
<table style="width:100%">
<tbody>
<tr>
<th>Speech to Text providers</th><th>Text to Speech providers</th><th>Bot engines</th>
</tr>
<tr>
<td><ul>
<li>Azure</li>
<li>Google</li>
<li>Yandex</li>
</ul></td>
<td><ul>
<li>Azure</li>
<li>Google</li>
<li>Amazon</li>
<li>Yandex</li>
</ul></td>
<td><ul>
<li>Azure Bot Service</li>
    <li>Dialogflow</li></ul></td>
    </tr>
    </tbody>
    </table>
<p>Why so many services? Certainly, an existing Azure Bot Service environment would need expect support for Azure’s transcription and Text to Speech (TTS) synthesis services. The same is true for Dialogflow. The additional Text to Speech (TTS) providers can help to give a bot a more distinctive voice. Beyond that, it is also possible to mix and match STT and TTS engines. This might make the most sense to do if someone had a Dialogflow bot but wanted to use something like Azure’s Custom Voice service that lets developers design their own unique synthesized voice. I don’t expect we will see too many mixed-platform voicebots for reasons we will touch on in the review, but there are certainly scenarios where it could make sense.</p>
<h2 id="pricing">Pricing</h2>
<p>AudioCodes has 2 mutually exclusive pricing options for its Voice.AI Gateways – per minute and per concurrent-session. I describe the pricing they shared with me below.</p>
<h3 id="perminuteoption">Per-minute option</h3>
<p>The first model is priced on a per-minute basis:</p>
<table>
<thead>
<tr>
<th><strong>Minutes per Month</strong>         </th>
<th><strong>Price per Minute</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>10,000 to 500,000</td>
<td>$0.018</td>
</tr>
<tr>
<td>500,00 to 1,000,000</td>
<td>$0.015</td>
</tr>
</tbody>
</table>
<p> <br>
AudioCodes has a 10,000 minutes / mo minimum charge and a 12 month commitment which comes to $180/mo and a total commitment of $2160 for a year.</p>
<h3 id="persessionoption">Per-session option</h3>
<p>They also have a per-session option based on based on a maximum number of concurrent sessions per configuration:</p>
<table>
<thead>
<tr>
<th><strong>Sessions</strong>        </th>
<th><strong>Monthly price per session</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>5-10</td>
<td>$105</td>
</tr>
<tr>
<td>11-50</td>
<td>$89</td>
</tr>
<tr>
<td>51-100</td>
<td>$79</td>
</tr>
<tr>
<td>101-500</td>
<td>$71</td>
</tr>
</tbody>
</table>
<p> <br>
To use this option, you need to commit to at least 12 months of service at those levels with a minimum of 5 sessions a month - $525/mo for a total $6300 1-year commitment.</p>
<p>You will also need to cover the cost of transcription and speech synthesis, as well as the bot on top of this. The math to figure out the cost for a given scenario us going to vary significantly based on the voicebot and user interacton behavior. A chatty bot will incure more TTS charges. A chatty customer will incure more STT. As a lower volume usage example, let’s assume our average voicebot interaction lasts 3 minutes, 40% of which is the customer, 50% is the bot, and 10% is silence and we will handle 10,000 calls a month. Using Azure’s Speech to Text (STT) and AWS Polly for Speech to Text (STT), this comes to 3.36 cents a minute. The SIP trunk connectivity will usually run a quarter cent to a cent a minute, but that puts the Voice.AI Gateway price well below <a href="https://dialogflow.com/pricing">Dialogflow’s Phone Gateway 5 cents per minute pricing</a> for its Enterprise Essentials package.</p>
<table>
<thead>
<tr>
<th><strong>Service Charge</strong>           </th>
<th><strong>Unit Price</strong>     </th>
<th><strong>Unit</strong>          </th>
<th><strong>Units</strong>       </th>
<th style="text-align:right"><strong>Total</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>AudioCodes (Less than 500,000)  </td>
<td>$ 0.0180</td>
<td>/minute</td>
<td>30,000</td>
<td style="text-align:right">540.00</td>
</tr>
<tr>
<td>Azure Speech-to-Text, standard</td>
<td>$ 0.0167</td>
<td>/minute</td>
<td>12,000</td>
<td style="text-align:right">200.00</td>
</tr>
<tr>
<td>Dialogflow Text Charges</td>
<td>$ 0.0020</td>
<td>/minute</td>
<td>12,000</td>
<td style="text-align:right">24.00</td>
</tr>
<tr>
<td>AWS Polly TTS, neural voice</td>
<td>$ 0.0115</td>
<td>/minute</td>
<td>15,000</td>
<td style="text-align:right">172.94</td>
</tr>
<tr>
<td>---------------------------------------------</td>
<td>-------------</td>
<td>-----------</td>
<td>----------</td>
<td style="text-align:right">----------</td>
</tr>
<tr>
<td>Total</td>
<td>$ 0.0312</td>
<td>/minute</td>
<td>30,000</td>
<td style="text-align:right">$  1,006.94</td>
</tr>
</tbody>
</table>
<h1 id="productreview">Product Review</h1>
<h2 id="setupmethodology">Setup &amp; Methodology</h2>
<p>To provide a fair comparison with my other reviews, I decided to stick with the existing Dialogflow bot I used for the <a href="https://cogint.ai/voximplant-dialogflow-connector-2019/">Voximplant</a> and <a href="https://cogint.ai/signalwire-dialogflow-2/">SignalWire</a> posts. To connect to the bot, I <a href="https://dialogflow.com/docs/reference/v2-auth-setup">exported the bot’s service account JSON</a> from Google Cloud and sent it to the team at AudioCodes.</p>
<p>To show how I could control my own connectivity, I made a SIP trunk using Twilio’s Elastic SIP trunk service. AudioCodes gave me a SIP URI and I plugged this into the Original setup inside Twilio:<br>
<img src="https://cogint.ai/content/images/2019/12/2---Twilio-Originiation-URI.png" alt="AudioCodes Voice.AI Gateway Review"><br>
Then I assigned a phone number to this trunk. I shared that phone number along with Twilio’s published list of IP addresses for the AudioCodes team to whitelist. The next day they had it ready and I was able to verify the bot connected.</p>
<p>Since the Voice.AI Gateway is offered as a managed service, I don’t have much other setup or code to share beyond the few tidbits inside Dialogflow below since AudioCodes took care of everything else.</p>
<h2 id="speechtotextstt">Speech to Text (STT)</h2>
<p>The Voice.AI Gateway performs its own transcription with the chosen transcription engine before passing along that transcribed text to the bot. My final tests used Google Cloud Text-to-Speech.</p>
<p>One of my intents is “Talk to Chad” to initiate a call transfer. In my testing, I noticed with the transcription consistently would not capture my name properly. I never had this problem when Dialogflow did the transcription natively (vs. converting it to text first and sending it to Dialogflow that way was was the case here).<br>
<img src="https://cogint.ai/content/images/2019/12/3---Talk-to-God.png" alt="AudioCodes Voice.AI Gateway Review"></p>
<p>It is hard to tell if perhaps the Google STT was not performing well or not configured optimally. Dialogflow does some automatic optimizations to its own STT to help better match vocal utterances to intents with its Auto Speech Adaptation feature:<br>
<img src="https://cogint.ai/content/images/2019/12/4---Dialogflow-auto-speech-adaptation.png" alt="AudioCodes Voice.AI Gateway Review"></p>
<p>AudioCodes did say they just added an option to define words to help the transcription engine better match the input for Google’s Speech-to-Text service, like this:</p>
<pre><code>{
    &quot;sttContextPhrases&quot;: [
            &quot;Chad&quot;
        ],
    &quot;sttContextBoost&quot;: 10
}
</code></pre>
<p>They say this could be included as an input parameter as I will cover in a bit.</p>
<h2 id="texttospeechtts">Text to Speech (TTS)</h2>
<p>Since the Voice.AI gateway supports voice generation I was eager to try some different voices. I decided to go with AWS Polly’s <a href="https://d1.awsstatic.com/product-marketing/Polly/voices/features_emma_neural.be854134ed0f48f776e209d2def02b38d5e6afb7.mp3">Emma</a> for speech synthesis. Emma has an option for one of AWS’s higher-quality <em>neural</em> models. I also wanted to test synthesis in a different language variant than the bot was set to – <em>en-GB</em> in this case.</p>
<p>I verified <a href="https://en.wikipedia.org/wiki/Speech_Synthesis_Markup_Language">SSML</a> playback worked fine. Polly <a href="https://docs.aws.amazon.com/polly/latest/dg/managing-lexicons.html">Lexicons</a> for customizing pronunciation are not supported.<br>
<img src="https://cogint.ai/content/images/2019/12/5---SSML-response.png" alt="AudioCodes Voice.AI Gateway Review"></p>
<p>It would have been fun to experiment with <a href="https://speech.microsoft.com/customvoice">Azure’s Custom Voice </a>to make my own unique voice, but that was well beyond the scope of this review.</p>
<h2 id="calltransfer">Call Transfer</h2>
<p>The Voice.AI Gateway does not support Dialogflow’s Telephony Tab, but it is easy to initiate a call transfer by with a <code>TransferCall</code> string followed by the number surrounded in brackets as can be seen below.<br>
<img src="https://cogint.ai/content/images/2019/12/6--call-transfer.png" alt="AudioCodes Voice.AI Gateway Review"><br>
This actually has the advantage that you can say set it to something immediately before the transfer right from the GUI without having to do anything fancy with follow-up intents or fulfillment.</p>
<h2 id="recording">Recording</h2>
<p>The Voice.AI gateway does not record directly itself, but it does support the <a href="https://tools.ietf.org/html/rfc7866">SIPREC</a> standard for sending recordings to third party recording systems. SIPREC is a SIP-based specification that essentially forks calls and sends the media to an external recording system. This approach is very common in large enterprises and call centers who often have sophisticated recording systems for doing analysis and storage for regulatory compliance. I did not verify this feature, but it is common in SBCs so I doubt there would be any issues.</p>
<h2 id="playbackinterruption">Playback Interruption</h2>
<p>The Voice.AI gateway does have barge-in capabilities. In testing I had to tell the AudioCodes team how long I should let a prompt play by default before starting STT again, letting the user barge-in.</p>
<h2 id="events">Events</h2>
<h3 id="welcome">Welcome</h3>
<p>When a new call comes in, the Voice.AI gateway sends a <code>VOICE_AI_WELCOME</code> event. That can be used like the default <code>WELCOME</code> event or Dialogflow’s Phone Gateway <code>TELEPHONY_WELCOME</code>. This event also includes a parameter with the calling phone number that can be accessed with <code>#VOICE_AI_WELCOME.caller</code>.<br>
<img src="https://cogint.ai/content/images/2019/12/7---VOICE_AI_WELCOME-event.png" alt="AudioCodes Voice.AI Gateway Review"><br>
Looking at the <a href="https://cloud.google.com/dialogflow/docs/history?authuser=1#webhook_errors_in_stackdriver_logs">logs in Stackdriver</a>, shows the called number and SIP URL are also included as shown in the <code>textPayload</code> object below:</p>
<pre><code>textPayload: &quot;Dialogflow Request : {&quot;session&quot;:&quot;95f08c1f-42ae-40f4-9ef0-f84e7c0c351b&quot;,&quot;query_input&quot;: {
    &quot;event&quot;: { 
        &quot;name&quot;: &quot;VOICE_AI_WELCOME&quot;,
            &quot;parameters&quot;: {
            &quot;calleeHost&quot;: &quot;voiceaisbcse.westeurope.cloudapp.azure.com&quot;,
            &quot;callee&quot;: &quot;+16172076328&quot;,
            &quot;callerHost&quot;: &quot;cogintai-audiocodes.pstn.twilio.com&quot;,
            &quot;caller&quot;: &quot;+16173145968&quot;
            }
        }
     },
     &quot;timezone&quot;:&quot;America/New_York&quot;}&quot;
</code></pre>
<h3 id="dtmfdetection">DTMF Detection</h3>
<p>The Gateway will detect DTMF digit entry and send a <code>DTMF</code> event with a single DTMF digit in the <code>digits</code> parameter.</p>
<p>In the course of my discussions with AudioCodes, they mentioned they added some options to pass custom payload parameters to control various details. This includes setting the ASR engine to be continuous or to give it a timeout.</p>
<h2 id="controlparameters">Control Parameters</h2>
<p>I ran out of time to verify this and did not get any documentation, but the AudioCodes team said they added some the following parameters that can be passed with the intent:</p>
<ul>
<li><code>speechLanguage</code></li>
<li><code>voiceName</code></li>
<li><code>continuousASR</code> – True/False, to always listen for spoken input</li>
<li><code>continuousASRTimeoutInMS</code> - to control barge in</li>
</ul>
<p>These would need to be set in code as part of fulfillment or passed as a custom payload via the GUI. One can see how this would enable switching of voices, languages, and control of how and when you should let users speak over your bot’s speech output.</p>
<h1 id="synopsis">Synopsis</h1>
<p>AudioCodes support for Dialogflow matured quite a bit in the couple of months I was interacting with them off-and-on for this post. It was apparent the system was originally architected around Azure. Azure Bot Service development is much more code oriented vs. Dialogflow’s more typical GUI-centric method. Of course one can control a Dialogflow bot without the GUI, but this becomes one other thing that needs to be maintained without the benefit of the GUI's guidance and tools. That is certainly not much work at all for an experience Bot developer but does mean more work for a Dialogflow novice that wants to keep things in the GUI as much as possible.  Little things like hanging up when the call is done are still missing in the Voice.AI gateway, but I am sure will come soon.</p>
<p>Beyond that, the ability to mix platforms is nice but I wouldn’t recommend doing that if it can be avoided. Building a great voicebot is usually hard enough without having to worry about additional interaction dependencies. Perhaps there are some exceptions if a specific synthesized voice has been chosen as a corporate brand and the IVR team decides to use a different underlying bot platform or if a specific STT engine has already been tuned for one environment. A larger enterprise or call center may also have some premise-based transcription infrastructure in place they want to reuse. However, with few exceptions like Microsoft premise-based version of its bot framework, in most cases sensitive data will make its way to the cloud one way or another so it is better to organize around modern cloud best practices. Most of the time companies choose one provider – Azure, AWS, or Google and stick with them for everything. Voicebot development is certainly easier this way. Furthermore, the bots themselves are doing more to optimize for speech input to reduce latency (unless you do STT on device) and improve performance. Dialogflow and Amazon Lex bot accept direct audio input. Dialogflow includes speech output too. It seems AudioCodes is moving in the direction of using bot-platform integrated speech services for Dialogflow at least.</p>
<p>Where I see the Voice.AI gateway really shining is in more traditional call center environments. These often have a lot of premise-based equipment, perhaps with some enterprise-controlled elements in the cloud. This audience often would not have dedicated staff to manage an RTC-Bot gateway. They would prefer to pay to have a neck to wring if something breaks, so the managed service makes a lot of sense here. Similarly, recording with SIPREC is only practical if you have a SIPREC recorder already, but that is what that audience usually has already.</p>
<h2 id="scorecard">Scorecard</h2>
<p>The Voice.AI ended up being a reasonable fit against the criterion I outlined in <a href="https://cogint.ai/3-methods-for-connecting-a-phone-call-to-dialogflow/">prior posts</a>. Certainly, some of these requirements will matter more than others for your specific project.</p>
<table>
<thead>
<tr>
<th><strong>Requirement</strong></th>
<th><strong>Voice.AI Gateway support</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Call Transfer</td>
<td>Yes – simple short code method</td>
</tr>
<tr>
<td>Recording</td>
<td>Yes, but only with external SIPREC systems</td>
</tr>
<tr>
<td>Playback interruption       </td>
<td>Yes – some options to set programmatically</td>
</tr>
<tr>
<td>No activity detection</td>
<td>No</td>
</tr>
<tr>
<td>DTMF detection</td>
<td>Yes</td>
</tr>
<tr>
<td>SMS</td>
<td>No</td>
</tr>
</tbody>
</table>
<p> </p>
<p>I have some other reviews planned in the near future. Make sure to <a href="https://cogint.ai/subscribe/">subscribe</a> so you don't miss anything!</p>
<p><em><strong>EDITS</strong></em><br>
<em>14-Jan, 2020: Updated pricing per AudioCodes guidances to include volume minimums without a managed service requirement in <a href="#pricing">Pricing</a></em></p>
<hr>
<h3 id="abouttheauthor">About the Author</h3>
<p>Chad Hart is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and strategy advisory helping to advance the communications industry. In addition, recently he co-authored a study on <a href="https://krankygeek.com/research">AI in RTC</a> and helped to organize an <a href="https://krankygeek.com">event</a> / <a href="https://www.youtube.com/watch?v=P38cd3GLn74&amp;list=PL4_h-ulX5eNfaM0QM5r-PewWaY_zgLH7b">YouTube series</a> covering that topic.</p>
<hr>
<h3 id="remembertosubscribefornewpostnotificationsandfollowcogintai">Remember to <a href="https://cogint.ai/subscribe/">subscribe</a> for new post notifications and follow <a href="https://twitter.com/cogintai">@cogintai</a>.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[Building a Multi-business Voicebot IVR]]></title><description><![CDATA[How to apply a Dialogflow agent to multiple different businesses with customization. The post covers how we arrived at our architecture, how we created a templating system for providing customized fulfillment with lots of node.js fulfillment code for reference.]]></description><link>https://cogint.ai/building-a-multi-business-voicebot-ivr/</link><guid isPermaLink="false">5d40e8c404a8c82a4f530e86</guid><category><![CDATA[voicebot]]></category><category><![CDATA[dialogflow]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Wed, 31 Jul 2019 01:02:00 GMT</pubDate><media:content url="https://cogint.ai/content/images/2019/07/Depositphotos_12288583_s-2019.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2019/07/Depositphotos_12288583_s-2019.jpg" alt="Building a Multi-business Voicebot IVR"><p>In the previous 4 installments of our <a href="https://cogint.ai/building-a-voicebot-ivr-with-dialogflow/">Building a Voicebot IVR with Dialogflow</a> series, we validated we could make a decent phone-based voicebot interface for your average retail business. As we documented, setting up this system is no trivial matter. It is certainly not something a typical small business would do, so we set out on researching ways to make this technology more widely accessible. We devised a system for using Dialogflow to provide individual voicebots for different businesses using a templating approach.</p>
<p>In this post we will walk through how we arrived at our architecture, how we created a templating system for providing customized fulfillment, and we share a lot of our node.js code for reference. We’ll start by covering our <a href="#architecture">approach</a> and then dig into the <a href="#implementation">implementation</a>.</p>
<h1 id="architecture">Architecture</h1>
<h2 id="hierarchiesforhandlingmultiplebusinesses">Hierarchies for handling multiple businesses</h2>
<p>We wanted to allow a non-technical business owner to set up their own voicebot IVR in minutes. There are many different kinds of businesses with a near infinite number of things a caller could ask. To reduce the scope of possibilities, we started with a few key assumptions. First, we assumed businesses in a similar category would have similar intents - i.e. restaurants will get asked about “menus”. Second, we assumed business in a given sub-category will have very similar same intents with individual fulfillment that is basically the same except for varying parameter values - i.e. “how big is your large pizza” will vary by pizza restaurant - say “10 inch” for Joe’s Pizza” and “12 inch for Alice’s Pizza”. This means we could start with a few business categories and setup a reasonable number of generic intents for each. These intents could be grouped into templates by business or sub-business type and we could template the responses.</p>
<p>We also wanted to make sure every business has its own unique phone number. As covered in the <a href="https://cogint.ai/building-a-voicebot-ivr-with-dialogflow/">previous posts</a>, we had a system for that, so we just needed to figure how to tie that phone number to what appears to be a unique agent, applying the unique responses for each business at the right time. For that, we considered 2 options:</p>
<ol>
<li>One agent per category</li>
<li>One agent per business</li>
</ol>
<h3 id="oneagentpercategory">One agent per category</h3>
<p>Dialogflow is not really designed to handle multiple applications within the same bot, but as long as your intents are the same you can use different fulfillment to provide unique responses for each individual business. This approach would let us use one Dialogflow agent per business category - i.e pizza shop, hairdresser, dentist, etc..</p>
<p><img src="https://cogint.ai/content/images/2019/07/dialogflow-architecture---one-agent-per-category.png" alt="Building a Multi-business Voicebot IVR"><br>
Using the <a href="https://cogint.ai/adding-sms-to-your-voicebot-ivr/#usingdialogflowcontextstomanageresponsesbychannel">contexts discussed in the previous post</a> with <a href="https://cogint.ai/voximplant-dialogflow-connector-2019/">VoxImplant’s VoxEngine API’s</a>, we were able to pass the called phone number as a unique identifier for each business through to Dialogflow’s fulfillment. Our fulfillment service would then use the phone number to look up the appropriate responses for that business.</p>
<h3 id="oneagentperbusiness">One Agent per Business</h3>
<p>The other approach is to use Dialogflow more for how it was intended - one agent per bot with each having its own intents and fulfillment. In this case, we do not need to rely so heavily on fulfillment, since much of each business's individual responses could be statically stored with the intent. Fulfillment still needs to be used in some cases where a static response is not practical, but this is far less than doing it for every intent like we had to in the <em>the one agent per template</em> approach. Responses are faster when you can define them statically in the bot since you can skip the fulfillment step.</p>
<p><img src="https://cogint.ai/content/images/2019/07/dialogflow-architecture---one-agent-per-business.png" alt="Building a Multi-business Voicebot IVR"></p>
<h3 id="addingflexibilityatacost">Adding flexibility, at a cost</h3>
<p>We chose the one agent per business approach, but it wasn’t without some cost. The <em>one agent per template</em> approach works ok if you have a simple bot without much variation between businesses. However, we came up with many examples where we might want to have business-specific intents. While it is possible to use contexts to filter these on a per-business basis, this would lead to a bloated bot with many intents. The Dialogflow GUI is set up for the one agent per business model, so using that allows for easy tweaking without always having to involve communicating with a database in our back-end.</p>
<table style="border: none; border-collapse: collapse;">
<tbody>
<tr style="height: 0pt;">
<td style="vertical-align: top; padding: 5pt 5pt 5pt 5pt; border: solid #000000 1pt;">
<p style="line-height: 1.2; margin-top: 0pt; margin-bottom: 0pt;"><strong><span>Approach</span></strong></p>
</td>
<td style="vertical-align: top; padding: 5pt 5pt 5pt 5pt; border: solid #000000 1pt;">
<p style="line-height: 1.2; margin-top: 0pt; margin-bottom: 0pt;"><strong><span>Advantages</span></strong></p>
</td>
<td style="vertical-align: top; padding: 5pt 5pt 5pt 5pt; border: solid #000000 1pt;">
<p style="line-height: 1.2; margin-top: 0pt; margin-bottom: 0pt;"><strong><span>Disadvantages</span></strong></p>
</td>
</tr>
<tr style="height: 0pt;">
<td style="vertical-align: top; padding: 5pt 5pt 5pt 5pt; border: solid #000000 1pt;">
<p style="line-height: 1.2; margin-top: 0pt; margin-bottom: 0pt;"><span>One Agent per App</span></p>
</td>
<td style="vertical-align: top; padding: 5pt 5pt 5pt 5pt; border: solid #000000 1pt;">
<ul style="margin-top: 0pt; margin-bottom: 0pt;">
<li><span>Simpler architecture</span></li>
<li><span>Standardized agents are easier to debug and update globally</span></li>
</ul>
</td>
<td style="vertical-align: top; padding: 5pt 5pt 5pt 5pt; border: solid #000000 1pt;">
<ul>
<li><span>Does not scale well</span></li>
<li><span>Difficult to customize agents</span></li>
<li><span>Dialogflow GUI not designed for this</span></li>
</ul>
</td>
</tr>
<tr style="height: 0pt;">
<td style="vertical-align: top; padding: 5pt 5pt 5pt 5pt; border: solid #000000 1pt;">
<p>One Agent per Business</p>
</td>
<td style="vertical-align: top; padding: 5pt 5pt 5pt 5pt; border: solid #000000 1pt;">
<ul style="margin-top: 0pt; margin-bottom: 0pt;">
<li><span>Fast responses since fulfillment is not always needed</span></li>
<li><span>Customizable intents</span></li>
<li><span>Easier to debug</span></li>
</ul>
</td>
<td style="vertical-align: top; padding: 5pt 5pt 5pt 5pt; border: solid #000000 1pt;">
<ul>
    <li><span><strike>Can't create agents programmatically</strike></span></li>
<li><span>Added layer of creating agents from templates</span></li>
<li><span>Costly to handle agent API keys</span></li>
</ul>
</td>
</tr>
</tbody>
</table>
<h2 id="programmaticallycreatingagents">Programmatically creating agents</h2>
<p>Since we chose to use one agent per business, we wanted a way to programmatically create the agent from a template. This was not possible when we originally started putting together this summary. It was only possible to create an agent manually through the Dialogflow web console. Our solution was just to manually create a bunch of Dialogflow agents and keep track of them as <code>available</code> or <code>not available</code> in our database.</p>
<p>Whenever you create a new Agent, a new project is created in the Google Cloud (GCP) account you used to authenticate against Dialogflow. Google forces you to create one project per agent, so there is no sharing of keys. This forced us to create extra logic to track the Dialogflow API keys for each agent. Manually copying over this key information was not pleasant 🙁.</p>
<p>Of course, <a href="https://cloud.google.com/dialogflow/docs/release-notes">Google added an API</a> to create an agent right after we finished our research. We did not try this, but it would appear to address much of the bot creation pains mentioned above.</p>
<h1 id="implementation">Implementation</h1>
<h2 id="staticvsdynamicresponses">Static vs. dynamic responses</h2>
<p>Imagine you are a business owner. If someone asks:</p>
<blockquote>
<p>When are you open?</p>
</blockquote>
<p>Without context, you could respond with an all-encompassing response like:</p>
<blockquote>
<p>“We are open from 5 PM to midnight,  Monday  to Thursday. On Friday and Saturday we open at 10 am and close at 2 am. On Sunday we are open from 10 am to midnight”</p>
</blockquote>
<p>This is actually easy to fit into a static response, built into the intent. However, if someone asks something more specific like:</p>
<blockquote>
<p>How late are you open tomorrow night?</p>
</blockquote>
<p>You could respond with the long phrase above, but that’s a long response with way more information than was requested - not a great experience. Assuming it was Saturday, it would be better to respond with just:</p>
<blockquote>
<p>tomorrow we are open to midnight</p>
</blockquote>
<p>In this case we can’t just use a static intent without sounding robotic. Fulfilment is needed here to:</p>
<ol>
<li>Figure out what day it was an add 1 to it for “tomorrow”</li>
<li>Look up the hours and return the appropriate response</li>
</ol>
<p>It is easy to get carried away by getting more specific, so we sought to find a balance between intents that were too broad and too specific. In this example, we could simplify the intent to cover any questions about “hours for tomorrow”, we could probably get away with broadening that to:</p>
<blockquote>
<p>On Sunday we are open from 10 am to midnight</p>
</blockquote>
<p>Using a methodology like this we mapped intents to a set of fixed and dynamic responses. The next step was to stick this all in a database that could be used for our agent templates (for static responses) and fulfillment (for dynamic ones).</p>
<h2 id="datamodel">Data Model</h2>
<p>This is just an example that shows our journey in this topic. We used <a href="https://nodejs.org">node.js</a> with <a href="https://www.mongodb.com/">MongoDB</a> using <a href="https://mongoosejs.com/">mongoose</a>, <a href="https://lodash.com/">lodash</a> and <a href="https://expressjs.com/">Express</a> but you could use any similar stack you prefer. Note intermediate to advanced node skills are assumed for most of the rest of this post and we will skip a lot of detail to keep focus on the Dialoflow specifics. You can see the full code in our <a href="https://github.com/emilianop11/voicebot-modules">repo</a>.</p>
<h3 id="businessinformation">Business Information</h3>
<p>Before we start digging into some code, lets review the restaurant data models we setup. Let’s start with our <em>restaurant</em> model that keeps track of all the business specific details. Below is the database entry:<br>
<img src="https://cogint.ai/content/images/2019/07/database---business-information.png" alt="Building a Multi-business Voicebot IVR"><br>
This is also gives you an idea of our data structure. Pay special attention to the <code>agent</code> and <code>openHours</code> fields, we will be using those moving forward: <code>openHours</code> will be used as an example on how to respond back to Dialogflow’s fulfilment request. <code>agent</code> tells us the Dialogflow agent that is tied to this business.</p>
<h3 id="dialogflowagenttracking">Dialogflow agent tracking</h3>
<p>This is an <code>agent</code> entry example:<br>
<img src="https://cogint.ai/content/images/2019/07/database---dialogflow-agent-tracking.png" alt="Building a Multi-business Voicebot IVR"></p>
<p>You can see here how we keep track of the agent credentials so we can individually update them (you should have them in a separate config file but we are trying to show everything as straightforward as possible), the project name, and if the agent is already assigned to a business or not. When a new user finishes filling the data for their business, you just need to go through this collection checking for which agents are available, mark them as <code>available</code> = <code>false</code> and assign them to the corresponding restaurant document for the user (<code>agent</code> field on the restaurant model).</p>
<h3 id="agenttemplate">Agent template</h3>
<p>The last database entry we would like to show is what we called <code>agent template</code>. This document keeps the format of each answer we need to create in order to reply back to a fulfillment request. Let’s just focus on <code>hoursOfOperation</code> as we mentioned above:<br>
<img src="https://cogint.ai/content/images/2019/07/hours-of-operation-agent-template.png" alt="Building a Multi-business Voicebot IVR"></p>
<p>Ok, now that you have a rough idea of the contents of the DB, let's get to the the Dialogflow setup and fulfillment code.</p>
<h2 id="dialogflowsetup">Dialogflow Setup</h2>
<p>First you need to get into Dialogflow and <a href="https://cogint.ai/dialogflow-phone-bot/#getanaccountcreateanagent">create an agent</a>.</p>
<h3 id="makeyourintent">Make your Intent</h3>
<p>After that we will include a sample intent for an intent named <code>Hours Of Operation</code>.<br>
<img src="https://cogint.ai/content/images/2019/07/dialogflow-hours-of-operation-intent.png" alt="Building a Multi-business Voicebot IVR"></p>
<p>Make sure you properly set the entity type you will be getting out of each question in the <em>Action and parameters</em> section.</p>
<p>As shown above in the agent template model, each intent property has a nested structure. At the first child level you will see <code>date</code> and <code>date-time</code>. This corresponds to the parameter we get in the Dialogflow fulfillment request body according to how the user asked the question.</p>
<h3 id="intentjsonresponses">Intent JSON responses</h3>
<p>Our code needs to understand what exactly does “now” or “tomorrow” mean. If you set the parameters above Dialogflow should automatically extract values for these. The JSON below shows how Dialogflow flow codes “Are you open now?” into tangible information we can use to compute the answer:</p>
<pre><code class="language-javascript">{  
   &quot;responseId&quot;:&quot;9eb99604-0303-4d64-b757-8d4d125e11ce-2dd8e723&quot;,
   &quot;queryResult&quot;:{  
      &quot;queryText&quot;:&quot;are you open now?&quot;,
      &quot;parameters&quot;:{  
         &quot;date-time&quot;:{  
            &quot;date_time&quot;:&quot;2019-06-09T23:42:17-03:00&quot;
         },
         &quot;date&quot;:&quot;&quot;
      },
      &quot;allRequiredParamsPresent&quot;:true,
      &quot;intent&quot;:{  
         &quot;name&quot;:&quot;projects/my-demo-agent/agent/intents/30fe78ed-9d2d-4156-acfb-10c174db0417&quot;,
         &quot;displayName&quot;:&quot;Hours of operation&quot;
      }
   },
   &quot;session&quot;:&quot;projects/my-demo-agent/agent/sessions/f2698a2d-c8ca-1029-9dc0-c6a41a3a5352&quot;
}

</code></pre>
<p>Here we got a <code>date-time</code> parameter. If the question was “are you open tomorrow” we get a <code>date</code> parameter instead since no specific hour is provided:</p>
<pre><code class="language-javascript">{  
   &quot;responseId&quot;:&quot;2a1e9fdd-e5f4-4597-be68-73b7e16b1d29-2dd8e723&quot;,
   &quot;queryResult&quot;:{  
      &quot;queryText&quot;:&quot;are you open tomorrow?&quot;,
      &quot;parameters&quot;:{  
         &quot;date&quot;:&quot;2019-06-10T12:00:00-03:00&quot;,
         &quot;date-time&quot;:&quot;&quot;
      },
      &quot;allRequiredParamsPresent&quot;:true,
  }
}
</code></pre>
<h3 id="fulfillment">Fulfillment</h3>
<p>Lets see how we can set up an application that can provide an answer to each of these requests using the data we gathered from our customer. First of all, make sure you set up your intent to use fulfillment. As you can see from this image we are tunneling our application using <em>ngrok</em>*, so Dialogflow can hit our HTTP server:<br>
<img src="https://cogint.ai/content/images/2019/07/dialogflow-fulfillment-webhook.png" alt="Building a Multi-business Voicebot IVR"><br>
*<em>If you never heard about <a href="https://ngrok.com">ngrok</a>, it's a great tool for making your local web servers accessible over the Internet that you will definitely love.</em></p>
<h2 id="fulfillmentcode">Fulfillment code</h2>
<p>For our example, let’s try to make our bot answer the question:</p>
<blockquote>
<p>Are you open tomorrow?</p>
</blockquote>
<p>This is the piece of code that will handle the incoming request from Dialogflow.<br>
Then, at a high level we just build our answer and reply back.</p>
<pre><code class="language-javascript">const {WebhookClient} = require('dialogflow-fulfillment');

app.post('/fulfillment', (req, res) =&gt; {
  const agent = new WebhookClient({ request: req, response: res });

  buildIntentAnswer(agent)
  	.then(respondToFulfilment(agent));
});
</code></pre>
<pre><code class="language-javascript">const buildIntentAnswer = data =&gt; getFormattedData(data).then(getAnswer);

const respondToFulfilment = _.curry((agent, response) =&gt; {
	let intentMap = new Map();
  	intentMap.set(agent.intent, (agent) =&gt; agent.add(response));
  	return agent.handleRequest(intentMap);
});
</code></pre>
<p>If you want to know more about the <code>WebhookClient</code> and <code>handleRequest</code> functions, I strongly suggest you to check out <a href="https://dialogflow.com/docs/reference/fulfillment-library/webhook-client">Dialogflow’s</a><a href="https://dialogflow.com/docs/reference/fulfillment-library/webhook-client"> docs on those</a>.</p>
<p>The most important function of this chain is <code>buildIntentAnswer</code> which we will cover deeply up next.</p>
<h3 id="getformatteddatagatheringrestaurantinformation">getFormattedData - gathering restaurant information</h3>
<p>To get an answer for our question, the first thing we need to do is to gather some relevant business information. We need to know if the restaurant is actually open or closed at the moment the user asked. In order to do that, we need to query our database and find the restaurant hours of operation.</p>
<pre><code class="language-javascript">const getProjectName = data =&gt; data.session.split('/')[1];

const getFormattedData = (data) =&gt; {
	const agent = getProjectName(data);
	const agentType = 'restaurant';

	return new Promise((resolve, reject) =&gt; {
		getRelevantBusinessInformation(agent, agentType, data.intent).then((businessInfoForIntent) =&gt; {
			const fData = hoursOfOperation.getFormattedData(data, businessInfoForIntent);
			fData.agent = getProjectName(data);
			fData.agentType = agentType;
			resolve(fData);
		});
	});
}

const getRelevantBusinessInformation = (agent, agentType, intentName) =&gt; {
	return new Promise((resolve, reject) =&gt; {
		Agent.findOne({'name': agent}).then((agent) =&gt; {
			models[agentType].findOne({agent: agent._id}).then((restaurant) =&gt; {
				if (intentName === 'Hours of operation')
					return resolve(restaurant.operation.openHours.toObject());
				else
					throw new Error('Intent not yet supported');

			});
		});
	});
}
</code></pre>
<p><code>getFormattedData</code> cares about obtaining that business information and shaping it in a way we can use to compute our answer.</p>
<p><code>getRelevantBusinessInformation</code> matches the agent in use (we got the name in the incoming request object), with the particular restaurant that is assigned to it. Once we have a matching restaurant it just returns the relevant information for our intent, in this case <code>openHours</code>.</p>
<p>Once we got the <code>openHours</code> object, we need to use that information to create meaningful string values that will be used in the answer. A tangible example is that you need to translate the openingHour time from <code>12</code> in the database to  “twelve o ‘ clock” (<code>hourToText</code> function).</p>
<p>For that, we include an <code>hoursOfOperation</code> intent module, which encapsulates all of this logic. Think that each intent will need a complete different set of rules. These individual per-intent modules serve that purpose.</p>
<h5 id="hoursofoperationjs">hoursOfOperation.js</h5>
<pre><code class="language-javascript">const DAYS_OF_THE_WEEK = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
const converter = require('number-to-words');

hourToText = (hour) =&gt; {
	const strHour = hour.toString();
	const lastTwo = strHour.slice(-2);
	const remaining = strHour.substring(0, strHour.length - 2);
	const txtMins = lastTwo === '00' ? 'o clock' : converter.toWords(lastTwo);
	const txthours = converter.toWords(remaining);
	return `${txthours} ${txtMins}`
};

const dateHandler = (data, operationData) =&gt; {
	let date = data.parameters.date;
	date = new Date(date);
	const day = DAYS_OF_THE_WEEK[date.getDay()];
	const dayInfo = operationData[day];
	dayInfo.day = day;
	
	return {
		intent: data.intent,
		businessData: dayInfo,
		processedParams: {
			type: 'date',
			day
		},
		txtVars: {
			day,
			openHour: hourToText(dayInfo.openHour),
			closeHour: hourToText(dayInfo.closeHour)
		}
	};
}

const getHandler = (paramType) =&gt; {
	const mapping = {
		'date': dateHandler,
		'date-time': dateTimeHandler,
		'time': timeHandler
	};
	return mapping[paramType] ? mapping[paramType] : defaultHandler;
}

function getRelevantParam(params) {
	for (let param in params) {
		if (params[param]) return param;
	}
	throw new Error('No relevant param found');
}

exports.getFormattedData = (data, operationData) =&gt; {
	const handler = getHandler(getRelevantParam(data.parameters));
	return handler(data, operationData);
};

exports.getState = (data) =&gt; {
	if (data.processedParams.type === 'date-time') {
		if (!data.businessData.open) return 'closed';

		const openHour = data.businessData.openHour;
		const closeHour = data.businessData.closeHour;
		const hour = data.processedParams.hour;

		//The restaurant closes before the day ends
		if (openHour &lt; closeHour) {
			if (hour &gt; openHour &amp;&amp; hour &lt; closeHour) return 'open';
			else return 'closed';
		} else { //The restaurant closes the day after
			if (hour &gt; openHour) return 'open';
			else return 'closed'
		}
	}

	if (data.processedParams.type === 'date') {
		return data.businessData.open ? 'open' : 'closed';
	}
};
</code></pre>
<h3 id="getanswerbuildingtheanswer">getAnswer - building the answer</h3>
<p>We just finished gathering all the information we need, now we need to build the answer. We need the actual explicit sentence we want to play over the phone. We will make use of <code>getState</code> in our <code>hoursOfOperation</code> module, which will let us know if our restaurant is open or closed, comparing the information provided in the question and the actual restaurant opening hours. Note that this module contains logic to handle different types of parameters. We just included a <code>dateHandler</code> in this example, but you may need one for each type of parameter you could potentially get.</p>
<pre><code>const getAnswer = (relevantData) =&gt; {
	return new Promise((resolve, reject) =&gt; {
		const answerVariant = computeAnswerVariant(relevantData);
		AgentTemplate.findOne({type: relevantData.agentType}).then((template) =&gt; {
			const possibleAnswers = template.getAnswers(relevantData.intent, answerVariant, relevantData.txtVars);
			const answer = _.sample(possibleAnswers);
			return resolve(answer);
		});
	});
}


const computeAnswerVariant = (data) =&gt; {
	return {
		state: hoursOfOperation.getState(data),
		paramType: data.processedParams.type
	};	
}
</code></pre>
<p>The template model gets all possible answers (if we don't want to repeat the same sentence over and over again we provide different variations of the same answer). Lodash's <code>_.sample</code> method simply picks a random one of the array of answers.</p>
<p>This is a piece of the <code>AgentTemplate</code> mongoose schema that produces the text sentences:</p>
<pre><code class="language-javascript">const getTemplatePropertyFromIntentName = (intentName) =&gt; {
  const mapping = {
    'Hours of operation': 'HoursOfOperation',
    'Location': 'Location'
  };

  return mapping[intentName];
}

agentTemplateSchema.methods.getAnswers = (intentName, answerVariant, params) =&gt; {
  const replaceVars = (text, params) =&gt; {
    for (let prop in params) text = text.replace(`{{${prop}}}`, params[prop]);
    return text;
  }

  const templateProp = getTemplatePropertyFromIntentName(intentName);

  let answers;

  try {
    answers = this.intents[templateProp][answerVariant.paramType][answerVariant.state];
  } catch(e) {
    answers = this.intents[templateProp][answerVariant];
  }
  
  return answers.map(ans =&gt; replaceVars(ans, params));
};

const AgentTemplate = mongoose.model('AgentTemplate', agentTemplateSchema);

module.exports = AgentTemplate;
</code></pre>
<p>As you can see, <code>getAnswers</code> method in the model just accesses the proper child in the document (<code>date</code> in this case) and then, replaces all the values surrounded by curly braces with the proper value.</p>
<p>That covers our brief code review. We encourage you to clone <a href="https://github.com/emilianop11/voicebot-modules.git">the repo</a> and run it locally to see it working.</p>
<h2 id="everythingthathasabeginninghasanend">Everything that has a beginning has an end</h2>
<p>This is the last post in our <a href="https://cogint.ai/building-a-voicebot-ivr-with-dialogflow/">Building a Voicebot IVR with Dialogflow</a> series. Our plan to summarize our research in a single post early in May morphed into a series covering methods for <a href="https://cogint.ai/3-methods-for-connecting-a-phone-call-to-dialogflow/">adding phone connectivity to Dialogflow</a>, reviews of the Dialogflow connectors provided by <a href="https://cogint.ai/signalwire-dialogflow-2/">SignalWire</a> and <a href="https://cogint.ai/voximplant-dialogflow-connector-2019">VoxImplant</a>, how to <a href="https://cogint.ai/adding-sms-to-your-voicebot-ivr/">add SMS to your IVR</a> and this last one showing how we pulled it all together.  Next week Chad will be giving a presentation summarizing this series during his <em>Kill Your IVR with a Voicebot</em> talk at <a href="https://www.cluecon.com/">ClueCon</a> in Chicago on August 6th.</p>
<p>Now it’s your turn! We are always happy to share notes on projects and talk about our work. Make sure to leave some comments below so we can connect.</p>
<hr>
<h3 id="abouttheauthors">About the Authors</h3>
<p><em>Chad Hart</em> is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and strategy advisory helping to advance the communications industry. In addition, he recently co-authored a study on <a href="https://krankygeek.com/research">AI in RTC</a> and helped to organize an <a href="https://krankygeek.com">event</a> / <a href="https://www.youtube.com/watch?v=P38cd3GLn74&amp;list=PL4_h-ulX5eNfaM0QM5r-PewWaY_zgLH7b">YouTube series</a> covering that topic.</p>
<p><em>Emiliano Pelliccioni</em> is a computer engineer working at webRTC.ventures and specializes in developing real time communication applications for clients around the globe. One of his projects includes developing bot integrations for a major CPaaS provider.</p>
<hr>
<h3 id="remembertosubscribefornewpostnotificationsandfollowcogintai">Remember to <a href="https://cogint.ai/subscribe/">subscribe</a> for new post notifications and follow <a href="https://twitter.com/cogintai">@cogintai</a>.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[Adding SMS to your Voicebot IVR]]></title><description><![CDATA[How to combine telephony voice and SMS inside the same Dialogflow bot to make a multi-channel, intelligent IVR. Discussion of the use case, voicebot gateway architecture, and using contexts as filters.]]></description><link>https://cogint.ai/adding-sms-to-your-voicebot-ivr/</link><guid isPermaLink="false">5d366e9e04a8c82a4f530e6e</guid><category><![CDATA[voicebot]]></category><category><![CDATA[dialogflow]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Tue, 23 Jul 2019 10:27:11 GMT</pubDate><media:content url="https://cogint.ai/content/images/2019/07/AdobeStock_239766332-smaller.jpeg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2019/07/AdobeStock_239766332-smaller.jpeg" alt="Adding SMS to your Voicebot IVR"><p>Earlier in this <a href="https://cogint.ai/building-a-voicebot-ivr-with-dialogflow/">series on using Dialogflow as an Interactive Voice Response (IVR) replacement</a>, we established SMS interaction is a nice to have feature. Users are used to texting and often times it is a better experience to just send the user a link. One might think that handling SMS with Dialogflow is simple, and it is, but many complexities come into play when you try to blend voice and SMS in the same bot.  In this post we will show our findings on ways to implement this feature.</p>
<p>We will describe the use case some more, walk through the architecture we landed on for handling SMS and voice from the same phone number, and discuss using Dialogflow’s Contexts as a filter to select channels.</p>
<h2 id="usecasewhysmsandvoiceatthesametime">Use case: why SMS and Voice at the same time</h2>
<p>We used a restaurant as a reference business for our prototype. Imagine a caller on the move, looking for something to eat. They find the restaurant and want to know what kind of food they have. Maybe they do a web search and can’t find the menu, or maybe they just call in the first place - either because they have other questions or because they are not in a position to stare at a several inch piece of glass to see this info at the moment they were interested.</p>
<p>They first thing they ask is, “what is your menu?” Here the voicebot IVR could read off the menu, but that would take forever assuming there are more than a handful of menu options. The bot could also structure the menu into categories - say appetizers, salads, main courses, etc. and let the caller select just the category, but that leads you back into a traditional IVR where you need to deal with navigating hierarchies. In a lot of cases it is just easier to ask the user if they would like a link to the menu they can read themselves at their leisure.</p>
<p>So the IVR could read off the menu URL. However, reading off a URL like <a href="https://myrandomlocalrestaurant.com/summermenu">https://myrandomlocalrestaurant.com/summermenu</a> on a call is never a great experience. After listening to what is often a long, un-punctuated string, the user needs to either remember the URL or write it down - which they may not be in a good position to do if their phone is held up to their ear. At some point they still need to enter the URL into a browser, hopefully without making a mistake. There are a lot of ways this interaction could go wrong, leading to a lost opportunity for the restaurant.</p>
<p>Wouldn’t it just be easier to send the caller something they can click on in the first place? In most cases the caller is calling from a mobile device that is SMS capable. You should be able to get their phone number from the incoming caller ID. Why not just send them the link via SMS?</p>
<p>Then, once you send them an SMS link, you could continue to engage the customer on that channel. This has the advantage of providing a second, asynchronous channel for on-going communication with the customer.</p>
<p>Now that we have established why a business would want to have a multi-channel bot that can handle both voice and SMS, next let’s look at how to implement that.</p>
<h2 id="architecturetelephonysmsindialogflow">Architecture: Telephony + SMS in Dialogflow</h2>
<p>What we really want from a Dialogflow developer perspective is something that looks like this:<br>
<img src="https://cogint.ai/content/images/2019/07/ideal-voice-SMS-bot-gateway.png" alt="Adding SMS to your Voicebot IVR"></p>
<h6 id="thisisthegatewayscenariowewerelookingforcouldntfindandhadtocreate">This is the gateway scenario we were looking for, couldn’t find, and had to create</h6>
<p>The gateway would handle the incoming interactions, tell if it was from the phone or SMS, and just send that on to Dialogflow.</p>
<p>If that ideal gateway were available <a href="https://cogint.ai/building-a-voicebot-ivr-with-dialogflow/">this blog series</a> probably wouldn’t exist. As we discussed earlier in the series, you can use <a href="https://cogint.ai/signalwire-dialogflow-2/#hackforsmssupport">Twilio or Signalwire to make a good SMS bot</a> but neither of those platforms fit our <a href="https://cogint.ai/3-methods-for-connecting-a-phone-call-to-dialogflow/#whatelseshouldthedialogflowgatewayhandle">gateway requirements</a> like <a href="https://cogint.ai/voximplant-dialogflow-connector-2019">VoxImplant</a>. So we could do something more like this where we effectively have a different gateway for each channel:<br>
<img src="https://cogint.ai/content/images/2019/07/dual-channel-voice-SMS-bot-gateway.png" alt="Adding SMS to your Voicebot IVR"></p>
<h6 id="wesplitthegatewayinto2channelsoneforsmsandoneforvoice">We split the Gateway into 2 channels - one for SMS and one for Voice</h6>
<p>A user could call in to the Telephony-CPaaS and when needed, you could have your bot controller app signal the SMS-CPaaS to send the message and continue as a SMS-bot as needed from there.</p>
<p>The problem with this approach is that each channel has its own phone number. This might be ok in some scenarios, but in most cases you want to minimize confusion for the customer and stick to a single number. If you want a single number then you need to have some kind of additional proxy - or just forward calls/messages from one CPaaS to the other.<br>
<img src="https://cogint.ai/content/images/2019/07/single-number-voice-sms-voicebot-gateway.png" alt="Adding SMS to your Voicebot IVR"></p>
<h6 id="toreusethesamephonenumberweendedupusingsignalwirecpaas1andforwardingvoicecallstovoximplantcpaas2">To reuse the same phone number, we ended up using SignalWire (CPaaS 1) and forwarding voice calls to VoxImplant (CPaaS 2).</h6>
<p>We had some SignalWire logic from another unrelated project for phone number selection that we wanted to reuse so we ended up using SignalWire numbers and forwarding calls to VoxImplant via SIP.  This setup involves a few clicks to enable inbound SIP inside VoxImplant and a 6-line script inside SignalWire:</p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;Response&gt;
    &lt;Dial record=&quot;record-from-answer-dual&quot;&gt;
        &lt;Sip&gt;sip:{{To}}@dialogflow-7sqrp2g.cogintai.voximplant.com&lt;/Sip&gt;
    &lt;/Dial&gt;
&lt;/Response&gt;
</code></pre>
<h6 id="signalwirelamlscriptusedtoforwardanincomingcalltovoximplantviasipthisalsorecordsthecall">SignalWire LAML script used to forward an incoming call to VoxImplant via SIP. This also records the call.</h6>
<h2 id="usingdialogflowcontextstomanageresponsesbychannel">Using Dialogflow contexts to manage responses by channel</h2>
<p>The next challenge we faced was dilenating between incoming telephony and SMS messages at the bot.</p>
<h3 id="differentintentresponsesfordifferentchannels">Different Intent responses for different channels</h3>
<p>If the bot was very simple, you might be able to reuse the exact same intent responses across voice and text channels. We found for many intents, it gives a better experience to differentiate the responses by channel. For example, if the user asks:</p>
<blockquote>
<p>how can I find you”</p>
</blockquote>
<p>The voicebot can respond with a verbal description:</p>
<blockquote>
<p>We are located at 4 Thompsons Point, building number 106 in Portland Maine just of the Fore River Parkway, Exit 5 or 5A on Route 295. Just a five-minute walk from the Portland Transportation Center, serviced by Amtrak and Concord Bus.</p>
</blockquote>
<p>While it makes more sense to just send an SMS user a map link they can use to navigate themselves:</p>
<blockquote>
<p>We are at 4 Thompsons Point #106, Portland, ME 04102. Here is a link to our address for driving or public transportation: <a href="https://goo.gl/maps/2Zc7hc6QdiSfHrjV7">https://goo.gl/maps/2Zc7hc6QdiSfHrjV7</a></p>
</blockquote>
<h3 id="contextsasintentfilters">Contexts as Intent filters</h3>
<p>Contexts let you store stateful information across intents during a user's bot interaction. In Dialogflow, you can <a href="https://cloud.google.com/dialogflow/docs/contexts-overview">set a context</a> at any time. Contexts can also store data, but in our case we many just needed the context as a filter.</p>
<p>As discussed in the <a href="https://cogint.ai/voximplant-dialogflow-connector-2019/">VoxImplant 2019 review</a>, we chose VoxImplant because they allow you to set contexts as part of their runtime scripting:</p>
<pre><code>phoneContext = {
  name: &quot;phone&quot;,
  lifespanCount: 99,
  parameters: {
    caller_id: call.callerid(),
    called_number: call.number()
  }
}

dialogflow.setQueryParameters({contexts: [phoneContext]})
</code></pre>
<p>We use the code above to tell our Dialogflow bot that the incoming call is a phone call. Then we simply duplicated the relevant intents and added a phone contexts to the duplicates:<br>
<img src="https://cogint.ai/content/images/2019/07/intent-with-context.png" alt="Adding SMS to your Voicebot IVR"></p>
<h3 id="permissions">Permissions</h3>
<p>How do you know if the user is on mobile and can receive an SMS? There are a number of different phone number lookup services where you can send the user’s caller ID and it will give you a good idea if it a mobile. However, due to number porting these are not 100% reliable (at least in the US where any number is technically SMS capable). We also decided it might make sense to ask the user for permission while verifying the can recieve texts. As a result, we ended up assigning 4 different context levels:</p>
<ol>
<li><em>Phone</em> - starting default for incoming telephone calls</li>
<li><em>SMS_capable</em> - for telephony callers we think are on a mobile phone, but we haven’t confirmed</li>
<li><em>SMS_authorized</em> - telephony callers that gave explicit confirmation they can receive text messages on their caller ID (or they gave another number)</li>
<li>No context - used for SMS interactions and as default</li>
</ol>
<p>Follow-up intents can be used to move a user from <em>SMS_capable</em> to <em>SMS_authorized</em>. We used fulfillment to actually send the text message.</p>
<h3 id="thiscangetmessy">This can get messy</h3>
<p>Duplicating intents with several different contexts like this does clutter the Dialogflow GUI. If we just had two levels perhaps we could have reused the <a href="https://cogint.ai/3-methods-for-connecting-a-phone-call-to-dialogflow/#method1usethedialogflowphonegateway">Telephony Tab</a> to manage a different set of responses within a single intent; we had 4 and there is no way to make custom tabs today. Unfortunately there is not really an alternative to this other than not using the GUI and programming everything via API - a topic we will cover later in this series.</p>
<h2 id="whatsnext">What’s Next</h2>
<p>We are getting close to the end of our series. Next we will explore some of the difficulties in reusing a Dialogflow bot across multiple unique businesses. Also, <a href="https://cogint.ai/author/chad/">Chad</a> will be discussing many of these findings during his <em>Kill Your IVR with a Voicebot</em> talk at <a href="https://www.cluecon.com/">ClueCon</a> in Chicago on August 6th. Make sure to <a href="https://cogint.ai/subscribe/">subscribe</a> so you don’t miss our posts and leave your comments below.</p>
<hr>
<h3 id="abouttheauthors">About the Authors</h3>
<p><em>Chad Hart</em> is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and strategy advisory helping to advance the communications industry. In addition, recently he co-authored a study on <a href="https://krankygeek.com/research">AI in RTC</a> and helped to organize an <a href="https://krankygeek.com">event</a> / <a href="https://www.youtube.com/watch?v=P38cd3GLn74&amp;list=PL4_h-ulX5eNfaM0QM5r-PewWaY_zgLH7b">YouTube series</a> covering that topic.</p>
<p><em>Emiliano Pelliccioni</em> is a computer engineer working at webRTC.ventures and specializes in developing real time communication applications for clients around the globe. One of his projects includes developing bot integrations for a major CPaaS provider.</p>
<hr>
<h3 id="remembertosubscribefornewpostnotificationsandfollowcogintai">Remember to <a href="https://cogint.ai/subscribe/">subscribe</a> for new post notifications and follow <a href="https://twitter.com/cogintai">@cogintai</a>.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[Voximplant's Dialogflow Connector: 2019 Review]]></title><description><![CDATA[A deep look at VoxImplant's Dialogflow Connector with some sample code showing how to use it to build an IVR replacement]]></description><link>https://cogint.ai/voximplant-dialogflow-connector-2019/</link><guid isPermaLink="false">5d1187ed04a8c82a4f530e5b</guid><category><![CDATA[review]]></category><category><![CDATA[voicebot]]></category><category><![CDATA[dialogflow]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Tue, 25 Jun 2019 10:38:00 GMT</pubDate><media:content url="https://cogint.ai/content/images/2019/07/Depositphotos_12288222_xl-2015-small.jpeg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2019/07/Depositphotos_12288222_xl-2015-small.jpeg" alt="Voximplant's Dialogflow Connector: 2019 Review"><p>In this third installment of our <a href="https://cogint.ai/building-a-voicebot-ivr-with-dialogflow">Building a Voicebot IVR with Dialogflow</a> series, we take a look at Voximplant’s Dialogflow Connector. Voximplant was the first CPaaS vendor to have a direct telephony integration with Dialogflow. Alexey Aylarov gave an introduction how they build this gateway <a href="https://cogint.ai/making-ivrs-not-suck-with-dialogflow-alexey-aylarov/">here</a> soon after it was first released. <a href="https://cogint.ai/author/emiliano/">Emiliano</a> and I ended up using Voximpant’s Dialogflow Connector for our project, so we will go much deeper into how Voximplant matched up to our requirements and provide some code samples in this post.</p>
<p><img src="https://cogint.ai/content/images/2019/06/VoxImplant-Dialogflow-Connector-architecture.png" alt="Voximplant's Dialogflow Connector: 2019 Review"></p>
<h1 id="voxengineapproach">VoxEngine Approach</h1>
<h2 id="serverlessexecution">Serverless Execution</h2>
<p>Unlike the XML-script based approach used by many platforms, Voximplant has a JavaScript-based execution environment it calls VoxEngine. While not terribly complex, it does require some JavaScript skills if you want to do more than copy and paste example code you may find. This all runs <a href="https://en.wikipedia.org/wiki/Serverless_computing">serverless</a> so you don’t have do setup your own development environment and worry about servers. It is quick to get going if you just need to manage a few lines of code. The downside is you need to get used to their web-based Integrated Development Environment (IDE) and debugging tools or figure out how to use thier APIs to synch your JavaScript files. You will likely start to miss your preferred IDE as your VoxEngine scripts grow in complexity. Also, make sure to remember to save often since the web interface won’t do that for you automatically!</p>
<h2 id="dialogflowapiwrappers">Dialogflow API wrappers</h2>
<p>Voximplant provides a lot of control over its interaction with Dialogflow. It has effectively wrapped most of the Dialogflow API’s for interacting with an existing agent (but not the ones for programming an agent).</p>
<p>This API includes a <a href="https://voximplant.com/docs/references/voxengine/ai#createdialogflow">method to start a Dialogflow session</a> and a number of events and classes:</p>
<table style="width:100%">
    <tr><th>Classes</th><th>Events</th></tr>
    <tr><td><ul>
        <li>DialogflowError</li>
<li>DialogflowPlaybackFinished</li>
<li>DialogflowPlaybackMarkerReached</li>
<li>DialogflowPlaybackStarted</li>
<li>DialogflowResponse</li>
<li>DialogflowStopped</li>
        </ul></td><td>
<li>DialogflowEventInput</li>
<li>DialogflowInstance</li>
<li>DialogflowOutputAudioConfig</li>
<li>DialogflowQueryInput</li>
<li>DialogflowQueryParameters</li>
<li>DialogflowResponse</li>
<li>DialogflowResult</li>
<li>DialogflowSettings</li>
<li>DialogflowStreamingRecognitionResult</li>
<li>DialogflowSynthesizeSpeechConfig</li>
<li>DialogflowTextInput</li>
<li>DialogflowVoiceSelectionParams</li>
        </td></tr>
</table>
<br>
<p>I will review some of these events and classes in the <a href="#heading=h.6oeviojls4jm">making our voicebot</a> section.</p>
<h1 id="pricing">Pricing</h1>
<p>Voximplant charges $0.005 / minute for inbound traffic to VoxEngine and $0.015/minute for PSTN calls out of VoxEngine. This gives their Dialogflow Connector a 32% discount vs. the call forwarding approach on their same platform.</p>
<p>US phone numbers are $1.00/month.</p>
<p>As mentioned previously in this series, you can use the Dialogflow Phone Gateway for free, but I assume one would pay Google for one of its <a href="https://cloud.google.com/dialogflow/docs/editions">Enterprise plans</a> for an unlimited quota with an SLA.</p>
<p><img src="https://cogint.ai/content/images/2019/06/VoxImplant-Dialogflow-pricing-comparison-1.jpg" alt="Voximplant's Dialogflow Connector: 2019 Review"></p>
<h1 id="makingourvoicebot">Making our voicebot</h1>
<p>The first post in this series describes <a href="https://cogint.ai/3-methods-for-connecting-a-phone-call-to-dialogflow/#whatelseshouldthedialogflowgatewayhandle">requirements</a> for making a voicebot gateway to replace an IVR. In this section I will give some highlights of Voximplant’s setup and review how to implement some of the requirements, with code samples where appropriate.</p>
<p><strong>You can see my entire VoxEngine JavaScript program in <a href="https://gist.github.com/chadwallacehart/c5071cad01aa670578c2c263c311d83c">this gist</a></strong>.</p>
<p>Note the samples are below are not intended to be a step-by-step development guide - refer to Voximplant for that.</p>
<h2 id="setupviamarketplace">Setup via Marketplace</h2>
<p>In addition to the reference guide <a href="https://voximplant.com/blog/how-to-use-dialogflow-connector">here</a> for setting up the Dialogflow Connector, Voximplant also added an integration option inside thier Marketplace to make this easy. You can find this off of their main side menu.</p>
<p><img src="https://cogint.ai/content/images/2019/06/VoxImplant-Dialogflow-Connector-wizard.png" alt="Voximplant's Dialogflow Connector: 2019 Review"></p>
<p>From there you will need to go into the Google Cloud Console to get your service account key. Follow the steps <a href="https://dialogflow.com/docs/reference/v2-auth-setup">setting up authentication</a> guide from the Dialogflow docs to get that. Once you get that and upload it, Voximplant will create a new application that includes the Agent connection. You should see the default Dialogflow Connector code show up in your scenarios list:</p>
<p><img src="https://cogint.ai/content/images/2019/06/VoxImplant-scenario.png" alt="Voximplant's Dialogflow Connector: 2019 Review"><br>
You can also access, add, and delete an agent in the Dialogflow Connector menu inside your application. If you add a Dialogflow agent this way it will not automatically create the Scenario code.<br>
<img src="https://cogint.ai/content/images/2019/06/VoxImplant-Dialogflow-Connector-page.png" alt="Voximplant's Dialogflow Connector: 2019 Review"></p>
<p>Voximplant’s <a href="https://voximplant.com/blog/how-to-use-dialogflow-connector/resize?w=800">guide</a> mentions this, but don’t forget to set your Text to Speech configuration in Dialogflow to <em>MP3</em> or <em>Ogg Opus</em>. I forgot this and was wondering why I was only hearing silence.</p>
<p>The code itself is documented so I will give some highlights below.</p>
<h2 id="dialogfloweventsandcontexts">Dialogflow Events and Contexts</h2>
<h3 id="sendingevents">Sending Events</h3>
<p>In addition to handling text and speech-based inputs to initiate an <em>intents</em>, Dialogflow can also handle incoming events. The advantage to events vs. sending utterances is that here is no Machine Learning processing of the utterance. Using an event allows you to immediately and definitively  invoke an intent.</p>
<p>Voximplant uses this event-based system when it sends an initial query, after connecting:</p>
<pre><code>// Sending WELCOME event to let the agent says a welcome message
dialogflow.sendQuery({event : {name: &quot;WELCOME&quot;, language_code: &quot;en&quot;}})
</code></pre>
<h3 id="settingcontexts">Setting Contexts</h3>
<p>In addition, Dialogflow also lets you set <a href="https://cloud.google.com/dialogflow/docs/contexts-overview">contexts</a>. Contexts let you store stateful information across intents during a user's bot interaction. Contexts can also be used as filters when you might want to have different responses for the same intent in different scenarios - like responding differently on a voice call vs. a text message. In our voicebot we wanted to have a <code>phone</code> context that kept the user’s caller ID and phone number. VoxEngine has a <code>dialogflow.setQueryParameters</code> method to do this that you should set before sending a query. To do this we just added the following instead of the above code:</p>
<pre><code>// Set a phone context with phone parameters
// Note: Dialogflow seems to convert camelCase to camel_case, so I just changed it here
// ToDo: error handling if returned parameters are null?
phoneContext = {
  name: &quot;phone&quot;,
  lifespanCount: 99,
  parameters: {
    caller_id: call.callerid(),
    called_number: call.number()
  }
}

dialogflow.setQueryParameters({contexts: [phoneContext]})

// Sending WELCOME event to let the agent says a welcome message
dialogflow.sendQuery({event : {name: &quot;WELCOME&quot;, language_code:&quot;en&quot;}})

</code></pre>
<h2 id="calltransfer">Call Transfer</h2>
<p>The bottom part of Voximplant’s code gives examples for handling telephony responses from Dialogflow including call transfer, speech synthesis, and playback of an audio file - all the options available in Dialogflow’s Telephony menu. Basically all you need to do is set your Telephony options there, just like you would do if you were using Dialogflow’s Phone Gateway.</p>
<p><img src="https://cogint.ai/content/images/2019/06/signalwire-dialogflow-telephony-fail.png/resize?w=800" alt="Voximplant's Dialogflow Connector: 2019 Review"></p>
<h6 id="dialogflowsbuiltintelephonyoptionsallworkwithvoximplant">Dialogflow’s built-in Telephony options all work with Voximplant</h6>
<p>Just uncomment out the transfer code and enter one of your phone numbers to dial from:</p>
<pre><code>function processTelephonyMessage(msg) {
  // Transfer call to msg.telephonyTransferCall.phoneNumber
  if (msg.telephonyTransferCall !== undefined) {
    dialogflow.stop()
    let newcall = VoxEngine.callPSTN(msg.telephonyTransferCall.phoneNumber, VOICEBOT_PHONE_NUMBER)
    VoxEngine.easyProcess(call, newcall)
  }
}
</code></pre>
<h2 id="recording">Recording</h2>
<p>Call recording is trivial to do. Just add a <code>call.record({stereo: true})</code>. Stereo is not even mandatory, but it makes debugging easier since the caller and Dialogflow agent are on separate audio channels. I placed this in the <code>onCallRecorded</code> function.</p>
<p>Voximplant puts the call recording in the call history tab. That is all I needed since I just wanted the recordings for debugging. In a real application you could share the recording URL and save it somewhere else.<br>
<img src="https://cogint.ai/content/images/2019/06/VoxImplant-call-history.png" alt="Voximplant's Dialogflow Connector: 2019 Review"></p>
<h6 id="examplefromvoximplantscallhistoryshowingchargeschargesandrecordingplayback">Example from Voximplant’s call history showing charges charges and recording playback</h6>
<h2 id="playbackinterruption">Playback Interruption</h2>
<p>We want our voicebot to be realistic as possible. One aspect of human-to-human conversations is that we interrupt each other. Ideally the voicebot could speak and listen at the same time and even interrupt its own responses if needed. The way Dialogflow’s query API works is you send it an utterance and it returns a response.  Sending a bunch of queries back to back is fine, it does not make sense to playback a multiple responses over the top of each other. To avoid this lot of voicebots take a sequential approach:</p>
<ol>
<li>Stream audio to Dialogflow, which listens for an utterance</li>
<li>When Dialogflow hears and utterance it sends a response to the Gateway</li>
<li>The gateway then stops listening for new audio</li>
<li>The gateway plays back the audio provided by Dialogflow (or synthesizes speech from the returned text)</li>
<li>Then the gateway starts listening again, starting the cycle over</li>
</ol>
<p>Voximplant does not have a perfect solution for playback interruption, but they do have a playback marker concept that lets you tell the gateway when to start listening again after playback. VoxImplant actually lets you set this to a negative value, so it starts listening again before the playback of the previous intent response is done. If you get this timer right you can allow some ability to interrupt without worrying about overlapping playback.</p>
<p>Voximplant has a single line of code for this:</p>
<pre><code>   // Playback marker used for better user experience
   dialogflow.addMarker(-300)`
</code></pre>
<p>It may be possible continuously listen for user utterances and use a <code>dialogflow.stopMediaTo(call)</code> to stop playback if a new intent comes in while the previous intent response is still playing.  The logic to get this right seems complex and the application itself might want to choose when it is worth interrupting playback. I did not experiment with this yet.</p>
<h2 id="noactivitydetection">No Activity Detection</h2>
<p>if you were in the middle of a call with another person and they suddenly went silent, you would say “are you there”? The voicebot needs the mechanism to do something similar. Google Assistant provides an <code>actions_intent_NO_INPUT</code> event to Dialogflow to handle this. We can create something similar inside VoxEngine.</p>
<p>First we will need to create a timer to keep track of silence time. I created a <code>Timer</code> class for this:</p>
<pre><code>const MAX_NO_INPUT_TIME = 15000
let dialogflow, call, hangup

// Fire the &quot;NO_INPUT&quot; event if there is no speech for MAX_NO_INPUT_TIME
class Timer {
 constructor() {
   this.expired = false
   this.noInputTimer = null
   }
   start(){
       this.noInputTimer = setTimeout(()=&gt;{
           this.expired = true
           Logger.write(&quot;No_Input timer exceeded&quot;)
           dialogflow.sendQuery({event : {name: &quot;NO_INPUT&quot;, language_code: &quot;en&quot;}})
       }, MAX_NO_INPUT_TIME || 30 * 1000)
       Logger.write(&quot;No_Input timer started&quot;)
   }
   stop(){
       this.expired = false
       clearTimeout(this.noInputTimer)
       Logger.write(&quot;No_Input cleared&quot;)
   }
 }

let timer = new Timer()
</code></pre>
<p>You will notice my class has a start function that uses a simple <code>setTimeout</code> and will send a <code>NO_INPUT</code> event to the Dialogflow agent if it expires.</p>
<p>Then we just add this start timer to whenever an Dialogflow audio response finishing playing. If the timer runs out then the <code>NO_INPUT</code> event is sent.</p>
<pre><code>   dialogflow.addEventListener(AI.Events.DialogflowPlaybackFinished, (e) =&gt; {
     timer.start()
   })
   dialogflow.addEventListener(AI.Events.DialogflowPlaybackStarted, (e) =&gt; {
     // Dialogflow TTS playback started
     timer.stop()
   })
</code></pre>
<p>I thought this would be all I needed, but when I first tried it didn’t work. It turns out calling <code>sendMedia</code> function right after the <code>sendQuery</code> overrides the stream. To prevent this race conditions, I had to add another check to the <code>onDialogflowResponse</code> function to not send media to Dialogflow if the timer is expired. We want the <code>NO_INPUT</code> response to come back and play first. It will not work without this.</p>
<pre><code>// Handle Dialogflow responses
function onDialogflowResponse(e) {
 // If DialogflowResponse with queryResult received - the call stops sending media to Dialogflow
 // in case of response with queryResult but without responseId we can continue sending media to dialogflow
 if (e.response.queryResult !== undefined &amp;&amp; e.response.responseId === undefined) {
   if (!timer.expired)
     call.sendMediaTo(dialogflow)
</code></pre>
<p>On the Dialogflow side, make sure to make an intent and populate the <code>NO_INPUT</code> event with some default responses.<br>
<img src="https://cogint.ai/content/images/2019/06/Dialogflow-No-Input-intent.png/resize?w=800" alt="Voximplant's Dialogflow Connector: 2019 Review"></p>
<h2 id="dtmfdetection">DTMF detection</h2>
<p><a href="https://en.wikipedia.org/wiki/Dual-tone_multi-frequency_signaling">DTMF</a> entry is a nice to have feature in some circumstances, even if the overall goal is to eliminate the traditional “select 1 for…” approach. For example, if you asked for a phone number, a user may prefer to touchtone that rather than say it. In other cases one might need to maintain some existing IVR functionality for scripts that auto-navigate through some options.</p>
<p>Voximplant’s <code>call</code> class has the ability to alert on DTMF tones:</p>
<pre><code>let waitForTone = false // global we’ll need later

// ...
// This is part of the VoxEngine.addEventListener block
// ...

 call.handleTones(true)
 call.addEventListener(CallEvents.ToneReceived, onTone)
</code></pre>
<p>Our <code>onTone</code> function then just needs to send an event to Dialogflow. We will add a parameter to  pass the digit:</p>
<pre><code>function onTone(e){
 //ToDo: error handling - i.e. check to make sure Dialogflow is connected and running first, tone valuess
 waitForTone = true
 dialogflow.sendQuery({event : {name: &quot;DTMF&quot;, language_code: &quot;en&quot;, parameters: { dtmf_digits: e.tone} }})
}
</code></pre>
<p>In a real app you likely would want to capture multiple digits if they are entered in sequence and send them to Dialogflow as a single event instead of a series of events.</p>
<p>Like with the No Activity Detection <a href="#heading=h.977nimv8k3d9">above</a>, we need to pause sending media to Dialogflow while our while we handle our event response:</p>
<pre><code>function onDialogflowResponse(e) {
 // If DialogflowResponse with queryResult received - the call stops sending media to Dialogflow
 // in case of response with queryResult but without responseId we can continue sending media to dialogflow
 if (e.response.queryResult !== undefined &amp;&amp; e.response.responseId === undefined) {
       if (!timer.expired &amp;&amp; !waitForTone)
         call.sendMediaTo(dialogflow)
</code></pre>
<p>Lastly, remember to reset our global <code>waitForTone</code> to resume sending media to Dialogflow:</p>
<pre><code>   dialogflow.addEventListener(AI.Events.DialogflowPlaybackFinished, (e) =&gt; {
     timer.start()
     waitForTone = false
   })
</code></pre>
<p>Like with the No Activity Detection, we need to setup our event in Dialogflow. I created an <a href="https://dialogflow.com/docs/entities">Entity</a> to handle the parameters passed by the VoxEngine script. This one also needs some training phrases.<br>
<img src="https://cogint.ai/content/images/2019/06/Dialogflow-DTMF-intent.png/resize?w=800" alt="Voximplant's Dialogflow Connector: 2019 Review"></p>
<h2 id="nosmsintegrationwithdialogflow">No SMS Integration with Dialogflow</h2>
<p>Voximplant does not have any VoxEngine control over SMS. This means VoxEngine has no way to send incoming SMS messages to our bot. Like with other platforms, you could always setup your own server and use webhooks to handle this interaction. We were looking for something simpler.</p>
<h2 id="scorecard">Scorecard</h2>
<p>Voximplant ended up being a good (but not perfect) fit against the criteria we identified in the <a href="https://cogint.ai/3-methods-for-connecting-a-phone-call-to-dialogflow/">first post of this series</a>:</p>
<table>
<thead>
<tr>
<th><strong>Requirement</strong></th>
<th><strong>Voximplant Dialogflow Connector</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Call Transfer</td>
<td>Yes</td>
</tr>
<tr>
<td>Recording</td>
<td>Yes</td>
</tr>
<tr>
<td>Playback Interruption</td>
<td>Some - playback marker gives some of the effect</td>
</tr>
<tr>
<td>No activity detection</td>
<td>Yes</td>
</tr>
<tr>
<td>DTMF detection</td>
<td>Yes</td>
</tr>
<tr>
<td>SMS support</td>
<td>No</td>
</tr>
</tbody>
</table>
<h2 id="whatsnext">What’s Next</h2>
<p>Now that we have established our requirements and evaluated a few implementation options, in the last few posts in this series we will start to get into architectural considerations and actual implementation challenges. You can leave comments below and remember to <a href="https://cogint.ai/subscribe/">subscribe</a> if you want to see more.</p>
<hr>
<h3 id="abouttheauthor">About the Author</h3>
<p>Chad Hart is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and strategy advisory helping to advance the communications industry. In addition, recently he co-authored a study on <a href="https://krankygeek.com/research">AI in RTC</a> and helped to organize an <a href="https://krankygeek.com">event</a> / <a href="https://www.youtube.com/watch?v=P38cd3GLn74&amp;list=PL4_h-ulX5eNfaM0QM5r-PewWaY_zgLH7b">YouTube series</a> covering that topic.</p>
<hr>
<h3 id="remembertosubscribefornewpostnotificationsandfollowcogintai">Remember to <a href="https://cogint.ai/subscribe/">subscribe</a> for new post notifications and follow <a href="https://twitter.com/cogintai">@cogintai</a>.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[SignalWire’s Dialogflow Connector: 2019 review]]></title><description><![CDATA[Updated review of SignalWire's Dialogflow Connector for connecting phone calls into Dialogflow to add voicebot functionality and replace IVRs. Includes a trick for SMS bots.]]></description><link>https://cogint.ai/signalwire-dialogflow-2/</link><guid isPermaLink="false">5d08478304a8c82a4f530e4a</guid><category><![CDATA[voicebot]]></category><category><![CDATA[dialogflow]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Mon, 17 Jun 2019 10:55:00 GMT</pubDate><media:content url="https://cogint.ai/content/images/2019/08/AdobeStock_63025043-small.jpeg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2019/08/AdobeStock_63025043-small.jpeg" alt="SignalWire’s Dialogflow Connector: 2019 review"><p>Last week we talked about the <a href="https://cogint.ai/3-methods-for-connecting-a-phone-call-to-dialogflow/">3 Methods for Connecting a Phone call to Dialogflow</a>. The third method we discussed was direct connectivity to Dialogflow from your telephony platform. This approach provides the best call quality possible and should cost less since you don’t need to pay for call charges out of the telephony environment or into the Dialogflow Phone Gateway. The downsides are there are few options for doing this and each platform is proprietary. SignalWire is one of the Communications Platform as a Service (CPaaS) who has been doing this for a while and that is what I will review today.</p>
<p>SignalWire introduced a basic Dialogflow connector when they launched last year. In my <a href="https://cogint.ai/calling-into-dialogflow-with-signalwire/">initial review of that</a>, I discussed some bugs and that the main advantage of their implementation SignalWire was free connectivity into Dialogflow. The updates I noticed this time were:</p>
<ul>
<li>New connectivity charge per minute to connect to Dialogflow</li>
<li>More TTS voices for the welcome prompt</li>
<li>The start to some Dialogflow telephony integration</li>
<li>Support for Dialogflow agents set to languages other than English</li>
</ul>
<p><img src="https://cogint.ai/content/images/2019/06/signalwire-dialogflow-connector-architecture.png/resize?w=1200" alt="SignalWire’s Dialogflow Connector: 2019 review"></p>
<h2 id="pricing">Pricing</h2>
<p>SignalWire Dialogflow connectivity is now priced at 2 cents per minute, This is quite a bit higher than their 0.65 cents per minute for placing an outbound call. However, this is still a deal compared to the 5 cents per minute Google changes on their Enterprise plan on top of the 0.65 cents per minute you would then need to pay SignalWire for the outbound call if you used the CPaaS + Dialogflow Phone Gateway approach described earlier.</p>
<p><img src="https://cogint.ai/content/images/2019/06/signalwire-dialogflow-connector-pricing.png" alt="SignalWire’s Dialogflow Connector: 2019 review"></p>
<h6 id="examplefromsignalwiresusagehistoryshowingdialogflowconnectorcharges">Example from SignalWire’s usage history showing Dialogflow Connector charges</h6>
<p><img src="https://cogint.ai/content/images/2019/06/signalwire-dialogflow-price-comparison.png/resize?w=1200" alt="SignalWire’s Dialogflow Connector: 2019 review"></p>
<h6 id="acostcomparisonofthecallforwardingapproachvsusingsignalwiresdialogflowconnectortheconnectorreducesthecostbyneary60">A cost comparison of the call forwarding approach vs. using SignalWire’s Dialogflow connector. The connector reduces the cost by neary 60%.</h6>
<h2 id="dialogflowtelephonyinteraction">Dialogflow Telephony interaction</h2>
<p>Like before, SignalWire also has the ability to play a welcome message prior to connecting to SignalWire. They have the complete list of Standard and Wavenet Text-to-Speech (TTS) voices from Google’s TTS to choose from as a default TTS engine, but this selection only works on the welcome prompt. The Agent voice was still what was set inside Dialogflow. I also noticed that the “Synthesize voice” option inside Dialogflow’s telephony integration worked, but this also used the Dialogflow voice selection, not use the Signalwire one. I also tried the Dialogflow Telephony integration Transfer call feature, but that did not seem to do anything when I tested.</p>
<p><img src="https://cogint.ai/content/images/2019/06/signalwire-dialogflow-telephony-fail.png" alt="SignalWire’s Dialogflow Connector: 2019 review"></p>
<h6 id="dialogflowsbuiltintransfercallfeaturedidnotwork">Dialogflow’s built-in <em>Transfer Call</em> feature did not work</h6>
<h3 id="calltransferwebhook">Call Transfer Webhook</h3>
<p>It is possible to setup a transfer using webhooks and one SignalWire’s REST API’s, but this would add some complexity and would require a helper server. I did not see a quick or straightforward way of doing this though, so I did not try it.</p>
<h2 id="recording">Recording</h2>
<p>Unfortunately Dialogflow Agents cannot be addressed using SignalWire’s LAML scripting language. This means it is not possible to implement a simple record and forward script to recording the incoming call. You could get around the lack of Dialogflow Agent addressing by forwarding the call to your Dialogflow number, but that would bring you back to <a href="https://cogint.ai/3-methods-for-connecting-a-phone-call-to-dialogflow/#method2forwardcallstodialogflowphonegateway">Method 2</a> with its issues, which is what we were trying to avoid with the Dialogflow Connector in the first place.</p>
<h2 id="hackforsmssupport">Hack for SMS support</h2>
<p>Twilio is the only vendor to have a native Text Messaging Integration with Dialogflow. This is not documented anywhere, but it turns out you can use that same integration with SignalWire too. Simply just go to Dialogflow’s integrations, select Twilio (Text Messaging) and then  insert your SignalWire project key and API token in the Dialog Account SID and Account Token field respectively.  Make a note of the generated <em>Request URL</em>:<br>
<img src="https://cogint.ai/content/images/2019/06/dialogflow-twilio-sms-connector.png/resize?w=1200" alt="SignalWire’s Dialogflow Connector: 2019 review"><br>
Now to into your phone number settings inside SignalWire, pop down to Messaging Settings, and place the <em>Request URL</em> into the “when a message comes in” field:<br>
<img src="https://cogint.ai/content/images/2019/06/signalwire-message-settings.png/resize?w=1200" alt="SignalWire’s Dialogflow Connector: 2019 review"><br>
As I do not believe this is officially supported, this is a really a hack, but it works!</p>
<h2 id="signalwiresscore">SignalWire’s score</h2>
<p>SignalWire was not much of a fit against the criteria we identified in the <a href="https://cogint.ai/3-methods-for-connecting-a-phone-call-to-dialogflow/">first post of this series</a>:</p>
<table>
<thead>
<tr>
<th><strong>Requirement</strong></th>
<th><strong>SignalWire Dialogflow Connector</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Call Transfer</td>
<td>Maybe, but it is not straight forward</td>
</tr>
<tr>
<td>Recording</td>
<td>No</td>
</tr>
<tr>
<td>Playback Interruption</td>
<td>No</td>
</tr>
<tr>
<td>No activity detection</td>
<td>No</td>
</tr>
<tr>
<td>DTMF detection</td>
<td>No</td>
</tr>
<tr>
<td>SMS support</td>
<td>Yes - use the Twilio Text Messaging integration</td>
</tr>
</tbody>
</table>
<h2 id="whatsnext">What’s Next</h2>
<p>Next week I will provide an update to VoxImplant’s Dialogflow Connector that they <a href="https://cogint.ai/making-ivrs-not-suck-with-dialogflow-alexey-aylarov/">introduced here</a> a year ago.  There are a lot of changes there. After that we will review the major challenges we encountered in implementing this system and share some implementation examples from our research. Make sure to <a href="https://cogint.ai/subscribe/">subscribe</a> so you don't miss anything as we progress through this series.</p>
<hr>
<h3 id="abouttheauthor">About the Author</h3>
<p>Chad Hart is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and strategy advisory helping to advance the communications industry. In addition, recently he co-authored a study on <a href="https://krankygeek.com/research">AI in RTC</a> and helped to organize an <a href="https://krankygeek.com">event</a> / <a href="https://www.youtube.com/watch?v=P38cd3GLn74&amp;list=PL4_h-ulX5eNfaM0QM5r-PewWaY_zgLH7b">YouTube series</a> covering that topic.</p>
<hr>
<h3 id="remembertosubscribefornewpostnotificationsandfollowcogintai">Remember to <a href="https://cogint.ai/subscribe/">subscribe</a> for new post notifications and follow <a href="https://twitter.com/cogintai">@cogintai</a>.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[3 Methods for Connecting a Phone Call to Dialogflow]]></title><description><![CDATA[A look at different ways of creating a telephone voicebot with Dialogflow including a review of Dialogflow's Phone Gateway and methods for communications platform (CPaaS) interaction]]></description><link>https://cogint.ai/3-methods-for-connecting-a-phone-call-to-dialogflow/</link><guid isPermaLink="false">5cfef64f04a8c82a4f530e15</guid><category><![CDATA[voicebot]]></category><category><![CDATA[dialogflow]]></category><category><![CDATA[review]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Tue, 11 Jun 2019 00:31:00 GMT</pubDate><media:content url="https://cogint.ai/content/images/2019/06/3-dialogflow-gateway-methods-picture-v2-1.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2019/06/3-dialogflow-gateway-methods-picture-v2-1.png" alt="3 Methods for Connecting a Phone Call to Dialogflow"><p>We are starting up a new series on using Dialogflow as an Interactive Voice Response (IVR) replacement. We have covered this topic a few times here, including looking at Dialogflow’s own <a href="https://cogint.ai/dialogflow-phone-bot/">Phone Gateway</a> and the Gateway interface implementations of <a href="https://cogint.ai/making-ivrs-not-suck-with-dialogflow-alexey-aylarov/">VoxImplant</a> and <a href="https://cogint.ai/calling-into-dialogflow-with-signalwire/">SignalWire</a>. Beyond just building simple demo systems, Chad had been exploring improved ways of using Dialogflow to implement an IVR replacement for telephony environments.</p>
<p>Joining me to help with this series is Emiliano Pelliccioni. Emiliano is a developer at webRTC.ventures. Emiliano has worked on similar projects with Chad in the past and has continued researching this area. We decided to get together to share our research and experiments in this domain.</p>
<p>In this first post, we want to share some of the methods we explored to connecting Dialogflow to a phone call. Let’s first review what’s involved in making this connection and some nice-to-have features before reviewing the methods.</p>
<h1 id="whatisadialogflowtelephonygateway">What is a Dialogflow Telephony Gateway?</h1>
<p>We want to be able to dial a phone number and have Dialogflow handle the interaction as a voicebot IVR. To do this, there needs to be some kind of gateway that handles both signaling and media conversion. On the signaling side, the gateway needs to take the telephony signaling - which is almost always based on SIP - and use that to invoke the proper Dialogflow commands to launch and interact with the bot. This also includes handling hang-ups and the termination of the call.</p>
<p>Slightly more complicated is the media conversation that needs to take place. Dialogflow’s interface for real time speech input is gRPC. The gateway needs to convert the SRTP or RTP media used by the telephony end to a gRPC bitstream using Dialogflow-friendly codecs. The gateway also needs to play back the response speech generated by Dialogflow (or use its own Text-to-Speech mechanism to vocalize Dialogflow’s response text).</p>
<p><img src="https://cogint.ai/content/images/2019/06/dialogflow-telephony-gateway.png" alt="3 Methods for Connecting a Phone Call to Dialogflow"></p>
<h1 id="whatelseshouldthedialogflowgatewayhandle">What else should the Dialogflow Gateway handle?</h1>
<p>Beyond basic connectivity, there are a few other features that will help to improve development and user interaction.</p>
<p>A short list of the top features we evaluated is:</p>
<ul>
<li><strong>Recording</strong> - not a hard requirement, but having a full recording of both parties is invaluable for debugging and improving the system</li>
<li><strong>Call transfer</strong> - in most cases you need to give the user an option to talk to a human, or the natural result of a bot will be to transfer the call</li>
<li><strong>Playback interruption</strong> - ideally your voicebot could handle an asynchronous conversation, so the user could interrupt whatever the bot is saying and that speech would be processed</li>
<li><strong>No activity detection</strong> - if you were in the middle of a conversation and it suddenly went silent, you would say “are you there”? The bot needs the mechanism to do something similar. If you were using Dialogflow to make a Google Assistant bot, they give you an <code>actions_intent_NO_INPUT</code> event and mechanisms to <a href="https://developers.google.com/actions/assistant/reprompts">setup reprompt intents</a> - the gateway needs to provide something similar</li>
<li><strong>DTMF detection</strong> - even if the goal is to eliminate DTMF menus, sometimes it is nice to have DTMF as a backup option or alternative input method - especially if you are trying to do something like capture a phone number and Dialogflow cannot understand the caller</li>
<li><strong>SMS</strong> - nice to have; more on this below</li>
</ul>
<p>The scope of our project was fairly limited, but other options could include customized Speech-to-Text (STT) and Text-to-Speech (TTS) engines instead of using the ones built into Dialogflow. This could allow for better coverage of custom vocabularies or unique voice synthesis.</p>
<h3 id="smssupport">SMS support</h3>
<p>There are many cases when it is easier to send the user a link. A restaurant wouldn’t want to read off an entire menu - it is easier to just send a link to this. In practice, most callers use their mobile phones to call, which means they should be able to receive text messages. The gateway should help determine if the caller is on an SMS-capable device and send them text messages if that would help in the interaction.</p>
<p>If you are going to send SMS, you should also be prepared to receive SMS and interact via text without requiring voice. In fact, this could allow ongoing dialog after the phone call has finished. To implement this, the gateway needs to keep some state on the user and manage interactions between the voice telephony and SMS environment.</p>
<h1 id="threemethodsforimplementingadialogflowtelephonygateway">Three Methods for Implementing a Dialogflow Telephony Gateway</h1>
<p>We found 3 major methods for connecting a phone call to Dialogflow:</p>
<ol>
<li>Use Dialogflow’s built-in Phone Gateway</li>
<li>Forward a call from a telephony system into Dialogflow’s Phone Gateway</li>
<li>Directly connect a telephony system to Dialogflow</li>
</ol>
<h2 id="method1usethedialogflowphonegateway">Method 1: Use the Dialogflow Phone Gateway</h2>
<p><img src="https://cogint.ai/content/images/2019/06/dialogflow-phone-gateway.png" alt="3 Methods for Connecting a Phone Call to Dialogflow"><br>
Chad previously<a href="https://cogint.ai/dialogflow-phone-bot/"> reviewed this</a> in August 2018. Nothing has changed here in terms of the setup or functionality. The service is still in what Google defines as Beta, but that is usually a pretty high standard.  See that previous post for a walkthrough or just go to Dialogflow’s own <a href="https://cloud.google.com/dialogflow-enterprise/docs/telephony">docs on using the Phone Gateway</a> (which they call “Telephony Gateway” in that link).</p>
<p>English is still the <a href="https://cloud.google.com/dialogflow-enterprise/docs/reference/language">only supported language with telephony</a> if you want to generate speech output from Dialogflow. Other than that, the main benefits of the Phone Gateway are:</p>
<ul>
<li>It is very easy to setup</li>
<li>It is free, subject to quotas unless you want the <a href="https://cloud.google.com/dialogflow-enterprise/pricing">Enterprise Edition</a></li>
<li>A <code>TELEPHONY_WELCOME</code> event is included for special handling of phone calls</li>
<li>The Dialoflow Intent GUI includes a tab for special handling of telephony responses, including audio playback, special speech synthesis, and call transfer (see below)</li>
<li>You can easily transfer calls to a single US number</li>
</ul>
<p><img src="https://cogint.ai/content/images/2019/06/dialogflow-telephony-tab.png" alt="3 Methods for Connecting a Phone Call to Dialogflow"></p>
<h3 id="dialogflowphonegatewaysummaryscorecard">Dialogflow Phone Gateway Summary Scorecard</h3>
<p>So, Dialogflow has some convenient features in its Phone Gateway but in the end, it is pretty limited:</p>
<table>
<thead>
<tr>
<th><strong>Requirement</strong></th>
<th><strong>Dialogflow Phone Gateway</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Recording</td>
<td>No</td>
</tr>
<tr>
<td>Call Transfer</td>
<td>Yes, but only to US numbers</td>
</tr>
<tr>
<td>Playback Interruption</td>
<td>No</td>
</tr>
<tr>
<td>No activity detection</td>
<td>No</td>
</tr>
<tr>
<td>DTMF detection</td>
<td>No</td>
</tr>
<tr>
<td>SMS support</td>
<td>No</td>
</tr>
</tbody>
</table>
<h2 id="method2forwardcallstodialogflowphonegateway">Method 2: Forward Calls to Dialogflow Phone Gateway</h2>
<p><img src="https://cogint.ai/content/images/2019/06/call-forwarding.png" alt="3 Methods for Connecting a Phone Call to Dialogflow"><br>
Dialogflow does not have a whole lot of telephony controls, but it is possible to use another telephony platform to actually forward calls to the Dialogflow Phone Gateway. This platform could be anything - a commercial PBX or ACD system, an open source telephony platform like Asterisk or Freeswitch, for a Communications Platform as a Service (CPaaS) that provides this functionality as a cloud-based service like Twilio, Nexmo, SignalWire, VoxImplant, and others. We largely evaluated CPaaS so we are only going to refer to that option from here on out. This approach enables some features if you are willing to leverage Dialogflow’s webhooks to interact with the telephony platform.</p>
<h3 id="forwardingbenefits">Forwarding Benefits</h3>
<p>Some of the benefits of this approach vs. just using the Dialogflow Phone Gateway are:</p>
<ul>
<li>Support for any phone number you want - the Dialogflow Phone Gateway only supports US numbers now</li>
<li>Support for multiple phone numbers - you just get one with the Dialogflow Phone Gateway</li>
<li>Easy Recording - this is almost always available as a feature</li>
<li>More control over call transfer if your platform can handle incoming webhooks and programmatic control</li>
<li>Handle SIP calls if your platform supports it</li>
<li>Advanced call flows - such as conferencing in an agent to listen or help with the voicebot interaction</li>
</ul>
<p>Features like recording are generally simple to implement. Call transfer control usually better if it is possible to tell your CPaaS to hang-up and send a call somewhere based on a webhook fulfillment.</p>
<h4 id="nexmoskrankygeekaiinrtcshowexample">Nexmo’s Kranky Geek AI in RTC Show Example</h4>
<p>Nexmo provided a good example of this at the last Kranky Geek AI in RTC event:</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/bxZzEpS6Uxs?start=333" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<p>You can see that code here:<br>
<a href="https://github.com/alwell-kevin/simple-smart-ivr-framework">https://github.com/alwell-kevin/simple-smart-ivr-framework</a></p>
<h3 id="forwardingdownsides">Forwarding Downsides</h3>
<p>The main drawback of this approach is that there is still no direct way for your CPaaS app to communicate with Dialogflow. Dialogflow can only signal something back to your CPaaS App. This means you could have your CPaaS app listen for things like DTMF presses or the user interrupting an audio playback, but the CPaaS can’t talk directly to your app to signal an event.</p>
<h4 id="smsproxydevelopmentmayberequired">SMS proxy development may be required</h4>
<p>Dialogflow’s Phone Gateway also doesn’t support SMS, but nearly every CPaaS platform does. Unfortunately only Twilio has a Text Messaging option built into Dialogflow’s integrations. While most CPaaS platforms provide easy mechanisms for managing text message interaction programmatically, a developer would need to invoke Dialogflow’s API’s to manually manage these interactions.</p>
<p><img src="https://cogint.ai/content/images/2019/06/SMS-proxy.png" alt="3 Methods for Connecting a Phone Call to Dialogflow"><br>
As shown in the figure above, this app would need to receive the SMS text content from the CPaaS, and forward it to one of Dialogflow’s API’s. Once the intent response has been received back, your app would use the CPaaS API to send an SMS to the user containing the answer.</p>
<h4 id="flexibilitymoredevelopmenttime">Flexibility = more development time</h4>
<p>The same may be true for some of the other requirements. If you are willing to manage a lot more code, you could have your app translate between the CPaaS and Dialogflow for some of these features - but that is essentially building a good part of the gateway.</p>
<h4 id="costqualityimplications">Cost &amp; quality implications</h4>
<p>This forwarding is also more expensive - both in telephony cost and call quality. You are paying for the inbound call leg to CPaaS, the outbound leg from the CPaaS to Dialogflow’s Phone Gateway, and then eventually again when you upgrade to Dialogflow’s Enterprise plan (which you will likely do in a production environment). Also, forwarding a call over the PSTN is less than ideal for voice quality - the extra gateway leg will definitely introduce some latency and hopefully does not cause other impairments.</p>
<p>A direct connection from the CPaaS into Dialogflow is more ideal, and that is what we will discuss in <a href="#method3directconnectivitytodialogflow">Method 3</a>.</p>
<h3 id="forwardingsummaryscorecard">Forwarding Summary Scorecard</h3>
<p>Forwarding is better, but mileage will vary depending on the capabilities of your platform.</p>
<table>
<thead>
<tr>
<th><strong>Requirement</strong></th>
<th><strong>CPaaS + Dialogflow Phone Gateway</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Call Transfer</td>
<td>Yes - some work to code, but full control over transferring</td>
</tr>
<tr>
<td>Recording</td>
<td>Yes - generally easy with a given CPaaS</td>
</tr>
<tr>
<td>Playback Interruption</td>
<td>Not unless you run voice activity detection and are controlling the TTS output</td>
</tr>
<tr>
<td>No activity detection</td>
<td>No</td>
</tr>
<tr>
<td>DTMF detection</td>
<td>No</td>
</tr>
<tr>
<td>SMS support</td>
<td>Maybe, depending on the CPaaS</td>
</tr>
</tbody>
</table>
<h2 id="method3directconnectivitytodialogflow">Method 3: Direct Connectivity to Dialogflow</h2>
<p><img src="https://cogint.ai/content/images/2019/06/Direct-CPaaS-Connection.png" alt="3 Methods for Connecting a Phone Call to Dialogflow"><br>
As is illustrated in the figure above, if your CPaaS can connect directly to Dialogflow you will save a conversion step. Assuming you want to leverage Dialogflow’s built-in Speech-to-Text and Text-to-Speech capabilities, this means your CPaaS needs to have a Gateway that can both signal Dialogflow’s API’s and convert RTP media to Dialogflow-friendly codecs over gRPC and back.</p>
<h3 id="advantages">Advantages</h3>
<ul>
<li>All the same benefits as in the forwarding methodology</li>
<li>Lower cost - no Dialogflow telephony charges (if paying for Enterprise)</li>
<li>Better quality - I did not quantitatively measure this, but it should have lower latency with better voice quality; use of HD audio end-to-end is also possible (though only used if connecting end-to-end with VoIP)</li>
</ul>
<p>After that, the advantages really depend on the specific platform.</p>
<h3 id="disadvantages">Disadvantages</h3>
<p>The main disadvantage here is the limited number of options available. Nearly every telephony platform provides call forwarding but very few offer a direct Dialogflow connector. After that, the ease of implementation will really depend on the platform selected and your development skills.</p>
<h3 id="directconnectivitysolutions">Direct Connectivity Solutions</h3>
<p>The two main commercial CPaaS options are <a href="https://cogint.ai/making-ivrs-not-suck-with-dialogflow-alexey-aylarov/">VoxImplant</a> and <a href="https://cogint.ai/calling-into-dialogflow-with-signalwire/">SignalWire</a>.</p>
<p>On the open source side, there is the <a href="https://github.com/davehorton/simple-dialogflow-example">Dialogflow Interface</a> to the <a href="https://www.drachtio.org/">Drachtio SIP Server</a> which also requires Freeswitch. <a href="http://unimrcp.org/solutions/google-dialogflow">UniMRCP</a> has a MRCP interface for Dialogflow.</p>
<p>If you are looking for a licensed, commercial gateway, Audiocodes has what it calls a <a href="https://www.audiocodes.com/solutions-products/solutions/audiocodes-voiceai/voiceai-gateway">Voice.AI Gateway</a> that connects to Dialogflow.  USAN also has a <a href="http://usan.com/google/dfetg/">Dialogflow gateway product</a>. Some quick searches also show <a href="http://www.voxibot.com">Voxibot</a> and  <a href="https://www.tenios.de/en/voicebot-connector">Tenios</a> claim to have some direct Dialogflow Voice gateway capabilities.</p>
<h3 id="directconnectivitysummaryscorecard">Direct Connectivity Summary Scorecard</h3>
<p>This scorecard will vary considerably by platform since implementation details vary considerably. The basic conversion of media to the Dialogflow gRPC interface seems to be common among all. Few have deep capabilities for interacting with Dialogflow.</p>
<table>
<thead>
<tr>
<th><strong>Requirement</strong></th>
<th><strong>CPaaS + Dialogflow Phone Gateway</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Recording</td>
<td>Yes - generally easy with a given platform</td>
</tr>
<tr>
<td>Call Transfer</td>
<td>Yes - some work to code, but full control over transferring</td>
</tr>
<tr>
<td>Playback Interruption</td>
<td>Depends on the platform</td>
</tr>
<tr>
<td>No activity detection</td>
<td>Depends on the platform</td>
</tr>
<tr>
<td>DTMF detection</td>
<td>Depends on the platform</td>
</tr>
<tr>
<td>SMS support</td>
<td>Maybe, depending on the platform</td>
</tr>
</tbody>
</table>
<h1 id="whatsnext">What’s Next</h1>
<p>We plan to provide updated evaluations of SignalWire and VoxImplant’s Dialogflow connectors next. After that, we will review the major challenges we encountered in implementing this system and share some implementation examples from our research. Make sure to <a href="https://cogint.ai/subscribe/">subscribe</a> so you don't miss anything as we progress through this series.</p>
<p>You can see the next parts of the series <a href="https://cogint.ai/building-a-voicebot-ivr-with-dialogflow/">here</a>.</p>
<hr>
<h3 id="abouttheauthors">About the Authors</h3>
<p>Chad Hart is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and strategy advisory helping to advance the communications industry. In addition, he recently he co-authored a study on <a href="https://krankygeek.com/research">AI in RTC</a> and helped to organize an <a href="https://krankygeek.com">event</a> / <a href="https://www.youtube.com/watch?v=P38cd3GLn74&amp;list=PL4_h-ulX5eNfaM0QM5r-PewWaY_zgLH7b">YouTube series</a> on that topic.</p>
<p>Emiliano Pelliccioni is a computer engineer working at <a href="https://webrtc.ventures/">webRTC.ventures</a> and specializes in developing real time communication applications for clients around the globe. One of his projects includes developing bot integrations for a major CPaaS provider.</p>
<hr>
<h3 id="remembertosubscribefornewpostnotificationsandfollowcogintai">Remember to <a href="https://cogint.ai/subscribe/">subscribe</a> for new post notifications and follow <a href="https://twitter.com/cogintai">@cogintai</a>.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[Kranky Geek AI in RTC 2018 Event Review]]></title><description><![CDATA[A review of the Kranky Geek AI in RTC event with relevant highlights from speech analytics, voicebot, computer vision, and RTC optimization talks.]]></description><link>https://cogint.ai/ai-in-rtc-2018-event-review/</link><guid isPermaLink="false">5bf8615104a8c82a4f530ddc</guid><category><![CDATA[speech analytics]]></category><category><![CDATA[computer vision]]></category><category><![CDATA[voicebot]]></category><category><![CDATA[rtc_optimization]]></category><category><![CDATA[review]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Tue, 27 Nov 2018 09:45:42 GMT</pubDate><media:content url="https://cogint.ai/content/images/2018/11/ai-in-rtc-logo-1.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2018/11/ai-in-rtc-logo-1.png" alt="Kranky Geek AI in RTC 2018 Event Review"><p>Less than two weeks ago I ran the <a href="https://krankygeek.com">Kranky Geek AI in RTC conference</a> with Tsahi Levent-Levi and Chris Koehncke. Historically we covered mostly WebRTC content but last year we decided to add some AI and Machine Learning topics. This year we focused most of the event on AI. Nearly all of this content is highly relevant to the topics covered by this blog, so below is a summary of the most relevant talks with highlights and links.</p>
<p>Much like our <a href="https://krankygeek.com/research">report</a>, we segmented the AI in RTC talks into 4 main areas:</p>
<ul>
<li><strong><a href="https://cogint.ai/ai-in-rtc-2018-event-review/#speechanalytics">Speech analytics</a></strong> – speech to text with Machine Learning analysis of the waveform and transcript</li>
<li><strong><a href="https://cogint.ai/ai-in-rtc-2018-event-review/#voicebots">Voicebots</a></strong> - automated programs that interact with users in a conversational dialog using speech as input and output like Siri, Alexa, Cortana, etc.</li>
<li><strong><a href="https://cogint.ai/ai-in-rtc-2018-event-review/#computervision">Computer Vision</a></strong> – processing video to analyze and understand what is seen</li>
<li><strong><a href="https://cogint.ai/ai-in-rtc-2018-event-review/#rtcoptimization">RTC Optimization</a></strong> - machine learning methods used to improve service quality or cost performance<br>
<img src="https://cogint.ai/content/images/2018/11/ai-in-rtc-with-logos.png" alt="Kranky Geek AI in RTC 2018 Event Review"></li>
</ul>
<p>I have details on the talks in each of these areas below.</p>
<h1 id="speechanalytics">Speech Analytics</h1>
<p>This is a big area and we included three talks – two from services that make heavy use of speech analytics – Voicera and Dialpad - and one that provides a transcription and speech analytics API – Voicebase.</p>
<h2 id="paralinguistics">Paralinguistics</h2>
<blockquote>
<p><em><strong>paralingusitics</strong></em><br>
The branch of linguistics which studies non-phonemic aspects of speech, such as tone of voice, tempo, etc.; non-phonemic characteristics of communication; paralanguage.<br>
<a href="https://en.oxforddictionaries.com/definition/paralinguistics">Oxford Dictionary</a></p>
</blockquote>
<p>Perhaps an better definition for paralinguistics as provided by Voicebase’s CTO, Jeff Shukis:</p>
<blockquote>
<p>How something is said, distinct from what is said</p>
</blockquote>
<p>In this talk, Jeff walked through how Voicebase's investigation of paralinguistic data and where they ended up. In summary, they ended up capturing the two most dominant frequencies on a per-word level along with a relative energy metric. They also look at the relative volume level and total time spoken for each word to inform on speech rate. For end-customer applications, they end up rolling this into some aggregate metrics across the conversation to look for meaningful changes in tone and volume. The relevance of any one of these features is really determined when all the data is fed into a machine learning model that maps the call data against customer provided agent and call outcome data.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/WURDqnOXG1I" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<h2 id="dealingwithcustomjargon">Dealing with custom jargon</h2>
<p>Every industry and business has its own custom vocabulary. Words like “WebRTC” don’t show up in a standard dictionary. Most personal and company names are also hard for speech engines. Unfortunately, these terms often end up being some of the most meaningful words for understanding what was said. Dialpad talked about how they address this with a technique they call Domain Adaptation.  Etienne Manderscheid, their VP of Machine Learning, gave a step-by-step example on how to implement domain adaptation with Kaldi. Etienne actually agreed to do a complete cogint.ai post with a complete code walkthrough, so I’ll save the details for that.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/ekntgaWG-30" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<h1 id="voicebots">Voicebots</h1>
<p>As I covered <a href="https://cogint.ai/vocebot-ai-in-the-call-center/">here before</a>, IVRs and contact centers are huge new opportunity areas for voicebots. Nexmo and IBM both actually covered this topic.</p>
<h2 id="contactcentervoicebotarchitecturesandchallenges">Contact Center Voicebot  architectures and challenges</h2>
<p>Brian Pulito of IBM gave more of an architectural talk, setting up some of the challenges contact centers face with traditional technologies and where voicebots and other AI tools fit. Brian also walked through some the challenges in implementing these systems, including:</p>
<ul>
<li>Dealing with noise</li>
<li>Handling dialects and custom vocabularies</li>
<li>Voice authentication</li>
<li>Handling latency</li>
<li>Using SSML for more natural speech synthesis</li>
<li>Slot filling</li>
<li>Intent training time</li>
</ul>
<iframe width="560" height="315" src="https://www.youtube.com/embed/tUyQhtwuINQ" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<h2 id="integratingwithdialogflow">Integrating with Dialogflow</h2>
<p>We have covered telephony integration with Dialogflow on several different platforms, including <a href="https://cogint.ai/dialogflow-phone-bot/">Dialogflow’s own Phone Gateway</a>, <a href="https://cogint.ai/making-ivrs-not-suck-with-dialogflow-alexey-aylarov/">VoxImplant</a>, and <a href="https://cogint.ai/calling-into-dialogflow-with-signalwire/">SignalWire</a>. Nexmo gave a walkthrough of their approach for this. Unlike VoxImplant and SignalWire that have a native gRPC integration that sends audio over IP to Dialogflow, Nexmo walked through how to simply forward an incoming call to Dialogflow’s phone gateway. While less than ideal from a cost (you make an extra outbound call) and quality perspective (you add another leg through the PSTN), this is actually very easy to do. In addition, Dialogflow’s ability to add a webhook for fulfillment means you can do a better job of handling call transfers than the native Phone Gateway allows.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/bxZzEpS6Uxs" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<h1 id="computervision">Computer Vision</h1>
<p>We had a several talks covering Computer Vision (CV). A couple of talks covered many topics, but included some interesting CV-related tidbits:</p>
<ul>
<li><a href="https://youtu.be/zt1oiG3Yen0">Intel talked</a> about some of their tools for helping with computer vision in the cloud</li>
<li><a href="https://youtu.be/8sRluA_hrtc">Microsoft showed</a> some cool videos showing Mixed Reality broadcasts with the HoloLens</li>
</ul>
<p>Then we had a few that were entirely focused on CV.</p>
<h2 id="persondetectioninsidefacebooksportal">Person detection inside Facebook’s Portal</h2>
<p>Facebook recently launched a dedicated video chat device that leverages Facebook Messenger. Portal is mean to be placed in a stationary location inside the home. To make sure it captures the appropriate action, no matter where the call participants are located in the room, it utilizes computer vision identify people and frame them properly.</p>
<p>Facebook is frequently in the news about privacy issues, so a Facebook camera that tracks people has been met with a lot of skepticism. We were lucky that Facebook let Eric Hwang and Arthur Alem talk about the portal implementation at all, even if they weren’t allowed to go into deep detail on most of it. They did show examples of the CV features and discussed the challenges of running their vision algorithms on a constrained device in a latency sensitive application. They also talked a bit about their WebRTC implementation with simulcast and how that applies with user-based video selection and calling to non-Portal Messenger clients.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/LmZV1l65NB4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<p>We also had a few deeper Computer Vision talks from Agora.io and Houseparty. They both focused on used CV algorithms to improve media quality, so I will cover them in the next section.</p>
<h1 id="rtcoptimization">RTC Optimization</h1>
<p>In our <a href="https://krankygeek.com/research">report</a>, we were surprised by the relative lack of ML activity for improving media quality and delivery. Talks at the AI-in-RTC made me feel a lot better about this. Houseparty and Agora.io both covered improving video quality and we also had a couple of talks from Callstats.io and RingCentral on using Machine Learning to make better sense of the metadata that accompanies calls.</p>
<h2 id="superresolutiononrealtimecommunicationsvideo">Super-Resolution on Real Time Communications Video</h2>
<p>In the day’s most technical talk, Shawn Zhong of Agora went into details on their super resolution machine learning model. <a href="https://en.wikipedia.org/wiki/Super-resolution_imaging">Super-resolution imaging</a> is a set of techniques for improving how an image looks by enhancing a its resolution. Your camera always captures at a high resolution, but in RTC this resolution is reduced by the video encoder to match available bandwidth and processing constraints. The image quality is often then further reduced due to packet loss during transmission. Super-resolution aims to restore the video quality back to the original before the degradation.</p>
<p>Tony talked about how they use a <a href="https://en.wikipedia.org/wiki/Generative_adversarial_network">Generative and Adversarial Network (GAN)</a> to address this problem. He spoke in detail on how GAN’s work here and the challenges of optimizing heavy Deep Neural Networks (DNN) for use on a typical mobile device.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/Y7p0ye0mrBE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<h2 id="opensourcemltoimprovevideoquality">Open Source ML to Improve Video Quality</h2>
<p>Gustavo Garcia Barnado previously analyzed the use of Google’s ML kit to provide <a href="https://webrtchacks.com/ml-kit-smile-detection/">smile detection on iOS for webrtcHacks</a>. For his Kranky Geek AI in RTC  talk, Gustavo shared some experiments he did using machine learning to improve video quality. This is super-resolution again. Unlike Shawn who approached the super-resolution program from a low-level Machine Learning perspective, Gustavo used an Artifacts Reduction Convolutional Neural Network (AR-CNN) model he found for Tensorflow to see what would happen. When it worked they migrated it to work on CoreML for Apple devices.</p>
<p>If you are a Machine Learning expert like Shawn, you can build an optimized end-to-end model. But if you aren’t an ML PhD, Gustavo shows how you can still get great results leveraging open source libraries.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/rEsC8pLaVSE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<h2 id="analyzingcallstatisticswithunsupervisedlearning">Analyzing Call Statistics with Unsupervised Learning</h2>
<p>For WebRTC deployments, the <a href="https://developer.mozilla.org/en-US/docs/Web/API/RTCStats">RTCStats API</a> is a great way to collect a lot of data. However, in many ways it has become too good and it is easy to get lost in all the data collected. Varun Singh of Callstats showed how they used <a href="https://en.wikipedia.org/wiki/Principal_component_analysis">Principal Component Analysis (PCA)</a> and <a href="https://en.wikipedia.org/wiki/T-distributed_stochastic_neighbor_embedding">t-distributed Stochastic Neighbor Embedding (t-SNE)</a> for clustering users with similar issues together. Varun walks through a real word example where they were able to identify some specific ISPs that were causing issues for users across different WebRTC apps.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/4VeUiPbXf7c" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<h2 id="usingmltonormalizecallqualitydata">Using ML to normalize call quality data</h2>
<p>In VoIP systems, Call quality is generally measured by end user and intermediary devices using a metric known as <a href="https://en.wikipedia.org/wiki/Mean_opinion_score">Mean Opinion Score (MOS)</a>.   RingCentral noticed all of these devices measured MOS slightly differently. This created a lot of operational headaches whey trying to identify and troubleshoot call quality issues. Curtis Lee Peterson of RingCentral’s operations team talked through how they took more than a million data records and ran them through a Tensorflow model to provide normalized, accurate MOS data.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/QlJSBPpTx34" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<h1 id="more">More?</h1>
<p>See the complete Kranky Geek AI in RTC playlist <a href="https://www.youtube.com/playlist?list=PL4_h-ulX5eNfaM0QM5r-PewWaY_zgLH7b">here</a>. The list incudes a few additional WebRTC-oriented talked not incuded above including Google's annual talk and one from Discord describing how they adapted the WebRTC stack to handling 2.8 Million concurrent callers in their gamer chat app.<br>
Make sure to <a href="https://www.youtube.com/channel/UC9qvM7eiCvDRO5Sm28byZiw?sub_confirmation=1">subscribe</a> for future videos.</p>
<p>If you are looking for market research, we are running a special discount on the <a href="https://krankygeek.com/research">AI in RTC report</a>. <a href="https://chadwallacehart.com/contact/">Contact me</a> about that for more info.</p>
<p>Our next Kranky Geek event in San Francisco is scheduled for November 15, 2019, so mark your calendars now!</p>
<hr>
<h3 id="abouttheauthor">About the Author</h3>
<p>Chad Hart is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and strategy advisory helping to advance the communications industry. He recently co-authored a study on AI in RTC - check it out at <a href="https://krankygeek.com/research">krankygeek.com/research</a>.(<a href="https://krankygeek.com/research">https://krankygeek.com/research</a>).</p>
<hr>
<h3 id="remembertosubscribefornewpostnotificationsandfollowcogintai">Remember to <a href="https://cogint.ai/subscribe/">subscribe</a> for new post notifications and follow <a href="https://twitter.com/cogintai">@cogintai</a>.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[SignalWire's Dialogflow Connector]]></title><description><![CDATA[Review and walkthrough of SignalWire's Dialogflow connector that lets you pick phone numbers and dial into the voicebot. SignalWire is a new CPaaS offer from the Freeswitch team]]></description><link>https://cogint.ai/calling-into-dialogflow-with-signalwire/</link><guid isPermaLink="false">5b997fdb04a8c82a4f530d47</guid><category><![CDATA[voicebot]]></category><category><![CDATA[guide]]></category><category><![CDATA[review]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Thu, 13 Sep 2018 10:59:48 GMT</pubDate><media:content url="https://cogint.ai/content/images/2018/09/switchboard-operator.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2018/09/switchboard-operator.jpg" alt="SignalWire's Dialogflow Connector"><p>In my <a href="https://cogint.ai/dialogflow-phone-bot/">last post</a> I reviewed Dialogflow's new Phone Gateway feature. Dialogflow makes it dirt simple to add a phone number to a bot, but the Phone Gateway feature is pretty limited (and it is in Beta after all).</p>
<p>What if you like Dialogflow for building your bot/IVR, but do not want to use Google's numbers or PSTN gateway service? There are a growing number of third-party alternatives looking to expand voicebot capabilities into business IVRs. Google <a href="https://cloud.google.com/blog/products/gcp/transforming-the-contact-center-with-ai">announced a number of telephony platform partners</a> that are interfacing with it as part of Google's Contact Center AI initiative. However, these programs are all in Beta with very limited access and appear to largely be aimed at existing large contact center customers of these companies. VoxImplant and SignalWire are 2 CPaaS options that started down this path much earlier and have products they can show publicly.</p>
<p>Alexey of VoxImplant gave a preview of their Dialogflow Connector in an <a href="https://cogint.ai/making-ivrs-not-suck-with-dialogflow-alexey-aylarov/">earlier post here</a>. A review of SignalWire was a logical next step, so here it is.</p>
<p>SignalWire is from the team behind <a href="https://freeswitch.org">FreeSWITCH</a>, the popular open source telephony platform. SignalWire is a CPaaS based on a lot of that software that has been tuned for purpose. It was only launched late this July.  It is currently in a closed Beta, but that should be ending within weeks. Developers can request a login at <a href="https://signalwire.com">signalwire.com</a></p>
<p>I provide a qualitative, less-technical assessment of SignalWire's Dialogflow connector in the first part below and a short walkthrough further down.</p>
<h1 id="signalwireassessment">SignalWire Assessment</h1>
<h2 id="thegood">The Good</h2>
<p>I see a few benefits in using SignalWire's connector vs. Dialogflow's Phone Gateway.</p>
<h3 id="multiplenumbers">Multiple numbers</h3>
<p>You can add as many phone numbers to your agent as you want. The Dialogflow Phone Gateway only lets you pick one per agent. Multiple numbers for the agent allows you to localize them for a geography. Running multiple numbers on the same endpoint is also critical for call tracking in campaigns where specific phone numbers are tied to ads.</p>
<h3 id="potentialsmsintegration">Potential SMS integration</h3>
<p>Dialogflow provides their Phone Gateway for voice calling and a number of options for SMS interaction. Surprisingly, there is no way to combine voice and SMS on the same number with any of their standard integration options. SignalWire does not have SMS-to-Dialogflow-chatbot functionality built in natively, but this is possible to build via their API interfaces (in what I would say would take a few hours if you know the Dialogflow APIs).</p>
<h3 id="pricing">Pricing</h3>
<p>Currently SignalWire only charges $0.005 per minute for the call and their phone numbers are currently free. If you want a permanent number that doesn't expire after 30 days, Dialogflow charges you $0.05 per minute. The reality is SignalWire is not charging users for their Dialogflow fees. I do not see how this is sustainable, but the SignalWire team assures me they will be competitive with Dialogflow's Phone Gateway rate. In any case, you can't beat the price for now - ⅒ of the Dialogflow <em>Enterprise Essentials</em> plan price.</p>
<h3 id="telephonylogs">Telephony logs</h3>
<p>Dialogflow's GUI lets you see intent history and they have the ability to export their logs to Stackdriver on Google Cloud or <a href="https://chatbase.com">Chatbase</a>. I have not found an easy way to just see sessions that came in over the phone or to filter them by phone number. SignalWire gives you logging by phone number with a history of the interaction. Unfortunately that interaction does not include the Dialogflow responses. Still, the provided speech detection inputs are helpful for debugging and identifying problem callers.</p>
<h3 id="nogooglevoiceintegrationissues">No Google Voice integration issues</h3>
<p>This is not a problem for most, but its a huge one for me. Dialogflow doesn't work when you call it from a Google Voice number. I don't have good reception in my office and generally only use Google Voice, making testing of the Dialogflow Phone Gateway difficult. Its nice to be able to call the agent number and have it work no matter how I dial.</p>
<h2 id="bugs">Bugs</h2>
<p>I ran into a few bugs that I reported. To be fair, SignalWire is in a closed Beta and I suspect most of these issues will be quickly addressed.</p>
<h3 id="agentvoice">Agent voice</h3>
<p>Dialogflow lets you choose from multiple Text-to-Speech (TTS) voices in their audio responses. Unfortunately this is limited to US-English if you have the phone gateway. SignalWire currently only uses the default US voice. So if you set your Dialogflow bot to something different than the default you won't hear that voice. The SignalWire team says a fix on this is imminent.</p>
<h3 id="sayawelcomemessagerepeatsonsilence">Say a welcome message repeats on silence</h3>
<p>The &quot;Say a welcome message&quot; field you set in the SignalWire agent setup automatically repeats when it the user does not say anything for several seconds. This make it a more useful reminder prompt when the user goes silent. Dialogflow has some of those capabilities built in already, so I am not so sure another set of prompts outside bot framework will be helpful. Even at call start, when SignalWire says this message will be played, I think it is better to just let the Dialogflow Welcome intent handle the transition. Fortunately you can just turn this off if you don't like it.</p>
<h3 id="unverifiedappwarning">Unverified app warning</h3>
<p>When authenticating with Dialogflow, it gives an unverified app warning as shown below:<br>
<img src="https://cogint.ai/content/images/2018/09/1.2-not-verified.png" alt="SignalWire's Dialogflow Connector"><br>
The SignalWire team say this is a recent bug they are working with Google to fix it.</p>
<h2 id="conclusion">Conclusion</h2>
<p>This was all very easy to setup. Then again the Dialogflow Phone Gateway was easy too. So why bother with using an external party like SignalWire? I think the most compelling reason to use SignalWire is the ability to influence its development. Team behind it does custom development, so if you really need something you can pay them to do it. That's not an option with Google.</p>
<p>In addition, Google is not a CPaaS and is unlikely to go too deep down that path (thus partnering with some telephony platforms instead). Just being able to add some programmability to the process is also helpful vs. what Dialogflow has today. SignalWire's programmability on Dialogflow is pretty limited today, but its not hard to see how this will change quickly the way they have their system setup. The SignalWire team tells me they will be adding more logic commands for Dialogflow to let you invoke it like the other recording and conferencing parts of their offer. That would let you make a recording of the whole call or join an agent into the Dialogflow session.</p>
<p>Overall I think there is a lot of potential for this category. There are a lot of crappy IVRs with complex telephony environments. If you want to add a voicebot to these environments, some kind of RTC-bot gateway is required, and that is what we are starting to see.</p>
<h1 id="signalwirewalkthrough">SignalWire Walkthrough</h1>
<p>First you will need to setup an account. After a few confirmation emails and some <em>Space</em> and <em>Project</em> setup you should come to a screen like this where you can select a Dialogflow agent.<br>
<img src="https://cogint.ai/content/images/2018/09/1.1-DialogFlow-Agents.png/resize?w=1200" alt="SignalWire's Dialogflow Connector"></p>
<p>If you click on the import you'll need to authenticate to your Dialogflow account. As mentioned above, you might get a &quot;This app isn't verified&quot; screen where you need to click on Advanced to proceed. Assuming you trust the SignalWire team up to this point, it's fine to proceed.</p>
<p>After that you should see the list of Agents:<br>
<img src="https://cogint.ai/content/images/2018/09/1.3-Import-Agents.png/resize?w=1200" alt="SignalWire's Dialogflow Connector"></p>
<p>Just select the ones you want to make available and then configure them in this screen:<br>
<img src="https://cogint.ai/content/images/2018/09/1.4-setup-phone-agent.png/resize?w=1200" alt="SignalWire's Dialogflow Connector"><br>
Here you have the option of saying a welcome message and identifying some text to feed to Dialogflow when the call starts. As mentioned earlier, the &quot;Say a Welcome Message&quot; is better used as a silence prompt if you use it at all. In my bot, &quot;Hello&quot; and similar phrases are tied to the <em>Default Welcome Intent</em> in Dialogflow. Adjust or turn off as needed for yours.</p>
<p>That's all you need to do to connect to Dialogflow; now we just need to get a phone number and assign it to the Dialogflow agent. That is also super simple - just go to <em>Phone Numbers</em> and enter an area code:<br>
<img src="https://cogint.ai/content/images/2018/09/2.1-new-phone-number.png/resize?w=1200" alt="SignalWire's Dialogflow Connector"><br>
Select the one you want to <em>Buy</em> - as mentioned above, its free for now, so there is no buying.</p>
<p>Then you'll come to a new phone number setup screen. Again, no rocket science here - just fill in the descriptions, pick &quot;A DialogFlow Agent&quot; for handling incoming calls, and select the appropriate agent.<br>
<img src="https://cogint.ai/content/images/2018/09/2.32-new-phone-number-setup.png/resize?w=1200" alt="SignalWire's Dialogflow Connector"></p>
<p>Make a call to your number and verify it works. That's it!</p>
<hr>
<h3 id="abouttheauthor">About the Author</h3>
<p>Chad Hart is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and strategy advisory helping to advance the communications industry. He recently co-authored a study on AI in RTC - check it out at <a href="https://krankygeek.com/research">krankygeek.com/research</a>.</p>
<hr>
<h3 id="remembertosubscribefornewpostnotificationsandfollowcogintai">Remember to <a href="https://cogint.ai/subscribe/">subscribe</a> for new post notifications and <a href="https://twitter.com/cogintai">follow @cogintai</a>.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[How to make a dial-in IVR with Dialogflow]]></title><description><![CDATA[A review of Dialogflow's new phone gateway and knowledge connector with a walkthrough on how to use them to build a conversational voicebot IVR in minutes.]]></description><link>https://cogint.ai/dialogflow-phone-bot/</link><guid isPermaLink="false">5b85af1004a8c82a4f530d32</guid><category><![CDATA[voicebot]]></category><category><![CDATA[dialogflow]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Thu, 30 Aug 2018 11:21:52 GMT</pubDate><media:content url="https://cogint.ai/content/images/2018/08/header-image-1.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2018/08/header-image-1.png" alt="How to make a dial-in IVR with Dialogflow"><p>Continuing on my quest to see all clunky, hierarchical IVRs die, I have been experimenting with Dialogflow's new <em>Phone Gateway</em> and <em>Knowledge Connectors</em> that were <a href="https://developers.googleblog.com/2018/07/new-dialogflow-features-at-cloud-next.html">launched in late June</a> at CloudNext. The <em>Knowledge Connector</em> extracts data out of a Frequently Asked Questions (FAQ) document and makes it available for the bot to use in its responses. The <em>Phone Gateway</em> includes lets you connect any Dialogflow bot to a phone line. Together, these two features make it relatively simple to build a voicebot replacement to a informational IVR with the added bonus that the bot can be reused on other media too.</p>
<p>Read below for:</p>
<ul>
<li>some background on Dialogflow and the IVR use case,</li>
<li>a detailed walkthrough of how to do it in minutes, and</li>
<li>some of my learnings and potential next steps.</li>
</ul>
<h1 id="conceptsandingredients">Concepts and Ingredients</h1>
<p>Why is replacing a traditional IVR with a voicebot better? What are these new Dialogflow features exactly? Let's review some of the core principals first.</p>
<h2 id="menusvsintents">Menus vs. Intents</h2>
<p>Traditional IVR systems always use menus because that is the only way they could navigate through a bunch of explicit options. In this approach, the number of items in a given menu were limited by 2 things:</p>
<ol>
<li>The number of DTMF keys on the phone</li>
<li>User patience to listen through a list of options and then make a selection</li>
</ol>
<p>Voice recognition - where users can speak their options - is supplementing the DTMF entry. However, that technology isn't everywhere and the main challenge of how many menu items can a user remember before they forget and have to go back through the menu still remains. This means there is pressure to keep each menu short. To fit all the options needed under this constraint, IVRs must have a multi-layered menu hierarchy.</p>
<p>Imagine if people had conversations like this. When someone calls a receptionist at a business they don't spout out a menu, they ask &quot;how can I help you&quot; and then response with the appropriate answer. Intent-based Natural Language Understanding (NLU) systems that voicebots interact like a real person would. They take what the user says - their <em>utterance</em> - and match it to an <em>intent</em> which indicates a response. Conversational bot systems are actually much more dynamic than this with follow-on intents, response variations, and other options for slot-filling, but the core concept is the same.</p>
<p><img src="https://cogint.ai/content/images/2018/08/ivr-menu-vs-flat-voicebot-side-by-side.png" alt="How to make a dial-in IVR with Dialogflow"></p>
<h2 id="dialogflow">Dialogflow</h2>
<p>As it competes with Amazon's Alexa, Google has been launching a bunch of new features for <a href="https://dialogflow.com/">Dialogflow</a>, its natural language processing and bot builder tool. Unlike <a href="https://developers.google.com/actions/">Actions for Google</a>, which only lets you create bots for the Google Assistant, Dialogflow has integrations with a wide variety of platforms including Alexa, Cortana, many popular chat platforms, and now the telephone network.</p>
<h2 id="informationalinteractivevoiceresponsesystems">Informational Interactive Voice Response Systems</h2>
<p>Interactive Voice Response (IVR) systems have become the bane of telecoms, but they were once a convenience for users. They help direct users and reduce time dealing with multiple transfers and clueless operators. The main primary functions of the IVR come down to:</p>
<ol>
<li>Directing callers to the right person</li>
<li>Offloading agent (the person answering the phone) by providing or collecting information before the agent gets on</li>
</ol>
<p>Dialogflow can help with both of these, but here I am going to focus on the offloading part. Large business like banks have sophisticated systems that let you make self-serve transactions (today as an alternative to doing that on the web or an app).  Many smaller organizations still have IVRs that provide basic information - opening hours, addresses, etc. Even more sophisticated systems usually have pieces of their IVR that does the same thing. For this post, I am going to focus on these &quot;Informational&quot; elements that can be provided by an IVR.</p>
<h2 id="dialogflowknowledgeconnector">Dialogflow Knowledge Connector</h2>
<p>Web-based Frequently Asked Questions (FAQs) have become a popular content format on the web mainly because of the way Google search provides <a href="https://support.google.com/webmasters/answer/6229325">featured snippets</a>. FAQs are usually easy to write and contain a lot of good information. The problem is FAQs are often not displayed prominently on a website so often primarily for the search engines. In addition, having them doesn't help if someone calls in on the phone unit now.</p>
<p>The concept of taking FAQ content and adding to a bot is straight forward, but the work of populating that data is tedious.  Microsoft had a tool called called <a href="https://www.qnamaker.ai/">QnA Maker</a> that helps to automatically parse Q&amp;A style documents to populate a bot. Just point it at a webpage or document and it uses NLP technology to suck in the data.</p>
<p>This summer Google released something similar in Dialogflow called <em>Knowledge Connectors</em>.</p>
<h2 id="phonegateway">Phone Gateway</h2>
<p>The other big piece here that Google recently launched is the Phone Gateway. I have talked a few times <a href="https://cogint.ai/tag/voicebot/">on this blog</a> about voicebot gateways from vendors like <a href="https://voximplant.com/solutions/dialogflow-connector">VoxImplant</a> and <a href="https://signalwire.com">Signalwire</a> that added a telephony gateway to Dialogflow. Now, much like <a href="https://www.ibm.com/us-en/marketplace/voice-gateway">IBM</a>, Google has added its own Phone Gateway.</p>
<p>Google provides access to numbers directly from within Dialogflow interface. If all you care about is connecting a phone number to Dialogflow, I don't think anyone could offer a simpler way to do it. Better yet, if you just need a number for testing Google gives them away for free for 30-days.</p>
<p>If you want a permanent number they sell those too - you'll just need to sign-up for their Enterprise plan which will increase your bot price from totally free to $0.05/minute to $0.075/minute depending on <a href="https://cloud.google.com/dialogflow-enterprise/pricing">the plan and number type</a>.</p>
<p>Presumably their Contact Center AI <a href="https://cloud.google.com/blog/products/gcp/transforming-the-contact-center-with-ai">telephony partners</a> provide something similar to their customers from their own interfaces.</p>
<h1 id="howtoguide">How To Guide</h1>
<p>Here is a step-by-step guide on how to:</p>
<ul>
<li>create your agent,</li>
<li>add the phone gateway integration,</li>
<li>import a number of FAQs with the knowledge connector,</li>
<li>make the bot more conversational,</li>
<li>transfer calls to a human.</li>
</ul>
<p>Dialogflow has many features and I am not going to go into most of them. Also, this is just a quick and dirty demonstration, so remember this is a lot of tweaking and improvement you would want to make in a real bot.</p>
<h2 id="getanaccountcreateanagent">Get an account, create an agent</h2>
<p>If you don't have a Dialogflow account already, go to <a href="https://dialogflow.com">dialogflow.com</a>, sign-in with a Google account, and pick your account settings.</p>
<p>If it is a new account, you will be forced to create an agent:<br>
<img src="https://cogint.ai/content/images/2018/08/2---Create-an-Agent.png/resize?w=1200" alt="How to make a dial-in IVR with Dialogflow"></p>
<p>For reasons I will explain later, I decided to make a Star Wars movie hotline.</p>
<h2 id="edityourdefaultintents">Edit your default intents</h2>
<p>Next you will come to an Intents screen (or click on Intents on the left).<br>
<img src="https://cogint.ai/content/images/2018/08/3---Default-Intents.png/resize" alt="How to make a dial-in IVR with Dialogflow"></p>
<p>The <em>Default Welcome Intent</em> is the first thing your bot will say. The <em>Default Fallback Intent</em> is what the bot says if it does not understand the input.</p>
<p>Click on <em>Default Welcome Intent</em>. You'll see a bunch of training phrases and then you will see a bunch of Default text responses. I modified mine to respond with some statements prompting the user to ask about Star Wars:<br>
<img src="https://cogint.ai/content/images/2018/08/4.1---Default-Welcome-Intent.png/resize?w=1200" alt="How to make a dial-in IVR with Dialogflow"></p>
<p>Click on <em>Save</em> and you should see some messages saving <em>Agent Training Started</em> and a completion message soon after.  Once that's complete, you can do a quick test by typing in your query in the upper right. It should return with one of your responses. Note how you can enter nearly any greeting and it will respond. If you have a non-standard greeting it does not pick up, just add that to the <em>Training Phrases</em>.</p>
<h2 id="setupthephonegateway">Setup the Phone Gateway</h2>
<p>Before we go any further let's setup our Phone Gateway and make sure we can call into our bot. Click on the sandwich menu icon in the upper left and click on <em>Integrations</em>. There are a lot here, but since the scope of this walk-through is an IVR voicebot, pick the <em>Dialog Phone Gateway</em> icon. Then you'll get a screen like this:<br>
<img src="https://cogint.ai/content/images/2018/08/5---Phone-Gateway-Setup.png/resize" alt="How to make a dial-in IVR with Dialogflow"></p>
<p>This is where you can pick a phone number and other options. The menu only lets me pick English, but I assume other language options will be available over time. Optionally you can enter some area codes that you want your phone number to start with. Pick a phone number, click create, wait for the confirmation and then close out of there.</p>
<p>That's it - now you have a phone number you can use for 30 days. Per the <em>Note</em> in the screen above, if you want a number for longer than that then you need to sign up for the Enterprise Edition.</p>
<p>Give your number a call and you should hear your welcome intent. It should respond to greetings, but not much else, which isn't very useful so let's move to the next phase.</p>
<h2 id="knowledgeconnectors">Knowledge connectors</h2>
<p>Usually programming a bot involves manually create a bunch of intents and responses like we say on the <em>Default Welcome Intent</em> screen. Dialogflow has some <em>Prebuilt Agents</em> you can modify if they happen to fit your use case. This saves some time, but it is possible to skip the Intent entry step entirely using <em>Knowledge Connectors</em>. As explained earlier <em>Knowledge Connectors</em> lets you populate the Intents and responses automatically from a Frequently Asked Questions (FAQ) document.</p>
<h3 id="enablebetafeatures">Enable Beta Features</h3>
<p>Google's is in Beta, so we will need to enable the feature. To do this click on the gear icon next to your bot name in the upper left and then click the slider for <em>Enable beta features and APIs</em> and click save:<br>
<img src="https://cogint.ai/content/images/2018/08/6---enable-beta-features.png/resize" alt="How to make a dial-in IVR with Dialogflow"></p>
<h3 id="addknowledgebaseurls">Add Knowledge Base URLs</h3>
<p>Now head back to the left menu and pick <em>Knowledge</em> and then <em>Create Knowledge Base</em>.</p>
<p>Then you'll need to pick a name for your knowledge set.</p>
<p>After that you will see a link to create a knowledge document.</p>
<p>From there you will need to fill in the form with a document name, <em>FAQ</em> for the knowledge type and <em>text/html</em> if you are using a URL, followed by the URL itself:<br>
<img src="https://cogint.ai/content/images/2018/08/7---Knowledge-Create-New-Document.png/resize" alt="How to make a dial-in IVR with Dialogflow"></p>
<p>Click <em>Create</em> and a few moments later you should see the document in the list.<br>
<img src="https://cogint.ai/content/images/2018/08/8---Knowledge-document-created.png/resize" alt="How to make a dial-in IVR with Dialogflow"></p>
<p>If you don't see the document, jump down to my issues section below. If you do see the document, you should be able to open it and see the full Q&amp;A. That screen will also let you disable individual Q&amp;A pairs.</p>
<p>I went back and added a bunch more FAQ documents to round out my knowledge set. Make sure to hit save when you're done.</p>
<p>Give your number a call and ask it some questions related to the content in your FAQ's and you should get answers. I found I had to turn up the preferences to return Knowledge results in the main <em>Knowledge</em> tab for better results:<br>
<img src="https://cogint.ai/content/images/2018/08/9---Knowledge-results-preference.png/resize" alt="How to make a dial-in IVR with Dialogflow"></p>
<p>Once you start adding other intents this will need to be tested and adjusted more.</p>
<h2 id="addsmalltalk">Add Small Talk</h2>
<p>Without any real data entry, your bot should be in decent shape, but it is hardly conversational outside of the narrow FAQ documents you gave it. Dialogflow has another feature called <em>Small Talk</em> that provides default responses to popular filler discourse, like &quot;thank you&quot;.</p>
<p>Go over to <em>Small Talk</em> in the menu and enable it.</p>
<h2 id="realintents">Real intents</h2>
<p>We made it pretty far without doing anything complicated, but our bot is missing a few features you would have:</p>
<ol>
<li>The ability to hang-up</li>
<li>Option to talk to a human</li>
</ol>
<h3 id="hangupintent">Hang-up intent</h3>
<p>We never setup a way to end the conversation. The user can hang-up, but the usual protocol is to say some kind of farewell first before hanging up. This is easy to add and is included in most of the <em>Prebuilt Agents</em> if you started that way.</p>
<p>Go to <em>Intents</em>. Create a new intent and call it something like &quot;Hangup&quot; and then add some farewell training phrases. Then, customize your Text response and make sure to click the <em>Set this intent as end of conversation</em>.<br>
<img src="https://cogint.ai/content/images/2018/08/10---Hang-up-intent.png/resize?w=1200" alt="How to make a dial-in IVR with Dialogflow"></p>
<p>Make sure to do some tests. I found phrases like &quot;I'm finished&quot; matched some of my knowledge base articles. Adjust the Knowledge results preference slider if you need to.</p>
<h3 id="transfertooperatorintent">Transfer to operator intent</h3>
<p>To make this work cleanly we are going to add a new intent so the user can signal they want to talk to a human. Then we will make a follow-up intent to confirm and transfer the call. Technically this could be done in one step, but since this was meant to be a FAQ bot we don't want users to be transferred accidentally.</p>
<p>Click on the plus sign next to <em>Intents</em> and create an intent called Operator. Add some &quot;speak to a person&quot; training phrases and add a confirmation prompt as a response.<br>
<img src="https://cogint.ai/content/images/2018/08/11---Operator-intent.png/resize?w=1200" alt="How to make a dial-in IVR with Dialogflow"></p>
<p>As always, make sure to save, let it train, and then test.<br>
Now go back to the <em>Intents</em> screen, hover over the operator intent you just made and create a follow-up intent:<br>
<img src="https://cogint.ai/content/images/2018/08/12---Operator-follow-up.png/resize" alt="How to make a dial-in IVR with Dialogflow"></p>
<p>Select &quot;yes&quot; from the drop down menu - this will auto-populate confirmation intent phrases.</p>
<h3 id="setittodialout">Set it to dial out</h3>
<p>Lastly, go to the <em>Responses</em> section, click the &quot;+&quot; and select Telephony.</p>
<p>Click on &quot;ADD RESPONSES&quot; and select &quot;Transfer call&quot;. Then just put your phone number in the box.<br>
<img src="https://cogint.ai/content/images/2018/08/13---Transfer-call---redacted.jpg/resize" alt="How to make a dial-in IVR with Dialogflow"><br>
Give your voicebot a call and make sure it works.</p>
<h2 id="tipstricksandissues">Tips, Tricks, and Issues</h2>
<p>It is important to remember that the <em>Dialogflow Phone Gateway</em> and <em>Knowledge Connector</em> are in Beta. Google's &quot;beta&quot; usually just means &quot;new&quot; but I encounted a bunch of bugs and glitches so it see this is really in Beta.</p>
<h3 id="dontusegooglevoice">Don't use Google Voice</h3>
<p>Don't use a Google Voice number with the <em>Phone Gateway</em> - it doesn't work.</p>
<blockquote>
<p>Note: Calling the gateway from a device using Project Fi, Google Voice, or Google Hangouts is not currently supported.</p>
</blockquote>
<p>This was painful for me since I do not have cellular reception in my office and generally use my Google Voice number to dial over VoIP. Ironically I ended up using another bot - Alexa on my Amazon Echo - to place test PSTN calls to the voicebot.</p>
<h3 id="parsingfaqdocuments">Parsing FAQ documents</h3>
<p>The Knowledge connector was super finicky for me. I originally wanted to build voicebot on the <a href="https://www.krankygeek.com/ai-in-rtc-faq/">AI in RTC report FAQ</a> but I could not get it to parse the document. I kept getting &quot;failed to crawl&quot; errors, despite several attempts to restructure the document in several ways.</p>
<p>That FAQ built in Wordpress. Other FAQs I made in WordPress in the same manner parsed just fine, so I am not sure what it is.<br>
<img src="https://cogint.ai/content/images/2018/08/Failed-to-crawl.png/resize" alt="How to make a dial-in IVR with Dialogflow"></p>
<p>I recommend just using a CSV file as I'll discuss below.</p>
<h3 id="nointerruptingplayback">No interrupting playback</h3>
<p>A lot of the answers I got off of the IMDb movie FAQs were very long. Unfortunately I was not able to find a good way to &quot;Cancel&quot; in the middle of playback. On the Google Assistant you can always do an &quot;OK Google&quot; to interrupt the response playback, but I did not see a way to implement that mechanism on the Phone Gateway.</p>
<p>Also, for the really long ones, occasionally the intent recognizer started up again before the previous text-to-speech response even finished. I suspect this is a bug.</p>
<h3 id="keepfaqresponsesshort">Keep FAQ responses short</h3>
<p>In most cases users don't want to hear a bot drone on, especially when they can't easily cancel. It is supposed to be a dialog after all, not a lecture. For this reason I recommend keeping the FAQ responses to a few sentences vs. a few paragraphs.</p>
<p>Unfortunately there is no easy way to break up long responses to allow the user to choose to continue or not. You could do this if you converted all the FAQs questions to intents and then break them up to a series of follow-up intents. Dialogflow does allow you to easily convert a FAQ to an intent. You could use this feature to break up the text into follow-up intents, but that involves a lot more work and assumes your text is already structured in a manner that makes sense to interrupt in the middle and say &quot;would you like to hear more&quot;. Alternatively you could directly interface with Dialogflow's APIs and webhooks for more control, but that requires a developer.</p>
<h3 id="noeditingfaqsindialogflowsousecsvs">No editing FAQs in Dialogflow so use CSV's</h3>
<p>Unlike Microsoft's QnA Maker, there is no way to edit or add the FAQ items within the GUI after they are imported. Given all the hassle I had parsing HTML pages, I think its easier to scrape the page content into a CSV where you can edit the text outside of Dialogflow and reimport. That also gives better controls over content versioning.</p>
<h3 id="sometimestheinterfaceisslowbepatient">Sometimes the interface is slow, be patient</h3>
<p>I found in a bunch of cases changes wouldn't stick. It seems sometimes the interface is slow. Make sure to wait for the &quot;Agent training completed&quot; toast message before testing something new.</p>
<p>Other times I would get random 500 errors. They eventually went away on their own.<br>
<img src="https://cogint.ai/content/images/2018/08/500-error.png/resize" alt="How to make a dial-in IVR with Dialogflow"></p>
<h2 id="conclusions">Conclusions</h2>
<p>I tried creating another bot for the <a href="https://www.krankygeek.com/ai-in-rtc-faq">AI in RTC report FAQ</a>. Since I still could not import from the URL, it took me about 10 minutes to copy and reformat the contents in a CSV file.  From there it took me about 25 minutes to walk through these steps, including testing, to make it work. It is very far from perfect but not too bad as a base to get started in a short period of time.</p>
<p>Give it a try at <a href="tel:16173807150">+1 617-380-7150</a> and see how it works for you. In the mean time I will think about turning this into a proper voicebot!</p>
<hr>
<p>Chad Hart is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and strategy advisory helping to advance the communications industry. He recently co-authored a study on AI in RTC - check it out at <a href="https://krankygeek.com/research">krankygeek.com/research</a>.</p>
<hr>
<h3 id="remembertosubscribefornewpostnotificationsandfollowcogintai">Remember to <a href="https://cogint.ai/subscribe/">subscribe</a> for new post notifications and <a href="https://twitter.com/cogintai">follow @cogintai</a>.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[AI in RTC Report Highlights: Speech Analytics & Voicebots show the most promise]]></title><description><![CDATA[Highlights and key findings from the recently released Kranky Geek Research AI in RTC study. Speech Analytics & Voicebots show the most promise. Computer vision and RTC optimization lag behind in adoption. ]]></description><link>https://cogint.ai/ai-in-rtc-report-highlights/</link><guid isPermaLink="false">5b7cd6ab04a8c82a4f530d23</guid><category><![CDATA[analysis]]></category><category><![CDATA[speech analytics]]></category><category><![CDATA[computer vision]]></category><category><![CDATA[voicebot]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Wed, 22 Aug 2018 13:26:52 GMT</pubDate><media:content url="https://cogint.ai/content/images/2018/08/intro-picture.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2018/08/intro-picture.jpg" alt="AI in RTC Report Highlights: Speech Analytics & Voicebots show the most promise"><p>We hear it all the time - Machine Learning (ML) and its use in creating Artificial Intelligence (AI) applications is having a profound application on many industries.  <a href="https://cogint.ai/ai-in-rtc-report-highlights/bloggeek.me">Tsahi Levi-Levent</a>, blogger and one of the co-organizers with me in the Kranky Geek event series decided to team up to do a deep study on the application of Artificial Intelligence in Real Time Communications (AI in RTC). After a couple months of research, many dozens of conversations, and analyzing hundreds of products we put our findings into a <a href="https://krankygeek.com/research">147-page report</a>. See below for more on the study and some of my take-aways.</p>
<h2 id="aboutthestudy">About the Study</h2>
<p>From the outset, we decided to focus on four domains:</p>
<ul>
<li><strong>Speech Analytics</strong> – converting speech to text (STT) (aka ASR or transcription) and analyzing the waveform and converted text. I had done a lot of work here launching a speech analytics service and was familiar with the new, burgeoning ecosystem here.</li>
<li><strong>Voicebots</strong> – automated programs that interact with users in a conversational dialog using speech as input and output like many IVR systems and  Amazon’s Alexa. Like almost everyone, I hate IVR’s so I was very interested to see how advancements in this tech could make IVR’s suck less. I had also previously investigated the use of using voicebots in conference calls to help control the bridge and was wanted to explore this and other use cases.</li>
<li><strong>Computer Vision (CV)</strong> – programs that analyze and understand images and video. I had done a lot of my own <a href="https://webrtchacks.com/tag/computer-vision/">experimentation here on webrtcHacks</a>. Other than some overlay features in social media apps and some virtual name tag demos from Cisco and Microsoft, I wanted to understand why video conferencing providers weren’t doing more with CV</li>
<li><strong>RTC Optimization</strong> – machine learning methods used to improve VoIP media quality or cost performance. I knew the least about this area but given the recent focus on controlling bandwidth and error correction by RTC stack designers, I expected we would find some interesting research on this topic.</li>
</ul>
<p>The only other area outside of these our research uncovered was the use of machine learning for route optimization in the call centers – i.e. determining which agent to pass a given customer to based on the problem, agent expertise, user history, etc. We decided to not investigate this time around because while it can be RTC related, it did not involve processing the media stream and is a more general problem for all customer interactions.</p>
<h3 id="methodology">Methodology</h3>
<p>In addition to our own personal experience and on-going work, we conducted significant primary and secondary research. Our main source of information was company interviews. We identified more than 100 target companies that included:</p>
<ul>
<li><strong>RTC companies</strong> - telcos, CPaaS providers, cloud-based Unified Communications and call center providers</li>
<li><strong>AI companies</strong> – speech analytics, voicebot, computer vision, and other ML-technology vendors</li>
</ul>
<p>In the end we interviewed about 40 of these companies and did deep reviews of the others. To supplement these interviews, we also conducted a web survey where we had 96 unique companies of all varieties respond.</p>
<p><img src="https://cogint.ai/content/images/2018/08/top-ai-drivers-and-inhibitors.jpg" alt="AI in RTC Report Highlights: Speech Analytics & Voicebots show the most promise"></p>
<h2 id="findings">Findings</h2>
<p>These interviews, subsequent analysis, and writing the 147-page report was major time commitment, unfortunately we can’t give everything away for free, but here are some of my take-aways:</p>
<ul>
<li><strong>Speech analytics is where all the action is</strong> – the majority of the companies we covered had some speech analytics initiative.  I was not surprised this was such a popular area based on my recent professional work, but I was discovered many new ones and re-discovered some vendors who have been in this domain for a while.</li>
<li><strong>Voicebots are the next big AI in RTC domain</strong> - the area has perhaps the move immediate potential for RTC apps as voicebot technology by the major cloud vendors is being commoditized and surpassing traditional conversational IVR implementations. The hard part here is integrating conversational AI tech with established telephony environments – I covered that in <a href="https://cogint.ai/vocebot-ai-in-the-call-center/">my last cogint.ai post</a>.</li>
<li><strong>Computer vision hasn’t received much attention</strong> – outside of social media apps, video RTC companies are just starting to look at it and CV-tech companies have been focused on other markets, like <a href="https://bloggeek.me/autonomous-cars-killing-rtc-ai/">autonomous cars</a></li>
<li><strong>Only big cloud vendors do everything</strong> - outside of the major cloud vendors – Amazon, Google, Microsoft, and IBM – the core machine learning technology vendors were only focused on one domain.</li>
<li><strong>No one is using ML in RTC stacks</strong> - with only a couple exceptions – see <a href="https://2hz.ai/">2Hz</a> and some <a href="https://hacks.mozilla.org/2017/09/rnnoise-deep-learning-noise-suppression/">Mozilla research</a> – hardly anyone is leveraging ML to improve their low-level VoIP mechanics.</li>
<li><strong>Lack of ML expertise is an issue for RTC companies</strong> – lack of staff who know and can apply ML was cited as the number 1 inhibitor in our survey.</li>
<li><strong>Promise &amp; peril from partnering with big AI cloud vendors</strong> – the big cloud vendors are also big AI vendors. They are proving the value of AI technologies and democratizing ML tools, meaning it will only get easier for RTC companies to work with them. At the same time Amazon, Google, and Microsoft also offer their own communications products and services. RTC companies without their own ML expertise are in a difficult situation of relying on technology from companies that are growing increasingly competitive.</li>
</ul>
<p>Overall there are more use cases for using AI in RTC than I imagined. At the same time, very little effort has been placed exploring most of these use cases. In addition, most RTC companies are nowhere near the head of the curve when it comes to ML so don’t expect any immediate general market shifts. On the other hand, AI technologies are easier to find on opensource repositories and purchase than ever. Even if there isn’t always an easy path ahead, the potential here is extremely exciting.  Based on our conversations and analysis, I expect AI in RTC will only become a bigger topic with a growing variety of implementations and use cases.</p>
<h2 id="moreinformation">More information</h2>
<p>You can see the full table of contents, list of figures, download a report preview over at <a href="https://krankygeek.com/research">krankygeek.com/research</a>. For those with some budget for market research, we are offering a publication launch discount until September 7. <a href="https://chadwallacehart.com/contact/">Ask me</a> for details or <a href="https://krankygeek.com/research">visit the report site</a> to purchase.</p>
<p><a href="https://krankygeek.com/research"><img src="https://cogint.ai/content/images/2018/08/201808-ai-rtc-cover.jpg" alt="AI in RTC Report Highlights: Speech Analytics & Voicebots show the most promise"></a></p>
<hr>
<p>Chad Hart is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and strategy advisory helping to advance the communications industry.</p>
<hr>
<h3 id="remembertosubscribeandfollowus">Remember to <a href="https://cogint.ai/subscribe/">Subscribe</a> and <a href="https://twitter.com/cogintai">Follow</a> us.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[When will Voice AI Replace the Call Center Voice Channel?]]></title><description><![CDATA[Consumer voicebot technology is becoming common place, so how long until this tech pervades the call center?  We look at the status of telephony-oriented voicebot technology and when it might arrive.]]></description><link>https://cogint.ai/vocebot-ai-in-the-call-center/</link><guid isPermaLink="false">5b3aded304a8c82a4f530d11</guid><category><![CDATA[voicebot]]></category><category><![CDATA[analysis]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Tue, 03 Jul 2018 13:20:49 GMT</pubDate><media:content url="https://cogint.ai/content/images/2018/07/shutterstock_795529078.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2018/07/shutterstock_795529078.jpg" alt="When will Voice AI Replace the Call Center Voice Channel?"><p>Google’s Duplex demo a few months ago forced us to think about a world where we might get a random call from a business and not realize it is a robot making the call. Recent <a href="https://arstechnica.com/gadgets/2018/06/google-duplex-is-calling-we-talk-to-the-revolutionary-but-limited-phone-ai/">reports</a>  have verified that this technology is not just some staged demo and actually works. While there are certainly many sticky implications of this from a consumer perspective, voicebots are already an interesting channel for contact centers. Text-based chatbots have been consuming more and more customer interaction-minutes. With the emergence of improved voice technology, will customer&lt;-&gt;agent voice interactions  decline further in favor of this new kind of voice channel?</p>
<h2 id="voicebot20">Voicebot 2.0</h2>
<p>Voicebots are not really new technology. High-end <a href="https://en.wikipedia.org/wiki/Interactive_voice_response">IVR</a> systems have been able to handle basic voice interactions for years. However, these systems were expensive and therefore tended to be used only in large, well-funded call centers. More recently new machine learning approaches have fueled some major advancements in bot and speech technology which has in turn created a new, rapidly growing ecosystem.</p>
<p>A large part of voicebot tech is actually derived from text-based chatbots.  The main advancement here has been around <a href="https://en.wikipedia.org/wiki/Natural_language_understanding">Natural Language Understanding (NLU)</a> - capabilities that let software match the vagaries of human speech to specific actions while extracting the right objects and figures from speech. The methodologies for programming bots is starting to converge, helping to spread best practices and reduce the learning curve. Platforms like Google’s Dialogflow (formerly api.ai), Wit.ai (owned by Facebook), Microsoft’s LUIS, IBM’s Watson, and Amazon’s Lex provide, along with a few yet-to-be acquired start-ups and some open source projects, provide relatively easy platforms for building bots.</p>
<p>Second, speech recognition and speech synthesis technologies have significantly improved. New machine learning approaches continue to help improve recognition accuracy and make computer speech sound more human. In addition, cloud services started to offer machine learning-centric hardware as a service. These help to run these heavy, specialized loads efficiently at lower costs.</p>
<p><img src="https://cogint.ai/content/images/2018/07/watson-voice-agent-flow.png" alt="When will Voice AI Replace the Call Center Voice Channel?"></p>
<h6 id="examplevoicebotarchitecturefromawatsonvoiceagentsource">Example voicebot architecture from a Watson Voice Agent. <a href="https://voiceagentsbk.mybluemix.net/images/vgaas_image_2.png">Source</a>.</h6>
<p>Lastly, voice assistants and smart speakers – largely from Amazon and Google – have helped to bring bot and speech technologies together. More importantly, they have made a growing portion of the population comfortable interacting with machines via voice through massive exposure. Amazon effectively introduced the smart speaker category in late 2014. By the end of 2017 it had shipped more than 30 million of the devices with Google gaining share behind it. <a href="http://www.pewresearch.org/fact-tank/2017/12/12/nearly-half-of-americans-use-digital-voice-assistants-mostly-on-their-smartphones/">Pew Research reports</a> that more than 46% of American now use digital assistants.</p>
<p>Usage is not ubiquitous, but ubiquity is certainly on the horizon. These new voice platforms need new apps to be successful, so major investment has gone into making it easier to develop voicebots. Often these development tools can be used on more than one voice platform with the assumption there will be multiple overlapping ecosystems.</p>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/fFLWra0S1mrGLB?startSlide=26" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/kleinerperkins/internet-trends-report-2018-99574140" title="Internet Trends Report 2018" target="_blank">Internet Trends Report 2018</a> </strong> from <strong><a href="//www.slideshare.net/kleinerperkins" target="_blank">Kleiner Perkins Caufield &amp; Byers</a></strong> </div>
<h2 id="whyarenttheremorevoicebotsinthecallcenter">Why aren’t there more Voicebots in the Call Center?</h2>
<blockquote>
<p>If voicebot technology is becoming widespread, why do I still need to spend minutes navigating through a typical IVR instead of just saying what I want?</p>
</blockquote>
<p>Even though voicebot technology originally debuted for call centers, the industry overall is well behind what is happening in the consumer market. There are a few reasons for this. One is just the ability to integrate the voice bot platforms with today's telephony systems is difficult. The platforms generally do not offer their own native telephony interfaces (i.e. SIP &amp; RTP). This means you need to do that integration yourself. Second, there is often data privacy and compliance issues at play. Just like with chatbots, these can be overcome, but the voice channel is new and more complex. There are also a lot of trust issues. Yes, everyone is moving to using public cloud infrastructure, but there is a general reluctance to send all your customer interaction data to someone like Amazon when they might be competing against you tomorrow (or are already with Amazon Connect)? Many traditional call center infrastructure providers are well tuned to these needs, but they also lack the millions of users and vast ecosystems that make the voice assistant platforms powerful in the first place.</p>
<h3 id="newtelephonyvoicebotplatformsareemerging">New telephony voicebot platforms are emerging</h3>
<p>Google is not the only one with fully automated voicebots that handle telephone calls.   <a href="https://voximplant.com/">VoxImplant</a> is a Communications Platform as a Service (CPaaS) vendor that <a href="https://cogint.ai/making-ivrs-not-suck-with-dialogflow-alexey-aylarov/">introduced a DialogFlow connector</a> a few weeks ago. In addition, <a href="https://www.voca.ai/">Voca.ai</a> is a recently launched startup with a telephone voicebot aimed at financial call centers.</p>
<p>It’s not just start-ups with voicebot platforms for telephony. IBM is in this game today too. Leveraging Watson - IBM’s Jeopardy! champion AI - for use in the call center used to be a lot of work. IBM has made a lot of recent progress in simplifying access Watson for telephony use cases. In addition to making the development of its bots much simpler, IBM also recently put its Watson telephony gateway in their IBM Cloud service. This effectively makes Watson another CPaaS offer with the ability to connect a SIP channel in minutes.</p>
<h3 id="botslikeoutboundcalls">Bots like Outbound Calls</h3>
<p>Interestingly, like the Google Duplex demo, outbound calls tend to be a better fit for the technology in its current state. Unlike an inbound call where it is hard to tell what the conversation will cover before engaging in the conversation, the call center dictates the agenda in an outbound calling scenario. Those calls tend to be more specific, making it easier to tune the NLU engine for the scenario.</p>
<h1 id="thevoicechannelisntgoingawaybutitwillbesupplementedbyvoicebots">The Voice Channel Isn’t Going Away, but it will be supplemented by Voicebots</h1>
<p>So, will the introduction of more voicebot technology into the contact center mean agents aren’t needed any more? The data actually indicates just the opposite.</p>
<p>A <a href="https://www2.deloitte.com/us/en/pages/operations/articles/global-contact-center-survey.html">2017 Deloitte</a> study of 450 diverse contact centers showed that customer interactions on the voice channel will fall by 17% by 2019, but still remain significant at 47%, three times more than web chat and email, the next largest channels. More importantly, their respondents expect customer interactions to get more complex and that voice is by far the leader in dealing with complex interactions. Supporting this, the US Bureau of Labor Statistics predicts the larger “Telephone call centers” category will increase in headcount by 27.4% between 2016 and 2026.</p>
<p><img src="https://cogint.ai/content/images/2018/07/bls-telephone-call-center.jpg" alt="When will Voice AI Replace the Call Center Voice Channel?"></p>
<h6 id="theusblstracksemploymentdatabycategorythisisthe2016dataand2026projectionnaics561420telephonecallcenterssourceusbureauoflaborstatics">The US BLS tracks employment data by category. This is the 2016 data and 2026 projection <em>NAICS 561420 - Telephone Call Centers</em>. Source: <a href="https://www.bls.gov/oes/2016/may/naics5_561420.htm">US Bureau of Labor Statics</a></h6>
<p>Self-service, voice-bots, and automation are not predicted to reduce overall agent headcount. If anything, it appears this technology will be needed to support increased demand for contact center interaction. Today’s simplistic IVR systems are certainly poised to be replaced by voicebots. However, as this happens, agents will need to handle an increasing load of more complex tasks.</p>
<p>It is early days for this technology, especially in the contact center. Voicebots might not replace agents on the phone, but the technology will certainly be a larger part of the mix in the days to come.</p>
<hr>
<p>Interested in a deeper dive this an other topics in AI and RTC? Check out our <a href="https://www.krankygeek.com/research/">upcoming report</a>. If you participate in our <a href="https://docs.google.com/forms/d/1PplZrKqsXYbcmJTyt5kvCeyAyqPFAEaeqVWhWSbKvSs/edit">web survey</a> on this topic you get an ebook along with a chance for 1 of 5 $100 Amazon Gift cards.<br>
<img src="https://cogint.ai/content/images/2018/07/ebook-giveaways.png" alt="When will Voice AI Replace the Call Center Voice Channel?"></p>
<hr>
<p>Chad Hart is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and and strategy advisory helping to advance the communications industry.</p>
<hr>
<h3 id="remembertosubscribeandfollowus">Remember to <a href="https://cogint.ai/subscribe/">Subscribe</a> and <a href="https://twitter.com/cogintai">Follow</a> us.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[Computer Vision Training, the AIY Vision Kit, and Cats]]></title><description><![CDATA[Review of how to do computer vision training followed with specifics on how to implement this for the AIY Vision Kit]]></description><link>https://cogint.ai/custom-vision-training-on-the-aiy-vision-kit/</link><guid isPermaLink="false">5b15c2f204a8c82a4f530cfc</guid><category><![CDATA[vision]]></category><category><![CDATA[guide]]></category><dc:creator><![CDATA[Chad Hart]]></dc:creator><pubDate>Tue, 05 Jun 2018 17:53:24 GMT</pubDate><media:content url="https://cogint.ai/content/images/2018/06/intro-graphic.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2018/06/intro-graphic.png" alt="Computer Vision Training, the AIY Vision Kit, and Cats"><p>This is a story of how to do a custom pet detector using computer vision. For those who are looking at examples of how to apply computer vision, I hope to illustrate a general methodology that should be applicable across a wide range of applications. My particular issue was cats on my kitchen counter, but there is a wide variety of scenarios where you have a camera that is focused on a particular area and you just want to identify when certain objects appear that don't belong so you can track them.</p>
<p>For anyone that has an AIY Vision Kit, this will also act as a starting guide for how to do custom vision training on your kit until Google does a better job of documenting this. We'll get more technical with some code and specifics around the Vision Kit at the end.</p>
<h2 id="thechallenge">The Challenge 🐈</h2>
<p>Cats. They can be cute, but they can also be evil. Mine have got into the habit of jumping on the kitchen counter. They lick food they and throw random objects on the ground. I know don't like the taste of any of this stuff, so it is probably out of spite. The other day one remorselessly murdered my Alexa by dropping my Echo Home off a 7-foot shelf. Not cute anymore 😒.<br>
<img src="https://cogint.ai/content/images/2018/06/IMG_20180604_140809.jpg" alt="Computer Vision Training, the AIY Vision Kit, and Cats"></p>
<h5 id="fig1kittydidnottakekindlytothemeowskillandpushedalexatoherdeath">Fig 1. Kitty did not take kindly to the <a href="https://www.amazon.com/Zhenhua-Meow/dp/B01GOSN706">Meow!</a> skill and pushed Alexa to her death</h5>
<p>I have <a href="https://webrtchacks.com/javascript-dog-trainer/">fixed pet problems before</a> with modern technology, so I figured I could do the same again using the new AIY Vision Kit I picked up a few weeks ago. To start I just wanted to use Computer Vision to alert me when they jump up where they aren't supposed to be.</p>
<h2 id="firstsometerminology">First, some Terminology</h2>
<p>If you are brand new to Machine Learning and Computer Vision, here are a few terms to keep mind:</p>
<ul>
<li><strong>Class</strong> - one or more types used to identify an object in an image. For example, the Dog/Cat/Person model has 3 classes - dog, cat, and person.</li>
<li><strong>Image Classification</strong>  - the process of using machine learning to identify classes in an image</li>
<li><strong>Object Detection</strong> - the process of using machine learning to identify one or more objects in an image and then classify each with a set of coordinates that indicates where the object is located in the image</li>
<li><strong>Network</strong> - the Neural Network architecture used. Building a Neural Network for computer vision is usually reserved for specialized Machine Learning PhD's. Fortunately, there are many high-quality open source networks available. Some of the popular ones include YOLO, Inception, and Resnet. We will be using the <a href="https://arxiv.org/abs/1512.02325">Single Shot Multibox Detector (SSD)</a> with <a href="https://ai.googleblog.com/2017/06/mobilenets-open-source-models-for.html">MobileNets</a> in this project.</li>
<li><strong>Model</strong> - a model is a <em>Network</em>  that has been trained on a specific dataset.</li>
<li><strong>Training</strong> - for our purposes, this is the process of taking a bunch of labeled data, like a picture of a cat with a label file that says &quot;cat&quot; and the cat's coordinates, to build a model</li>
<li><strong>Inference</strong> - running an image through the model to output a result</li>
</ul>
<h2 id="aiyvisionkitaselfcontainedvisionsystemthatiscomparativelyeasytouse">AIY Vision Kit - a self-contained vision system that is (comparatively) easy to use</h2>
<p>If you are not familiar, the <a href="https://aiyprojects.withgoogle.com/vision/">AIY Vision Kit</a> is a $90 &quot;do-it-yourself intelligent camera&quot; from Google that you can get from Target (in the US at least). Aimed at developers and STEM educators, the Vision Kit is housed in a self-assembled cardboard. The hardware includes a Raspberry Pi Zero and a Google designed add-on board called the <em>Vision Bonnet</em>. The Bonnet includes features a special Intel-made processor made for handling the kinds of neural networks modern computer vision algorithms run on. For more on the Vision Kit, see the <a href="https://webrtchacks.com/aiy-vision-kit-tensorflow-uv4l-webrtc/">post I did on webrtcHacks</a> covering the original version.<br>
<img src="https://cogint.ai/content/images/2018/06/aiy-vision-kit-unboxing.png" alt="Computer Vision Training, the AIY Vision Kit, and Cats"></p>
<h5 id="fig2unboxingtheaiyvisionkit">Fig 2. Unboxing the AIY Vision Kit</h5>
<h3 id="cloudvsedgeai">Cloud vs. Edge AI</h3>
<p>Like nearly everything else, it is pretty common to run Computer Vision in the cloud. Microsoft, Amazon, Google, IBM, and others all have Cloud API's you can pay for. As I showed in <a href="https://webrtchacks.com/webrtc-cv-tensorflow/">another webrtcHacks post</a>, it is also not too difficult to setup your own service using Open Source.</p>
<p>The cloud is easy, but is not always best for a few reasons:</p>
<ul>
<li>Privacy - not everyone wants to send a live video feed to some remote destination</li>
<li>Latency - it takes time to send an image up, have it processed, and then get the results back</li>
<li>Costs - processing images (aka &quot;running inference&quot;) in the cloud isn't free</li>
</ul>
<p>The Vision Kit does what is known as &quot;Edge AI&quot;. Inference actually runs on device and no Internet connection is required. In my case this means:</p>
<ul>
<li>I don't have to worry about sending images/videos of my house to the wrong API account or who knows who else</li>
<li>I get instant inference, which is helpful when you want to your application to respond within a few 10's of milliseconds instead of seconds</li>
<li>I can process as many images as I want without worry how much it will cost - in fact a continuous 30 frames per second video stream</li>
</ul>
<p>While this post will focus on the AIY Vision Kit, most of the concepts will apply to other embedded AI devices. You can actually buy a <a href="https://developer.movidius.com/">different kit</a> from Intel that includes the same chip, just on a USB stick. Microsoft recently <a href="https://azure.microsoft.com/en-us/blog/accelerating-ai-on-the-intelligent-edge-microsoft-and-qualcomm-create-vision-ai-developer-kit/">announced</a> something similar with a new Qualcomm chip called the Snapdragon™ Neural Processing Engine (NPE).</p>
<h3 id="includedcomputervisionmodels">Included Computer Vision Models</h3>
<p>The kit comes with several <a href="https://aiyprojects.withgoogle.com/models/">models</a>. Most are image classifiers:<br>
<img src="https://cogint.ai/content/images/2018/06/aiy-models.png" alt="Computer Vision Training, the AIY Vision Kit, and Cats"></p>
<h5 id="figure3thecurrentmodelsavailablefortheaiyvisionkitsourceslideshare">Figure 3. The current models available for the AIY Vision Kit. Source: <a href="https://www.slideshare.net/ChadHart/aiy-vision-kit-embedded-ml-for-stem-and-makers-gdg-boston-tensorflow">SlideShare</a></h5>
<p>The AIY Kit also includes a &quot;Dog / Cat / Human&quot; object detector. Since I am looking to detect cats, one would think this would be a quick project. Unfortunately this built in object detector model did not do a great job of  detecting my black cats. A bunch of the time it would not classify them at all. Other times I had miss-classifications like this where it mistook a mug full of markers for a person and totally missed the cat:<br>
<img src="https://cogint.ai/content/images/2018/06/2-after_detection.jpg" alt="Computer Vision Training, the AIY Vision Kit, and Cats"></p>
<h5 id="fig4aiyvisionkitdogcathumanannotatedimageafterobjectdetectionnotetheareahighlightedwiththisresultobject0kindperson1score0567637bbox5862083965">Fig 4. AIY Vision Kit Dog/Cat/Human annotated image after object detection - note the area highlighted with this result <code>Object #0: kind=PERSON(1), score=0.567637, bbox=(586, 208, 39, 65)</code></h5>
<h3 id="whydoesntitwork">Why doesn't it work?</h3>
<p>Google has not published how they built this particular model, but it is likely they used pet data like what is found in <a href="http://www.robots.ox.ac.uk/~vgg/data/pets/">The Oxford-IIIT Pet Dataset</a> for their pet images when they trained the model. Looking at the pictures of <a href="http://www.robots.ox.ac.uk/~vgg/data/pets/getCategory.php?category=Bombay">some of the black cats</a>, nearly all of them are on the ground with good lighting. None of them are on a kitchen counter. Perhaps the model just did not &quot;see&quot; enough examples that closely matched my kitchen. I also suspect black cats, particuarly at a distance, are hard because there are not a lot of easily identifiable features when you have low contrast lighting.</p>
<p>Since deep neural networks are somewhat of a black box, it is difficult to tell what is happening. However, this does not mean we need to give up.</p>
<h2 id="makeitworkwithtensorflowandcustomtraining">Make it work with Tensorflow and Custom Training</h2>
<p>The AIY Vision Kit, like all AI things Google, is based on Tensorflow, the <a href="https://cogint.ai/ml-github-comparison/">most popular</a> Machine Learning framework on the planet today. With some work, you can load your own models onto the Vision Kit to classify and/or detect whatever you want. Let's give this a try...<br>
<img src="https://cogint.ai/content/images/2018/06/high-level-process.png" alt="Computer Vision Training, the AIY Vision Kit, and Cats"></p>
<h5 id="fig5highlevelprocessforcustomtrainingontheaiyvisionkit">Fig 5. High-level process for custom training on the AIY Vision Kit</h5>
<h3 id="processoverview">Process overview</h3>
<p>We will be using Tensorflow's <a href="https://github.com/tensorflow/models/tree/master/research/object_detection">Object Detection API</a> to train our own model. The steps are not for the faint of heart. This will take you hours, after you get the hang of it. Loading the model on the Vision Kit adds a few extra steps.</p>
<p>The whole process goes something like this:</p>
<ol>
<li>Get a lot of images covering the classes you care about covering - a couple hundred for each class, ideally covering a variety of angles, backgrounds, and lighting conditions you will encounter in the real world</li>
<li>Label each image, by hand</li>
<li>Prepare the dataset for training - convert the labels to the appropriate format, make a label map file, and separate the images into a large training set and a smaller evaluation set</li>
<li>Set the right parameters inside the object detection configuration file</li>
<li>Prepare your Tensorflow environment - this can be another list of items if you are training in the Cloud like I did with ML-Engine</li>
<li>Run the training to produce a graph</li>
<li>Freeze the graph</li>
<li>Compile the graph using the Bonnet Compiler (in Ubuntu)</li>
<li>Load the compiled graph onto the Kit</li>
<li>Tweak the example code to make it work with the compiled graph</li>
<li>Fire up your code and hope it all works!</li>
</ol>
<p>This process is generic for the Object Detection API up to 9. The specifics of the process depend on your environment. I recommend following along with some guides to do this. Two that helped me the most are:</p>
<ul>
<li><a href="https://pythonprogramming.net/video-tensorflow-object-detection-api-tutorial/">Streaming Object Detection Video - Tensorflow Object Detection API Tutorial</a></li>
<li><a href="https://www.youtube.com/watch?v=Rgpfk6eYxJA">How To Train an Object Detection Classifier Using TensorFlow 1.5 (GPU) on Windows 10</a></li>
</ul>
<p>I will give some highlights on steps 9-12 below.</p>
<h1 id="tipsforaiyers">Tips for AIY'ers</h1>
<p>It was a long saga to get this all working on the Vision Kit. If you want to see the journey with valuable commentary from Googles and community contributions, check out this <a href="https://github.com/google/aiyprojects-raspbian/issues/314#issuecomment-389317428">github issue</a>.</p>
<h3 id="howtogenerateabunchofimagesquickly">How to generate a bunch of images quickly</h3>
<p>The first challenge is getting a bunch of images. I was able to use the <a href="https://github.com/Motion-Project/motion">Motion Project</a> to generate a bunch of images quickly. <em>Motion</em> is a Linux program that can run on the Pi. It looks for changes in a video camera image between frames and can save a snapshot. I set this up this program to take snapshots whenever motion was detected in the camera's field of view. I did this a bunch of times over a couple days, turning the camera to get different angles, raising its height, making sure the counter and kitchen table had different types of objects on it, and with a variety of lighting conditions.</p>
<p>My cats are very naughty, so it didn't take long for me to get a few hundred images.  I also wanted to make sure I could classify people, so I let it run with people around too. In retrospect, I wish I took more people images since there is a lot more variability in people vs my cats who don't change outfits.</p>
<p>Motion includes a ton of parameters. One of my first mistakes was taking too many pictures - I ended up with a lot of pictures that were basically the same. Remember, you need to manually label each of these pictures. I found that including more images without a lot of variety just added to the work load without changing the accuracy much. I should have put a longer delay between taking snapshots.</p>
<h3 id="settingupyourpipelineconfigurationfile">Setting up your pipeline configuration file</h3>
<p>For object detection on the AIY Vision Kit, you need to start with this configuration file: <a href="https://github.com/tensorflow/models/blob/master/research/object_detection/samples/configs/embedded_ssd_mobilenet_v1_coco.config">embedded_ssd_mobilenet_v1_coco.config</a></p>
<p>Then change the following lines:</p>
<ul>
<li>num_classes - set this to the number of classes (counting from 1) for your custom model - in my case this was 2 (cat &amp; person)</li>
<li><code>fine_tune_checkpoint</code> - used if you are going to continue training from a saved checkpoint. Leave it out if you are going to train from scratch. More on this in a bit</li>
<li><code>input_path</code> - path to your training <code>record</code> file</li>
<li><code>label_map_path</code> - where you saved your label map file</li>
</ul>
<h3 id="trainingongooglecloud">Training on Google Cloud</h3>
<p>I originally tried to do some training on my MacBook Pro. You usually need to run 10,000's of thousands of training steps up to 200,000. With no usable GPU for training on my Mac, sometimes a step could take up to 5 seconds. Doing the math, 100,000 steps would take me many days, not to mention nearly melt my machine from running at full tilt all that time.</p>
<p>So I then decided to move my training to Google Cloud's ML-Engine, mostly because that seems to be the <a href="https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/running_on_cloud.md">best documented</a> as part of the Object Detection API repo.</p>
<p>This involves a bunch more extra steps and some fiddling to make it work. When I first tried it, it would run for a while but would eventually fail due to memory issues (which I addressed by adjusting the batch size). Other times it would fail a few minutes in (I never fully figure out why). When this process is spread over a handful of machines and you are doing it a few times you can quickly burn through your Latte budget for the day without doing any real training.</p>
<p>In the end I found it simplest to just run on a single machine with the following:</p>
<pre><code>gcloud ml-engine jobs submit training object_detection_eval_`date +%s` \
    --job-dir=gs://n5r8-cat-detector/train \
    --packages dist/object_detection-0.1.tar.gz,slim/dist/slim-0.1.tar.gz \
    --module-name object_detection.eval \
    --region us-east1 --scale-tier BASIC_GPU --python-version 3.5 \
    --runtime-version 1.6 \
    -- \
    --checkpoint_dir=gs://{{my-gcp-bucket}}/train \
    --eval_dir=gs://{{my-gcp-bucket}}/test \
    --pipeline_config_path=gs://{{my-gcp bucket}}/data/ssd_mobilenet_v1_cat.config
</code></pre>
<p>I originally intended to let this run for a while to verify it works before switching to running it on multiple machines. Then, once it was working I was hesitant to mess with it (and I had other things to do), so I just let it run in the background.</p>
<p>My last run ran for 100,000 steps consuming 10.67 ML-units for a total cost of $5.30.</p>
<h3 id="runningthebonnetcompiler">Running the Bonnet Compiler</h3>
<p>You need to compile your graph to run on the Vision Bonnet. After you <a href="https://dl.google.com/dl/aiyprojects/vision/bonnet_model_compiler_latest.tgz">download</a> the Bonnet Compiler, you'll need to find a place to run it. The Vision Kit page says:</p>
<blockquote>
<p>The compiler works only with x86 64 CPU running Linux. It was tested with Ubuntu 14.04. You should NOT run it on VisionBonnet.</p>
</blockquote>
<p>This is a pain for those that are running OS X (me) or Windows. Fortunately for me, I already had an Ubuntu instance setup on VirtualBox. Installing and configuring VirtualBox is a bunch more steps. If you do this, make sure you use the Virtual Box guest additions package to make it easy to pass files back and forth from the host machine to VM.</p>
<p>I am running Ubuntu 16.04 and it works fine for me.</p>
<p>If I was starting from scratch and just needed a quick Ubuntu environment to run the compiler then I probably would just use Docker. Now that I think about it I wish I tried that.</p>
<h3 id="compilercommand">Compiler command</h3>
<p>Here is the compiler command I used:</p>
<pre><code>./bonnet_model_compiler.par \
    --frozen_graph_path=aiy_cat_detector.pb \
    --output_graph_path=cat_detector.binaryproto \
    --input_tensor_name=&quot;Preprocessor/sub&quot; \
    --output_tensor_names=&quot;concat,concat_1&quot; \
    --input_tensor_size=256
</code></pre>
<p>Note the output tensor names. This part was not obvious and one of the <a href="https://github.com/weiranzhao">Googler's</a> pointed it out to me.</p>
<h3 id="aiyobjectdetectioncodechanges">AIY Object Detection code changes</h3>
<p>If that all works, now you need to do some tweaks to the AIY Vision Kit object detection samples to make it work.</p>
<h4 id="changetheobjectdetectionhelperlibrary">Change the Object Detection helper library</h4>
<p>Make a copy of <a href="https://github.com/google/aiyprojects-raspbian/blob/aiyprojects/src/aiy/vision/models/object_detection.py">https://github.com/google/aiyprojects-raspbian/blob/aiyprojects/src/aiy/vision/models/object_detection.py</a> and modify 3 lines:</p>
<ul>
<li><a href="https://github.com/google/aiyprojects-raspbian/blob/aiyprojects/src/aiy/vision/models/object_detection.py#L29">Line 29</a> to modify the labels to match what you setup in your training</li>
<li><a href="https://github.com/google/aiyprojects-raspbian/blob/aiyprojects/src/aiy/vision/models/object_detection.py#L75">Line 75</a> to change the assertion here from <code>4</code> to match your number of labels</li>
<li><a href="https://github.com/google/aiyprojects-raspbian/blob/aiyprojects/src/aiy/vision/models/object_detection.py#L84">Line 84</a> - change the index here from <code>4</code> to match your number of labels</li>
</ul>
<h4 id="writeyourprogram">Write your program</h4>
<h5 id="imageinference">Image Inference</h5>
<p>I started out by modifying the <a href="https://github.com/google/aiyprojects-raspbian/blob/aiyprojects/src/examples/vision/object_detection.py">object_detection.py</a> for initial testing. All you need to do is change <code>from aiy.vision.models import object_detection</code> to your modified <code>object_detection.py</code> helper file like this:</p>
<pre><code>from aiy.vision.inference import ImageInference
# from aiy.vision.models import object_detection
# Use my modified file instead
import aiy_cat_detection
</code></pre>
<h5 id="camerainference">Camera Inference</h5>
<p>Lastly, I wrote/modified a program to run <code>CameraInference</code>. I added a couple other bells &amp; whistles, like the privacy LED indicator and some sounds.</p>
<p>The full thing is just:</p>
<pre><code>import argparse

from picamera import PiCamera
from time import time, strftime


from aiy.vision.leds import Leds
from aiy.vision.leds import PrivacyLed
from aiy.toneplayer import TonePlayer

from aiy.vision.inference import CameraInference
import aiy_cat_detection

# Sound setup
MODEL_LOAD_SOUND = ('C6w', 'c6w', 'C6w')
BEEP_SOUND = ('E6q', 'C6q')
player = TonePlayer(gpio=22, bpm=30)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--num_frames',
        '-f',
        type=int,
        dest='num_frames',
        default=-1,
        help='Sets the number of frames to run for, otherwise runs forever.')

    parser.add_argument(
        '--num_pics',
        '-p',
        type=int,
        dest='num_pics',
        default=-1,
        help='Sets the max number of pictures to take, otherwise runs forever.')

    args = parser.parse_args()

    with PiCamera() as camera, PrivacyLed(Leds()):
        # See the Raspicam documentation for mode and framerate limits:
        # https://picamera.readthedocs.io/en/release-1.13/fov.html#sensor-modes
        # Set to the highest resolution possible at 16:9 aspect ratio
        camera.sensor_mode = 5
        camera.resolution = (1640, 922)
        camera.start_preview(fullscreen=True)

        with CameraInference(aiy_cat_detection.model()) as inference:
            print(&quot;Camera inference started&quot;)
            player.play(*MODEL_LOAD_SOUND)

            last_time = time()
            pics = 0
            save_pic = False

            for f, result in enumerate(inference.run()):

                for i, obj in enumerate(aiy_cat_detection.get_objects(result, 0.3)):

                    print('%s Object #%d: %s' % (strftime(&quot;%Y-%m-%d-%H:%M:%S&quot;), i, str(obj)))
                    x, y, width, height = obj.bounding_box
                    if obj.label == 'CAT':
                        save_pic = True
                        player.play(*BEEP_SOUND)

                # save the image if there was 1 or more cats detected
                if save_pic:
                    # save the clean image
                    camera.capture(&quot;images/image_%s.jpg&quot; % strftime(&quot;%Y%m%d-%H%M%S&quot;))
                    pics +=1
                    save_pic = False

                if f == args.num_frames or pics == args.num_pics:
                    break

                now = time()
                duration = (now - last_time)

                # The Movidius chip runs at 35 ms per image.
                # Then there is some additional overhead for the object detector to
                # interpret the result and to save the image. If total process time is
                # running slower than 50 ms it could be a sign the CPU is geting overrun
                if duration &gt; 0.50:
                    print(&quot;Total process time: %s seconds. Bonnet inference time: %s ms &quot; %
                          (duration, result.duration_ms))

                last_time = now

        camera.stop_preview()

if __name__ == '__main__':
    main()
</code></pre>
<p>All my code and model is <a href="https://github.com/chadwallacehart/aiy_custom_cat_detector">available on GitHub</a> for reference.</p>
<h3 id="startingfromscratchvstransferlearning">Starting from Scratch vs. Transfer learning</h3>
<p>Transfer learning is the idea of taking an existing model and quickly retraining it on a new set of classes. Rather than starting from scratch, you can just remove that last few layers of the neural network and then perform a relatively small number of training steps to produce a new model. The <code>fine_tune_checkpoint</code> above lets you do this.</p>
<p>Unfortunately, Google did not publish their model other than in its compiled binary form. Tensorflow does <a href="https://github.com/tensorflow/models/tree/master/research/slim#Pretrained">publish a number of models</a> based on various sets that are useful for transfer learning. However, the particular MobileNet SSD configuration that the Vision Bonnet requires - a <code>256</code>x<code>256</code> input image with depthwise multiplier of <code>0.125</code> - is not one of them.</p>
<p>With no existing model to work from, I tried to train my model from scratch. This did not work well. It would sometimes think my oven was a person. I suspect my input images did not have enough variety for it to accurately distinguish between objects. I never really learned what features make an object.</p>
<p>Then <a href="https://github.com/zhoujustin">zhoujustin</a> saved the day and <a href="https://drive.google.com/file/d/1_MeZ8kvmpNibPZvSJGnwKNRATeuyxNtu/view?usp=sharing">shared a trained model</a> based on the 20-class <a href="http://host.robots.ox.ac.uk/pascal/VOC/">VOC dataset</a>. I set this as the <code>fine_tune_checkpoint</code> and my results have been pretty good.</p>
<h2 id="theresults">The results</h2>
<p>After struggling to get something to work, my new custom trained model works great!<br>
Here is an example with very low light:<br>
<img src="https://cogint.ai/content/images/2018/06/6-after_detection.jpg" alt="Computer Vision Training, the AIY Vision Kit, and Cats"></p>
<p>And here is one where my cat seems to be more attracted to the constant beeping my kit is making instead of running away from it:<br>
<img src="https://cogint.ai/content/images/2018/06/7-after_detection.jpg" alt="Computer Vision Training, the AIY Vision Kit, and Cats"></p>
<p>I have some work to do here on the deterrent part, but at least now I have accurate detection. Next step is to get my robot involved. The bounding box coordinates will come in handy for aiming projectiles...</p>
<h2 id="conclusions">Conclusions</h2>
<p>Ideally the built in AIY cat detector model would have worked for me out of the box, but that is really wishful thinking to expect it to work well in all circumstances. It is exciting to see you can get high accuracy results through custom training - even when inference is running on a low-power device.</p>
<p>It several months to make this work, but we got there eventually. Thanks to everyone on <a href="https://github.com/google/aiyprojects-raspbian/issues/314#issuecomment-389317428">GitHub issue 314</a> for helping!</p>
<p>Now I need to get back to shooing my cats off the counter...</p>
<hr>
<p><a href="https://chadwallacehart.com/bio">Chad Hart</a> is an analyst and consultant with <a href="https://cwh.consulting">cwh.consulting</a>, a product management, marketing, and and strategy advisory helping to advance the communications industry. He is currently working on a <a href="https://www.krankygeek.com/research">AI in RTC report</a>.</p>
<hr>
<h3 id="remembertosubscribeandfollowus">Remember to <a href="https://cogint.ai/subscribe/">Subscribe</a> and <a href="https://twitter.com/cogintai">Follow</a> us.</h3>
</div>]]></content:encoded></item><item><title><![CDATA[Making IVRs not Suck with Dialogflow (Alexey Aylarov)]]></title><description><![CDATA[Alexey Aylarov of VoxImplant introduces Google's Dialogflow and reviews how they integrated it into their telephony system to provide an alternative to IVRs.]]></description><link>https://cogint.ai/making-ivrs-not-suck-with-dialogflow-alexey-aylarov/</link><guid isPermaLink="false">5b0c839b04a8c82a4f530ceb</guid><category><![CDATA[voicebot]]></category><category><![CDATA[dialogflow]]></category><dc:creator><![CDATA[Alexey Aylarov]]></dc:creator><pubDate>Tue, 29 May 2018 12:30:53 GMT</pubDate><media:content url="https://cogint.ai/content/images/2018/05/shutterstock_259628300.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cogint.ai/content/images/2018/05/shutterstock_259628300.jpg" alt="Making IVRs not Suck with Dialogflow (Alexey Aylarov)"><p>We are all getting used to asking Siri, Alexa, and Google to find things via voice. Alexa has <a href="https://voicebot.ai/2018/03/22/amazon-alexa-skill-count-surpasses-30000-u-s/">more than 30,000 skills</a> and smart speakers <a href="https://www.canalys.com/newsroom/google-beats-amazon-to-first-place-in-smart-speaker-market?campaignname=googlechirp">grew by 210% in Q1</a>. Clearly voice assistants have matured, which is why it is insane that businesses still make their customers sit through tedious <a href="https://en.wikipedia.org/wiki/Interactive_voice_response">Interactive Voice Response (IVR)</a> systems that rely on archaic touch-tone input and multi-layer menus. Sure, some high-end enterprises might have better systems, but, by-in-large, the IVR experience has not changed much in decades.</p>
<p>I believe this is about to change. I was <a href="https://cogint.ai/google-uses-ai-to-make-phone-calls-interesting-again/">commenting on Google's recent Duplex demo</a> and Alexey Aylarov of <a href="https://voximplant.com">VoxImplant</a> mentioned they were just wrapping up an integration with Dialogflow - the conversational bot company formerly know as api.ai that Google bought and rebranded.</p>
<p>VoxImplant is a Communications Platform as a Service (CPaaS) with most of its team in Moscow.  Alexey claimed they could do something similar to Duplex using public API’s (though without many of Google’s more advanced tricks).  He has a good <a href="https://webrtchacks.com/?s=alexey">history of sharing</a> the workings behind new concept demos, so I asked if he would share his experience and learnings integrating with Dialogflow here. Please see below for Alexey's high-level review of Dialogflow, more details on how VoxImplant went about the telephony integration, and for the more technical, some demos and code at the end.</p>
<p><a href="https://cogint.ai/author/chad/">Chad Hart</a>, Editor</p>
<hr>
<h1 id="makingivrsnotsuckwithdialogflow">Making IVRs not Suck with Dialogflow</h1>
<p>In most cases when we need to communicate with a business over the phone today we have to deal with a good old IVR. “Press 1 to …, press 2 to …, press 3 to …”. Just the initial options prompt itself can last for a few minutes. After you endure this first level of IVR menu comes a 2nd level, which can also lead to the 3rd one, and so on. It can be maddening. I haven’t met anyone who thinks that kind of customer experience is great. Fortunately alternatives to the IVR menu are becoming practical for a large audience. Thanks to the progress in machine learning and IT in general, speech recognition and voice bots have started to become accessible for business.</p>
<p>Rather than navigate through IVR menus, wouldn’t it be better if you could just say what you need/want, like you would with a real operator? That is totally possible with today’s technology natural language processing (NLP) and speech recognition technologies. Let's explore how we did this in our platform using Dialogflow.</p>
<h2 id="dialogflow">Dialogflow</h2>
<p>Google’s Dialogflow lets people create intelligent bots that understand natural language and can handle conversations like a live person. Dialogflow supports many nice features out of the box that are a good fit for commonly used in IVR interactions, such as:</p>
<ul>
<li><em>Understanding intents</em> - mapping a variety of spoken phrases to defined action</li>
<li><em>Slot filling</em> - handling multiple data inputs per user utterance and knowing to keep asking when more information is required</li>
<li><em>Fallbacks</em> - handling errors and avoiding looks if something is not understood</li>
<li><em>API and webhooks</em> - for integration with external web services</li>
<li><em>Speech recognition</em> - the new V2 API can directly handle speech input from Google’s Cloud Speech API</li>
</ul>
<p>Dialogflow is a powerful tool that developers can quickly become familiar with after reading the docs and checking some examples. They make it easy to build rather complex bots without programming (or at least serious programming). If you are familiar with modern bot programming, Dialogflow works with number of common bot abstractions you need to set up for your agent to make it work Intents, Parameters, Contexts, Entities, and so on.</p>
<p>Choosing Dialogflow as an integration option was an easy decision for us. We already had a Google Speech integration (see below), so there were minimal technical challenges on our end. We also found it works well for our audience, and their documentation and examples are great, so we not think our users will have much trouble getting started with their API.</p>
<p>There are already a lot of articles and posts about Dialogflow and how to build various kinds of bots. Rather than rehash these guides, instead we will focus the rest of this post on how to integrate Dialogflow into a telephony system.</p>
<p><img src="https://cogint.ai/content/images/2018/05/VoxImplant-Dialogflow-high-level-architecture-high-res.png" alt="Making IVRs not Suck with Dialogflow (Alexey Aylarov)"></p>
<h2 id="telephonyconsiderations">Telephony Considerations</h2>
<h3 id="transcriptionintegration">Transcription Integration</h3>
<p>Before API V2, Dialogflow agents could only work with text. That means you had to handle converting any speech to text yourself. Then you could pass that text to the API and receive response from an agent after NLU/NLP job has been done. In the new API V2 there is a <a href="https://dialogflow.com/docs/reference/api-v2/rpc/google.cloud.dialogflow.v2#google.cloud.dialogflow.v2.StreamingDetectIntentRequest">StreamingDetectIntentRequest</a> method that lets send audio directly to a Dialogflow agent. This method will transcribe the speech and then automatically process the transcription to create a response. It turns out this new method is basically the same as the Google Cloud Speech API.</p>
<p>You can still handle your own speech recognition, but is really easier to use Google’s methods. Google’s Cloud Speech API allows uploading of a recording, but you really should be streaming the audio to reduce latency and prevent awkward silences while audio is processed. Google uses the GRPC protocol for streaming your audio data in real-time to Dialogflow. Unfortunately I do not think there is any magic method for how to convert a live audio stream into <a href="https://opensource.google.com/projects/grpc">GRPC</a>. Ultimately you need some kind of converter that takes the stream from your system, chunks it up, and then sends it over GRPC. We had already integrated Google’s Cloud Speech API into Voximplant for automatic speech recognition with our own library, so it was relatively easy for us to add Dialogflow’s streaming API support.</p>
<h3 id="codecs">Codecs</h3>
<p>One of the first areas you will need to align-on is the audio encoding. <a href="https://dialogflow.com/docs/reference/api-v2/rpc/google.cloud.dialogflow.v2#google.cloud.dialogflow.v2.AudioEncoding">Google supports</a> <code>Linear PCM</code>, <code>FLAC</code>, <code>G.711 PCMU</code>, <code>AMR/AMR-WB</code>, <code>OPUS</code> in OGG container and <code>Speex Wideband</code>. Your telephony system definitely supports one of these, so it is just a matter of matching the codec whatever the caller is using. We do a lot of <a href="https://en.wikipedia.org/wiki/Public_switched_telephone_network">PSTN</a> audio processing at our backend,  so we usually use PCM. One could use an encoding that does more compression to reduce bandwidth consumption, but it is important to remember that additional transcoding/audio processing significantly affects recognition accuracy. Compressing the audio stream only makes sense if you already receiving the encoded audio in the format supported by Google’s backend.</p>
<h3 id="speechdurationmodes">Speech Duration Modes</h3>
<p>Dialogflow/Google Speech supports two speech recognition modes:</p>
<ol>
<li><em>Single utterance</em> - recognition stops as soon as Dialogflow decides that user stopped talking and processes the sentence using NLU/NLP. (<code>singleUtterance = true</code>)</li>
<li><em>Long running</em> - you send speech and recognition will continue until it’s stopped using the API so everything is transcribed and sent through the NLU/NLP engine. (<code>singleUtterance = false</code>)</li>
</ol>
<p>The long running mode also gives interim recognition results that arrive in <a href="https://dialogflow.com/docs/reference/api-v2/rpc/google.cloud.dialogflow.v2#streamingrecognitionresult">StreamingRecognitionResult</a> objects. These can be used by the NLU engine to predict an intent before speech even stops, like what happens with a person.</p>
<h3 id="returnedresult">Returned Result</h3>
<p>After NLU/NLP is done, the Dialogflow agent returns a <a href="https://dialogflow.com/docs/reference/api-v2/rpc/google.cloud.dialogflow.v2#google.cloud.dialogflow.v2.QueryResult">QueryResult</a> object populated with some data - action, intent, contexts, etc. (see the next section for a code example). For example, it can be used by telephony backend to say something using Text-to-Speech (TTS) engine or to change IVR branch, or to connect with a live person, etc. We had an existing Text-to-Speech capability for the many languages we support, but recently added Google’s Text-to-Speech with WaveNet-powered voices. The WaveNet TTS engine sounds very realistic, but unfortunately it is only available for US English today. We do expect that new languages will appear in the not too distant future. I also expect that Dialogflow will support sending audio generated by Google’s TTS at some point too.</p>
<h2 id="democode">Demo &amp; Code</h2>
<p>If you want to try it in action you can play with our pizza order &amp; delivery phone bot <a href="https://demos05.voximplant.com/dialogflow-connector/">here</a>:</p>
<p><a href="https://demos05.voximplant.com/dialogflow-connector/"><img src="https://cogint.ai/content/images/2018/05/pizza-order-demo-1.png" alt="Making IVRs not Suck with Dialogflow (Alexey Aylarov)"></a></p>
<p>Dialogflow allows you to import a project, which makes it easy to get started by modifying an existing application through the GUI. You can grab the Dialogflow agent used in this demo here: <a href="https://demos05.voximplant.com/dialogflow-connector/PizzaOrderDelivery.zip">PizzaOrderDelivery.zip</a>.</p>
<p>You can see from the demo that some of the interpreted information is relayed back to the webpage as a visual confirmation. To do this we setup a NodeJS proxy in our backend to send the interpreted responses from Dialogflow to the local browser. We plan to add websocket support to our API engine to make this easier.</p>
<p>On our side, we use something like the below cloud function to process the returned <code>QueryResult</code> object and respond with Text-to-Speech:</p>
<pre><code>    function sendMediaToDialogflow() {
      call.removeEventListener(CallEvents.PlaybackFinished)
      call.sendMediaTo(dialogflow)
    }

    function onDialogflowQueryResult(e) {
      if (e.result.fulfillmentText !== undefined) {
        call.say(e.result.fulfillmentText, Language.Premium.US_ENGLISH_FEMALE)
        call.addEventListener(CallEvents.PlaybackFinished, sendMediaToDialogflow)
      }
    }

</code></pre>
<p>Many of the function calls are obviously specific to our implementation, but one can see how similar logic could be used implement something like Google’s Duplex demo for outbound calls too!</p>
<ul>
<li><a href="https://cogint.ai/author/alexey/">Alexey Aylarov</a>, CEO <a href="https://voximplant.com">VoxImplant</a></li>
</ul>
</div>]]></content:encoded></item></channel></rss>