.NET - Integração com IA


    Hoje veremos como usar os novos recursos da plataforma .NET para criar aplicações integradas com a Inteligência Artificial.

A integração da Inteligência Artificial, particularmente de Modelos de Linguagem Grande (LLMs), em aplicações modernas, deixou de ser um experimento novo e se tornou um imperativo de negócios.



Felizmente o lançamento das bibliotecas Microsoft.Extensioins.IA (mais recente) e Microsoft.SemanticKernel pretende ser um divisor de águas facilitando a vida do desenvolvedor.

O pacote Microsoft.Extensions.AI é um conjunto de bibliotecas inovador projetado para integrar serviços de IA de forma contínua em aplicações .NET. Estas bibliotecas fornecem uma camada unificada de abstrações C#, permitindo que os desenvolvedores trabalhem com vários serviços de IA, incluindo modelos de linguagem pequenos e grandes (SLMs e LLMs), embeddings e middleware.

Esta biblioteca visa atuar como uma camada unificadora dentro do ecossistema .NET, permitindo que os desenvolvedores escolham os frameworks e bibliotecas de sua preferência, ao mesmo tempo que garantem integração e colaboração contínuas. As bibliotecas fornecem abstrações essenciais para funcionalidades padrão de IA, tais como:

Chat: Recursos que possibilitam prompts conversacionais para recuperação de informações ou análise de dados.

Geração de Embeddings: Integração com recursos de pesquisa vetorial.

Tool Calling (Chamada de Ferramenta): Facilitação da integração com outros serviços, plataformas ou código.

Principais Benefícios

API Unificada: O Microsoft.Extensions.AI oferece um conjunto consistente de APIs e convenções para integrar serviços de IA em aplicações .NET. Essa abordagem é semelhante às abstrações bem-sucedidas de logging e injeção de dependência (DI) no .NET.

Flexibilidade: Os desenvolvedores podem implementar essas abstrações com vários serviços de IA, garantindo que suas aplicações permaneçam adaptáveis e preparadas para o futuro.

Integração de Middleware: As bibliotecas incluem middleware para adicionar recursos chave sem sobrecarregar os produtores, beneficiando os consumidores imediatamente.

Já o SDK Microsoft.SemanticKernel (SK) é uma biblioteca de código aberto desenvolvida pela Microsoft, projetada para facilitar a integração de modelos de linguagem de inteligência artificial (LLMs, ou Large Language Models) e outras tecnologias de IA em aplicações .NET.

Ela atua como uma camada de abstração que simplifica a interação com serviços de IA, como OpenAI, Azure OpenAI e modelos locais (ex.: via Ollama), permitindo que desenvolvedores criem soluções inteligentes com menos esforço. Lançada como parte do ecossistema de IA da Microsoft, a SK é amplamente utilizada para construir agentes de IA conversacionais, automações inteligentes e sistemas que combinam IA com lógica de negócios.

O que ela faz?

A Microsoft.SemanticKernel(SK) fornece um conjunto de ferramentas e abstrações que permitem:

Integração com LLMs: Conecta-se a provedores de IA (ex.: OpenAI, Azure OpenAI, Ollama) para realizar tarefas como geração de texto, tradução, resumo, perguntas e respostas, e até geração multimodal (quando suportada, como análise de imagens).

Nota:   No contexto da SK, a geração multimodal é suportada quando integrada a modelos que oferecem essa capacidade, como os fornecidos pelo Azure OpenAI Service (ex.: GPT-4o). A SK abstrai essa funcionalidade via IChatCompletionService e ChatHistory, permitindo que você adicione conteúdo multimodal (ex.: imagens) às mensagens.

Gerenciamento de Conversas: Oferece um sistema de histórico de chat (ChatHistory) e serviços como IChatCompletionService para manter o contexto das interações e obter respostas de modelos de linguagem.

Suporte a Plugins e Funções: Permite definir funções personalizadas em C# com a anotação [KernelFunction], que o LLM pode chamar dinamicamente (feature conhecida como Tool Calling), integrando lógica de aplicação com IA.

RAG (Retrieval-Augmented Generation): Facilita a consulta de bases de conhecimento externas (ex.: documentos, bancos vetoriais como Chroma ou Qdrant) para enriquecer respostas do LLM com dados recentes ou específicos, reduzindo alucinações e limitando o conhecimento desatualizado.

Embeddings: Suporta a geração de vetores a partir de texto usando modelos como text-embedding-ada-002 (via conectores OpenAI), úteis para buscas semânticas e armazenamento em bancos de dados vetoriais.

Orquestração de Serviços: Usa um modelo de kernel (um container de serviços) para gerenciar múltiplas capacidades de IA, como chat, embeddings e plugins, de forma modular e escalável.

Assim, a SK é construída sobre as bases do ecossistema .NET, aproveitando:

Microsoft.Extensions.AI: Define interfaces como IChatClient, que servem como padrão para mensagens de chat (ChatMessage, ChatRole), embora a SK implemente suas próprias abstrações (ex.: ChatHistory, IChatCompletionService).

