Skip to content

Commit f3fc039

Browse files
Add Aspire.Hosting.OpenAI integration (#10830)
* Add Aspire.Hosting.OpenAI integration * Add tests * Remove duplicate files * Fix package icon * Ensure health check is blocking dependent resources * Split OpenAI and Model resources * Fix playground * Add StatusPage health check for OpenAI * Fix playground * Add lifetime * Simplify lifetime * Generate manifests for samples --------- Co-authored-by: David Fowler <[email protected]>
1 parent 2383d5b commit f3fc039

39 files changed

+1658
-26
lines changed

.github/copilot-instructions.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* Follow the instructions in the repo to build.
3030
* If temporarily introducing warnings during a refactoring, you can add the flag `/p:TreatWarningsAsErrors=false` to your build command to prevent the build from failing. However before you finish your work, you must strive to fix any warnings as well.
3131

32-
In building and testing, never use `dotnet` without extension. Use `dotnet.sh` on Unix, `dotnet.cmd` on Windows.
32+
In building and testing, never use `dotnet` without extension. Use `./dotnet.sh` on Unix, `.\dotnet.cmd` on Windows.
3333

3434
### Testing
3535

@@ -43,11 +43,16 @@ In building and testing, never use `dotnet` without extension. Use `dotnet.sh` o
4343

4444
(1) Build from the root with `build.sh`.
4545
(2) If that produces errors, fix those errors and build again. Repeat until the build is successful.
46-
(3) To then run tests, use a command similar to this `dotnet.sh test tests/Aspire.Seq.Tests/Aspire.Seq.Tests.csproj` (using the path to whatever projects are applicable to the change).
46+
(3) To then run tests, use a command similar to this `dotnet.sh test tests/Aspire.Seq.Tests/Aspire.Seq.Tests.csproj --no-build` (using the path to whatever projects are applicable to the change).
4747

4848
Note that tests for a project can be executed without first building from the root.
4949

50-
(4) To run just certain tests, it's important to include the filter after `--`, for example `dotnet.sh test tests/Aspire.Hosting.Testing.Tests/Aspire.Hosting.Testing.Tests.csproj --no-build --logger "console;verbosity=detailed" -- --filter "TestingBuilderHasAllPropertiesFromRealBuilder"`
50+
(4) To run just certain tests, it's important to include the filter after `--`, for example:
51+
52+
dotnet.sh test tests/Aspire.Hosting.Testing.Tests/Aspire.Hosting.Testing.Tests.csproj --logger "console;verbosity=detailed" -- --filter "TestingBuilderHasAllPropertiesFromRealBuilder"
53+
```
54+
55+
Important: Avoid passing `--no-build` unless you have just built in the same session and there have been no code changes since. In automation or while iterating on code, omit `--no-build` so changes are compiled and picked up by the test run.
5156
5257
### Important: Excluding Quarantined Tests
5358
@@ -83,3 +88,9 @@ Example: `[QuarantinedTest("..issue url..")]`
8388
## Editing resources
8489

8590
The `*.Designer.cs` files are in the repo, but are intended to match same named `*.resx` files. If you add/remove/change resources in a resx, make the matching changes in the `*.Designer.cs` file that matches that resx.
91+
92+
## Markdown files
93+
94+
* Markdown files should not have multiple consecutive blank lines.
95+
* Code blocks should be formatted with triple backticks (```) and include the language identifier for syntax highlighting.
96+
* JSON code blocks should be indented properly.

