Gerando Embeddings com Microsoft.Extensions.AI
    Neste artigo veremos como gerar embeddings usando os recursos do pacote Microsoft.Extensions.AI na plataforma .NET.

No universo da inteligência artificial, os embeddings são a espinha dorsal de inúmeras aplicações avançadas, desde busca semântica até sistemas de recomendação e processamento de linguagem natural.

Mas o que exatamente são embeddings e por que eles são tão essenciais para a IA moderna?



Em essência, embeddings são uma forma de representar dados complexos — como palavras, sentenças ou até imagens — em um formato numérico que as máquinas conseguem processar.

Essas representações são vetores numéricos densos (arrays de números) nos quais pontos de dados semelhantes ficam posicionados mais próximos uns dos outros em um espaço de alta dimensão.

Por exemplo, as palavras "rei" e "rainha" provavelmente terão embeddings mais próximos entre si do que do embedding de "maçã", refletindo as relações semânticas entre eles. Essa capacidade de mapear dados em uma forma que captura significado e relações é o que torna os embeddings tão poderosos.

Ao transformar dados abstratos ou não estruturados em vetores, os embeddings permitem que sistemas de IA executem tarefas como agrupamento, busca e classificação com eficiência notável. Eles possibilitam a comparação de entradas complexas de forma intuitiva e contextual, fazendo a ponte entre dados brutos e a compreensão computacional.

Seja para construir um chatbot que entende contexto ou um mecanismo de busca que retorna resultados relevantes com base em significado (e não apenas palavras-chave), os embeddings são ferramentas indispensáveis para soluções modernas de IA.

O que é o Microsoft.Extensions.AI ?

O Microsoft.Extensions.AI é um conjunto de bibliotecas .NET desenvolvido em colaboração com o ecossistema .NET que fornece uma camada unificada de abstrações em C# para interagir com serviços de IA — como LLMs, SLMs e geradores de embeddings.

A biblioteca permite que desenvolvedores integrem capacidades de IA em aplicações .NET sem precisar mergulhar nas complexidades de cada SDK específico de cada provedor, tornando o desenvolvimento mais rápido e padronizado.

A seguir veremos um exemplo prático de como gerar embeddings usando a API da OpenAI via Github Models e também usando o Ollama.

O que é o Github Models ?

O GitHub Models é um serviço do GitHub que oferece acesso a modelos de IA (incluindo os modelos da OpenAI) de forma gratuita para desenvolvimento, usando um token de acesso pessoal do GitHub (PAT) como credencial.

Ele expõe uma API compatível com a OpenAI no endpoint https://models.inference.ai.azure.com, o que significa que podemos usar o mesmo SDK da OpenAI simplesmente trocando o endpoint e a chave — sem custo durante o desenvolvimento.

Para obter seu token:
1- Acesse github.com → Settings → Developer Settings → Personal Access Tokens (PAT)
2- Gere um token com permissão para GitHub Models
3- Use-o como se fosse uma API key da OpenAI

Para usar o PAT com o projeto use o User Secrets:

dotnet user-secrets init
dotnet user-secrets set "OpenAI_Key" "seu_token_aqui"
 

Nota: Você precisa ter o Ollama instalado localmente : https://www.youtube.com/watch?v=DzV7DcFprSE

Exemplo Prático

Abra o Visual Studio (ou o VS Code com a CLI do .NET) e crie uma nova aplicação console .NET 10 com o nome GerandoEmbeddings.

 Em seguida, adicione os seguintes pacotes NuGet ao projeto:

<ItemGroup>
  <PackageReference Include="Microsoft.Extensions.AI" Version="10.4.1" />
  <PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="10.4.1" />
  <PackageReference Include="OllamaSharp" Version="5.4.25" />
  <PackageReference Include="OpenAI" Version="2.9.1" />
  <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" 
Version="6.0.1" />
</ItemGroup> 

Por que esses pacotes?

Microsoft.Extensions.AI — contém as abstrações (IEmbeddingGenerator, etc.)
Microsoft.Extensions.AI.OpenAI — fornece o método de extensão .AsEmbeddingGenerator() para o cliente OpenAI
OllamaSharp — substituto oficial do depreciado Microsoft.Extensions.AI.Ollama
OpenAI — SDK oficial da OpenAI, necessário tanto para a API direta da OpenAI quanto para o GitHub Models
Microsoft.Extensions.Configuration.UserSecrets - Permite armazenar dados sensíveis (como API keys) fora do código-fonte, durante o desenvolvimento.
Nota: Os pacotes Microsoft.Extensions.AI.* ainda estão em preview. Marque a opção "Incluir pré-lançamentos" no NuGet Package Manager do Visual Studio, ou use a flag --prerelease na CLI.

