IA serve para sortear? Use random no código e deixe o LLM interpretar

Ilustração de dados e números sendo sorteados ao lado de um ícone de inteligência artificial
Resposta rápida

Não. Um estudo de Harvard com 11 LLMs mostrou que, com uma chamada por número, 10 dos 11 modelos não passaram em nenhuma das 15 distribuições testadas. Temperature e seed também não garantem um sorteio justo. O caminho seguro é sortear no código (random, secrets ou crypto) e mandar só o resultado para o modelo interpretar.

Este guia é para quem tem um app, um bot ou uma automação que pede ao modelo para escolher um item da lista, sortear o vencedor de uma promoção ou embaralhar perguntas e cartas. A regra é uma só: o sorteio acontece no código, e a IA recebe o resultado pronto para interpretar ou redigir.

É o mesmo padrão do post de tarot com ChatGPT aqui do blog. Lá as cartas são tiradas fora da IA e o modelo faz só a leitura. Aqui a ideia sai do tarot e vira decisão de arquitetura para qualquer sistema que dependa de acaso.

Por que a resposta do LLM não serve como fonte de aleatoriedade

Pedir "escolha um aleatório" ao modelo não produz uma distribuição justa. Quem mostra isso é um estudo de Minda Zhao, Yilun Du e Mengyu Wang, de Harvard, publicado na ACL 2026. Eles testaram a amostragem probabilística nativa de 11 LLMs de fronteira em 15 distribuições estatísticas (arXiv).

Os resultados variam conforme o jeito de pedir.

  • Números em lote, vários na mesma resposta: a taxa mediana de aprovação nos testes estatísticos foi de 13% (Large Language Models Are Bad Dice Players).
  • Requisições independentes, com uma chamada por número: 10 de 11 modelos não passaram em nenhuma distribuição.

Esse segundo cenário é justamente o de um app que chama a API a cada sorteio. Então o formato mais comum em produção é também o que teve o pior resultado no estudo.

E tem uma consequência bem prática. Ao gerar questões de múltipla escolha, os modelos mostraram viés severo na posição da resposta correta, mesmo com instrução explícita para distribuir de forma uniforme (estudo completo).

A lição é direta: escrever "distribua de forma uniforme" no prompt não corrige o viés. Os próprios autores concluem que, quando a aplicação exige garantia de distribuição, ferramentas externas de aleatorização continuam indispensáveis.

Temperature e seed resolvem? O que dizem OpenAI e Anthropic

Não resolvem. Esses parâmetros mexem na variação e na reprodutibilidade da saída, e não transformam o modelo em um dado honesto.

Se liga no que cada documentação diz.

OpenAI e o parâmetro seed

O seed aparece no contexto da API Chat Completions, no cookbook de saídas reproduzíveis. A promessa é de saídas consistentes "em geral", não sempre.

A documentação de uso avançado explica que o sistema faz um esforço para amostrar de forma determinística (best effort), sem garantia. Ela recomenda acompanhar o campo system_fingerprint para detectar mudanças no backend. Mesmo com parâmetros e fingerprint iguais, ainda existe uma pequena chance de respostas diferentes.

Ou seja, o seed ajuda a repetir um resultado. Ele não faz o resultado ser justo.

Anthropic, temperature e o Claude Opus 4.7

