{"id":603495,"date":"2019-08-14T15:13:55","date_gmt":"2019-08-14T22:13:55","guid":{"rendered":"https:\/\/www.microsoft.com\/en-us\/research\/?post_type=msr-blog-post&#038;p=603495"},"modified":"2019-08-22T12:09:42","modified_gmt":"2019-08-22T19:09:42","slug":"empowermd-accelerated-engineering-with-azure","status":"publish","type":"msr-blog-post","link":"https:\/\/www.microsoft.com\/en-us\/research\/articles\/empowermd-accelerated-engineering-with-azure\/","title":{"rendered":"EmpowerMD: Accelerated engineering with Azure"},"content":{"rendered":"<p><a href=\"https:\/\/www.microsoft.com\/en-us\/research\/people\/adunnith\/\">By Adi Unnithan, Software Engineer<\/a><\/p>\n<p>As a fast-moving team, EmpowerMD needed to be resourceful in building the <a href=\"https:\/\/www.microsoft.com\/en-us\/research\/project\/empowermd\/articles\/project-empowermd-ambient-intelligence-for-the-clinic-2\/\">Intelligent Scribe Service<\/a>. Using <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/aka.ms\/azurecompliance\">HITRUST certified and HIPAA compliant<span class=\"sr-only\"> (opens in new tab)<\/span><\/a> services on Azure, we were able to stay focused on building our product, keeping infrastructure and operational costs low. Here\u2019s an overview of the services we used to get productive quickly.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-605049 size-large\" src=\"https:\/\/www.microsoft.com\/en-us\/research\/wp-content\/uploads\/2019\/08\/BlogAzureDiagram-1024x625.png\" alt=\"EmpowerMD Azure Architecture\" width=\"1024\" height=\"625\" srcset=\"https:\/\/www.microsoft.com\/en-us\/research\/wp-content\/uploads\/2019\/08\/BlogAzureDiagram-1024x625.png 1024w, https:\/\/www.microsoft.com\/en-us\/research\/wp-content\/uploads\/2019\/08\/BlogAzureDiagram-300x183.png 300w, https:\/\/www.microsoft.com\/en-us\/research\/wp-content\/uploads\/2019\/08\/BlogAzureDiagram-768x469.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<h2>Azure App Service<\/h2>\n<p>We deploy both our frontend and backend to <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/en-us\/services\/app-service\/\">Azure App Service<span class=\"sr-only\"> (opens in new tab)<\/span><\/a>, a fully managed platform for hosting apps. App Service provides, among many other features, the ability to <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/app-service\/configure-authentication-provider-aad\">easily setup authentication<span class=\"sr-only\"> (opens in new tab)<\/span><\/a> with Azure Active Directory (AAD). This feature also enabled us to seamlessly, securely make calls between our frontend and backend.<\/p>\n<h2>Azure Functions<\/h2>\n<p>Every API call in our backend is a Node.js-based <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/en-us\/services\/functions\/\">Azure Function<span class=\"sr-only\"> (opens in new tab)<\/span><\/a>. These API calls are repeatable, stateless, and scalable\u2014we can easily scale up our resources to support a growing userbase. \u00a0By using Azure Functions we don\u2019t have to manage servers and we only pay when a function runs.<\/p>\n<p><a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/azure-functions\/durable\/durable-functions-overview\">Durable Functions<span class=\"sr-only\"> (opens in new tab)<\/span><\/a>, an extension of Azure Functions, helps us orchestrate complex scenarios like <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/azure-functions\/durable\/durable-functions-concepts#fan-in-out\">fan-out\/fan-in<span class=\"sr-only\"> (opens in new tab)<\/span><\/a> where we need to run several operations in parallel and wait for them to complete. Implementing fan-in can be complicated with many potential scaling, state management, and reliability issues. Durable Functions shrinks this complexity down to a single line of code.<\/p>\n<h2>Microsoft Graph<\/h2>\n<p>When dealing with medical data users should only see clinical encounters they are authorized to access. This is based on their membership in security groups within their organization. Depending on their role\u2014for example, a doctor, scribe, or transcriptionist\u2014they may have different permissions and capabilities within an encounter. This type of authorization scenario based on security groups was made much easier with the <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developer.microsoft.com\/en-us\/graph\">Microsoft Graph API<span class=\"sr-only\"> (opens in new tab)<\/span><\/a>.<\/p>\n<h2>Azure Cosmos DB<\/h2>\n<p>For storing data we use <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/en-us\/services\/cosmos-db\/\">Azure Cosmos DB<span class=\"sr-only\"> (opens in new tab)<\/span><\/a>, a schema-less NoSQL document database. This means that entities\u2014typically rows in a relational database\u2014are stored as denormalized JSON documents. These documents don\u2019t have a predefined structure or schema. This allows us to create entities in our database that look a lot closer to the objects in our application. As a result, we don&#8217;t have to think about the <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/en.wikipedia.org\/wiki\/Object-relational_impedance_mismatch\">intricacies<span class=\"sr-only\"> (opens in new tab)<\/span><\/a> of working with a relational database\u2014and this improves programmer productivity.<\/p>\n<p>Our team was proficient with MongoDB, a popular NoSQL database with considerable community support. Fortunately, Cosmos DB provides a <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/cosmos-db\/mongodb-introduction\">MongoDB API<span class=\"sr-only\"> (opens in new tab)<\/span><\/a> so we didn\u2019t have to learn a new API.<\/p>\n<h2>Azure Key Vault<\/h2>\n<p>Securely storing secrets, keys and certificates with auditing can be a difficult and error-prone process. <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/key-vault\/key-vault-whatis\">Azure Key Vault<span class=\"sr-only\"> (opens in new tab)<\/span><\/a> removes the need for us to manage this in a range of scenarios.<\/p>\n<h2>Azure Machine Learning<\/h2>\n<p>One of the most common problems in building an AI product is determining how to take an ML model that a data scientist has built and deploy it to production. We rely on <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/en-us\/services\/machine-learning-service\/\">Azure Machine Learning<span class=\"sr-only\"> (opens in new tab)<\/span><\/a> (Azure ML) to help us take care of \u201cMLOps\u201d (DevOps for machine learning) tasks such as this.<\/p>\n<p>Out of the box, Azure ML supports deploying a model with <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/palletsprojects.com\/p\/flask\/\">Flask<span class=\"sr-only\"> (opens in new tab)<\/span><\/a>, <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/www.nginx.com\/\">nginx<span class=\"sr-only\"> (opens in new tab)<\/span><\/a>, and a <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/en.wikipedia.org\/wiki\/Web_Server_Gateway_Interface\">WSGI server<span class=\"sr-only\"> (opens in new tab)<\/span><\/a>\u00a0to an endpoint hosted in <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/en-us\/services\/container-instances\/\">Azure Container Instances (ACI)<span class=\"sr-only\"> (opens in new tab)<\/span><\/a>. This can be a hassle to set up and even harder to scale out. AzureML provides the ability to configure and run a scalable deployment to <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/en-us\/services\/kubernetes-service\/\">Azure Kubernetes Service<span class=\"sr-only\"> (opens in new tab)<\/span><\/a>.<\/p>\n<p>Our data scientists were happy to not deal with infrastructure either. Azure Machine Learning can also help them automate the training, testing, and deployment of models through <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/machine-learning\/service\/concept-ml-pipelines\">AzureML Pipelines.<span class=\"sr-only\"> (opens in new tab)<\/span><\/a><\/p>\n<h2>Azure DevOps<\/h2>\n<p>Combining the power of Azure Machine Learning with <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/en-us\/services\/devops\/\">Azure DevOps<span class=\"sr-only\"> (opens in new tab)<\/span><\/a> can accelerate a variety of MLOps scenarios. Before Azure DevOps, developers needed to set up and manage services to support builds, releases, and code reviews. It can be frustrating to maintain all these separate infrastructure pieces much less configure them to know about each other.<\/p>\n<p>Using DevOps, we can submit and review pull requests built upon our familiarity of git. With the push of a button, we can run continuous integration and deployment to test, stabilization, and production environments. <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/en-us\/services\/devops\/artifacts\/\">Azure Artifacts<span class=\"sr-only\"> (opens in new tab)<\/span><\/a> gives us a private package repository with out-of-the-box support for Python pip and Node.js npm. <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/en-us\/services\/devops\/boards\/\">Azure Boards<span class=\"sr-only\"> (opens in new tab)<\/span><\/a> makes it easy to review and track work items.<\/p>\n<p>DevOps can weave these pieces of day-to-day development together. As an example, for healthcare compliance and auditability purposes we need to link pull requests and commits to work items.<\/p>\n<p>A DevOps release pipeline can continuously deploy models to Azure Machine Learning. Likewise, when model training code is checked in, a DevOps build pipeline is triggered as part of continuous integration. The CI process can also run an AzureML Pipeline to evaluate a newly trained model against a model running in production.<\/p>\n<h2>Azure Application Insights<\/h2>\n<p>If problems occur in our production services, we need to know right away and quickly determine how to fix it. <a class=\"msr-external-link glyph-append glyph-append-open-in-new-tab glyph-append-xsmall\" rel=\"noopener noreferrer\" target=\"_blank\" href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/azure-monitor\/app\/app-insights-overview\">Azure Application Insights<span class=\"sr-only\"> (opens in new tab)<\/span><\/a> is a powerful tool that lets us know of performance and functional issues in areas ranging from JavaScript code running in the browser to calls we make to Cosmos DB.<\/p>\n<p>&nbsp;<\/p>\n<p>The Azure platform has been vital to helping our team build a world-class healthcare AI product quickly. It&#8217;s stepped in where we needed reliable, compliant services and components. Moreover, it&#8217;s increased our product focus by taking care of routine, difficult, and detailed tasks. We\u2019re looking forward to using more of the Azure platform as we continue to build out the Intelligent Scribe Service.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Microsoft Azure was instrumental in helping us bootstrap fundamental components and services. This kept us focused on building our healthcare AI product.<\/p>\n","protected":false},"author":38526,"featured_media":0,"template":"","meta":{"msr-url-field":"","msr-podcast-episode":"","msrModifiedDate":"","msrModifiedDateEnabled":false,"ep_exclude_from_search":false,"_classifai_error":"","msr-content-parent":468111,"msr_hide_image_in_river":0,"footnotes":""},"research-area":[],"msr-locale":[268875],"msr-post-option":[],"class_list":["post-603495","msr-blog-post","type-msr-blog-post","status-publish","hentry","msr-locale-en_us"],"msr_assoc_parent":{"id":468111,"type":"project"},"_links":{"self":[{"href":"https:\/\/www.microsoft.com\/en-us\/research\/wp-json\/wp\/v2\/msr-blog-post\/603495","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.microsoft.com\/en-us\/research\/wp-json\/wp\/v2\/msr-blog-post"}],"about":[{"href":"https:\/\/www.microsoft.com\/en-us\/research\/wp-json\/wp\/v2\/types\/msr-blog-post"}],"author":[{"embeddable":true,"href":"https:\/\/www.microsoft.com\/en-us\/research\/wp-json\/wp\/v2\/users\/38526"}],"version-history":[{"count":40,"href":"https:\/\/www.microsoft.com\/en-us\/research\/wp-json\/wp\/v2\/msr-blog-post\/603495\/revisions"}],"predecessor-version":[{"id":605064,"href":"https:\/\/www.microsoft.com\/en-us\/research\/wp-json\/wp\/v2\/msr-blog-post\/603495\/revisions\/605064"}],"wp:attachment":[{"href":"https:\/\/www.microsoft.com\/en-us\/research\/wp-json\/wp\/v2\/media?parent=603495"}],"wp:term":[{"taxonomy":"msr-research-area","embeddable":true,"href":"https:\/\/www.microsoft.com\/en-us\/research\/wp-json\/wp\/v2\/research-area?post=603495"},{"taxonomy":"msr-locale","embeddable":true,"href":"https:\/\/www.microsoft.com\/en-us\/research\/wp-json\/wp\/v2\/msr-locale?post=603495"},{"taxonomy":"msr-post-option","embeddable":true,"href":"https:\/\/www.microsoft.com\/en-us\/research\/wp-json\/wp\/v2\/msr-post-option?post=603495"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}