Skip to content

Commit 8c3550e

Browse files
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
1 parent d036477 commit 8c3550e

File tree

1 file changed

+278
-0
lines changed

1 file changed

+278
-0
lines changed

sdk/cloudmachine/README.MD

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
# Azure CloudMachine
2+
3+
Write Azure apps in 5 minutes
4+
5+
## Getting started
6+
7+
### Prerequisites
8+
9+
> You must have an [Azure subscription](https://azure.microsoft.com/free/dotnet/).
10+
> You must have .NET 8 (or higher) installed
11+
> You must have Azure CLI installed
12+
> You must have Azure Developer CLI installed
13+
> You must have npm installed
14+
> You must be logged into Azure CLI and Azure Developer CLI
15+
16+
### Walkthrough
17+
18+
#### Create Server Project
19+
20+
In a command line window type
21+
```dotnetcli
22+
mkdir cmdemo
23+
cd cmdemo
24+
mkdir server
25+
cd server
26+
dotnet new web
27+
```
28+
29+
Add `Azure.CloudMachine.All` package
30+
```dotnetcli
31+
dotnet add package Azure.CloudMachine.All --prerelease
32+
```
33+
#### Use Azure Dev CLI to provision CloudMachine
34+
35+
Open Program.cs file and add the following two lines of code to the top of the file
36+
```csharp
37+
using Azure.Provisioning.CloudMachine;
38+
39+
if (CloudMachineInfrastructure.Configure(args)) return;
40+
```
41+
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.
42+
```dotnetcli
43+
dotnet run -bicep
44+
```
45+
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.
46+
```dotnetcli
47+
azd init
48+
```
49+
select template, choose 'yes' when asked 'Continue initializing an app here?', choose the 'minimal' template, and use 'cmserver' as the environment name
50+
51+
Once the initialization completes, let's provision the resources. Select `eastus` as the region
52+
```dotnetcli
53+
azd provision
54+
```
55+
When provisioning finishes, you should see something like the following in the console output
56+
```dotnetcli
57+
(✓) Done: Resource group: cm125957681369428 (627ms)
58+
```
59+
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.
60+
```dotnetcli
61+
az resource list --resource-group <resource_group_from_command_line> --output table
62+
```
63+
64+
#### Use CDK to add resources to the CloudMachine
65+
66+
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:
67+
```csharp
68+
class AssistantService {
69+
internal static void Configure(CloudMachineInfrastructure cm) {
70+
cm.AddFeature(new OpenAIFeature() { Chat = new AIModel("gpt-4o-mini", "2024-07-18") });
71+
}
72+
}
73+
```
74+
And change the infrastructure configuration call att he begining of the file to:
75+
```csharp
76+
if (CloudMachineInfrastructure.Configure(args, AssistantService.Configure)) return;
77+
```
78+
And now regenerate new bicep with the new Azure OpenAI resources, and re-provision
79+
```dotnetcli
80+
dotnet run -bicep
81+
azd provision
82+
```
83+
84+
#### Call CloudMachine APIs
85+
86+
You are now ready to call Azure OpenAI service from the app. To do this, add `CloudMachineClient` field and a `Chat` method to `AssistantService`:
87+
```csharp
88+
class AssistantService {
89+
CloudMachineClient cm = new CloudMachineClient();
90+
91+
public async Task<string> Chat(string message) {
92+
var client = cm.GetOpenAIChatClient();
93+
ChatCompletion completion = await client.CompleteChatAsync(message);
94+
return completion.Content[0].Text;
95+
}
96+
}
97+
```
98+
Lastly, create an instance of the service and call the `Chat` method when the app users browses the app:
99+
```csharp
100+
var service = new AssistantService();
101+
app.MapGet("/", async () => {
102+
return await service.Chat("List all noble gases");
103+
});
104+
```
105+
The full program should look like following:
106+
```csharp
107+
using Azure.CloudMachine;
108+
using Azure.CloudMachine.OpenAI;
109+
using Azure.Provisioning.CloudMachine;
110+
using Azure.Provisioning.CloudMachine.OpenAI;
111+
using OpenAI.Chat;
112+
113+
if (CloudMachineInfrastructure.Configure(args, AssistantService.Configure)) return;
114+
115+
var builder = WebApplication.CreateBuilder(args);
116+
var app = builder.Build();
117+
118+
var service = new AssistantService();
119+
app.MapGet("/", async () => {
120+
return await service.Chat("List all noble gases");
121+
});
122+
123+
app.Run();
124+
125+
class AssistantService {
126+
CloudMachineClient cm = new CloudMachineClient();
127+
128+
public async Task<string> Chat(string message) {
129+
var client = cm.GetOpenAIChatClient();
130+
ChatCompletion completion = await client.CompleteChatAsync(message);
131+
return completion.Content[0].Text;
132+
}
133+
134+
internal static void Configure(CloudMachineInfrastructure cm) {
135+
cm.AddFeature(new OpenAIFeature() {
136+
Chat = new AIModel("gpt-4o-mini", "2024-07-18")
137+
});
138+
}
139+
}
140+
```
141+
You can now start the application
142+
```dotnetcli
143+
dotnet run
144+
```
145+
and browse to the URI printed in the console.
146+
147+
#### Use TDK to expose Web APIs and generate TypeSpec
148+
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:
149+
```csharp
150+
interface IAssistantService {
151+
Task<string> Chat(string message);
152+
}
153+
```
154+
Make sure that the `AssistantService` implements the interface:
155+
```csharp
156+
class AssistantService : IAssistantService
157+
```
158+
Expose the service methods as web APIs by adding the following line after the existing 'var service = new AssistantService();' line:
159+
```csharp
160+
app.Map(service);
161+
```
162+
Lastly, add the ability to generate TypeSpec for the new API by adding new statement to the `Configure` method
163+
```csharp
164+
cm.AddEndpoints<IAssistantService>();
165+
```
166+
Your program shoud now look like following:
167+
```csharp
168+
using Azure.CloudMachine;
169+
using Azure.CloudMachine.OpenAI;
170+
using Azure.Provisioning.CloudMachine;
171+
using Azure.Provisioning.CloudMachine.OpenAI;
172+
using OpenAI.Chat;
173+
using System.ClientModel.TypeSpec;
174+
175+
if (CloudMachineInfrastructure.Configure(args, AssistantService.Configure)) return;
176+
177+
var builder = WebApplication.CreateBuilder(args);
178+
var app = builder.Build();
179+
180+
var service = new AssistantService();
181+
app.Map(service);
182+
app.MapGet("/", async () => {
183+
return await service.Chat("List all noble gasses");
184+
});
185+
186+
app.Run();
187+
188+
class AssistantService : IAssistantService {
189+
CloudMachineClient cm = new CloudMachineClient();
190+
191+
public async Task<string> Chat(string message) {
192+
var client = cm.GetOpenAIChatClient();
193+
ChatCompletion completion = await client.CompleteChatAsync(message);
194+
return completion.Content[0].Text;
195+
}
196+
197+
internal static void Configure(CloudMachineInfrastructure cm) {
198+
cm.AddFeature(new OpenAIFeature() {
199+
Chat = new AIModel("gpt-4o-mini", "2024-07-18")
200+
});
201+
cm.AddEndpoints<IAssistantService>();
202+
}
203+
}
204+
205+
interface IAssistantService {
206+
Task<string> Chat(string message);
207+
}
208+
```
209+
You can now start the application and browse to the /chat endpoint [TDB]
210+
211+
But what's more interesting, you can run the app with the -tsp switch to generate TypeSpec for the endpoint:
212+
```dotnetcli
213+
dotnet run -tsp
214+
```
215+
This will create a `tsp` directory, AssistantService.tsp file, with the following contents:
216+
```tsp
217+
import "@typespec/http";
218+
import "@typespec/rest";
219+
import "@azure-tools/typespec-client-generator-core";
220+
221+
@service({
222+
title: "AssistantService",
223+
})
224+
225+
namespace AssistantService;
226+
227+
using TypeSpec.Http;
228+
using TypeSpec.Rest;
229+
using Azure.ClientGenerator.Core;
230+
231+
@client interface AssistantServiceClient {
232+
@get @route("chat") Chat(@body message: string) : {
233+
@statusCode statusCode: 200;
234+
@body response : string;
235+
};
236+
}
237+
```
238+
#### Generate client libraries from TypeSpec
239+
Let's now generate and build a C# client library from the `AssistantService.tsp` file:
240+
```dotnetcli
241+
cd ..
242+
npm install @typespec/http-client-csharp
243+
tsp compile .\server\tsp\AssistantService.tsp --emit "@typespec/http-client-csharp"
244+
dotnet build tsp-output\@typespec\http-client-csharp\src\AssistantService.csproj
245+
```
246+
247+
#### Create command line client app for the service
248+
```dotnetcli
249+
mkdir cmdclient
250+
cd cmdclient
251+
dotnet new console
252+
dotnet add reference ..\tsp-output\@typespec\http-client-csharp\src\AssistantService.csproj
253+
```
254+
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)
255+
256+
```csharp
257+
using AssistantService;
258+
259+
var client = new AssistantServiceClient(new Uri("http://localhost:5121/"));
260+
261+
while(true){
262+
string message = Console.ReadLine();
263+
var completion = client.Chat(message);
264+
Console.WriteLine(completion);
265+
}
266+
```
267+
Now start the server
268+
```dotnetcli
269+
start cmd
270+
cd..
271+
cd server
272+
dotnet run
273+
```
274+
Go back to the client project command window and start the client:
275+
```dotnetcli
276+
dotnet run
277+
```
278+
You can use the simple command line app to ask Azure OpenAI some questions.

0 commit comments

Comments
 (0)