Code: Guardrails fracos no chatbot e como reduzir conteúdo de risco

Um chatbot em produção é como um atendente novo que fala rápido, nunca cansa e atende todo mundo ao mesmo tempo. O detalhe é que ele também pode ser “convencido” a dizer coisas que a empresa jamais colocaria num FAQ: instruções perigosas, conteúdo inadequado, incentivo à autolesão, discurso de ódio, ou até vazamento acidental de dados. Guardrails fracos quase nunca parecem um problema no dia 1 — eles aparecem no dia em que alguém testa o limite ou quando um usuário comum tropeça num tema sensível e o sistema responde sem freio.

A boa notícia: reduzir risco não exige “censurar tudo”. Exige projetar o fluxo com três travas simples e consistentes: filtrar entrada, limitar saída e ter uma rota segura quando o conteúdo passa do limite. Um exemplo prático é usar recursos de moderação disponíveis em APIs de modelos (como a API da OpenAI) para detectar conteúdo potencialmente nocivo e orientar a resposta do sistema.

AS-IS — chama o modelo e devolve a resposta “como vier”

No AS-IS, o chatbot simplesmente encaminha o texto do usuário para o modelo e imprime a resposta. Sem checagem de conteúdo, sem limite de tokens, sem fallback, sem trilha clara do que aconteceu.

# AS-IS (Python): chatbot “cru” sem filtros nem limites reais

from openai import OpenAI
client = OpenAI()

def chat_as_is(user_text: str) -> str:
    resp = client.responses.create(
        model="gpt-4.1-mini",
        input=user_text,
    )
    return resp.output_text

O problema desse desenho é que ele assume que “bom senso” vai emergir sempre. Em produção, isso falha: usuários tentam burlar instruções (“ignore suas regras”), pedem conteúdo perigoso, inserem instruções maliciosas em textos colados, ou levam a conversa para temas sensíveis.

TO-BE — filtra entrada, limita saída e modera a resposta antes de exibir

No TO-BE, o chatbot opera como um sistema governável:

  • Modera a entrada (bloqueia ou redireciona pedidos claramente inadequados).
  • Limita tamanho de entrada e de saída (reduz chance de abuso e também custo).
  • Modera a saída (se o modelo “escapar”, a resposta não vai para o usuário).
  • Define respostas seguras (recusar com orientação alternativa; ou escalar para humano quando necessário).
  • Registra uma trilha simples (o suficiente para auditar e corrigir sem debate infinito).
# TO-BE (Python): guardrails práticos com moderação de entrada/saída + limites + fallback
# Exemplo usando a API da OpenAI como referência de implementação.

from openai import OpenAI
from typing import Tuple, Dict, Any
import time
import uuid

client = OpenAI()

MOD_MODEL = "omni-moderation-latest"
CHAT_MODEL = "gpt-4.1-mini"

def moderate(text: str) -> Tuple[bool, Dict[str, Any]]:
    m = client.moderations.create(
        model=MOD_MODEL,
        input=text
    )
    flagged = bool(m.results[0].flagged)
    return (not flagged), {"flagged": flagged, "categories": m.results[0].categories}

def safe_refusal() -> str:
    return (
        "Não dá para ajudar com esse tipo de pedido. "
        "Se você descrever o objetivo de forma segura (ex.: prevenção, proteção, bem-estar), eu ajudo com alternativas."
    )

def chat_to_be(user_text: str, user_id: str = "anon") -> str:
    request_id = f"cb_{uuid.uuid4().hex}"
    started = time.time()

    user_text = (user_text or "").strip()

    # 1) Limite de entrada (evita abuso e custo)
    if len(user_text) > 4000:
        return "A mensagem ficou muito longa. Resuma em poucas linhas e tente de novo."

    # 2) Moderação de entrada
    ok_in, in_details = moderate(user_text)
    if not ok_in:
        print("[CHAT_AUDIT]", {
            "request_id": request_id,
            "user_id": user_id,
            "stage": "blocked_input",
            "moderation": in_details,
        })
        return safe_refusal()

    # 3) Chamada ao modelo com limites e instruções defensivas
    resp = client.responses.create(
        model=CHAT_MODEL,
        input=[
            {"role": "system", "content": (
                "Responder de forma útil e segura. "
                "Se houver pedido perigoso, ilegal, sexual inadequado, autolesão ou ódio, recusar e oferecer alternativa segura. "
                "Não inventar dados pessoais nem instruções operacionais sensíveis."
            )},
            {"role": "user", "content": user_text},
        ],
        max_output_tokens=350,
    )
    answer = resp.output_text or ""

    # 4) Moderação de saída (segunda trava)
    ok_out, out_details = moderate(answer)
    if not ok_out:
        print("[CHAT_AUDIT]", {
            "request_id": request_id,
            "user_id": user_id,
            "stage": "blocked_output",
            "moderation": out_details,
        })
        return safe_refusal()

    # 5) Trilha mínima (sem armazenar texto sensível inteiro)
    print("[CHAT_AUDIT]", {
        "request_id": request_id,
        "user_id": user_id,
        "stage": "served",
        "latency_ms": int((time.time() - started) * 1000),
        "input_len": len(user_text),
        "output_len": len(answer),
        "in_flagged": in_details["flagged"],
        "out_flagged": out_details["flagged"],
    })

    return answer

Antes, o chatbot operava na confiança. Agora, ele opera em mecanismos: se a entrada é problemática, não entra; se a saída escapa, não sai; e a conversa tem um caminho seguro quando chega em temas de risco.

Análise — reduzir risco é trocar “confiança” por mecanismos

Guardrails fracos normalmente significam uma aposta: “o usuário não vai tentar nada estranho” e “o modelo sempre vai entender o contexto”. Em produção, essa aposta não escala.

A virada de jogo é pragmática:

  • consistência: o sistema responde do mesmo jeito em casos de risco (recusa curta + alternativa segura);
  • controle de cauda: limites e moderação pegam justamente os casos que viram incidente;
  • correção rápida: trilha simples para investigar e ajustar sem guerra interna.

Se quiser evoluir, o próximo passo natural é sair do “bloqueia ou libera” e ter rotas: responder normalmente, responder com cuidado (tom e conteúdo restritos), recusar, ou escalar para humano — sempre com o mesmo padrão operacional.

Veja também: