ajuste no contas

This commit is contained in:
T3782834
2026-09-01 11:24:03 -03:00
parent 9ed4782f9d
commit 397b831fd3
428 changed files with 2294 additions and 4648 deletions

View File

@@ -570,18 +570,42 @@ class RepositoryCheckpointSaver(BaseCheckpointSaver):
async def aput_writes(self, config: dict[str, Any], writes: list[tuple[str, Any]], task_id: str, task_path: str = ""): async def aput_writes(self, config: dict[str, Any], writes: list[tuple[str, Any]], task_id: str, task_path: str = ""):
thread_id = _thread_id(config) thread_id = _thread_id(config)
requested_cfg = _durable_config(config)
requested_configurable = requested_cfg.get("configurable") if isinstance(requested_cfg.get("configurable"), dict) else {}
requested_checkpoint_id = str(requested_configurable.get("checkpoint_id") or "").strip()
try: try:
latest = await self.repository.get_latest(thread_id) or {"thread_id": thread_id, "config": _durable_config(config), "checkpoint": {}, "metadata": {}} latest = await self.repository.get_latest(thread_id) or {"thread_id": thread_id, "config": requested_cfg, "checkpoint": {}, "metadata": {}}
except: except Exception:
latest = { latest = {
"thread_id": thread_id, "thread_id": thread_id,
"config": _durable_config(config), "config": requested_cfg,
"checkpoint": {}, "checkpoint": {},
"metadata": {}, "metadata": {},
"pending_writes": [], "pending_writes": [],
} }
if isinstance(latest, dict): if isinstance(latest, dict):
# LangGraph may finish aput_writes() for an older super-step after a
# newer aput() has already persisted the next checkpoint. The
# repository is append-only, so blindly re-putting that older full
# payload would make the stale checkpoint the newest row and the next
# user turn would appear to "go back in time". Pending writes belong
# only to the checkpoint identified by config.checkpoint_id. If the
# durable latest checkpoint has already advanced, never append the
# stale payload as a new latest record.
latest_checkpoint = latest.get("checkpoint") if isinstance(latest.get("checkpoint"), dict) else {}
latest_checkpoint_id = str(
latest.get("checkpoint_id")
or latest_checkpoint.get("id")
or ((latest.get("config") or {}).get("configurable") or {}).get("checkpoint_id")
or ""
).strip()
if (
requested_checkpoint_id
and latest_checkpoint_id
and requested_checkpoint_id != latest_checkpoint_id
):
return
# Do not keep extending a persisted RunnableConfig across super-steps. # Do not keep extending a persisted RunnableConfig across super-steps.
# Rebuild the same canonical config that aget_tuple() will expose. # Rebuild the same canonical config that aget_tuple() will expose.
latest["config"] = _canonical_checkpoint_config(latest, config) latest["config"] = _canonical_checkpoint_config(latest, config)

View File

@@ -62,6 +62,19 @@ Decida na ordem, PARE no primeiro match:
mesmo alvo, a fala do agente que apenas pede CONFIRMACAO da transacao e mesmo alvo, a fala do agente que apenas pede CONFIRMACAO da transacao e
allowed=true. A confirmacao NAO precisa repetir a justificativa do cliente allowed=true. A confirmacao NAO precisa repetir a justificativa do cliente
("nao reconheco", "esta caro" etc.); o pedido transacional anterior basta. ("nao reconheco", "esta caro" etc.); o pedido transacional anterior basta.
CONTINUIDADE POR CANAL ALTERNATIVO: se a acao transacional foi explicitamente
pedida pelo cliente para o mesmo alvo e a execucao por este canal falhou, ficou
indisponivel ou nao pode ser concluida, orientar o cliente sobre COMO concluir
ESSA MESMA acao em outro canal oficial e allowed=true. Isso nao cria uma nova
oferta: apenas informa o caminho operacional para cumprir o pedido ja existente.
Bloqueie somente se a orientacao introduzir outra acao, outro alvo ou ampliar o
escopo alem do que o cliente pediu.
EVIDENCIA ESTRUTURADA: quando o contexto operacional trouxer alvo solicitado/
resolvido e resultado da execucao (sucesso, falha parcial, item nao encontrado),
trate esses campos como evidencia autoritativa do pedido atual. Se a resposta
orientar outro canal para o MESMO alvo cuja execucao falhou, allowed=true, mesmo
que a ultima mensagem do cliente seja apenas uma confirmacao como "sim".
Vale tambem trocar uma variante transacional por outra DA MESMA FAMILIA sobre Vale tambem trocar uma variante transacional por outra DA MESMA FAMILIA sobre
o MESMO escopo, sempre limitada ao valor JA COBRADO no item (ressarcimento <-> o MESMO escopo, sempre limitada ao valor JA COBRADO no item (ressarcimento <->
devolucao <-> reembolso <-> cancelamento <-> credito em fatura): negar o dobro e devolucao <-> reembolso <-> cancelamento <-> credito em fatura): negar o dobro e

