O Hermes para de adivinhar o tamanho do seu contexto: ancoragem de usage alinha os limiares de compressão com números reais


Sua sessão chega ao turno 40 e está tudo bem — então, do nada, aparece um aviso de “contexto longo demais, comprimindo”, mesmo você estando longe do limite da janela. Ou um dia a API lança um erro 413 dizendo que a requisição é grande demais, enquanto a conversa claramente não é tão longa assim. Os dois cenários costumavam ser comuns no Hermes, e compartilham uma única causa raiz: o Hermes estava adivinhando o tamanho do seu contexto — reestimando o transcript inteiro turno após turno com heurísticas como chars/4 e imagens fixas de 1500 tokens, deixando o erro se acumular conforme o histórico crescia. A mudança mesclada em 28 de agosto (PR #97206) arranca essa raiz: a contabilização de contexto agora ancora no usage reportado pelo provider, e a janela de estimativa encolhe de “a conversa inteira” para “mensagens anexadas desde a última resposta”.

Antes: estimativa do transcript inteiro, erro em bola de neve

Cada resposta de provider na verdade carrega um relatório de usage preciso: usage.prompt_tokens (exatamente quantos tokens essa requisição enviou, incluindo system prompt, schemas de ferramentas e histórico completo) e usage.completion_tokens (quantos foram gerados). O fornecedor do modelo conta isso ele mesmo — essa é a verdade real.

Mas o Hermes antigo quase não usava isso. Toda vez que precisava checar o tamanho do contexto, ele reestimava a sessão inteira com heurísticas: caracteres ASCII divididos por 4, 1500 tokens fixos por imagem, regras de densidade CJK… A estimativa era boa no início da sessão, mas conforme o histórico crescia, o erro se acumulava. Algumas sessões eram superestimadas — comprimidas antes mesmo de bater no limiar; outras subestimadas — a requisição estourava o limite do provider e tomava 413. As issues #89938 e #88960 são exemplos típicos dessa classe “estimativa-vs-realidade”.

Novo mecanismo: ancoragem de usage, janela de erro reduzida a um turno

O núcleo do PR #97206 é uma fórmula:

current context tokens =
  last response's usage.prompt_tokens
  + last response's usage.completion_tokens
  + estimate(ONLY messages appended since that response)

Em outras palavras: o tamanho real da conversa inteira vem direto dos números do provider; apenas o punhado de mensagens adicionadas desde a última resposta precisa ser estimado. A janela de erro encolhe de “o transcript inteiro” para “um turno” — e ela se autocorrige a cada resposta, porque o valor real é o ponto de partida, nunca algo que a estimativa precisa perseguir.

A âncora é capturada em exatamente um lugar: o bloco de usage logo após context_compressor.update_from_response() no loop principal da conversa (capture_usage_anchor), atualizado a cada resposta. Os limiares de compressão e a lógica de recuperação de 413 passam todos a usar esse número ancorado.

Correções complementares: recuperação de 413 conta bytes

A mesma onda traz correções complementares (#97197 e outras): a recuperação de 413 costumava medir o tamanho da requisição em tokens estimados — agora mede bytes reais, porque o julgamento de 413 do provider é baseado no tamanho do payload HTTP, e nenhuma estimativa de tokens converte corretamente para bytes. O compressor agora também realmente libera os bytes ocupados por imagens históricas durante a compactação (#97160), então a recuperação de 413 não é “passar raspando” mas “liberar espaço de verdade”.

O que isso significa para você

  • Menos compressões surpresa: as checagens de limiar se alinham com números reais, e sessões deixam de ficar “virtualmente inchadas” e comprimidas cedo demais;
  • Menos 413s: as checagens de tamanho de requisição passam de estimativas para contagem de bytes, e sessões longas deixam de morrer aleatoriamente com “payload muito grande”;
  • /context honesto: os números que você vê batem com os números da sua fatura do provider — o que você vê é real.

O mantenedor Teknium foi direto: “Estou realmente cansado de ficarmos estimando tokens. Parem de estimar coisas.” Essa onda é essa frase, transformada em código.

Essas mudanças foram mescladas em 28 de agosto e atualmente vivem no main upstream, ainda sem tag de release. Elas entram em vigor automaticamente assim que você rodar hermes update para uma build que as contém.

Leitura adicional