A documentação do SDK oficial da Anthropic é explícita: mesmo com temperature 0.0, os resultados não são totalmente determinísticos (anthropic-sdk-ruby, MessageCreateParams#temperature). O guia de migração reforça que temperature 0 nunca garantiu respostas idênticas.

A partir do Claude Opus 4.7, há outra mudança. Definir temperature, top_p ou top_k com valor diferente do padrão retorna erro 400. A orientação da Anthropic é omitir esses parâmetros e guiar o comportamento pelo prompt (What’s new in Claude Opus 4.7).

Tome cuidado se o seu código antigo "ajustava a aleatoriedade" pela temperature: em modelos novos isso pode simplesmente quebrar a chamada.

Resumindo a seção: nenhum desses ajustes transforma o modelo em gerador de sorteio.

Como sortear no código e passar o resultado para o LLM

A arquitetura tem três etapas: o código sorteia, o resultado entra no prompt como dado fixo e o modelo só interpreta ou redige.

Pensa num apresentador de bingo. A máquina gira as bolas e ele só lê o número em voz alta e faz a graça. Ninguém pede para o apresentador inventar a bola 😀.

Bora ver na prática?

  1. Sorteie no código (Python). O módulo random resolve os três casos clássicos, conforme a documentação do Python.
    import random
    
    cartas = ["O Louco", "O Mago", "A Sacerdotisa", "A Imperatriz", "O Imperador"]
    
    # Escolher um item
    carta = random.choice(cartas)
    
    # Embaralhar a própria lista (altera a lista original)
    random.shuffle(cartas)
    
    # Tirar 3 itens sem repetição
    tiragem = random.sample(cartas, k=3)
    
    # Nova lista embaralhada, mantendo a original intacta
    embaralhada = random.sample(cartas, k=len(cartas))

    random.choice devolve um elemento de uma sequência não vazia. random.shuffle embaralha no lugar, ou seja, mexe na lista original. random.sample tira k elementos únicos, sem reposição, e com k=len(lista) devolve uma nova lista embaralhada.

    Erro comum deste passo: chamar random.choice com a lista vazia. Isso gera IndexError, então valide antes de sortear (por exemplo, quando a planilha de participantes chega sem linhas). Outro tropeço clássico é esperar que shuffle retorne a lista: ele altera a original e não devolve uma cópia.

  2. Se o app roda em Node.js ou no navegador, use a API de crypto. No Node.js, crypto.randomInt([min, ]max) retorna um inteiro entre min (inclusive) e max (exclusivo). A implementação evita o viés de módulo, e o intervalo precisa ser menor que 2**48 (Node.js docs).
    const { randomInt } = require('node:crypto');
    
    const participantes = ['[email protected]', '[email protected]', '[email protected]'];
    
    // Sortear um vencedor
    const vencedor = participantes[randomInt(participantes.length)];
    
    // Embaralhar uma cópia (Fisher-Yates)
    function embaralhar(lista) {
      const copia = [...lista];
      for (let atual = copia.length - 1; atual > 0; atual--) {
        const sorteado = randomInt(atual + 1);
        [copia[atual], copia[sorteado]] = [copia[sorteado], copia[atual]];
      }
      return copia;
    }

    No navegador, a regra é não usar Math.random() quando o sorteio importa. Ele não fornece números criptograficamente seguros, e a alternativa indicada é crypto.getRandomValues(), da Web Crypto API (MDN).

    function indiceAleatorio(n) {
      // Descarta valores acima do último múltiplo de n para não favorecer índices
      const limite = Math.floor(0x100000000 / n) * n;
      const buffer = new Uint32Array(1);
      do {
        crypto.getRandomValues(buffer);
      } while (buffer[0] >= limite);
      return buffer[0] % n;
    }
    
    const opcoes = ['Pizza', 'Sushi', 'Hambúrguer'];
    const escolhida = opcoes[indiceAleatorio(opcoes.length)];

    Erro comum deste passo: fazer valor % n direto com o número de getRandomValues. Isso recria o viés de módulo que o randomInt do Node evita, e é por isso que o exemplo descarta valores fora do limite.

  3. Passe o resultado como dado fixo no prompt. O modelo recebe o que já foi sorteado e uma instrução clara de que não pode mudar isso.
    prompt = f"""Você é um leitor de tarot.
    As cartas abaixo JÁ foram sorteadas pelo sistema, nesta ordem.
    Não troque, não reordene e não sorteie outras cartas.
    
    Cartas: {", ".join(tiragem)}
    
    Escreva uma interpretação curta para cada carta, na ordem recebida."""

    Depois você envia esse prompt ao modelo que já usa no seu projeto, do jeito de sempre.

    Erro comum deste passo: mandar a lista inteira e pedir "escolha três aleatoriamente" ou "embaralhe antes de responder". Aí o sorteio voltou para dentro do modelo, que é exatamente o que o estudo mostrou não funcionar.

  4. Confira se o modelo respeitou o sorteio. O resultado esperado é um texto que cita exatamente os itens sorteados, na ordem enviada. Como o sorteio está numa variável, dá para checar no próprio código se cada item aparece na resposta e registrar em log o que foi sorteado.

Erro comum deste passo: confiar no texto do modelo como registro oficial do resultado. O registro é a variável do código. A resposta da IA é só a redação em cima dele.

random ou secrets/crypto: qual usar em cada caso

Depende do que está em jogo. Se o sorteio só gera variedade, random atende. Se alguém ganha alguma coisa ou existe risco de manipulação, use secrets ou crypto.

A documentação do Python define random como gerador pseudoaleatório pensado para modelagem e simulação, e avisa que ele não deve ser usado para fins de segurança (random). Para isso existe o módulo secrets, que deve ser preferido nesses casos e oferece secrets.choice() (secrets).

CenárioO que usar
Tiragem de tarot, sugestão de receita, variação de texto, jogo casualrandom (Python)
Sorteio de prêmio ou vencedor em automaçãosecrets.choice (Python) ou crypto.randomInt (Node.js)
Embaralhar playlist ou fila de tarefasrandom.sample / random.shuffle ou Fisher-Yates com crypto.randomInt
Ordem das alternativas em quiz ou provaEmbaralhar no código antes de mandar ao modelo
Sorteio feito no front-endcrypto.getRandomValues, nunca Math.random

O tarot é o caso mais tranquilo: as cartas saem do código e o modelo cuida da leitura.

No sorteio de vencedor a régua sobe. Se a sua automação lê os inscritos de uma planilha e anuncia o ganhador, o sorteio precisa sair de secrets.choice ou crypto.randomInt. A IA só redige o anúncio, beleza?

O quiz é o caso que liga direto ao estudo de Harvard. Se você pede ao modelo para gerar questões e "variar a posição da correta", o viés posicional tende a aparecer mesmo com essa instrução. O jeito certo é o modelo gerar o enunciado e as alternativas, e o código embaralhar a ordem antes de exibir.

Conclusão

O próximo passo é uma busca no seu projeto. Procure nos prompts do app ou da automação por "escolha aleatória", "aleatoriamente", "sorteie", "embaralhe" ou "random", e anote cada lugar onde o modelo está decidindo algo que deveria ser acaso.

Para cada ocorrência, leve a decisão para o código com random, secrets ou crypto, conforme a tabela acima, e passe ao modelo só o resultado. Depois rode a checagem do passo 4 para confirmar que a resposta cita exatamente o que foi sorteado.

Perguntas frequentes

Esse problema de aleatoriedade ruim também vale para gerar senhas ou tokens com IA?

Sim, o mesmo princípio se aplica. Senha, token e chave de acesso não devem nascer de um pedido tipo "gere algo aleatório" para o modelo, e a geração precisa ficar com secrets no Python ou crypto no Node.js, nunca com a IA.

Essa técnica de sortear fora da IA funciona em outras linguagens além de Python e Node.js?

A lógica vale para qualquer stack, mesmo sem exemplo específico aqui: use o gerador de aleatoriedade seguro da própria linguagem, equivalente ao secrets do Python ou ao crypto do Node.js, e passe o resultado já pronto para o modelo interpretar.

Fontes consultadas

Consulta em .

Veja mais exemplos práticos no canal Hora de Codar. Se quiser aprofundar o contexto, veja Codex vs Antigravity: Mesmo App, Mesmo Prompt, Quem Ganha? (resultado improvável).

Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 30min

Blog | Mais populares