Conectores: Usa bibliotecas como Microsoft.SemanticKernel.Connectors.OpenAI para se comunicar com serviços de IA. Por exemplo, o conector OpenAI pode ser configurado com um endpoint local do Ollama (http://localhost:11434/v1) ou com serviços na nuvem (ex.: Azure OpenAI).

Padrão Builder: O Kernel.CreateBuilder() permite configurar serviços de IA de forma modular, adicionando conectores (ex.: AddOpenAIChatCompletion, AddAzureOpenAIChatCompletion) e plugins.

Como os dois pacotes se relacionam ?

As duas bibliotecas não são diretamente dependentes uma da outra, mas estão alinhadas como partes complementares do mesmo ecossistema de IA da Microsoft.

Abstração Comum:

Microsoft.Extensions.AI define interfaces como IChatClient, que especifica métodos como CompleteAsync para interações de chat, e tipos como ChatMessage e ChatRole. Essa biblioteca estabelece um padrão para como o .NET deve interagir com serviços de IA, servindo como uma camada de baixo nível.

Microsoft.SemanticKernel implementa suas próprias abstrações (ex.: IChatCompletionService, ChatHistory), que são inspiradas, mas não diretamente baseadas em IChatClient. O SK foi projetado antes do lançamento de Microsoft.Extensions.AI e usa uma abordagem mais rica para gerenciar conversas e serviços.

Complementaridade:

As duas bibliotecas são complementares porque atendem a diferentes níveis de abstração e uso:

Microsoft.Extensions.AI é ideal para cenários simples onde você quer uma interface leve e genérica para chamar serviços de IA, sem a necessidade de orquestração avançada. Por exemplo, você pode usar IChatClient para enviar uma mensagem e obter uma resposta diretamente.

Microsoft.SemanticKernel é mais adequado para cenários complexos, como construir agentes de IA com memória, plugins, RAG ou multimodalidade. Ele encapsula Microsoft.Extensions.AI em alguns casos, mas adiciona funcionalidades como o kernel (um container de serviços) e suporte a conectores (ex.: OpenAI, Azure OpenAI).

Entretanto, elas são tecnicamente independentes, ou seja, você pode usar uma sem a outra. Por exemplo:

- Você pode usar apenas Microsoft.Extensions.AI para criar um cliente de chat básico sem depender do SK.
- Você pode usar o SK sem importar Microsoft.Extensions.AI, já que o SK tem suas próprias implementações (ex.: IChatCompletionService em vez de IChatClient).

No entanto, como parte do ecossistema .NET, a Microsoft está alinhando as duas para futura interoperabilidade. Por exemplo, futuras versões do SK podem adotar mais diretamente as interfaces de Microsoft.Extensions.AI para maior consistência.

Diferenças Práticas:

Microsoft.Extensions.AI:
  - Foco em simplicidade e padronização.
  - Menos recursos embutidos (ex.: sem suporte nativo a RAG ou Tool Calling).
  - Exemplo de uso: Um cliente de chat genérico que alterna entre provedores com mínima configuração.

Microsoft.SemanticKernel:
   - Foco em orquestração e extensibilidade.
   - Inclui recursos avançados como RAG, embeddings, e integração de plugins via [KernelFunction].
   - Exemplo de uso: Um assistente de IA que consulta documentos (RAG) e executa funções personalizadas (Tool Calling).

Em resumo, Microsoft.Extensions.AI fornece os blocos de construção básicos, enquanto o SK os utiliza e expande para criar soluções mais sofisticadas.

Aplicações Práticas

Um exemplo é a interface IChatClient, que permite o consumo de modelos de linguagem de diferentes provedores e o padrão builder - Kernel.CreateBuilder() - que permite configurar serviços de IA de forma modular.

Por exemplo, os desenvolvedores podem alternar entre um serviço Azure OpenAI e uma instalação Ollama local com o mínimo de alterações de código. Abaixo temos o código da classe Program em um projeto Console que usa o arquivo launchSettings.json para definir o ambiente:

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
// Configuração do Kernel do Semantic Kernel
var builder = Kernel.CreateBuilder();
// Verifica a variável de ambiente personalizada para determinar o ambiente
string appEnvironment = Environment.GetEnvironmentVariable("APP_ENVIRONMENT") ?? "Unknown";
Console.WriteLine($"APP_ENVIRONMENT: {appEnvironment}"); // Depuração
// Configuração do serviço de chat com base no ambiente
if (isDevelopment)
{
    // Configuração para Ollama local
    builder.AddOpenAIChatCompletion(
        modelId: "llama3.1:latest",
        endpoint: new Uri("http://localhost:11434/v1"),
        apiKey: null); // Ollama local não requer API key
}
else
{
    // Configuração para Azure OpenAI
    builder.AddAzureOpenAIChatCompletion(
        deploymentName: "seu-nome-usuario",
        endpoint: "https://seu-endpoint-azure",
        apiKey: "sua-apikey-azure");
}
var kernel = builder.Build();
// Obtém o serviço de chat completion
var chatService = kernel.GetRequiredService<IChatCompletionService>();
try
{
    // Configuração da mensagem do usuário
    var chatHistory = new ChatHistory();
    Console.WriteLine("\nTraduza o texto para o latin: 'Gosto de usar a IA com .NET'\n");
    chatHistory.AddUserMessage("Traduza o texto para o latim: Gosto de usar a IA com .NET");
    // Chamada assíncrona para completar a conversa
    var response = await chatService.GetChatMessageContentsAsync(chatHistory);
    // Exibição da resposta
    Console.WriteLine("Resposta do modelo: " + response[0].Content);
}
catch (Exception ex)
{
    Console.WriteLine($"Erro ao chamar o modelo: {ex.Message}");
}
Console.ReadKey();

Obs: Neste exemplo vou acessar o LLM llama31:latest instalado localmente no meu ambiente:

Executando o projeto irermos obter o seguinte resultado:

Entendendo o código:

- Microsoft.SemanticKernel: Fornece o núcleo do SK, incluindo o Kernel (um container de serviços de IA) e o builder para configurá-lo. Isso abstrai integrações com provedores de IA, alinhado com as interfaces de Microsoft.Extensions.AI.

- Microsoft.SemanticKernel.ChatCompletion: Define interfaces como IChatCompletionService (para completar conversas) e ChatHistory (para gerenciar histórico de mensagens). Isso é inspirado em IChatClient do Microsoft.Extensions.AI, mas otimizado para cenários como Tool Calling e RAG.

var builder = Kernel.CreateBuilder();
Cria um builder para o Kernel, que atua como um orquestrador de serviços de IA. O SK usa um padrão de injeção de dependências (similar ao ASP.NET Core), permitindo adicionar conectores para LLMs. Isso facilita a extensão para multimodalidade (ex.: processar imagens via modelos como GPT-4o) ou embeddings (ex.: converter texto em vetores para buscas vetoriais).

Adiciona o conector de chat completion ao builder:

- Para desenvolvimento: Usa Microsoft.SemanticKernel.Connectors.OpenAI configurado para Ollama (local, sem API key). O endpoint aponta para o servidor Ollama, e modelId especifica o modelo (atualizado para "llama3.1:latest" para melhor suporte a prompts em português).

- Para produção: Usa o conector Azure OpenAI, com deployment, endpoint e API key (substitua pelos valores reais).

GetRequiredService<IChatCompletionService>(): Obtém o serviço de chat do kernel. Essa interface abstrai chamadas a LLMs, suportando multimodalidade (ex.: adicionar imagens a ChatHistory para análise via modelos como GPT-4 Vision).

ChatHistory: Gerencia o contexto da conversa. Aqui, adicionamos uma mensagem de usuário (prompt em português). Em cenários avançados, isso pode incluir histórico para manter estado ou embeddings para RAG (ex.: buscar documentos relevantes via vetores gerados por modelos de embedding).

Mensagens no console: Melhoram a UX, exibindo o prompt e uma mensagem de espera.

GetChatMessageContentsAsync: Chama o LLM assincronamente para completar a conversa. Retorna uma lista de conteúdos.
 
Cores: Altera para verde antes da resposta e reseta para padrão, destacando a saída.

Bloco try-catch: Captura erros, como falhas de conexão com Ollama ou Azure.

Neste exemplo onde desenvolvemos um console que usa Ollama ou Azure OpenAI para tradução, o uso do Microsoft.SemanticKernel foi escolhido porque:

- Ele suporta conectores para Ollama (via AddOpenAIChatCompletion com endpoint local) e Azure OpenAI (via AddAzureOpenAIChatCompletion), alinhando-se com suas necessidades de alternância de ambiente.

- Oferece IChatCompletionService.GetChatMessageContentsAsync, que é mais robusto para gerenciar ChatHistory e suportar cenários futuros como multimodalidade ou RAG.

Se tivessemos usado apenas Microsoft.Extensions.AI, precisariamos implementar manualmente a lógica para conectar ao Ollama ou Azure OpenAI, o que seria mais trabalhoso para cenários avançados. 

Conclusão

Os pacotes Microsoft.Extensions.AI e Microsoft.SemanticKernel representam um avanço significativo na integração de serviços de IA dentro do ecossistema .NET. O fornecimento de abstrações unificadas e middleware capacita os desenvolvedores a construir aplicações de IA robustas, adaptáveis e preparadas para o futuro.

Quer esteja trabalhando com recursos de chat, embeddings ou tool calling, estes pacotes oferecem as ferramentas de que você precisa para ter sucesso no campo em rápida evolução da IA, e , com o avanço do ecossistema .NET para IA, espera-se que as duas bibliotecas se integrem mais profundamente, permitindo uma transição suave entre elas.

E estamos conversados...  

"Po

Referências:


José Carlos Macoratti