Automações com agentes de IA e Copilot Studio

(def instrutor {:nome "Cácio José da Costa Silva"
			    :empresa "Alura"
			    :cargo "Instrutor e pagodeiro nas horas vagas"})

1

Conceitos básicos, interface e building blocks

2

IA Generativa no Copilot Studio

3

Publicar, compartilhar e proteger agente

4

Laboratório

(outro momento)

Premissas

  • Esse workshop foi desenhado para citizen developers

  • "Tecniquês" vai ser evitado

  • Demonstrações práticas

Entendendo Tópicos

Tópicos

 Uma analogia simples

Custom topics

  • Invocados por FRASES
  • Podem ser criados

Tipos de tópicos

System topics

  • Invocados por Eventos
  • Podem ser alterados

Qual seu nome?

  • Chamo-me Fulano
  • Meu nome é Fulano
  • Fulano

Entidades

 Recebendo dados dos usuários

Fala de onde?

  • Brasília
  • Estou na capital
  • "Tô aqui no quadradinho"

Qual sua idade?

  • 41
  • Tenho 41
  • Quarenta e um

Condicionais e variáveis globais

(Com exemplo é melhor)

System topics

Mergulhando mais fundo

System topics

 Início da conversa (Conversation start)

  • Disparado quando o chat inicia

  • Dá ao usuário a mensagem introdutória
    • Dita o tom da conversa

    • Dar contexto ao usuário

  • Quick replies

    • Opção para selecionar tópicos mais rapidamente

  • ​Pode ser usado para inicializar variáveis (globais)

System topics

 Escalonar (Escalate)

  • Acionado quando o usuário deseja falar com um humano

    • Oferecer os telefones de contato

    • Quando não houver essa possibilidade, deve ser desabilitado

System topics

 Conversational boosting

  • Acionado como última tentativa de dar uma resposta ao usuário 

    • Nenhum outro tópico foi escolhido

    • Oferece resposta com base em IA generativa por padrão

System topics

 Fallback

  • Acionado quando nenhum tópico satisfaz a mensagem do usuário

    • Ideal para uma mensagem amigável quando não for possível ajudar

System topics

 Fim da conversa (End of conversation)

  • Acionado com redirect

    • Você quem invoca ele a partir de outro tópico

    • Não é inicializado por evento espontâneo

System topics

 Redefinir conversa (Reset conversation)

  • Também acionado com redirect

    • Limpa todas as variáveis

    • Finaliza todos os tópicos

    • Solicita ao usuário para iniciar uma nova conversa

System topics

 Se houver erro (On Error)

  • Acionado quando algum erro de processamento acontece no chatbot

    • Não aparece para o usuário, somente no teste

System topics

 Vários Tópicos Correspondentes e Entrar

  • Entrar

    • Acionado quando o chatbot precisa autenticar o usuário

  • ​Vários Tópicos correspondentes

    • Acionado quando a mensagem do usuário pode ser tratada por mais de um tópico

Incrementando com IA Generativa

Mão na massa...