A seguir na classe Program defina o código abaixo:

using Microsoft.Extensions.AI;
using Microsoft.Extensions.Configuration;
using OllamaSharp;
using OpenAI;
using System.ClientModel;

// ─── Seleção do provedor ───────────────────────────────────────────────────
Console.WriteLine("=== Gerador de Embeddings com Microsoft.Extensions.AI ===");
Console.WriteLine();
Console.WriteLine("Selecione o provedor de embeddings:");
Console.WriteLine("  1 - Ollama (local)");
Console.WriteLine("  2 - OpenAI via GitHub Models (gratuito para dev)");
Console.Write("Opção: ");

string? opcao = Console.ReadLine()?.Trim();
Console.WriteLine();

IEmbeddingGenerator>? embeddingGenerator = null;

IConfiguration configuration = new ConfigurationBuilder()
                              .SetBasePath(Directory.GetCurrentDirectory())
                              .AddJsonFile("appsettings.json", optional: true)
                              .AddUserSecrets() //  importante
                              .Build();
switch (opcao)
{
    // ── Ollama (local) ─────────
    case "1":
        Console.Write("Nome do modelo Ollama (ex: nomic-embed-text, mxbai-embed-large): ");
        string ollamaModel = Console.ReadLine()?.Trim() ?? "nomic-embed-text";

        // OllamaApiClient implementa IEmbeddingGenerator>
        // diretamente — basta um cast implícito via atribuição à interface.
        embeddingGenerator = new OllamaApiClient(
            new Uri("http://localhost:11434/"),
            ollamaModel);

        Console.WriteLine($"[Ollama] Provedor configurado com o modelo '{ollamaModel}'.");
        break;

    // ── OpenAI via GitHub Models ──────────
    case "2":
        Console.Write("Informe seu GitHub Personal Access Token (PAT): ");
        //string OpenAI_Key = Console.ReadLine()?.Trim() ?? string.Empty;
        string OpenAI_Key = configuration["OpenAI_Key"]
            ?? throw new InvalidOperationException("OpenAI_Key não configurada");

        Console.WriteLine();
        Console.WriteLine("Selecione o modelo de embedding:");
        Console.WriteLine("  1 - text-embedding-3-small (padrão, mais rápido)");
        Console.WriteLine("  2 - text-embedding-3-large (maior dimensionalidade)");
        Console.Write("Opção: ");
        string? modelOpcao = Console.ReadLine()?.Trim();

        string openAiModel = modelOpcao == "2"
            ? "text-embedding-3-large"
            : "text-embedding-3-small";

        // GitHub Models usa o endpoint da Azure Inference com token do GitHub.
        // O SDK da OpenAI é reutilizado integralmente — apenas endpoint e key mudam.
        embeddingGenerator = new OpenAIClient(
                new ApiKeyCredential(OpenAI_Key),
                new OpenAIClientOptions
                {
                    Endpoint = new Uri("https://models.inference.ai.azure.com")
                })
            .GetEmbeddingClient(openAiModel)  // ← obtém o EmbeddingClient específico
            .AsIEmbeddingGenerator();         // ← converte para IEmbeddingGenerator>

        Console.WriteLine($"[GitHub Models] Provedor configurado com o modelo '{openAiModel}'.");
        break;

    default:
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine("Opção inválida. Encerrando.");
        Console.ResetColor();
        return;
}

// ─── Loop de geração de embeddings ────────────────────────────────────────
Console.WriteLine();
Console.WriteLine("Digite o texto para gerar o embedding (ou 'sair' para encerrar):");
Console.WriteLine(new string('─', 60));

