Category Archives: One Page of Code

hello-ai: A Simple Demonstration of Azure OpenAI

I wrote some code demonstrating how to use Azure OpenAI to support the AI mini-workshop we ran for Virtual Boston Azure. I created versions in Python and C#.

This weekend I create a web front-end for it and deployed as an Azure Static Web App with an Azure Function supporting the refactored C# logic to execute the Azure OpenAI service calls.

The new app is running here: https://hello-ai.doingazure.com

You can find the source code here: https://github.com/codingoutloud/hello-ai

Note that while the additional grounding fails to stop all of the hallucinations, it does help with the most obvious one (so we are making progress) but there’s more to be done.

Workshop: AI Mini-Workshop at Boston Azure

The March 28 Virtual Boston Azure was headlined by Pamela Fox from Microsoft. She explained all about the RAG pattern which is commonly used for building effective applications based on Large Language Models (“LLMs”) and Generative AI (“GenAI”). Pamela shared many superb insights, including lots of depth, while answering a ton of interesting follow-up questions. Was a fantastic talk. Boston Azure has a YouTube channel at youtube.com/bostonazure where you can find recordings of many past events. Pamela Fox’s talk is available there as the 48th video to be posted to the channel.

After Pamela’s talk around 15 people stuck around to participate in our first ever “AI mini-workshop” hands-on experience. The remainder of this post is about that mini-workshop.

The AI mini-workshop was a facilitated hands-on coding experience with the following goals:

1. Demystify Azure OpenAI

As background, OpenAI’s ChatGPT burst onto the scene in November 2022. That led to an explosion of people learning about AI and associated technologies such as “LLMs” which is the common shorthand for Large Language Models.

The vast majority of people interact with LLMs via chat interfaces such as available from OpenAI’s public version of ChatGPT or via Copilot on Microsoft Bing search. There’s also a more integrated programming experience surfaced through GitHub Copilot for use with VS Code and several other popular IDEs.

But what about programming your own solution that uses an LLM? Microsoft has done a great job of providing an enterprise-grade version of the OpenAI LLM as a set of services known as Azure OpenAI.

The first goal of this AI mini-workshop was to demystify this programming experience.

This was accomplished by giving the mini-workshop participants a working C# or Python program that fit on a page. And there are only around 10 lines of meaningful code needed to interact with the AI service. This is NOT that complex.

Creating a production-grade application has additional requirements, but at its core, it is straight-forward to interact with Azure OpenAI service programmatically.

The hoped for “Aha!” moment was this:

Aha #1! I can do this! I can programmatically interact with the Azure OpenAI LLM. It isn’t that mysterious after all.

Aha #2! This is possible without much code! In the Python and C# solutions shared there were only around 10 lines of core code.

2. Understand Some AI Concepts

Part of the mini-workshop exercise was to recognize a hallucination and fix it through some additional grounding using a very simple form of RAG.

The hope here is for some “Aha!” moments:

Aha #3! Here’s a concrete, understandable example of a hallucination!

Aha #4! And here’s a concrete, simple example use of RAG pattern to better ground the AI so that it no longer hallucinates about today’s date! But do note that other hallucinations remain…

3. Wield Great Power

The ability to program a LLM to generate unique content is something that essentially NO DEVELOPER COULD DO, EVER, before the super-powerful LLMs that were developed at costs of hundreds of millions of dollars and democratized by the Microsoft Azure OpenAI services (as well as by OpenAI themselves).

The hands-on AI mini-workshop required either (a) a functional Python 3 environment, or (b) a functional C#/.NET environment – everything else was provided, including sufficient access to the Azure OpenAI LLM service to complete the mini-workshop.

But in the end with very little coding you can get to the 5th Aha! moment which is:

Aha #5! I have at my command capabilities that have not been possible in all of the history of computers. The magic of LLMs available via Azure OpenAI gives me superpowers that we are only in the very beginning of understanding the ways this can be put to use.


The source code for the AI mini-working is available here. Note that the API key has subsequently been rolled (invalidated), but the code works pretty well otherwise. ๐Ÿ™‚

My original thinking was to distribute the keys separately (like this). If this was an in-person workshop I would have kept the configuration values separated from the source, but given the added challenge of doing this with an online distributed audience I decided to simplify the mini workshop by included the configuration values directly in the source code. Looking back, I believe it was a good concession for minimizing obstacles to learning. So I’d do it again next time.

Programming Windows Azure Blob Storage in One Page of Code

Microsoft Windows Azure supports several storage approaches: Blobs, Tables, Queues, Drives, and CDN. We even have SQL Azure available to us for full relational power. This post will outline some basic thoughts on programming Blob storage in .NET. And at the end there will be one (long) page of example code (though you will need to supply your Database Access Keys for your Azure Cloud Account). This code is a complete program that will upload a file into Azure Blob Storage and mark it as Publicly Readable, as would be suitable for linking to such resources from a public web site.

Do I Need .NET?

