-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added CloudMachine README Walkthrough (#47025)
* Create README.MD * Update README.MD * Update README.MD * Update README.MD * Update README.MD * Update README.MD * Update README.MD * Update README.MD * Update README.MD * Update README.MD * Update README.MD * Update README.MD * Update README.MD
- Loading branch information
1 parent
d036477
commit 8c3550e
Showing
1 changed file
with
278 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,278 @@ | ||
# Azure CloudMachine | ||
|
||
Write Azure apps in 5 minutes | ||
|
||
## Getting started | ||
|
||
### Prerequisites | ||
|
||
> You must have an [Azure subscription](https://azure.microsoft.com/free/dotnet/). | ||
> You must have .NET 8 (or higher) installed | ||
> You must have Azure CLI installed | ||
> You must have Azure Developer CLI installed | ||
> You must have npm installed | ||
> You must be logged into Azure CLI and Azure Developer CLI | ||
### Walkthrough | ||
|
||
#### Create Server Project | ||
|
||
In a command line window type | ||
```dotnetcli | ||
mkdir cmdemo | ||
cd cmdemo | ||
mkdir server | ||
cd server | ||
dotnet new web | ||
``` | ||
|
||
Add `Azure.CloudMachine.All` package | ||
```dotnetcli | ||
dotnet add package Azure.CloudMachine.All --prerelease | ||
``` | ||
#### Use Azure Dev CLI to provision CloudMachine | ||
|
||
Open Program.cs file and add the following two lines of code to the top of the file | ||
```csharp | ||
using Azure.Provisioning.CloudMachine; | ||
|
||
if (CloudMachineInfrastructure.Configure(args)) return; | ||
``` | ||
The `CloudMachineInfrastructure.Configure` call allows running the app with `-bicep` switch, which generate bicep files required to provision resources in Azure. Let's generate these bicep files now. | ||
```dotnetcli | ||
dotnet run -bicep | ||
``` | ||
As you can see, a folder called `infra` was created and it should have several bicep files in it. Let's now initialize the project for azd. | ||
```dotnetcli | ||
azd init | ||
``` | ||
select template, choose 'yes' when asked 'Continue initializing an app here?', choose the 'minimal' template, and use 'cmserver' as the environment name | ||
|
||
Once the initialization completes, let's provision the resources. Select `eastus` as the region | ||
```dotnetcli | ||
azd provision | ||
``` | ||
When provisioning finishes, you should see something like the following in the console output | ||
```dotnetcli | ||
(✓) Done: Resource group: cm125957681369428 (627ms) | ||
``` | ||
And if you go to your Azure portal, or execute the following az cli command to see the resource group created. The resource group will have server resources such us Storage, ServiceBus, and EventGrid. | ||
```dotnetcli | ||
az resource list --resource-group <resource_group_from_command_line> --output table | ||
``` | ||
|
||
#### Use CDK to add resources to the CloudMachine | ||
|
||
Since we are writing an AI application, we need to provision Azure OpenAI resources. To do this, add the follwoing class to the end of the Program.cs file: | ||
```csharp | ||
class AssistantService { | ||
internal static void Configure(CloudMachineInfrastructure cm) { | ||
cm.AddFeature(new OpenAIFeature() { Chat = new AIModel("gpt-4o-mini", "2024-07-18") }); | ||
} | ||
} | ||
``` | ||
And change the infrastructure configuration call att he begining of the file to: | ||
```csharp | ||
if (CloudMachineInfrastructure.Configure(args, AssistantService.Configure)) return; | ||
``` | ||
And now regenerate new bicep with the new Azure OpenAI resources, and re-provision | ||
```dotnetcli | ||
dotnet run -bicep | ||
azd provision | ||
``` | ||
|
||
#### Call CloudMachine APIs | ||
|
||
You are now ready to call Azure OpenAI service from the app. To do this, add `CloudMachineClient` field and a `Chat` method to `AssistantService`: | ||
```csharp | ||
class AssistantService { | ||
CloudMachineClient cm = new CloudMachineClient(); | ||
|
||
public async Task<string> Chat(string message) { | ||
var client = cm.GetOpenAIChatClient(); | ||
ChatCompletion completion = await client.CompleteChatAsync(message); | ||
return completion.Content[0].Text; | ||
} | ||
} | ||
``` | ||
Lastly, create an instance of the service and call the `Chat` method when the app users browses the app: | ||
```csharp | ||
var service = new AssistantService(); | ||
app.MapGet("/", async () => { | ||
return await service.Chat("List all noble gases"); | ||
}); | ||
``` | ||
The full program should look like following: | ||
```csharp | ||
using Azure.CloudMachine; | ||
using Azure.CloudMachine.OpenAI; | ||
using Azure.Provisioning.CloudMachine; | ||
using Azure.Provisioning.CloudMachine.OpenAI; | ||
using OpenAI.Chat; | ||
|
||
if (CloudMachineInfrastructure.Configure(args, AssistantService.Configure)) return; | ||
|
||
var builder = WebApplication.CreateBuilder(args); | ||
var app = builder.Build(); | ||
|
||
var service = new AssistantService(); | ||
app.MapGet("/", async () => { | ||
return await service.Chat("List all noble gases"); | ||
}); | ||
|
||
app.Run(); | ||
|
||
class AssistantService { | ||
CloudMachineClient cm = new CloudMachineClient(); | ||
|
||
public async Task<string> Chat(string message) { | ||
var client = cm.GetOpenAIChatClient(); | ||
ChatCompletion completion = await client.CompleteChatAsync(message); | ||
return completion.Content[0].Text; | ||
} | ||
|
||
internal static void Configure(CloudMachineInfrastructure cm) { | ||
cm.AddFeature(new OpenAIFeature() { | ||
Chat = new AIModel("gpt-4o-mini", "2024-07-18") | ||
}); | ||
} | ||
} | ||
``` | ||
You can now start the application | ||
```dotnetcli | ||
dotnet run | ||
``` | ||
and browse to the URI printed in the console. | ||
|
||
#### Use TDK to expose Web APIs and generate TypeSpec | ||
First, let's define an API we want to expose. We will do it using an interface. Add the following interface to the end of Program.cs: | ||
```csharp | ||
interface IAssistantService { | ||
Task<string> Chat(string message); | ||
} | ||
``` | ||
Make sure that the `AssistantService` implements the interface: | ||
```csharp | ||
class AssistantService : IAssistantService | ||
``` | ||
Expose the service methods as web APIs by adding the following line after the existing 'var service = new AssistantService();' line: | ||
```csharp | ||
app.Map(service); | ||
``` | ||
Lastly, add the ability to generate TypeSpec for the new API by adding new statement to the `Configure` method | ||
```csharp | ||
cm.AddEndpoints<IAssistantService>(); | ||
``` | ||
Your program shoud now look like following: | ||
```csharp | ||
using Azure.CloudMachine; | ||
using Azure.CloudMachine.OpenAI; | ||
using Azure.Provisioning.CloudMachine; | ||
using Azure.Provisioning.CloudMachine.OpenAI; | ||
using OpenAI.Chat; | ||
using System.ClientModel.TypeSpec; | ||
|
||
if (CloudMachineInfrastructure.Configure(args, AssistantService.Configure)) return; | ||
|
||
var builder = WebApplication.CreateBuilder(args); | ||
var app = builder.Build(); | ||
|
||
var service = new AssistantService(); | ||
app.Map(service); | ||
app.MapGet("/", async () => { | ||
return await service.Chat("List all noble gasses"); | ||
}); | ||
|
||
app.Run(); | ||
|
||
class AssistantService : IAssistantService { | ||
CloudMachineClient cm = new CloudMachineClient(); | ||
|
||
public async Task<string> Chat(string message) { | ||
var client = cm.GetOpenAIChatClient(); | ||
ChatCompletion completion = await client.CompleteChatAsync(message); | ||
return completion.Content[0].Text; | ||
} | ||
|
||
internal static void Configure(CloudMachineInfrastructure cm) { | ||
cm.AddFeature(new OpenAIFeature() { | ||
Chat = new AIModel("gpt-4o-mini", "2024-07-18") | ||
}); | ||
cm.AddEndpoints<IAssistantService>(); | ||
} | ||
} | ||
|
||
interface IAssistantService { | ||
Task<string> Chat(string message); | ||
} | ||
``` | ||
You can now start the application and browse to the /chat endpoint [TDB] | ||
|
||
But what's more interesting, you can run the app with the -tsp switch to generate TypeSpec for the endpoint: | ||
```dotnetcli | ||
dotnet run -tsp | ||
``` | ||
This will create a `tsp` directory, AssistantService.tsp file, with the following contents: | ||
```tsp | ||
import "@typespec/http"; | ||
import "@typespec/rest"; | ||
import "@azure-tools/typespec-client-generator-core"; | ||
@service({ | ||
title: "AssistantService", | ||
}) | ||
namespace AssistantService; | ||
using TypeSpec.Http; | ||
using TypeSpec.Rest; | ||
using Azure.ClientGenerator.Core; | ||
@client interface AssistantServiceClient { | ||
@get @route("chat") Chat(@body message: string) : { | ||
@statusCode statusCode: 200; | ||
@body response : string; | ||
}; | ||
} | ||
``` | ||
#### Generate client libraries from TypeSpec | ||
Let's now generate and build a C# client library from the `AssistantService.tsp` file: | ||
```dotnetcli | ||
cd .. | ||
npm install @typespec/http-client-csharp | ||
tsp compile .\server\tsp\AssistantService.tsp --emit "@typespec/http-client-csharp" | ||
dotnet build tsp-output\@typespec\http-client-csharp\src\AssistantService.csproj | ||
``` | ||
|
||
#### Create command line client app for the service | ||
```dotnetcli | ||
mkdir cmdclient | ||
cd cmdclient | ||
dotnet new console | ||
dotnet add reference ..\tsp-output\@typespec\http-client-csharp\src\AssistantService.csproj | ||
``` | ||
And change the Program.cs file to the following, replacing the client URI with the URI in your server's launchsettings.json file ('cmdemo\server\Properties' folder) | ||
|
||
```csharp | ||
using AssistantService; | ||
|
||
var client = new AssistantServiceClient(new Uri("http://localhost:5121/")); | ||
|
||
while(true){ | ||
string message = Console.ReadLine(); | ||
var completion = client.Chat(message); | ||
Console.WriteLine(completion); | ||
} | ||
``` | ||
Now start the server | ||
```dotnetcli | ||
start cmd | ||
cd.. | ||
cd server | ||
dotnet run | ||
``` | ||
Go back to the client project command window and start the client: | ||
```dotnetcli | ||
dotnet run | ||
``` | ||
You can use the simple command line app to ask Azure OpenAI some questions. |