mirror of
https://github.com/hoshikawa2/nemo_guardrails_configuration.git
synced 2026-07-09 17:04:20 +00:00
Funcional
This commit is contained in:
@@ -859,8 +859,7 @@ Já o código **app_nemo.py** utiliza o framework **Nemo Guardrails** para ilust
|
|||||||
python -m src.app_nemo
|
python -m src.app_nemo
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
## 12. Mapeamento da planilha para implementação
|
## 12. Mapeamento da planilha para implementação
|
||||||
|
|
||||||
|
|||||||
43
nemo_guardrails_tracing_project/config/config.py
Normal file
43
nemo_guardrails_tracing_project/config/config.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
from nemoguardrails import LLMRails, RailsConfig
|
||||||
|
from src.actions import (
|
||||||
|
mask_pii_action,
|
||||||
|
detectar_toxicidade_action,
|
||||||
|
detectar_out_of_scope_action,
|
||||||
|
validar_alcada_action,
|
||||||
|
verbalizacao_prematura_action,
|
||||||
|
validar_groundedness_action,
|
||||||
|
supervisor_vas_avulso_action,
|
||||||
|
enforce_compliance_anatel_action,
|
||||||
|
calcular_tcr_action,
|
||||||
|
detectar_fallback_action,
|
||||||
|
registrar_violacao_action,
|
||||||
|
validar_consistencia_historica_action,
|
||||||
|
contabilizar_tokens_action,
|
||||||
|
calcular_eficiencia_nlu_action,
|
||||||
|
calcular_eficiencia_nlu_action,
|
||||||
|
detectar_loop_action,
|
||||||
|
medir_tamanho_mensagem_action,
|
||||||
|
calcular_precisao_revocacao_action,
|
||||||
|
avaliar_acuracia_semantica_action
|
||||||
|
)
|
||||||
|
def init(app: LLMRails):
|
||||||
|
|
||||||
|
app.register_action(mask_pii_action)
|
||||||
|
app.register_action(detectar_toxicidade_action)
|
||||||
|
app.register_action(detectar_out_of_scope_action)
|
||||||
|
app.register_action(validar_alcada_action)
|
||||||
|
app.register_action(verbalizacao_prematura_action)
|
||||||
|
app.register_action(validar_groundedness_action)
|
||||||
|
app.register_action(supervisor_vas_avulso_action)
|
||||||
|
app.register_action(enforce_compliance_anatel_action)
|
||||||
|
app.register_action(calcular_tcr_action)
|
||||||
|
app.register_action(detectar_fallback_action)
|
||||||
|
app.register_action(registrar_violacao_action)
|
||||||
|
app.register_action(validar_consistencia_historica_action)
|
||||||
|
app.register_action(contabilizar_tokens_action)
|
||||||
|
app.register_action(calcular_eficiencia_nlu_action)
|
||||||
|
app.register_action(calcular_eficiencia_nlu_action)
|
||||||
|
app.register_action(detectar_loop_action)
|
||||||
|
app.register_action(medir_tamanho_mensagem_action)
|
||||||
|
app.register_action(calcular_precisao_revocacao_action)
|
||||||
|
app.register_action(avaliar_acuracia_semantica_action)
|
||||||
@@ -1,11 +1,27 @@
|
|||||||
colang_version: "1.0"
|
|
||||||
|
|
||||||
models:
|
models:
|
||||||
- type: main
|
- type: main
|
||||||
engine: openai
|
engine: openai
|
||||||
model: gpt-5
|
model: gpt-5
|
||||||
|
api_key_env_var: OPENAI_API_KEY
|
||||||
|
parameters:
|
||||||
|
temperature: 0
|
||||||
|
base_url: http://127.0.0.1:8051/v1
|
||||||
|
max_tokens: 50 # 🔥 evita respostas longas do LLM
|
||||||
|
|
||||||
|
# 🔥 usado apenas se você chamar explicitamente no flow
|
||||||
|
- type: self_check_input
|
||||||
|
engine: openai
|
||||||
|
model: openai.gpt-oss-120b
|
||||||
|
api_key_env_var: OPENAI_API_KEY
|
||||||
|
parameters:
|
||||||
|
temperature: 0
|
||||||
|
base_url: http://127.0.0.1:8051/v1
|
||||||
|
|
||||||
|
|
||||||
rails:
|
rails:
|
||||||
input:
|
input:
|
||||||
flows:
|
flows:
|
||||||
- main
|
- check_input_terms
|
||||||
|
output:
|
||||||
|
flows:
|
||||||
|
- check_output_terms
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
define user express input
|
|
||||||
$input_text
|
|
||||||
|
|
||||||
define flow main
|
|
||||||
user express input
|
|
||||||
|
|
||||||
execute executar_pipeline_validacoes
|
|
||||||
|
|
||||||
bot say $nemo_response
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
pytest>=8.0.0
|
pytest>=8.0.0
|
||||||
pyyaml>=6.0.1
|
pyyaml>=6.0.1
|
||||||
openai>=1.0.0
|
openai>=1.0.0
|
||||||
nemoguardrails>=0.9.0
|
nemoguardrails>=0.21.0
|
||||||
opentelemetry-api>=1.20.0
|
opentelemetry-api>=1.20.0
|
||||||
opentelemetry-sdk>=1.20.0
|
opentelemetry-sdk>=1.20.0
|
||||||
opentelemetry-exporter-otlp>=1.20.0
|
opentelemetry-exporter-otlp>=1.20.0
|
||||||
|
|||||||
@@ -1,150 +1,284 @@
|
|||||||
# src/actions.py
|
from typing import Optional
|
||||||
|
from nemoguardrails.actions import action
|
||||||
import json
|
from .deterministic_rails import (
|
||||||
import uuid
|
mask_pii,
|
||||||
|
validar_alcada,
|
||||||
|
enforce_compliance_anatel,
|
||||||
|
calcular_tcr,
|
||||||
|
detectar_fallback,
|
||||||
|
registrar_violacao,
|
||||||
|
validar_consistencia_historica,
|
||||||
|
contabilizar_tokens,
|
||||||
|
calcular_eficiencia_nlu,
|
||||||
|
detectar_no_match_rag,
|
||||||
|
detectar_loop,
|
||||||
|
medir_tamanho_mensagem,
|
||||||
|
calcular_precisao_revocacao,
|
||||||
|
avaliar_acuracia_semantica,
|
||||||
|
)
|
||||||
from .llm_rails import (
|
from .llm_rails import (
|
||||||
detectar_toxicidade,
|
detectar_toxicidade,
|
||||||
detectar_out_of_scope,
|
detectar_out_of_scope,
|
||||||
verbalizacao_prematura,
|
verbalizacao_prematura,
|
||||||
validar_groundedness,
|
validar_groundedness,
|
||||||
|
supervisor_vas_avulso,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .deterministic_rails import validar_alcada
|
|
||||||
|
|
||||||
try:
|
|
||||||
from .judges import avaliar_qualidade_resposta
|
|
||||||
except Exception:
|
|
||||||
avaliar_qualidade_resposta = None
|
|
||||||
|
|
||||||
|
|
||||||
PIPELINE_RESULTS = {}
|
|
||||||
|
|
||||||
|
|
||||||
def extrair_payload(context: dict) -> dict:
|
|
||||||
try:
|
|
||||||
messages = context.get("messages", [])
|
|
||||||
content = messages[-1]["content"]
|
|
||||||
return json.loads(content)
|
|
||||||
except Exception:
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
def add_trace(trace, label, result):
|
|
||||||
trace.append({
|
|
||||||
"rail": label,
|
|
||||||
"allowed": result.allowed,
|
|
||||||
"reason": result.reason,
|
|
||||||
"code": getattr(result, "code", label),
|
|
||||||
"mechanism": getattr(result, "mechanism", ""),
|
|
||||||
"data": getattr(result, "data", {}),
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
def executar_pipeline_validacoes(context: dict):
|
|
||||||
print("🔥🔥🔥 ACTION FOI EXECUTADA")
|
|
||||||
payload = extrair_payload(context)
|
|
||||||
|
|
||||||
request_id = payload.get("request_id") or str(uuid.uuid4())
|
|
||||||
input_text = payload.get("input_text", "")
|
|
||||||
ctx = payload.get("context", {}) or {}
|
|
||||||
|
|
||||||
trace = []
|
|
||||||
failures = []
|
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# INPUT RAILS - LLM
|
# HELPERS
|
||||||
# =========================
|
# =========================
|
||||||
|
|
||||||
r_tox = detectar_toxicidade(input_text)
|
def get_payload(context: Optional[dict]) -> dict:
|
||||||
add_trace(trace, "TOX", r_tox)
|
return (context or {}).get("payload", {})
|
||||||
if not r_tox.allowed:
|
|
||||||
failures.append(("TOX", r_tox.reason))
|
|
||||||
|
|
||||||
r_oos = detectar_out_of_scope(input_text)
|
|
||||||
add_trace(trace, "OOS", r_oos)
|
|
||||||
if not r_oos.allowed:
|
|
||||||
failures.append(("OOS", r_oos.reason))
|
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# BUSINESS RAIL - DETERMINISTIC
|
# ACTIONS
|
||||||
# =========================
|
# =========================
|
||||||
|
|
||||||
valor = ctx.get("ajuste_valor")
|
@action(is_system_action=True)
|
||||||
r_adj = validar_alcada(valor)
|
async def mask_pii_action(context: Optional[dict] = None, **kwargs):
|
||||||
add_trace(trace, "ADJ", r_adj)
|
print("🔥 MSK")
|
||||||
if not r_adj.allowed:
|
|
||||||
failures.append(("ADJ", r_adj.reason))
|
|
||||||
|
|
||||||
# =========================
|
payload = get_payload(context)
|
||||||
# LLM RESPONSE
|
input_text = payload.get("input_text") or context.get("user_message", "")
|
||||||
# =========================
|
|
||||||
|
|
||||||
final_response = ctx.get("resposta_llm", "")
|
result = mask_pii(input_text)
|
||||||
|
|
||||||
trace.append({
|
if context is not None:
|
||||||
"step": "LLM",
|
context["text"] = getattr(result, "sanitized_text", input_text)
|
||||||
"allowed": True,
|
|
||||||
"input": input_text,
|
|
||||||
"output_preview": final_response[:200],
|
|
||||||
"mechanism": "provided_response_or_proxy",
|
|
||||||
})
|
|
||||||
|
|
||||||
# =========================
|
return result
|
||||||
# OUTPUT RAILS - LLM
|
|
||||||
# =========================
|
|
||||||
|
|
||||||
r_revprec = verbalizacao_prematura(final_response, ctx)
|
|
||||||
add_trace(trace, "REVPREC", r_revprec)
|
|
||||||
if not r_revprec.allowed:
|
|
||||||
failures.append(("REVPREC", r_revprec.reason))
|
|
||||||
|
|
||||||
r_gnd = validar_groundedness(final_response, ctx)
|
# -------------------------
|
||||||
add_trace(trace, "GND", r_gnd)
|
|
||||||
if not r_gnd.allowed:
|
|
||||||
failures.append(("GND", r_gnd.reason))
|
|
||||||
|
|
||||||
# =========================
|
@action(is_system_action=True)
|
||||||
# OPTIONAL JUDGE / CMP
|
async def detectar_toxicidade_action(context: Optional[dict] = None, **kwargs):
|
||||||
# =========================
|
print("🔥 TOX")
|
||||||
|
|
||||||
if avaliar_qualidade_resposta is not None:
|
text = context.get("text") or context.get("user_message", "")
|
||||||
r_cmp = avaliar_qualidade_resposta(input_text, final_response)
|
|
||||||
add_trace(trace, "CMP", r_cmp)
|
|
||||||
if not r_cmp.allowed:
|
|
||||||
failures.append(("CMP", r_cmp.reason))
|
|
||||||
else:
|
|
||||||
trace.append({
|
|
||||||
"rail": "CMP",
|
|
||||||
"allowed": True,
|
|
||||||
"reason": "CMP não configurado",
|
|
||||||
"mechanism": "skipped",
|
|
||||||
"data": {},
|
|
||||||
})
|
|
||||||
|
|
||||||
# =========================
|
result = detectar_toxicidade(text)
|
||||||
# FINAL DECISION
|
|
||||||
# =========================
|
|
||||||
|
|
||||||
blocked = len(failures) > 0
|
return result
|
||||||
|
|
||||||
if blocked:
|
|
||||||
first_code, first_reason = failures[0]
|
|
||||||
nemo_response = f"BLOCKED:{first_code} - {first_reason}"
|
|
||||||
else:
|
|
||||||
nemo_response = final_response
|
|
||||||
|
|
||||||
result = {
|
# -------------------------
|
||||||
"allowed": not blocked,
|
|
||||||
"label": "CONFORME" if not blocked else "PROBLEMA",
|
@action(is_system_action=True)
|
||||||
"response": final_response,
|
async def detectar_out_of_scope_action(context: Optional[dict] = None, **kwargs):
|
||||||
"reason": nemo_response if blocked else "",
|
print("🔥 OOS")
|
||||||
"failures": failures,
|
|
||||||
"trace": trace,
|
text = context.get("text") or context.get("user_message", "")
|
||||||
}
|
|
||||||
|
result = detectar_out_of_scope(text)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
# -------------------------
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def validar_alcada_action(context: Optional[dict] = None, **kwargs):
|
||||||
|
print("🔥 ADJ")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
ctx = payload.get("context", {})
|
||||||
|
|
||||||
|
valor = ctx.get("ajuste_valor", 0)
|
||||||
|
|
||||||
|
result = validar_alcada(valor)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
# -------------------------
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def verbalizacao_prematura_action(context: Optional[dict] = None, **kwargs):
|
||||||
|
print("🔥 REVPREC")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
ctx = payload.get("context", {})
|
||||||
|
|
||||||
|
resposta = ctx.get("resposta_llm", "")
|
||||||
|
|
||||||
|
result = verbalizacao_prematura(resposta, ctx)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
# -------------------------
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def validar_groundedness_action(context: Optional[dict] = None, **kwargs):
|
||||||
|
print("🔥 GND")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
ctx = payload.get("context", {})
|
||||||
|
|
||||||
|
resposta = ctx.get("resposta_llm", "")
|
||||||
|
|
||||||
|
result = validar_groundedness(resposta, ctx)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
# -------------------------
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def supervisor_vas_avulso_action(context: Optional[dict] = None, **kwargs):
|
||||||
|
print("🔥 REVPREC_SUP")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
|
||||||
|
result = supervisor_vas_avulso(payload)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def enforce_compliance_anatel_action(context=None, **kwargs):
|
||||||
|
print("🔥 CMP")
|
||||||
|
|
||||||
|
text = context.get("text") or context.get("user_message", "")
|
||||||
|
payload = get_payload(context)
|
||||||
|
ctx = payload.get("context", {})
|
||||||
|
|
||||||
|
result = enforce_compliance_anatel(text, ctx)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def calcular_tcr_action(context=None, **kwargs):
|
||||||
|
print("🔥 TCR")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
status = payload.get("context", {}).get("status", "")
|
||||||
|
|
||||||
|
result = calcular_tcr(status)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def detectar_fallback_action(context=None, **kwargs):
|
||||||
|
print("🔥 FALLBACK")
|
||||||
|
|
||||||
|
text = context.get("text") or context.get("user_message", "")
|
||||||
|
|
||||||
|
result = detectar_fallback(text)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def registrar_violacao_action(context=None, **kwargs):
|
||||||
|
print("🔥 VIOL")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
agent_id = payload.get("agent_id", "unknown")
|
||||||
|
code = payload.get("violation_code", "UNKNOWN")
|
||||||
|
|
||||||
|
result = registrar_violacao(agent_id, code)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def validar_consistencia_historica_action(context=None, **kwargs):
|
||||||
|
print("🔥 HIST")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
ctx = payload.get("context", {})
|
||||||
|
|
||||||
|
result = validar_consistencia_historica(ctx)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def contabilizar_tokens_action(context=None, **kwargs):
|
||||||
|
print("🔥 PMPTK")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
prompt = payload.get("prompt_tokens", 0)
|
||||||
|
completion = payload.get("completion_tokens", 0)
|
||||||
|
|
||||||
|
result = contabilizar_tokens(prompt, completion)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def calcular_eficiencia_nlu_action(context=None, **kwargs):
|
||||||
|
print("🔥 EFIC")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
ctx = payload.get("context", {})
|
||||||
|
|
||||||
|
result = calcular_eficiencia_nlu(
|
||||||
|
ctx.get("chunks_retornados", 0),
|
||||||
|
ctx.get("chunks_utilizados", 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def detectar_no_match_rag_action(context=None, **kwargs):
|
||||||
|
print("🔥 NO-M")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
ctx = payload.get("context", {})
|
||||||
|
|
||||||
|
result = detectar_no_match_rag(
|
||||||
|
ctx.get("chunks", []),
|
||||||
|
ctx.get("resposta_llm", "")
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def detectar_loop_action(context=None, **kwargs):
|
||||||
|
print("🔥 VLOOP")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
mensagens = payload.get("context", {}).get("mensagens", [])
|
||||||
|
|
||||||
|
result = detectar_loop(mensagens)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def medir_tamanho_mensagem_action(context=None, **kwargs):
|
||||||
|
print("🔥 MSIZE")
|
||||||
|
|
||||||
|
text = context.get("text") or context.get("user_message", "")
|
||||||
|
|
||||||
|
result = medir_tamanho_mensagem(text)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def calcular_precisao_revocacao_action(context=None, **kwargs):
|
||||||
|
print("🔥 REVPREC_METRIC")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
ctx = payload.get("context", {})
|
||||||
|
|
||||||
|
result = calcular_precisao_revocacao(
|
||||||
|
ctx.get("y_true", []),
|
||||||
|
ctx.get("y_pred", [])
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@action(is_system_action=True)
|
||||||
|
async def avaliar_acuracia_semantica_action(context=None, **kwargs):
|
||||||
|
print("🔥 SEMAC")
|
||||||
|
|
||||||
|
payload = get_payload(context)
|
||||||
|
ctx = payload.get("context", {})
|
||||||
|
|
||||||
|
result = avaliar_acuracia_semantica(
|
||||||
|
ctx.get("audio_transcrito", ""),
|
||||||
|
ctx.get("referencia_humana", "")
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
PIPELINE_RESULTS[request_id] = result
|
|
||||||
|
|
||||||
return {
|
|
||||||
"nemo_response": nemo_response
|
|
||||||
}
|
|
||||||
@@ -1,133 +1,47 @@
|
|||||||
import json
|
#https://docs.nvidia.com/nemo/guardrails/latest/configure-rails/actions/index.html
|
||||||
import uuid
|
#https://docs.nvidia.com/nemo/guardrails/latest/configure-rails/actions/registering-actions.html
|
||||||
|
#https://docs.nvidia.com/nemo/guardrails/latest/observability/logging/index.html
|
||||||
|
|
||||||
from nemoguardrails import LLMRails, RailsConfig
|
from nemoguardrails import LLMRails, RailsConfig
|
||||||
|
|
||||||
from src.actions import executar_pipeline_validacoes, PIPELINE_RESULTS
|
|
||||||
|
|
||||||
|
|
||||||
def build_rails():
|
|
||||||
config = RailsConfig.from_path("./config")
|
config = RailsConfig.from_path("./config")
|
||||||
rails = LLMRails(config)
|
rails = LLMRails(config)
|
||||||
|
|
||||||
rails.register_action(
|
def extract_return_values(response):
|
||||||
executar_pipeline_validacoes,
|
results = []
|
||||||
"executar_pipeline_validacoes"
|
|
||||||
)
|
|
||||||
|
|
||||||
return rails
|
log = response.log
|
||||||
|
|
||||||
|
for rail in log.activated_rails:
|
||||||
rails = build_rails()
|
for action in rail.executed_actions:
|
||||||
|
rv = action.return_value
|
||||||
|
if rv is not None:
|
||||||
def executar_atendimento(user_input: str, context: dict):
|
results.append({
|
||||||
|
"action": action.action_name,
|
||||||
request_id = str(uuid.uuid4())
|
"allowed": getattr(rv, "allowed", None),
|
||||||
|
"reason": getattr(rv, "reason", None),
|
||||||
payload = {
|
"sanitized_text": getattr(rv, "sanitized_text", None),
|
||||||
"request_id": request_id,
|
"code": getattr(rv, "code", None),
|
||||||
"input_text": user_input,
|
"mechanism": getattr(rv, "mechanism", None),
|
||||||
"context": context or {},
|
"data": getattr(rv, "data", None)
|
||||||
}
|
|
||||||
|
|
||||||
# 🔥 chama direto seu pipeline
|
|
||||||
executar_pipeline_validacoes({
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": json.dumps(payload)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
|
|
||||||
result = PIPELINE_RESULTS.pop(request_id, None)
|
return results
|
||||||
|
|
||||||
return result
|
MESSAGE = "Meu CPF é 169.323.728-86"
|
||||||
|
|
||||||
|
response = rails.generate(
|
||||||
if __name__ == "__main__":
|
messages=[{"role": "user", "content": MESSAGE}],
|
||||||
|
options={
|
||||||
def rodar_teste(nome, user_input, context):
|
"output_vars": ["triggered_input_rail", "relevant_chunks"],
|
||||||
print("\n" + "="*60)
|
"log": {
|
||||||
print(f"🧪 TESTE: {nome}")
|
"activated_rails": True,
|
||||||
print("-"*60)
|
"llm_calls": True
|
||||||
print("INPUT:", user_input)
|
}
|
||||||
print("CONTEXT:", context)
|
|
||||||
|
|
||||||
result = executar_atendimento(user_input, context)
|
|
||||||
|
|
||||||
print("\n📌 RESULTADO FINAL:")
|
|
||||||
print(result)
|
|
||||||
|
|
||||||
print("\n🔍 TRACE:")
|
|
||||||
for step in result.get("trace", []):
|
|
||||||
print(step)
|
|
||||||
|
|
||||||
print("="*60)
|
|
||||||
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# ✅ TESTE 1 - OK (CONFORME)
|
|
||||||
# =========================
|
|
||||||
rodar_teste(
|
|
||||||
"OK - Cancelamento válido",
|
|
||||||
"quero cancelar VAS",
|
|
||||||
{
|
|
||||||
"ajuste_valor": 20,
|
|
||||||
"resposta_llm": "Cancelamento realizado com sucesso."
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
feedback = extract_return_values(response)
|
||||||
|
|
||||||
# =========================
|
for f in feedback:
|
||||||
# ❌ TESTE 2 - TOXICIDADE
|
print(f)
|
||||||
# =========================
|
|
||||||
rodar_teste(
|
|
||||||
"TOX - Linguagem ofensiva",
|
|
||||||
"quero cancelar VAS seu lixo",
|
|
||||||
{
|
|
||||||
"ajuste_valor": 20,
|
|
||||||
"resposta_llm": "Cancelamento realizado."
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# ❌ TESTE 3 - ALÇADA
|
|
||||||
# =========================
|
|
||||||
rodar_teste(
|
|
||||||
"ADJ - Valor acima da alçada",
|
|
||||||
"quero cancelar VAS",
|
|
||||||
{
|
|
||||||
"ajuste_valor": 2000,
|
|
||||||
"resposta_llm": "Cancelamento realizado."
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# ❌ TESTE 4 - GROUNDEDNESS
|
|
||||||
# =========================
|
|
||||||
rodar_teste(
|
|
||||||
"GND - Resposta não confiável",
|
|
||||||
"quero cancelar VAS",
|
|
||||||
{
|
|
||||||
"ajuste_valor": 20,
|
|
||||||
"resposta_llm": "O cancelamento ativa cashback infinito e crédito ilimitado."
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# ⚠️ TESTE 5 - MÚLTIPLOS PROBLEMAS
|
|
||||||
# =========================
|
|
||||||
rodar_teste(
|
|
||||||
"MULTI - TOX + ADJ + GND",
|
|
||||||
"quero cancelar VAS seu inútil",
|
|
||||||
{
|
|
||||||
"ajuste_valor": 5000,
|
|
||||||
"resposta_llm": "Você ganha benefícios ilimitados com esse cancelamento."
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Texto:
|
|||||||
{text}
|
{text}
|
||||||
|
|
||||||
Classifique como:
|
Classifique como:
|
||||||
- TOXICO
|
- TOXICO: Apenas se encontrar palavras ofensivas ou condenatórias
|
||||||
- NORMAL
|
- NORMAL
|
||||||
|
|
||||||
Responda JSON:
|
Responda JSON:
|
||||||
|
|||||||
Reference in New Issue
Block a user