Workshop

 Preparação do ambiente

  • Verificar acesso ao copilot studio
  • Disponibilizar atividade (https://github.com/cacio-costa/workshop-copilot-studio)

Reativo X Imperativo

 Mudando o modo de pensar

Imperativo ➡

Reativo ➡

Fluxo de dados reativo

 Operações em paralelo

Projeto Reactor

Core types

 Mono e Flux

public class ExemploDeCoreTypes {

    /**
     * Mono representa um fluxo de 0..1 elementos
     */
    public Mono<String> getMensagem() {
        return Mono.just("Olá, mundo reativo!");
    }


    /**
     * Flux representa um fluxo de 0..N elementos
     */
    public Flux<Integer> getFlux() {
        return Flux.range(1, 5);
    }
    
}

Operadores reativos comuns

 Map, FlatMap e Filter

public class OperadoresReativos {


    public Flux<String> processaDados() {
        return Flux.just(1, 2, 3, 4, 5)
       
               // `map` transforma um valor em outro
               .map(i -> i * 2) 
               
               // `filter` remove elementos que não passam no predicado
               .filter(i -> i > 5) 
               
                // `flatMap` mapeia e "achata" fluxos aninhados.
               .flatMap(i -> Flux.just("Número: " + i, "Potência: " + (i * i)));
    }
    
}

Operadores reativos comuns

 Zip

public class OperadoresReativos {

    // atributos e construtor


    public Mono<RelatorioDeInadimpletes> getCombinedData() {
    
        return Mono.zip(
            relatorioService.getQuantidadeDeInadimplementes(),
            relatorioService.getMontanteAReceber(),
            relatorioService.getClientesInadimplementes(),
            
            (quantidade, montante, clientes) -> 
            	new RelatorioDeInadimplentes (quantidade, montante, clientes)
        );
        
    }
    
    
}

Backpressure

 Lidando com altas cargas

@RestController
public class OperadoresReativos {

    // atributos e construtor


    @GetMapping(value = "/stream-data-drop", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<Data> fluxoComDrop() {
        return dataSource.getData()
            .limitRate(100) // Controle de backpressure
            .onBackpressureDrop(); // Descarta elementos que o cliente não conseguir processar
    }
    
    @GetMapping(value = "/stream-data-buffer", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<Data> fluxoComBuffer() {
        return dataSource.getData()
            .limitRate(100) // Controle de backpressure
            .onBackpressureBuffer(10); // Cria um buffer com 10 elementos
    }
    
    
}

Schedulers

 Concorrência simplificada

@RestController
public class SchedulersController {

    // atributos e construtor

    @GetMapping("/processo-paralelo")
    public Flux<Result> processoParalelo() {
        return Flux.range(1, 100)
            .parallel()
            .runOn(Schedulers.parallel())
            .map(this::processaItem)
            .sequential();
    }
    
    private void processaItem(Integer numero) {
        // processamento pesado...
    }
    
    
}

Immediate

Executa processamento na thread atual.

Single

Executa em uma única thread dedicada.

Parallel

Executa em um pool de threads paralelo.

Schedulers

 Tipos

Bounded Elastic

Cria threads sob demanda com um limite máximo.

Schedulers

 Combinando Schedulers

@RestController
public class SchedulersController {

    // atributos e construtor

    @GetMapping("/tarefa-intensa")
    public Flux<Result> tarefaIntensa() {
        return Flux.range(1, 100)
            .flatMap(i -> Mono.fromCallable(() -> executaComputacaoPesada(i))
                .subscribeOn(Schedulers.boundedElastic()))
            .publishOn(Schedulers.parallel());
    }

    private Result executaComputacaoPesada(int input) {
        // Simulação de uma tarefa pesada
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        return new Result(input, input * input);
    }
    
    
}

Tratamento de erro

 onErrorReturn

Flux.just("A", "B")
    .concatWith(Flux.error(new RuntimeException("Erro"))) // concatena fluxo de erro
    .onErrorReturn("Default") // retorna valor padrão em caso de erro
    .subscribe(
        valor -> System.out.println("Recebeu: " + valor),
        erro -> System.err.println("Erro: " + erro)
    );
    
// SAÍDA
Recebeu: A
Recebeu: B
Recebeu: Default

Tratamento de erro

 onErrorResume

Flux.just("A", "B")
    .concatWith(Flux.error(new RuntimeException("Erro")))
    .onErrorResume(e -> Flux.just("Fallback1", "Fallback2")) // altera para fluxo alternativo
    .subscribe(
        valor -> System.out.println("Recebeu: " + valor),
        erro -> System.err.println("Erro: " + erro)
    );
    
// SAÍDA
Recebeu: A
Recebeu: B
Recebeu: Fallback1
Recebeu: Fallback2

Tratamento de erro

 onErrorContinue

Flux.range(1, 5)
    .map(i -> {
        if (i == 3) {
            throw new RuntimeException("Erro");
        }

        return i;
    })
    .onErrorContinue((erro, item) ->
        System.err.println("Erro aconteceu no item " + item)
    )
    .subscribe(
        valor -> System.out.println("Recebeu: " + valor),
        erro -> System.err.println("Erro: " + erro)
    );
    
// SAÍDA
Received: 1
Received: 2
Received: 4
Received: 5
Erro aconteceu no item 3

Tratamento de erro

 Tratando erros específicos

Flux.just("A", "B")
    .concatWith(Flux.error(new RuntimeException("Erro")))
    .onErrorResume(IOException.class, e -> Flux.just("IO Fallback"))
    .onErrorResume(RuntimeException.class, e -> Flux.just("Runtime Fallback")) 
    .subscribe(
        valor -> System.out.println("Recebeu: " + valor),
        erro -> System.err.println("Erro: " + erro)
    );
    
// SAÍDA
Recebeu: A
Recebeu: B
Recebeu: Runtime Fallback

Spring WebFlux

Spring WebFlux VS Spring MVC

 Diferenças

Considerações finais

Obrigado

(def recursos {:linkedin      "/cacio-costa/"
			   :email         "cacio.costa@alura.com.br"
               :ig-grupo-qdqa "@grupoqdqa"})
Made with Slides.com