No, .NET is not needed to program against Blob storage. Any programming language or platform can be used, provided it can support calling out via http. Programs speak to the Blob storage service in Azure via a RESTful interface โ€“ yes, good old-fashioned http goodness.

Isnโ€™t REST Awkward to Program Against?

Well, there are a few details to making these REST requests: construct a well-formed request body, set up the http headers, add your hash (in most cases Azure requires this step as proof you have the right key), create a web connection, send your request, handle the response, and repeat. But in .NET it is even easier due to the Azure SDK where you will find some helper classes, such as CloudBlobContainer, CloudBlobClient, and CloudBlob. These helpful helpers help you help yourself to Blob storage services without having to worry about most of the details โ€“ you just deal with some objects.

How Do I Access the Azure SDK, and How Many Thousands of Dollars Does it Cost?

For .NET / Visual Studio developers, download the SDK as part of the Windows Azure Tools for Microsoft Visual Studio. Or, better still, follow these instructions from David Aiken for getting started with Windows Azure.

For non-.NET, non-Visual Studio developers, download the Windows Azure SDK separately.

And even though the Azure SDK makes Azure development super รผber ultra convenient on .NET, it does not cost any money. A freebie. If you are developing on a non-.NET platform, there is very likely an open source client library for you. Microsoft provides a library now for PHP, too.

Can You Give Me a Short Example?

Sure, here is a code snippet showing the two primary classes in action (and bold blue). Under the hood, there are REST calls being made out to the Blob storage services, but you donโ€™t need to deal with this plumbing in your code.

FileInfo = new FileInfo(โ€œc:/temp/foo.pngโ€);
string blobUriPath = fileInfo.Name;

CloudBlobContainer blobContainer = // getting blob container not shown here

CloudBlob blob = blobContainer.GetBlobReference(blobUriPath);
blob.UploadFile(fileInfo.FullName);

blob.Metadata[“SomeArbitraryPropertyName”] = Guid.NewGuid().ToString(); // arbitrary value
blob.SetMetadata();

blob.Properties.ContentType = “image/png”;
blob.SetProperties();

Are these Calls Really REST Under the Hood!!??

They sure are. You can prove this by firing up an http sniffer like Fiddler. You will see http traffic whiz back and forth.

What if Something Goes Wrong?

Here are a couple of errors Iโ€™ve run into:

For other errors or issues, try the Azure Support Forum.

Is it Production Quality Code?

Hmmmโ€ฆ We have a continuous stream of code on a single (long) page, in a single source fileโ€ฆ Is it โ€œProduction Quality Codeโ€ you might wonder? Iโ€™m going to go with โ€œnoโ€ โ€“ this code is not production ready. It is for getting up to speed quickly and learning about Azure Blob Storage.

Can I Tell if My Blobs Get to the Cloud?

You sure can. One way is to use the nifty myAzureStorage.com tool:

Go to http://myAzureStorage.com in your browser:

image

Now you need to know something about how your Azure Storage account was configured in the Cloud. You need to know both the Account Name and one of the Access Key values (Primary or Secondary โ€“ it doesnโ€™t matter which).

In our case we will type in the following:

Account Name = bostonazuretemp

Access Key = Gfd1TqS/60hKj0Ob3xPbtbQfmH/R0DMDKDC8VXWpxdMvhRPH1A+f6FMoIzyP+zDQmoN3GYQzJlLOASKKEvTJkA==

Note: the Access Key above is no longer valid. Use a different real one if you like, or see the One Page of Code snippet below for how to do this using local storage in the Dev Fabric.

You may also want to check โ€œRemember Meโ€ and your screen will look something like this:

image

Now simply click on โ€œLog Inโ€ and you will see your storage. The default tab is for Table storage, so click the BLOBs tab to view your Blob Containers:

image

In my case I see one – โ€œbillwโ€ โ€“ and I can click on it to drill into it and see its blobs:

image

And for each blob, I can click on the blob to examine its attributes and metadata:

image

What Project Template Should I Use in Visual Studio?

Create a Visual C# Console Application on .NET Framework 4 using Visual Studio 2010 or Visual C# Express 2010:

image

Show Me the Code!

Okay, the working code –ย fully functionalย – on One Page of Code – appears below.ย After you create a new Visual C# Console application in Visual Studio 2010, as shown above, simply clobber the contents of the file Program.cs with the code below. That oughta be easy. Then start playing with it.

You will also need to add a reference to Microsoft.WindowsAzure.StorageClient – but first you’ll need to switch away from the .NET Frameworkย Client Profile.

Sharing Files on the Public Web using Azure Blob Storage

Also note that the following code will post to Azure Blob Storage in such a way that the item stored will be accessible from a web browser. This is not the default behaviour; read the code to see the couple of lines that influence this.

Note that this code is intensionally compressed to fit in a short space and all in one place – this is not intended to be production code, but “here is a simple example” code.ย For instance, this code does not use config filesย – but you should. This isย just to help you quickly understand the flow and take all the magic out of getting a code sample to work.

You can also download this code directly:ย SnippetUploaderInOnePageOfCode.cs.

