Ajustes conforme relatorio de testes 2026-08-27

This commit is contained in:
2026-08-29 10:03:42 -03:00
parent 1fd18531c0
commit 81f24d7357
699 changed files with 7989 additions and 2364 deletions

View File

@@ -0,0 +1,133 @@
import pytest
from agent_framework.guardrails.rails import CoherenceRail
@pytest.mark.asyncio
async def test_coer_delegates_to_enumerated_expected_input_contract_without_calling_llm():
rail = CoherenceRail()
decision = await rail.evaluate(
"ano",
{
"expected_input": {
"key": "resposta_usuario",
"allowed_values": ["SIM", "NAO"],
"normalize": "upper_strip",
"reprompt": "Não entendi. Responda sim ou não.",
}
},
)
assert decision.allowed is True
assert decision.code == "COER"
assert decision.metadata["mechanism"] == "expected_input_contract"
assert decision.metadata["delegated"] is True
@pytest.mark.asyncio
async def test_coer_without_expected_input_keeps_normal_classification(monkeypatch):
async def fake_classifier(*args, **kwargs):
return {"allowed": False, "label": "COER", "reason": "fala incompreensível"}
monkeypatch.setattr("agent_framework.guardrails.rails.classify_with_framework_llm", fake_classifier)
rail = CoherenceRail()
decision = await rail.evaluate("ano", {})
assert decision.allowed is False
assert decision.metadata["mechanism"] == "llm_rail"
@pytest.mark.asyncio
async def test_coer_emits_non_blocking_semantic_signal_for_opt_in_unmatched(monkeypatch):
async def fake_classifier(*args, **kwargs):
return {"allowed": True, "label": "OK", "reason": "fala coerente e substantiva"}
monkeypatch.setattr("agent_framework.guardrails.rails.classify_with_framework_llm", fake_classifier)
rail = CoherenceRail()
decision = await rail.evaluate(
"então tirando esses serviços o valor será 275, certo?",
{
"expected_input": {
"key": "resposta_usuario",
"allowed_values": ["SIM", "NAO"],
"normalize": "upper_strip",
"reprompt": "Não entendi. Responda sim ou não.",
"unmatched": {
"meaningful_input": {"action": "resume_as", "value": "NAO"}
},
}
},
)
assert decision.allowed is True
assert decision.metadata["mechanism"] == "expected_input_contract"
assert decision.metadata["semantic_coherent"] is True
assert decision.metadata["data"]["allowed"] is True
@pytest.mark.asyncio
async def test_coer_emits_incoherent_signal_without_blocking_when_unmatched_policy_exists(monkeypatch):
async def fake_classifier(*args, **kwargs):
return {"allowed": False, "label": "COER", "reason": "fala incompreensível"}
monkeypatch.setattr("agent_framework.guardrails.rails.classify_with_framework_llm", fake_classifier)
rail = CoherenceRail()
decision = await rail.evaluate(
"ano",
{
"expected_input": {
"key": "resposta_usuario",
"allowed_values": ["SIM", "NAO"],
"normalize": "upper_strip",
"reprompt": "Não entendi. Responda sim ou não.",
"unmatched": {
"meaningful_input": {"action": "resume_as", "value": "NAO"}
},
}
},
)
assert decision.allowed is True
assert decision.metadata["semantic_coherent"] is False
@pytest.mark.asyncio
async def test_coer_delegates_without_own_llm_when_semantic_classifier_is_configured(monkeypatch):
async def should_not_run(*args, **kwargs):
raise AssertionError("COER LLM should not run when expected_input semantic_classifier owns semantics")
monkeypatch.setattr("agent_framework.guardrails.rails.classify_with_framework_llm", should_not_run)
rail = CoherenceRail()
decision = await rail.evaluate(
"legal!",
{
"expected_input": {
"key": "resposta_usuario",
"allowed_values": ["SIM", "NAO"],
"normalize": "upper_strip",
"semantic_classifier": {
"enabled": True,
"prompt": "Classifique em {{ allowed_values }}",
},
}
},
)
assert decision.allowed is True
assert decision.metadata["mechanism"] == "expected_input_semantic_classifier"
assert decision.metadata["delegated"] is True
@pytest.mark.asyncio
async def test_coer_delegates_short_reply_to_active_transaction_parameter_contract(monkeypatch):
async def should_not_run(*args, **kwargs):
raise AssertionError("COER LLM must not own coherence while transaction parameters are being collected")
monkeypatch.setattr("agent_framework.guardrails.rails.classify_with_framework_llm", should_not_run)
rail = CoherenceRail()
decision = await rail.evaluate(
"Tamboro",
{
"transaction_status": "COLLECTING_PARAMETERS",
"missing_parameters": ["subject"],
"active_transaction": {"tool_name": "contestar_cobranca"},
},
)
assert decision.allowed is True
assert decision.metadata["mechanism"] == "transaction_parameter_contract"
assert decision.metadata["delegated"] is True
assert decision.metadata["missing_parameters"] == ["subject"]