Azure OpenAI é um serviço avançado da Microsoft que permite a integração de modelos de IA em suas aplicações, proporcionando funcionalidades como geração de texto, tradução de idiomas, análise de sentimentos e mais. Uma das funcionalidades interessantes é a geração de imagens a partir de descrições textuais, utilizando a tecnologia DALL-E.
O gerador de imagens do Azure OpenAI, baseado no modelo DALL-E, permite criar imagens realistas a partir de descrições textuais. Isso pode ser extremamente útil para diversas aplicações, como marketing digital, design gráfico, educação, entre outras.
Vamos criar a pasta raiz do nosso projeto:
mkdir OpenAiImageGenerator
Em seguida, vamos criar o arquivo .gitignore
para nossa solução:
dotnet new gitignore
Agora, criaremos uma minimal Web API:
dotnet new webapi
Precisamos adicionar o pacote NuGet para interagir com o Azure OpenAI:
dotnet add package Azure.AI.OpenAI --version 2.0.0-beta.2
Para utilizar o serviço Azure OpenAI, você precisa criar o recurso de nuvem correspondente e fazer o deploy de um modelo de geração de imagens. Para isso, siga os guias abaixo:
Adicione as configurações ao arquivo appsettings.json
da sua Web API:
"AzureOpenAi": {
"Endpoint": "<your-endpoint>",
"Key": "<your-key>",
"ImageModel": "<your-image-generator-model>"
}
Vamos criar o modelo de requisição para gerar uma imagem:
namespace OpenAiImageGenerator.Services.Models;
public record CreateImageRequest(string GeneralIdea);
E o modelo que será retornado pela nossa API:
namespace OpenAiImageGenerator.Services.Models;
public record ImageResult(string Url);
Agora, vamos criar o serviço para trabalhar com as imagens:
using OpenAiImageGenerator.Services.Models;
namespace OpenAiImageGenerator.Services;
public interface IImageService
{
Task<ImageResult> CreateImageAsync(CreateImageRequest request);
}
using Azure;
using Azure.AI.OpenAI;
using OpenAI.Images;
using OpenAiImageGenerator.Services.Models;
namespace OpenAiImageGenerator.Services;
public class AzureOpenAiImageService(IConfiguration configuration) : IImageService
{
private ImageClient GetImageClient()
{
string endpoint = configuration["AzureOpenAi:Endpoint"]!;
string key = configuration["AzureOpenAi:Key"]!;
AzureOpenAIClient azureClient = new(new Uri(endpoint), new AzureKeyCredential(key));
return azureClient.GetImageClient(configuration["AzureOpenAi:ImageModel"]!);
}
public async Task<ImageResult> CreateImageAsync(CreateImageRequest request)
{
var client = GetImageClient();
var image = await client.GenerateImageAsync(
request.GeneralIdea,
new ImageGenerationOptions
{
Quality = GeneratedImageQuality.Standard,
Size = GeneratedImageSize.W1024xH1024,
Style = GeneratedImageStyle.Vivid,
ResponseFormat = GeneratedImageFormat.Uri,
}
);
return new ImageResult(image.Value!.ImageUri.ToString());
}
}
Precisamos ainda configurar a injeção do dependência do serviço criado no Program.cs
:
builder.Services.AddScoped<IImageService, AzureOpenAiImageService>();
Vamos implementar o endpoint para expor o serviço de criação de imagem:
app.MapPost("/image", async (CreateImageRequest request, IImageService service)
=> await service.CreateImageAsync(request))
.WithName("CreateImage")
.WithOpenApi();
O Program.cs
ficou dessa forma:
using OpenAiImageGenerator.Services;
using OpenAiImageGenerator.Services.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IImageService, AzureOpenAiImageService>();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.UseHttpsRedirection();
app.MapPost("/image", async (CreateImageRequest request, IImageService service)
=> await service.CreateImageAsync(request))
.WithName("CreateImage")
.WithOpenApi();
app.Run();
Para testar, e execute a aplicação dotnet run
envie a seguinte requisição:
{
"generalIdea": "A dog coding in his laptop. He is also eating a cheese pizza"
}
Temos a reposta com a URL da imagem gerada!
Tudo ocorreu bem! Vamos agora criar um endpoint que irá receber a URL da imagem e irá descrevê-la. Para isso, adicionaremos uma nova chave no appsettings.json
:
"ChatModel": "<your-chat-model>"
Nesse caso, estou utilizando o GPT-4o! Leia esse artigo para mais informações.
Vamos criar um novo record de entrada:
namespace OpenAiImageGenerator.Services.Models;
public record DescribeImageRequest(string Url);
E um novo record de saída:
namespace OpenAiImageGenerator.Services.Models;
public record DescribeImageResult(string Description);
Adicione o novo método no serviço de imagens:
Task<DescribeImageResult> DescribeImageAsync(DescribeImageRequest request);
private ChatClient GetChatClient()
{
string endpoint = configuration["AzureOpenAi:Endpoint"]!;
string key = configuration["AzureOpenAi:Key"]!;
AzureOpenAIClient azureClient = new(new Uri(endpoint), new AzureKeyCredential(key));
return azureClient.GetChatClient(configuration["AzureOpenAi:ChatModel"]!);
}
public async Task<DescribeImageResult> DescribeImageAsync(DescribeImageRequest request)
{
var client = GetChatClient();
ChatMessageContentPart[] content =
[
ChatMessageContentPart.CreateImageMessageContentPart(new Uri(request.Url))
];
ChatCompletion completion = await client.CompleteChatAsync(
[
new SystemChatMessage("You are a helpful assistant that create image descriptions"),
new UserChatMessage(content)
]);
var result = completion.Content[0].Text;
return new DescribeImageResult(result);
}
Com o novo método pronto, podemos criar o novo endpoint no Program.cs
:
app.MapPost("/image/describe", async (DescribeImageRequest request, IImageService service)
=> await service.DescribeImageAsync(request))
.WithName("DescribeImage")
.WithOpenApi();
app.MapPost("/image/describe", async (DescribeImageRequest request, IImageService service)
=> await service.DescribeImageAsync(request))
.WithName("DescribeImage")
.WithOpenApi();
Vamos fazer a requisição utilizando a URL da imagem retornada anteriormente e obter a resposta descrevendo a imagem:
Resultado:
{
"description": "The image depicts a golden retriever sitting in a cozy, leather armchair in a warmly lit room with a brick wall and bookshelves. The dog is engaged with a laptop on a wooden table, appearing to type with one paw while holding a slice of pepperoni pizza in its mouth. On the table in front of the dog, there's an open pizza box with a whole pepperoni pizza inside. A lamp with a beige shade provides soft lighting. The scene is playful and humorous, suggesting the dog is busy multitasking while enjoying its meal."
}
E é isso pessoal!
Você já pode baixar o projeto por esse link, e não esquece de me seguir no LinkedIn!
Até a próxima, abraços!