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: DefaultTratamento 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: Fallback2Tratamento 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 3Tratamento 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 FallbackSpring 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"})Copy of Automações com Agentes e Copilot Studio
By cacio-costa
Copy of Automações com Agentes e Copilot Studio
- 3