45 lines
1.5 KiB
Python
45 lines
1.5 KiB
Python
"""Testes do contrato de saída do rail OOS.
|
|
|
|
O `label` ("IN_SCOPE"/"OUT_OF_SCOPE") saiu do prompt em 2026-08-05: nenhum
|
|
consumidor de produção o lia (a decisão usa `allowed` + `code`, fixado no
|
|
pipeline) e ele era gerado a cada turno. O `reason` passou a vir VAZIO quando
|
|
`allowed=true`, como no FRASEOLOGIA — descrever por que algo está DENTRO do
|
|
escopo não é lido por ninguém.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
import pytest
|
|
|
|
os.environ.setdefault("USE_MOCK_LLM", "true")
|
|
|
|
from agent_framework.guardrails.calibrated.llm_rails import out_of_scope
|
|
from agent_framework.guardrails.calibrated.prompts.out_of_scope import build_oos_prompt
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _force_mock(monkeypatch):
|
|
monkeypatch.setenv("USE_MOCK_LLM", "true")
|
|
|
|
|
|
def test_prompt_oos_nao_pede_mais_label():
|
|
prompt = build_oos_prompt("Posso ajudar com sua fatura?")
|
|
assert '"label"' not in prompt
|
|
assert "IN_SCOPE" not in prompt.split("Responda APENAS JSON valido:")[-1]
|
|
|
|
|
|
def test_prompt_oos_exige_reason_vazio_quando_allowed():
|
|
prompt = build_oos_prompt("Posso ajudar com sua fatura?")
|
|
contrato = prompt.split("Responda APENAS JSON valido:")[-1]
|
|
assert "se allowed=true: string vazia" in contrato
|
|
# e os exemplos de IN_SCOPE seguem a mesma regra
|
|
assert '{"allowed": true, "reason": ""}' in prompt
|
|
|
|
|
|
def test_oos_rail_devolve_shape_esperado():
|
|
r = out_of_scope("Posso te ajudar com mais alguma dúvida sobre a fatura?")
|
|
assert r.code == "OOS"
|
|
assert r.mechanism == "llm_supervisor"
|
|
assert isinstance(r.allowed, bool)
|