Saltar para o conteúdo

Histórico de conversa

Uma conversa longa acaba por embater num muro intransponível: a janela de contexto do modelo. Tudo nesta página existe por causa desse muro, e a parte interessante é o que é atirado fora, o que é mantido e o que pode ser recuperado.

Não são tanto alternativas, mas sim uma escada, do mais barato ao mais caro.

Mecanismo Custo Mantém Perde
Elisão Nada Cada palavra da narrativa Resultados antigos de ferramentas sem incidentes
Descarte de imagens Nada O texto que as rodeia Capturas de ecrã antigas
Instantâneos Nada Cada palavra, como píxeis Legibilidade para um modelo sem visão
Resumo Uma chamada ao modelo Uma narrativa Os detalhes que não escolheu

A elisão e o descarte ocorrem primeiro porque são gratuitos e sem perdas naquilo que importa: eliminam volume que ninguém ia voltar a ler.

Um resumo é o único dos quatro que gasta uma chamada ao modelo e o único que decide por si o que era importante. Ambos são custos reais. A chamada é o mais interessante, por causa do momento em que acontece.

A compactação ocorre habitualmente antes do muro, com base num limite. Mas também ocorre de forma reativa, depois de o próprio fornecedor rejeitar um pedido por ser demasiado grande — a estimativa heurística subestimou aquilo que o fornecedor mediu na realidade. Nessa situação, um compactador que resume tem de fazer um pedido para reduzir o contexto, e o pedido que faz é precisamente aquele que acabou de transbordar.

A compactação por instantâneos renderiza o histórico descartado em páginas densas de glifos em píxeis e devolve-as como imagens.

A premissa é uma peculiaridade de faturação: um modelo com visão cobra por uma imagem uma tarifa fixa ou proporcional à área, que não tem nada a ver com o número de caracteres que ela contém. Doze mil caracteres de conversa descartada custam o equivalente a doze mil caracteres em tokens de texto. Os mesmos caracteres renderizados numa única página custam uma imagem.

O que faz valer a pena tê-lo, em vez de ser apenas engenhoso, é que não precisa de nenhuma chamada ao modelo, nenhuma chave e nenhuma rede. É a única estratégia sempre disponível durante a recuperação de um transbordo.

A forma da reconstrução é: início literal, meio em imagem, fim literal. O início é a tarefa e as restrições a que tudo o que vem a seguir se reporta; o fim é onde o trabalho está neste momento. O meio é o que menos se relê e o que mais custa.

Os instantâneos são novamente renderizados a partir do texto de origem retido em cada passagem, nunca a partir dos píxeis da passagem anterior. Converter uma imagem em imagem degrada os glifos uma geração por compactação, até que nada consiga lê-los.

Historicamente, todas as execuções do harness começavam com um histórico vazio e reconstruíam a continuidade a partir de um bloco <context> no prompt — um resumo da conversa, e não a conversa em si. Daí resultaram três consequências:

  • Retomar era recontar. O modelo nunca via o seu próprio raciocínio anterior nem os bytes reais que as suas ferramentas devolviam, apenas uma descrição deles.
  • O rebobinar morria com o processo. Um checkpoint é um índice na lista de mensagens ativas, por isso um reinício perdia todas as etiquetas que o modelo tinha definido.
  • Repetir não conseguia distinguir “nada a repetir” de “nada carregado”. Depois de um reinício, o turno falhado desaparece de qualquer forma do estado ativo.

Os três problemas são resolvidos ao persistir a transcrição. Esta é guardada em cada limite de turno e nunca a meio de um turno: um histórico capturado entre uma chamada a uma ferramenta e o seu resultado é um que nenhum fornecedor aceita, por isso uma falha nesse instante restaura o turno anterior, em vez de um meio turno que não pode ser reproduzido.

Uma execução retomada é reduzida às suas mensagens mais recentes, cortando num limite que não seja um resultado de ferramenta órfão — um resultado cuja chamada foi cortada é um pedido que os fornecedores rejeitam de imediato, e uma transcrição que não pode ser enviada é pior do que uma curta.

Cada mensagem registra a mensagem de que é continuação, e cada conversa nomeia a sua ponta de branch atual. Essa única decisão constitui a funcionalidade inteira.

Criar um branch não escreve nada. Apenas move o ponteiro. O caminho que deixou continua lá, por isso voltar atrás é outro movimento do ponteiro em vez de uma restauração — e editar um prompt para o executar de novo deixa de lhe custar a resposta com que estava a comparar.

Sem isso, todas as formas de voltar atrás têm de ocultar ou eliminar mensagens, e ocultar é uma mentira que o leitor seguinte não consegue desmascarar.

Branch Fork
O que acontece O ponteiro move-se O caminho é copiado
Para onde vai A mesma conversa Uma nova conversa
Custo Nada Uma cópia do branch

Um fork copia com ids novos, em vez de partilhar linhas. Duas conversas que partilhassem linhas mostrariam uma à outra as suas mensagens posteriores, que é precisamente a única coisa que um fork não pode fazer.

O par checkpoint / rewind dentro da execução marca um limite de turno limpo e regressa a ele depois de uma exploração, guardando um digest. Como os checkpoints são persistidos juntamente com a transcrição, uma etiqueta definida pelo modelo antes de um reinício ainda fica onde foi definida. Um checkpoint cujo alvo não sobreviveu a um corte é descartado, não ajustado — rebobinar “até à etiqueta” e aterrar noutro sítio é exatamente a falha que uma etiqueta existe para evitar.