{"id":2126,"date":"2016-11-01T03:23:12","date_gmt":"2016-11-01T03:23:12","guid":{"rendered":"https:\/\/www.microsoft.com\/reallifecode\/index.php\/2016\/11\/01\/creating-speech-driven-applications-with-cognitive-services-and-luis\/"},"modified":"2020-03-15T06:37:40","modified_gmt":"2020-03-15T13:37:40","slug":"creating-speech-driven-applications-with-cognitive-services-and-luis","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/ise\/creating-speech-driven-applications-with-cognitive-services-and-luis\/","title":{"rendered":"Creating Speech-Driven Applications with Cognitive Services and LUIS"},"content":{"rendered":"<p>Ever wonder what it\u2019s like to have Jarvis, the assistant from Iron Man, help you build an application? With recent advances in machine learning and speech recognition, this is now possible. We have been assisting several partners to embrace conversation as a platform and to take advantage of Microsoft\u2019s APIs for cognitive services. Recently, we collaborated with <a href=\"http:\/\/www.huma.ai\/\">Huma.AI<\/a>, a San Francisco-based startup, which is combining artificial intelligence, design, and rapid prototyping in new and exciting ways.<\/p>\n<p>In this case study, we will walk through a generalized sample project we created to help Huma.AI and others to use <a href=\"https:\/\/www.microsoft.com\/cognitive-services\/en-us\/speech-api\/documentation\/overview\">Microsoft Cognitive Services\u2019 speech to text service<\/a> to interpret a user\u2019s voice commands, and <a href=\"https:\/\/www.microsoft.com\/cognitive-services\/en-us\/luis-api\/documentation\/home\">Language Understanding Intelligent Service (LUIS)<\/a> to determine a user\u2019s intents. We will also discuss how we leveraged a new service still in beta called <a href=\"https:\/\/cris.ai\/\">CRIS (Custom Recognition Intelligent Service)<\/a> to enhance the speech recognition experience by building a custom language model and custom speech to text interpreter for domain specific vocabulary.<\/p>\n<h2 id=\"the-problem\">The Problem<\/h2>\n<p>Huma.AI was using API.AI for both its speech to text and text to intent capabilities. However, the company started to experience limitations of API.AI. Speech to text is a critical part of their product strategy, and Huma.AI wanted a solution that was best-of-breed. Microsoft Cognitive Services\u2019 speech to text service combined with CRIS proved to be the most accurate and customizable solution with which to integrate. Huma.AI was able to migrate all its existing intents in just two days, and it proved more accurate and easier to train than API.AI.<\/p>\n<p>The startup decided to work with Microsoft to switch over to Microsoft Cognitive Services for speech to text, and LUIS for text to intent. Companies attempting to perform non-trivial tasks through voice commands, however, quickly ran into a complexity problem when trying to quantify intent. For instance, in our CellPainter sample, you can say the following commands to paint or modify the UI:<\/p>\n<ul>\n<li>Add a blue cell in 14.<\/li>\n<li>Make 14 green.<\/li>\n<li>Move it up.<\/li>\n<li>Put a red cell in 12.<\/li>\n<li>Move it down.<\/li>\n<\/ul>\n<p>The challenge here is that users may express the same idea or intent in multiple different ways. With any robust speech interaction model, we must consider all possible natural language commands. This complication makes the problem more than just \u201cspeech to text,\u201d but rather \u201cspeech to intent.\u201d<\/p>\n<h2 id=\"overview-of-the-solution\">Overview of the Solution<\/h2>\n<p>To support Huma.AI and other partners attempting to pioneer the next wave of speech-driven applications, we created a generalized problem statement and simplified its requirements down to an application we called CellPainter. This application updates its interface based on the user\u2019s voice commands to demonstrate how we handled the intent of manipulating colored cells in a grid. Huma.AI was then able to take the sample project and integrate the Cognitive Services Speech API and the LUIS API into its own application.<\/p>\n<h3 id=\"implementation\">Implementation<\/h3>\n<p>Microsoft Cognitive Services are a set of pre-trained and pre-built libraries for specific but common machine learning tasks developed by Microsoft Research. Using these services, developers can easily integrate features like facial, speech, and image recognition into their applications.<\/p>\n<p> <img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cse\/wp-content\/uploads\/sites\/55\/2016\/11\/CellMoverWorkflow.png\" alt=\"Image CellMoverWorkflow\" width=\"1544\" height=\"697\" class=\"aligncenter size-full wp-image-11077\" srcset=\"https:\/\/devblogs.microsoft.com\/ise\/wp-content\/uploads\/sites\/55\/2016\/11\/CellMoverWorkflow.png 1544w, https:\/\/devblogs.microsoft.com\/ise\/wp-content\/uploads\/sites\/55\/2016\/11\/CellMoverWorkflow-300x135.png 300w, https:\/\/devblogs.microsoft.com\/ise\/wp-content\/uploads\/sites\/55\/2016\/11\/CellMoverWorkflow-1024x462.png 1024w, https:\/\/devblogs.microsoft.com\/ise\/wp-content\/uploads\/sites\/55\/2016\/11\/CellMoverWorkflow-768x347.png 768w, https:\/\/devblogs.microsoft.com\/ise\/wp-content\/uploads\/sites\/55\/2016\/11\/CellMoverWorkflow-1536x693.png 1536w\" sizes=\"(max-width: 1544px) 100vw, 1544px\" \/><\/p>\n<p>The CellPainter application is built using the following:<\/p>\n<ol>\n<li><strong>RecorderJS<\/strong> to record audio<\/li>\n<li>Every call to the <strong><a href=\"https:\/\/www.microsoft.com\/cognitive-services\/en-us\/speech-api\/documentation\/overview\">Cognitive Service Speech API<\/a><\/strong> requires you to pass through a JWT access token as part of the speech request header. Before you can do this, you need to acquire an access token with your subscription key.<\/li>\n<li>The <strong><a href=\"https:\/\/www.microsoft.com\/cognitive-services\/en-us\/speech-api\/documentation\/overview\">Cognitive Service Speech API<\/a><\/strong> to recognize a user\u2019s voice commands.<\/li>\n<li><strong><a href=\"https:\/\/www.microsoft.com\/cognitive-services\/en-us\/luis-api\/documentation\/home\">LUIS<\/a><\/strong> to predict a user\u2019s intentions, which are interpreted and used to update cells in a web user interface<\/li>\n<\/ol>\n<h2 id=\"speech-to-text\">Speech to Text<\/h2>\n<p>Since Huma.AI is built with Node.js and React, we decided to make CellPainter with Node.js, which allows us to demonstrate integration with Cognitive Service Speech APIs in JavaScript.<\/p>\n<ol>\n<li><a href=\"https:\/\/www.microsoft.com\/cognitive-services\/en-us\/sign-up\">Sign up<\/a> for Microsoft Cognitive Services<\/li>\n<li>Get your keys for the Speech API<\/li>\n<\/ol>\n<p>With the API key <code class=\"highlighter-rouge\">clientSecret<\/code>, we acquire an access token for all subsequent speech API requests:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>var request = require('request');\r\n...\r\n\r\nrequest.post({\r\n    url: 'https:\/\/oxford-speech.cloudapp.net\/token\/issueToken',\r\n    form: {\r\n      'grant_type': 'client_credentials',\r\n      'client_id': encodeURIComponent(clientId),\r\n      'client_secret': encodeURIComponent(clientSecret),\r\n      'scope': 'https:\/\/speech.platform.bing.com'\r\n    }\r\n  }\r\n\r\n<\/code><\/pre>\n<\/div>\n<p>Then, with the access token and the audio data, we make a POST request to the Speech API endpoint:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>request.post({\r\n      url: 'https:\/\/speech.platform.bing.com\/recognize',\r\n      qs: {\r\n        'scenarios': 'ulm',\r\n        'appid': &lt;APPID&gt;,\r\n        'locale': 'en-US',\r\n        'device.os': 'wp7',\r\n        'version': '3.0',\r\n        'format': 'json',\r\n        'requestid': '1d4b6030-9099-11e0-91e4-0800200c9a66',\r\n        'instanceid': '1d4b6030-9099-11e0-91e4-0800200c9a66'\r\n      },\r\n      body: waveData,\r\n      headers: {\r\n        'Authorization': 'Bearer ' + accessToken,\r\n        'Content-Type': 'audio\/wav; samplerate=16000',\r\n        'Content-Length' : waveData.length\r\n      }\r\n    }\r\n<\/code><\/pre>\n<\/div>\n<h2 id=\"text-to-intent\">Text to Intent<\/h2>\n<p>Now that we have converted the user\u2019s spoken voice command into text using the Speech API, we are ready to determine a quantifiable intent from it using machine learning.<\/p>\n<h3 id=\"train-the-model\">Train the Model<\/h3>\n<p>Before we can use LUIS to determine intent, we need to create a new LUIS application to train a model for this use case by populating it with utterances, entities, and intents. <strong>Utterances<\/strong> are words the users might say. <strong>Entities<\/strong> are subjects you wish to identify within the utterances. <strong>Intents<\/strong> are the user\u2019s goals identified from the utterance.<\/p>\n<p>For example:<\/p>\n<ul>\n<li>Utterance: \u201cmove the red cell left\u201d<\/li>\n<li>Identified entities: [\u201cCellColor\u201d: \u201cred\u201d, \u201cdirection\u201d: \u201cleft\u201d]<\/li>\n<li>Identified intent: \u201cintent\u201d: \u201cMoveCell\u201d<\/li>\n<\/ul>\n<h4 id=\"train-with-data\">Train with Data<\/h4>\n<ul>\n<li><a href=\"https:\/\/www.luis.ai\/\">Create an account<\/a> with LUIS. Log into LUIS and create a new application. To learn more about how to use LUIS to train data for an application, you can <a href=\"https:\/\/www.luis.ai\/help#Video\">watch their tutorial video<\/a>.<\/li>\n<li>Add entities and train the model to identify this newly created entity. For example: \u201cCellColor\u201d, \u201cposition\u201d, \u201cdirection\u201d<\/li>\n<li>Add intents and train the model. If no intents are recognized, LUIS will return \u201cnone.\u201d For example: \u201cAddCell\u201d, \u201cMoveCell\u201d, \u201cdelete\u201d, \u201cNone\u201d<\/li>\n<li>Add many utterances to train the model. With each utterance added, LUIS will attempt to identify the relevant entities and intent.\n<ul>\n<li>If LUIS does not identify the intent correctly, you can train it by selecting the correct intent from the list of dropdowns.<\/li>\n<li>If the entities are not identified correctly, you can train it by clicking and highlighting the word in the utterance, then select the correct entity that matches the highlighted word. For example: For utterance \u201cadd a red cell,\u201d the identified intent should be \u201cAddCell\u201d and the word \u201cred\u201d LUIS should highlight it with the entity \u201cCellColor.\u201d<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p> <img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cse\/wp-content\/uploads\/sites\/55\/2016\/11\/luis_train.gif\" alt=\"Image luis train\" width=\"1191\" height=\"655\" class=\"aligncenter size-full wp-image-11081\" \/><\/p>\n<h4 id=\"training-publishing-and-feedback-loops\">Training, Publishing, and Feedback Loops<\/h4>\n<p>To improve the accuracy of the model, continue to add more utterances with variations in style and format to the LUIS application to improve identification of entities and intent. To test the model, publish the application to expose an HTTP endpoint.<\/p>\n<p> <img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cse\/wp-content\/uploads\/sites\/55\/2016\/11\/luis_publish.gif\" alt=\"Image luis publish\" width=\"998\" height=\"465\" class=\"aligncenter size-full wp-image-11080\" \/><\/p>\n<p>Submitting the query \u201cadd a blue cell to three,\u201d we receive the following JSON response:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"nt\">\"query\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"add a blue cell to three\"<\/span><span class=\"p\">,<\/span>\r\n  <span class=\"nt\">\"intents\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\r\n    <span class=\"p\">{<\/span>\r\n      <span class=\"nt\">\"intent\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"AddCell\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"score\"<\/span><span class=\"p\">:<\/span> <span class=\"mf\">0.992903054<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"actions\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\r\n        <span class=\"p\">{<\/span>\r\n          <span class=\"nt\">\"triggered\"<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\r\n          <span class=\"nt\">\"name\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"AddCell\"<\/span><span class=\"p\">,<\/span>\r\n          <span class=\"nt\">\"parameters\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\r\n        <span class=\"p\">}<\/span>\r\n      <span class=\"p\">]<\/span>\r\n    <span class=\"p\">},<\/span>\r\n<span class=\"err\">...<\/span>\r\n\r\n<span class=\"s2\">\"entities\"<\/span><span class=\"err\">:<\/span> <span class=\"p\">[<\/span>\r\n    <span class=\"p\">{<\/span>\r\n      <span class=\"nt\">\"entity\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"three\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"type\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"builtin.number\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"startIndex\"<\/span><span class=\"p\">:<\/span> <span class=\"mi\">19<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"endIndex\"<\/span><span class=\"p\">:<\/span> <span class=\"mi\">23<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"score\"<\/span><span class=\"p\">:<\/span> <span class=\"mf\">0.951857269<\/span>\r\n    <span class=\"p\">},<\/span>\r\n    <span class=\"p\">{<\/span>\r\n      <span class=\"nt\">\"entity\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"blue\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"type\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"CellColor\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"startIndex\"<\/span><span class=\"p\">:<\/span> <span class=\"mi\">6<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"endIndex\"<\/span><span class=\"p\">:<\/span> <span class=\"mi\">9<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"score\"<\/span><span class=\"p\">:<\/span> <span class=\"mf\">0.9930215<\/span>\r\n    <span class=\"p\">},<\/span>\r\n    <span class=\"p\">{<\/span>\r\n      <span class=\"nt\">\"entity\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"three\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"type\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"position\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"startIndex\"<\/span><span class=\"p\">:<\/span> <span class=\"mi\">19<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"endIndex\"<\/span><span class=\"p\">:<\/span> <span class=\"mi\">23<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"score\"<\/span><span class=\"p\">:<\/span> <span class=\"mf\">0.898235142<\/span>\r\n    <span class=\"p\">},<\/span>\r\n    <span class=\"p\">{<\/span>\r\n      <span class=\"nt\">\"entity\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"cell\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"type\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"CellType\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"startIndex\"<\/span><span class=\"p\">:<\/span> <span class=\"mi\">11<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"endIndex\"<\/span><span class=\"p\">:<\/span> <span class=\"mi\">14<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"score\"<\/span><span class=\"p\">:<\/span> <span class=\"mf\">0.9981711<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">],<\/span>\r\n<span class=\"err\">...<\/span>\r\n\r\n<\/code><\/pre>\n<\/div>\n<p>Each query made to the HTTP endpoint is tracked by LUIS. LUIS maintains the history of all the queries and the predicted intents and entities. This method helps us identify queries that ended in poor predictions. We can then feed those bad queries as utterances into our LUIS model and train it to identify the correct intents and entities instead. The next time a user utters a query with the same pattern, the model will correctly predict the intents and entities.<\/p>\n<h2 id=\"adding-intents-to-the-app\">Adding Intents to the App<\/h2>\n<p>Now that we have identified quantifiable intent for painting or manipulating cells from the user\u2019s original spoken commands, we can use the intents and entities returned in the prior section to perform the appropriate actions within the application.<\/p>\n<p>For example, if the JSON result returned from the LUIS application HTTP endpoint has identified the intent as the \u201cAddCell\u201d intent, then we look for the position and color entities in the JSON result for adding a cell.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>\r\nvar entities = resp[\"entities\"];\r\n\r\nif ( resp[\"intents\"][0][\"intent\"] === \"AddCell\" ) {\r\n    \/\/ WE WANT TO ADD A CELL, SO LOOK FOR POSITION AND COLOR\r\n\r\n    for ( var i = 0; i &lt; entities.length; i++ ) {\r\n        if ( entities[i][\"type\"] === \"CellColor\" ) {\r\n            addColor = entities[i][\"entity\"];\r\n        }\r\n        if ( entities[i][\"type\"] === \"builtin.number\" ) {\r\n            addPosition = entities[i][\"entity\"];\r\n        }\r\n    }\r\n\r\n    ...\r\n\r\n    addCell(addPosition, addColor);\r\n    ...\r\n}\r\n\r\n<\/code><\/pre>\n<\/div>\n<h2 id=\"custom-language-model\">Custom Language Model<\/h2>\n<p>With any natural language, certain words and phrases are specific or unique to a particular domain or context. For example, if users say \u201cadd a login button called foo,\u201d then the already-trained model may interpret the command as \u201cadd a login button called food.\u201d This error occurs because a model trained broadly on conversational phrases has most likely come across the word \u201cfood\u201d far more frequently than the software-specific term \u201cfoo.\u201d As a result, the model attempted to self-correct what it considered a statistically more accurate result. In such cases, we can enhance the baseline language model by adding words that are relevant to our context to derive a custom language model. We can do this by creating a <a href=\"https:\/\/cris.ai\/\">CRIS<\/a> application, then train the custom language model by feeding it with the specific words and phrases expected within the application\u2019s context. For the CellPainter example, you can import <a href=\"https:\/\/github.com\/ritazh\/speech-to-text-demo\/blob\/master\/cris.json\">cris.json<\/a> to train the custom language model on additional words, which we used to improve our results.<\/p>\n<h2 id=\"the-end-to-end-app\">The End-to-End App<\/h2>\n<h3 id=\"installation\">Installation<\/h3>\n<p>Clone the CellPainter repo and then install dependencies:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>    git clone https:\/\/github.com\/ritazh\/speech-to-text-demo.git\r\n    cd speech-to-text-demo\r\n    npm i\r\n<\/code><\/pre>\n<\/div>\n<p>Run the application then hit <code class=\"highlighter-rouge\">http:\/\/localhost:3000<\/code> in your browser:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>    node app.js\r\n<\/code><\/pre>\n<\/div>\n<p>Get your keys for Cognitive Services\u2019 Speech API and LUIS and plug them into the application:<\/p>\n<ul>\n<li>Follow <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/cognitive-services\/\">the steps in the Cognitive Services documentation<\/a> to create your LUIS app, then get your LUIS application ID and subscription key.<\/li>\n<li>To get the same trained LUIS app for painting cells, import ours using <a href=\"https:\/\/github.com\/ritazh\/speech-to-text-demo\/blob\/master\/cellmover.json\">cellmover.json<\/a>.<\/li>\n<li>To get the same context trained by CRIS, upload <a href=\"https:\/\/github.com\/ritazh\/speech-to-text-demo\/blob\/master\/cris.json\">cris.json<\/a> to create the same custom language model.<\/li>\n<\/ul>\n<p> <img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cse\/wp-content\/uploads\/sites\/55\/2016\/11\/demo.gif\" alt=\"Image demo\" width=\"956\" height=\"526\" class=\"aligncenter size-full wp-image-11078\" \/><\/p>\n<h2 id=\"opportunities-for-reuse\">Opportunities for Reuse<\/h2>\n<p>That\u2019s it! What we\u2019ve done here is leveraged pre-trained speech to text machine learning tasks developed by Microsoft Research to bring natural language processing to our application.<\/p>\n<p>We have also demonstrated that we can train our language model with CRIS to customize word recognition for vocabulary specific to an application\u2019s context. Despite the complexity of users\u2019 intents, we were able to train LUIS to help us derive variations of ways to convey intent by providing common ones we already anticipated. We\u2019ve applied the same architecture in many customer and partner use cases.<\/p>\n<p>Our <a href=\"https:\/\/github.com\/ritazh\/speech-to-text-demo.git\">solution for CellPainter<\/a> is on GitHub, which can serve as an example of how to enable natural language commands in your own application.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Using Microsoft Cognitive Services and LUIS to develop applications that leverage machine learning and speech recognition.<\/p>\n","protected":false},"author":21377,"featured_media":11079,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[19],"tags":[48,103,138,204,231,250],"class_list":["post-2126","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-machine-learning","tag-api-ai","tag-bing-speech-api","tag-custom-recognition-intelligent-service-cris","tag-huma-ai","tag-language-understanding-intelligent-service-luis","tag-microsoft-cognitive-services"],"acf":[],"blog_post_summary":"<p>Using Microsoft Cognitive Services and LUIS to develop applications that leverage machine learning and speech recognition.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/2126","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/users\/21377"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/comments?post=2126"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/2126\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media\/11079"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media?parent=2126"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/categories?post=2126"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/tags?post=2126"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}