Without further ado, here is your One Page of Code

using System;
using System.Diagnostics;
using System.IO;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace CodeSnippetUploader
{
ย ย ย  class Program
ย ย ย  {
#if false
ย ย ย ย ย ย ย  private const string AccountKey = “Put a real Storage Account Key – find it on http://windows.azure.com dev portal for your Storage Service”;
#else
ย ย ย ย ย ย ย  private const string AccountKey = null;ย ย // use local storage in the Dev Fabric
#endif
ย ย ย ย ย ย ย  private const string AccountName = “bostonazuretemp”;
ย ย ย ย ย ย ย  private const string ContainerName = “snippets”;
ย ย ย ย ย ย ย  private const string MimeTypeName = “text/plain”; // since these are assumed to be code snippets

ย ย ย ย ย ย ย  static void Main(string[] args)
ย ย ย ย ย ย ย  {
ย ย ย ย ย ย ย ย ย ย ย  // pass in the single snippet code file you want uploaded
ย ย ย ย ย ย ย ย ย ย ย  string snippetFilePath = args[0];

ย ย ย ย ย ย ย ย ย ย ย  string baseUri = null;
ย ย ย ย ย ย ย ย ย ย ย  CloudBlobClient blobStorage = null;

ย ย ย ย ย ย ย ย ย ย ย  if (AccountKey == null)
ย ย ย ย ย ย ย ย ย ย ย  {
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  var clientStorageAccount = CloudStorageAccount.DevelopmentStorageAccount; // use storage services in the Developer Fabric, not real cloud
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  baseUri = clientStorageAccount.BlobEndpoint.AbsoluteUri;
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  blobStorage = new CloudBlobClient(baseUri, clientStorageAccount.Credentials);
ย ย ย ย ย ย ย ย ย ย ย  }
ย ย ย ย ย ย ย ย ย ย ย  else
ย ย ย ย ย ย ย ย ย ย ย  {
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  byte[] key = Convert.FromBase64String(AccountKey);
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  var creds = new StorageCredentialsAccountAndKey(AccountName, key);
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  baseUri = string.Format(“http://{0}.blob.core.windows.net“, AccountName);
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  blobStorage = new CloudBlobClient(baseUri, creds);
ย ย ย ย ย ย ย ย ย ย ย  }

ย ย ย ย ย ย ย ย ย ย ย  CloudBlobContainer blobContainer = blobStorage.GetContainerReference(ContainerName);
ย ย ย ย ย ย ย ย ย ย ย  bool didNotExistCreated = blobContainer.CreateIfNotExist();

ย ย ย ย ย ย ย ย ย ย ย  var perms = new BlobContainerPermissions
ย ย ย ย ย ย ย ย ย ย ย  {
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  PublicAccess = BlobContainerPublicAccessType.Container // Blob (see files if you know the name) or Container (enumerate like a directory)
ย ย ย ย ย ย ย ย ย ย ย  };
ย ย ย ย ย ย ย ย ย ย ย  blobContainer.SetPermissions(perms); // This line makes the blob public so it is available from a web browser (no magic needed to read it)

ย ย ย ย ย ย ย ย ย ย ย  var fi = new FileInfo(snippetFilePath);
ย ย ย ย ย ย ย ย ย ย ย  string blobUriPath = fi.Name; // could also use paths, as in: “images/” + fileInfo.Name;
ย ย ย ย ย ย ย ย ย ย ย  CloudBlob blob = blobContainer.GetBlobReference(blobUriPath);
ย ย ย ย ย ย ย ย ย ย ย  blob.UploadFile(fi.FullName); // REST call under the hood; use tool like Fiddler to see generated http traffic (http://fiddler2.com)

ย ย ย ย ย ย ย ย ย ย ย  blob.Properties.ContentType = MimeTypeName; // IMPORTANT: Mime Type here needs to match type of the uploaded file
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  // e.g., *.png <=> image/png, *.wmv <=> video/x-ms-wmv (http://en.wikipedia.org/wiki/Internet_media_type)
ย ย ย ย ย ย ย ย ย ย ย  blob.SetProperties(); // REST call under the hood

ย ย ย ย ย ย ย ย ย ย ย  blob.Metadata[“SourceFileName”] = fi.FullName; // not required – just showing how to store metadata
ย ย ย ย ย ย ย ย ย ย ย  blob.Metadata[“WhenFileUploadedUtc”] = DateTime.UtcNow.ToLongTimeString();
ย ย ย ย ย ย ย ย ย ย ย  blob.SetMetadata(); // REST call under the hood

ย ย ย ย ย ย ย ย ย ย ย  string url = String.Format(“{0}/{1}/{2}”, baseUri, ContainerName, blobUriPath);
ย ย ย ย ย ย ย ย ย ย ย  Process process = System.Diagnostics.Process.Start(url); // see the image you just uploaded (works from Console, WPF, or Forms app – not from ASP.NET app)
ย ย ย ย ย ย ย  }
ย ย ย  }
}