Aspire.slnx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
<Project Path="src/Aspire.Hosting.MySql/Aspire.Hosting.MySql.csproj" />
5959
<Project Path="src/Aspire.Hosting.Nats/Aspire.Hosting.Nats.csproj" />
6060
<Project Path="src/Aspire.Hosting.NodeJs/Aspire.Hosting.NodeJs.csproj" />
61+
<Project Path="src/Aspire.Hosting.OpenAI/Aspire.Hosting.OpenAI.csproj" />
6162
<Project Path="src/Aspire.Hosting.Oracle/Aspire.Hosting.Oracle.csproj" />
6263
<Project Path="src/Aspire.Hosting.Orleans/Aspire.Hosting.Orleans.csproj" />
6364
<Project Path="src/Aspire.Hosting.PostgreSQL/Aspire.Hosting.PostgreSQL.csproj" />
@@ -119,6 +120,10 @@
119120
<Project Path="playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/AzureFunctionsEndToEnd.AppHost.csproj" />
120121
<Project Path="playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.Functions/AzureFunctionsEndToEnd.Functions.csproj" />
121122
</Folder>
123+
<Folder Name="/playground/AzureOpentAIEndToEnd/">
124+
<Project Path="playground/AzureOpenAIEndToEnd/AzureOpenAIEndToEnd.AppHost/AzureOpenAIEndToEnd.AppHost.csproj" />
125+
<Project Path="playground/AzureOpenAIEndToEnd/AzureOpenAIEndToEnd.WebStory/AzureOpenAIEndToEnd.WebStory.csproj" />
126+
</Folder>
122127
<Folder Name="/playground/AzureSearchEndToEnd/">
123128
<Project Path="playground/AzureSearchEndToEnd/AzureSearch.ApiService/AzureSearch.ApiService.csproj" />
124129
<Project Path="playground/AzureSearchEndToEnd/AzureSearch.AppHost/AzureSearch.AppHost.csproj" />
@@ -389,6 +394,7 @@
389394
<Project Path="tests/Aspire.Hosting.MySql.Tests/Aspire.Hosting.MySql.Tests.csproj" />
390395
<Project Path="tests/Aspire.Hosting.Nats.Tests/Aspire.Hosting.Nats.Tests.csproj" />
391396
<Project Path="tests/Aspire.Hosting.NodeJs.Tests/Aspire.Hosting.NodeJs.Tests.csproj" />
397+
<Project Path="tests/Aspire.Hosting.OpenAI.Tests/Aspire.Hosting.OpenAI.Tests.csproj" />
392398
<Project Path="tests/Aspire.Hosting.Oracle.Tests/Aspire.Hosting.Oracle.Tests.csproj" />
393399
<Project Path="tests/Aspire.Hosting.PostgreSQL.Tests/Aspire.Hosting.PostgreSQL.Tests.csproj" />
394400
<Project Path="tests/Aspire.Hosting.Python.Tests/Aspire.Hosting.Python.Tests.csproj" />
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>$(DefaultTargetFramework)</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<IsAspireHost>true</IsAspireHost>
9+
<UserSecretsId>55ef4430-77f1-4dfa-9af3-e2e39d665e2a</UserSecretsId>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<Compile Include="..\..\KnownResourceNames.cs" Link="KnownResourceNames.cs" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<AspireProjectOrPackageReference Include="Aspire.Hosting.Azure" />
18+
<AspireProjectOrPackageReference Include="Aspire.Hosting.Azure.CognitiveServices" />
19+
<AspireProjectOrPackageReference Include="Aspire.Hosting.AppHost" />
20+
<ProjectReference Include="..\AzureOpenAIEndToEnd.WebStory\AzureOpenAIEndToEnd.WebStory.csproj" />
21+
</ItemGroup>
22+
23+
</Project>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
var builder = DistributedApplication.CreateBuilder(args);
5+
6+
var chat = builder.AddAzureOpenAI("openai")
7+
.AddDeployment("chat", "gpt-4o", "2024-05-13");
8+
9+
builder.AddProject<Projects.AzureOpenAIEndToEnd_WebStory>("webstory")
10+
.WithExternalHttpEndpoints()
11+
.WithReference(chat);
12+
13+
#if !SKIP_DASHBOARD_REFERENCE
14+
// This project is only added in playground projects to support development/debugging
15+
// of the dashboard. It is not required in end developer code. Comment out this code
16+
// or build with `/p:SkipDashboardReference=true`, to test end developer
17+
// dashboard launch experience, Refer to Directory.Build.props for the path to
18+
// the dashboard binary (defaults to the Aspire.Dashboard bin output in the
19+
// artifacts dir).
20+
builder.AddProject<Projects.Aspire_Dashboard>(KnownResourceNames.AspireDashboard);
21+
#endif
22+
23+
builder.Build().Run();
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"$schema": "http://json.schemastore.org/launchsettings.json",
3+
"profiles": {
4+
"https": {
5+
"commandName": "Project",
6+
"dotnetRunMessages": true,
7+
"launchBrowser": true,
8+
"applicationUrl": "https://localhost:15215;http://localhost:15216",
9+
"environmentVariables": {
10+
"ASPNETCORE_ENVIRONMENT": "Development",
11+
"DOTNET_ENVIRONMENT": "Development",
12+
"ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:16195",
13+
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:17037"
14+
}
15+
},
16+
"http": {
17+
"commandName": "Project",
18+
"dotnetRunMessages": true,
19+
"launchBrowser": true,
20+
"applicationUrl": "http://localhost:15216",
21+
"environmentVariables": {
22+
"ASPNETCORE_ENVIRONMENT": "Development",
23+
"DOTNET_ENVIRONMENT": "Development",
24+
"ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:16195",
25+
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:17038",
26+
"ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true"
27+
}
28+
},
29+
"generate-manifest": {
30+
"commandName": "Project",
31+
"launchBrowser": true,
32+
"dotnetRunMessages": true,
33+
"commandLineArgs": "--publisher manifest --output-path aspire-manifest.json",
34+
"environmentVariables": {
35+
"ASPNETCORE_ENVIRONMENT": "Development",
36+
"DOTNET_ENVIRONMENT": "Development"
37+
}
38+
}
39+
}
40+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
}
8+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning",
6+
"Aspire.Hosting.Dcp": "Warning"
7+
}
8+
}
9+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"$schema": "https://json.schemastore.org/aspire-8.0.json",
3+
"resources": {
4+
"openai": {
5+
"type": "azure.bicep.v0",
6+
"connectionString": "{openai.outputs.connectionString}",
7+
"path": "openai.module.bicep"
8+
},
9+
"chat": {
10+
"type": "value.v0",
11+
"connectionString": "{openai.outputs.connectionString};Deployment=chat"
12+
},
13+
"webstory": {
14+
"type": "project.v0",
15+
"path": "../AzureOpenAIEndToEnd.WebStory/AzureOpenAIEndToEnd.WebStory.csproj",
16+
"env": {
17+
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
18+
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
19+
"OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory",
20+
"ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true",
21+
"HTTP_PORTS": "{webstory.bindings.http.targetPort}",
22+
"ConnectionStrings__chat": "{chat.connectionString}"
23+
},
24+
"bindings": {
25+
"http": {
26+
"scheme": "http",
27+
"protocol": "tcp",
28+
"transport": "http",
29+
"external": true
30+
},
31+
"https": {
32+
"scheme": "https",
33+
"protocol": "tcp",
34+
"transport": "http",
35+
"external": true
36+
}
37+
}
38+
},
39+
"openai-roles": {
40+
"type": "azure.bicep.v0",
41+
"path": "openai-roles.module.bicep",
42+
"params": {
43+
"openai_outputs_name": "{openai.outputs.name}",
44+
"principalType": "",
45+
"principalId": ""
46+
}
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)