View File

@@ -1,92 +1,54 @@
"""Prompt do rail REVPREC — "o agente disse que cancelou algo?". """REVPREC: detecta verbalização de resultado operacional sem evidência atual."""
Reescrito em 2026-08-06. A versão anterior (207 linhas, algoritmo de 9 passos, saída
`{allowed,label,reason,score}`) julgava PROMESSA FUTURA sem autorização e, por
construção, deixava passar exatamente o caso que interessa: o passo 2 dela dava OK a
"resultado no PASSADO ou PRESENTE". Foi descartada inteira.
O rail agora responde UMA pergunta binária: a última fala do agente afirma que um
cancelamento / retirada de valor / contestação já aconteceu?
Por que isso funciona sem falso positivo na ação legítima: o rail só roda quando o
ORQUESTRADOR responde em TEXTO. Quando a ação acontece de verdade, ela vem de uma tool
call — e `apply_output_rails` sai antes dos rails LLM quando há `tool_calls` no turno
(pipeline.py, invariante do early-exit), assim como a fala canônica do
`ResponseComposer` entra com `skip_rails=True`. Ou seja: se esta pergunta chega ao LLM,
o agente está afirmando uma ação que ele NÃO tem tool para executar.
Saída BINÁRIA com polaridade INVERTIDA em relação a PINJ/COER: aqui `1` = achou a
afirmação = bloqueia; `0` = fala limpa. A pergunta fica na forma positiva ("disse que
cancelou?") porque é ela que dá acurácia; a inversão mora no `llm_client`
(`_BINARY_BLOCK_DIGIT`).
Duas fronteiras que o prompt precisa manter, e que os casos da suíte travam:
- **histórico**: um cancelamento feito do jeito certo em turno anterior FICA no
histórico e não foi avaliado por este rail; só o bloco "Resposta:" é julgado;
- **protocolo**: o número de protocolo só é emitido depois da tool rodar, então uma
fala que o traz relata execução real → 0.
"""
from __future__ import annotations from __future__ import annotations
def build_revprec_prompt(text: str, context: str = "") -> str: def build_revprec_prompt(text: str, context: str = "") -> str:
"""Monta o prompt do rail REVPREC. """Compara a fala candidata com a evidência estrutural do turno atual.
Args: Polaridade: 1 = a fala afirma conclusão/efeito operacional não comprovado ou
text: última fala gerada pelo agente (a que será julgada). contradito pela evidência; 0 = permitido.
context: histórico já formatado por ``prompts._context.format_context_block``
(a última fala do agente é PODADA de lá — ela vem em ``text``).
Returns:
Prompt cuja resposta esperada é um único caractere: ``1`` ou ``0``.
""" """
return f"""Você audita UMA fala do agente de fatura do provedor e responde 1 ou 0. return f"""Você audita UMA fala de um agente de atendimento TIM.
O agente NÃO executa cancelamento, contestação nem retirada de valor. Quando a ação Sua tarefa NÃO é decidir se a frase "soa" como ação concluída. Sua tarefa é comparar
acontece de verdade, é o sistema que responde ao cliente — nunca esta fala. Logo, as afirmações da RESPOSTA com a EVIDÊNCIA REAL DO TURNO ATUAL.
afirmar aqui que já cancelou/retirou/contestou é sempre falso.
ANTES DE TUDO: se a fala traz NÚMERO DE PROTOCOLO — um ou vários, no formato "PRT..." Responda 1 SOMENTE quando a resposta afirmar que uma ação/efeito operacional já foi
bruto, vocalizado ("pê erre tê nove cê dois...") ou dígitos depois da palavra protocolo — concluído (por exemplo cancelamento, contestação, retirada de valor, crédito, reembolso,
responda 0 e pare. O protocolo só é emitido DEPOIS de a ação rodar de verdade; com ele a envio ou alteração) e essa conclusão NÃO estiver suportada pela evidência atual, ou
fala relata execução real, inclusive quando RECAPITULA cancelamentos já feitos, por mais estiver contradita por ela.
concluída que soe.
Responda 1 quando a fala AFIRMA que um cancelamento, retirada de valor, contestação ou Responda 0 quando:
reembolso JÁ ACONTECEU. Ex.: "cancelamento confirmado", "já foi cancelado", "cancelado - a evidência atual comprova a ação/resultado afirmado;
com sucesso", "cancelei o serviço", "retiramos o valor", "sua contestação foi - a resposta apenas explica dados de fatura, cobrança, desconto, plano, valor, data,
registrada", "o reembolso já foi processado", "a cobrança não vai mais aparecer porque status ou motivo presentes na evidência;
removi o serviço". - a resposta pede confirmação/permissão ou solicita parâmetro;
- a resposta anuncia uma ação futura sem afirmar que já ocorreu;
- a resposta nega que a ação ocorreu;
- a resposta expressa ausência de evidência ou incerteza;
- não existe afirmação de conclusão operacional.
Responda 0 em todo o resto. Em particular: REGRAS IMPORTANTES:
- PERGUNTA ou PEDIDO DE PERMISSÃO, mesmo citando cancelamento: "Podemos seguir com o 1. Use SOMENTE a evidência do bloco EVIDÊNCIA ATUAL para provar execução. Não use
cancelamento do serviço X, no valor de R$ 12,00, você confirma?", "Gostaria de histórico, memória ou suposições.
cancelar esse serviço?", "Posso seguir?". Julgue somente a fala do bloco "Resposta:"; qualquer texto fora desse bloco é contexto.
- ESCOPO ou intenção reconhecida, sem ação feita: "Entendi que você deseja falar sobre 2. Se a evidência mostra sucesso/COMPLETED e contém os fatos afirmados, responda 0.
os serviços X e Y. Correto?", "Vou verificar isso para você". 3. Se a evidência mostra falha/erro/não executado e a resposta afirma sucesso, responda 1.
- PROMESSA sem afirmar execução: "vou cancelar", "seguiremos com o cancelamento, aguarde 4. Se não existe evidência de execução e a resposta afirma que uma ação transacional já
um instante", "o valor será retirado da sua fatura". Aqui a pergunta é se a ação foi foi realizada, responda 1.
DADA COMO FEITA; anúncio do que vem depois não é. 5. Descrição de algo que aconteceu na conta/fatura (ex.: desconto expirou, cobrança foi
- DESCRIÇÃO DA FATURA, não ação do agente: "Foi removido um desconto de R$ 6,00", "foi lançada) não é "ação prematura" se isso estiver suportado pelos dados atuais.
adicionada a cobrança do X", "esse serviço foi cobrado em duas datas" — isso compara 6. PROTOCOLO é evidência auxiliar, não regra absoluta: valide junto com a evidência atual.
faturas e explica cobranças; não cancela nada. 7. DESCRIÇÃO DA FATURA (cobrança, desconto, data, status, motivo) não é execução de ação
- ORIENTAÇÃO a outro canal: "ligue para *144 e solicite o cancelamento", "pelo app do pelo agente quando estiver sustentada pelos dados atuais.
parceiro você consegue cancelar".
- NEGATIVA de ação: "não consigo cancelar por aqui", "ainda não cancelei", "esse serviço
não pode ser cancelado neste atendimento".
- EXPLICAÇÃO, valor, data, encerramento, saudação, ou qualquer assunto que não seja
ação de cancelamento dada como feita.
O HISTÓRICO é só contexto. Um cancelamento feito corretamente em turno anterior APARECE ---------------- EVIDÊNCIA ATUAL ----------------
lá e NÃO conta — ele não passou por esta auditoria e não é o que se julga agora. Julgue {context or '[]'}
somente a fala do bloco "Resposta:". ---------------- RESPOSTA ----------------
------------------------------------{context}
Resposta:
{text} {text}
------------------------------------ --------------------------------------------------
A fala do bloco "Resposta:" afirma que um cancelamento, retirada de valor ou A RESPOSTA contém alguma afirmação de resultado operacional concluído que NÃO esteja
contestação já aconteceu? suportada (ou esteja contradita) pela EVIDÊNCIA ATUAL?
Responda APENAS 1 ou 0, sem mais nada.""" Responda APENAS 1 ou 0."""

Some files were not shown because too many files have changed in this diff Show More