CINXE.COM
Build Intelligent Apps On Azure Blog
<?xml version="1.0" encoding="utf-8"?> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"> <channel> <title>Build Intelligent Apps On Azure Blog</title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA</link> <description>Build Intelligent Apps On Azure Blog</description> <lastBuildDate>Thu, 15 Feb 2024 09:00:00 GMT</lastBuildDate> <docs>https://validator.w3.org/feed/docs/rss2.html</docs> <generator>https://github.com/jpmonette/feed</generator> <language>en</language> <item> <title><![CDATA[Kick-off #60Days of IA]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/kick-off</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/kick-off</guid> <pubDate>Thu, 15 Feb 2024 09:00:00 GMT</pubDate> <description><![CDATA[Combine the power of AI, cloud-scale data, and cloud-native app development to create highly differentiated digital experiences. Develop adaptive, responsive, and personalized experiences by building and modernizing intelligent applications with Azure.]]></description> <content:encoded><![CDATA[ <p>Let’s ride the buzz of AI with the focus on building intelligent apps using cloud-native technologies. Build '#IntelligentApps' brings to you a learning journey to build your skills on creating differentiated experiences while modernizing your applications. It’s time to 'learn it all'.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We’ll Cover<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/kick-off#what-well-cover" class="hash-link" aria-label="Direct link to What We’ll Cover" title="Direct link to What We’ll Cover"></a></h2> <ul> <li>What is Build Intelligent Apps?</li> <li>How Can I <em>participate</em>?</li> <li>How Can I <em>skill up</em>? (in just 60 Days)</li> <li><strong>Exercise:</strong> Take the <a href="https://aka.ms/build-ia/csc" target="_blank" rel="noopener noreferrer">Build Intelligent Apps Skills Challenge</a></li> </ul> <p><img loading="lazy" alt="Build intelligent apps" src="https://azure.github.io/Cloud-Native/assets/images/60-days-of-ia-cloud-skills-banner-026f80a6be3454d467eeb985c05866a9.jpg" width="1300" height="300" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-ready-to-build-intelligentapps-starting-february-19">Get Ready To Build #IntelligentApps starting February 19!<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/kick-off#get-ready-to-build-intelligentapps-starting-february-19" class="hash-link" aria-label="Direct link to Get Ready To Build #IntelligentApps starting February 19!" title="Direct link to Get Ready To Build #IntelligentApps starting February 19!"></a></h2> <p>Today, we kick off with content and activities for you to skill up on all things Intelligent Apps or AI Apps on Azure with content, events, and community interactions! Read on to learn about what is coming!</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="explore-our-initiatives">Explore Our Initiatives<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/kick-off#explore-our-initiatives" class="hash-link" aria-label="Direct link to Explore Our Initiatives" title="Direct link to Explore Our Initiatives"></a></h2> <p>We have a number of initiatives planned for the month to help you learn and skill up on relevant technologies. Click on the links to visit the relevant pages for each.</p> <ul> <li><a href="https://aka.ms/build-ia/60days" target="_blank" rel="noopener noreferrer">#60Days of IA</a> - 8 themed weeks of blogs on AI led application development</li> <li><a href="https://aka.ms/FallForIA/LearnLive" target="_blank" rel="noopener noreferrer">Learn Live Series</a> – 8 weekly live episodes on 'Kubernetes' and 'Serverless'</li> <li><a href="https://aka.ms/build-ia/ATE-series" target="_blank" rel="noopener noreferrer">Ask The Expert</a> – join live Q&A sessions with Product Engineering and Advocacy teams</li> <li><a href="https://aka.ms/build-ia/csc" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a> – skill up by competing with peers to complete modules</li> </ul> <p><img loading="lazy" alt="Build intelligent apps" src="https://azure.github.io/Cloud-Native/assets/images/60-days-of-ia-cloud-skills-modules-43a5b9ca105934979c7ce8cff3338a87.png" width="1920" height="1080" class="img_ev3q"></p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="register-for-the-events">Register for the events!<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/kick-off#register-for-the-events" class="hash-link" aria-label="Direct link to Register for the events!" title="Direct link to Register for the events!"></a></h2><p>What are 4 things you can do today, to jumpstart your learning journey?</p><ul> <li><strong>Register</strong> for live Q&A sessions (free, online)<!-- --> <ul> <li>February 29 – <a href="https://aka.ms/intelligent-apps/ate-aks/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Ask The Expert: Intelligent Apps with Azure Kubernetes Service</a></li> <li>March 7 – <a href="https://aka.ms/intelligent-apps/ate-cosmos/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Ask The Expert: Intelligent Apps with Azure Cosmos DB</a></li> <li>March 21 - <a href="https://aka.ms/intelligent-apps/ate-ai/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Ask The Expert: Intelligent Apps with Azure AI</a></li> <li>April 4 – <a href="https://aka.ms/intelligent-apps/ate-functions/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Ask The Expert: Intelligent Apps with Azure Functions</a></li> </ul> </li> <li><strong>Register</strong> for the <a href="https://aka.ms/intelligent-apps/aks-learnlive?ocid=buildia24_LL_website&ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Learn Live Series: Kubernetes Edition</a> – weekly live learning<!-- --> <ul> <li>February 21 – <a href="https://aka.ms/learn-live-building-intelligent-apps-aks-ep1?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Episode 1: Deploying Intelligent Apps with OpenAI on AKS</a></li> <li>February 28 – <a href="https://aka.ms/learn-live-building-intelligent-apps-aks-ep2?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Episode 2: Bring Your Own AI Models to Intelligent Apps on AKS with KAITO</a></li> <li>March 6 – <a href="https://aka.ms/learn-live-building-intelligent-apps-aks-ep3?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Episode 3: Enhance Observability of Your Intelligent Apps on AKS</a></li> <li>March 13 – <a href="https://aka.ms/learn-live-building-intelligent-apps-aks-ep4?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Episode 4: Taking Your Intelligent App Global with AKS</a></li> </ul> </li> <li><strong>Register</strong> for the <a href="https://aka.ms/aks-day?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Kubernetes Day at KubeCon, EU</a> to meet the product engineering teams in-person and learn about the new product capabilities for intelligent apps.</li> <li><strong>Complete</strong> the <a href="https://aka.ms/intelligent-apps/apps-csc?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a> to earn a Microsoft Learn badge – ends on <em>April 15</em>!</li> </ul></div></div> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="60days-of-intelligent-apps">#60Days Of Intelligent Apps<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/kick-off#60days-of-intelligent-apps" class="hash-link" aria-label="Direct link to #60Days Of Intelligent Apps" title="Direct link to #60Days Of Intelligent Apps"></a></h2> <p><a href="https://aka.ms/build-ia/60days" target="_blank" rel="noopener noreferrer">#60Days of IA</a> is a series of blog posts grouped into themed weeks - taking you from core concepts to end-to-end solution examples in 60 days. Each blog will provide conceptual lessons paired with exercises and resources to help you reinforce learnings and take next steps.</p> <p>This series takes you through learning journey in <strong>eight stages</strong>, each building on the previous week to help you skill up in a beginner-friendly way:</p> <ul> <li><strong>Week 1</strong>: Power of <a href="https://azure.microsoft.com/en-us/blog/build-next-generation-ai-powered-applications-on-microsoft-azure/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Applications</a></li> <li><strong>Week 2</strong>: <a href="https://learn.microsoft.com/en-us/azure/aks/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a> is the platform of choice for intelligent apps</li> <li><strong>Week 3</strong>: <a href="https://learn.microsoft.com/en-us/azure/cosmos-db/introduction?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Cosmos DB</a> is the database of choice for intelligent apps</li> <li><strong>Week 4</strong>: <a href="https://learn.microsoft.com/en-us/azure/ai-services/ai-services-and-ecosystem?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI</a> is your choice for <a href="https://www.microsoft.com/en-us/ai/responsible-ai?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Responsible AI</a></li> <li><strong>Week 5</strong>: Building an intelligent <a href="https://azure.microsoft.com/en-us/solutions/serverless/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">serverless</a> event driven <a href="https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview?pivots=programming-language-csharp?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">functions app</a></li> <li><strong>Week 6</strong>: Build intelligent microservices with <a href="https://learn.microsoft.com/en-us/azure/container-apps/overview?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">serverless containers</a></li> <li><strong>Week 7</strong>: <a href="https://learn.microsoft.com/en-us/platform-engineering/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Platform engineering</a> needs for your intelligent apps</li> <li><strong>Week 8</strong>: Managing cost for your intelligent apps</li> </ul> <p>We will start with defining intelligent apps and then expand on how to build with cloud-native technologies like <a href="https://azure.microsoft.com/en-us/products/kubernetes-service/?WT.mc_id=javascript-99907-ninarasi&ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a>, <a href="https://azure.microsoft.com/en-us/products/container-apps/?WT.mc_id=javascript-99907-ninarasi&?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Container Apps</a> and <a href="https://azure.microsoft.com/en-us/products/functions?WT.mc_id=javascript-99907-ninarasi&?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Functions</a>, as well as integrate AI and cloud-scale data. You will learn how to build end-to-end scenarios for real world application development based on <a href="https://learn.microsoft.com/en-us/azure/architecture/??ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">reference architectures</a>. Before we dive deep on intelligent apps, here is a high-level overview of the <strong>Intelligent Apps</strong> landscape on Azure for you to leverage the most comprehensive, trusted cloud to prime the customer and employee experiences.</p> <p><img loading="lazy" alt="intelligent apps on Azure" src="https://azure.github.io/Cloud-Native/assets/images/intelligent-apps-on-azure-3a921fedb320e7c7d903aebad7248d3b.png" width="1280" height="720" class="img_ev3q"></p> <p>Bring your applications to a modern application platform in the cloud, which leverages a cloud data platform at scale and agile development methods with DevOps is the best way to prime the customer and employee experiences. Azure offers the latest apps, data, AI and is the most comprehensive, trusted cloud.</p> <p><img loading="lazy" alt="intelligent apps" src="https://azure.github.io/Cloud-Native/assets/images/intelligent-apps-5fb4e761e294fadde7c79685bd415a00.png" width="1280" height="720" class="img_ev3q"></p> <p><strong>Containers on Azure</strong> services offer you a wide range of capabilities, from simplicity to control to suit your different needs.</p> <p><img loading="lazy" alt="containers on azure" src="https://azure.github.io/Cloud-Native/assets/images/Containers-on-Azure-98bc0be88024cfcfaab2150a56d0f9f9.jpg" width="1280" height="720" class="img_ev3q"></p> <p><img loading="lazy" alt="containers on azure" src="https://azure.github.io/Cloud-Native/assets/images/Containers-on-Azure-2-d540131359e93ea0f5da8bc2082fec3d.jpg" width="1280" height="720" class="img_ev3q"></p> <p>To start with the basics for developing <a href="https://azure.microsoft.com/en-us/products/kubernetes-service/?WT.mc_id=javascript-99907-ninarasi&ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Kubernetes</a> applications, explore <a href="https://azure.github.io/Cloud-Native/cnny-2023" target="_blank" rel="noopener noreferrer">#30Days of CloudNative</a>.</p> <p>Cloud-native development when paired with <strong>serverless computing</strong> enhances your solution architecture for building cost optimized, resilient applications.</p> <p><img loading="lazy" alt="serverless on Azure" src="https://azure.github.io/Cloud-Native/assets/images/serverless-on-azure-f9eb0000337edcfd1c86e90460767400.jpg" width="1280" height="720" class="img_ev3q"></p> <p>To start with the basics for <a href="https://azure.microsoft.com/solutions/serverless/?WT.mc_id=javascript-99907-ninarasi&?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">serverless computing</a>, explore <a href="https://azure.github.io/Cloud-Native/blog" target="_blank" rel="noopener noreferrer">#30DaysOfServerless</a>.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="lets-get-started">Let’s Get Started<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/kick-off#lets-get-started" class="hash-link" aria-label="Direct link to Let’s Get Started" title="Direct link to Let’s Get Started"></a></h2> <p>Now you know everything! We hope you are as excited as we are to dive into a full month of active learning and doing! Don't forget to <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/rss.xml" target="_blank" rel="noopener noreferrer">subscribe</a> for updates in your favorite feed reader. <strong>And, look out for our first Intelligent Apps blog on Monday, February 19!</strong></p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[1. Harnessing the power of Intelligent Apps]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/harnessing-the-power-of-intelligent-apps</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/harnessing-the-power-of-intelligent-apps</guid> <pubDate>Mon, 19 Feb 2024 09:00:00 GMT</pubDate> <description><![CDATA[Combine the power of AI, cloud-scale data, and cloud-native app development to create highly differentiated digital experiences. Develop adaptive, responsive, and personalized experiences by building and modernizing intelligent applications with Azure.]]></description> <content:encoded><![CDATA[ <p><img loading="lazy" alt="intelligent apps on Azure" src="https://azure.github.io/Cloud-Native/assets/images/harnessing-the-power-of-intelligent-apps-3b3c32d8c0893071a61077331b877218.jpg" width="1000" height="561" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="harnessing-the-power-of-intelligent-apps">Harnessing the Power of Intelligent Apps<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/harnessing-the-power-of-intelligent-apps#harnessing-the-power-of-intelligent-apps" class="hash-link" aria-label="Direct link to Harnessing the Power of Intelligent Apps" title="Direct link to Harnessing the Power of Intelligent Apps"></a></h2> <p>Organizations are increasingly adopting advanced technologies to drive innovation and elevate operational efficiency. Intelligent apps—applications that integrate machine learning (ML), data analytics, and predictive or generative artificial intelligence (AI) to create differentiated digital experiences—are one way to achieve this. According to Gartner®, “by 2026, 30% of new applications will use AI to drive personalized adaptive user interfaces, up from less than 5% today”<sup>1</sup>.</p> <p>Intelligent apps tend to fall into one of three categories:</p> <ul> <li><strong>Outcome-based apps</strong> — These apps focus on user intent, predictions, and task automation to enable better decision-making.</li> <li><strong>Functionality-based apps</strong> — These apps use ML, AI, or APIs to generate content. They examine user patterns to provide personalized recommendations or feedback.</li> <li><strong>Feature-based apps</strong> — These apps have AI or ML components built in, which means they rely on neural networks and internal LLMs to run advanced algorithms.</li> </ul> <p>Because Intelligent apps help organizations leverage business intelligence and other data to drive and automate organizational decision-making, they’re becoming a pivotal part of modern business strategies. In this article, we’ll spotlight the success stories of some organizations that have leveraged Microsoft Azure to create and deploy intelligent apps in their workflows and products.</p> <hr> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="intelligent-apps-in-action">Intelligent Apps in Action<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/harnessing-the-power-of-intelligent-apps#intelligent-apps-in-action" class="hash-link" aria-label="Direct link to Intelligent Apps in Action" title="Direct link to Intelligent Apps in Action"></a></h2> <p>Intelligent Apps offer tangible business outcomes by automating complex processes, enhancing decision-making, and providing personalized experiences. By leveraging Azure services, the organizations discussed below have experienced a paradigm shift in their operations — and a boost in productivity and agility.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-intelligent-apps-power-the-ultimate-lego-experience">How Intelligent Apps Power the Ultimate LEGO Experience<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/harnessing-the-power-of-intelligent-apps#how-intelligent-apps-power-the-ultimate-lego-experience" class="hash-link" aria-label="Direct link to How Intelligent Apps Power the Ultimate LEGO Experience" title="Direct link to How Intelligent Apps Power the Ultimate LEGO Experience"></a></h3> <p>Denmark’s ultimate LEGO experience center, LEGO House, found challenges in maintaining its on-premises data center. To keep serving its custom-built digital experiences, the business upgraded its facilities with <a href="https://azure.microsoft.com/en-us/products/kubernetes-service/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a> (AKS) in 2023.</p> <p>This shift in approach to the cloud was a boon for responsiveness — LEGO House could take on visitor feedback to swiftly update experiences and develop new ones. The containerized, component-based setup on AKS also allowed LEGO House’s digital tech stack to become more scalable and flexible, transforming development efficiency and maintenance.</p> <p>LEGO House continued its partnership with Microsoft to launch experiences like City Architect — powered by <a href="https://azure.microsoft.com/en-us/products/iot-edge?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure IoT Edge Device</a> — and Robo Lab. These innovations allowed visitors to interact with digitally projected landscapes and build robots, fostering principles of programming. AKS streamlines integration and supports element reuse, enhancing efficiency and creativity.</p> <p>The results were remarkable — improved stability, higher uptime, and positive visitor feedback. Azure services made life easier for LEGO House’s developers and gave the entire LEGO ecosystem a strong foundation for growth. Specifically, by allowing the reuse of elements, AKS provides a common foundation for all LEGO experience builds. The organization’s next move is to rebuild the entire House on the <a href="https://azure.microsoft.com/en-us/solutions/ai?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI</a> platform and AKS. Read more about how LEGO <a href="https://customers.microsoft.com/en-us/story/1703088157691224129-lego-house-azure-kubernetes-service-media-and-entertainment-denmark?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">modernized interactive experiences across LEGO House with Azure Kubernetes Service</a>.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="using-intelligent-apps-to-make-cars-smarter-with-tomtom">Using Intelligent Apps to Make Cars Smarter With TomTom<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/harnessing-the-power-of-intelligent-apps#using-intelligent-apps-to-make-cars-smarter-with-tomtom" class="hash-link" aria-label="Direct link to Using Intelligent Apps to Make Cars Smarter With TomTom" title="Direct link to Using Intelligent Apps to Make Cars Smarter With TomTom"></a></h3> <p>TomTom’s navigation solutions have a proven track record of innovating the driving experience. Today, the company continues to adapt to drivers’ evolving needs. Using <a href="https://azure.microsoft.com/en-us/products/ai-services/openai-service/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure OpenAI Service</a>, <a href="https://learn.microsoft.com/en-us/azure/cosmos-db/introduction?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Cosmos DB</a>, and <a href="https://azure.microsoft.com/en-us/products/kubernetes-service/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">AKS</a> to develop Digital Cockpit, TomTom has created smarter, AI-powered vehicles, facilitating huge advancements in user experience.</p> <p>Digital Cockpit is an AI-driven, conversational in-car infotainment system that allows drivers to interact naturally with the vehicle. It can perform tasks like navigation, controlling onboard systems, and even managing work tasks during electric vehicle recharging.</p> <p>Let’s look closer at the Azure services that drive Digital Cockpit:</p> <ul> <li><strong>Azure OpenAI Service</strong> — The Azure OpenAI Service supports generative AI chatbots that provide natural-sounding voices and accurate transcription of spoken audio.</li> <li><strong>Azure Cosmos DB</strong> — Azure Cosmos DB, a globally distributed database, retains customer conversations and preferences, allowing the system to continuously learn and tailor driver experiences.</li> <li><strong>AKS</strong> — AKS accelerates service deployment and scaling, enhancing overall architecture efficiency.</li> </ul> <p>Internally, integrating Azure services resulted in a significant improvement in TomTom’s development efficiency. For example, the team working on the prototype no longer required ten engineers — three team members were sufficient to complete the task. Additionally, response times decreased from 12 to 2.5 seconds, and the system demonstrated a 95 percent success rate in understanding complex driver requests. Read more about how <a href="https://customers.microsoft.com/en-us/story/1723808815413508250-tomtom-azure-netherlands?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">TomTom brings AI-powered, talking cars to life with Azure</a>.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Try the <a href="https://aka.ms/intelligent-apps/apps-csc?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps Skills Challenges</a> to compete for the leaderboard and earn a Microsoft Learn Badge.</p></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-gluwa-leverages-intelligent-apps-to-make-banking-more-accessible">How Gluwa Leverages Intelligent Apps to Make Banking More Accessible<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/harnessing-the-power-of-intelligent-apps#how-gluwa-leverages-intelligent-apps-to-make-banking-more-accessible" class="hash-link" aria-label="Direct link to How Gluwa Leverages Intelligent Apps to Make Banking More Accessible" title="Direct link to How Gluwa Leverages Intelligent Apps to Make Banking More Accessible"></a></h3> <p>San Francisco-based startup Gluwa is on a mission to address the financial gap for the unbanked and underbanked, estimated at 1.4 billion people globally. Combining blockchain technology and Azure services, Gluwa connects investors with individuals in emerging markets.</p> <p>Gluwa harnesses the capabilities of various Azure services to power its blockchain services. <a href="https://azure.microsoft.com/en-us/products/container-instances?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Container Instances</a> and AKS play a pivotal role in peer-to-peer discovery, fostering a dynamic and efficient environment. <a href="https://azure.microsoft.com/en-us/products/app-configuration?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure App Configuration</a> streamlines the centralization of app configurations, ensuring seamless control and adaptability.</p> <p>For secure media delivery, Gluwa relies on the powerful combination of <a href="https://azure.microsoft.com/en-us/products/cdn?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Content Delivery Network</a> and <a href="https://learn.microsoft.com/en-us/azure/storage/common/storage-introduction?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Storage</a>, which bolsters reliability and safeguards sensitive data. Using <a href="https://azure.microsoft.com/en-us/products/devops?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure DevOps</a> to manage intricate lifecycle builds, Gluwa streamlined the development process. <a href="https://azure.microsoft.com/en-us/products/app-service?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure App Services</a> serve as the backbone for Gluwa’s APIs, complemented by <a href="https://azure.microsoft.com/en-us/products/cache?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Redis</a> for optimal cache distribution, to enhance overall performance. Finally, <a href="https://azure.microsoft.com/en-us/products/azure-sql/database?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure SQL</a> and Azure Cosmos DB are scalable database solutions that support Gluwa’s infrastructure, ensuring adaptability and responsiveness in meeting evolving demands within the blockchain landscape.</p> <p>Gluwa’s decentralized financial platform, Gluwa Invest, encourages stable coin investments, while the Creditcoin blockchain records loans, providing transparency and immutability. Together, they’ve facilitated nearly 4.27 million loan transactions, totaling over $79.7 million. Gluwa turned to Azure’s reliable, scalable cloud foundation to make these innovative and socially impactful initiatives a reality. Read more about how <a href="https://customers.microsoft.com/en-us/story/1709609183358710412-gluwa-azure-banking-and-capital-markets-usa?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Gluwa uses blockchain to help investors fund loans to the unbanked</a>.</p> <hr> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/harnessing-the-power-of-intelligent-apps#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary"></a></h2> <p>Azure services have empowered organizations developing intelligent apps by offering scalability, flexibility, and seamless integration of ML, data analytics, and AI.</p> <p>Azure’s impact extends beyond immediate efficiency gains, empowering developers to iterate, learn, and keep creating new experiences. Businesses that build with Azure services can streamline collaboration across ecosystems, unlocking collective vision and applied creativity.</p> <p>Explore Microsoft <a href="https://customers.microsoft.com/en-us/home?sq=aks&ff=&p=1&so=story_publish_date%20desc&ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Customer Stories</a> for deeper insights into transformative, AI-powered solutions. Finally, don’t forget to mark your calendar for <a href="https://aka.ms/aks-day?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Kubernetes Day</a> at <a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-europe/" target="_blank" rel="noopener noreferrer">KubeCon EU 2024</a> to get the latest on cutting-edge developments in cloud technology.</p> <p><sup>1</sup> Source: <a href="https://www.gartner.com/en/articles/demand-grows-for-intelligent-applications-powered-by-ai" target="_blank" rel="noopener noreferrer">Gartner, Demand Grows for Intelligent Applications Powered by AI, September 27, 2023</a>. GARTNER is a registered trademark and service mark of Gartner, Inc. and/or its affiliates in the U.S. and internationally and is used herein with permission. All rights reserved.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[2. Power Up: Crafting an Intelligent Energy Forecasting Application Using Azure Kubernetes Service]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/power-up-crafting-an-intelligent-energy-forecasting-application-using-azure-kubernetes-service</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/power-up-crafting-an-intelligent-energy-forecasting-application-using-azure-kubernetes-service</guid> <pubDate>Tue, 27 Feb 2024 09:00:00 GMT</pubDate> <description><![CDATA[In this article, we’ll will guide you through creating an intelligent app that leverages Azure technologies, including Azure Kubernetes Service (AKS), to build an application that forecasts energy usage and pricing.]]></description> <content:encoded><![CDATA[ <p>At the forefront of recent technological innovation are intelligent apps: apps that use machine learning (ML), artificial intelligence (AI), and data analytics. These apps support smarter, data-driven decisions, making them particularly useful in sectors like energy management, where efficiency and long-term planning are critical.</p> <p>Our upcoming series will guide you through creating an intelligent app that leverages Azure technologies, including <a href="https://azure.microsoft.com/products/kubernetes-service?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a> (AKS), to build an application that forecasts energy usage and pricing.</p> <p>Your app will harness AKS for hosting and AI to analyze historical energy consumption data. Then, you’ll integrate the Kubernetes AI Toolchain Operator (KAITO) with with XGBoost and LLaMA 2 to build an intelligent app that underscores the importance of green energy practices and demonstrates the versatility and efficacy of Azure services.</p> <p>We invite you to join us on this three-part educational series, where you’ll learn the skills needed to construct your own intelligent apps. But, this series is more than a technical walkthrough: It’s an opportunity to engage with cutting-edge technologies and contribute to meaningful advancements in energy management.</p> <p>Whether you’re an experienced developer or new to the AI and ML sphere, this series will give you a glimpse into the future of application development and the strategic impact of Azure technologies in driving forward-thinking solutions.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-synergy-of-azure-kubernetes-service-and-intelligent-apps">The Synergy of Azure Kubernetes Service and Intelligent Apps<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/power-up-crafting-an-intelligent-energy-forecasting-application-using-azure-kubernetes-service#the-synergy-of-azure-kubernetes-service-and-intelligent-apps" class="hash-link" aria-label="Direct link to The Synergy of Azure Kubernetes Service and Intelligent Apps" title="Direct link to The Synergy of Azure Kubernetes Service and Intelligent Apps"></a></h2> <p>Using AKS as the backbone of intelligent apps has numerous benefits — especially when deploying your AI-driven application. AKS provides a managed, cloud-based container orchestration service that simplifies deploying, managing, and scaling AI-backed applications, making it ideal for a project like the one you’ll create in this series.</p> <p>One of the primary advantages of AKS is its ability to handle distributed applications with evolving demands. For AI-driven apps, the ability to scale resources based on computational demands is crucial. Because AKS allows for automatic scaling, intelligent apps have the necessary resources during peak analysis times without wasting resources during quieter periods. But this dynamic scalability isn’t just about handling loads efficiently: It’s also cost-effective, ensuring that you pay only for the resources you use.</p> <p>Integrating the KAITO operator with AKS further enhances the deployment of AI models like LLaMA 2 by simplifying the complexities of managing AI workloads. KAITO, designed specifically for Kubernetes environments, acts as a bridge between the advanced AI models and the scalable, managed infrastructure provided by AKS. It offers custom resource definitions (CRDs) tailored for AI applications, facilitating the deployment, updating, and management of AI models within the Kubernetes ecosystem.</p> <p>This seamless integration enables developers to focus more on the application logic and less on the underlying infrastructure, accelerating the development cycle and reducing the time to market for innovative AI solutions.</p> <p>AKS and KAITO create a robust, flexible, and efficient environment for developing and deploying intelligent applications. This combination not only leverages the cloud’s power and scalability but also optimizes the deployment of AI models, making it easier for developers to bring complex, data-driven applications to life.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Register for <strong><a href="https://developer.microsoft.com/en-us/reactor/events/21815/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps on AKS: Episode 2</a></strong>, a live hands-on training with an expert on how to use AKS to run your own AI models with KAITO.</p></div></div> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="laying-the-groundwork-with-azure-kubernetes-service">Laying the Groundwork with Azure Kubernetes Service<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/power-up-crafting-an-intelligent-energy-forecasting-application-using-azure-kubernetes-service#laying-the-groundwork-with-azure-kubernetes-service" class="hash-link" aria-label="Direct link to Laying the Groundwork with Azure Kubernetes Service" title="Direct link to Laying the Groundwork with Azure Kubernetes Service"></a></h2> <p>In the <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1" target="_blank" rel="noopener noreferrer">first installment of this series</a>, you’ll roll up your sleeves and set up an AKS environment. This step is foundational to the rest of the series, laying the groundwork for deploying and managing your application — and accessing the full scalability and flexibility that AKS offers.</p> <p>The article starts with a straightforward step-by-step guide on establishing the AKS environment, ensuring you have a solid base for the exciting journey ahead. This tutorial is succinct to maintain clarity and speedy development, offering links to additional resources for well-documented steps.</p> <p>Next, you’ll meet KAITO, a tool that streamlines deploying AI applications in Kubernetes environments. The core of this article is configuring <a href="https://github.com/Azure/kaito" target="_blank" rel="noopener noreferrer">the KAITO operator</a> to work seamlessly with the LLaMA 2 model, providing hands-on instructions, code samples, and screenshots to guide you through each step.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="adding-intelligence-to-the-app">Adding Intelligence to the App<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/power-up-crafting-an-intelligent-energy-forecasting-application-using-azure-kubernetes-service#adding-intelligence-to-the-app" class="hash-link" aria-label="Direct link to Adding Intelligence to the App" title="Direct link to Adding Intelligence to the App"></a></h2> <p>The <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2" target="_blank" rel="noopener noreferrer">second part of this series</a> dives into the more practical aspects of building the Intelligent App. You’ll leverage an open-source energy dataset alongside powerful tools like XGBoost and a custom Python API to craft a forecasting model that predicts future energy demands with speed and precision.</p> <p>Integrating these tools with AKS and Azure Container Registry highlights the high-impact relationship between robust data processing capabilities and scalable cloud infrastructure. Hands-on examples and streamlined code will guide you through setting up the environment, processing the dataset, and deploying the forecasting model.</p> <p>This practical application reinforces the theoretical foundations laid in Part 1 and sets the stage for advanced analytics and AI-driven predictions. As you progress through the tutorial, the focus will remain on simplicity and efficiency, ensuring that even complex AI-related processes become accessible.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Complete the <strong><a href="https://aka.ms/intelligent-apps/apps-csc?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps Skills Challenge</a></strong> to compete for the leaderboard and earn a Microsoft Learn Badge.</p></div></div> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="building-a-web-interface">Building a Web Interface<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/power-up-crafting-an-intelligent-energy-forecasting-application-using-azure-kubernetes-service#building-a-web-interface" class="hash-link" aria-label="Direct link to Building a Web Interface" title="Direct link to Building a Web Interface"></a></h2> <p>As the concluding installment of our series, <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3" target="_blank" rel="noopener noreferrer">part 3</a> assembles all the pieces by introducing a user-friendly web interface. Here, users can input or upload their energy usage data and parameters, after which the Intelligent App will generate future predictions on usage and pricing.</p> <p>This web front end serves as the direct point of interaction with your AKS-hosted application, seamlessly displaying the reports and predictions the AI model produces.</p> <p>After deploying this interface in the AKS environment established in <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1" target="_blank" rel="noopener noreferrer">part 1</a>, you’ll experience the complete cycle of developing an intelligent, data-driven application and appreciate how straightforward it is to engineer intelligent apps that can deliver tangible, user-centric outcomes.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="ready-to-get-started">Ready to Get Started?<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/power-up-crafting-an-intelligent-energy-forecasting-application-using-azure-kubernetes-service#ready-to-get-started" class="hash-link" aria-label="Direct link to Ready to Get Started?" title="Direct link to Ready to Get Started?"></a></h2> <p>Together, these three articles guide you through creating an innovative, AI-driven energy forecasting app. Setting up a scalable AKS environment with integrated cutting-edge AI models, processing open-source energy data for insightful predictions, and deploying a user-friendly web interface will equip you with the tools you need to build your own Intelligent Apps.</p> <p>Stay tuned for each part of the series and get ready to dive into the world of Azure, AI, and application development with us. Join us in this exciting venture and harness the power of technology to make a difference. Register for the <strong><a href="https://aka.ms/learn-live-building-intelligent-apps-aks-ep2?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps on AKS: Episode 2</a></strong> to experience live hands-on training with an expert on how to use AKS to run your own AI models with KAITO.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[2.1 Forecasting Energy Usage with Intelligent Apps Part 1: Laying the Groundwork with AKS, KAITO, and LLaMA]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1</guid> <pubDate>Tue, 05 Mar 2024 09:00:00 GMT</pubDate> <description><![CDATA[In this series, you’ll create an Intelligent App powered by Azure Kubernetes Service (AKS) to forecast energy usage and cost.]]></description> <content:encoded><![CDATA[ <p><img loading="lazy" alt="Forecasting Energy Usage with Intelligent Apps: Laying the Groundwork with AKS, KAITO, and LLaMA" src="https://azure.github.io/Cloud-Native/assets/images/2-1-1-f0fc40a7278794b517cea5c2e8b4a789.jpg" width="700" height="426" class="img_ev3q"></p> <p><em>This three-part series demonstrates how to create an Intelligent App that forecasts future energy consumption and pricing based on historical data. In this first article, you’ll set up an Azure Kubernetes Service (AKS) environment, install KAITO, and set up KAITO to work with the LLaMA 2 model.</em></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="forecasting-energy-usage-with-intelligent-apps-part-1-laying-the-groundwork-with-aks-kaito-and-llama">Forecasting Energy Usage with Intelligent Apps Part 1: Laying the Groundwork with AKS, KAITO, and LLaMA<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1#forecasting-energy-usage-with-intelligent-apps-part-1-laying-the-groundwork-with-aks-kaito-and-llama" class="hash-link" aria-label="Direct link to Forecasting Energy Usage with Intelligent Apps Part 1: Laying the Groundwork with AKS, KAITO, and LLaMA" title="Direct link to Forecasting Energy Usage with Intelligent Apps Part 1: Laying the Groundwork with AKS, KAITO, and LLaMA"></a></h2> <p>Intelligent Apps leverage artificial intelligence (AI) and machine learning (ML) technologies to enhance traditional applications with advanced capabilities. They enable businesses to make smarter decisions, automate tasks, and drive innovation by extracting actionable insights from vast amounts of data.</p> <p>In this series, you’ll create an Intelligent App powered by <a href="https://azure.microsoft.com/en-ca/products/kubernetes-service" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a> (AKS) to forecast energy usage and cost. Each article will demonstrate the use of core Azure technologies, particularly AKS, to build an application that generates forecasts based on AI capabilities applied to user input and historical data analysis.</p> <p>Let’s get started!</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites"></a></h3> <p>To follow this tutorial, ensure you have the following:</p> <ul> <li>An <a href="https://azure.microsoft.com/en-us/free/search" target="_blank" rel="noopener noreferrer">Azure Subscription</a> that supports the GPU-enabled <a href="https://learn.microsoft.com/en-us/azure/virtual-machines/ncv3-series" target="_blank" rel="noopener noreferrer">Standard_NC12s_v3 instance type</a> in the selected region. You might need to request an increase in vCPU quota.</li> <li>Basic understanding of <a href="https://azure.microsoft.com/en-us/products/kubernetes-service" target="_blank" rel="noopener noreferrer">AKS</a> and Kubernetes</li> </ul> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="building-an-intelligent-app-with-azure-kubernetes-service-and-kaito">Building an Intelligent App with Azure Kubernetes Service and KAITO<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1#building-an-intelligent-app-with-azure-kubernetes-service-and-kaito" class="hash-link" aria-label="Direct link to Building an Intelligent App with Azure Kubernetes Service and KAITO" title="Direct link to Building an Intelligent App with Azure Kubernetes Service and KAITO"></a></h3> <p>This first article walks you through setting up an AKS environment and the Kubernetes AI Toolchain Operator (KAITO) to automate AI/ML model deployment in the AKS cluster.</p> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="downloading-the-llama-2-model">Downloading the LLaMA 2 Model<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1#downloading-the-llama-2-model" class="hash-link" aria-label="Direct link to Downloading the LLaMA 2 Model" title="Direct link to Downloading the LLaMA 2 Model"></a></h4> <p>A fundamental piece in your Intelligent App’s architecture is the target model. Here, you’ll use LLaMA 2, an open-source project developed by Meta in partnership with Microsoft.</p> <p>LLaMA 2 is a large-scale training and inference framework for ML models. It provides a distributed computing infrastructure that enables executing ML tasks across multiple nodes or clusters, using parallelism and optimization techniques to improve performance.</p> <p>To configure your model, download LLaMA 2 by following the instructions in <a href="https://github.com/Azure/kaito/tree/main/presets/models/llama2" target="_blank" rel="noopener noreferrer">this document</a>. Ensure you download the LLaMA 2 7B Chat (llama2-7b-chat) model.</p> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="configuring-the-aks-cluster-and-kaito">Configuring the AKS Cluster and KAITO<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1#configuring-the-aks-cluster-and-kaito" class="hash-link" aria-label="Direct link to Configuring the AKS Cluster and KAITO" title="Direct link to Configuring the AKS Cluster and KAITO"></a></h4> <p><img loading="lazy" alt="engergy-usage-aks model" src="https://azure.github.io/Cloud-Native/assets/images/2-1-2-330abba56cfa621014fbd395b9b6297c.jpg" width="1484" height="694" class="img_ev3q"></p> <p>Creating an AKS environment is the first step for onboarding large AI inference models onto Kubernetes. Later, you’ll integrate the node provisioner controller with AKS APIs, letting you dynamically add GPU nodes to the cluster to promote scalability and optimal resource use.</p> <p>Additionally, AKS facilitates testing service endpoints within the cluster, providing a reliable environment for validating and fine-tuning AI inference services.</p> <p>KAITO is an open-source operator that transforms how you deploy AI models on Kubernetes. It streamlines the process, automating critical tasks like infrastructure provisioning and resource optimization. It intelligently selects the optimal hardware configuration for your specific model, using available CPU and GPU resources on AKS. KAITO eliminates the manual setup complexities, accelerating your deployment time and reducing associated costs.</p> <p>To set up an AKS cluster and install KAITO, follow <a href="https://github.com/Azure/kaito/blob/main/docs/installation.md" target="_blank" rel="noopener noreferrer">this tutorial</a>, adjusting the KAITO installation steps to match the <strong>llama2-7b</strong> model you downloaded earlier.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Checkout the <strong><a href="https://aka.ms/learn-live-building-intelligent-apps-aks-ep2?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps on AKS: Episode 2</a></strong>, a hands-on training with an expert on how to use AKS to run your own AI Models with KAITO.</p></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="pushing-llama-2-chat-model-to-azure-container-registry">Pushing LLaMA 2 Chat Model to Azure Container Registry<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1#pushing-llama-2-chat-model-to-azure-container-registry" class="hash-link" aria-label="Direct link to Pushing LLaMA 2 Chat Model to Azure Container Registry" title="Direct link to Pushing LLaMA 2 Chat Model to Azure Container Registry"></a></h4> <p>Now that you have AKS with the KAITO installation, you need to push the local model image to the AKS cluster.</p> <p>Create an Azure Container Registry (ACR) resource using Azure CLI with the following command, replacing <code><YOUR-ACR-NAME></code> with a new ACR name:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az acr create --name <YOUR-ACR-NAME> --resource-group $RESOURCE_GROUP --sku Standard --location $LOCATION</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Now, push your local LLaMA 2 model’s Docker image to the ACR hosted at <code><YOUR-ACR-NAME>.azurecr.io</code> by running:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">docker push <YOUR-ACR-NAME>.azurecr.io/llama2_7b_chat_model:latest</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Finally, run the command to update the AKS cluster to attach it to your ACR, allowing the cluster to pull the model container image from <code><YOUR-ACR-NAME>.azurecr.io</code>:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az aks update -g $RESOURCE_GROUP -n $MY_CLUSTER --attach-acr <YOUR-ACR-NAME></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="starting-the-inference-service">Starting the Inference Service<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1#starting-the-inference-service" class="hash-link" aria-label="Direct link to Starting the Inference Service" title="Direct link to Starting the Inference Service"></a></h4> <p>After installing KAITO, run the following command to start a <code>llama-2-7b</code> inference service, replacing <code><YOUR-ACR-NAME></code> with the ACR name you created previously:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$ cat examples/kaito_workspace_llama2_7b.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: kaito.sh/v1alpha1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: Workspace</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> name: workspace-llama-2-7b</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">resource:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> instanceType: "Standard_NC12s_v3"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> labelSelector:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> matchLabels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> apps: llama-2-7b-chat</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">inference:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> preset:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> name: "llama-2-7b-chat"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> accessMode: private</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> presetOptions:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> image: <YOUR-ACR-NAME>.azurecr.io/llama2_chat_model:latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> imagePullSecrets:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> - energy-usage-secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">$ kubectl apply -f examples/kaito_workspace_llama2_7b-chat.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Kubernetes uses this YAML code to instantiate a workspace resource with the specified configurations. This enables deploying and managing inference workloads within the cluster.</p> <p>You can monitor the workspace status by executing the command below. The model deployment has been completed once the <code>WORKSPACEREADY</code> column becomes <code>True</code>:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$ kubectl get workspace workspace-llama-2-7b-chat</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| NAME | INSTANCE | RESOURCEREADY | INFERENCEREADY | WORKSPACEREADY | AGE |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| workspace-llama-2-7b-chat | Standard_NC12s_v3 | True | True | True | 4d2h |</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p><strong>Note</strong>: Achieving machine and workspace readiness may take up to 20 minutes.</p> <p>Now, run the command below to find the inference service’s cluster IP:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$ kubectl get svc workspace-llama-2-7b-chat</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| NAME | TYPE | CLUSTER-IP | EXTERNAL-IP | PORT(S) | AGE |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| workspace-llama-2-7b-chat | ClusterIP | <CLUSTERIP> | <none> | 80/TCP,29500/TCP | 4d2h |</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Finally, run a curl pod to test the service endpoint in the cluster:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">export CLUSTERIP=$(kubectl get svc workspace-llama-2-7b-chat -o jsonpath="{.spec.clusterIPs[0]}")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">$ kubectl run -it --rm --restart=Never curl --image=curlimages/curl -- curl -X POST http://$CLUSTERIP/generate -H "accept: application/json" -H "Content-Type: application/json" -d "{\"input_data\": {\"input_string\":[[ {\"role\": \"user\", \"content\": \"What is the capital of India?\"}]]}, \"parameters\": {\"max_gen_len\": 64, \"temperature\": 0}}"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>You should receive these results:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{"results":[[{"role":"User","content":"What is the capital of India?"},{"role":"Assistant","content":" The capital of India is New Delhi."}]]}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p><strong>Note</strong>: You can test with your own questions, but there may be inaccuracies within the response. This is because AKS hasn’t fine-tuned the model for your scenario.</p> <p>That’s it! You’ve successfully established your AKS environment and familiarized yourself with setting up KAITO to deploy the LLaMA 2 model within your Kubernetes environment. You’re now ready to analyze a model and make predictions using Azure’s AI services.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps">Next Steps<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1#next-steps" class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps"></a></h2> <p>In this article, you established an AKS cluster and configured KAITO to integrate with the LLaMA 2 model for advanced ML capabilities. In part 2, you’ll use AKS and KAITO to analyze historical energy consumption data with advanced ML models. You’ll create a dynamic web interface for users to input data, generate predictions, and visualize results seamlessly.</p> <p>Be sure to join the <a href="https://azure.github.io/Cloud-Native/Build-IA/CloudSkills" target="_blank" rel="noopener noreferrer">Cloud Skill Challenge</a> to level up your cloud computing skills and gain hands-on experience. You can also register for the <a href="https://aka.ms/learn-live-building-intelligent-apps-aks-ep3?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">next episode</a> on <strong>Intelligent Apps with Azure Kubernetes Service</strong>, an instructor led live learning experience to deploy your app on AKS. And, join the AKS product and engineering team at <em>KubeCon EU 2024</em>—the premier conference for cloud-native technologies, for <strong>AKS <a href="https://aka.ms/aks-day" target="_blank" rel="noopener noreferrer">Customer</a> and <a href="https://aka.ms/aks-lab-day" target="_blank" rel="noopener noreferrer">Lab</a> Days</strong>.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[2.2 Forecasting Energy Usage with Intelligent Apps Part 2]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2</guid> <pubDate>Tue, 05 Mar 2024 09:05:00 GMT</pubDate> <description><![CDATA[In this series, you’ll create an Intelligent App powered by Azure Kubernetes Service (AKS) to forecast energy usage and cost.]]></description> <content:encoded><![CDATA[ <p><img loading="lazy" alt="Graphic of a bar chart with a magnifying glass in front of it. To the left of the magnifying glass is a lightning bolt. At the bottom of the graphic is text that reads, &quot;Forecasting Energy Usage with Intelligent Apps: Making Predictions.&quot;" src="https://azure.github.io/Cloud-Native/assets/images/2-2-1-5d5b7a390c60123a537e7ab426daafcc.png" width="624" height="380" class="img_ev3q"></p> <p><em>This three-part series demonstrates how to create an Intelligent App that forecasts future energy consumption and pricing based on historical data. In this second article, you’ll build out an app that analyzes historical data on energy consumption to build a forecasting model that forecasts future energy usage/pricing based on parameters input by the user.</em></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="forecasting-energy-usage-with-intelligent-apps-part-2-making-predictions">Forecasting Energy Usage with Intelligent Apps Part 2: Making Predictions<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2#forecasting-energy-usage-with-intelligent-apps-part-2-making-predictions" class="hash-link" aria-label="Direct link to Forecasting Energy Usage with Intelligent Apps Part 2: Making Predictions" title="Direct link to Forecasting Energy Usage with Intelligent Apps Part 2: Making Predictions"></a></h2> <p>In <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1" target="_blank" rel="noopener noreferrer">Part 1 of this series</a>, you set up an <a href="https://azure.microsoft.com/products/kubernetes-service?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a> (AKS) cluster, installed <a href="https://azure.microsoft.com/updates/preview-ai-toolchain-operator-addon-for-aks/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Kubernetes AI Toolchain Operator</a> (KAITO), and configured KAITO with Llama 2. In this article, you’ll use the groundwork from Part 1 to build the Intelligent App.</p> <p>Using historical data analysis and an open-source dataset, you’ll construct a model capable of predicting future energy usage and pricing with the flexibility of user-defined parameters.</p> <p>Let’s get started!</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites"></a></h3> <p>To follow this tutorial, ensure you:</p> <ul> <li>Completed Part 1 of this series</li> <li>Have a Jupyter notebook or a preferred Python integrated development environment (IDE), like <a href="https://code.visualstudio.com/" target="_blank" rel="noopener noreferrer">Visual Studio Code</a>, downloaded</li> <li><a href="https://kubernetes.io/docs/tasks/tools/" target="_blank" rel="noopener noreferrer">kubectl</a>, the Kubernetes command-line tool, installed</li> <li>The <a href="https://github.com/contentlab-io/Microsoft-Forecasting-Energy-Usage-with-Intelligent-Apps/tree/main/Part%202" target="_blank" rel="noopener noreferrer">Forecast API source code</a> downloaded</li> </ul> <p>For a sneak peek of the final product, check out the <a href="https://github.com/contentlab-io/Microsoft-Forecasting-Energy-Usage-with-Intelligent-Apps/tree/main/Part%202" target="_blank" rel="noopener noreferrer">complete project code</a>.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Checkout the <a href="https://aka.ms/learn-live-building-intelligent-apps-aks-ep3?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps on AKS: Episode 3</a>, a technical deep dive hands-on training with an expert on how OpenCost, Prometheus, and Grafana with AKS can improve intelligent apps.</p></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="predicting-energy-consumption-and-pricing-with-an-intelligent-app">Predicting Energy Consumption and Pricing with an Intelligent App<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2#predicting-energy-consumption-and-pricing-with-an-intelligent-app" class="hash-link" aria-label="Direct link to Predicting Energy Consumption and Pricing with an Intelligent App" title="Direct link to Predicting Energy Consumption and Pricing with an Intelligent App"></a></h3> <p>The Intelligent App will analyze historical data on energy consumption to build a regression model. For this tutorial, you’ll use an open-source <a href="https://www.kaggle.com/datasets/nicholasjhana/energy-consumption-generation-prices-and-weather" target="_blank" rel="noopener noreferrer">Kaggle dataset</a> named “Hourly energy demand generation and weather.”</p> <p>At a high level, you’ll take the following steps to build the Intelligent App:</p> <ul> <li><strong>Dataset analysis and feature engineering</strong>—You’ll start by examining the dataset. For this tutorial, you want to understand the relationships between energy consumption, pricing, and influencing factors like time. You’ll engineer new features from the raw data. This includes working hours, the day of the week, and the month.</li> <li><strong>Model training</strong>—You’ll use XGBoost as a suitable regression model, as it accounts for both time elements and external factors. You’ll train it using the processed Kaggle dataset. The goal is to teach our model to identify patterns and make reliable predictions of electricity prices.</li> <li><strong>User input</strong>—The app will let users provide parameters, such as a date, time, amount of electricity generated from burning, and more. The model will use these inputs to generate predictions.</li> <li><strong>Report generation</strong>—Llama2 will come into play here. It will help you create a clear and informative report summarizing the user’s input, the model’s predictions, and any insights derived from the analysis.</li> </ul> <p><strong>Note:</strong> To keep this article focused, we’ll assume you have a pre-cleaned dataset with engineered features. If you’d like to see the details of this process, <a href="https://github.com/contentlab-io/Microsoft-Forecasting-Energy-Usage-with-Intelligent-Apps/blob/main/Part%202/data/predicting-future-energy-pricing.ipynb" target="_blank" rel="noopener noreferrer">refer to this notebook</a>.</p> <p>With the steps above completed, you need to split the data into training and testing sets using the code below. Doing so allows you to predict “price actual” — the target feature for this tutorial.</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Define the target feature </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">target = 'price actual' </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Split data into feature matrix (X) and target vector (y) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">X, y = df.drop(columns=target), df[target] </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Split the data into training and testing sets </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Next, use the code below to define a function to train your model.</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">def train_xgboost_regressor(X_train, y_train, X_test, y_test): </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> """ </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Train an XGBoost regressor using cross-validation, tune hyperparameters, and evaluate the model. </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Parameters: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> X_train (DataFrame): The DataFrame containing the training features. </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> y_train (Series): The Series containing the training target variable. </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> X_test (DataFrame): The DataFrame containing the testing features. </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> y_test (Series): The Series containing the testing target variable. </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Returns: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> float: Mean squared error (MSE) of the model. </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> float: R-squared (R2) score of the model. </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> """ </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Define the XGBoost regressor </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> xgb_regressor = xgb.XGBRegressor() </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Define parameter grid for hyperparameter tuning </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> param_grid = { </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> 'learning_rate': [0.05, 0.1], </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> 'max_depth': [3, 5, 7], </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> #'min_child_weight': [1, 3, 5], </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> #'subsample': [0.6, 0.8, 1.0], </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> #'colsample_bytree': [0.6, 0.8, 1.0], </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> #'gamma': [0, 0.1, 0.2] </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Perform GridSearchCV for hyperparameter tuning </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> grid_search = GridSearchCV(estimator=xgb_regressor, param_grid=param_grid, cv=5, scoring='neg_mean_squared_error', verbose=1) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> grid_search.fit(X_train, y_train) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Get the best parameters </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> best_params = grid_search.best_params_ </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Initialize XGBoost regressor with best parameters </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> best_xgb_regressor = xgb.XGBRegressor(**best_params) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Perform cross-validation </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> cv_scores = cross_val_score(best_xgb_regressor, X_train, y_train, cv=5, scoring='neg_mean_squared_error') </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Train the XGBoost regressor on the full training set </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> best_xgb_regressor.fit(X_train, y_train) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Make predictions on the test set </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> y_pred = best_xgb_regressor.predict(X_test) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Save the model </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> save_model(best_xgb_regressor, 'xgb_model.joblib') </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Calculate MSE and R2 score </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> rmse = root_mean_squared_error(y_test, y_pred) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> r2 = r2_score(y_test, y_pred) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return rmse, r2 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">rmse, r2 = train_xgboost_regressor(X_train, y_train, X_test, y_test) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">print("Test RMSE:", rmse) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">print("Test R2 Score:", r2) </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>The output of the code snippet above should look like the following:</p> <p><img loading="lazy" alt="Screenshot of output code in the terminal. It reads, &quot;Fitting 5 folds for each of 6 candidates, totalling 30 fits Test RMSW: 5.738308690044228 Test R2 Score: 0.8378464489048971" src="https://azure.github.io/Cloud-Native/assets/images/2-2-2-fd8c7337125621030a8d3db77f8b5979.png" width="624" height="55" class="img_ev3q"></p> <p>After fitting the model with cross-validation and hyperparameter tuning, you’ll see an average root mean squared error (RMSE) of approximately 5.74 and an R-squared (R2) score of about 0.84 on the test data. So, the R-squared values show promising performance in predicting energy prices!</p> <p>Next, you’ll create the Forecast API, set up its communication with Llama2, and deploy it onto your AKS cluster.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Complete the <a href="https://aka.ms/intelligent-apps/apps-csc?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps Skills Challenge</a> to compete for the leaderboard and earn a Microsoft Learn Badge.</p></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="setting-up-the-backend-service">Setting Up the Backend Service<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2#setting-up-the-backend-service" class="hash-link" aria-label="Direct link to Setting Up the Backend Service" title="Direct link to Setting Up the Backend Service"></a></h4> <p>In the sections that follow, you’ll deploy a simple Python service named “Forecast API.” This service will have an endpoint called <code>predict-chat</code> that will interact with the Llama2 Chat inference service within your AKS cluster. But first, you’ll set up a backend service.</p> <p>Unzip the <a href="https://github.com/contentlab-io/Microsoft-Forecasting-Energy-Usage-with-Intelligent-Apps/tree/main/Part%202" target="_blank" rel="noopener noreferrer">source code</a> that accompanies this article. It contains the files necessary to run your Python API using the Flask library, including the following:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Name </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">---- </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">app.py </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">deployment.yaml </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Dockerfile </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">requirements.txt </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">service.yaml </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Open the <code>app.py</code> file:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">from flask import Flask, request, jsonify </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import os </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import requests </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">app = Flask(__name__) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">GENERATE_ENDPOINT_CHAT = os.environ.get('GENERATE_ENDPOINT_CHAT') </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">@app.route('/predict-chat', methods=['POST']) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">def predict_chat(): </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> try: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> data = request.get_json() </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> gen_fossil_brown_coal = data.get('gen_fossil_brown_coal') or 582.0 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> gen_fossil_gas = data.get('gen_fossil_gas') or 5537.0 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> gen_fossil_hard_coal = data.get('gen_fossil_hard_coal') or 4039.0 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> gen_fossil_oil = data.get('gen_fossil_oil') or 331.0 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> gen_hydro = data.get('gen_hydro') or 454.0 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> gen_other_renewable = data.get('gen_other_renewable') or 97.0 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> gen_wind_onshore = data.get('gen_wind_onshore') or 7556.0 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> total_load_actual = data.get('total_load_actual') or 31648.0 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> price = data.get('price') or 40.61 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> max_gen_len = data.get('max_gen_len') or 1024 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> temperature = data.get('temperature') or 0.0 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> prompt = f"""Display the following report table based on user inputs in tabular text format and write a single-paragraph report summarizing the electricity usage and forecast price: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> ### Table </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Generation from fossil brown coal/lignite: {gen_fossil_brown_coal} MW </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Generation from fossil gas: {gen_fossil_gas} MW </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Generation from fossil hard coal: {gen_fossil_hard_coal} MW </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Generation from fossil oil: {gen_fossil_oil} MW </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Generation from hydro pumped storage: {gen_hydro} MW </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Generation from other renewable sources: {gen_other_renewable} MW </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Generation from onshore wind: {gen_wind_onshore} MW </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> ### Totals: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Total actual load: {total_load_actual} MW </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Forecast price: {price} EUR/MWh </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> ### Short analysis: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Please write a short analysis on the data above.""" </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> generate_response = requests.post(GENERATE_ENDPOINT_CHAT, json={ </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "input_data": {"input_string":[[ {"role": "user", "content": prompt}]]}, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "parameters": {"max_gen_len": max_gen_len, "temperature": temperature} </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> if generate_response.status_code == 200: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return generate_response.json(), 200 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> else: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return jsonify({'error': 'Failed to invoke generate endpoint'}), 500 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> except Exception as e: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return jsonify({'error': str(e)}), 500 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">if __name__ == '__main__': </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> app.run(debug=True) </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Let’s review what the code inside the <code>app.py</code> file is doing.</p> <ul> <li>The <code>app.py</code> file is an API endpoint for generating a report on electricity usage and forecasted price based on user-provided input data.</li> <li>When a POST request is received by the <code>/predict-chat</code> endpoint, the application extracts the input data from the request, including parameters like generation from different energy sources, total actual load, price, and additional settings like <code>max_gen_len</code> and <code>temperature</code>. Note that for now, the app sends dummy values. In Part 3, you’ll update your app to take real values from the user and predict the electricity price using the prediction model.</li> <li>Then, the app constructs a prompt containing the input data and sends a request to another endpoint, specified by the <code>GENERATE_ENDPOINT_CHAT</code> environment variable, to generate a response. The response includes the report table in tabular text format and a short data analysis.</li> <li>If the generation request is successful, the application returns a report produced with the generative capabilities of Llama 2 Chat, which is hosted as an inference service in your AKS cluster.</li> </ul> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="building-and-pushing-to-acr">Building and Pushing to ACR<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2#building-and-pushing-to-acr" class="hash-link" aria-label="Direct link to Building and Pushing to ACR" title="Direct link to Building and Pushing to ACR"></a></h5> <p>Run the following commands to build the image locally and push it to your Azure Container Registry (ACR). Be sure to replace username and password with your <code>username</code> and <code>password</code>.</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">sudo docker build --no-cache -f Dockerfile -t forecast-api -t <YOUR-ACR-NAME>.azurecr.io/forecast-api:latest . </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">docker login <YOUR-ACR-NAME>.azurecr.io --username <username> --password-stdin <password> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">docker push <YOUR-ACR-NAME>.azurecr.io/forecast-api:latest </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="connecting-to-aks">Connecting to AKS<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2#connecting-to-aks" class="hash-link" aria-label="Direct link to Connecting to AKS" title="Direct link to Connecting to AKS"></a></h5> <p>Start by making sure you’re logged in to Azure and that you have the correct AKS credentials by running the following:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az login --tenant <YOUR-AZURE-TENANT-ID> </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Next, run the following commands:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">export RESOURCE_GROUP=<YOUR-RESOURCE-GROUP> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export MY_CLUSTER=<YOUR-AKS-CLUSTER-NAME> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export LOCATION=<YOUR-LOCATION> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export SUBSCRIPTION=<YOUR-AZURE-SUBSCRIPTION> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az account set --subscription $SUBSCRIPTION </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az aks get-credentials --resource-group $RESOURCE_GROUP --name $MY_CLUSTER </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="deployment">Deployment<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2#deployment" class="hash-link" aria-label="Direct link to Deployment" title="Direct link to Deployment"></a></h5> <p>Before deploying, you need to retrieve the cluster IP of the Llama2 7B chat workspace running on your AKS cluster. Run the following command in your terminal:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">> kubectl get svc </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Copy the inference service’s cluster IP:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">workspace-llama-2-7b-chat ClusterIP <CLUSTERIP> <none> 80/TCP,29500/TCP 10m </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Next, open the source code directory. Modify the <code>deployment.yaml</code> file, replacing the <code>WORKSPACE-LLAMA-CHAT-CLUSTER-IP</code> placeholder below with your inference service cluster IP you copied above:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: apps/v1 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: Deployment </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> name: forecast-api-deployment </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> replicas: 1 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> selector: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> matchLabels: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> app: forecast-api </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> template: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> metadata: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> labels: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> app: forecast-api </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> spec: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> containers: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> - name: forecast-api </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> image: <YOUR-ACR-NAME>.azurecr.io/forecast-api:latest </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> ports: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> - containerPort: 5000 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> env: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> - name: GENERATE_ENDPOINT_CHAT </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> value: "http://<WORKSPACE-LLAMA-CHAT-CLUSTER-IP>/chat" </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Then, save the updated <code>deployment.yaml</code> file.</p> <p>Execute the following commands to deploy the service to your AKS cluster:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">snap install kubectl --classic </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f deployment.yaml </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f service.yaml </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="invoking-the-service">Invoking the service<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2#invoking-the-service" class="hash-link" aria-label="Direct link to Invoking the service" title="Direct link to Invoking the service"></a></h5> <p>Now that the Forecast API service is deployed, try it out!</p> <p>Run the command below and grab your Forecast API external IP:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">> kubectl get svc </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME TYPE CLUSTER-IP EXTERNAL-IP </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">forecast-api-service LoadBalancer <CLUSTER-IP> <FORECAST-API-IP> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">workspace-llama-2-7b-chat ClusterIP <CLUSTER-IP> <none> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">workspace-llama-2-7b-chat-headless ClusterIP None <none> </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Now, run the curl command below to test your Forecast API service. Be sure to replace the <code><FORECAST-API-IP></code> placeholder with your Forecast API external IP:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">curl --location 'http://<FORECAST-API-IP>/predict-chat' \ </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--header 'Content-Type: application/json' \ </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--data '{ </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "gen_fossil_brown_coal": 582.0, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "gen_fossil_gas": 5537.0, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "gen_fossil_hard_coal": 4039.0, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "gen_fossil_oil": 331.0, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "gen_hydro": 454.0, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "gen_other_renewable": 97.0, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "gen_wind_onshore": 7556.0, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "total_load_actual": 31648.0, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "price": 40.61, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "max_seq_len": 0, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "max_gen_len": 2048, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "temperature": 0.5 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}' </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>The Forecast API service will process the request containing the data from energy sources and price, invoke the inference service, and return the response to the user:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">"content": "Based on the user inputs provided, the following is the table of electricity generation and forecast price: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| Generation Source | MW | </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| --- | --- | </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| Fossil Brown Coal/Lignite | 582.0 | </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| Fossil Gas | 5537.0 | </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| Fossil Hard Coal | 4039.0 | </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| Fossil Oil | 331.0 | </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| Hydro Pumped Storage | 454.0 | </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| Other Renewable Sources | 97.0 | </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">| Onshore Wind | 7556.0 | </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Total Actual Load | 31648.0 | </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Forecast Price | 40.61 EUR/MWh | </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Based on the data provided, the electricity generation from various sources shows a predominance of fossil fuels, with fossil gas being the largest contributor at 5537.0 MW, followed by fossil hard coal at 4039.0 MW, and fossil brown coal/lignite at 582.0 MW. Onshore wind is the largest renewable source of electricity generation at 7556.0 MW.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>That’s it! Note how the generative capabilities of Llama2 7B chat model can transform the cold numbers of your input into an intelligent analysis.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps">Next Steps<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2#next-steps" class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps"></a></h2> <p>In this second installment of the series, you analyzed historical data, used a dataset to construct a model capable of predicting future energy pricing, and used LLaMA2 to generate a report on the energy usage. Continue to Part 3, where you’ll build a basic web interface for the Intelligent App, display the report generated by model, and deploy the app.</p> <p>To keep your learning going, participate in the <a href="https://aka.ms/intelligent-apps/csc" target="_blank" rel="noopener noreferrer">Cloud Skill Challenges</a>, check out the <a href="https://aka.ms/intelligent-apps/ate-aks?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Ask The Expert session</a> with the AKS product team, and register for <strong>AKS <a href="https://aka.ms/aks-day" target="_blank" rel="noopener noreferrer">Customer</a> and <a href="https://aka.ms/aks-lab-day" target="_blank" rel="noopener noreferrer">Lab</a> Days</strong> at KubeCon EU to stay abreast of the latest developments in cloud technology.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[2.3 Forecasting Energy Usage with Intelligent Apps Part 3]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3</guid> <pubDate>Tue, 05 Mar 2024 09:10:00 GMT</pubDate> <description><![CDATA[In this series, you’ll create an Intelligent App powered by Azure Kubernetes Service (AKS) to forecast energy usage and cost.]]></description> <content:encoded><![CDATA[ <p><img loading="lazy" alt="Graphic with a bar chart in a computer-like window in the top-right corner. To the left of the graph is a circle with a lightning bolt in it. At the bottom of the graphic is text that reads, &quot;Forecasting Energy Usage with Intelligent Apps: Adding a Website Interface.&quot;" src="https://azure.github.io/Cloud-Native/assets/images/2-3-1-2f14667a3bdf00f74a1dd5894dc9f96d.png" width="624" height="380" class="img_ev3q"></p> <p>*This three-part series demonstrates how to create an Intelligent App that forecasts future energy consumption and pricing based on historical data. In this final installment of the series, you’ll create a basic web interface that enables the user to input energy usage data and parameters, output the results and the model-generated report into the web interface for easy viewing. Finally, you’ll deploy using the AKS environment set up in Part 1. *</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="forecasting-energy-usage-with-intelligent-apps-part-3-adding-a-web-interface">Forecasting Energy Usage with Intelligent Apps Part 3: Adding a Web Interface<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3#forecasting-energy-usage-with-intelligent-apps-part-3-adding-a-web-interface" class="hash-link" aria-label="Direct link to Forecasting Energy Usage with Intelligent Apps Part 3: Adding a Web Interface" title="Direct link to Forecasting Energy Usage with Intelligent Apps Part 3: Adding a Web Interface"></a></h2> <p>In <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1" target="_blank" rel="noopener noreferrer">Part 1 of this series</a>, you set up an <a href="https://azure.microsoft.com/products/kubernetes-service?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a> (AKS) cluster and prepared it for automated deployment with the help of <a href="https://azure.microsoft.com/updates/preview-ai-toolchain-operator-addon-for-aks/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Kubernetes AI Toolchain Operator</a> (KAITO) and Llama 2. Then, in <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2" target="_blank" rel="noopener noreferrer">Part 2</a>, you built a model that predicts future energy usage/pricing based on parameters input by the user and set up the Intelligent App’s back end.</p> <p>In this third and final article of the series, you’ll create a primary web interface that empowers users to input energy usage data and parameters to generate forecasts. Through this interface, users can gain insights into future energy demands, aiding in strategic decision-making and resource allocation.</p> <p>Let’s dive in!</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites"></a></h3> <p>To follow along, ensure you have:</p> <ul> <li>Completed Parts <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-1" target="_blank" rel="noopener noreferrer">1</a> and <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-2" target="_blank" rel="noopener noreferrer">2</a> of this series</li> <li>A code editor like <a href="https://code.visualstudio.com/" target="_blank" rel="noopener noreferrer">Visual Studio Code</a></li> <li>Python 3.10 or higher</li> <li>The new Forecast web app <a href="https://github.com/contentlab-io/Microsoft-Forecasting-Energy-Usage-with-Intelligent-Apps/tree/main/Part%202" target="_blank" rel="noopener noreferrer">source code</a> downloaded</li> </ul> <p>For a sneak peek of the final product, check out the <a href="https://github.com/contentlab-io/Microsoft-Forecasting-Energy-Usage-with-Intelligent-Apps/tree/main/Part%203" target="_blank" rel="noopener noreferrer">complete project code</a>.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="building-an-intelligent-app-with-azure-kubernetes-service-and-kaito">Building an Intelligent App with Azure Kubernetes Service and KAITO<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3#building-an-intelligent-app-with-azure-kubernetes-service-and-kaito" class="hash-link" aria-label="Direct link to Building an Intelligent App with Azure Kubernetes Service and KAITO" title="Direct link to Building an Intelligent App with Azure Kubernetes Service and KAITO"></a></h3> <p>In this tutorial, you’ll create a basic web interface that enables the user to input or upload energy usage data and parameters to generate future predictions of usage/pricing. Then, you’ll output the results and the report generated from the model into the web interface for easy viewing. Finally, you’ll deploy the Intelligent App using the AKS environment you set up in Part 1.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Checkout the <strong><a href="https://aka.ms/learn-live-building-intelligent-apps-aks-ep4?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps on AKS: Episode 4</a></strong>, a technical deep dive hands-on training with an expert on how to use AKS and Azure to take your intelligent app global.</p></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="creating-the-web-interface">Creating the Web Interface<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3#creating-the-web-interface" class="hash-link" aria-label="Direct link to Creating the Web Interface" title="Direct link to Creating the Web Interface"></a></h4> <p>To develop your web interface, you’ll use <a href="https://streamlit.io/" target="_blank" rel="noopener noreferrer">streamlit</a>—a Python framework for creating web apps. This combination offers flexibility and ease of development, enabling seamless data processing and integration of visualization components.</p> <p><em>The User Interface</em></p> <p>The core of your web interface is a streamlit form where users can input relevant parameters. The form includes fields for adding data related to electricity generation from different sources. Upon submitting the form, users trigger the prediction process.</p> <p>Locate the directory of the source code you have downloaded and open the <a href="https://github.com/contentlab-io/Microsoft-Forecasting-Energy-Usage-with-Intelligent-Apps/blob/main/Part%202/app.py" target="_blank" rel="noopener noreferrer">app.py file</a>. It centralizes the logic needed by the new Forecast app to process user input and produce the price prediction and analysis.</p> <p>For simplicity, let’s review just the most pertinent parts of the file:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># omitted for brevity </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">def generate_report(user_input, price): </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Get the IP address from the environment variable </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> IP_ADDRESS = os.environ.get('ENERGYFORECASTAPI_IP') </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Endpoint URL </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> url = f'http://{IP_ADDRESS}/predict-chat' </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Request payload </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> payload = { </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># omitted for brevity </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> } </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Header </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> headers = {'Content-Type': 'application/json'} </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Perform the request </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> response = requests.post(url, json=payload, headers=headers) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Check the response </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> if response.status_code == 200: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> print("Response:", response.json()) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> json_data = response.json() </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> report = json_data['results'][0][1]['content'] </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return report </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> else: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> st.header('Error', divider='rainbow') </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> print("Error:", response.text) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return response.text </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">def get_forecast_price(user_input): </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> model = load('xgb_model.joblib') </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> price = np.float64(model.predict(user_input)[0]) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> price = np.around(price, 2) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return price </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">st.title("Predicting Energy Pricing") </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">st.write("This Intelligent App analyzes data on energy consumption and predicts the electricity price for the next hour. It then creates a report summarizing the electricity usage and price.") </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">with st.form("my_form"): </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># some parts were omitted for brevity </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> user_input = [[np.float64(generation_fossil_brown_coal_lignite), np.float64(generation_fossil_gas), </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> np.float64(generation_fossil_hard_coal), np.float64(generation_fossil_oil), </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> np.float64(generation_hydro_pumped_storage_consumption), np.float64(generation_other_renewable), </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> np.float64(generation_wind_onshore), np.float64(total_load_actual), hour, weekday, month, business_hour, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> weekend]] </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> price = get_forecast_price(user_input) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> st.header('Forecast Price', divider='rainbow') </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> st.write(f"{str(round(price, 2))} EUR/MW") </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> report = generate_report(user_input, price) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> st.header('Analysis', divider='rainbow') </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> st.write(report) </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="building-and-pushing-to-acr">Building and Pushing to ACR<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3#building-and-pushing-to-acr" class="hash-link" aria-label="Direct link to Building and Pushing to ACR" title="Direct link to Building and Pushing to ACR"></a></h5> <p>Open your terminal at the root directory of the Forecast app’s source code you downloaded earlier. Run the pair of commands below to initiate and use a Python virtual environment:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">python -m venv .env </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">.env\Scripts\activate </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Then, run the following command to complete the installation of dependencies of your Python project:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">pip install -r requirements.txt</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Execute the following commands to build the image locally and push it to your Azure Container Registry (ACR). Be sure to replace <code><username></code> and <code><password></code> with your username and password.</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">sudo docker build --no-cache -f Dockerfile -t forecast-web -t <YOUR-ACR-NAME>.azurecr.io/forecast-web:latest . </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">docker login <YOUR-ACR-NAME>.azurecr.io --username <username> --password-stdin <password> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">docker push <YOUR-ACR-NAME>.azurecr.io/forecast-web:latest </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="connecting-to-aks">Connecting to AKS<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3#connecting-to-aks" class="hash-link" aria-label="Direct link to Connecting to AKS" title="Direct link to Connecting to AKS"></a></h5> <p>Start by making sure you’re logged in to Azure and that you have the correct AKS credentials by running the following command:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az login --tenant <YOUR-AZURE-TENANT-ID></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Next, run the following commands to enable access to your AKS cluster via your terminal:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">export RESOURCE_GROUP=<YOUR-RESOURCE-GROUP> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export MY_CLUSTER=<YOUR-AKS-CLUSTER-NAME> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export LOCATION=<YOUR-LOCATION> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export SUBSCRIPTION=<YOUR-AZURE-SUBSCRIPTION> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az account set --subscription $SUBSCRIPTION </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az aks get-credentials --resource-group $RESOURCE_GROUP --name $MY_CLUSTER </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="deployment">Deployment<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3#deployment" class="hash-link" aria-label="Direct link to Deployment" title="Direct link to Deployment"></a></h4> <p>Before deploying, you need to retrieve the cluster IP of the Forecast API service running on your AKS cluster. Execute the following command in your terminal:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">> kubectl get svc forecast-api-service </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Copy the inference service’s cluster IP:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">forecast-api-service LoadBalancer <CLUSTERIP> <EXTERNAL-IP> 80:32306/TCP 46h </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Next, modify the <code>deployment.yaml</code> file using the code below, replacing the <code><ENERGY-FORECAST-API-IP></code> placeholder below with the Forecast API service’s cluster IP value you copied above:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: apps/v1 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: Deployment </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> name: forecast-web-deployment </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> replicas: 1 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> selector: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> matchLabels: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> app: forecast-web </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> template: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> metadata: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> labels: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> app: forecast-web </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> spec: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> containers: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> - name: forecast-web </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> image: openaidemoacr.azurecr.io/forecast-web:latest </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> ports: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> - containerPort: 8501 </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> env: </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> - name: ENERGYFORECASTAPI_IP </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> value: <ENERGY-FORECAST-API-IP> </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Then, save the updated <code>deployment.yaml</code> file.</p> <p>Execute the following commands to provision a new pod and deploy the service to your AKS cluster:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">snap install kubectl --classic </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f deployment.yaml </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f service.yaml </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p><strong>Note:</strong> After the deployment commands have been applied, the Forecast web app may take a few minutes to get up and running.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Complete the <strong><a href="https://aka.ms/intelligent-apps/apps-csc?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps Skills Challenge</a></strong> to compete for the leaderboard and earn a Microsoft Learn Badge.</p></div></div> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="running-the-web-app">Running the Web App<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3#running-the-web-app" class="hash-link" aria-label="Direct link to Running the Web App" title="Direct link to Running the Web App"></a></h5> <p>Now that the Forecast web app is deployed, let’s try it out!</p> <p>Run the command below and grab your app’s external IP:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">> kubectl get svc forecast-web-service </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">forecast-web-service LoadBalancer 10.0.81.68 <EXTERNAL-IP> 80:30805/TCP </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Now, paste the <code><External-IP></code> into a new web browser tab to test your Forecast web app:</p> <p><img loading="lazy" alt="Screenshot of the Predicting Energy Pricing app open in a browser." src="https://azure.github.io/Cloud-Native/assets/images/2-3-2-2717a2cd0938f3c98cd9088517e2c520.png" width="426" height="627" class="img_ev3q"></p> <p>Fill in the form with the energy fields, plus the date and time, and hit <strong>Submit</strong>.</p> <p>Once you submit the form, you’ll see predictions for energy prices categorized and a detailed report summarizing the electricity usage and price.</p> <p>Once the form is submitted, the Forecast web queries the model trained in Part 2 and obtains the forecast price. Then, it accesses the Forecast API service, which is hosted in your AKS cluster, to produce the summary report using the generative capabilities of the Llama2 Chat model:</p> <p><img loading="lazy" alt="Screenshot of the results in the Forecast app. It includes an analysis of generation sources and their respective usage, a total for the actual load, and a price forecast." src="https://azure.github.io/Cloud-Native/assets/images/2-3-3-d3878a1e76901e33b7c01aafbb437e35.png" width="502" height="505" class="img_ev3q"></p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="why-build-intelligent-apps-with-kaito">Why Build Intelligent Apps with KAITO?<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3#why-build-intelligent-apps-with-kaito" class="hash-link" aria-label="Direct link to Why Build Intelligent Apps with KAITO?" title="Direct link to Why Build Intelligent Apps with KAITO?"></a></h3> <p>KAITO provides significant advantages when building an AI project. One key benefit is the drastic reduction in time and effort required to deploy AI models. This is because KAITO automates many complex tasks that traditionally demand significant manual intervention.</p> <p>Without utilizing KAITO, building an AI project within Kubernetes could present several challenges:</p> <ul> <li>You need to manually handle complex tasks, like provisioning infrastructure resources, deploying models, managing endpoints, and optimizing resource utilization. The manual approach takes substantial time and effort and increases the likelihood of errors and inconsistencies across deployments.</li> <li>The absence of automated infrastructure provisioning may result in suboptimal resource allocation and higher operational costs.</li> </ul> <p>But with the help of KAITO, you can swiftly deploy hosted models from a variety of open-source repositories or custom models—all without the need for extensive expertise in Kubernetes infrastructure management. Moreover, KAITO facilitates the seamless provisioning of infrastructure resources tailored to the specific requirements of AI workloads, optimizing cost efficiency and operational effectiveness.</p> <p>For more details, refer to this <a href="https://www.youtube.com/watch?v=9EvA9gbTS9M&t=676s" target="_blank" rel="noopener noreferrer">Microsoft Ignite presentation</a>.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/forecasting-energy-usage-with-intelligent-apps-3#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h3> <p>In this article, you created a web interface using Streamlit, Docker, and Kubernetes, allowing users to input data and generate insights into energy usage patterns.</p> <p>Azure technologies provide solutions for reducing carbon footprint and promoting sustainability. The <a href="https://github.com/Azure/carbon-aware-keda-operator" target="_blank" rel="noopener noreferrer">Carbon Aware Keda Operator</a> is one such innovation designed to reduce the carbon footprint of Kubernetes resources.</p> <p>Now that you’ve had hands-on experience in building an Intelligent App, join the <a href="https://aka.ms/intelligent-apps/csc" target="_blank" rel="noopener noreferrer">Cloud Skill Challenges</a> and check out the <a href="https://aka.ms/intelligent-apps/ate-aks?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Ask The Expert session</a> with the AKS product team to keep up with the latest in cloud computing. And don’t forget about the <strong>AKS <a href="https://aka.ms/aks-day" target="_blank" rel="noopener noreferrer">Customer</a> and <a href="https://aka.ms/aks-lab-day" target="_blank" rel="noopener noreferrer">Lab</a> Days</strong> at KubeCon EU, a great opportunity to network with AKS and Azure experts. Let’s work together to drive innovation!</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[3. Cosmos DB and Intelligent Apps: A Match Made for Innovation]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/cosmos-db-and-intelligent-apps-a-match-made-for-innovation</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/cosmos-db-and-intelligent-apps-a-match-made-for-innovation</guid> <pubDate>Thu, 07 Mar 2024 09:00:00 GMT</pubDate> <description><![CDATA[In this series, you’ll learn why Cosmos DB is an ideal choice for powering such applications—and how it makes building Intelligent Apps accessible and approachable.]]></description> <content:encoded><![CDATA[ <p><img loading="lazy" alt="Cosmos DB and Intelligent Apps: A Match Made for Innovation" src="https://azure.github.io/Cloud-Native/assets/images/3-1-f7591beb1d3d4e2aa01db52eaeab6713.jpeg" width="624" height="380" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="cosmos-db-and-intelligent-apps-a-match-made-for-innovation">Cosmos DB and Intelligent Apps: A Match Made for Innovation<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/cosmos-db-and-intelligent-apps-a-match-made-for-innovation#cosmos-db-and-intelligent-apps-a-match-made-for-innovation" class="hash-link" aria-label="Direct link to Cosmos DB and Intelligent Apps: A Match Made for Innovation" title="Direct link to Cosmos DB and Intelligent Apps: A Match Made for Innovation"></a></h2> <p>Intelligent Apps represent the next frontier in application development. Merging machine learning (ML), data analytics, and artificial intelligence (AI), Intelligent Apps help drive and automate informed decisions within everyday workflows. These applications can offer predictive insights and personalized experiences by understanding user intent, making predictions, and automating tasks.</p> <p>The core of Intelligent Apps lies in their ability to harness vast amounts of data, analyze it for patterns, and use these insights to improve decision-making processes, enhance user experiences, and streamline operations.</p> <p><a href="https://azure.microsoft.com/free/cosmos-db?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Cosmos DB</a> plays an instrumental role in building these advanced applications. Its scalability, multi-model support, and seamless integration with Azure AI Services make it a solid foundation for Intelligent Apps. Using Cosmos DB, you can manage and analyze large volumes of diverse data worldwide with minimal latency, ensuring the apps you build are intelligent, highly responsive, and globally available. Moreover, the service’s ability to handle real-time data updates and queries empowers Intelligent Apps to deliver dynamic, up-to-the-minute insights and actions.</p> <p>Our three-part series demonstrates how to use Cosmos DB alongside Azure AI Services to create an Intelligent App that forecasts price fluctuations based on historical pricing and product data. In completing this series, you’ll learn why Cosmos DB is an ideal choice for powering such applications—and how it makes building Intelligent Apps accessible and approachable.</p> <p>Join us as we embark on this journey to unlock the potential of Intelligent Apps with Cosmos DB!</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Complete the <strong><a href="https://aka.ms/intelligent-apps/data-csc?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps Data Skills Challenge</a></strong> to compete for the leaderboard and earn a Microsoft Learn Badge.</p></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="building-an-intelligent-forecasting-demo-for-e-commerce">Building an Intelligent Forecasting Demo for E-Commerce<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/cosmos-db-and-intelligent-apps-a-match-made-for-innovation#building-an-intelligent-forecasting-demo-for-e-commerce" class="hash-link" aria-label="Direct link to Building an Intelligent Forecasting Demo for E-Commerce" title="Direct link to Building an Intelligent Forecasting Demo for E-Commerce"></a></h3> <p>In the competitive e-commerce landscape, the ability to adapt pricing in real time based on demand and historical data is a valuable asset. So, this project focuses on developing a forecasting model that leverages AI/ML capabilities to predict future price changes. By integrating this model into your projects, you can enhance your applications with data-driven decision-making tools that respond effectively to market trends.</p> <p>At the heart of this project is Azure Cosmos DB, chosen for its robust data management and analysis features. Cosmos DB facilitates the handling of large datasets required for accurate forecasting, providing a scalable, globally distributed database environment that supports real-time updates and queries. This capability is crucial for applying AI algorithms to historical price data, enabling the app to generate timely predictions that can inform pricing strategies.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="laying-the-groundwork-with-cosmos-db">Laying the Groundwork with Cosmos DB<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/cosmos-db-and-intelligent-apps-a-match-made-for-innovation#laying-the-groundwork-with-cosmos-db" class="hash-link" aria-label="Direct link to Laying the Groundwork with Cosmos DB" title="Direct link to Laying the Groundwork with Cosmos DB"></a></h3> <p><a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1" target="_blank" rel="noopener noreferrer">Part 1 of our series</a> starts with the foundation: setting up an Azure Cosmos DB environment tailored for the intelligent forecasting application. We’ll guide you through the initial steps of creating and configuring your Cosmos DB instance to ensure it’s ready to handle the complexities of historical pricing data.</p> <p>This installment reviews how to populate your database with relevant data that will serve as the backbone for the dynamic repricing model. Once the Cosmos DB environment is established and filled with historical pricing data, you’ll be in a strong position to start leveraging Azure AI Services to analyze this data and predict future price trends.</p> <p>But the first article isn’t just about setting up a database: It’s about preparing the stage for a sophisticated application that can dynamically adjust e-commerce prices. Through this exercise, you’ll learn the importance of a well-structured data foundation and how it enables the creation of more responsive and intelligent e-commerce platforms.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="analyzing-data-with-azure-ai-services">Analyzing Data with Azure AI Services<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/cosmos-db-and-intelligent-apps-a-match-made-for-innovation#analyzing-data-with-azure-ai-services" class="hash-link" aria-label="Direct link to Analyzing Data with Azure AI Services" title="Direct link to Analyzing Data with Azure AI Services"></a></h3> <p>In part 2 of this series, the spotlight turns to Azure AI Services. You’ll explore how to harness Azure’s powerful AI capabilities to sift through the dataset, identifying patterns and trends that are key to understanding future price fluctuations.</p> <p>This stage is all about bridging the gap between raw data and actionable insights, demonstrating how to apply AI capabilities to accurately forecast prices. We’ll walk step-by-step through integrating Azure AI Services with Cosmos DB, helping you create a seamless workflow that brings the dynamic repricing model to life.</p> <p>This hands-on exploration will equip you with the skills to implement intelligent forecasting within your own e-commerce platforms—something that helps you make data-driven decisions on inventory pricing. By the end of part 2, you’ll have a fully operational forecasting model capable of predicting price trends based on historical data.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="building-the-web-interface">Building the Web Interface<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/cosmos-db-and-intelligent-apps-a-match-made-for-innovation#building-the-web-interface" class="hash-link" aria-label="Direct link to Building the Web Interface" title="Direct link to Building the Web Interface"></a></h3> <p>In part 3 of this series, you’ll create a simple, yet effective web interface for the Intelligent App. This interface will serve as the window through which you can easily view and interact with the results of the dynamic repricing tool. We’ll guide you through the development process, showcasing how to use popular web technologies to build an interface.</p> <p>This web interface is critical in making the Intelligent App not just a powerful analytical tool but also a practical solution for e-commerce businesses. By providing a clear and intuitive way to access and understand the pricing forecasts, you can efficiently make informed decisions about pricing.</p> <p>This final piece of the series ties together all the components of the project and highlights the importance of user experience in the deployment of Intelligent Apps.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Check out the <a href="https://aka.ms/intelligent-apps/ate-cosmos?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Cosmos DB Ask The Expert</a> session to learn how to build RAG solutions, manage chat history by seamlessly connecting with Azure OpenAI, as well as explore the power of Azure Cosmos DB's copilot. The experts will also cover how to seamlessly integrate your operational and transactional data with AI frameworks and sdks like Semantic Kernel, Langchain, and LlamaIndex.</p></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="harnessing-cosmos-db-for-intelligent-apps">Harnessing Cosmos DB for Intelligent Apps<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/cosmos-db-and-intelligent-apps-a-match-made-for-innovation#harnessing-cosmos-db-for-intelligent-apps" class="hash-link" aria-label="Direct link to Harnessing Cosmos DB for Intelligent Apps" title="Direct link to Harnessing Cosmos DB for Intelligent Apps"></a></h3> <p>In this exploration of how to build an Intelligent App with Cosmos DB, you’ll have completed a project that showcases the power of Azure services and demonstrates the practical applications of these technologies in forecasting for e-commerce. And by walking through the steps needed to use Cosmos DB alongside Azure AI Services, you’re walking away with a blueprint for building apps that can dynamically adjust pricing based on historical data and market trends.</p> <p>Stay tuned for our series to dive deeper into the creation of this forecasting tool. Whether you’re looking to enhance your technical skills or implement intelligent solutions in your own projects, following along will shine light onto the value of using Cosmos DB for Intelligent Apps.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[3.1 Dynamic Repricing of Products Using Intelligent Apps Part 1]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1</guid> <pubDate>Fri, 08 Mar 2024 09:00:00 GMT</pubDate> <description><![CDATA[In this series, you’ll learn why Cosmos DB is an ideal choice for powering such applications—and how it makes building Intelligent Apps accessible and approachable. In the first article of this series, you’ll set up and populate the Cosmos DB database with data to use in the later parts of the series.]]></description> <content:encoded><![CDATA[ <p><img loading="lazy" alt="Cosmos DB and Intelligent Apps: A Match Made for Innovation" src="https://azure.github.io/Cloud-Native/assets/images/3-1-1-95d16f4679738d90454174a0d0aaa18a.jpeg" width="624" height="380" class="img_ev3q"></p> <p><em>This three-part series demonstrates how to use Azure Cosmos DB to build an Intelligent App that uses historical pricing and product data to forecast future price fluctuations for specific products. In the first article of this series, you’ll set up and populate the Cosmos DB database with data to use in the later parts of the series.</em></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="dynamic-repricing-of-products-using-intelligent-apps-part-1-setting-up-and-populating-cosmos-db-with-data">Dynamic Repricing of Products Using Intelligent Apps Part 1: Setting Up and Populating Cosmos DB with Data<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1#dynamic-repricing-of-products-using-intelligent-apps-part-1-setting-up-and-populating-cosmos-db-with-data" class="hash-link" aria-label="Direct link to Dynamic Repricing of Products Using Intelligent Apps Part 1: Setting Up and Populating Cosmos DB with Data" title="Direct link to Dynamic Repricing of Products Using Intelligent Apps Part 1: Setting Up and Populating Cosmos DB with Data"></a></h2> <p>Intelligent Apps leverage data and artificial intelligence (AI) to provide smart, personalized, and adaptive experiences for users. AI and machine learning (ML) techniques like natural language processing (NLP), computer vision, and deep learning help understand context, intent, and user preferences to deliver relevant and timely insights and actions.</p> <p>Some examples of Intelligent Apps include:</p> <ul> <li><strong>Virtual assistants</strong>—Interactive applications that understand and execute user commands</li> <li><strong>Chatbots</strong>—Automated messaging systems that provide information or assistance</li> <li><strong>Recommendation</strong> systems—Algorithms that suggest relevant items based on user preferences and behavior</li> </ul> <p>In this three-part series, you’ll create an Intelligent App powered by Azure Cosmos DB and AI/ML capabilities that dynamically suggests changes to product prices based on demand and historical trends. This app will help optimize revenue and customer satisfaction by adjusting product prices according to market conditions and customer behavior.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="laying-the-groundwork-for-an-intelligent-app-with-cosmos-db">Laying the Groundwork for an Intelligent App with Cosmos DB<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1#laying-the-groundwork-for-an-intelligent-app-with-cosmos-db" class="hash-link" aria-label="Direct link to Laying the Groundwork for an Intelligent App with Cosmos DB" title="Direct link to Laying the Groundwork for an Intelligent App with Cosmos DB"></a></h3> <p>First, you’ll set up an Azure Cosmos DB database and populate it with product data and historical information about sales and demand. In part 2, you’ll analyze this data using AI and ML to forecast and suggest price changes.</p> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites"></a></h4> <p>To follow this tutorial, ensure you have the following:</p> <ul> <li><a href="https://azure.microsoft.com/free/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">An Azure account</a></li> <li>A <a href="https://www.kaggle.com/account/login?phase=startRegisterTab&returnUrl=%2F" target="_blank" rel="noopener noreferrer">Kaggle account</a> to download the <a href="https://www.kaggle.com/datasets/sujaykapadnis/price-quote-data/data" target="_blank" rel="noopener noreferrer">dataset</a> this tutorial uses</li> </ul> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="create-an-azure-cosmos-db-account">Create an Azure Cosmos DB Account<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1#create-an-azure-cosmos-db-account" class="hash-link" aria-label="Direct link to Create an Azure Cosmos DB Account" title="Direct link to Create an Azure Cosmos DB Account"></a></h4> <p>Azure Cosmos DB is a fully managed multi-model database that ensures fast access to data, easy scalability, reliable uptime, and strong data consistency. Cosmos DB supports various data models and APIs, including SQL, MongoDB, Cassandra, Gremlin, and table storage, making it easy to query and manipulate data using familiar tools and languages.</p> <p>Although you already have an Azure account, you also need to create an Azure Cosmos DB account by following the steps below:</p> <ol> <li> <p>Sign in to the <a href="https://portal.azure.com/" target="_blank" rel="noopener noreferrer">Azure portal</a>.</p> </li> <li> <p>Click <strong>Create a resource</strong> on the upper-left side of the page.</p> </li> <li> <p>Search for “Azure Cosmos DB” and select it. On the <strong>Azure Cosmos DB</strong> page, select <strong>Create</strong>.</p> </li> <li> <p>Enter the settings for your new account:</p> <ul> <li> <p>Select your desired subscription.</p> </li> <li> <p>Create a new resource group or select an existing one if you have one you’d like to use.</p> </li> <li> <p>Enter a unique account name.</p> </li> <li> <p>Select <strong>SQL (Core)</strong> as the API. This is the default API for Azure Cosmos DB and allows you to use SQL syntax to query and manage your data.</p> </li> <li> <p>Select a <strong>Location</strong> for the account.</p> </li> <li> <p>Click <strong>Review + create</strong>.</p> </li> </ul> </li> <li> <p>Review your account settings and click <strong>Create</strong> to create the account.</p> </li> </ol> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Complete the <strong><a href="https://aka.ms/intelligent-apps/data-csc?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Data Skills Challenge</a></strong> to compete for the leaderboard and earn a Microsoft Learn Badge.</p></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="create-a-database-and-a-container">Create a Database and a Container<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1#create-a-database-and-a-container" class="hash-link" aria-label="Direct link to Create a Database and a Container" title="Direct link to Create a Database and a Container"></a></h4> <p>Next, you’ll create a database and container within Azure Cosmos DB. Databases facilitate management, billing, and scaling, while a container is a schema-agnostic grouping of items (documents) with a partition key and a provisioned throughput. The partition property determines how the data is distributed across physical partitions for scalability and performance.</p> <p>To create a database and container, follow the steps below:</p> <ol> <li> <p>From the Azure portal, navigate to your Azure Cosmos DB account and select <strong>Data Explorer</strong> on the left menu. In the <strong>Data Explorer</strong>, select <strong>New Database</strong> on the top menu.</p> </li> <li> <p>In the <strong>Add Database</strong> panel, enter a name for the new database, like “ProductsDB.”</p> </li> <li> <p>Check <strong>Provision database throughput</strong> if you want to enable shared throughput for the database. This shares the throughput (RU/s) you provision among all containers in the database. You can also activate or deactivate autoscale, which automatically adjusts the throughput based on your application’s usage patterns.</p> </li> <li> <p>Select <strong>OK</strong> to create the database.</p> </li> <li> <p>In <strong>Data Explorer</strong>, expand the <strong>ProductsDB</strong> database and select <strong>New Container</strong> on the top menu. Then, open the <strong>Add Container</strong> panel and create a new container:</p> <ul> <li> <p>Enter “Products” as the container name.</p> </li> <li> <p>Enter “/ITEM_ID” as the container’s partition key. This will <a href="https://learn.microsoft.com/en-us/azure/cosmos-db/partitioning-overview" target="_blank" rel="noopener noreferrer">partition</a> the data by its <code>ITEM_ID</code> property, since columns with a wide range of values make excellent partition keys.</p> </li> <li> <p>Use the default value of 400 throughput units. If you’d like, you can also deactivate autoscale for the container.</p> </li> </ul> </li> <li> <p>Select <strong>OK</strong> to create the container.</p> </li> </ol> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="populate-the-container">Populate the Container<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1#populate-the-container" class="hash-link" aria-label="Direct link to Populate the Container" title="Direct link to Populate the Container"></a></h4> <p>Now that you’ve created your database and container, you need to populate them with some data. For this demonstration, you’ll use a CSV file that contains <a href="https://www.ons.gov.uk/economy/inflationandpriceindices/datasets/consumerpriceindicescpiandretailpricesindexrpiitemindicesandpricequotes" target="_blank" rel="noopener noreferrer">UK inflation data</a>. The dataset contains over 100,000 rows of data representing 600 products sold in UK shops over 12 months.</p> <p>To populate the container with this data, follow these steps:</p> <ol> <li> <p>Download the <a href="https://www.kaggle.com/datasets/sujaykapadnis/price-quote-data/data" target="_blank" rel="noopener noreferrer">CSV file</a>.</p> </li> <li> <p>In the Azure portal, navigate to your Azure Cosmos DB account and select <strong>Data Explorer</strong> on the left menu.</p> </li> <li> <p>In <strong>Data Explorer</strong>, expand the <strong>ProductsDB</strong> database and the <strong>Products</strong> container, and select <strong>Items</strong>.</p> </li> </ol> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="upload-the-csv-file"><em>Upload the CSV File</em><a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1#upload-the-csv-file" class="hash-link" aria-label="Direct link to upload-the-csv-file" title="Direct link to upload-the-csv-file"></a></h5> <p>Now, upload the CSV file:</p> <ol> <li> <p>From the top menu, select <strong>Upload Item</strong>.</p> </li> <li> <p>In the <strong>Upload Item</strong> panel, select <strong>Browse</strong>, and choose the CSV file you downloaded previously.</p> </li> <li> <p>Select <strong>Upload</strong> to upload the file to the container.</p> </li> <li> <p>After the upload finishes, you should see the items in the container, each representing a row in the CSV file. You can select an item to view its properties and values in JSON format.</p> </li> </ol> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="verify-the-data-in-the-container"><em>Verify the Data in the Container</em><a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1#verify-the-data-in-the-container" class="hash-link" aria-label="Direct link to verify-the-data-in-the-container" title="Direct link to verify-the-data-in-the-container"></a></h5> <p>To verify that the data in the container is correct and consistent, you can use the SQL query editor in the Data Explorer.</p> <ol> <li> <p>Select <strong>New SQL Query</strong>.</p> </li> <li> <p>The query editor lets you execute SQL queries against the data in the container. For example, run the following query to get the container’s item count:</p> <p><code>SELECT VALUE COUNT(1) FROM c</code></p> <p>You should get a result of <code>10000</code>, which matches the number of rows in the CSV file.</p> </li> <li> <p>You can also run queries to check the data quality and integrity, like the following:</p> <ul> <li> <p><strong>Get the distinct values of ITEM_ID</strong> — <code>SELECT DISTINCT VALUE c.ITEM_ID FROM c</code></p> </li> <li> <p><strong>Get the average price of each product</strong> — <code>SELECT c.ITEM_ID, c.ITEM_DESC, AVG(c.PRICE) AS avg_price FROM c GROUP BY c.ITEM_ID, c.ITEM_DESC</code></p> </li> <li> <p><strong>Get the price trend of a product over time</strong> — <code>SELECT c.QUOTE_DATE, c.PRICE FROM c WHERE c.ITEM_ID = '210102' ORDER BY c.QUOTE_DATE</code></p> </li> </ul> </li> <li> <p>You can also use the built-in charts to visualize the query results. In the top-right corner of the query editor, select <strong>Chart</strong> and choose the chart type you want to use, such as line, bar, or pie.</p> </li> </ol> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps">Next Steps<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1#next-steps" class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps"></a></h3> <p>In this article, you configured an Azure Cosmos DB database and populated it with data about product price changes. You also verified the data in the container using SQL queries and charts.</p> <p>In the <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-2" target="_blank" rel="noopener noreferrer">next part of the series</a>, you’ll learn how to use Azure’s AI and ML capabilities to analyze the data and suggest product price forecasts.</p> <p>If you want to challenge yourself and learn more about Azure, Cosmos DB, and AI/ML, we encourage you to participate in the <strong><a href="https://azure.github.io/Cloud-Native/Build-IA/CloudSkills" target="_blank" rel="noopener noreferrer">Data Cloud Skill Challenge</a></strong>. You can also register for <strong>AKS <a href="https://aka.ms/aks-day" target="_blank" rel="noopener noreferrer">Customer</a> and <a href="https://aka.ms/aks-lab-day" target="_blank" rel="noopener noreferrer">Lab</a> Days</strong> at the premier conference for cloud-native technologies, <em>KubeCon EU 2024</em>.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[3.2 Dynamic Repricing of Products Using Intelligent Apps Part 2]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-2</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-2</guid> <pubDate>Fri, 08 Mar 2024 09:01:00 GMT</pubDate> <description><![CDATA[In this series, you’ll learn why Cosmos DB is an ideal choice for powering such applications—and how it makes building Intelligent Apps accessible and approachable.]]></description> <content:encoded><![CDATA[ <p><img loading="lazy" alt="Dynamic Repricing of Products Using Intelligent Apps Part 2: Price Forecasting with AI/ML" src="https://azure.github.io/Cloud-Native/assets/images/3-2-1-e5a063f4e30bad99d184e8bec1007e72.jpeg" width="624" height="380" class="img_ev3q"></p> <p><em>This three-part series demonstrates how to use Azure Cosmos DB to build an Intelligent App that uses historical pricing and product data to forecast future price fluctuations for specific products. In this installment, you’ll use artificial intelligence and machine learning to build the price forecasting model.</em></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="dynamic-repricing-of-products-using-intelligent-apps-part-2-price-forecasting-with-aiml">Dynamic Repricing of Products Using Intelligent Apps Part 2: Price Forecasting with AI/ML<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-2#dynamic-repricing-of-products-using-intelligent-apps-part-2-price-forecasting-with-aiml" class="hash-link" aria-label="Direct link to Dynamic Repricing of Products Using Intelligent Apps Part 2: Price Forecasting with AI/ML" title="Direct link to Dynamic Repricing of Products Using Intelligent Apps Part 2: Price Forecasting with AI/ML"></a></h2> <p><a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1" target="_blank" rel="noopener noreferrer">In Part 1 of this series</a>, you set up and populated an <a href="https://azure.microsoft.com/free/cosmos-db?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Cosmos DB</a> database, laying the groundwork for your Intelligent Application. You also imported your data to a Cosmos DB instance.</p> <p>In this second article, you’ll use this data alongside Azure’s machine learning (ML) and artificial intelligence (AI) capabilities to build a model that analyzes pricing trends and predicts future prices for a fictional e-commerce business.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="analyzing-price-trends-to-predict-future-prices">Analyzing Price Trends to Predict Future Prices<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-2#analyzing-price-trends-to-predict-future-prices" class="hash-link" aria-label="Direct link to Analyzing Price Trends to Predict Future Prices" title="Direct link to Analyzing Price Trends to Predict Future Prices"></a></h3> <p>The ability to forecast pricing is a game-changer. With the power of foresight, businesses can preemptively adjust their pricing strategies in line with market expectations.</p> <p>In this tutorial, we’ll give you a step-by-step guide to generating a predictive ML model for an e-commerce business, using Azure’s suite of ML tools.</p> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-2#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites"></a></h4> <p>Before you begin, make sure you have the following:</p> <ul> <li>An active <a href="https://azure.microsoft.com/free/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Account</a></li> <li>A Cosmos DB instance with the <a href="https://www.kaggle.com/datasets/sujaykapadnis/price-quote-data/data" target="_blank" rel="noopener noreferrer">pricing data</a> you set up in Part 1</li> <li>Access to <a href="https://studio.azureml.net/" target="_blank" rel="noopener noreferrer">Azure Machine Learning Studio</a></li> <li>An <a href="https://learn.microsoft.com/azure/machine-learning/tutorial-azure-ml-in-a-day?view=azureml-api-2&ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Machine Learning workspace</a></li> <li>A <a href="https://learn.microsoft.com/azure/machine-learning/quickstart-create-resources?view=azureml-api-2#create-a-new-notebook&ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Jupyter notebook set up</a> in your workspace</li> <li>Familiarity with <a href="https://azure.microsoft.com/products/machine-learning?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Machine Learning</a> concepts</li> <li>Basic Python programming knowledge and understanding of ML concepts</li> </ul> <p><strong>Note</strong>: You should add and run all code in this article into your Jupyter Notebook in the order in which it appears.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Check out the Azure <strong><a href="https://aka.ms/intelligent-apps/ate-cosmos?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Cosmos DB Ask The Expert</a></strong> session to learn how to build RAG solutions, manage chat history by seamlessly connecting with <em>Azure OpenAI</em>, as well as explore the power of <em>Azure Cosmos DB's copilot</em>. The experts will also cover how to seamlessly integrate your operational and transactional data with AI frameworks and sdks like Semantic Kernel, Langchain, and LlamaIndex.</p></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="extract-historical-pricing-data-from-cosmos-db">Extract Historical Pricing Data from Cosmos DB<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-2#extract-historical-pricing-data-from-cosmos-db" class="hash-link" aria-label="Direct link to Extract Historical Pricing Data from Cosmos DB" title="Direct link to Extract Historical Pricing Data from Cosmos DB"></a></h4> <p>Start by extracting historical pricing data from Cosmos DB, where you stored it in Part 1. For this tutorial, you’ll extract items with names ending in <code>JACKET</code>. Because the dataset is relatively small, a simple <code>like</code> query will do. However, when working with larger data sets, you should consider additional upfront data cleaning and categorizing, to ensure you can query your database efficiently.</p> <p>Run the code below to extract the data:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">from azure.cosmos import CosmosClient, exceptions</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import pandas as pd</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Initialize a Cosmos client</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">endpoint = "your_cosmos_db_endpoint"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">key = 'your_cosmos_db_key'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">client = CosmosClient(endpoint, key)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Connect to the database and container</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">database_name = 'your_database_name'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">container_name = 'your_container_name'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">database = client.get_database_client(database_name)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">container = database.get_container_client(container_name)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Query these items using the SQL query syntax</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">query = "SELECT * FROM c where ITEM_DESC like '%JACKET'"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">items = list(container.query_items(query=query, enable_cross_partition_query=True))</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Convert the query result to a DataFrame</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pricing_data = pd.DataFrame(items)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="preprocess-data-and-split-into-training-and-testing">Preprocess Data and Split into Training and Testing<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-2#preprocess-data-and-split-into-training-and-testing" class="hash-link" aria-label="Direct link to Preprocess Data and Split into Training and Testing" title="Direct link to Preprocess Data and Split into Training and Testing"></a></h4> <p>Before feeding the data into an ML model, preprocess it and split it into training and testing sets using the code below:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">from sklearn.model_selection import train_test_split</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Assume the DataFrame `pricing_data` has columns: 'quote_date', 'price', 'price_relative', 'item_id', etc.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Convert 'quote_date' from string to datetime for proper chronological splitting</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pricing_data['QUOTE_DATE'] = pd.to_datetime(pricing_data['QUOTE_DATE'], format='%Y%m')</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Selecting the features and target for the model</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">X = pricing_data[['QUOTE_DATE', 'ITEM_ID', 'PRICE_RELATIVE','STRATUM_WEIGHT', 'SHOP_WEIGHT']]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">y = pricing_data['price']</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Split the data into training and testing sets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># We'll use a chronological split rather than a random split to maintain the time series integrity</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">split_date = pd.Timestamp('YYYY-MM-DD') # replace with the appropriate date</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">train = pricing_data.loc[pricing_data['QUOTE_DATE'] <= split_date]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">test = pricing_data.loc[pricing_data['QUOTE_DATE'] > split_date]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">X_train, y_train = train[['ITEM_ID', 'PRICE_RELATIVE', 'STRATUM_WEIGHT', 'SHOP_WIGHT']], train['PRICE']</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">X_test, y_test = test[['ITEM_ID', 'PRICE_RELATIVE', 'STRATUM_WEIGHT', 'SHOP_WEIGHT']], test['PRICE']</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="train-a-forecasting-model-using-azure-machine-learning">Train a Forecasting Model Using Azure Machine Learning<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-2#train-a-forecasting-model-using-azure-machine-learning" class="hash-link" aria-label="Direct link to Train a Forecasting Model Using Azure Machine Learning" title="Direct link to Train a Forecasting Model Using Azure Machine Learning"></a></h4> <p>Next, you’ll build and train the forecasting model using Azure Machine Learning. Note that in the code below, you’re using a local compute target, which works on simple datasets like the one used for this tutorial. However, Azure Machine Learning offers more powerful compute targets for more complex models.</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">from azureml.core import Workspace, Experiment, Environment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">from azureml.train.automl import AutoMLConfig</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Connect to your Azure ML workspace</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ws = Workspace.from_config()</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Define your experiment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">experiment_name = 'price_forecasting_experiment'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">experiment = Experiment(ws, experiment_name)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Configure the automated ML job </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">automl_config = AutoMLConfig(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> task='forecasting',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> primary_metric='normalized_root_mean_squared_error',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> experiment_timeout_minutes=30,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> training_data=train,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> label_column_name='PRICE',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> n_cross_validations=5,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enable_early_stopping=True,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> verbosity=logging.INFO,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> compute_target='local'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">) </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Submit the experiment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">run = experiment.submit(automl_config, show_output=True)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="evaluate-and-integrate-the-model">Evaluate and Integrate the Model<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-2#evaluate-and-integrate-the-model" class="hash-link" aria-label="Direct link to Evaluate and Integrate the Model" title="Direct link to Evaluate and Integrate the Model"></a></h4> <p>Next, check the results of the model by running the following:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">from azureml.widgets import RunDetails</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Show run details while running</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">RunDetails(run).show()</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Wait for the run to complete</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">run.wait_for_completion()</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Retrieve the best model from the AutoML run</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">best_run, fitted_model = run.get_output()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">print(best_run)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">print(fitted_model)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Evaluate the best model's accuracy using the test data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Assuming test data is a Pandas DataFrame with the same structure as the training data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">X_test = test_data.drop('PRICE', axis=1) # Features (drop the target column)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">y_test = test_data['PRICE'] # True values of the target column</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Predict using the fitted model</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">y_pred = fitted_model.predict(X_test)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Calculate the accuracy or any other performance metrics</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">from sklearn.metrics import mean_squared_error, r2_score</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">mse = mean_squared_error(y_test, y_pred)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">r2 = r2_score(y_test, y_pred)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">print(f"Mean Squared Error: {mse}")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">print(f"R-squared: {r2}")</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>With the performance metrics calculated, you can now determine whether the model’s predictions are accurate enough for your needs. If they are, you can integrate the model with a hypothetical e-commerce platform. The easiest way to integrate a model is to deploy it using an Azure Machine Learning endpoint:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">ws = Workspace.from_config() </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Register the model from the best run</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">model = best_run.register_model(model_name='price_forecast_model', model_path='outputs/model.pkl') </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Download the scoring file produced by AutoML</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">best_run.download_file('outputs/scoring_file_v_1_0_0.py', 'score.py')</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Download the environment file produced by AutoML</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">best_run.download_file(constants.CONDA_ENV_FILE_PATH, 'environment.yml')</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Create the environment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">env = Environment.from_conda_specification(name='forecasting_environment', file_path='environment.yml')</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Create the inference configuration</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">inference_config = InferenceConfig(entry_script='score.py', environment=env)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Create the deployment configuration</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">deployment_config = AciWebservice.deploy_configuration(cpu_cores=1, memory_gb=1)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Deploy the model as a web service</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">service_name = 'price-forecast-service'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">service = Model.deploy(ws, service_name, [model], inference_config, deployment_config) </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">service.wait_for_deployment(show_output=True)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># The web service endpoint URL</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">print(service.scoring_uri)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>And with that, you’ve deployed your Azure ML endpoint and are ready for Part 3!</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-2#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h3> <p>In this tutorial, you extracted data from Cosmos DB, preprocessed it, performed a train/test split, initiated a model training pipeline using Azure Machine Learning, and, finally, tested and deployed the model. These are crucial steps to building a system that can intelligently forecast product prices.</p> <p>In the third and final article of this series, you’ll build a web interface that displays the generated price forecasts using approachable, simple graphs that help businesses easily make data-informed decisions.</p> <p>To challenge yourself, learn more about Azure’s AI and ML tooling, and put the skills you’ve learned in this tutorial to work, participate in the <a href="https://azure.github.io/Cloud-Native/Build-IA/CloudSkills" target="_blank" rel="noopener noreferrer">Data Cloud Skill Challenge</a>. You can also register for <strong>AKS <a href="https://aka.ms/aks-day" target="_blank" rel="noopener noreferrer">Customer</a> and <a href="https://aka.ms/aks-lab-day" target="_blank" rel="noopener noreferrer">Lab</a> Days</strong> at the premier conference for cloud-native technologies, <em>KubeCon EU 2024</em>.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[3.3 Dynamic Repricing of Products Using Intelligent Apps Part 3: Graphing and Displaying Price Forecasts in a Web Interface]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3</guid> <pubDate>Fri, 08 Mar 2024 09:05:00 GMT</pubDate> <description><![CDATA[In this series, you’ll learn why Cosmos DB is an ideal choice for powering such applications—and how it makes building Intelligent Apps accessible and approachable.]]></description> <content:encoded><![CDATA[ <p><img loading="lazy" alt="Dynamic Repricing of Products Using Intelligent Apps: Graphing and Displaying Price Forecasts in a Web Interface" src="https://azure.github.io/Cloud-Native/assets/images/3-3-1-af19fe2f48ffe5dbb5ae7a93b6031151.png" width="624" height="380" class="img_ev3q"></p> <p><em>This three-part series demonstrates how to use Azure Cosmos DB to build an Intelligent App that uses historical pricing and product data to forecast future price fluctuations for specific products. In the final article of the series, you’ll build a web interface to graph and display the Intelligent App’s price forecasts.</em></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="dynamic-repricing-of-products-using-intelligent-apps-part-3-graphing-and-displaying-price-forecasts-in-a-web-interface">Dynamic Repricing of Products Using Intelligent Apps Part 3: Graphing and Displaying Price Forecasts in a Web Interface<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3#dynamic-repricing-of-products-using-intelligent-apps-part-3-graphing-and-displaying-price-forecasts-in-a-web-interface" class="hash-link" aria-label="Direct link to Dynamic Repricing of Products Using Intelligent Apps Part 3: Graphing and Displaying Price Forecasts in a Web Interface" title="Direct link to Dynamic Repricing of Products Using Intelligent Apps Part 3: Graphing and Displaying Price Forecasts in a Web Interface"></a></h2> <p>In <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-1" target="_blank" rel="noopener noreferrer">Part 1</a> of this series, you set up an Azure Cosmos DB database and populated the database with pricing data. Then, in <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-2" target="_blank" rel="noopener noreferrer">Part 2</a>, you successfully set up an Azure Machine Learning model and deployed it as a web service.</p> <p>In this final article of the series, you’ll create a web application using Flask that interacts with the Azure Machine Learning endpoint to retrieve predictions and display them using a simple graph.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites"></a></h3> <p>Before proceeding, ensure you have the following: </p> <ul> <li><a href="https://www.python.org/downloads/" target="_blank" rel="noopener noreferrer">Python</a> version 3.10 or greater</li> <li>Flask (<code>pip install flask</code>)</li> <li>Requests (<code>pip install requests</code>)</li> <li>Matplotlib (<code>pip install matplotlib</code>)</li> <li>Access to the Azure Machine Learning endpoint created in Part 2</li> <li><a href="https://docs.docker.com/get-docker/" target="_blank" rel="noopener noreferrer">Docker</a>, including the <a href="https://docs.docker.com/engine/reference/commandline/cli/" target="_blank" rel="noopener noreferrer">Docker command-line interface</a> (CLI), installed. You’ll use this to build a container image to run the web app on Azure Kubernetes Service (AKS).</li> <li>The <a href="https://docs.microsoft.com/cli/azure/install-azure-cli?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure CLI</a> installed. You’ll use this for deployment to AKS.</li> </ul> <p>For a preview of the completed Intelligent App, take a look at the <a href="https://aka.ms/intelligent-apps/60daysofIA/3.3projectcode" target="_blank" rel="noopener noreferrer">project code</a>.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Complete the <strong><a href="https://aka.ms/intelligent-apps/data-csc?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Data Skills Challenge</a></strong> to compete for the leaderboard and earn a Microsoft Learn Badge.</p></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="building-the-web-interface">Building the Web Interface<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3#building-the-web-interface" class="hash-link" aria-label="Direct link to Building the Web Interface" title="Direct link to Building the Web Interface"></a></h3> <p>It only takes a few steps to create a simple web app that queries the Azure Machine Learning endpoint, retrieves predictions, and displays the resulting prediction in a graph. Let’s dive in!</p> <p>Start by creating a new folder for your web application. Then, create these files and folders in it:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">/your-flask-app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> /templates</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> index.html</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> app.py</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>The <code>app.py</code> file is the backbone of the Flask application. So, add the following code to it:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">from flask import Flask, render_template, request</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import requests</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import matplotlib.pyplot as plt</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import io</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import base64</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">from datetime import datetime, timedelta</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">app = Flask(__name__)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Replace with your actual Azure ML endpoint and key</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">scoring_uri = '<your_azure_ml_endpoint>'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">api_key = '<your_api_key>' # Replace with your actual key if needed</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">def generate_future_dates(start_date, periods=3, freq='M'):</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Generate future dates for the next 'periods' months</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> future_dates = [(start_date + timedelta(days=30 * i)).strftime('%Y%m') for i in range(1, periods + 1)]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return future_dates</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">def get_predictions(dates):</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Prepare the data in JSON format</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> data = {"data": [[date] for date in dates]}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> headers = {'Content-Type': 'application/json'}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> if api_key:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> headers['Authorization'] = f'Bearer {api_key}'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Send the request to the Azure ML endpoint</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> response = requests.post(scoring_uri, json=data, headers=headers)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> if response.status_code == 200:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return response.json()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> else:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> raise Exception(f"Failed to fetch prediction: {response.text}")</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">@app.route('/', methods=['GET', 'POST'])</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">def index():</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> graph_url = None</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> if request.method == 'POST':</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> start_date = datetime.utcnow()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> future_dates = generate_future_dates(start_date)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> predictions = get_predictions(future_dates)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"> # Plotting the predictions</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> plt.figure(figsize=(10, 5))</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> plt.plot(future_dates, predictions, marker='o', linestyle='-')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> plt.title('Future Price Predictions for Jackets')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> plt.xlabel('Date (YYYYMM)')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> plt.ylabel('Predicted Price')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> plt.grid(True)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Save plot to a BytesIO buffer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> img = io.BytesIO()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> plt.savefig(img, format='png', bbox_inches='tight')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> img.seek(0)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> graph_url = base64.b64encode(img.getvalue()).decode('utf8')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> plt.close()</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"> return render_template('index.html', graph_url=graph_url)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">if __name__ == '__main__':</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> app.run(debug=True)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>This simple Flask app accepts incoming requests and queries the Azure Machine Learning endpoint for the next few months of price forecasts for jackets. When it receives the predictions, it generates a graph using <code>matplotlib</code>, encoding it with base64 so it can display it in the HTML template. In a larger app, you could save the image to disk and then load it in the web page instead of base64 encoding it—but we’ve skipped that here to keep things simple.</p> <p>Next, create an <code>index.html</code> file in the templates directory. Add the following code for the user interface:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"><!DOCTYPE html></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"><html lang="en"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"><head></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <meta charset="UTF-8"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <meta name="viewport" content="width=device-width, initial-scale=1.0"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <title>Price Forecast Visualization</title></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <!-- Load Tailwind CSS from CDN --></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></head></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"><body class="bg-gray-100 flex flex-col justify-center items-center min-h-screen"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <div class="w-full bg-blue-800 text-white"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <div class="container mx-auto py-4"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <h1 class="text-center text-xl md:text-3xl font-bold">Price Forecast for Jackets</h1></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </div></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </div></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <div class="mt-8 mb-4"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <form method="post"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Get Future Price Predictions</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </button></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </form></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </div></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> {% if graph_url %}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <div class="shadow-xl bg-white rounded-lg p-8"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <h2 class="text-lg md:text-xl font-semibold mb-4 text-center">Price Prediction Graph</h2></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <div class="flex justify-center"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <img src="data:image/png;base64,{{ graph_url }}" alt="Price Prediction Graph" class="max-w-full h-auto rounded-lg"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </div></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </div></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> {% endif %}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></body></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></html></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>To run your Flask app, navigate to the directory containing your <code>app.py</code> file and execute the following command:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">flask run</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Your web application should now be accessible at <code>http://127.0.0.1:5000</code>. Users can input feature data, submit it, and see both the predicted price and a simple graph comparing the current and predicted prices.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Check out the <strong><a href="https://aka.ms/intelligent-apps/ate-cosmos?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Cosmos DB Ask The Expert</a></strong> session to learn how to build RAG solutions, manage chat history by seamlessly connecting with <em>Azure OpenAI</em>, as well as explore the power of <em>Azure Cosmos DB's copilot</em>.</p><p>The experts also cover how to seamlessly integrate your operational and transactional data with AI frameworks and sdks like Semantic Kernel, Langchain, and LlamaIndex.</p></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="deploying-to-azure-kubernetes-service-aks">Deploying to Azure Kubernetes Service (AKS)<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3#deploying-to-azure-kubernetes-service-aks" class="hash-link" aria-label="Direct link to Deploying to Azure Kubernetes Service (AKS)" title="Direct link to Deploying to Azure Kubernetes Service (AKS)"></a></h3> <p>Running locally is great, but in production, you’ll probably want to deploy to the cloud. Fortunately, Azure makes this easy. Let’s review how to deploy your Flask app using AKS.</p> <p>First, you need to containerize the Flask app and push it to an Azure Container Registry. Then, you’ll create an AKS cluster and deploy the container image to it.</p> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="create-a-dockerfile">Create a Dockerfile<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3#create-a-dockerfile" class="hash-link" aria-label="Direct link to Create a Dockerfile" title="Direct link to Create a Dockerfile"></a></h4> <p>Start by creating a file named <code>Dockerfile</code> in the Flask app’s root folder. Add the following contents:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">FROM python:3.11-slim</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">WORKDIR /usr/src/app</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">RUN pip install --no-cache-dir Flask</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">COPY . .</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">CMD ["flask", "run"]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="create-a-container-registry">Create a Container Registry<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3#create-a-container-registry" class="hash-link" aria-label="Direct link to Create a Container Registry" title="Direct link to Create a Container Registry"></a></h4> <p>Next, create a container registry to store the container image. Use the Azure CLI to create a new resource group if you don’t already have one you’d like to use:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az group create --name my-container-resources --location eastus</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Then, create a container registry in the resource group:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az acr create --resource-group my-container-resources --name my-registry --sku Basic</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>You’re now ready to build the container and push it to the registry.</p> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="build-and-push-the-container-image">Build and Push the Container Image<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3#build-and-push-the-container-image" class="hash-link" aria-label="Direct link to Build and Push the Container Image" title="Direct link to Build and Push the Container Image"></a></h4> <p>Build the container image using the following command:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">docker build -t my-app-image .</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Then, push the image to your container registry:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">docker push my-registry.azurecr.io/my-app-image</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="create-an-aks-cluster">Create an AKS Cluster<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3#create-an-aks-cluster" class="hash-link" aria-label="Direct link to Create an AKS Cluster" title="Direct link to Create an AKS Cluster"></a></h4> <p>Now, it’s time to create an AKS cluster. Run the following:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az aks create --name my-aks-cluster --resource-group my-resource-group --node-count 3 --node-vm-size Standard_B2s --location eastus</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>It may take a few minutes for Azure to spin up your cluster. Once it’s ready, you can deploy the Flask app.</p> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="deploy-the-application-to-aks">Deploy the Application to AKS<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3#deploy-the-application-to-aks" class="hash-link" aria-label="Direct link to Deploy the Application to AKS" title="Direct link to Deploy the Application to AKS"></a></h4> <p>Create a Kubernetes deployment file named <code>deployment.yaml</code> in the project’s root folder with the following contents. Update the image field to match the name of your registry and container image.</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: apps/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: Deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> name: my-app-deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> replicas: 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> selector:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> matchLabels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> app: my-app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> template:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> labels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> app: my-app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> containers:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> - name: my-app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> image: my-registry.azurecr.io/my-app-image</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> ports:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> - containerPort: 5000</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Finally, deploy the application to the AKS cluster using the following command:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f deployment.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="verify-the-deployment">Verify the Deployment<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3#verify-the-deployment" class="hash-link" aria-label="Direct link to Verify the Deployment" title="Direct link to Verify the Deployment"></a></h4> <p>Once deployed, verify that the application is running using the following command:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get pods</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>You should see a pod named <code>my-app</code> in the <code>Running</code> state.</p> <p>To access the application, port-forward the service using the following command: </p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl port-forward svc/my-app-service 5000:5000</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Finally, navigate to <code>http://localhost:5000</code> in a web browser to verify the application is running.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/dynamic-repricing-of-products-using-intelligent-apps-part-3#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h3> <p>In the final part of this series, you learned how to create a simple Flask web app that interacts with the Azure Machine Learning endpoint to provide real-time price predictions and visualize them. By integrating cloud-based artificial intelligence (AI) models with a web interface like this, businesses can dynamically adjust their pricing—helping them remain competitive and stand out from the rest.</p> <p>If you like what you’ve seen in this series, try the <strong><a href="https://aka.ms/intelligent-apps/csc" target="_blank" rel="noopener noreferrer">Intelligent Apps Cloud Skill Challenge</a></strong>. You can also register for <strong>AKS <a href="https://aka.ms/aks-day" target="_blank" rel="noopener noreferrer">Customer</a> and <a href="https://aka.ms/aks-lab-day" target="_blank" rel="noopener noreferrer">Lab</a> Days</strong> at the premier conference for cloud-native technologies, <em>KubeCon EU 2024</em>.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[4. Fuel Your Intelligent Apps with Azure AI]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/fuel-your-intelligent-apps-with-azure-ai</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/fuel-your-intelligent-apps-with-azure-ai</guid> <pubDate>Mon, 11 Mar 2024 09:00:00 GMT</pubDate> <description><![CDATA[In this kickoff post, we'll set the stage for the week of posts by describing the application scenario (motivation) and introducing core terminology (LLM Ops), developer tools (Azure AI Studio, frameworks) and design patterns (RAG) to help you jumpstart your journey building and deploying generative AI solutions in the enterprise. By the end of this week, you should have a good understanding of how to build a copilot app end-to-end on the Azure AI platform, how to deploy it for integration with real-world applications, and how to incorporate responsible AI principles into your development workflow.]]></description> <content:encoded><![CDATA[ <p>Welcome to the <code>Azure AI</code> week on <strong>#60Days Of IA</strong>. Over the next 5 days, we'll share a series of blog posts that give you a comprehensive look at the tools and end-to-end development workflow reequired to build intelligent applications <a href="https://techcommunity.microsoft.com/t5/ai-ai-platform-blog/a-code-first-experience-for-building-a-copilot-with-azure-ai/ba-p/4058659?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">code-first on the Azure AI platform</a>.</p> <p>In this kickoff post, we'll set the stage for the week of posts by describing the application scenario (motivation) and introducing core terminology (LLM Ops), developer tools (Azure AI Studio, frameworks) and design patterns (RAG) to help you jumpstart your journey building and deploying generative AI solutions in the enterprise. By the end of this week, you should have a good understanding of how to build a copilot app end-to-end on the Azure AI platform, how to deploy it for integration with real-world applications, and how to incorporate responsible AI principles into your development workflow.</p> <p>Ready? Let's get started!</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover-today">What We'll Cover Today<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/fuel-your-intelligent-apps-with-azure-ai#what-well-cover-today" class="hash-link" aria-label="Direct link to What We'll Cover Today" title="Direct link to What We'll Cover Today"></a></h2> <ul> <li><strong>Application Scenario |</strong> What is Contoso Chat?</li> <li><strong>Paradigm Shift |</strong> What is LLM Ops?</li> <li><strong>Unified Platform |</strong> What is Azure AI Studio?</li> <li><strong>Copilot Experience |</strong> What is the development workflow?</li> <li><strong>The Week Ahead |</strong> What will we cover?</li> <li><strong>Resources:</strong> <a href="https://aka.ms/ai-studio/collection?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Explore the Code-First Azure AI Collection</a></li> </ul> <hr> <p><img loading="lazy" alt="Roadmap" src="https://azure.github.io/Cloud-Native/assets/images/banner-6dc91900960e8cdf2fbeece64e5fc877.png" width="1000" height="420" class="img_ev3q"></p> <br> <p>Generative AI applications are transforming the user experience and accelerating adoption of AI tools and solutions in the enterprise. But as developers, we face new challenges in building solutions <strong>end-to-end</strong> - from prompt engineering to LLM Ops. We need new tools, frameworks, and guidance to help us navigate and streamline a fast-growing ecosystem.</p> <p>In <a href="https://techcommunity.microsoft.com/t5/ai-ai-platform-blog/a-code-first-experience-for-building-a-copilot-with-azure-ai/ba-p/4058659?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">a recent blog post</a> we described how the Azure AI platform is addressing these challanges with a <em>code-first experience for building a copilot application end-to-end</em> with your data and APIs. This week, we unpack that post in more detail - walking you through a end-to-end application sample, and several <em>quickstart</em> options, to get you started on your own generative AI solutions.</p> <p>To kick things off, let's set the stage by describing a common generative AI application scenario ("Contoso Chat") and introduce core terminology, tools and processes that we will be using throughout the week, on our development journey.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="1--the-application-scenario">1 | The Application Scenario<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/fuel-your-intelligent-apps-with-azure-ai#1--the-application-scenario" class="hash-link" aria-label="Direct link to 1 | The Application Scenario" title="Direct link to 1 | The Application Scenario"></a></h2> <p>Say hello to <em>Contoso Outdoor Company</em> - an online retailer of outdoor adventuring equipment with a loyal and growing customer base. Your website has a rich catalog of items organized into categories like <em>tents</em>, <em>backpacks</em>, <em>hiking boots</em> and more. Customers visit the site looking to find the best gear for their next adventure, and often have questions about the products, or how they might fit with their previous purchases.</p> <p><img loading="lazy" alt="Contoso Outdoors site" src="https://azure.github.io/Cloud-Native/assets/images/app-contoso-outdoors-2e49c3ff8b9705669d3e5f144b6aef09.png" width="2734" height="2008" class="img_ev3q"></p> <p>The company has a customer support line, but it is getting overwhelmed with calls and you don't have the resources to meet the demand. You hear about generative AI applications and decide to build a <em>customer support chat AI</em> agent that knows your catalog and customers. You can then integrate it into the site as shown, to improve customer satisfaction and drive follow-up actions.</p> <p><img loading="lazy" alt="Contoso Chat concept" src="https://azure.github.io/Cloud-Native/assets/images/app-contoso-chat-concept-1e6a568ef26af525237d5b3df58804c8.png" width="1457" height="529" class="img_ev3q"></p> <p>You identify three requirements for your chat AI application:</p> <ul> <li><strong>Custom Data</strong>. The application responses must prioritize your catalog data.</li> <li><strong>Responsible AI</strong>. The application must follow responsible AI principles.</li> <li><strong>LLM Ops</strong>. The end-to-end development workflow must be operationalizable.</li> </ul> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="2--the-paradigm-shift">2 | The Paradigm Shift<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/fuel-your-intelligent-apps-with-azure-ai#2--the-paradigm-shift" class="hash-link" aria-label="Direct link to 2 | The Paradigm Shift" title="Direct link to 2 | The Paradigm Shift"></a></h2> <p>Building generative AI applications requires a different mindset from traditional ML applications. The latter are trained on finite custom data, deploying an endpoint that makes <em>predictions</em>. By contrast, generative AI applications are trained on massive amounts of data, using large language models (LLM) and natural language processing (NLP) to <em>generate</em> new content.</p> <p>The focus now moves from <strong>MLOps</strong> (workflow for building ML apps) to <strong>LLMOps</strong> (workflow for building generative AI apps) - starting with <em>prompt engineering</em>, a process where we refine the inputs to the LLM ("prompts") through a process of trial-and-error (build-run-evaluate) till the responses meet our quality, cost and performance requirements. The generative AI application lifecycle now looks more like this:</p> <p><img loading="lazy" alt="LLM App Lifecyle" src="https://azure.github.io/Cloud-Native/assets/images/llm-app-lifecycle-6509347ca42b47d5c7ae425b890e5efe.png" width="1147" height="646" class="img_ev3q"></p> <ol> <li><strong>Ideation Phase</strong>: Start by building the basic AI application (copilot) for your scenario. At this stage, you define the architectural elements (AI resources, design patterns) and language models (chat completion, chat evaluation, text embeddings) that you will need to build-run-evaluate the basic experience. And have sample data to test against.</li> <li><strong>Augmentation Phase</strong>: Iteratively refine the quality and performance of your application by <em>engineering</em> the prompts, <em>tuning</em> the models, and <em>evaluating</em> the responses with sample data (smal) and batch runs (large). Use relevant metrics (groundedness, coherence, relevance, fluency) to guide decisions on what to change, and when to stop iterating.</li> <li><strong>Operationalization Phase:</strong> Now, you're ready to deploy the application to a production environment so that the endpoint can be accessed by others, for integrating into user-facing experiences. This is also a good time to review the entire workflow for responsible AI practices, and explore automation and monitoring solutions for efficiency and performance.</li> </ol> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="3--the-azure-ai-platform">3 | The Azure AI Platform<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/fuel-your-intelligent-apps-with-azure-ai#3--the-azure-ai-platform" class="hash-link" aria-label="Direct link to 3 | The Azure AI Platform" title="Direct link to 3 | The Azure AI Platform"></a></h2> <p>Implementing this end-to-end workflow and managing the various phases of the application lifecycle can be challenging for developers. Azure AI Studio addresses these challenges with a <a href="https://ai.azure.com/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer"><strong>unified platform</strong></a> for building generative AI applications and custom copilot experiences.</p> <p>Use the platform to <strong>explore</strong> language models from Microsoft and the broader community, and experiment with them in a built-in playground. Then <strong>build</strong> your AI project by seamlessly integrating with deployed models and built-in AI services - and <strong>manage</strong> your AI resources (for compute, access, billing and more) from the unified UI.</p> <p><img loading="lazy" alt="Azure AI Studio" src="https://azure.github.io/Cloud-Native/assets/images/azure-ai-c35fed704147614a7f607c699852d602.png" width="1147" height="633" class="img_ev3q"></p> <p>As a developer, you have both low-code and code-first options for engaging with the platform. Use the <a href="https://ai.azure.com/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI Studio UI</a> for a browser-based low-code experience, and the <a href="https://learn.microsoft.com/azure/ai-studio/how-to/sdk-generative-overview?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI SDK</a> for a Python-based code-first experience. In our posts this week, we'll focus on the code-first experience, and show you how to build a copilot app on Azure AI using the Python SDK and popular frameworks.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="4--the-copilot-experience">4 | The Copilot Experience<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/fuel-your-intelligent-apps-with-azure-ai#4--the-copilot-experience" class="hash-link" aria-label="Direct link to 4 | The Copilot Experience" title="Direct link to 4 | The Copilot Experience"></a></h2> <p>So how do we get started on the end-to-end development journey using the Azure AI platform? Let's start by defining what we mean by a <em>copilot</em> experience for enterprise-grade generative AI applications. A copilot is:</p> <ul> <li>a generative AI application that uses large language models (LLM) and natural language processing (NLP)</li> <li>to assist customers in completing complex cognitive tasks <strong>using your data</strong></li> <li>typically using conversational “chat” interactions (request-reponse)</li> </ul> <p>The copilot (generative AI application) is deployed in the cloud to expose an interaction endpoint (API) that can be integrated into customer-facing experiences (e.g,, web or mobile apps) for real-world use. For our specific application scenario, the implementation will involve two components:</p> <ul> <li>Contoso Chat (copilot API) as the backend component with the chat AI</li> <li>Contoso Outdoors (web App) as the frontend component with the chat UI</li> </ul> <p><img loading="lazy" alt="Azure Copilot" src="https://azure.github.io/Cloud-Native/assets/images/copilot-architecture-a14ddb6e2ac8e5ded7e544f1093325fc.png" width="2856" height="1292" class="img_ev3q"></p> <p>The figure shows the high-level application architecture for <a href="https://www.youtube.com/watch?v=UbJg7RNLi7E" target="_blank" rel="noopener noreferrer">building generative AI applications using custom code with Azure AI</a>, where the <strong>App</strong> represents the front-end component and the blue box encloses the components of the <strong>Copilot</strong> implementation exposed through the managed online endpoint (API). The copilot experience now involves the following steps:</p> <ul> <li>The user (customer) asks a question from the chat UI (web app)</li> <li>The web app sends the question to the chat API (copilot endpoint)</li> <li>The chat API invokes our custom Python code (chat function) which:<!-- --> <ul> <li>converts the user question (prompt) into a machine-friendly format (vector)</li> <li>uses the vectorized prompt to find matches in our custom data (search index)</li> <li>combines the user question with custom results for an enhanced prompt</li> <li>sends this prompt to the chat model to get the completion (answer)</li> </ul> </li> <li>The chat API now returns the answer as a response to the chat UI request</li> </ul> <p>To build this workflow requires us to complete the following steps:</p> <ol> <li>Provision the necessary resources on Azure</li> <li>Create the search index using our custom data</li> <li>Deploy chat and embedding models for use by the chat function</li> <li>Configure connections between chat function and models, resources</li> <li>Write the code to <em>orchestrate</em> the steps for the chat function</li> <li>Deploy our chat function to expose the API endpoint online</li> <li>Integrate the API endpoint with our front-end application for usage</li> </ol> <p>From an LLM Ops perspective, we also need to consider two additional steps:</p> <ol> <li>Evaluation of the chat function using sample data - to assess quality</li> <li>Automation of the workflow steps - for iteration and operationalization</li> </ol> <p>This is a non-trivial set of requirements for building, running, evaluating, and deploying a generative AI application. Thankfully, the Azure AI platform and related ecosystem of tools and services, helps streamline the process for developers - allowing us to focus on our chat function logic and user experience.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="5--the-week-ahead">5 | The Week Ahead!<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/fuel-your-intelligent-apps-with-azure-ai#5--the-week-ahead" class="hash-link" aria-label="Direct link to 5 | The Week Ahead!" title="Direct link to 5 | The Week Ahead!"></a></h2> <p>In the upcoming week, we'll dive into the implementation details of these processes in the context of a signature reference sample (Contoso Chat) and as quickstart templates that showcase usage with popular frameworks. Here's what we'll cover:</p> <ul> <li><a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-contoso-chat-end-to-end" target="_blank" rel="noopener noreferrer"><strong>Day 1:</strong></a> Build the Contoso Chat app on Azure AI (end-to-end reference sample)</li> <li><a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk" target="_blank" rel="noopener noreferrer"><strong>Day 2:</strong></a> Build a Copilot app on Azure AI with the Python SDK (quickstart)</li> <li><a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-prompt-flow" target="_blank" rel="noopener noreferrer"><strong>Day 3:</strong></a> Build a Copilot app on Azure AI with promptflow (framework)</li> <li><a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain" target="_blank" rel="noopener noreferrer"><strong>Day 4:</strong></a> Build a Copilot app on Azure AI with LangChain (framework)</li> <li><a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure" target="_blank" rel="noopener noreferrer"><strong>Day 5:</strong></a> Deploy your Copilot app responsibly on Azure AI (advanced topics)</li> </ul>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[4.1 Build Contoso Chat End-to-End]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/build-contoso-chat-end-to-end</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/build-contoso-chat-end-to-end</guid> <pubDate>Mon, 11 Mar 2024 09:01:00 GMT</pubDate> <description><![CDATA[Building generative AI applications poses new challenges for streamlining end-to-end application development - from prompt engineering, to LLM Ops. In this post we introduce Contoso Chat, a sample application for building a copilot with your data - using the Azure AI platform with prompt flow.]]></description> <content:encoded><![CDATA[ <p><strong>Welcome to Day 1️⃣ of Azure AI week on ##60Days Of IA</strong></p> <p>In today's post, we'll introduce you to the <a href="https://aka.ms/aitour/contoso-chat" target="_blank" rel="noopener noreferrer">Contoso Chat</a> sample - a comprehensive end-to-end reference sample that walks you through the journey of building the customer support AI application we talked about in our kickoff post yesterday. By the end of this tutorial, you will be able to:</p> <ul> <li>explain how to build a copilot app end-to-end on Azure AI</li> <li>explain what Retrieval Augmented Generation does for copilot apps</li> <li>explain what prompt flow is and how it streamlines your workflow</li> <li>describe the Azure AI platform and Azure AI SDK capabilities</li> </ul> <p><em>Ready? Let's go!</em></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-youll-learn-today">What You'll Learn Today<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-contoso-chat-end-to-end#what-youll-learn-today" class="hash-link" aria-label="Direct link to What You'll Learn Today" title="Direct link to What You'll Learn Today"></a></h2> <ul> <li><strong>Contoso Chat Sample</strong>: Building a copilot with Azure AI and Prompt flow</li> <li><strong>Retrieval Augmented Generation</strong>: Design pattern for using custom data</li> <li><strong>Prompt flow</strong>: Open-source tooling for orchestrating end-to-end workflow</li> <li><strong>Azure resources</strong>: Provisioning Azure for the Contoso Chat AI project</li> <li><strong>Hands-on lab</strong>: Step-by-step tutorial to build & deploy Contoso Chat</li> <li><strong>Exercise</strong>: <a href="https://aka.ms/aitour/contoso-chat" target="_blank" rel="noopener noreferrer"><em>Fork the sample</em></a> then work through the hands-on tutorial.</li> <li><strong>Resources</strong>: <a href="https://aka.ms/ai-studio/collection?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer"><em>Explore this collection</em></a> for samples, docs and training resources.</li> </ul> <br> <p><img loading="lazy" alt="Build Contoso Chat - from prompt-engineering to LLM Ops" src="https://azure.github.io/Cloud-Native/assets/images/banner-6dc91900960e8cdf2fbeece64e5fc877.png" width="1000" height="420" class="img_ev3q"></p> <hr> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="contoso-chat-sample">Contoso Chat Sample<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-contoso-chat-end-to-end#contoso-chat-sample" class="hash-link" aria-label="Direct link to Contoso Chat Sample" title="Direct link to Contoso Chat Sample"></a></h2> <p>The <a href="https://aka.ms/aitour/contoso-chat" target="_blank" rel="noopener noreferrer">Contoso Chat</a> sample provides a comprehensive end-to-end reference example for using Azure AI Studio and Prompt flow, to build a copilot application end-to-end. The sample implements a <em>customer support chat AI</em> experience - allowing customers on the Contoso Outdoors website to ask questions about related products and receive relevant responses based on their query and purchase history. The illustrated guide below gives you a high-level overview of the steps involved in building the application - from provisioning Azure resources to deploying and using the chat AI endpoint. To learn more about the application scenario, refer to our <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/fuel-your-intelligent-apps-with-azure-ai" target="_blank" rel="noopener noreferrer">kickoff post</a> for this week.</p> <p><img loading="lazy" alt="Sketchnote" src="https://azure.github.io/Cloud-Native/assets/images/contoso-chat-sketchnote-d9a7a4995f13f09e9a5a9ef860d7e366.png" width="3840" height="2160" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="rag-design-pattern">RAG Design Pattern<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-contoso-chat-end-to-end#rag-design-pattern" class="hash-link" aria-label="Direct link to RAG Design Pattern" title="Direct link to RAG Design Pattern"></a></h2> <p>Our first step is to define the application architecture for Contoso Chat. We know we want to have our copilot <em>grounded in our data</em> so that customer queries return responses that reflect the product catalog or customer purchase history.</p> <p>The challenge is that Large Language Models (LLM) are trained on massive datasets so the default responses may not be <em>relevant</em> or <em>accurate</em> with respect to your data. This is where prompt engineering and design patterns like Retrieval Augmented Generation (RAG) come in. RAG is a design pattern that uses an information <em>retrieval</em> component to get data relevant to the user prompt, then <em>augments</em> the prompt with that context before sending it to the LLM, as illustrated below.</p> <p><img loading="lazy" alt="RAG" src="https://azure.github.io/Cloud-Native/assets/images/rag-e3cc68e747ef64a374c15357852679f4.png" width="2452" height="1190" class="img_ev3q"></p> <p>We can break down the workflow into the following steps:</p> <ol> <li>User asks a question ("User prompt")</li> <li>The question is sent to an information retrieval component ("AI Search")</li> <li>This vectorizes the query ("Embedding Model")</li> <li>And uses the vector to retrieve relevant results ("Product Index")</li> <li>Results are used to augment User prompt ("Model prompt")</li> <li>The enhanced prompt is sent to the LLM ("Chat completion")</li> </ol> <p>The answer is then returned to the user, who now sees a response that is more relevant to the products in your catalog, and personalized to their purchase history. Note that this basic copilot workflow requires us to deploy two large language models:</p> <ol> <li>Text-Embedding model (e.g., <code>text-embedding-ada-002</code>) that vectories the user query</li> <li>Text-Generation model (e.g., <code>gpt-35-turbo</code>) that generates the final response</li> </ol> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="prompt-flow-orchestration">Prompt flow Orchestration<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-contoso-chat-end-to-end#prompt-flow-orchestration" class="hash-link" aria-label="Direct link to Prompt flow Orchestration" title="Direct link to Prompt flow Orchestration"></a></h2> <p>Implementing the RAG pattern requires a number of interactions between the language model deployments and the data sources used (e.g., search index for products, cusomer database for purchase history), and <em>coordination</em> of intermediate steps before the final response can be delivered. This is where frameworks like Prompt flow, LangChain and Semantic kernel come in.</p> <p>The Contoso Chat sample makes extensive use of Prompt flow - an <a href="https://github.com/microsoft/promptflow" target="_blank" rel="noopener noreferrer">open-source project</a> on GitHub, with its own SDK and VS Code extension. Prompt flow provides a comprehensive solution that simplifies the process of prototyping, experimenting, iterating, and deploying your AI applications. It is <a href="https://learn.microsoft.com/azure/ai-studio/how-to/prompt-flow?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">recommended for use as a feature within Azure AI Studio</a>, making it a natural first choice for building our Contoso Chat application. The figure shows a high-level architecture diagram showcasing the Azure components used with Prompt flow as the orchestration layer.</p> <p><img loading="lazy" alt="Prompt Flow Architecture" src="https://azure.github.io/Cloud-Native/assets/images/contoso-chat-flow-93b5445266637eae6aefcc9e85678a8d.png" width="2582" height="866" class="img_ev3q"></p> <p>With Prompt flow, your application is defined as a a directed acyclic graph of <em>nodes</em> (<code>flow.dag.yaml</code>) that connect <em>input</em> (prompt) and final <em>output</em> (response) - with intermediate nodes implemented as Python <em>functions</em> (tools) that process or transform the data flowing through them. The Prompt flow extension in VS Code provides a rich <em>visual editor</em> capability as shown below, making it easy to define, debug, run, and test, your application in a local development environment. <em>This view also helps us see how the RAG pattern is implemented in practice, in our copilot</em>.</p> <p><img loading="lazy" alt="Contoso Chat Flow" src="https://azure.github.io/Cloud-Native/assets/images/promptflow-visual-21dff741b41220833a6add4946da83ab.png" width="1436" height="905" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="azure-provisioning">Azure Provisioning<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-contoso-chat-end-to-end#azure-provisioning" class="hash-link" aria-label="Direct link to Azure Provisioning" title="Direct link to Azure Provisioning"></a></h2> <p>The Contoso Chat sample comes with a <a href="https://github.com/Azure-Samples/contoso-chat/blob/main/provision.sh" target="_blank" rel="noopener noreferrer"><code>provision.sh</code></a> script that will pre-provision many of the Azure resources for you, for use in the development workflow. To get started with the implementation, follow the instructions in the <a href="https://github.com/Azure-Samples/contoso-chat/blob/main/README.md" target="_blank" rel="noopener noreferrer">README</a> file in the repo by doing the following:</p> <ol> <li><a href="https://github.com/Azure-Samples/contoso-chat/fork" target="_blank" rel="noopener noreferrer">Fork the sample</a> to your own GitHub account</li> <li><a href="https://github.com/Azure-Samples/contoso-chat/blob/main/README.md#3-development-environment" target="_blank" rel="noopener noreferrer">Setup development environment</a> using GitHub Codespaces</li> <li><a href="https://github.com/Azure-Samples/contoso-chat/tree/main#41-authenticate-with-azure" target="_blank" rel="noopener noreferrer">Authenticate</a> with your Azure subscription</li> <li><a href="https://github.com/Azure-Samples/contoso-chat/tree/main#42-run-provisioning-script" target="_blank" rel="noopener noreferrer">Run the Provisioning script</a> and verify your setup is complete</li> </ol> <p>At this point, you should have an Azure resource group created for your project with the following resources created for your application. Note that in order to complete this step, you must have a valid Azure subscription that has been given access to the relevant Azure OpenAI services. You must also have available quota for model deployments in the specific regions that we use in the provisioning script.</p> <p><img loading="lazy" alt="Provisioning Azure" src="https://azure.github.io/Cloud-Native/assets/images/provision-azure-86013b78767740531d53ab8efc7fb697.png" width="2622" height="1302" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="hands-on-lab">Hands-on Lab<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-contoso-chat-end-to-end#hands-on-lab" class="hash-link" aria-label="Direct link to Hands-on Lab" title="Direct link to Hands-on Lab"></a></h2> <p>You can now complete the step-by-step tutorial in the <a href="https://github.com/Azure-Samples/contoso-chat/blob/main/README.md" target="_blank" rel="noopener noreferrer">README</a> to build, evaluate and deploy the application. Let's quickly review the main steps involved in the end-to-end workflow.</p> <table><thead><tr><th style="text-align:left">Stage</th><th style="text-align:left">Description</th></tr></thead><tbody><tr><td style="text-align:left">1. Build a Copilot.</td><td style="text-align:left">Get familiar with the application codebase. Check out the <code>data/</code> folder to see the data we will be using for customer order (history) and product catalog (index).</td></tr><tr><td style="text-align:left">2. Provision Azure.</td><td style="text-align:left">Run the <code>./provision.sh</code> script or manually provision the required resources. This should setup an Azure AI hub (manage), an Azure AI project (build), an Azure Cosmos DB resource (customer data) and an Azure AI Search resource (product index). Verify you have a <code>config.json</code> created (for local Azure configuration) and an <code>.env</code> file (for relevant keys and endpoints for access).</td></tr><tr><td style="text-align:left">3. Add Models & Data.</td><td style="text-align:left">The provisioning script does the model deployments - but review them now. Make sure you have a chat completion model (gpt-35-turbo), a chat evaluation model (gpt-4) and a text-embeddings model (text-embedding-ada-02). Use the provided notebooks to populate the data in Azure Cosmos DB and Azure AI Search.</td></tr><tr><td style="text-align:left">4. Add Connections</td><td style="text-align:left">The <code>devcontainer</code> configuration ensures you have the Prompt flow extension installed in VS Code, and the <code>pf</code> too for command-line, by default. Use the provided notebooks to setup <em>connection configurations</em> from prompt flow to key services (Azure OpenAI, Azure AI Search, Azure Cosmos DB) for use in related notes of the prompt flow graph. Use the <code>pf</code> tool to validate these were setup correctly (on VS Code). The provision script may have setup some of these for you in the cloud (Azure) for use in later stages (deploy) - take a minute to verify and correct these as described in README.</td></tr><tr><td style="text-align:left">5. Build Prompt Flow</td><td style="text-align:left">You are all set to run the prompt flow with your data in Azure. Explore the components of the prompt flow. Click the <em>stylized P</em> icon in the sidebar to see the Prompt Flow extension activity menu. Open the <code>contoso-chat/flow.dag.yaml</code> file in VS Code, then click the <em>Visual Editor</em> option to see the view shown in the earlier screeshot above. Run it to validate it works - then explore the nodes, outputs and code.</td></tr><tr><td style="text-align:left">6. Evaluate Prompt Flow</td><td style="text-align:left">You can complete a local evaluation by opening the relevant notebook and running it <em>cell-by-cell</em>. Review the code in each cell of the notebook, then analyze the output to understand what the relevant metrics are telling you about the quality of the basic flow. The <em>batch run</em> step takes a while and requires Azure connection setup so consider that an optional step. Switch periodically to the <em>Azure AI Studio</em> website view to see how the relevant Azure AI project pages are updated to show the status of various activities or configurations.</td></tr><tr><td style="text-align:left">7. Deploy Prompt Flow</td><td style="text-align:left">Deploying the prompt flow is a 2-step process. First, we need to upload the flow (code, assets) to Azure AI Studio. Do this using the provided notebook, or you can try to do this manually using the <em>import</em> option in Azure AI Studio under the <em>Prompt Flow</em> section. Once uploaded, you need to select a runtime ("automatic") and start it to get a compute instance provisioned to execute your flow. Use that to <em>test</em> that your flow was imported successfully. Then click the <em>Deploy</em> option to deploy the flow. This will take a while - refresh the <em>Deployments</em> page to get updates. Once deployment is successful, use the built-in testing feature to try a simple question against the hosted API endpoint. <strong>Congratulations</strong> Your chat AI endpoint is ready for use!</td></tr><tr><td style="text-align:left">8. Summary & Clean up</td><td style="text-align:left">This was a lot. Note that almost every step of this process can be achieved using code (SDK), command-line (CLI) or UI (Studio website) so explore the documentation. <em>Note that Azure AI Studio is in preview</em> so the features are constantly evolving and things may break unexpectedly - send feedback if so! Finally, don't forget to <strong>delete your codespaces and your Azure resources for this lab</strong> to avoid unnecessary charges. And watch the sample repo for updates on workshop content and exercises to extend this further.</td></tr><tr><td style="text-align:left"></td><td style="text-align:left"></td></tr></tbody></table> <p>Completing this workshop can take 60-90 minutes based on your level of familiarity with the tools. In the <em>next</em> blog post, we'll dive a bit deeper into the process with specific focus on the <strong>Azure AI SDK</strong> to understand <em>how</em> you can implement core steps of the workflow from your Python application. And, in the <em>final</em> post of this week, we'll return to the Contoso Chat sample to explore deployment and evaluation in more detail - with additional guidance for ensuring responsible AI usage in your generative AI applications.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="exercise">Exercise<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-contoso-chat-end-to-end#exercise" class="hash-link" aria-label="Direct link to Exercise" title="Direct link to Exercise"></a></h2> <p>Congratulations! You made it to the end of this whirlwind tour of the Contoso Chat sample. Now it's time for you to do the hard work of building this yoursel!! Start by <a href="https://aka.ms/aitour/contoso-chat" target="_blank" rel="noopener noreferrer"><em>forking the sample</em></a> - then follow the step-by-step instructions in the README.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-contoso-chat-end-to-end#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources"></a></h2> <p>We've referenced a number of links and samples in this post. Bookmark the <a href="https://aka.ms/ai-studio/collection?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer"><em>Azure AI Studio: Code-First Collection</em></a> and revisit it regularly for an updated list of resources for code-first development of generative AI applications on Azure.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[4.2 Build A Copilot Code-First with the Azure AI Python SDK]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk</guid> <pubDate>Tue, 12 Mar 2024 09:00:00 GMT</pubDate> <description><![CDATA[Have a generative AI application you want to build, but don't know where to start? In this blog post, we introduce the Azure AI Studio Python Quickstart Sample, explain the end-to-end development workflow, then show you how you can get started customizing it, to explore your own application requirements.]]></description> <content:encoded><![CDATA[ <p><strong>Welcome to Day 2️⃣ of the Azure AI week on #60Days Of IA</strong></p> <p>Let's recap what we learned so far. In our <em>kickoff</em> post we set the stage by describing our application scenario (Contoso Chat), the paradigm shift for generative AI apps (LLM Ops) and the unified platform for streamlining development (Azure AI Studio). In the next post we walked through the signature <a href="https://aka.ms/aitour/contoso-chat" target="_blank" rel="noopener noreferrer">Contoso Chat</a> application sample to understand how we can implement that scenario using Azure AI Studio and Prompt flow - from building the chat function, to evaluating it, deploying it to a hosted endpoint, then testing that API in a chat client.</p> <p>But what if you want to get started building your own application scenario? Over the next three posts, we'll look at <em>starter samples</em> that will get you from ideation (define chat function) to operationalization (deploy chat API) using different tools and frameworks to simplify orchestration.</p> <p>Ready? Let's go!</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-youll-learn-today">What You'll Learn Today<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#what-youll-learn-today" class="hash-link" aria-label="Direct link to What You'll Learn Today" title="Direct link to What You'll Learn Today"></a></h2> <ul> <li>What is the copilot architecture?</li> <li>What is the Azure AI SDK?</li> <li>What is the Quickstart sample?</li> <li>How can I customize and extend this for my scenario?</li> <li><strong>Challenge:</strong> Fork <a href="https://github.com/Azure-Samples/aistudio-python-quickstart-sample" target="_blank" rel="noopener noreferrer">this quickstart</a> and build it, then extend it with your data.</li> <li><strong>Resources:</strong> Bookmark <a href="https://aka.ms/ai-studio/collection?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">this collection</a> for training & documentation.</li> </ul> <br> <p><img loading="lazy" alt="Build a Copilot on Azure Code-First with Azure AI SDK" src="https://azure.github.io/Cloud-Native/assets/images/banner-4d2eba8f8235ac22e80ba59b0b9a3651.png" width="1000" height="420" class="img_ev3q"></p> <hr> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="1--learning-objectives">1 | Learning Objectives<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#1--learning-objectives" class="hash-link" aria-label="Direct link to 1 | Learning Objectives" title="Direct link to 1 | Learning Objectives"></a></h2> <p>The <a href="https://github.com/Azure-Samples/aistudio-python-quickstart-sample" target="_blank" rel="noopener noreferrer">copilot ai-sdk quickstart</a> is a Python-based starter sample for a code-first approach to building a copilot experience on the Azure AI platform. Since this is the foundational sample, we'll use it to explore some of the details of the implementation and set the stage for you to explore customizing it further for your application requirements.</p> <p>By the end of this tutorial you should be able to:</p> <ol> <li>Explain the functional components of the copilot architecture</li> <li>Explain the Azure resources required to implement a copilot</li> <li>Explain the core functionality provided by the Azure AI SDK</li> <li>Build, run, evaluate, and deploy, a basic copilot with Azure AI Studio.</li> <li>Explore the Azure AI curated VS Code environment to customize the sample</li> </ol> <p>Keep in mind that this is a <em>quickstart sample</em> and is <strong>not meant for production use</strong>. We encourage you to extend and customize the sample to understand the platform capabilities and end-to-end development workflow. Make sure to validate the responses yourself and evaluate its suitability for your application needs in context.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="2-copilot-architecture">2| Copilot Architecture<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#2-copilot-architecture" class="hash-link" aria-label="Direct link to 2| Copilot Architecture" title="Direct link to 2| Copilot Architecture"></a></h2> <p>Let's first revisit the high-level application architecture for our copilot and familiarize ourselves with the core functional components. Our goal is to <strong>build the chat function</strong> component and deploy it to get a hosted <strong>Copilot API</strong> endpoint that we can integrate into front-end applications to provide a conversational chatbot capability grounded in our data. <img loading="lazy" alt="Copilot architecture" src="https://azure.github.io/Cloud-Native/assets/images/copilot-architecture-a14ddb6e2ac8e5ded7e544f1093325fc.png" width="2856" height="1292" class="img_ev3q"></p> <p>Let's review what we will need to implement this architecture:</p> <ol> <li><strong>Model Deployments</strong> - we need deployed models for chat and embeddings.</li> <li><strong>Search Index</strong> - we need a search index populated with our product data.</li> <li><strong>Azure Resources</strong> - we need to setup and configure our Azure AI project.</li> <li><strong>App Evaluation</strong> - we need to evaluate copilot quality for responsible AI.</li> <li><strong>App Deployment</strong> - we need to deploy the copilot for a hosted API endpoint.</li> </ol> <p>The <a href="https://github.com/Azure-Samples/aistudio-python-quickstart-sample" target="_blank" rel="noopener noreferrer">copilot ai-sdk quickstart</a> provides a starter codebase that implements this chat function using the Retrieval Augmented Generation (RAG) pattern with custom data. The implementation makes use of Azure AI Studio and the <a href="https://aka.ms/aistudio/docs/sdk?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI SDK (Python)</a> for a code-first approach. Since these technologies are currently in preview, we expect the sample to keep evolving quickly and <strong>recommend following the README-based tutorial there</strong> for the latest instructions.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="3--azure-ai-sdk">3 | Azure AI SDK<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#3--azure-ai-sdk" class="hash-link" aria-label="Direct link to 3 | Azure AI SDK" title="Direct link to 3 | Azure AI SDK"></a></h2> <p>Before we dive into the sample, let's take a moment to learn about the <a href="https://learn.microsoft.com/python/api/overview/azure/ai?view=azure-python-preview?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI SDK for Python (preview)</a>. The SDK consists of two packages:</p> <ul> <li><a href="https://pypi.org/project/azure-ai-generative/" target="_blank" rel="noopener noreferrer">azure-ai-generative</a> - which provides the functionality needed for building, evaluating and deploying Generative AI applications. This has extra packages (index, evaluate, promptflow) you can use for enhanced local development capabilities - or optionally, remove if unused.</li> <li><a href="https://pypi.org/project/azure-ai-resources/" target="_blank" rel="noopener noreferrer">azure-ai-resources</a> - which provides the functionality for connecting to, and managing, your Azure AI projects and resources. Use this for control plane operations to create and manage data, indexes, models and deployments.</li> </ul> <p>The generative package makes use of the resources package to <a href="https://learn.microsoft.com/azure/ai-studio/how-to/sdk-generative-overview#connecting-to-projects?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">create an <code>AIClient</code> instance</a> that can be used for connecting to the Azure AI project resources.</p> <div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ai</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">resources</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">client </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> AIClient</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">identity </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> DefaultAzureCredential</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ai_client </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> AIClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> credential</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">DefaultAzureCredential</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> subscription_id</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'subscription_id'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> resource_group_name</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'resource_group'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> project_name</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'project_name'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Once connected, you can use the generative package to build an index, run a local evaluation, or deploy chat functions and prompt flows, using the imports shown:</p> <div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ai</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">generative</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">index </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> build_index</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ai</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">generative</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">evaluate </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> evaluate</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ai</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">resources</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">entities</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">deployment </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Deployment</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>To get started, you will need to <a href="https://learn.microsoft.com/en-us/azure/ai-studio/how-to/sdk-install?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">install the SDK</a> in your local development environment. When you use the quickstart sample with GitHub Codespaces or the Azure AI curated VS Code environment, the SDK comes pre-installed and ready to use.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="4--using-the-quickstart-sample">4 | Using the Quickstart Sample<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#4--using-the-quickstart-sample" class="hash-link" aria-label="Direct link to 4 | Using the Quickstart Sample" title="Direct link to 4 | Using the Quickstart Sample"></a></h2> <p>The <a href="https://github.com/Azure-Samples/aistudio-python-quickstart-sample" target="_blank" rel="noopener noreferrer">copilot ai-sdk quickstart</a> provides a comprehensive <strong>README.md</strong> document that describes the step-by-step process for building, running, evaluating, and deploying, a starter copilot sample.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="41--pre-requisites">4.1 | Pre-Requisites<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#41--pre-requisites" class="hash-link" aria-label="Direct link to 4.1 | Pre-Requisites" title="Direct link to 4.1 | Pre-Requisites"></a></h3> <p>To get started, you will need an active Azure subscription and have access to the Azure OpenAI service to create and deploy the required models for chat completion, chat evaluation and embedddings. You will also need a GitHub account.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="42--setup-dev-environment">4.2 | Setup Dev Environment<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#42--setup-dev-environment" class="hash-link" aria-label="Direct link to 4.2 | Setup Dev Environment" title="Direct link to 4.2 | Setup Dev Environment"></a></h3> <p>The fastest way to get started exploring the sample is to fork the repo to your personal profile, then launch GitHub Codespaces by navigating to the "Codespaces" tab under the "Code" dropdown and creating a new codespace. Active codespaces are listed as shown below.</p> <p><img loading="lazy" alt="Launch" src="https://azure.github.io/Cloud-Native/assets/images/01-launch-codespaces-1ad39efaa8d2fb4aaba22c3d862d4481.png" width="440" height="308" class="img_ev3q"></p> <p>Once the Codespace is ready, you will see the Visual Studio Code editor view in your browser tab. Open the <strong>README.md</strong> in the editor, then follow the instructions to complete the tutorial.</p> <p><img loading="lazy" alt="Run" src="https://azure.github.io/Cloud-Native/assets/images/03-running-codespaces-b22f43ec205440e361612be69b0fa8bf.png" width="1237" height="793" class="img_ev3q"></p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="43--initialize-azure-ai-resources">4.3 | Initialize Azure AI Resources<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#43--initialize-azure-ai-resources" class="hash-link" aria-label="Direct link to 4.3 | Initialize Azure AI Resources" title="Direct link to 4.3 | Initialize Azure AI Resources"></a></h3> <p>To build the copilot, we need to provision the Azure resources listed below.</p> <ul> <li>An <a href="https://learn.microsoft.com/azure/ai-studio/concepts/ai-resources?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI hub resource</a> to provide a working <em>team</em> environment and manage resource access, billing and more.</li> <li>An <a href="https://learn.microsoft.com/azure/ai-studio/how-to/create-projects?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI project resource</a> to organize the data, models, and deployments for <em>an application</em>, and save its state for future use.</li> <li>An <a href="https://learn.microsoft.com/en-us/azure/search/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI Search resource</a> to host the search index for our product data.</li> <li>An <a href="https://learn.microsoft.com/azure/openai?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure OpenAI resource</a> to deploy the models for chat completion, chat evaluation and embeddings.</li> </ul> <p>For now, we will be creating these resources from the <a href="https://ai.azure.com/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI Studio UI</a> and <a href="https://portal.azure.com/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Portal</a> UI in the browser. However, we expect future support for a command-line (CLI) based approach for efficiency and automation. Refer to the sample README for the step-by-step guidance.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="44--initialize-azure-configuration">4.4 | Initialize Azure Configuration<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#44--initialize-azure-configuration" class="hash-link" aria-label="Direct link to 4.4 | Initialize Azure Configuration" title="Direct link to 4.4 | Initialize Azure Configuration"></a></h3> <p>Once we've created the Azure resources, we need to configure our Visual Studio Code environment to connect to the cloud. The repo comes with a <code>config.sample.json</code> that shows you the properties that need to be configured. The easiest way to set these is to download the <code>config.json</code> file from your Azure AI project resource and place it in the root folder. This information is then used to initialize the<code>AIClient</code> in the code, to support interactions with those resources, as explained earlier.</p> <div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "subscription_id": "your_subscription_id",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "resource_group": "your_resource_group",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "project_name": "your_project_name"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="45--configure-environment-variables">4.5 | Configure Environment Variables<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#45--configure-environment-variables" class="hash-link" aria-label="Direct link to 4.5 | Configure Environment Variables" title="Direct link to 4.5 | Configure Environment Variables"></a></h3> <p>The codebase comes with a sample <code>.env.sample</code> file that shows the environment variables you will need to configure, to run the sample. Copy this to <code>.env</code> then replace the placeholder strings with the values from the respective Azure resources you provisioned earlier. These environment variables will be used by the Azure AI SDK, to connect to relevant services (by endpoint) with required authentication (key) when implementing the chat function.</p> <div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">AZURE_SUBSCRIPTION_ID=replace_with_azure_subscription_id</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">OPENAI_API_TYPE=azure</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">OPENAI_API_KEY=replace_with_openai_key</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">OPENAI_API_BASE=replace_with_openai_base</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">OPENAI_API_VERSION=replace_with_openai_version</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">AZURE_AI_SEARCH_ENDPOINT=replace_with_aisearch_target</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">AZURE_AI_SEARCH_KEY=replace_with_aisearch_key</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">AZURE_AI_SEARCH_INDEX_NAME=replace_with_aisearch_index_name</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">AZURE_OPENAI_CHAT_MODEL=gpt-35-turbo-16k</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">AZURE_OPENAI_CHAT_DEPLOYMENT=gpt-35-turbo-16k-0613</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">AZURE_OPENAI_EVALUATION_MODEL=gpt-35-turbo-16k</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">AZURE_OPENAI_EVALUATION_DEPLOYMENT="gpt-35-turbo-16k-0613"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">AZURE_OPENAI_EMBEDDING_MODEL=text-embedding-ada-002</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">AZURE_OPENAI_EMBEDDING_DEPLOYMENT=text-ada-embedding-002-2</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="46--explore-custom-data">4.6 | Explore Custom Data<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#46--explore-custom-data" class="hash-link" aria-label="Direct link to 4.6 | Explore Custom Data" title="Direct link to 4.6 | Explore Custom Data"></a></h3> <p>At this point, the base system configuration is done and we just need to populate the data (for the search index) and then run, evaluate, and iterate, the chat function till the response quality is acceptable. Let's take a minute to explore the codebase <code>data/</code> folder to see the sample data we provide in the starter. We only use the product catalog data (to build the index) in <em>this</em> sample but you can explore usage of the other data types for advanced features or integrations later.</p> <table><thead><tr><th>Data Folder</th><th>Data Description</th></tr></thead><tbody><tr><td><code>data/0-misc</code></td><td>General information - e.g., customer policies for org.</td></tr><tr><td><code>data/1-customer-info</code></td><td>Customer purchase records - for 13 fictional customers</td></tr><tr><td><code>data/2-chat-history</code></td><td>Customer conversation history - for a subset of customers</td></tr><tr><td><code>data/3-product-info</code></td><td>Product catalog data - for 20 items in 7 categories</td></tr><tr><td><code>data/4-scores</code></td><td>Test data - for use in evaluations</td></tr><tr><td><code>data/5-prompt-templates</code></td><td>Example templates - for different contexts</td></tr></tbody></table> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="47--explore-the-codebase">4.7 | Explore The Codebase<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#47--explore-the-codebase" class="hash-link" aria-label="Direct link to 4.7 | Explore The Codebase" title="Direct link to 4.7 | Explore The Codebase"></a></h3> <p>Here are the main files you need to be aware of:</p> <table><thead><tr><th>File</th><th>Description</th></tr></thead><tbody><tr><td><code>src/run.py</code></td><td>The main entry point for executing core operations</td></tr><tr><td><code>src/streaming_utils.py</code></td><td>Functions for use in interactive conversation</td></tr><tr><td><code>src/copilot_aisdk/chat.py</code></td><td>The chat function implementation.</td></tr><tr><td><code>src/system-message.jinja2</code></td><td>The prompt template with system context (assistant)</td></tr></tbody></table> <p>You can now execute the various steps of the end-to-end workflow as follows:</p> <ul> <li><code>python src/run.py --build-index</code> - to build the search index</li> <li><code>python src/run.py --question "which tent is the most waterproof?"</code> - to test the chat function</li> <li><code>python src/run.py --evaluate</code> - to evaluate the chat function</li> <li><code>python src/run.py --deploy</code> - to deploy the chat function</li> <li><code>python src/run.py --invoke</code> - to test the deployed chat API endpoint</li> </ul> <p>Note that the exact syntax and parameters used in these commands may evolve over time - so check the README in the sample for the latest instructions.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="48--explore-the-chat-function">4.8 | Explore The Chat Function<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#48--explore-the-chat-function" class="hash-link" aria-label="Direct link to 4.8 | Explore The Chat Function" title="Direct link to 4.8 | Explore The Chat Function"></a></h3> <p>Let's briefly talk about the custom code for the copilot, found in the <code>src/chat.py</code> file.</p> <ul> <li>The main entry point is the <code>chat_completion</code> function that takes a list of messages representing the conversation history.</li> <li>The <code>get_documents</code> function extracts the last message ("user question") and uses it to retrieve relevant search results using the OpenAI embeddings model and the Azure AI Search client respectively, in a <em>retrieval augmented generation</em> (RAG) pattern.</li> <li>The <code>chat_completion</code> function then takes the returned response and crafts an enhanced prompt (with the system context template, initial user message, and returned search results) and sends the request to the OpenAI chat model for completion.</li> <li>The returned response is then returned to the user either interactively, or by adding it to the conversation thread (in stream mode).</li> </ul> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="5--operationalization">5 | Operationalization<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#5--operationalization" class="hash-link" aria-label="Direct link to 5 | Operationalization" title="Direct link to 5 | Operationalization"></a></h2> <p>The starter sample provides a simple sequence of command-line operations to build, run, evaluate, deploy, and test, the chat function. However, in a real-world scenario, you would integrate the deployed app with a front-end chat UI (like the Contoso Outdoors website) - and use the Azure AI Studio platform to further evaluate the chat function (batch runs), configure content filters (content safety), and monitor usage (performance) for iterative improvement. We'll discuss some of these tools and practices in the final post of this series.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="6--customizing-the-sample">6 | Customizing the Sample<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#6--customizing-the-sample" class="hash-link" aria-label="Direct link to 6 | Customizing the Sample" title="Direct link to 6 | Customizing the Sample"></a></h2> <p>The quickstart sample is a great starting point for exploring your own application scenarios using your own data. Note that the sample is not designed for production use - you will need to do your own validation and evaluation of responses to determine if the chat function is suitable for your application needs.</p> <p>However, this is a great time to introduce you to the <em>cloud development environment</em> provided by the <a href="https://learn.microsoft.com/azure/ai-studio/how-to/develop-in-vscode?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI curated Visual Studio Code environment</a>.This allows you to open your fork of the sample directly from Azure AI Studio, creating a compute instance with a development environment that has the Azure AI SDK and other dependencies pre-installed. Watch this video from the Azure AI Studio team to see how that works - then replicate the process to jumpstart your application exploration journey.</p> <iframe width="600" height="400" src="https://www.youtube.com/embed/UbJg7RNLi7E" title="Build generative AI applications using custom code with Azure AI" frameborder="0"></iframe> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-code-first-with-the-azure-ai-python-sdk#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources"></a></h2> <p>We've referenced a number of links and samples in this post. Bookmark the <a href="https://aka.ms/ai-studio/collection?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer"><em>Azure AI Studio: Code-First Collection</em></a> and revisit it regularly for an updated list of resources for code-first development of generative AI applications on Azure.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[4.3 Build a Copilot on Azure Code-First with Prompt Flow]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-prompt-flow</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-prompt-flow</guid> <pubDate>Wed, 13 Mar 2024 09:00:00 GMT</pubDate> <description><![CDATA[This blog walks you through how you can build, evaluate, and test a custom copilot implementation using Prompt Flow and Azure AI SDK.]]></description> <content:encoded><![CDATA[ <p><strong>Welcome to Day 3️⃣ of the Azure AI week on #60Days Of IA</strong> In the previous post, we learned about how to get started with the Azure AI SDK and using it to build a Copilot. In today's post we'll be covering <code>building a copilot with custom code and data using PromptFlow</code>.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-youll-learn-today">What You'll Learn Today<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-prompt-flow#what-youll-learn-today" class="hash-link" aria-label="Direct link to What You'll Learn Today" title="Direct link to What You'll Learn Today"></a></h2> <ul> <li>Quickstart Sample: Using PromptFlow to build a copilot.</li> <li>What is "Prompt Flow" ?</li> <li>Build the Copilot</li> <li>Evaluate and Test your flow</li> <li>Deploy the Copilot</li> <li>Challenge: <a href="https://github.com/Azure-Samples/aistudio-python-promptflow-sample" target="_blank" rel="noopener noreferrer">Try this Quickstart sample</a></li> <li>Resources: <a href="https://learn.microsoft.com/en-us/azure/ai-studio/how-to/prompt-flow?ocid=buildia24_60days_blog" target="_blank" rel="noopener noreferrer">To learn more</a></li> </ul> <br> <p><img loading="lazy" alt="Build a Copilot on Azure Code-First with Promptflow" src="https://azure.github.io/Cloud-Native/assets/images/BIA-3-50d30968064f5ff17afd9c1830f627ff.png" width="1000" height="420" class="img_ev3q"></p> <hr> <hr> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="1--learning-objectives">1 | Learning Objectives<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-prompt-flow#1--learning-objectives" class="hash-link" aria-label="Direct link to 1 | Learning Objectives" title="Direct link to 1 | Learning Objectives"></a></h2> <p>This <a href="https://github.com/Azure-Samples/aistudio-python-promptflow-sample" target="_blank" rel="noopener noreferrer">quickstart tutorial</a> walks you through the steps of creating a copilot app for the enterprise using custom Python code and Prompt Flow to ground the copilot responses in your company data and APIs. The sample is meant to provide a starting point that you can further customize to add additional intelligence or capabilities. By the end of this tutorial, you should be able to</p> <ol> <li>Describe Prompt Flow and its components</li> <li>Build a copilot code-first, using Python and Prompt Flow</li> <li>Run the copilot locally, and test it with a question</li> <li>Evaluate the copilot locally, and understand metrics</li> <li>Deploy the copilot to Azure, and get an endpoint for integrations</li> </ol> <p>Once you've completed the tutorial, try to customize it further for your application requirements, or to explore other platform capabilities. <strong>This is not a production sample</strong> so make sure you validate responses and evaluate the suitability of this sample for use in your application context.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-prompt-flow">What is Prompt Flow?<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-prompt-flow#what-is-prompt-flow" class="hash-link" aria-label="Direct link to What is Prompt Flow?" title="Direct link to What is Prompt Flow?"></a></h2> <p>Prompt Flow is a tool that simplifies the process of building a fully-fledged AI Solution. It helps you prototype, experiment, iterate, test and deploy your AI Applications. Some of the tasks you can achieve with promptflow include:</p> <ul> <li>Create executable flows linking LLM prompts and Python tools through a graph</li> <li>Debug, share, and iterate through your flows with ease</li> <li>Create prompt variants and evaluate their performance through testing</li> <li>Deploy a real-time endpoint that unlocks the power of LLMs for your application.</li> </ul> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="2--pre-requisites">2 | Pre-Requisites<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-prompt-flow#2--pre-requisites" class="hash-link" aria-label="Direct link to 2 | Pre-Requisites" title="Direct link to 2 | Pre-Requisites"></a></h2> <p>Completing the <a href="https://github.com/Azure-Samples/aistudio-python-promptflow-sample" target="_blank" rel="noopener noreferrer">tutorial</a> requires the following:</p> <ol> <li>An Azure subscription - <a href="https://azure.microsoft.com/free/cognitive-services?ocid=buildia24_60days_blog" target="_blank" rel="noopener noreferrer">Create one for free</a></li> <li>Access to Azure OpenAI in the Azure Subscription - <a href="https://aka.ms/oai/access?ocid=buildia24_60days_blog" target="_blank" rel="noopener noreferrer">Request access here</a></li> <li>Custom data to ground the copilot - <a href="https://github.com/Azure-Samples/aistudio-python-promptflow-sample/tree/main/data/3-product-info" target="_blank" rel="noopener noreferrer">Sample product-info data is provided</a></li> <li>A GitHub account - <a href="https://github.com/signup" target="_blank" rel="noopener noreferrer">Create one for free</a></li> <li>Access to GitHub Codespaces - <a href="https://docs.github.com/en/billing/managing-billing-for-github-codespaces/about-billing-for-github-codespaces#monthly-included-storage-and-core-hours-for-personal-accounts" target="_blank" rel="noopener noreferrer">Free quota should be sufficient</a></li> </ol> <p>The tutorial uses Azure AI Studio which is currently in public preview.</p> <ul> <li>Read <a href="https://learn.microsoft.com/azure/ai-studio/reference/region-support#azure-public-regions?ocid=buildia24_60days_blog" target="_blank" rel="noopener noreferrer">the documentation</a> to learn about regional availability of Azure AI Studio (preview)</li> <li>Read the <a href="https://learn.microsoft.com/azure/ai-studio/faq?ocid=buildia24_60days_blog?ocid=buildia24_60days_blog" target="_blank" rel="noopener noreferrer">Azure AI Studio FAQ</a> for answers to some commonly-asked questions.</li> </ul> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="components-of-our-prompt-flow">Components of our Prompt Flow<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-prompt-flow#components-of-our-prompt-flow" class="hash-link" aria-label="Direct link to Components of our Prompt Flow" title="Direct link to Components of our Prompt Flow"></a></h2> <ul> <li><strong>Flows:</strong> LLM apps essentially involve a series of calls to external services. For instance, our application connects to AI Search, Embeddings Model, and GPT-35-turbo LLM. A flow in PromptFlow are merely...... There are two types of flows:<!-- --> <ul> <li><strong>Standard flow:</strong> This is a flow for you to develop you LLM application.</li> <li><strong>Chat flow:</strong> This is similiar to standard flow but the difference is you can define the <code>chat_history</code>, <code>chat_input</code> and <code>chat_output</code> for our flow, enhancing the flow for conversations.</li> <li><strong>Evaluation Flow:</strong> this flow allows you to test and evaluate the quality of your LLM application. It runs on the output of yout flow and computes metrics that can be used to determine whether the flow performs well.</li> </ul> </li> </ul> <p><img loading="lazy" alt="example of our chat flow" src="https://azure.github.io/Cloud-Native/assets/images/flow-eb549bee6b170b0113b4c6504118644a.png" width="1837" height="919" class="img_ev3q"></p> <blockquote> <p>The flow is defined in <code>src/copilot_proptflow/flow.dag.yaml</code>, where you will find all the inputs, nodes and outputs.</p> </blockquote> <ul> <li><strong>Tools:</strong> these are the fundamental building blocks (nodes) of a flow. The three basic tools are:<!-- --> <ul> <li><strong>LLM:</strong> allows you to customize your prompts and leverage LLMs to achieve specific goals</li> <li><strong>Python:</strong> enables you to write custom Python functions to perform various tasks</li> <li><strong>Prompt:</strong> allows you to prepare a prompt as a string for more complex use cases.</li> </ul> </li> </ul> <p><img loading="lazy" alt="LLM Response .jinja2" src="data:image/png;base64,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" width="572" height="156" class="img_ev3q"></p> <p><em>LLM Response .jinja2 file</em></p> <p><img loading="lazy" alt="customer lookup .py" src="https://azure.github.io/Cloud-Native/assets/images/customer_lookup_py-8ad0df01239823cd7c10c46bfeae61ae.png" width="946" height="328" class="img_ev3q"></p> <p><em>Customer lookup .py file</em></p> <p>The <code>source code</code> in <code>.py</code> or <code>.jinja2</code> defines tools used by the flow.</p> <ul> <li><strong>Connections</strong> these are for storing information about how you can access external services such as LLM endpoints, API keys, databases, and custom connections e.g. Azure Cosomos DB. You can add your connection as follows using <code>Prompt flow: Create connection</code> command: <img loading="lazy" alt="Prompt flow: Create connection command" src="data:image/png;base64,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" width="705" height="83" class="img_ev3q"></li> </ul> <p>Once created, you can then update your new connection in you flow:</p> <p><img loading="lazy" alt="adding new connection to your flow" src="https://azure.github.io/Cloud-Native/assets/images/connections_editor-9ec98a325552cd07c4fc20890ac1427e.png" width="813" height="162" class="img_ev3q"></p> <ul> <li><strong>Variants:</strong> they are used to tune your prompts, for instance utilizing different variants for prompts to evaluate how your model responds to different inputs to get the most suitable combination for your application.</li> <li><strong>Running our code:</strong> You can run by clicking run on the visual editor.</li> </ul> <p><img loading="lazy" alt="screenshot showing the flow output" src="https://azure.github.io/Cloud-Native/assets/images/code_output-cc4aabbf74c12459354b4b41af4943df.png" width="1991" height="415" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="test-and-evaluate-our-promptflow">Test and evaluate our PromptFlow<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-prompt-flow#test-and-evaluate-our-promptflow" class="hash-link" aria-label="Direct link to Test and evaluate our PromptFlow" title="Direct link to Test and evaluate our PromptFlow"></a></h2> <p>Once you have built your flow, you need to evaluate the quality of your LLM app response to see if it is performing up to expectations. Some of the metrics you can include in your evaluation are:</p> <ul> <li>Groundedness: how well does the generated responses align with the source data?</li> <li>Relevance: to what extent is the model's generated responses directly related to the questions/input?</li> <li>Coherence: to what extent does the generated response sound natural, fluent and human like?</li> <li>Fluency: how grammatically proficient is the output generated by the AI?</li> </ul> <p>During local evaluation you can explore one metric e.g. groundedness or multiple metrics to evaluate your application. We will evaluate Groundedness by using the evaluation flow as shown below:</p> <p><img loading="lazy" alt="Screenshot showing evaluation of the groundeness of our flow" src="https://azure.github.io/Cloud-Native/assets/images/groundedness_flow-000dd035272bca2767c6c466ee0d102a.png" width="1345" height="687" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="exercise">Exercise<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-prompt-flow#exercise" class="hash-link" aria-label="Direct link to Exercise" title="Direct link to Exercise"></a></h2> <p>We have covered the building blocks of PromptFlow and how you can ground your data and build your AI Application. Next, once you are satisfied with the performance of your model, you can go ahead and deploy your application. You can do this using either <em>Azure AI Studio</em> or <em>Azure AI Python SDK.</em></p> <blockquote> <p>🚀 <strong>EXERCISE</strong></p> <p>Deploy the PromptFlow either using the Azure AI Studio UI or using the Azure AI SDK</p> </blockquote> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-prompt-flow#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources"></a></h2> <ul> <li><a href="https://github.com/Azure-Samples/aistudio-python-promptflow-sample" target="_blank" rel="noopener noreferrer">AI Studio Prompt Flow Quickstart Sample:</a> Code-first approach to building, running, evaluating, and deploying, a <strong>prompt flow based</strong> Copilot application <em>using your own data</em>.</li> <li><a href="https://aka.ms/aitour/contoso-chat/workshop" target="_blank" rel="noopener noreferrer">AI Tour Workshop 4:</a> Comprehensive step-by-step instructions for building the Contoso Chat production RAG app with Prompt Flow and Azure AI Studio</li> <li><a href="https://learn.microsoft.com/en-us/azure/ai-studio/?ocid=buildia24_60days_blog" target="_blank" rel="noopener noreferrer">Azure AI Studio - Documentation:</a> Build cutting-edge, market-ready, responsible applications for your organization with AI</li> </ul>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[4.4 Build a Copilot on Azure Code-First with Langchain]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain</guid> <pubDate>Thu, 14 Mar 2024 09:00:00 GMT</pubDate> <description><![CDATA[This project uses the AI Search service to create a vector store for a custom department store data. To enable the user to ask questions our data in a conversational format, we'll using Langchain to connect our prompt template with our Azure Open AI LLM.]]></description> <content:encoded><![CDATA[ <p><strong>Welcome to Day 4️⃣ of the Azure AI week on #60Days Of IA</strong> In the previous post, we learned about how to get started with the Azure AI SDK and Prompt Flow to build a Copilot. In today's post we'll be covering <code>building a copilot with custom code and data using Langchain</code>.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-youll-learn-today">What You'll Learn Today<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain#what-youll-learn-today" class="hash-link" aria-label="Direct link to What You'll Learn Today" title="Direct link to What You'll Learn Today"></a></h2> <ul> <li>Quickstart Sample: Using Langchain to build a copilot.</li> <li>What is "Langchain" ?</li> <li>Build the Copilot</li> <li>Evaluate the Copilot</li> <li>Deploy the Copilot</li> <li><strong>Challenge</strong>: <a href="https://github.com/Azure-Samples/aistudio-python-langchain-sample/tree/main" target="_blank" rel="noopener noreferrer">Try this quickstart sample</a></li> <li><strong>Resources</strong>: To learn more<!-- --> <ul> <li><a href="https://aka.ms/azureaistudio?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI Studio</a> - UI to explore, build & manage AI solutions.</li> <li><a href="https://learn.microsoft.com/azure/ai-studio?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI Studio Docs</a> - Azure AI Studio documentation.</li> <li><a href="https://learn.microsoft.com/azure/ai-services/what-are-ai-services?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI Services</a> - Azure AI Services documentation.</li> <li><a href="https://learn.microsoft.com/training/modules/improve-search-results-vector-search?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Training: Using vector search in Azure Cognitive Search</a></li> <li><a href="https://learn.microsoft.com/azure/ai-studio/tutorials/deploy-chat-web-app?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Tutorial: Deploy a web app for chat on your data</a></li> </ul> </li> </ul> <br> <p><img loading="lazy" alt="Build a Copilot on Azure Code-First with Langchain" src="https://azure.github.io/Cloud-Native/assets/images/BIA-4-ba7753c8afc145c9b84459b07a5132c6.png" width="1000" height="420" class="img_ev3q"></p> <hr> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="1--introduction">1 | Introduction<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain#1--introduction" class="hash-link" aria-label="Direct link to 1 | Introduction" title="Direct link to 1 | Introduction"></a></h2> <p>This project use the AI Search service to create a vector store for a custom department store data. We will be using Azure Open AI's text-embedding-ada-002 deployment for embedding the data in vectors. The vector representation of your data is stored in <a href="https://learn.microsoft.com/en-us/azure/search/search-what-is-azure-search?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI Search</a> (formerly known as "Azure Cognitive Search").</p> <p>To enable the user to ask questions our data in a conversational format, we'll using Langchain to connect our prompt template with our Azure Open AI LLM.</p> <p><img loading="lazy" src="https://azure.github.io/Cloud-Native/assets/images/rag-pattern-9258e32b911bad45b26e89185e972eb1.png" width="800" height="101" class="img_ev3q"></p> <p>We'll use Retrieval Augmented Generation (RAG), a pattern used in AI which uses an LLM to generate answers with your own data. In addition, we'll construct prompt template to provide the scope of our dataset, as well as the context to the submit questions. Lastly, we'll maintain the state of the conversation by store the chat history in the prompt.</p> <p><strong>Custom Data:</strong> The sample data that we'll be using in this project is a department store dataset. The dataset contains a list of customers, orders, products and their descriptions, and their prices. We'll be using this dataset to create a copilot that can answer questions about the products in the dataset.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-langchain">What is Langchain?<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain#what-is-langchain" class="hash-link" aria-label="Direct link to What is Langchain?" title="Direct link to What is Langchain?"></a></h2> <p>Langchain is a framework for developing applications powered by language models. It enables you to connect a language model such as Azure OpenAI to a prompt template including: prompt instructions, chat history, context of the chat conversation, few shot examples, content to ground its response in, etc.). This helps facilitate end-users to interact with the application to ask questions and language models to generate responses in a conversational format.</p> <p>In this exercise, we'll be using ConversationalRetrievalChain, which is a subclass of langchain that handles chats that are based on retrieving data from documents or vector datasources. We will use it to connect the Azure OpenAI model, retriever, prompt template and chat memory in order to search the AI Search database to retrieve the most relevant response. To activate the instance you need an LLM model (ex. gpt-35-turbo) to retrieve response, the prompt template rules, and chat history.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="2--pre-requisites">2 | Pre-Requisites<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain#2--pre-requisites" class="hash-link" aria-label="Direct link to 2 | Pre-Requisites" title="Direct link to 2 | Pre-Requisites"></a></h2> <p>Completing the <a href="https://github.com/Azure-Samples/aistudio-python-langchain-sample/tree/main" target="_blank" rel="noopener noreferrer">tutorial</a> requires the following:</p> <ol> <li>An Azure subscription - <a href="https://azure.microsoft.com/free/cognitive-services?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Create one for free</a></li> <li>Access to Azure OpenAI in the Azure Subscription - <a href="https://aka.ms/oai/access?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Request access here</a></li> <li>Custom data to ground the copilot - <a href="https://github.com/Azure-Samples/aistudio-python-langchain-sample/tree/main/data/3-product-info" target="_blank" rel="noopener noreferrer">Sample product-info data is provided</a></li> <li>A GitHub account - <a href="https://github.com/signup" target="_blank" rel="noopener noreferrer">Create one for free</a></li> <li>Access to GitHub Codespaces - <a href="https://docs.github.com/en/billing/managing-billing-for-github-codespaces/about-billing-for-github-codespaces#monthly-included-storage-and-core-hours-for-personal-accounts" target="_blank" rel="noopener noreferrer">Free quota should be sufficient</a></li> </ol> <p>The tutorial uses Azure AI Studio which is currently in public preview.</p> <ul> <li>Read <a href="https://learn.microsoft.com/azure/ai-studio/reference/region-support#azure-public-regions?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">the documentation</a> to learn about regional availability of Azure AI Studio (preview)</li> <li>Read the <a href="https://learn.microsoft.com/azure/ai-studio/faq?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI Studio FAQ</a> for answers to some commonly-asked questions.</li> </ul> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="open-the-copilot-with-jupiter-notebook">Open the copilot with Jupiter notebook<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain#open-the-copilot-with-jupiter-notebook" class="hash-link" aria-label="Direct link to Open the copilot with Jupiter notebook" title="Direct link to Open the copilot with Jupiter notebook"></a></h2> <p>We'll be using Python SDK to create our copilot for the Contoso outdoor/camping gear AI Chat application.</p> <p>Let's begin by opening the <code>copilot_langchain.ipynb</code> notebook in the visual studio code (VS code) editor.</p> <p><img loading="lazy" src="https://azure.github.io/Cloud-Native/assets/images/3-select-kernel-4a590a2678ea34d42043775763a364f1.png" width="800" height="539" class="img_ev3q"></p> <p>In VS code, click on <strong>Select Kernel</strong>. Then under Python Environments, select the <strong>Python 3.10.13</strong> environment you just created</p> <p><img loading="lazy" src="https://azure.github.io/Cloud-Native/assets/images/3-python-env-9c38c584f04ed4365a4a09c5d9a3c217.png" width="800" height="561" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="connect-to-azure-resources">Connect to azure resources<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain#connect-to-azure-resources" class="hash-link" aria-label="Direct link to Connect to azure resources" title="Direct link to Connect to azure resources"></a></h2> <p>In order to access the resources you created in your project in AI studio, we'll use the python SDK to authenticate and connect to them.</p> <p><img loading="lazy" src="https://azure.github.io/Cloud-Native/assets/images/conn-to-azure-d3f47ba3b62c95931dd3c5319bc3c667.png" width="800" height="271" class="img_ev3q"></p> <p>To find the most relevant results from the vector database, we'll be using Langchain's retriever to search content from Azure AI Search.</p> <p><img loading="lazy" src="https://azure.github.io/Cloud-Native/assets/images/langchain-retriever-db15974322e58790f909b7cd71030445.png" width="1020" height="73" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="create-prompt-template">Create Prompt Template<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain#create-prompt-template" class="hash-link" aria-label="Direct link to Create Prompt Template" title="Direct link to Create Prompt Template"></a></h2> <p>Prompt engineering is an integral part of providing good user experience and relevant answers. To achieve that you'll need to define a prompt template that includes system prompt rules, restrictions, chat history, input questions and context of conversation.</p> <p><img loading="lazy" src="https://azure.github.io/Cloud-Native/assets/images/prompt-template-94991e9e825cc5911bf333ceafa621b8.png" width="799" height="398" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="add-langchain-to-connect-azure-openai-and-prompt-template">Add Langchain to connect Azure OpenAI and Prompt template<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain#add-langchain-to-connect-azure-openai-and-prompt-template" class="hash-link" aria-label="Direct link to Add Langchain to connect Azure OpenAI and Prompt template" title="Direct link to Add Langchain to connect Azure OpenAI and Prompt template"></a></h2> <p>To process the search results and apply the system rules, you need it initialize the LLM. In our case, we'll using AzureChatOpenAI class to specify the GPT-35-Turbo model deployment and settings we need for the chat.</p> <p><img loading="lazy" src="https://azure.github.io/Cloud-Native/assets/images/init-azure-openai-0b30056ffa1d37a6fb768c1a6e871e21.png" width="1024" height="118" class="img_ev3q"></p> <p>All the dialogue that the end-user has with the chat needs retained to maintain the context of the conversation. That's why we are using the ConversationMemoryBuffer class to store the chat history.</p> <p><img loading="lazy" src="https://azure.github.io/Cloud-Native/assets/images/store-convo-e7af9adef38f169dfad207e47071fa59.png" width="1023" height="54" class="img_ev3q"></p> <p>To search the AI search database, we'll use a subclass of langchain to connect the Azure OpenAI, datasource retriever, prompt template and memory together. When an instance of the langchain is invoke with an user input prompt, the retriever is used to search your data in AI Search. The Azure OpenAI uses the prompt rules to process the response back to the user.</p> <p><img loading="lazy" src="https://azure.github.io/Cloud-Native/assets/images/config-langchain-b91e705d342577484133aaee2854f6f1.png" width="1024" height="141" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="run-the-copilot-with-jupiter-notebook">Run the copilot with Jupiter notebook<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain#run-the-copilot-with-jupiter-notebook" class="hash-link" aria-label="Direct link to Run the copilot with Jupiter notebook" title="Direct link to Run the copilot with Jupiter notebook"></a></h2> <p>To run a single question & answer through the sample copilot:</p> <p>Click on <strong>Run All</strong> to run the notebook.</p> <p><img loading="lazy" src="https://azure.github.io/Cloud-Native/assets/images/4-run-all-6e800f7c782b2de0e96bbff73f3ef27d.png" width="800" height="557" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="validate-your-copilot-by-asking-a-question-about-your-custom-data">Validate your copilot by asking a question about your custom data.<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain#validate-your-copilot-by-asking-a-question-about-your-custom-data" class="hash-link" aria-label="Direct link to Validate your copilot by asking a question about your custom data." title="Direct link to Validate your copilot by asking a question about your custom data."></a></h2> <p>Enter a question about the outdoor/camping gear and clothing products. For example:</p> <div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Which of your sleeping bags are polyester?</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p><img loading="lazy" src="https://azure.github.io/Cloud-Native/assets/images/5-question-7db74565dc1c2dbd15113ac7e853f154.png" width="800" height="92" class="img_ev3q"></p> <p><code>The CozyNights Sleeping Bag (item_number: 7) and the MountainDream Sleeping Bag (item_number: 14) are both made of polyester.</code></p> <p>Try asking another question. For example:</p> <div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">which tent is the most waterproof?</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/build-a-copilot-on-azure-code-first-with-langchain#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h2> <p>In this exercise you learned how to use Azure AI Search to create and load your data into a vector store. Next, you learned how to use prompt engineering by constructing <em>System Prompt</em> with instructions on how to engage with the user, the scope of the subject area to enforce grounding which prevents the LLM from providing responses that are not relevent to your data. You should now be able to build AI applications using Lanchain to connect Azure OpenAI, your prompts, chat history, context and retriever of your data source. You've now gained the knowledge on how to use the Retrieval Augmented Generation (RAG) pattern in AI which uses LLMs to generate answers with your own data.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[4.5 Deploying Your Copilot On Azure]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure</guid> <pubDate>Fri, 15 Mar 2024 09:00:00 GMT</pubDate> <description><![CDATA[You've build a RAG-based copilot application on Azure AI with Prompt flow. Now it's time to deploy it, test it, and integrated it into your chat UI experience. Let's dive in!]]></description> <content:encoded><![CDATA[ <p>Welcome to <code>Day 5️⃣</code> of our journey <strong>Building An AI App End-to-End On Azure!</strong>. It's time to wrap-up the week with a look at two key topics - <em>deployment</em> and <em>responsible AI</em>! Ready? Let's go!</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-youll-learn-in-this-post">What You'll Learn In This Post<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#what-youll-learn-in-this-post" class="hash-link" aria-label="Direct link to What You'll Learn In This Post" title="Direct link to What You'll Learn In This Post"></a></h2> <ul> <li>Deploying the chat AI (Contoso Chat)</li> <li>Deploying the chat UI (Contoso Web)</li> <li>Automate Deployments (CI/CD)</li> <li>Accelerate Solutions (Enterprise)</li> <li>Evaluate & Mitigate Harms (Responsible AI)</li> <li>Exercise: Explore training resources.</li> <li>Resources: <a href="https://aka.ms/ai-studio/collection?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer"><strong>Azure AI Studio Code-First Collection</strong></a></li> </ul> <br> <p><img loading="lazy" alt="Deploy with Responsible AI" src="https://azure.github.io/Cloud-Native/assets/images/banner-48e9ec5b9267e589628dd0902ff81a70.png" width="1000" height="420" class="img_ev3q"></p> <hr> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="1-revisiting-contoso-chat">1. Revisiting Contoso Chat<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#1-revisiting-contoso-chat" class="hash-link" aria-label="Direct link to 1. Revisiting Contoso Chat" title="Direct link to 1. Revisiting Contoso Chat"></a></h2> <p>We started the week by talking about LLM Ops, and identifying the three core phases of the end-to-end lifecycle for a generative AI application. In the previous posts, we've mostly focused on the first two phases: <strong>ideating</strong> (building & validating a starter app) and <strong>augmenting</strong> (evaluating & iterating app for quality). In this post, we'll focus on phase 3: <strong>operationalizing</strong> the application to get it ready for real-world usage.</p> <p><img loading="lazy" alt="LLM Ops" src="https://azure.github.io/Cloud-Native/assets/images/llm-app-lifecycle-6509347ca42b47d5c7ae425b890e5efe.png" width="1147" height="646" class="img_ev3q"></p> <p>First, let's remind ourselves of the high-level architecture for a copilot application. Our solution has two components:</p> <ul> <li><strong>Backend</strong>: The <em>chat AI</em> app that is deployed to provide a hosted API endpoint.</li> <li><strong>Frontend</strong>: The <em>chat UI</em> app that is deployed to support user interactions with API.</li> </ul> <p>Let's look at what deployment means in each case:</p> <p><img loading="lazy" alt="Copilot Arch" src="https://azure.github.io/Cloud-Native/assets/images/copilot-architecture-a14ddb6e2ac8e5ded7e544f1093325fc.png" width="2856" height="1292" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="2-deploy-your-chat-ai-app">2. Deploy your chat AI app<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#2-deploy-your-chat-ai-app" class="hash-link" aria-label="Direct link to 2. Deploy your chat AI app" title="Direct link to 2. Deploy your chat AI app"></a></h2> <p>In our example, the chat AI is implemented by the <a href="https://aka.ms/aitour/contoso-chat?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Contoso Chat</a> sample. Deploying this chat AI solution involves <a href="https://learn.microsoft.com/azure/ai-studio/concepts/deployments-overview?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer"><strong>three steps</strong></a>.</p> <ol> <li>Deploy the Models</li> <li>Deploy the Flows</li> <li>Deploy the Web App</li> </ol> <p>Let's look at the first two in this section, starting with <strong><a href="https://learn.microsoft.com/azure/ai-studio/concepts/deployments-overview?ocid=buildia24_60days_blogs#deploying-models" target="_blank" rel="noopener noreferrer">model deployment</a></strong>. Azure AI Studio has a rich model catalog from providers including OpenAI, HuggingFace, Meta and Microsoft Research. Some models can be deployed <em>as a service</em> (with a pay-as-you-go subscription) while others require <em>hosted, managed infra</em> (with a standard Azure subscription). Our chat AI uses three models, all of which used the hosted, managed option.</p> <ul> <li><code>gpt-35-turbo</code> - for chat completion (core function)</li> <li><code>text-embedding-ada-002</code> - for embeddings (query vectorization)</li> <li><code>gpt-4</code> - for chat evaluation (responsible AI)</li> </ul> <p>Next, let's talk about <strong><a href="https://learn.microsoft.com/azure/ai-studio/how-to/flow-deploy?tabs=azure-studio?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">deploying flows</a></strong>. There are two kinds of flows we'll use in our chat AI - <em>completion flows</em> (that we'll use for real-time inference) and <em>evaluation flows</em> (that we'll use for quality assessment). Azure AI Studio provides <a href="https://learn.microsoft.com/azure/ai-studio/how-to/flow-deploy?tabs=azure-studio?ocid=buildia24_60days_blogs#create-an-online-deployment" target="_blank" rel="noopener noreferrer">low-code deployment</a> via the UI and <a href="https://learn.microsoft.com/azure/ai-studio/how-to/flow-deploy?tabs=python?ocid=buildia24_60days_blogs#create-an-online-deployment" target="_blank" rel="noopener noreferrer">code-first deployment</a> using the Azure AI SDK. In our Contoso Chat sample, we use the SDK to <a href="https://github.com/Azure-Samples/contoso-chat/blob/main/deployment/push_and_deploy_pf.ipynb" target="_blank" rel="noopener noreferrer">upload the flow</a> to Azure, then deploy it using the UI as shown. <img loading="lazy" alt="Deploy Contoso Chat" src="https://azure.github.io/Cloud-Native/assets/images/contoso-chat-deploy-ce382b4dd234aba8c6112f5d5b11d6a2.png" width="2956" height="1388" class="img_ev3q"></p> <p>Finally, let's talk about <strong><a href="https://learn.microsoft.com/azure/ai-studio/concepts/deployments-overview?ocid=buildia24_60days_blogs#deploying-web-apps" target="_blank" rel="noopener noreferrer">deploying web apps</a></strong>. Here, the web app is a <em>chat UI</em> that can invoke requests on the deployed chat AI and validate the functionality in production. There are three options to consider:</p> <ol> <li><strong>Built-in Testing UI</strong>. When you deploy your flow via Azure AI Studio, you can visit the deployment details page and navigate to the <em>Test</em> tab, to get a built-in testing sandbox as shown. This provides a quick way to test prompts with each new iteration, in a manual (interactive) way. <img loading="lazy" alt="Deployment Testing" src="https://azure.github.io/Cloud-Native/assets/images/contoso-chat-test-4674309cf7c90e44d1e64a4f2ec95721.png" width="3558" height="2060" class="img_ev3q"></li> <li><strong>Deploy as Web App</strong>. Azure AI Studio also provides a <em>Playground</em> where you can deploy models directly (for chat completion) and <em>add your data (preview)</em> (for grounding responses) using Azure AI Search and Blob Storage resources, to customize that chat experience. Then <em>deploy a new web app</em> directly from that interface, to an Azure App Service resource. <img loading="lazy" src="https://learn.microsoft.com/azure/ai-studio/media/tutorials/chat-web-app/deploy-web-app.png?ocid=buildia24_60days_blogs" alt="Deploy as web app" class="img_ev3q"></li> <li><strong>Dedicated Web App</strong>. This is the option we'll explore in the next section.</li> </ol> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="3-deploy-your-chat-ui-app">3. Deploy your chat UI app<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#3-deploy-your-chat-ui-app" class="hash-link" aria-label="Direct link to 3. Deploy your chat UI app" title="Direct link to 3. Deploy your chat UI app"></a></h2> <p>The Contoso Chat sample comes with a dedicated <a href="https://github.com/Azure-Samples/contoso-web" target="_blank" rel="noopener noreferrer">Contoso Web</a> application that is implemented using the Next.js framework with support for static site generation. This provides a rich "Contoso Outdoors" website experience for users as shown below.</p> <p><img loading="lazy" alt="Contoso Web" src="https://azure.github.io/Cloud-Native/assets/images/app-contoso-chat-concept-1e6a568ef26af525237d5b3df58804c8.png" width="1457" height="529" class="img_ev3q"></p> <p>To use that application, simply <a href="https://github.com/Azure-Samples/contoso-web?tab=readme-ov-file#setting-up-endpoints" target="_blank" rel="noopener noreferrer">setup the endpoint variables</a> for Contoso Chat and deploy the app to Azure App Service. Alternatively, you can use <a href="https://github.com/nitya/contoso-web/tree/main-codespaces-swa?tab=readme-ov-file" target="_blank" rel="noopener noreferrer">this fork of the application</a> to explore a version that can be run in GitHub Codespaces (for development) and deployed to Azure Static Web Apps (for production) using GitHub Actions for automated deploys. Once deployed, you can click the <em>chat</em> icon onscreen *bottom right) to see the chat dialog as shown in the screenshot above, and interact with the deployed Contoso chat AI.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="4-automate-your-chat-ai-deployment">4. Automate your chat AI deployment<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#4-automate-your-chat-ai-deployment" class="hash-link" aria-label="Direct link to 4. Automate your chat AI deployment" title="Direct link to 4. Automate your chat AI deployment"></a></h2> <p>The <a href="https://github.com/Azure-Samples/contoso-chat" target="_blank" rel="noopener noreferrer">Contoso Chat sample</a> is a <strong>constantly-evolving</strong> application sample that is updated regularly to reflect both the changes to Azure AI Studio (preview) and showcase new capabilities for end-to-end development workflows. You can currently explore two additional capabilities implemented in the codebase, to streamline your deployment process further.</p> <ol> <li><strong>Using GitHub Actions</strong>. The sample has instructions to <a href="https://github.com/Azure-Samples/contoso-chat?tab=readme-ov-file#9-deploy-with-github-actions" target="_blank" rel="noopener noreferrer">Deploy with GitHub Actions</a> instead of the manual Azure AI Studio based deployment step we showed earlier. By setting up the actions workflow, you can automated deployments on every commit or PR, and get a baseline CI/CD pipeline for your chat AI, to build on later.</li> <li><strong>Using Azure Developer CLI</strong>. The sample was <a href="https://github.com/Azure-Samples/contoso-chat/pull/74" target="_blank" rel="noopener noreferrer">just azd-enabled</a> recently, making it possible to use the <a href="https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/azd-templates?tabs=csharp?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Developer CLI</a> as a unified tool to accelerate the end-to-end process from <em>provisioning</em> the resources to <em>deploying</em> the solution. The <a href="https://github.com/Azure-Samples/contoso-chat/blob/main/azure.yaml" target="_blank" rel="noopener noreferrer">azd template</a> adds support for <em>infrastructure-as-code</em>, allowing your application to have a consistent and repeatable deployment blueprint for all users. You can also <a href="https://azure.github.io/awesome-azd/?tags=ai&tags=chatgpt" target="_blank" rel="noopener noreferrer">browse the azd template gallery</a> for other <em>ChatGPT</em> style application examples.</li> </ol> <p>Note that the Contoso Chat sample is a <em>demo application</em> sample that is designed to showcase the capabilities of Azure AI Studio and Azure AI services. It is not a production-ready application, and should be used primarily as a learning tool and starting point for your own development.</p> <hr> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="5-enterprise-architecture-options">5. Enterprise Architecture Options<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#5-enterprise-architecture-options" class="hash-link" aria-label="Direct link to 5. Enterprise Architecture Options" title="Direct link to 5. Enterprise Architecture Options"></a></h2> <p>The objective of this series was to familiarize you with the Azure AI Studio (preview) platform and the capabilities it provides for building generative AI applications. And to give you a sense of how to build, run, test and deploy, your chat AI application for real-world use. But the platform is still in preview (and evolving rapidly). So what are your options if you want to build and deploy generative AI solutions at enterprise scale <strong>today</strong>? How can you design it using a well-architected cloud framework with <strong>cloud-native technologies</strong> like <a href="https://learn.microsoft.com/azure/container-apps/overview?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Container Apps</a> or <a href="https://learn.microsoft.com/azure/aks/intro-kubernetes?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a>?</p> <p>Here are some open-source samples and guidance you can explore to start with:</p> <ol> <li><a href="https://github.com/Azure-Samples/azure-search-openai-demo/" target="_blank" rel="noopener noreferrer">ChatGPT + Enterprise data with Azure Open AI and AI Search (Python)</a> - open-source sample that uses Azure App Service, Azure Open AI, Azure AI Search and Azure Blob Storage, for an enterprise-grade solution grounded in your (documents) data.</li> <li><a href="https://github.com/Azure-Samples/azure-search-openai-demo-csharp" target="_blank" rel="noopener noreferrer">ChatGPT + Enterprise data with Azure Open AI and AI Search (.NET)</a> - open-source sample chat AI for a fictitious company called "Contoso Electronics" using the application architecture shown below. <a href="https://devblogs.microsoft.com/dotnet/transform-business-smart-dotnet-apps-azure-chatgpt/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">This blog post</a> provides more details. <img loading="lazy" alt="Chat GPT Enterprise" src="https://azure.github.io/Cloud-Native/assets/images/chatgpt-enterprise-14564c996d2c974885d0832005ee72b8.png" width="1280" height="720" class="img_ev3q"></li> <li><a href="https://github.com/Azure-Samples/chat-with-your-data-solution-accelerator" target="_blank" rel="noopener noreferrer">Chat with your data Solution Accelerator</a> - uses Azure App Service, Azure Open AI, Azure AI Search and Azure Blob Storage, for an end-to-end baseline RAG sample that goes beyond the <a href="https://techcommunity.microsoft.com/t5/ai-azure-ai-services-blog/on-your-data-is-now-generally-available-in-azure-openai-service/ba-p/4059514?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure OpenAI Service On Your Data</a> feature (GA in Feb 2024).''</li> <li><a href="https://techcommunity.microsoft.com/t5/microsoft-mechanics-blog/build-your-own-private-chatgpt-style-app-with-enterprise-ready/ba-p/4069529?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Built a private ChatGPT style app with enterprise-ready architecture</a> - a blog post from the Microsoft Mechanics team that uses an <a href="https://aka.ms/GitHubChatBotUI?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">open-source chat UI sample</a> and discusses how to <a href="https://www.youtube.com/watch?v=IKcuod-JFYU&t=252s" target="_blank" rel="noopener noreferrer">enhance the chat experience with Azure AI Studio</a> and streamline setup by <a href="https://www.youtube.com/watch?v=IKcuod-JFYU&t=404s" target="_blank" rel="noopener noreferrer">using Azure Landing Zones</a>.</li> </ol> <p>We covered a lot today - but there's one last thing we should talk about before we wrap up. <strong>Responsible AI</strong>.</p> <hr> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="6-responsible-ai-in-practice">6. Responsible AI In Practice<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#6-responsible-ai-in-practice" class="hash-link" aria-label="Direct link to 6. Responsible AI In Practice" title="Direct link to 6. Responsible AI In Practice"></a></h2> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="61-principles-of-responsible-ai">6.1 Principles of Responsible AI<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#61-principles-of-responsible-ai" class="hash-link" aria-label="Direct link to 6.1 Principles of Responsible AI" title="Direct link to 6.1 Principles of Responsible AI"></a></h3> <p>By <a href="https://learn.microsoft.com/azure/machine-learning/concept-responsible-ai?view=azureml-api-2?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">one definition</a>, Responsible AI is <em>approach to developing, assessing, and deploying AI systems in a safe, trustworthy, and ethical way</em>. The <a href="https://www.microsoft.com/ai/principles-and-approach?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Responsible AI standard</a> was developed by Microsoft as a framework for building AI systems, using 6 principles to guide our design thinking.</p> <p><img loading="lazy" src="https://learn.microsoft.com/en-us/azure/machine-learning/media/concept-responsible-ai/concept-responsible-ml.png?view=azureml-api-2?ocid=buildia24_60days_blogs" alt="Responsible AI Standard" class="img_ev3q"></p> <table><thead><tr><th>Principle</th><th>Description</th></tr></thead><tbody><tr><td>Fairness</td><td>How might an AI system allocate opportunities, resources, or information in ways that are fair to the humans who use it?</td></tr><tr><td>Reliability & Safety</td><td>How might the system function well for people across different use conditions and contexts, including ones it was not originally intended for?</td></tr><tr><td>Privacy & Security</td><td>How might the system be designed to support privacy and security?.</td></tr><tr><td>Inclusiveness</td><td>How might the system be designed to be inclusive of people of all abilities?</td></tr><tr><td>Transparency</td><td>How might people misunderstand, misuse, or incorrectly estimate the capabilities of the system?</td></tr><tr><td>Accountability</td><td>How can we create oversight so that humans can be accountable and in control?</td></tr></tbody></table> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="62-implications-for-generative-ai">6.2 Implications for Generative AI<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#62-implications-for-generative-ai" class="hash-link" aria-label="Direct link to 6.2 Implications for Generative AI" title="Direct link to 6.2 Implications for Generative AI"></a></h3> <p>The <a href="https://learn.microsoft.com/en-us/training/modules/responsible-generative-ai/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Fundamentals of Responsible Generative AI</a> describes core guidelines for building generative AI solutions <em>responsibly</em> as a 4-step process:</p> <ol> <li><strong>Identify</strong> potential harms relevant to your solution.</li> <li><strong>Measure</strong> presence of these harms in outputs generated by your solution.</li> <li><strong>Mitigate</strong> harms at multiple layers to minimize impact, and ensure transparent communication about potential risks to users.</li> <li><strong>Operate</strong> your solution responsibly by defining and following a deployment and operational readiness plan.</li> </ol> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="63-identify-potential-harms">6.3 Identify Potential Harms<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#63-identify-potential-harms" class="hash-link" aria-label="Direct link to 6.3 Identify Potential Harms" title="Direct link to 6.3 Identify Potential Harms"></a></h3> <p>The first step of the process is to identify potential harms in your application domain using a 4-step process:</p> <ol> <li>Identify potential harms (offensive, unethical, fabrication) that may occur in generated content.</li> <li>Assess likelihood of each occurrence, and severity of impact.</li> <li>Test and verify if harms occur, and under what conditions.</li> <li>Document and communicate potential harms to stakeholders.</li> </ol> <p><img loading="lazy" src="https://learn.microsoft.com/en-us/training/wwl-data-ai/responsible-generative-ai/media/identify-harms.png" alt="4 steps" class="img_ev3q"></p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="64-measure-presence-of-harms">6.4 Measure Presence of Harms<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#64-measure-presence-of-harms" class="hash-link" aria-label="Direct link to 6.4 Measure Presence of Harms" title="Direct link to 6.4 Measure Presence of Harms"></a></h3> <p><a href="https://learn.microsoft.com/en-us/azure/ai-studio/concepts/evaluation-approach-gen-ai?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Evaluation of generative AI applications</a> is the process of measuring the presence of identified harms in the generated output. Think of it as a 3-step process:</p> <ol> <li>Prepare a diverse selection of input prompts that may result in the potential harms documented.</li> <li>Submit prompts to your AI application and retrieve generated output</li> <li><strong>Evaluate</strong> those responses using pre-defined criteria.</li> </ol> <p>Azure AI Studio provides many features and pathways to support evaluation. Start with <em>manual evaluation</em> (small set of inputs, interactive) to ensure coverage and consistency. Then scale to <em>automated evaluation</em> (larger set of inputs, flows) for increased coverage and operationalization.</p> <p><img loading="lazy" src="https://learn.microsoft.com/en-us/azure/ai-studio/media/evaluations/evaluation-monitor-flow.png" alt="Evaluation" class="img_ev3q"></p> <p>But what <em>metrics</em> can we use to quantify the quality of generated output? Quantifying accuracy is now complicated <em>because we don't have access to a ground truth or deterministic answer</em> that can serve as a baseline. Instead, we can use <a href="https://learn.microsoft.com/en-us/azure/ai-studio/concepts/evaluation-metrics-built-in?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">AI-assisted metrics</a> - where we <em>instruct</em> another LLM to score your generated output <strong>for quality and safety</strong> using the guidelines and criteria you provide.</p> <ul> <li><strong>Quality</strong> is measured using metrics like <em>relevance, coherence and fluency</em>.</li> <li><strong>Safety</strong> is measured using metrics like <em>groundedness and content harms</em>.</li> </ul> <p>In our <em>Contoso Chat</em> app sample, we <a href="https://github.com/Azure-Samples/contoso-chat/blob/main/eval/evaluate-chat-prompt-flow.ipynb" target="_blank" rel="noopener noreferrer">show examples</a> of local evaluation (with single and multiple metrics) and batch runs (for automated evaluation in the cloud). Here's an exmaple of what the output from the local evaluation looks like:</p> <p><img loading="lazy" alt="Local Eval" src="https://azure.github.io/Cloud-Native/assets/images/eval-local-9e0829a951099ad318f8667ec90a7099.png" width="2894" height="678" class="img_ev3q"></p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="65-content-safety-for-mitigation">6.5 Content Safety for Mitigation<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#65-content-safety-for-mitigation" class="hash-link" aria-label="Direct link to 6.5 Content Safety for Mitigation" title="Direct link to 6.5 Content Safety for Mitigation"></a></h3> <p>One of the most effective ways to mitigate harmful responses from generative AI models in Azure OpenAI is to use <a href="https://learn.microsoft.com/en-us/azure/ai-studio/concepts/content-filtering?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Content Filtering</a> powered by the <a href="https://learn.microsoft.com/en-us/azure/ai-services/content-safety/overview?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI Content Safety</a> service. The service works by running the user input (prompt) and the generated output (completion) through <em>an ensemble of classification models</em> that are trained to detect, and act on, identified caegories of harmful content.</p> <p>Azure AI Studio provides a default content safety filter, and allows you to create custom content filters with more tailored configurations if you opt-in to that capability first. These filters can then be <em>applied</em> to a model or app deployment to ensure that inputs and outputs are gated to meet your content safety requirements.</p> <p><img loading="lazy" src="https://learn.microsoft.com/en-us/azure/ai-studio/media/content-safety/content-filter/configure-threshold.png#lightbox" alt="Create Filter" class="img_ev3q"></p> <p>The screenshot shows the <a href="https://learn.microsoft.com/azure/ai-studio/concepts/content-filtering?ocid=buildia24_60days_blogs#content-filtering-categories-and-configurability" target="_blank" rel="noopener noreferrer">different content filtering categories</a> and the level of configurability each provides. This allows us to identify and mitigate different categories of issues (Violence, Hate, Sexual and Self-harm) by <strong>automatically detecting</strong> these in both user prompts (input) and model completions (output). An additional filter (optional) lets you enable filters for more advanced usage scenarios including <em>jailbreaks, protected content or code</em> as <a href="https://learn.microsoft.com/en-us/azure/ai-studio/concepts/content-filtering?ocid=buildia24_60days_blogs#more-filters-for-generative-ai-scenarios" target="_blank" rel="noopener noreferrer">described here</a>.</p> <p><img loading="lazy" src="https://learn.microsoft.com/en-us/azure/ai-studio/media/content-safety/content-filter/additional-models.png" alt="Content Filter" class="img_ev3q"></p> <p>Once the filters are applied, the deployment can be opened up in the Playground, or using an integrated web app, to validate that the filters work. Check out <a href="https://ignite.microsoft.com/en-US/sessions/5db0e51a-d8b1-4234-b149-31671a633ffc?source=sessions?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">this #MSIgnite session</a> from the Responsible AI team for strategies and examples for responsible AI practices with prompt engineering and retrieval augmented generation patterns in context.</p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="7-exercise">7. Exercise:<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#7-exercise" class="hash-link" aria-label="Direct link to 7. Exercise:" title="Direct link to 7. Exercise:"></a></h2> <p>We covered a lot today - and that also brings us to the end of our journey into Azure AI in this series. Want to get hands-on experience with some of these concepts? Here are some suggestions:</p> <ol> <li>Walk through the <a href="https://aka.ms/aitour/contoso-chat?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Contoso Chat</a> sample end-to-end, and get familiar with the Azure AI Studio platform and the LLM Ops workflow for generative AI solutions.</li> <li>Explore the <a href="https://aka.ms/rai-hub/website?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Responsible AI Developer Hub</a> and try out the Content Safety and Prompt flow Evaluation workshops to get familiar with the Responsible AI principles and practices for generative AI.</li> </ol> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="8-resources">8. Resources<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/deploying-your-copilot-on-azure#8-resources" class="hash-link" aria-label="Direct link to 8. Resources" title="Direct link to 8. Resources"></a></h2> <p>We covered a lot this week!! But your learning journey with Generative AI development and Azure AI is just beginning. Want to keep going? Here are three resources to help you:</p> <ol> <li><a href="https://aka.ms/ai-studio/collection?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI Studio for Developers</a></li> <li><a href="https://aka.ms/rai-hub/collection?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Responsible AI For Developers</a></li> <li><a href="https://aka.ms/aitour/contoso-chat?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Contoso Chat Sample</a></li> </ol>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[5 The Role of Platform Engineering in Developing Intelligent Apps]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/the-role-of-platform-engineering-in-developing-intelligent-apps</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/the-role-of-platform-engineering-in-developing-intelligent-apps</guid> <pubDate>Fri, 22 Mar 2024 09:00:00 GMT</pubDate> <description><![CDATA[Azure and platform engineering pave the way for the efficient development, deployment, and maintenance of Intelligent Apps, triumphing over traditional approaches.]]></description> <content:encoded><![CDATA[ <p><img loading="lazy" alt="The Role of Platform Engineering in Developing Intelligent Apps" src="https://azure.github.io/Cloud-Native/assets/images/5-1-5b06dbf0bdeacc4c9b1b3918e6440a9d.png" width="720" height="438" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-role-of-platform-engineering-in-developing-intelligent-apps">The Role of Platform Engineering in Developing Intelligent Apps<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/the-role-of-platform-engineering-in-developing-intelligent-apps#the-role-of-platform-engineering-in-developing-intelligent-apps" class="hash-link" aria-label="Direct link to The Role of Platform Engineering in Developing Intelligent Apps" title="Direct link to The Role of Platform Engineering in Developing Intelligent Apps"></a></h2> <p>Intelligent Apps leverage advanced technologies like machine learning (ML), data analytics, and artificial intelligence (AI) to enhance decision-making, content generation, and user experiences. These apps incorporate AI and ML components to process data, derive insights, and adapt to user behavior to boost efficiency and personalization.</p> <p><a href="https://learn.microsoft.com/platform-engineering/what-is-platform-engineering?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Platform engineering</a> is integral to building robust Intelligent Apps. It’s the DevOps-inspired practice of designing, building, and maintaining the infrastructure and systems that underpin software applications. This includes strengthening security, maintaining compliance, controlling costs, and enhancing business value within a governed framework and via an internal developer platform.</p> <p>Intelligent Apps require careful planning and execution as they necessitate complex processes like data management, model optimization and training, algorithm selection, and development. Fortunately, platform engineering helps with these tasks.</p> <p>Coupled with Azure services, platform engineering creates a robust foundation for developing, deploying, and maintaining Intelligent Apps. With the help of platform engineering, you’re free to focus on what you do best as a developer. Instead of worrying about the details of infrastructure, ensuring compliance, or navigating the maze of underlying technologies that support modern apps, you can put your efforts toward designing, implementing, and iterating on their Intelligent Apps.</p> <p>With platform engineering practices, Azure’s scalable infrastructure streamlines the development lifecycle, enabling rapid prototyping and iteration. Azure services—including Azure’s <a href="https://azure.microsoft.com/solutions/ai?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">AI portfolio</a> and <a href="https://azure.microsoft.com/products/ai-services/openai-service?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure OpenAI Service</a>—enhance app intelligence. Furthermore, <a href="https://azure.microsoft.com/products?ocid=buildia24_60days_blogs#devops" target="_blank" rel="noopener noreferrer">Azure’s DevOps-supporting tools</a> automate deployment and maintenance tasks, ensuring seamless updates and operational efficiency.</p> <p>Let’s explore how Azure and platform engineering pave the way for the efficient development, deployment, and maintenance of Intelligent Apps.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-platform-engineering-paves-the-way-for-intelligent-apps">How Platform Engineering Paves the Way for Intelligent Apps<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/the-role-of-platform-engineering-in-developing-intelligent-apps#how-platform-engineering-paves-the-way-for-intelligent-apps" class="hash-link" aria-label="Direct link to How Platform Engineering Paves the Way for Intelligent Apps" title="Direct link to How Platform Engineering Paves the Way for Intelligent Apps"></a></h3> <p>The rise of cloud computing and microservices has laid the groundwork for platform engineering techniques.</p> <p>As applications have become more advanced in their functionality, so too has the underlying ecosystem necessary to deploy, manage, and maintain them. This shift necessitated creating specialized platforms to manage deployment complexities using platform engineering processes. Cloud resources and Infrastructure as Code (IaC) further revolutionized platform engineering by automating infrastructure provisioning and management via code. This streamlined resource deployment, improved scalability, and boosted reliability across environments.</p> <p>While these technologies provide substantial benefits to developers, they require a careful strategy to be truly effective. This is where platform engineering truly shines. A well-engineered platform supports developer efforts through the concept of self-service with guardrails. It facilitates the autonomy you need in your workflows while simultaneously offering a set of organizational constraints that free you from unnecessary context switching, helping dissolve silos between teams.</p> <p>Often embracing an “everything as code” philosophy, platform engineering ensures that everything from infrastructure to deployment is easily managed. The “as code” concept allows for infrastructure, policy, security, and all cloud configurations to be maintained like any other form of code using familiar tools and repositories. This approach offers a powerful method for achieving self-service autonomy, enabling you to make changes in a format you’re already familiar with.</p> <p>Platform engineering supports the entire lifecycle of Intelligent Apps, from conceptualization to deployment and scaling:</p> <ul> <li><strong>Conceptualization and design</strong>—Platform engineering teams collaborate with app developers, data scientists, and stakeholders to grasp Intelligent Apps’ requirements. They offer tech insights, aiding in tech selection and architecture design for scalability, reliability, and performance. Platform engineers help design data architecture, encompassing pipelines, storage, and processing frameworks. They also provide start-right templates that ensure you can start the development process correctly, adhering to policy, following best practices, and utilizing the most relevant technologies.</li> <li><strong>Development and testing</strong>—Platform engineers configure development environments, giving you tools for efficient coding. They also establish continuous integration and continuous delivery (CI/CD) pipelines for automated processes and offer testing infrastructures. Tools like <a href="https://azure.microsoft.com/products/devops/pipelines/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Pipelines</a> and <a href="https://azure.microsoft.com/products/devops/test-plans/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Test Plans</a> help. By putting the right infrastructure in place—and empowering you with enough self-service autonomy to utilize this infrastructure—platform engineering allows for more focused and consistent development and testing cycles.</li> <li><strong>Model training and optimization</strong>—Using technologies like distributed computing and GPU acceleration, platform engineers work with data scientists to establish scalable infrastructure for model training. They enhance training efficiency by adjusting hardware setups, refining data pipelines, and employing parallel processing methods. Additionally, they integrate model monitoring tools for performance tracking and retraining.</li> <li><strong>Deployment and scaling</strong>—Platform engineers create automated deployment pipelines and infrastructure templates for deploying Intelligent Apps across various environments. They guarantee reliable, scalable processes, monitor performance, and use tools like Kubernetes for containerized workloads, ensuring scalability, resilience, and portability.</li> <li><strong>Monitoring and maintenance</strong>—Platform engineers deploy monitoring and observability tools, like <a href="https://azure.microsoft.com/products/monitor/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Monitor</a>, for real-time tracking of Intelligent Apps’ health, performance, and usage. They set up alert systems and automated responses, ensuring proactive issue detection and minimizing downtime. Regular performance tuning, capacity planning, and security audits optimize infrastructure efficiency.</li> </ul> <p>Platform engineering ensures scalability, improves reliability through optimized performance, and fosters efficiency by automating workflows—aspects that make for more powerful, performant Intelligent Apps.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Explore the <a href="https://learn.microsoft.com/platform-engineering/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Platform Engineering Guide</a> to learn how platform engineering teams can use building blocks from Microsoft and other vendors to create deeply personalized, optimized, and secure developer experiences.</p></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="platform-engineering-in-action">Platform Engineering in Action<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/the-role-of-platform-engineering-in-developing-intelligent-apps#platform-engineering-in-action" class="hash-link" aria-label="Direct link to Platform Engineering in Action" title="Direct link to Platform Engineering in Action"></a></h4> <p>To illustrate the impact of platform engineering on developing Intelligent Apps, let’s compare the journey of developing one such app using a traditional software development methodology versus using an Azure-supported platform engineering approach.</p> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="the-initial-phase">The Initial Phase<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/the-role-of-platform-engineering-in-developing-intelligent-apps#the-initial-phase" class="hash-link" aria-label="Direct link to The Initial Phase" title="Direct link to The Initial Phase"></a></h5> <p>In the traditional software development approach, the initial phase typically involves requirements gathering followed by siloed development stages. Comparatively, a platform engineering approach involves embracing integrated planning and development stages. Teams collaborate from the beginning, leveraging Azure’s cloud capabilities for streamlined workflows. Azure services, such as <a href="https://azure.microsoft.com/products/devops/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure DevOps</a>, facilitate seamless coordination between development, operations, and product teams, ensuring alignment with business objectives.</p> <p>From the outset, platform engineering supports your development efforts with a templated approach to creating new apps or services. Platform engineers often create start-right templates based on best practices, industry standards, or organizational guidelines to ensure consistency, efficiency, and quality from the project’s conception. These templates may encompass IaC templates, service catalogs, or repositories containing pre-built components and libraries you can use to accelerate development.</p> <p>Platform engineers help to define the core policies that govern resource provisioning and configuration. These policies might include restrictions on resource types, sizes, or regions, as well as rules for security, compliance, and cost management. With these guardrails in place, you can work without constantly looking over your shoulder to ensure you’re adhering to policy and best practices.</p> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="development-and-deployment-phases">Development and Deployment Phases<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/the-role-of-platform-engineering-in-developing-intelligent-apps#development-and-deployment-phases" class="hash-link" aria-label="Direct link to Development and Deployment Phases" title="Direct link to Development and Deployment Phases"></a></h5> <p>Traditionally, development progresses linearly with limited flexibility for adaptation. Deployment may encounter challenges due to disparate environments, leading to inconsistencies. Moreover, in traditional methods, siloing commonly occurs across design, development, testing, and deployment stages, hampering communication, slowing progress, creating inefficiencies, and hindering collaboration—ultimately resulting in disjointed outcomes.</p> <p>By empowering you with self-service platforms and powerful automation, a well-engineered platform expedites your development efforts. Self-service interfaces simplify provisioning infrastructure resources such as virtual machines, containers, databases, storage, and networking for use in these phases. You can request and provision the resources you need on-demand without waiting for manual intervention from infrastructure teams.</p> <p>Leveraging Azure services like <a href="https://azure.microsoft.com/products/kubernetes-service?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a> (AKS) and <a href="https://azure.microsoft.com/products/app-service?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure App Service</a> makes deployment automated and scalable, ensuring consistent performance across environments.</p> <p>Additionally, Azure’s AI-specific tools—including <a href="https://azure.microsoft.com/products/machine-learning/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Machine Learning</a>, <a href="https://azure.microsoft.com/products/virtual-machines/data-science-virtual-machines/?ocid=buildia24_60days_blogs#overview" target="_blank" rel="noopener noreferrer">Data Science Virtual Machines</a> (DSVMs), and <a href="https://azure.microsoft.com/products/ai-services/ai-language/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI Language</a>—make developing and deploying robust Intelligent Apps straightforward.</p> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="the-maintenance-phase">The Maintenance Phase<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/the-role-of-platform-engineering-in-developing-intelligent-apps#the-maintenance-phase" class="hash-link" aria-label="Direct link to The Maintenance Phase" title="Direct link to The Maintenance Phase"></a></h5> <p>During the maintenance phase, the benefits of platform engineering shine even brighter. Traditional methods often struggle with managing ongoing updates and addressing user feedback promptly. Moreover, post-deployment maintenance using traditional methodology requires dedicated resources for ongoing support and updates.</p> <p>Platform engineering selects, deploys, and configures infrastructure monitoring tools that provide visibility into the underlying infrastructure components’ health and performance. By letting you access these metrics directly, platform engineering arms you with the information you need to make informed decisions for maintenance and optimization.</p> <p>Platform engineering enables teams to iterate rapidly based on real-time insights, leveraging Azure’s analytics and monitoring tools to gather actionable data. For instance, <a href="https://learn.microsoft.com/azure/azure-monitor/overview?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Monitor</a> and <a href="https://learn.microsoft.com/azure/azure-monitor/app/app-insights-overview?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Application Insights</a> enable proactive monitoring and efficient troubleshooting, minimizing downtime and optimizing performance. Additionally, Azure DevOps facilitates iterative improvements through feature flags and A/B testing, so teams can gather feedback and iterate quickly.</p> <p>Furthermore, Azure’s AI-powered tools—including <a href="https://azure.microsoft.com/products/ai-services/ai-anomaly-detector/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">AI Anomaly Detector</a> and <a href="https://azure.microsoft.com/products/ai-services/ai-metrics-advisor/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure AI Metrics Advisor</a>—support analytics and anomaly detection, allowing teams to address issues before they impact users.</p> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="the-benefits-of-platform-engineering">The Benefits of Platform Engineering<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/the-role-of-platform-engineering-in-developing-intelligent-apps#the-benefits-of-platform-engineering" class="hash-link" aria-label="Direct link to The Benefits of Platform Engineering" title="Direct link to The Benefits of Platform Engineering"></a></h4> <p>Let’s review some of the benefits of using platform engineering over traditional development methods for your Intelligent Apps:</p> <ul> <li><strong>Reduced time to market</strong>—Platform engineering accelerates software development through reusable infrastructure components, automation tools, and standardized workflows. This contrasts with traditional methods, which prolong development cycles due to manual processes and lack of automation.</li> <li><strong>Improved app quality</strong>—Platform engineering ensures consistency, repeatability, and reliability with standardized configurations, security policies, and automated testing. With traditional approaches, quality may suffer due to manual testing, ad-hoc configurations, and inconsistent environments.</li> <li><strong>Scalability and resilience</strong>—Intelligent Apps designed with platform engineering in mind have resilient infrastructure that supports seamless scalability thanks to automated scaling and fault-tolerant architecture. Traditional, manual development methods can’t compete.</li> <li><strong>Enhanced ability to iterate based on user feedback</strong>—Traditional methods face the constraints of manual processes and lengthy deployment cycles. Comparatively, platform engineering facilitates rapid iteration and experimentation with flexible platform infrastructure.</li> <li><strong>Operational efficiency</strong>—Platform engineering improves efficiency through automation, standardized processes, and centralized management. This contrasts with traditional methods, where operational tasks are more manual, leading to inefficiencies and increased costs.</li> </ul> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Complete the <strong><a href="https://aka.ms/intelligent-apps/apps-csc?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps Skills Challenge</a></strong> to compete for the leaderboard and earn a Microsoft Learn Badge.</p></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/the-role-of-platform-engineering-in-developing-intelligent-apps#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h3> <p>Azure services and platform engineering have revolutionized the landscape of Intelligent Apps development, offering organizations unprecedented scalability, flexibility, and efficiency. And with Azure’s robust suite of tools, you can deliver intelligent solutions that drive growth and enhance customer experiences.</p> <p>As we look to the future, the potential of Intelligent Apps to provide substantial business value only continues to grow, promising even greater insights, automation, and competitive advantages. To learn more about the transformative power of Azure, join us at <a href="https://build.microsoft.com/en-US/home?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Microsoft Build</a>.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[6.1 Creating a Virtual Stylist Chatbot — Part 1: Analyzing Images with AI]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-1</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-1</guid> <pubDate>Tue, 26 Mar 2024 09:00:00 GMT</pubDate> <description><![CDATA[In this three-part series, you’ll build a virtual stylist chatbot that uses AI to analyze images and suggest clothing items. In this first part, you’ll analyze clothing images using AI to generate a text description of the piece, focusing on the clothing’s characteristics. ]]></description> <content:encoded><![CDATA[ <p><img loading="lazy" alt="virtual stylist chatbot that uses AI to analyze images and suggest clothing items" src="https://azure.github.io/Cloud-Native/assets/images/6-1-1-87f23e69dcf5f8154c19cca178c55920.jpeg" width="624" height="380" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="creating-a-virtual-stylist-chatbot--part-1-analyzing-images-with-ai">Creating a Virtual Stylist Chatbot — Part 1: Analyzing Images with AI<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-1#creating-a-virtual-stylist-chatbot--part-1-analyzing-images-with-ai" class="hash-link" aria-label="Direct link to Creating a Virtual Stylist Chatbot — Part 1: Analyzing Images with AI" title="Direct link to Creating a Virtual Stylist Chatbot — Part 1: Analyzing Images with AI"></a></h2> <p>Ever wished you had a personal fashion consultant who could help you find the ideal outfit for any occasion? What if you could use artificial intelligence (AI) to create a virtual stylist chatbot that could analyze clothing in images and suggest the perfect match from a database of clothing options.</p> <p>This assistant is an example of an intelligent app—an application that leverages AI to enhance and personalize its user experience.</p> <p>In this three-part series, you’ll learn how to build your own AI stylist app. When you’re done, you’ll have an app that can understand the contents of user-uploaded images and recommends similar items from a fashion image dataset.</p> <p>The first article of this series demonstrates how to create the app’s core logic. It analyzes the clothing styles in the image and finds the closest match in the dataset using Azure AI Search, Azure OpenAI Service, and Azure Functions. In the later parts of the series, you’ll add a chatbot interface to the app.</p> <p>Let’s get started!</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-1#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites"></a></h3> <p>Before you start, ensure you have:</p> <ul> <li>Python 3.10 or later</li> <li>An Azure subscription with access to <a href="https://azure.microsoft.com/products/ai-services/openai-service?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure OpenAI Service</a></li> <li><a href="https://learn.microsoft.com/cli/azure/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure command-line interface (CLI)</a> installed</li> <li><a href="https://github.com/Azure/azure-functions-core-tools" target="_blank" rel="noopener noreferrer">Azure Functions Core Tools</a> installed</li> <li>An Azure OpenAI Service resource with a GPT-4 Vision model deployed. Read the <a href="https://learn.microsoft.com/azure/ai-services/openai/how-to/create-resource?pivots=web-portal&ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">resource deployment guide</a> if you haven’t yet deployed a model. Note that <a href="https://learn.microsoft.com/azure/ai-services/openai/concepts/models?ocid=buildia24_60days_blogs#model-summary-table-and-region-availability" target="_blank" rel="noopener noreferrer">GPT-4 Vision</a> is only available in the Sweden Central and West US regions, so be sure to select either of those two.</li> <li>The deployment name, endpoint, and API key for your OpenAI Service. See the “Retrieve key and endpoint” section in the <a href="https://learn.microsoft.com/azure/ai-services/openai/dall-e-quickstart?pivots=programming-language-python?ocid=buildia24_60days_blogs#retrieve-key-and-endpoint" target="_blank" rel="noopener noreferrer">Azure OpenAI Service docs</a> for details on finding your model’s endpoint URL and API key.</li> <li>The <a href="https://www.kaggle.com/datasets/paramaggarwal/fashion-product-images-small" target="_blank" rel="noopener noreferrer">Fashion Product Images dataset</a> from Kaggle. Download and unzip the dataset. You’ll only need the CSV file in part 1, but keep all the images because you’ll use them later in the series.</li> <li>Familiarity with Python</li> <li><a href="https://flask.palletsprojects.com/en/3.0.x/installation/" target="_blank" rel="noopener noreferrer">Flask installed</a></li> <li><a href="https://code.visualstudio.com/Download" target="_blank" rel="noopener noreferrer">Visual Studio Code</a> or another code editor of your choice</li> </ul> <p>For a preview, refer to the complete code for <a href="https://github.com/rogerwinter/Microsoft-Creating-a-Virtual-Stylist-Chatbot/tree/main/stylist-backend" target="_blank" rel="noopener noreferrer">part 1 available on GitHub</a>.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="analyzing-clothing-styles-with-ai">Analyzing Clothing Styles with AI<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-1#analyzing-clothing-styles-with-ai" class="hash-link" aria-label="Direct link to Analyzing Clothing Styles with AI" title="Direct link to Analyzing Clothing Styles with AI"></a></h3> <p>With the prerequisites in place, it’s time to create an app from scratch. It will use Azure AI Search, Azure Functions (in Python), and Azure OpenAI Service to do the following:</p> <ul> <li>Accept an image uploaded from a web interface. It should be an image of a clothing item or a person wearing one or more pieces of clothing.</li> <li>Analyze that image using Azure OpenAI GPT-4 Turbo with Vision to generate a text description of the piece. Focus on describing the characteristics of the clothing.</li> <li>Use the text description of the clothing’s characteristics to find its closest matches in the clothing dataset.</li> <li>Return a suggestion from the dataset of which clothing items are the best matches.</li> </ul> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Complete the <strong><a href="https://aka.ms/intelligent-apps/apps-csc?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps Skills Challenge</a></strong> to compete for the leaderboard and earn a Microsoft Learn Badge.</p></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="create-the-search-index-and-upload-the-dataset">Create the Search Index and Upload the Dataset<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-1#create-the-search-index-and-upload-the-dataset" class="hash-link" aria-label="Direct link to Create the Search Index and Upload the Dataset" title="Direct link to Create the Search Index and Upload the Dataset"></a></h4> <p>First, you must create a search index and upload the dataset that contains the clothing options. You’ll use Azure AI Search, which can automatically ingest and parse the CSV data supplied with the fashion image dataset.</p> <p>Begin by uploading the CSV data included in the <a href="https://www.kaggle.com/datasets/paramaggarwal/fashion-product-images-small" target="_blank" rel="noopener noreferrer">fashion dataset</a> into Azure Blob Storage. Navigate to the Storage Accounts page to get started. To find it quickly, enter its name in the Azure Portal’s search bar:</p> <p><img loading="lazy" alt="image of storage accounts search in Azure" src="https://azure.github.io/Cloud-Native/assets/images/6-1-2-beab8e8713c79aeb77ead57a11b8a897.png" width="624" height="197" class="img_ev3q"></p> <p>When the page loads, choose an existing storage account if you already have one. If not, create a new one. Click the storage account’s name to load its dashboard page. Then, click <strong>Upload</strong> to upload a new file:</p> <p><img loading="lazy" alt="image of upload storage accounts search in Azure" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCACaAWMDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9U6KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiikoAWiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKSgCFXVl69Kfu968H+O/jXxf4a17Tbfw81wtpJbvJL5Fn53zbuP4TXmn/C2vib08++x/wBg5P8A4iuqNCUo8x8ni+IqWErSoSpS93yPsHcM9T+VIWVV69a+P/8AhbXxO6effY/7Byf/ABFemfAfxt4v8Ua5qVvr7TvawwI8f2iz8n5t3P8ACKcsPKMecWE4io4utGhGlLXyPXtUvvs8j/PXO32uPH/G/wD33V3xJI6XU2PSvPdYunjd65D606KfxM//AD2f/vuqsnip/wDns/8A33XBz301VZLqagD0KPxU/wDz2f8A77q1H4qf/ns//fdeZ/apqnjvpqAPSZPEz/8APZ/++6oz+Jpv+ez/APfdcV9qmqCSeagDto/E03/PzN/33V2DxNN/z2f/AL7rzyOSap455qAPRo/Ez/8APZ/++6tQeI3k/wCWz/8AfdeXyalNHT7XVn30AeyWOq+Z/HXS2UnnQ15R4f1J5NlemaDJvtX/AN+gDUoornPHE2r2/hHV5NAeyTWltna0fVCRbB/+mhH8NAFPxV8QvD/gi80eHXdUh02TVrn7FaeeCFebGcbui9vvf7NdfXyr4b162+KVnYNZ6rF4w8TeI4bnTZJ9csUS10OzVUe5T7Gr/O77o+/77KPv8tBX0J4A8Kv4H8H6ZoUuq3mtyWcPk/b9QbM03uaAOmooryv40ap4y8O+HV8QeHL+xhtNPD3GqWt1YmeWW2Ayxg+dPnQfwvw/TKUAd9pHiGw103n2C7iujZ3L2dzsb/VTJ99D7itavlnw1pWteFfFFt4d+Hni+xvJtakm1bXLrULNJ0iukeNb1/km3i5czJ+56JX1DGrLGoZt7f3qAJaKKwprjVP7aWOO3gfTfszubhpcS+fvGxNmz7m3f83/AOugDdormNNuvEEzaP8AbLCxgWa2ZtRWC8d/s82E2pF+7+deX+b5Ogrp6ACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA86+JPi6LwhcQ39ysk1tbRGZ4Y/4+a4P/hpvw7u/5Adxj/rmlbfx28I+IvFtv9m8OGW3nks3iS+h/wCWL76+f/8AhnX4y/8AQ26h/wB8f/Z10QcftHzmY/XueP1ZaHtH/DTnhz/oBXH/AHwldx8NvFUXiu4ub+3R4IbmITJDJ/BzXy//AMM6/GX/AKG7UP8Avn/7OvoD4F+D/EPhW1EHiMy3NxHaJC97MeZn30T5fsk5f9e5/wDaNvQ7/W7XzJpq4bWNH3769TurHz65W1n0rxI10unaxY372zbZY4LhH8p/9vZXOfSnmsmh+Y1Pj8Of7Feof8Ia+7/XRflVmPwoyfxr+VAHlv8AwjX/AEzoj8M/7Ferf8Iz/trR/wAIz/trQB5h/wAI7R/wjH+xXqf/AAjv+2tH/CO/7a0AeWf8Ix/sU/8A4RyvUP8AhHf9taRvDv8AtrQB4/deH/8AYrPj0p43r2C+8JeYu7zoo0/6aVR/4V7N5m/zovyoA5jw/avHsr07w9H5dm4/26ybHwfNaf8ALaP8jXRWNr9lh2UAWa5Hxl4Qs/HVpbafqUt02m+f5lzYxuUju1H/ACym67o/VP4v93NddRQBzkPgvQ7XxVJ4li0q1j16S0WxbUFixK0Ibd5Z9s810dFFABXJeOvBOm/Ebw3d+H9XEz6dd7BPDDKYmlVH3bCw+ba23sema62igDz2H4M+E9P8VaN4g07SotI1LSYXtoDp48hGhZNvlOg+V+35V6FRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRSZFAFHUo4Z9PuUnDeU0TK+z7+3HNfP8AdW8t14dhsrS41S68OaLfabNDqtrpstncpCk+x4XTy/32xPn3olfR9FAHi1lqmuSeLreNr/WW1X+1XSfT2tn/ALPTTfn2Pv2bPubH379+/wCSud1rVPFek+BdJaO+1x9Zu7CbUftTRu/+lKibLbyUT6/I+xOtfRdFAHhWseKNYj8SRvPqOtWd+2u2FrDZQ2/+gyWLyQ5ffs2fPvf+Pf8AwVf+F+p+KNS8STnXLu4jkjil+3afLHMVV/M/d7P3CInyf3HffXe3XgfTbzW49VnN5PcwsJooZLuZrZJRn51h37N3X866mgDw/VPEfij/AIWRcJpSah+7e5tv7Oukd4H2WzvDJv2bER3RP499MGqXh0vS5/7c8UGwllxrtzJaSR3Vs/k/IiJ5PyJv+/sHHy+te50UAeH3Wsa4uuyLBf66uox3Fmmj2jW7/ZruzPk+Y8/yff8A9dv37HSorzxb4jEMFjE2rHVLP+2Ptf8AobhPlSZ7b59mx/8Alns2V7rRQB8/+KdL1tdFubO/1TxBqFokGj6pNcQq4njlF0ftOzYn9xN+z+DZXu1nt+yxbGZ12fKz/eq1RQAUUUUAFFFFABRRRQAUUUUAFFFJQAtFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFI3SgCDb3JyfpSn5erZHpivnHxVb+JviJ8ftZ8LWnjbWPCum6XpFrexLo+weZJJI4bfvQ+1aWqfA/XdGsZLzUPjj4us7deWmuJrZEX8466vq0Eo809fmeX9bnLm5Ke3oe/8A40c+teA6f8Cde1SzjuLL44eLLq1kGUlgltpFb6MI6wfD3wt8T69408WeHz8WvGUH9gvar53mwfvfOh3/ANyj6vS/5+fmX7ev/wA+/wAUfTmT6/pRk+v6V4b/AMM7+J/+i0eMvztv/jdH/DO/if8A6LR4y/O2/wDjdL6vR/5+fmH1iv8A8+vxR7lk+v6UZPr+leG/8M7+J/8AotHjL87b/wCN0f8ADO/if/otHjL87b/43R9Xo/8APz8w+sV/+fX4o9yyfX9KMn1/SvDf+Gd/E/8A0Wjxl+dt/wDG6P8AhnfxP/0Wjxl+dt/8bo+r0f8An5+YfWK//Pr8Ue5ZPr+lGT6/pXhv/DO/if8A6LR4y/O2/wDjdH/DO/if/otHjL87b/43R9Xo/wDPz8w+sV/+fX4o9yyfX9KMn1/SvDf+Gd/E/wD0Wjxl+dt/8bo/4Z38T/8ARaPGX523/wAbo+r0f+fn5h9Yr/8APr8Ue5ZPr+lGT6/pXhv/AAzv4n/6LR4y/O2/+N0f8M7+J/8AotHjL87b/wCN0fV6P/Pz8w+sV/8An1+KPcsn1/SjJ9f0rw3/AIZ38T/9Fo8Zfnbf/G6P+Gd/E/8A0Wjxl+dt/wDG6Pq9H/n5+YfWK/8Az6/FHuWT6/pRk+v6V4b/AMM7+J/+i0eMvztv/jdH/DO/if8A6LR4y/O2/wDjdH1ej/z8/MPrFf8A59fij3LJ9f0oyfX9K8N/4Z38T/8ARaPGX523/wAbo/4Z38T/APRaPGX523/xuj6vR/5+fmH1iv8A8+vxR7lk+v6UZ968N/4Z38T/APRaPGX523/xuj/hnfxP/wBFn8Zfnbf/ABuj6vR/5+fmH1iv/wA+vxR7gGGckimrhlODXhrfs9eKFU4+M3jLI7Brf/43Vr9m3W9a1DSvF+l61q1xrcuieIrrSoL282+c8SbCN+P96pdGPJJwlcccVL2kadSPLc9wopF6UtYHoBRRRQAUUUxztWgB9FZ39rL/AM8zR/ay/wDPM0AaNFZ39rL/AM8zR/ay/wDPM0AaNFZ39rL/AM8zR/ay/wDPM0AaNFZ39rL/AM8zR/ay/wDPM0AaNFZ39rL/AM8zUlrffam2bNlAF2iiigAooooA8H8M7R+13416D/imtP8Az86Suh8bavYw+P8ARVuoJ9TgtbWaWSC3tnuPsjsU8u4dUGcfJIn4nH8decan8QvDvwx/ar8UX/irV7fRLK88O2MVtNeNsSV1mk3hfzroPDf7QXwW8LQXEVl450xpLiRrm5uJpmeWR2/jZ69atSqOUZQi37q/I+fo1ocs4Tko+8/zO3+H9uTrfiLUYLKbTdJvmh+zwTRGLzZlV/Om8rHy7/k5/i2ZryHWNJf/AIXb8UNZvreXWfDemx6bJe6bb37W01vsti5uU2Om/wCT+B/+efyV6D/w1f8ACPt480sf9tG/wrziD4k/A+8+InijxLrfizwzq51WSze0W4USPD5MWzuv9+uOVCvJ/wANnoU8Th4x5faI9Hi+JXiLWPF7Weh6M99otndwWc0n2fIZHSN3m87zvk2I/wBzY5eqEnxk1iOTWZLdIb+xOiXur6fcGxe2VvK2bBl5P3yPv++ESq8/x6+A11rkOsy+JfDsmrxfcvmQeYP+B7ap2vxp/Z8sWuWt9d8MQPdo8c3lwgb0k++v3Put+tL6viP+fb+40+t4f+dfedzZ654pv/EQ0M3mkR3Fraw393M1s7+asrybEhXf/B5f+sP/AHxWF4P8Qa9o82mJM9idC1TxHqVgkZjf7Sn766dH379n/LPZs2Vn6t8fvgRr11Z3OpeJ/Dt/PZnNvJOm94vp8vFWP+GjvgnG0C/8JfoQ+z3L3sXz/cnffvccff8Anf8A77o+r4j/AJ9v7hfWsN/OvvPb+f8AIpef8ivIf+Gr/hL/AND7pH/fbf4Uf8NX/CX/AKH3SP8Avtv8Kn6riP8An2/uH9aw/wDz8X3nr3P+RRz/AJFeQ/8ADV/wl/6H3SP++2/wo/4av+Ev/Q+6R/323+FH1XEf8+39wfWsP/z8X3nr3P8AkUc/5FeQ/wDDV/wl/wCh90j/AL7b/Cj/AIav+Ev/AEPukf8Afbf4UfVcR/z7f3B9aw//AD8X3nr3P+RRz/kV5D/w1f8ACX/ofdI/77b/AAo/4av+Ev8A0Pukf99t/hR9VxH/AD7f3B9aw/8Az8X3nr3P+RRz/kV5D/w1f8Jf+h90j/vtv8KP+Gr/AIS/9D7pH/fbf4UfVcR/z7f3B9aw/wDz8X3nr3P+RRz/AJFeQ/8ADV/wl/6H3SP++2/wo/4av+Ev/Q+6R/323+FH1XEf8+39wfWsP/z8X3nr3P8AkUc/5FeQ/wDDV/wl/wCh90j/AL7b/Cj/AIav+Ev/AEPukf8Afbf4UfVcR/z7f3B9aw//AD8X3nr3P+RRz/kV5D/w1f8ACX/ofdI/77b/AAo/4au+Ev8A0Pukf99t/hR9VxH/AD7f3B9bw/8Az8X3nrTZ2tgcY4rxP9mP/j6+Kf8A2Od//wCyVe/4aw+E2Cv/AAnWkcdP3p5/SsT9lHULfXLT4i6nYSrdaZfeLby6tLqM5SZHSP50reFKpTo1OeNtjhlWp1cTT5Hfc+gK8g8T+KtYt9a1GCS6k0yGEpGnlJuEdk/+uv8A/bdHwmz/AJZfffeK9fqFoUkZHZVLr0rhPaK1js+xw+XN9pi2LsmZ9+//AGt3er9RRxpDGqouxF6KKloAKZJ91qfTJPutQBz9czrPxAs9F1Kazm03Xp5If+Wljo9zcw/99omyumryr4tab4k1aa0Eer3Hh3SYtUsIbV9Mm/0m5d5k3vIf7if3P4/461pQjKVpGOIlKMOaJ6NoWuReINPF5BbX1ou/Z5d9ZvbTf98P89X6yPDLaxJpezXUh/tGF3heW1f5J0/gm2fwb/7lZvxU1a80P4Y+L9S0+ZrTULPSrqa2nj++jpC7o9ZS+M2h8B1NFee+MvF2oeH9Y8FOkrSWtzZ391eWv/Pz5Nl5yf8Aj9ct4u+LGuXHgbU2m0VvDd1qnhi51rSLy11Dzp02Ijuj/Imx085H/j71BZ7XRXmerfFa90karfxaB9r8NaTeJp+paq1/sm3/ACI7wQ7PnRHdP40/j2VU1T4+WGh+LrzSL+G0ext4byb7Vp959onT7ND5zpMmzYnyI/8AG9AHq9XNL/4+v+AV5N4X8U+JtV+J2m2+taZ/YljNoE94lrDf/aUf9/Ds3/ImyZEf/b+/9+vWdL/4+v8AgFAjXoooqySD7XF/z1j/AO+xR9qi/wCesf8A32K5LmjmgDavtL0nVGRry3s7p0+756I+386q/wDCM+HP+gVpf/gPF/hWfzRzVc9Qx9nS6mh/wjPhv/oF6Z/34i/wpP8AhG/Df/QM0z/wHiqhzRzU+1mP2MP5S/8A8I14d/6Bmmf9+IqP+Eb8O/8AQM0z/vxFVDmjmr9pPuHsKfYv/wDCN+Hf+gZpn/fiKj/hG/Dv/QM0z/vxFVDmjmj2k+4ewpl//hG/Dv8A0DNM/wC/EVH/AAjfh3/oGaZ/34iqhzRzR7SfcPq9PsX/APhG/Dv/AEDNM/78RUf8I34d/wCgZpn/AH4iqhzRzR7SfcPq9PsX/wDhG/Dv/QM0z/vxFR/wjfh3/oGaZ/34iqhzRzR7SfcPq9PsX/8AhG/Dv/QM0z/vxFR/wjfh3/oGaZ/34iqhzRzR7SfcPq9PsX/+Eb8O/wDQM0z/AL8RUf8ACN+Hf+gZpn/fiKqHNHNHtJ9w+r0+xf8A+Eb8O/8AQM0z/vxFR/wjPh3/AKBel/8AgPFVDmjmj2k+4fV6fYv/APCM+HP+gZpn/gPFR/wjPhz/AKBmmf8AgPFVDmjmj2k+4exh/KX/APhGfDn/AEDNM/8AAeKj/hGfDn/QM0z/AMB4qoc0c0e0n3D2MP5TR/4Rnw7/ANArS/8AwHirRtY7GwhSK08i3hX7scO1U/IVzvNHNRzze5p7OEDrftcX/PWP/vsULdQv8qyof+BVyXNWtL/4/oKBnT0+sm81i0sbq1tZ7q3gnuW2QxO+x5P9ytCGgCamSfdan1FN8sL/AO7QBg1h+MtDufEFjp0VqU322pWd4/mP/BDPvetL+2LD/n5Sk/tiz/5+UojLllzBKPNHlLdR3VpDqVnNbXcKXFrco8M0EifI6P8AfSoP7Ys/+flKP7Ys/wDn5SpKOKsfg3o+gaffjTpNQu719Om0+wOrajNeJZo6bPJh3/cT7n/fFVPDfwN0LTPDK6dqCXl/PPpCaNN519NMltDsTfDbbz+5R2Qfklegf2xZ/wDPylH9sWf/AD8pSGc1efCvw/fa4+pSpffvpkurqxS/mSyuZk2bJpofuO/yJ/3wlU7f4K+Fk1L7ZLbXt6iPeyQ2N1fTPaw/aUdLlEh+4iPvf/vuux/tiz/5+Uo/tiz/AOflKAOc8K/C7RfB+qpqVk+p3F7DZ/2fDPqN9Nc7Lbej+Sm/+D5K7rTf+Pg/7lZH9sWf/PylWdP1uwW43NeJ9yrA6Wisz/hItN/5/IqKCDnuaOaOaOags4Dx/pOs32rQyWPjOPw1apD/AMe8z7Ed65j/AIRvxKyuqfFi1L/wKswd2/Wuj+KPwvvPiM9r9n159FS2/wCeEKPv/wC+643Tf2bdS02/tbn/AITa4n8l9/lyWcOx/wDxyuqNT3D5TE4CdXEc8I+76s9utY3SzgR38x9ib5P79cX4j8SeIb7xoPCvhf8As20uobBNTv8AUdVgeZIUd3SFEhR03u+x/wCP5NldvBH5cKJ/cTZXI+KPAt5quvQ+IND15/DWupbfYppxZpeQ3MO/eiTQv/cf7j7/AON65T6eOxn+D/ic97rdz4Z8SW8WneJbO5mtnltd/wBiuNkKTb0d/ub4Zt+x/wC49RSfHrwlAljM7332W5hhupp/s3yWcM3+peb+5v8A+B/JTNW+CdtrHhW60241u+k1e81L+07zX9iedNNs8l02fcRHh3w7P4EpNY+COlaj42HiG1bTIUlS1hubW+0S2vPkh+RPJd/nh+T5P46DQ1YPixol34g/sdLbU9/9qvov26Sz/wBF+2Jv/c7/APgH/oFVZfi1oi6ldXkuqvb6JZ2FzM6SWf33huvs29H/AI/n+RE2fPVrUvhlDqXhLxDoialcWk+palNq0OpRp89hdPN5yOn+46Vma/8AA/SNZ0kacbiaK0XRE0aONIkfZsmSaOb5/vvvT7j/AH6AL+j/ABi8PaxeJZ4vrC93zRzQX0Ox4fJh875/n/jh+dP9x60vCPxG0TxwmnPpT3Dpf6b/AGsnnw7NkO/Z8/8Acfej/J/sPXLz/A+2vvCSaPcX9paT/b0vftWh6PDp+9E+R4dif30d03/7ddJ4N+H9t4N1jxJf29y8/wDbF59pSCRNiWaf88U/2N7zP/wOgDrOaOaOaOaADmjmjmjmgA5o5o5o5oAOaOaOaOaADmjmjmjmgA5o5o5o5oAOaOaOaOaADmjmjmjmgA5q1pf/AB/QVV5q1pf/AB/QUAeG/FH4M/ETxv45m1u3udNjgtnzpu24dHhRfufwffr6C8Nf2l/Ydj/bf2f+1/JX7T9l/wBXv/2a4fxd+0F4Q8F+ITot/eTSXUf/AB8taw70t/8Afr0LTr2HU7OG7tJkntZkV4pI/uslWQaFFFFABRXPeKvFVl4T01bq7Ek8sr+Vb2sCb5riU/dRF7tWT4Z8YXerXjaRrFmuj+IIR5rWqy+aksGfvwv/AB44R/7j/VC4B29FfN/x68Xa3afGDwxoMGteMNN0e50W8vJrfwXYJdXTTJPAiO++F9ibXeulb47S2XjbxN4ZGgyyyeH7SSYRz3YTU9T2QebvtbUR/vkf7m9H+/8AwUAe10V85SftZW0Pg/QdUfTNNfUNbu5ra0trfV3mghMcHnOLmVYC8LryhTynO/FSv+1Nfahp9rdaN4DvL928Oy+Ipre8vVs5IEhneGaM70+/lHKf3x12UAfRFFfLmrfHTxDrWsePTHp23wLa+B7fxHbXFjqX2bUE86Gd0dH2HY77Nn+x5e/599dVq37RNv4Z8VeFfD1xplvdWuqXFhp/nR6wJr2Ga4TMbvDs+5/tu6P/ABbKAPeaK+YPB3x21Hw34V8KWGqx/wBqXOtarrMJ1jW9R+xWyeTqc0KQedsf99sxsT5f9X9+vpygB9FFFAHMf2Hef3E/77o/sO8/uJ/33XT0UAcx/Yd5/cT/AL7o/sO8/uJ/33XT0UAcx/Yd5/cT/vuj+w7z+4n/AH3XT0UAcx/Yd5/cT/vuj+w7z+4n/fddPRQBzH9h3n9xP++6P7DvP7if99109FAHMf2Hef3E/wC+6P7DvP7if99109FAHMf2Hef3E/77o/sO8/uJ/wB9109FAHMf2Hef3E/77o/sO8/uJ/33XT0UAcx/Yd5/cT/vuj+w7z+4n/fddPRQBzH9h3n9xP8Avuj+w7z+4n/fddPRQBzH9h3n9xP++6P7DvP7if8AfddPRQBzH9h3n9xP++6P7DvP7if99109FAHMf2Hef3E/77o/sO8/uJ/33XT0UAcx/Yd5/cT/AL7o/sO8/uJ/33XT0UAcx/Yd5/cT/vurNjpdzBdI7ouxP9ut6mSUAfnd8SP+SjeKP+wrdf8Aob19ofAf/kjvhP8A680/9Cr4v+JH/JRvFH/YVuv/AEN6+0PgH/yR/wAJ/wDXn/7OaAPRKKKKAMi50GxutYg1SW3V9QgiaGKcnlEf7+2naloOn6tNZzXdsk81lL51vIfvRP6rWrRQB5z4++DOjfELxBp2uXeoa3pOrWNtJZxXWiarNZyGF3R3Rth+Yb40pk3wX0K88TJrtzea1e38MLxWbzanM62O+HyZHhG/5HdM/PXpNFAHk3/DPPhBdPMCnVU1L7d/af8AwkC6rN/an2ryfJ3/AGnfv/1P7vZ9zZ2rck+E2iTTTXV099d3cuiv4fmuLq8eV3tHbe+5m6v/ALVd7RQB5TdfAHwjMwHk31vD/wAI9/wi00UN/KqXNhsdESZc/O6b32P9/wCc80lx+z14Qm8RLrDQ6gkyX9nqgt11GYWv2y2RI4ZvJ37N+xETp/AK9XooA8pvv2e/CWraHBoNwdU/sGKeeabSk1KZLa786f7Q/nJv+cb2PWvU6fRQAUUUUAf/2Q==" width="355" height="154" class="img_ev3q"></p> <p>Next, select the <code>styles.csv</code> file from the fashion dataset downloaded from Kaggle.</p> <p><img loading="lazy" alt="image of file upload" src="https://azure.github.io/Cloud-Native/assets/images/6-1-4-e2a1e9aa7f205c2fe07e942deaeacd24.png" width="473" height="404" class="img_ev3q"></p> <p>If you have an existing storage container you’d like to use, select it from the dropdown menu. Otherwise, click the link to create a new one. Either way, ensure the container is empty before proceeding. The <code>styles.csv</code> file you upload should be the only file in the container.</p> <p>Now, you’re ready to create the AI Search service. Look it up using the Azure Portal search box:</p> <p><img loading="lazy" alt="image of searching for AI Search service in Azure Portal" src="https://azure.github.io/Cloud-Native/assets/images/6-1-5-1bd293d9503890e015798cc07192e1e0.png" width="413" height="147" class="img_ev3q"></p> <p>When the AI Search page loads, click <strong>+ Create</strong> to create a new AI Search instance.</p> <p><img loading="lazy" alt="image of create in AI services" src="https://azure.github.io/Cloud-Native/assets/images/6-1-6-0d59728e1b107130191dbde7ecaabaf3.png" width="587" height="108" class="img_ev3q"></p> <p>Select the subscription and resource group you’d like to use to create the search service. Then, enter a unique name of your choice — this demonstration uses “stylist-search-service.”</p> <p><img loading="lazy" alt="image of fields for creating a new search service in AI services" src="https://azure.github.io/Cloud-Native/assets/images/6-1-7-7286c9c6111f665a70fe5a9771369e79.png" width="623" height="395" class="img_ev3q"></p> <p>Use the defaults for all remaining settings and click <strong>Create</strong> to create the search service. This may take a few minutes. The Azure Portal will let you know when the service is ready.</p> <p>Now, it’s time to index the data in the <code>styles.csv</code> file you uploaded to Blob Storage earlier. From the main page of your new search index, click <strong>Import data</strong>.</p> <p><img loading="lazy" alt="image of import data option for indexing data" src="https://azure.github.io/Cloud-Native/assets/images/6-1-8-f9296498e9857d0b8b89e896d829f308.jpeg" width="624" height="108" class="img_ev3q"></p> <p>In the first data import screen, select <strong>Azure Blob Storage</strong> as the data source and enter “fashion-images” as the data source name. Choose <strong>Delimited text</strong> as the parsing mode, and enter a comma as the delimiter character. For the connection string, click <strong>Choose an existing connection</strong> and select the storage container where you uploaded <code>styles.csv</code>. Delete the forward slash in the Blob folder input box. Azure will auto-populate the connection string.</p> <p><img loading="lazy" alt="image of fields for importing data" src="https://azure.github.io/Cloud-Native/assets/images/6-1-9-4c1e5077197bd985a83fc2bcab7ef88e.png" width="405" height="352" class="img_ev3q"></p> <p>Click <strong>Next</strong> until Azure prompts you to customize the target index, and then update the field settings as follows:</p> <p><img loading="lazy" alt="image of field settings for importing data" src="https://azure.github.io/Cloud-Native/assets/images/6-1-10-73760999649050df4ac630e6c11b7456.png" width="625" height="293" class="img_ev3q"></p> <p>Click <strong>Next</strong>. On the final screen, enter a name for the indexer and click <strong>Submit</strong>.</p> <p><img loading="lazy" alt="image of final screen when importing data" src="https://azure.github.io/Cloud-Native/assets/images/6-1-11-daead3a7e13f0eff2a340565e78a1434.png" width="413" height="399" class="img_ev3q"></p> <p>Azure will create a search index and then run the ingester to import the data. It should finish in under two minutes. When it does, you’re done with search index creation.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Register for the new learning series on <strong><a href="https://aka.ms/serverless-learn-live?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps with Serverless on Azure</a></strong>. Join the community along with MVPs, and the Azure Product Group on how to leverage AI with Serverless on Azure technologies –Azure Functions and Azure Container Apps – to build intelligent applications.</p></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="create-the-azure-function">Create the Azure Function<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-1#create-the-azure-function" class="hash-link" aria-label="Direct link to Create the Azure Function" title="Direct link to Create the Azure Function"></a></h4> <p>The next step is to create the Azure Function that will perform image analysis, matching logic, and recommendation generation. You’ll use Python as the programming language and Flask as the web framework.</p> <p>To create and deploy the Azure Functions app, use the Azure Functions CLI. Open a terminal and create a new directory to store your app. Then, run:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">func init --python</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>The app generator will run. Open the directory in Visual Studio Code or your text editor of choice. You should see several files:</p> <p><img loading="lazy" alt="the directory in Visual Studio Code" src="https://azure.github.io/Cloud-Native/assets/images/6-1-12-0126ca1f4856fce21305ab3cd0c05ba2.png" width="271" height="200" class="img_ev3q"></p> <p>Open <code>requirements.txt</code> and add the following:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">azure-functions</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">requests</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">azure-search-documents</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>This change ensures Azure will install all the dependencies the function needs before trying to run it.</p> <p>Next, open <code>function_app.py</code> and replace its contents with the following:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">import base64</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import os</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import requests</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import azure.functions as func</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">from azure.search.documents import SearchClient</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">from azure.core.credentials import AzureKeyCredential</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">app = func.FunctionApp()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Get the environment variables</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">OPENAI_API_KEY = os.environ['OPENAI_API_KEY']</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">OPENAI_ENDPOINT = os.environ['OPENAI_ENDPOINT']</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">OPENAI_DEPLOYMENT_NAME = os.environ['OPENAI_DEPLOYMENT_NAME']</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">SEARCH_API_KEY = os.environ['SEARCH_API_KEY']</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">SEARCH_ENDPOINT = os.environ['SEARCH_ENDPOINT']</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">SEARCH_INDEX_NAME = os.environ['SEARCH_INDEX_NAME']</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Initialize the Azure OpenAI headers</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">openai_headers = {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> 'Authorization': 'Bearer {}'.format(OPENAI_API_KEY),</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> 'Content-Type': 'application/json'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Initialize the Azure Search client</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">search_credentials = AzureKeyCredential(SEARCH_API_KEY)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">search_client = SearchClient(SEARCH_ENDPOINT, SEARCH_INDEX_NAME, search_credentials)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">@app.route(route="stylist", methods=["post"], auth_level=func.AuthLevel.FUNCTION)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">def stylist(req: func.HttpRequest) -> func.HttpResponse:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # get image from request and convert to a base64 string</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> image = req.files["image"]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> image_bytes = image.read()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> image_base64 = base64.b64encode(image_bytes).decode("utf-8")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Generate a text description from the image using Azure OpenAI</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> base_url = f"{OPENAI_ENDPOINT}openai/deployments/{OPENAI_DEPLOYMENT_NAME}"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> endpoint = f"{base_url}/chat/completions?api-version=2023-12-01-preview"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> data = {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "messages": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> { "role": "system", "content": "You are a helpful assistant." },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> { "role": "user", "content": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "type": "text",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "text": "Describe the main fashion item in this picture. Make sure you include the type of item (e.g., Shirt, T-Shirt, Shorts, Pants, Dress, Purse, Clutch), the color of the item, and 'Men' or 'Women' if the fashion item appears to be specific to either of those genders."</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "type": "image_url",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "image_url": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "url": image_base64</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> ] }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> ],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "max_tokens": 2000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> response = requests.post(endpoint, headers=openai_headers, data=json.dumps(data))</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> result = response.json()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> image_description = result['text']</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Find the closest match from the search index using Azure OpenAI</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> search_result = search_client.search(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> search_text=image_description,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> select=["id", "productDisplayName"],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> top=1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> )</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> match_id = search_result["id"]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> match_name = search_result["productDisplayName"]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Generate a natural language recommendation based on the match result using Azure OpenAI</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> data = {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "messages": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> { "role": "system", "content": "You are a helpful assistant." },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> { "role": "user", "content": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "type": "text",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "text": f"Please generate a natural language recommendation based on the matching item: {match_id}, {match_name}. For example: The best match for your clothing item is: Peter England Men Party Blue Jeans. This is a pair of jeans for men in blue color, suitable for casual occasions. You can pair it with a shirt or a t-shirt of your choice."</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> ] }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> ],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "max_tokens": 2000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> response = requests.post(endpoint, headers=openai_headers, data=json.dumps(data))</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> result = response.json()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> recommendation = result['text']</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> # Return the recommendation as a JSON response</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return func.HttpResponse(json.dumps({</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> 'image_id': match_id,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> 'recommendation': recommendation</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> })) </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Let’s break down what’s happening step by step.</p> <p>First, you set up the function app and Azure clients. This code:</p> <ul> <li>Initializes an Azure Function with an HTTP trigger</li> <li>Retrieves necessary API keys and endpoints from environment variables for OpenAI and Azure Search services</li> <li>Sets up headers for interacting with Azure OpenAI Service and a client for using Azure Search</li> </ul> <p>Then, you define the <code>process_image</code> function. This function:</p> <ul> <li>Is the application’s code and executes on a specific request to the Flask app</li> <li>Receives an image as part of the request</li> </ul> <p>Next, you generate text descriptions with Azure OpenAI. This code:</p> <ul> <li>Constructs a request to Azure OpenAI Service’s chat API to generate a description of the main fashion item in the image. The request includes the image and a prompt to describe the fashion item, including its type, color, and gender specificity.</li> <li>Sends the request and extracts the generated description from the response</li> </ul> <p>After, you search for a matching product. This code:</p> <ul> <li>Uses the Azure Search client to search for a product that matches the description generated by OpenAI. The search query uses the textual description and selects specific fields (<code>id</code>, <code>productDisplayName</code>) from the search index.</li> <li>Extracts the ID and display name of the closest matching product from the search results</li> </ul> <p>Then, you generate a natural language recommendation. This code:</p> <ul> <li>Constructs another request to Azure OpenAI Service’s chat API to generate a natural language recommendation based on the matching product. The request includes the matching product’s details and asks for a natural language recommendation.</li> <li>Sends the request and extracts the recommendation from the response</li> </ul> <p>Next, the code returns the recommendation:</p> <ul> <li>The function ends by returning a JSON response containing the matching product’s ID and the natural language recommendation.</li> <li>The ID matches the file name of an image in the dataset, so you can use it to load and display images in the web UI in parts 2 and 3 of this series.</li> </ul> <p>Finally, you define a main function:</p> <ul> <li>This is the function Azure runs to boot the function app and prepare it to receive HTTP requests.</li> </ul> <p>This app combines image processing, text generation, and search capabilities to provide fashion item recommendations. It demonstrates how to implement the entire back end of an intelligent application.</p> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="deploy-the-azure-function">Deploy the Azure Function<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-1#deploy-the-azure-function" class="hash-link" aria-label="Direct link to Deploy the Azure Function" title="Direct link to Deploy the Azure Function"></a></h4> <p>The final step is to deploy the Azure Function to the cloud so the web interface can access it. Start by using the Azure CLI to create a new function app:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az functionapp create --resource-group <RESOURCE_GROUP_NAME> --consumption-plan-location westus --runtime python --runtime-version 3.9 --functions-version 4 --name <APP_NAME> --os-type linux --storage-account <STORAGE_NAME> </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>You can use the same resource group and storage account you used for the search service.</p> <p><strong>Note</strong>: The app name must be unique, so you might need to try a few options to find one available.</p> <p>Next, set all the environment variables the app will need by running:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az functionapp config appsettings set –name <APP_NAME> --resource-group <RESOURCE_GROUP> --settings</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">OPENAI_API_KEY=<your Azure OpenAI key></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">OPENAI_ENDPOINT=<your Azure OpenAI endpoint></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">OPENAI_DEPLOYMENT_NAME=<your Azure OpenAI deployment name></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">SEARCH_API_KEY=<your Search API key></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">SEARCH_ENDPOINT=<your Search service endpoint></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">SEARCH_INDEX_NAME=<your Search index name></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>If you’re unsure where to find any of these values, here’s how to locate them:</p> <ul> <li> <p>For the OpenAI values, find and load the Azure OpenAI page by entering OpenAI in the Azure Portal search bar. Click the name of your Azure OpenAI service, and you’ll see two menu options:</p> <p><img loading="lazy" alt="the directory in Visual Studio Code" src="https://azure.github.io/Cloud-Native/assets/images/6-1-13-f3a608e39936d86857dedb477579fe45.png" width="249" height="98" class="img_ev3q"></p> <p>Click <strong>Keys and Endpoint</strong> to locate the required information, or click <strong>Model deployments</strong> to navigate to Azure OpenAI Studio and find the names of your model deployments.</p> </li> <li> <p>For the search service, load your stylist search service’s page in Azure Portal:</p> <ul> <li>On the <strong>Overview</strong> page, the <strong>Url</strong> value is your search endpoint.</li> <li>Click <strong>Keys</strong> in the menu to access your search service’s keys.</li> <li>Click <strong>Indexes</strong> in the menu to see the name of your search service’s index.</li> </ul> </li> </ul> <p>Note that you’re saving these as app settings for simplicity. In a product app, you should keep secrets like API keys safe by using <a href="https://azure.microsoft.com/products/key-vault?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Key Vault</a>.</p> <p>Once you’ve created the app and saved its settings, you can deploy your function by running the following command from the Azure Functions CLI:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">func azure functionapp publish <APP_NAME></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>The CLI will begin deploying your app. When the deployment is complete, the interface will provide a URL to send HTTPS requests to the function app.</p> <p>Now, the back end of the stylist chatbot app is complete! You’re ready to move on to creating the web interface for the app.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Join the Azure Functions product group for an <strong><a href="https://aka.ms/intelligent-apps/ate-functions?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Ask The Expert</a></strong> session on how to focus on the pieces of code that matter most to you in AI application development, while Azure Functions handles the rest for you.</p></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps">Next Steps<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-1#next-steps" class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps"></a></h3> <p>In this article, you learned how to create a virtual stylist chatbot that can analyze clothing styles in an image and identify the best match from a dataset of clothing options — leveraging Azure Functions and Azure OpenAI Service to do so. You also learned how to use Azure AI Search feature to index, store, and retrieve entries from a search index. Next, you discovered how to use Azure OpenAI Service to generate natural language descriptions and recommendations based on the user’s input image.</p> <p>In the next part of this series, you’ll learn how to add a chatbot interface to the app using React and an <a href="https://azure.microsoft.com/products/app-service/static?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Static Web App</a>.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[6.2 Creating a Virtual Stylist Chatbot — Part 2: Adding a Chatbot Interface]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2</guid> <pubDate>Wed, 27 Mar 2024 09:00:00 GMT</pubDate> <description><![CDATA[In this four-part series, you’ll build a virtual stylist chatbot that uses AI to analyze images and suggest clothing items. In this second installment, you’ll design the chatbot’s interface.]]></description> <content:encoded><![CDATA[ <p><img loading="lazy" alt="Graphical representation of a chatbot. The human user&#39;s chat bubble contains a t-shirt with a question mark, while the bot&#39;s chat bubble contains three dots to indicate it is responding." src="https://azure.github.io/Cloud-Native/assets/images/6-2-1-dbbcc07a99683e80eea81967dd44fd7e.jpeg" width="624" height="380" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="creating-a-virtual-stylist-chatbot--part-2-adding-a-chatbot-interface">Creating a Virtual Stylist Chatbot — Part 2: Adding a Chatbot Interface<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2#creating-a-virtual-stylist-chatbot--part-2-adding-a-chatbot-interface" class="hash-link" aria-label="Direct link to Creating a Virtual Stylist Chatbot — Part 2: Adding a Chatbot Interface" title="Direct link to Creating a Virtual Stylist Chatbot — Part 2: Adding a Chatbot Interface"></a></h2> <p>Welcome to part 2 of this tutorial series on creating a virtual stylist chatbot using Azure OpenAI Service. </p> <p>In <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-1" target="_blank" rel="noopener noreferrer">part 1</a>, you built the chatbot app’s back end using Azure Functions, Azure AI Services, and GPT-4 Vision with Azure OpenAI Service. That tutorial covered using these services to analyze an image of a fashion item or outfit and generate natural language responses and recommendations based on it.</p> <p>In this second installment, you’ll create a chatbot interface for your virtual stylist app using Vite, Vue, TypeScript, and vue-advanced-chat. You’ll learn how to use these tools to build a web application that allows you to interact with your stylist bot conversationally.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites"></a></h3> <p>Before you begin, ensure you have:</p> <ul> <li>An Azure subscription with access to <a href="https://azure.microsoft.com/products/ai-services/openai-service?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure OpenAI Service</a></li> <li><a href="https://learn.microsoft.com/cli/azure/?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure command-line interface (CLI)</a> installed</li> <li><a href="https://github.com/Azure/azure-functions-core-tools" target="_blank" rel="noopener noreferrer">Azure Functions Core Tools</a> installed</li> <li>An Azure OpenAI Service resource with a GPT-4 Vision model deployed</li> <li>The deployment name, endpoint, and API key for your OpenAI Service</li> <li>The <a href="https://www.kaggle.com/datasets/paramaggarwal/fashion-product-images-small" target="_blank" rel="noopener noreferrer">Fashion Product Images dataset</a> from Kaggle</li> <li><a href="https://nodejs.org/en/download/" target="_blank" rel="noopener noreferrer">Node.js 20</a> or later installed on your local machine</li> <li>A text editor that supports Vue and TypeScript. If you use Visual Studio Code, consider installing the <a href="https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin" target="_blank" rel="noopener noreferrer">TypeScript Vue Plugin</a> to ensure the editor understands all the files you’re about to create.</li> </ul> <p>For a preview of this tutorial, check out the <a href="https://github.com/rogerwinter/Microsoft-Creating-a-Virtual-Stylist-Chatbot/tree/main/stylist-backend" target="_blank" rel="noopener noreferrer">project code available on GitHub</a>.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="creating-a-chatbot-interface-for-your-virtual-stylist">Creating a Chatbot Interface for Your Virtual Stylist<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2#creating-a-chatbot-interface-for-your-virtual-stylist" class="hash-link" aria-label="Direct link to Creating a Chatbot Interface for Your Virtual Stylist" title="Direct link to Creating a Chatbot Interface for Your Virtual Stylist"></a></h3> <p>In this section, you’ll create a chatbot interface for the virtual stylist app using Vue and vue-advanced-chat. You’ll use Vue to create the main components of the app, including the header, the footer, the chat window, and the image upload button. You’ll also use the vue-advanced-chat library to create the chat messages, chat input, and other chat options, using Tailwind CSS to style the app.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Complete the <strong><a href="https://aka.ms/intelligent-apps/apps-csc?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Intelligent Apps Skills Challenge</a></strong> to compete for the leaderboard and earn a Microsoft Learn Badge.</p></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="setting-up-the-project">Setting Up the Project<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2#setting-up-the-project" class="hash-link" aria-label="Direct link to Setting Up the Project" title="Direct link to Setting Up the Project"></a></h4> <p>The first step is creating a new Vue project using Vite. Vite is a fast and lightweight build tool that provides a smooth developer experience and supports features like hot module replacement, code splitting, and tree shaking.</p> <p>To create a new Vue project with Vite, run the following command in your terminal:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">npm init vite@latest virtual-stylist-chat -- --template vue-ts</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>This builds a new folder, <code>virtual-stylist-chat</code>, with the following structure:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">virtual-stylist-chat</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── index.html</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── public</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ └── favicon.svg</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── src</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── App.vue</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── assets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ │ └── logo.svg</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── components</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ │ └── HelloWorld.vue</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── main.ts</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ └── shims-vue.d.ts</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└── tsconfig.json</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Next, add a few dependencies:</p> <ul> <li><a href="https://github.com/advanced-chat/vue-advanced-chat" target="_blank" rel="noopener noreferrer">vue-advanced-chat</a>, a feature-rich and highly customizable Vue chat component library that provides many out-of-the-box features for chat interfaces. These include images, videos, files, voice messages, emojis, link previews, typing indicators, reactions, markdown text formatting, online presence indicators, delivery and read receipts, theming and customization options, and responsive design.</li> <li><a href="https://tailwindcss.com/" target="_blank" rel="noopener noreferrer">Tailwind CSS</a>, <a href="https://postcss.org/" target="_blank" rel="noopener noreferrer">PostCSS</a>, and <a href="https://www.npmjs.com/package/autoprefixer" target="_blank" rel="noopener noreferrer">autoprefixer</a> to simplify styling the app</li> <li><a href="https://www.npmjs.com/package/uuid" target="_blank" rel="noopener noreferrer">uuid</a> to generate unique IDs for each message</li> </ul> <p>To install the required packages, run the following command:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">npm install --save vue-advanced-chat tailwindcss@latest postcss@latest autoprefixer@latest uuid @types/uuid </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>This command adds vue-advanced-chat, Tailwind, and PostCSS as dependencies in the <code>package.json</code> file.</p> <p>Now that you’ve set up the project and installed the dependencies, check that it builds as expected by running <code>npm run dev</code>. The app should build and provide an address to view it in a web browser. Load it, and you should see the default welcome screen:</p> <p><img loading="lazy" alt="the Vite + Vue welcome page displays both logos and provides links to create-vue and Volar." src="https://azure.github.io/Cloud-Native/assets/images/6-2-2-7f17286af2d2ed6164e8f8d9cb4eaf1e.png" width="431" height="322" class="img_ev3q"></p> <p>Next, generate the <code>tailwind.config.js</code> and <code>postcss.config.js</code> files using the following command:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">npx tailwindcss init -p</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Edit the <code>tailwind.config.js</code> file and add the paths to your template files in the <code>content</code> property:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">// tailwind.config.js</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export default {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> content: ["./index.html", "./src/**/*. {vue,js,ts,jsx,tsx}"],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> theme: {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> extend: {},</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> plugins: [],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">};</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Then, replace the content of <code>style.css</code> file in the <code>src</code> folder with the following code to import Tailwind CSS using the <code>@tailwind</code> directives:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">@tailwind base;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">@tailwind components;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">@tailwind utilities;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Then, import the <code>styles.css</code> file in the <code>main.ts</code> file and remove the unused import:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">import { createApp } from "vue";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import App from "./App.vue";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import "./styles.css"; // import Tailwind CSS</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">createApp(App).mount("#app");</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Finally, copy the images from the <a href="https://www.kaggle.com/datasets/paramaggarwal/fashion-product-images-small" target="_blank" rel="noopener noreferrer">dataset</a> you downloaded in the first part of this series. Using your preferred CLI or file manager, create a new folder called <code>Images</code> inside the project’s <code>public</code> folder, and then copy all the images from the dataset’s <code>images_compressed</code> folder to the <code>Images</code> folder. The stylist bot will use these images to make recommendations based on the image IDs it returns.</p> <p>The result should look like this:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">virtual-stylist-chat</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── index.html</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── public</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── favicon.svg</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ └── images</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── 10001.jpg</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── 10002.jpg</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── 10003.jpg</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── ...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── 19998.jpg</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── 19999.jpg</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ └── 20000.jpg</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── src</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── App.vue</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── assets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ │ └── logo.svg</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── components</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ │ └── HelloWorld.vue</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── main.ts</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── styles.css</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── tailwind.config.js</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── postcss.config.js</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ └── shims-vue.d.ts</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└── tsconfig.json</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>Now, it’s time to start coding the chatbot interface.</p> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="coding-the-chatbot-interface">Coding the Chatbot Interface<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2#coding-the-chatbot-interface" class="hash-link" aria-label="Direct link to Coding the Chatbot Interface" title="Direct link to Coding the Chatbot Interface"></a></h4> <p>In this section, you’ll prepare your virtual stylist app’s chatbot interface. You’ll use Vue to create the main components, including the header, the footer, the chat window, and the image upload button. Then, you’ll use the vue-advanced-chat component to create the chat messages, input, and options.</p> <p>To keep things simple, we’ll link to the code of non-essential components like the header and footer. Since these aren’t critical to how the app functions, feel free to copy and paste them into your codebase.</p> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="header-and-footer">Header and Footer<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2#header-and-footer" class="hash-link" aria-label="Direct link to Header and Footer" title="Direct link to Header and Footer"></a></h5> <p>Start by creating two files in the <code>src/components</code> folder: <code>Header.vue</code> and <code>Footer.vue</code>. Next, copy the code from the <a href="https://github.com/contentlab-io/Microsoft-Creating-a-Virtual-Stylist-Chatbot/blob/main/stylist_frontend/src/components/Header.vue" target="_blank" rel="noopener noreferrer">header</a> and <a href="https://github.com/contentlab-io/Microsoft-Creating-a-Virtual-Stylist-Chatbot/blob/main/stylist_frontend/src/components/Footer.vue" target="_blank" rel="noopener noreferrer">footer</a> files in the GitHub repository into the files you just created.</p> <p>These files are simple Vue components that use HTML and CSS to create a stylish header and footer for the app. If you’d like to customize them, replace the logo image link in the header with a link to an image of your own.</p> <p>Now, it’s time to dive into the chat interface that makes this app work.</p> <h5 class="anchor anchorWithStickyNavbar_LWe7" id="creating-the-chat-window-component">Creating the Chat Window Component<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2#creating-the-chat-window-component" class="hash-link" aria-label="Direct link to Creating the Chat Window Component" title="Direct link to Creating the Chat Window Component"></a></h5> <p>The chat window component displays the messages between the user and the stylist bot. To start, create a new file called <code>ChatWindow.vue</code> inside the project’s src/components folder. Then, add the following code to it:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"><template></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <div class="chat-window h-screen"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <vue-advanced-chat</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> .messages="messages"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> .options="options"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> .rooms="[{ roomId: 'main', roomName: 'Stylist Chat', avatar: '/images/logo.svg', users: [currentUser]}]"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> :rooms-list-opened="false"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> :rooms-loaded="true"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> :messages-loaded="true"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> :current-user-id="currentUser._id"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> accepted-files=".png, .jpg, .jpeg"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> show-audio="false"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> @send-message="onInputSubmit"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> .message-actions="[{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> label: 'Send',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> action: (message: Message) => {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> console.log('Send message ' + message.content);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }]"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> v-bind="{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> 'current-user-id': currentUser?._id || '',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> 'room-info-enabled': false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> /></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </div></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></template></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"><script lang="ts"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import { defineComponent, ref, Ref } from "vue";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import { VueAdvancedChat, Message, register, RoomUser } from "vue-advanced-chat";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">register();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import { v4 as uuidv4 } from "uuid";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">function toTimeString(date: Date): string {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> let month = date.toLocaleString('default', { month: 'short' });</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return `${date.getFullYear()}-${month}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}`;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export default defineComponent({</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> name: "ChatWindow",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> components: {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> VueAdvancedChat,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> setup() {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Define the current user, the messages, and the options for the chat component</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const currentUser: Ref<RoomUser> = ref({</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> _id: "user",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> username: "User",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> avatar: "",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> status: { state: "online", lastChanged: new Date().toDateString()},</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> });</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const messages: Ref<Array<Message>> = ref([]);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const options = ref({</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableVoiceMessages: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableReactions: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableSeenBy: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableLinkPreview: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableUploads: true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableAttachments: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableReply: true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableEdit: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableDelete: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableGroup: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableSearch: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableOptions: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableScrollToBottom: true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableScrollToTop: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableLoadMore: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableComposer: true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableInput: true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableSendButton: true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableEmojis: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableRecording: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableMarkdown: true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableTypingIndicator: true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableOnlinePresence: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableCustomTheme: true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> enableRooms: false,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> customTheme: {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> primaryColor: "#333333",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> secondaryColor: "#f0f0f0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> tertiaryColor: "#ffffff",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> quaternaryColor: "#e0e0e0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> quinaryColor: "#999999",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> senaryColor: "#666666",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> septenaryColor: "#333333",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> octonaryColor: "#f0f0f0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> nonaryColor: "#ffffff",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> denaryColor: "#e0e0e0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> });</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Update the image preview in the chat message after it's uploaded</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const updateMessageImage = (newMessage: Message, url: string) => {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const existingMessage = messages.value.find(m => m._id === newMessage._id);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Update the URL of the first message file</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const message = existingMessage || newMessage;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> if(message && message.files && message.files.length > 0) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> message.files[0].url = url;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const existingMessages = messages.value.filter(m => m._id !== message._id);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> //set a new message ID to prevent file from being overwritten</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> message._id = uuidv4();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> messages.value = [...existingMessages, message];</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const onInputSubmit = async (event: CustomEvent) => {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Create a new message object with the content and the current user</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> console.log("called!")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> let content = event.detail[0].content;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> let files = event.detail[0].files;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const newMessage: Message = {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // generate uuid</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> _id: uuidv4(),</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> content,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> senderId: currentUser.value._id,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> date: new Date().toLocaleString('default', { year: 'numeric', month: 'short', day: 'numeric' }),</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> timestamp: toTimeString(new Date()),</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> };</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> if(files) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> newMessage.files = [...files.map((file: any) => {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> var messageFile = {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> name: file.name,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> size: file.size,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> type: file.type,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> url: file.url || file.localUrl, </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> extension: file.extension,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> preview: file.localUrl,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const reader = new FileReader();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> reader.readAsDataURL(file.blob);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> reader.onload = () => { </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Get the base64-encoded string from the reader result </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> messageFile.url = reader.result as string;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // reload messages so UI updates</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> messages.value = [...messages.value];</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> updateMessageImage(newMessage, messageFile.url!);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> callBackendFunction(content, reader.result as string);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> };</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return messageFile;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> })];</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> } else {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Push the new message to the messages array</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> messages.value = [...messages.value, newMessage];</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Call the backend function to get the response from the stylist bot</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> callBackendFunction(content, "");</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> };</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const callBackendFunction = async (prompt: string, image: string) => {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Get the previous prompts and responses from the messages array</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const context = messages.value</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> .filter((message) => message.content || message.replyMessage)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> .map((message) => ({</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> prompt: message.content,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> response: message.replyMessage,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }));</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Create a JSON object with the prompt, the image, and the context</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const data = {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> prompt,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> image,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> context,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> };</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Send a POST request to the backend function URL with the data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const response = await fetch("<backend function URL>", {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> method: 'POST',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> headers: {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> 'Content-Type': 'application/json',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> body: JSON.stringify(data),</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> });</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Get the response data from the fetch response</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const responseData = await response.json();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Create a new message object with the response data and the stylist bot</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const newMessage: Message = {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> _id: uuidv4(),</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> content: responseData.response,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> files: responseData.images,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> senderId: "stylist-bot",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> date: new Date().toLocaleString('default', { year: 'numeric', month: 'short', day: 'numeric' }),</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> timestamp: toTimeString(new Date()),</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> };</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Push the new message to the messages array</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> messages.value = [...messages.value, newMessage];</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> };</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Return the current user, the messages, the options, and the event handlers</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> currentUser,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> messages,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> options,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> onInputSubmit,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> };</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> mounted() {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Add a welcome message from the stylist bot when the component is mounted</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> this.messages = [...this.messages, { _id: "stylist-bot", content: "Hello! I'm your virtual stylist chatbot. You can ask me for fashion advice, recommendations, and more. You can also upload images of clothing items and accessories to get personalized suggestions. How can I help you today?", senderId: "stylist-bot", date: new Date().toTimeString()}];</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">});</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></script></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"><style scoped></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">.chat-window {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> @apply h-screen flex-1 overflow-y-auto;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></style> </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>This code defines a chat window component that uses the vue-advanced-chat component to display the messages between the user and the stylist bot. It also defines some data and methods to handle the chat logic, such as the current user, messages, options, input submit event, file upload event, and the back-end function call.</p> <p><code>currentUser</code> and <code>messages</code> are reactive objects that store information about the chat participant and chat history. The <code>currentUser</code> object represents the app user while the <code>messages</code> array contains the Message objects with the following properties:</p> <ul> <li><code>_id</code>—A unique identifier for the message</li> <li><code>content</code>—The text content of the message (optional)</li> <li><code>files</code>—Contains any files attached to the image (optional)</li> <li><code>senderId</code>—The ID of the message sender</li> <li><code>date</code>—The date of the message</li> <li><code>timestamp</code>—The time and date that appear with every message</li> </ul> <p>The <code>options</code> object contains the configuration options for the vue-advanced-chat component. It allows you to enable or disable various features of the chat interface, including:</p> <ul> <li>Voice messages</li> <li>Reactions</li> <li>Seen by</li> <li>Link preview</li> <li>Uploads and attachments</li> <li>Reply and send button</li> <li>Edit and delete</li> <li>Group and search</li> <li>Options</li> <li>Scroll to bottom and scroll to top</li> <li>Load more</li> <li>Composer</li> <li>Input</li> <li>Emojis</li> <li>Recording</li> <li>Markdown</li> <li>Typing indicator</li> <li>Online presence/status</li> <li>Custom theme</li> </ul> <p>You can learn more about the options and their meanings in the <a href="https://github.com/advanced-chat/vue-advanced-chat" target="_blank" rel="noopener noreferrer">documentation</a>.</p> <p>The <code>onInputSubmit</code> method is the event handler for the input submit event. It’s triggered when the user types a text message and presses the <strong>Enter</strong> key or clicks the <strong>Send</strong> button. This method creates a new message object with the text content and the current user, then pushes it to the messages array.</p> <p>If the message contains an attached image file, the function loads it into a base64-encoded string, which is what the back-end Azure function expects to receive. Finally, it calls the back-end function to prompt a response from the stylist bot.</p> <p>The <code>callBackendFunction</code> method calls the back-end Azure function to retrieve the stylist bot’s reply. It takes the prompt and the image as parameters and sends a POST request to the back-end function URL with the data and the options. The data object contains the prompt, image, and context.</p> <p>The context is an array of objects that store the previous prompts and responses from the <code>messages</code> array. The options object contains the headers for the request, such as the content type. The <code>response</code> object contains the response data from the back-end function, including the response, images, and context.</p> <p>Finally, the function creates a new <code>message</code> object with the response data and the stylist bot’s ID, and then adds it to the <code>messages</code> array.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Register for <a href="https://aka.ms/serverless-learn-live/ep2?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Episode 2</a> of the new learning series on <strong>Intelligent Apps with Serverless on Azure</strong>. Join the community along with MVPs, and the Azure Product Group on how to leverage AI with Serverless on Azure technologies—Azure Functions and Azure Container Apps—to build intelligent applications.</p></div></div> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="integrating-components-into-the-app-component">Integrating Components into the App Component<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2#integrating-components-into-the-app-component" class="hash-link" aria-label="Direct link to Integrating Components into the App Component" title="Direct link to Integrating Components into the App Component"></a></h4> <p>In this section, you’ll integrate the components you just created into the <code>src/App.vue</code> file—your main app component. You’ll import the header, footer, chat window, and image upload button components and display them in a simple layout.</p> <p>To start, open the <code>App.vue</code> file in the project’s <code>src</code> folder and replace the existing code with the following:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"><template></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <div class="app"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <Header /></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <div class="main"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <ChatWindow ref="chat" /></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <ImageUploadButton :chat="chat" /></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </div></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> <Footer /></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </div></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></template></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"><script lang="ts"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import { defineComponent, ref } from "vue";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import Header from "./components/Header.vue";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import Footer from "./components/Footer.vue";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">import ChatWindow from "./components/ChatWindow.vue";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export default defineComponent({</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> name: "App",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> components: {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Header,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Footer,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> ChatWindow</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> setup() {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Define a ref for the chat component</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> const chat = ref(ChatWindow);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> // Return the ref</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> return {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> chat,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> };</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">});</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></script></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"><style></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">.app {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> @apply min-h-screen flex flex-col;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">.main {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> @apply flex-1 flex flex-col;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></style></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>This code defines the app component that uses the header, footer, chat window, and image upload button components. It also defines a <a href="https://vuejs.org/guide/essentials/template-refs" target="_blank" rel="noopener noreferrer"><code>ref</code></a> for the chat component and passes it as a prop to the image upload button component. This action allows the image upload button component to access the chat component’s methods, such as <code>onFileUpload</code>.</p> <p>With that, you’re ready to deploy!</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps">Next Steps<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2#next-steps" class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps"></a></h3> <p>Part 2 of this series equipped you with the necessary skills to create a dynamic chatbot interface for your virtual stylist app. By setting up your project, installing dependencies, and coding the chatbot interface, you laid the groundwork for the final deployment and testing phase. Now, you’re ready to see your virtual stylist in action.</p> <p>Jump to the third part of this series, where you’ll deploy and test your Intelligent App.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> <item> <title><![CDATA[6.3 Creating a Virtual Stylist Chatbot — Part 3: Deploying the App]]></title> <link>https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-3</link> <guid>https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-3</guid> <pubDate>Thu, 28 Mar 2024 09:00:00 GMT</pubDate> <description><![CDATA[In this four-part series, you’ll build a virtual stylist chatbot that uses AI to analyze images and suggest clothing items. In the final article of this series, you’ll deploy and test the Intelligent App.]]></description> <content:encoded><![CDATA[ <p><img loading="lazy" alt="A minimalist graphic features a t-shirt, pants, and robot head in a rounded square, connected by broken line to a smartphone that displays a chatbot conversation." src="https://azure.github.io/Cloud-Native/assets/images/6-3-1-ecb4fb3c49a3ea6cc7451e84f880a3fb.jpeg" width="624" height="380" class="img_ev3q"></p> <h2 class="anchor anchorWithStickyNavbar_LWe7" id="creating-a-virtual-stylist-chatbotpart-3-deploying-the-app">Creating a Virtual Stylist Chatbot—Part 3: Deploying the App<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-3#creating-a-virtual-stylist-chatbotpart-3-deploying-the-app" class="hash-link" aria-label="Direct link to Creating a Virtual Stylist Chatbot—Part 3: Deploying the App" title="Direct link to Creating a Virtual Stylist Chatbot—Part 3: Deploying the App"></a></h2> <p>In <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-1" target="_blank" rel="noopener noreferrer">part 1</a> of this series, you used AI to analyze images of clothing and generate a text description of each piece. Then, in <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2" target="_blank" rel="noopener noreferrer">part 2</a>, you designed the chatbot’s interface.</p> <p>In this third and final installment, you’ll deploy the app as an Azure Static Web App using the Azure command-line interface (CLI). The Azure Static Web Apps service provides a hassle-free means of hosting static web apps with serverless APIs. It also features global distribution, custom domains, SSL certificates, authentication, authorization, and GitHub integration.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-3#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites"></a></h3> <p>To follow along, ensure you have:</p> <ul> <li>The complete code from <a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-2" target="_blank" rel="noopener noreferrer">part 2</a></li> <li>The Azure CLI installed and signed in to your Azure account</li> <li>A GitHub account, <a href="https://docs.github.com/en/repositories/creating-and-managing-repositories/quickstart-for-repositories" target="_blank" rel="noopener noreferrer">an empty repository</a> to push the app’s code to, and a <a href="https://docs.github.com/en/enterprise-server@3.9/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token" target="_blank" rel="noopener noreferrer">personal access token</a> granting read and write access to the repository</li> </ul> <p>For a preview of the project, check out the <a href="https://github.com/rogerwinter/Microsoft-Creating-a-Virtual-Stylist-Chatbot/" target="_blank" rel="noopener noreferrer">complete project code available on GitHub</a>.</p> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="pushing-the-app-to-github">Pushing the App to GitHub<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-3#pushing-the-app-to-github" class="hash-link" aria-label="Direct link to Pushing the App to GitHub" title="Direct link to Pushing the App to GitHub"></a></h3> <p>You can set up Azure Static Web Apps to deploy automatically every time you push a new commit to GitHub. Before proceeding, create a GitHub repository for the web app and push all its code to the repo.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Register for <a href="https://aka.ms/serverless-learn-live/ep3?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Episode 3</a> of the new learning series on <strong>Intelligent Apps with Serverless on Azure</strong>. Join the community along with MVPs, and the Azure Product Group on how to leverage AI with Serverless on Azure technologies –Azure Functions and Azure Container Apps – to build intelligent applications.</p></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="creating-an-azure-static-web-resource">Creating an Azure Static Web Resource<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-3#creating-an-azure-static-web-resource" class="hash-link" aria-label="Direct link to Creating an Azure Static Web Resource" title="Direct link to Creating an Azure Static Web Resource"></a></h3> <p>Next, you’ll create an Azure Static Web App resource using the Azure CLI. The Azure Static Web App resource is the container for the app and its settings.</p> <p>To create it, run the following command in your terminal:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az staticwebapp create \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> --name virtual-stylist-chat \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> --resource-group <your resource group> \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> --location westus2 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> --source virtual-stylist-chat \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> --branch main \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> --app-location / \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> --output-location dist \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> --login-with-github</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>This command will create an Azure Static Web App resource with the following parameters:</p> <ul> <li><strong><code>--name</code></strong>—The name of the resource, which must be globally unique</li> <li><strong><code>--resource-group</code></strong>—The name of the resource group to contain the resource</li> <li><strong><code>--location</code></strong> —The location of the resource</li> <li><strong><code>--source</code></strong>—The name of the GitHub repository that contains the app code</li> <li><strong><code>--branch</code></strong>—The name of the GitHub branch that contains the app code</li> <li><strong><code>--app-location</code></strong>—The location of the app code in the repository</li> <li><strong><code>--output-folder</code></strong>—The folder where the app output is generated</li> <li><strong><code>--login-with-github</code></strong>—The GitHub personal access token that grants access to the repository</li> </ul> <p>The command creates a GitHub Actions workflow file in the repository that triggers the app build and deployment whenever a change is pushed to the branch. It also outputs some information about the resource, like this:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{ </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "defaultHostname": "orange-beach-0c471f710.azurestaticapps.net",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/virtual-stylist-chat-rg/providers/Microsoft.Web/staticSites/virtual-stylist-chat",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "location": "West US 2",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "name": "virtual-stylist-chat",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "repositoryUrl": "https://github.com/username/virtual-stylist-chat",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "resourceGroup": "virtual-stylist-chat-rg",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "sku": "Free",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "type": "Microsoft.Web/staticSites",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "userId": "username",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "workflowFileUrl": "https://github.com/username/virtual-stylist-chat/blob/main/.github/workflows/azure-static-web-apps-virtual-stylist-chat.yml"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <p>You’ve now created an Azure Static Web App resource and a GitHub Actions workflow for the app.</p> <p>To link the function app from part 1 as the back end for the Azure Static Web App, you use <a href="https://learn.microsoft.com/cli/azure/staticwebapp/backends?view=azure-cli-latest&ocid=buildia24_60days_blogs#az-staticwebapp-backends-link" target="_blank" rel="noopener noreferrer"><code>az staticwebapp backends link</code></a>. This command links a pre-existing back end with a static web app, also known as “Bring your own API.” You need to provide the function app’s resource ID, the static web app’s resource group, and the back-end region.</p> <p>Link the function app as the back end for the static web app by running the following:</p> <div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az staticwebapp backends link \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> --backend-resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Web/sites/<function-app-name>" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> --name virtual-stylist-chat \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> --resource-group <your-resource-group> \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> --backend-region westus</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="testing-the-app">Testing the App<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-3#testing-the-app" class="hash-link" aria-label="Direct link to Testing the App" title="Direct link to Testing the App"></a></h3> <p>Now, you’ll test the app by uploading some images of clothing items or outfits to see how the stylist bot responds and makes recommendations. You’ll also witness how the app handles different types of inputs, such as images and text messages.</p> <h4 class="anchor anchorWithStickyNavbar_LWe7" id="uploading-an-image-of-a-fashion-item">Uploading an Image of a Fashion Item<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-3#uploading-an-image-of-a-fashion-item" class="hash-link" aria-label="Direct link to Uploading an Image of a Fashion Item" title="Direct link to Uploading an Image of a Fashion Item"></a></h4> <p>To start, you’ll upload an image of a blue denim jacket to see how the bot responds.</p> <p>Click <strong>Upload</strong> at the bottom of the chat window. Then, select the image file from your local machine. Alternatively, you can drag and drop the image file to the chat window.</p> <p>The app will display the image as a chat message and send it to the back-end function. This function will analyze the image and generate a natural language response and recommendations using Azure Functions, Azure AI Services, and GPT-4 Vision using Azure OpenAI Service. It will then display the response and its recommendations as another chat message. Your result will look something like this:</p> <p><img loading="lazy" alt="The Virtual Stylist Chatbot sends a greeting message that invites the user to request fashion advice and recommendations. The user responds with an image of a red t-shirt and a request to find a matching outfit." src="https://azure.github.io/Cloud-Native/assets/images/6-3-2-9dd29de2a21292ba333f40d35262fbbb.png" width="520" height="249" class="img_ev3q"></p> <p>As you can see, the stylist bot correctly identified the fashion item as a red t-shirt and provided some information and tips about it. It also suggested some images of other items to pair with red t-shirts, including blue jeans and a red hat:</p> <p><img loading="lazy" alt="The Virtual Stylist Chatbot returns a message with images of jeans and a red baseball cap" src="https://azure.github.io/Cloud-Native/assets/images/6-3-3-d127989105b0a2cf46bcb8250c83105b.png" width="625" height="383" class="img_ev3q"></p> <p>You can click the images to view them full-size:</p> <p><img loading="lazy" alt="The full-size photo of the jeans includes a partially visible torso and arms." src="https://azure.github.io/Cloud-Native/assets/images/6-3-4-76bcea1668037205234650cabb58336c.png" width="625" height="406" class="img_ev3q"></p> <p>If you don’t like the suggestions or just want to see more, you can reply with additional details or questions, and it will generate new suggestions based on the information you provide.</p> <div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Join the Azure Functions product group for an <strong><a href="https://aka.ms/intelligent-apps/ate-functions?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Ask The Expert</a></strong> session on how to focus on the pieces of code that matter most to you in AI application development, while Azure Functions handles the rest for you at extreme scale.</p></div></div> <h3 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/60DaysOfIA/creating-a-virtual-stylist-chatbot-part-3#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h3> <p>In this tutorial series, you learned how to create a virtual stylist chatbot app using Azure and OpenAI. You built the app’s back end using Azure Functions, Azure AI, and GPT-4 Vision on Azure OpenAI Service. You then learned how to use these services to analyze images and generate natural language responses and recommendations based on the images. Next, you created the chatbot interface for our app using Vite, Vue, TypeScript, Tailwind CSS, and vue-advanced-chat.</p> <p>You learned how to use these tools to build a web application that allows you conversationally interact with your stylist bot. Finally, you deployed the app as an Azure Static Web App using the Azure CLI.</p> <p>Get your hands on the newly released <a href="https://aka.ms/flexconsumption/signup?ocid=buildia24_60days_blogs" target="_blank" rel="noopener noreferrer">Azure Functions Flex Consumption Plan</a> for private networking, instance size selection, concurrency control, and fast and large scale out features on a serverless compute model.</p>]]></content:encoded> <category>Build-Intelligent-Apps</category> <category>60-days-of-IA</category> <category>learn-live</category> <category>hack-together</category> <category>community-buzz</category> <category>ask-the-expert</category> <category>azure-kubernetes-service</category> <category>azure-functions</category> <category>azure-openai</category> <category>azure-container-apps</category> <category>azure-cosmos-db</category> <category>github-copilot</category> <category>github-codespaces</category> <category>github-actions</category> </item> </channel> </rss>