while (true)
{
    Console.WriteLine();
    Console.Write("Texto: ");
    string? input = Console.ReadLine();

    if (string.IsNullOrWhiteSpace(input) || input.Equals("sair", StringComparison.OrdinalIgnoreCase))
    {
        Console.WriteLine("Encerrando. Até mais!");
        break;
    }

    try
    {
        // A interface IEmbeddingGenerator é uniforme independente do provedor.
        // Mesma chamada funciona para Ollama, OpenAI, GitHub Models etc.
        GeneratedEmbeddings> embeddings =
            await embeddingGenerator.GenerateAsync([input]);

        float[] vector = embeddings[0].Vector.ToArray();

        Console.WriteLine();
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine($"Dimensões do vetor: {vector.Length}");
        Console.ResetColor();

        // Exibe apenas os primeiros 10 valores para não poluir o console
        string preview = string.Join(", ", vector.Take(10).Select(v => v.ToString("F6")));
        Console.WriteLine($"Primeiros 10 valores: [{preview}, ...]");
        Console.WriteLine($"Vetor completo: [{string.Join(", ", vector)}]");
    }
    catch (Exception ex)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine($"Erro ao gerar embedding: {ex.Message}");
        Console.ResetColor();
    }
}

Entendendo o código:

Seleção de provedor via Console nativo: Utilizamos Console.WriteLine, Console.Write, Console.ReadLine e Console.ForegroundColor — nenhuma dependência externa de UI. Simples, direto e sem overhead.

O OllamaApiClient como IEmbeddingGenerator: O OllamaApiClient do pacote OllamaSharp implementa a interface IEmbeddingGenerator<string, Embedding<float>> nativamente. Basta atribuí-lo à variável tipada como a interface e o cast acontece implicitamente.

O GitHub Models reutiliza o SDK da OpenAI: Toda a integração com GitHub Models é feita pelo OpenAIClient do SDK oficial da OpenAI — apenas o endpoint (https://models.inference.ai.azure.com) e a credencial (token do GitHub no lugar da API key) mudam. Nenhum pacote adicional é necessário.

GenerateAsync é uniforme: A chamada embeddingGenerator.GenerateAsync([input]) é idêntica independentemente do provedor configurado. É exatamente o poder da abstração IEmbeddingGenerator — seu código de negócio não sabe nem precisa saber qual provedor está por trás.

A seguir temos os modelos de embedding recomendados:

Provedor Modelo Dimensões Observações
Ollama nomic-embed-text 768 Ótimo para textos gerais, é grátis e local
Ollama mxbai-embed-large 1024 Melhor qualidade , ainda local
Github Models text-embedding-3-small 1536 Rápido, gratuito para dev via PAT
Github Models text-embedding-3-large 3072 Maior qualidade semântica

Executando o projeto teremos:

Selecionando a opção 1 - Ollama  e a seguir informando o modelo:  nomic-embed-text :

Informando o texto : teste e teclando enter teremos o embedding gerado:

O processo se repete se você usar a segunda opção : 2-OpenAI via Github Models

Próximos passos

Após gerar os embeddings, o próximo passo natural é armazená-los em um banco de dados vetorial para realizar busca semântica sobre grandes coleções de documentos.

Bancos como Azure Cosmos DB, PostgreSQL com pgvector, Qdrant e Chroma são boas opções. A abstração IEmbeddingGenerator garante que você troque de provedor (de Ollama local para OpenAI em produção, por exemplo) sem alterar nada no restante do código.

Conclusão

Este exemplo demonstrou como utilizar o pacote Microsoft.Extensions.AI para gerar embeddings em uma aplicação console .NET de forma simples e padronizada, integrando diferentes provedores como Ollama (execução local) e OpenAI via GitHub Models.

O principal ganho dessa abordagem está no uso da interface IEmbeddingGenerator<string, Embedding<float>>, que abstrai completamente os detalhes de cada provedor. Com isso, o código se torna mais limpo, desacoplado e fácil de evoluir, permitindo trocar a implementação (local ou cloud) sem impactar a lógica da aplicação.

Além disso, o uso de recursos como User Secrets garante uma forma segura de trabalhar com credenciais durante o desenvolvimento, evitando a exposição de chaves sensíveis no código-fonte.

Esse padrão é especialmente útil em cenários reais, onde aplicações podem começar utilizando modelos locais (como Ollama) e, posteriormente, migrar para soluções em nuvem conforme a necessidade de escala e desempenho.

Como próximos passos, você pode evoluir este exemplo armazenando embeddings em bancos vetoriais e implementando buscas semânticas, abrindo caminho para a construção de aplicações mais avançadas como sistemas de recomendação, chatbots contextuais e soluções baseadas em RAG.

E estamos conversados

"Cantai ao Senhor, vós que sois seus santos, e celebrai a memória da sua santidade."
Salmos 30:4

Referências:


José Carlos Macoratti