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!

💡
Podemos te ajudar com uma revisão 100% gratuita do seu ambiente cloud.
Share this post