Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions docs/ai/quickstarts/snippets/text-to-image/hosting/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// <SnippetSetup>
using Aspire.Azure.AI.OpenAI;
using Microsoft.Extensions.AI;
using OpenAI;

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

// Add the Azure OpenAI client using hosting integration.
AspireAzureOpenAIClientBuilder openai = builder.AddAzureOpenAIClient("openai");
// </SnippetSetup>

// <SnippetAddImageGenerator>
// Register the image generator with dependency injection.
ImageGeneratorBuilder imageBuilder = builder.Services.AddImageGenerator(services =>
{
OpenAIClient openAiClient = services.GetRequiredService<OpenAIClient>();
OpenAI.Images.ImageClient imageClient = openAiClient.GetImageClient("gpt-image-1");
#pragma warning disable MEAI001 // Type is for evaluation purposes only.
return imageClient.AsIImageGenerator();
#pragma warning restore MEAI001
});
// </SnippetAddImageGenerator>

// <SnippetConfigureOptions>
imageBuilder.ConfigureOptions(options =>
{
options.MediaType = "image/png";
}).UseLogging();
// </SnippetConfigureOptions>

WebApplication app = builder.Build();

// <SnippetUseImageGenerator>
// Use the image generator in an endpoint.
app.MapPost("/generate-image", async (IImageGenerator generator, string prompt) =>
{
ImageGenerationResponse response = await generator.GenerateImagesAsync(prompt);
DataContent dataContent = response.Contents.OfType<DataContent>().First();

return Results.File(dataContent.Data.ToArray(), "image/png");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I missed on my first review, but this might slightly better:

    return Results.File(dataContent.Data.ToArray(), dataContent.MediaType);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll submit a PR.

});
// </SnippetUseImageGenerator>

app.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5219",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7210;http://localhost:5219",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<NoWarn>$(NoWarn);MEAI001</NoWarn>
<UserSecretsId>a9e545e9-e2b5-4e1b-81ce-217ca2d281c6</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Aspire.Azure.AI.OpenAI" Version="13.0.0-preview.1.25560.3" />
<PackageReference Include="Azure.AI.OpenAI" Version="2.5.0-beta.1" />
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="10.0.0-preview.1.25560.10" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"openai": "Endpoint=https://your-endpoint.com/;Key=your-api-key"
}
}
59 changes: 59 additions & 0 deletions docs/ai/quickstarts/text-to-image.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,65 @@ You can customize image generation by providing other options such as size, resp
- <xref:Microsoft.Extensions.AI.ImageGenerationOptions.RawRepresentationFactory>: The callback that creates the raw representation of the image generation options from an underlying implementation.
- <xref:Microsoft.Extensions.AI.ImageGenerationOptions.ResponseFormat>: Options are <xref:Microsoft.Extensions.AI.ImageGenerationResponseFormat.Uri>, <xref:Microsoft.Extensions.AI.ImageGenerationResponseFormat.Data>, and <xref:Microsoft.Extensions.AI.ImageGenerationResponseFormat.Hosted>.

## Use hosting integration

When you build web apps or hosted services, you can integrate image generation using dependency injection and hosting patterns. This approach provides better lifecycle management, configuration integration, and testability.

### Configure hosting services

The `Aspire.Azure.AI.OpenAI` package provides extension methods to register Azure OpenAI services with your application's dependency injection container:

1. Add the necessary packages to your web application:

```dotnetcli
dotnet add package Aspire.Azure.AI.OpenAI --prerelease
dotnet add package Azure.AI.OpenAI
dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease
```

1. Configure the Azure OpenAI client and image generator in your `Program.cs` file:

:::code language="csharp" source="snippets/text-to-image/hosting/Program.cs" id="SnippetSetup":::

The <xref:Microsoft.Extensions.Hosting.AspireAzureOpenAIExtensions.AddAzureOpenAIClient(Microsoft.Extensions.Hosting.IHostApplicationBuilder,System.String,System.Action{Aspire.Azure.AI.OpenAI.AzureOpenAISettings},System.Action{Azure.Core.Extensions.IAzureClientBuilder{Azure.AI.OpenAI.AzureOpenAIClient,Azure.AI.OpenAI.AzureOpenAIClientOptions}})> method registers the Azure OpenAI client with dependency injection. The connection string (named `"openai"`) is retrieved from configuration, typically from `appsettings.json` or environment variables:

```json
{
"ConnectionStrings": {
"openai": "Endpoint=https://your-resource-name.openai.azure.com/;Key=your-api-key"
}
}
```

1. Register the <xref:Microsoft.Extensions.AI.IImageGenerator> service with dependency injection:

:::code language="csharp" source="snippets/text-to-image/hosting/Program.cs" id="SnippetAddImageGenerator":::

The <xref:Microsoft.Extensions.DependencyInjection.ImageGeneratorBuilderServiceCollectionExtensions.AddImageGenerator*> method registers the image generator as a singleton service that can be injected into controllers, services, or minimal API endpoints.

1. Add options and logging::

:::code language="csharp" source="snippets/text-to-image/hosting/Program.cs" id="SnippetConfigureOptions":::

The preceding code:

- Configures options by calling the <xref:Microsoft.Extensions.AI.ConfigureOptionsImageGeneratorBuilderExtensions.ConfigureOptions(Microsoft.Extensions.AI.ImageGeneratorBuilder,System.Action{Microsoft.Extensions.AI.ImageGenerationOptions})> extension method on the <xref:Microsoft.Extensions.AI.ImageGeneratorBuilder>. This method configures the <xref:Microsoft.Extensions.AI.ImageGenerationOptions> to be passed to the next generator in the pipeline.
- Adds logging to the image generator pipeline by calling the <xref:Microsoft.Extensions.AI.LoggingImageGeneratorBuilderExtensions.UseLogging(Microsoft.Extensions.AI.ImageGeneratorBuilder,Microsoft.Extensions.Logging.ILoggerFactory,System.Action{Microsoft.Extensions.AI.LoggingImageGenerator})> extension method.

### Use the image generator in endpoints

Once registered, you can inject `IImageGenerator` into your endpoints or services:

:::code language="csharp" source="snippets/text-to-image/hosting/Program.cs" id="SnippetUseImageGenerator":::

This hosting approach provides several benefits:

- **Configuration management**: Connection strings and settings are managed through the .NET configuration system.
- **Dependency injection**: The image generator is available throughout your application via DI.
- **Lifecycle management**: Services are properly initialized and disposed of by the hosting infrastructure.
- **Testability**: Mock implementations can be easily substituted for testing.
- **Integration with .NET Aspire**: When using .NET Aspire, the `AddAzureOpenAIClient` method integrates with service discovery and telemetry.

## Best practices

When implementing text-to-image generation in your applications, consider these best practices:
Expand Down