- Chatbots conversacionais de longo prazo têm dificuldade para refletir de forma confiável, nas respostas, o essencial de interações passadas mesmo com uma janela de contexto longa, e este estudo aborda uma forma de reduzir problemas de consistência usando memória por resumo recursivo
- O procedimento central consiste em criar uma memória inicial a partir de uma conversa curta e, sempre que uma sessão é adicionada, resumir a memória anterior e a nova conversa em conjunto para atualizá-la como a memória mais recente
- Métodos baseados em busca dependem de um mecanismo de busca capaz de encontrar com precisão as falas passadas necessárias, enquanto métodos existentes baseados em memória podem ter a qualidade das respostas prejudicada por informações antigas não atualizadas
- Em experimentos com LLMs públicos e fechados, como Llama, ChatGLM e OpenAI GPT-3.5-Turbo, tanto avaliações automáticas quanto humanas indicaram maior consistência em conversas longas do que abordagens anteriores
- A abordagem também pode ser usada junto com janelas de contexto longas ou LLMs aumentados por recuperação, tornando-se uma opção prática para lidar com contextos de conversa muito longos sem simplesmente aumentar indefinidamente o tamanho total da conversa
Só contexto longo não basta para memória de conversas de longo prazo
- LLMs como GPT-4 e ChatGPT conseguem conduzir conversas dinâmicas e contextuais sobre vários temas, mas em conversas de longo prazo podem perder informações anteriores e gerar respostas inconsistentes
- Mesmo que uma janela de contexto longa permita processar todo o histórico da conversa como entrada, a capacidade de entender interações passadas e integrar informações essenciais às respostas ainda é limitada
- Exemplos representativos em que é necessário lembrar conversas passadas incluem companheiros pessoais de IA e serviços auxiliares de saúde
- Um companheiro pessoal de IA precisa relembrar conversas anteriores para formar um relacionamento
- Um serviço auxiliar de saúde precisa considerar todo o histórico de perguntas do paciente para fornecer resultados de diagnóstico
- Em um exemplo do Multi-Session Chat Dataset, quando o usuário voltou a mencionar o tema anterior de “composição musical” cerca de 20 turnos depois, a versão ChatGPT gpt-turbo-3.5-0301 respondeu que era “um modelo de linguagem de IA sem uma profissão no sentido tradicional”, gerando uma resposta inconsistente com a persona anterior
Limitações das abordagens baseadas em busca e em memória
- As principais abordagens para reforçar a capacidade de conversas de longo prazo se dividem em métodos baseados em busca e métodos baseados em memória
- Métodos baseados em busca armazenam falas passadas em um repositório e usam um buscador para encontrar o histórico mais relacionado à conversa atual, utilizando-o na geração da resposta
- A limitação é que é difícil obter um buscador ideal que capture completamente o significado necessário para a conversa atual
- Métodos baseados em memória resumem conversas passadas com um modelo treinado separadamente ou um LLM poderoso, armazenando as informações essenciais
- Sem um mecanismo de atualização iterativa, informações antigas preservadas podem prejudicar diretamente a qualidade das respostas
- MemoChat reorganiza o histórico de conversas passadas por tópicos de cada falante e usa prompts para que o LLM faça buscas em uma memória estruturada durante a geração
- MemoryBank propõe um mecanismo de memória que primeiro cria resumos de cada sessão de conversa e depois os comprime em um resumo global
- Se a memória armazenada ficar completamente fixa, torna-se difícil garantir consistência com a conversa em andamento
Geração de memória atualizada recursivamente
- A abordagem proposta é um método simples em formato de plugin, em que o próprio LLM cria resumos e continua atualizando e revisando o contexto passado para armazenar informações em tempo real dos falantes
- O procedimento é composto por três etapas
- Um LLM generativo recebe um contexto curto de conversa como entrada e gera um resumo inicial
- Depois, a memória anterior é combinada com conversas subsequentes para continuar atualizando um novo resumo ou memória
- O chatbot usa a memória mais recente como referência principal para responder à conversa atual
- Como o resumo gerado é muito mais curto do que a conversa completa, é possível lidar com contextos muito longos ao longo de várias sessões sem aumentar de forma custosa o comprimento máximo de entrada
- Uma conversa de longo prazo é definida como um Multi-Session Dialogue composto por várias sessões
- Usa-se o conjunto de sessões passadas
S = {S1, S2, ..., SN}, o contexto de conversa da sessão atualCte a resposta corretart - O objetivo é gerar uma resposta relevante e altamente consistente com base nas sessões passadas e no contexto atual
- Usa-se o conjunto de sessões passadas
- A memória
Mié a memória disponível no momento em que a i-ésima sessão termina, e todo o processo é definido como um processo sequencial em que cada memória depende apenas da sessão atual e da memória anterior
Iteração da memória e geração de respostas
- A abordagem proposta atribui duas tarefas a um LLM arbitrário
- Iteração da memória: resumir recursivamente as informações essenciais de acordo com o fluxo de conversas de longo prazo
- Geração de respostas baseada em memória: combinar a memória mais recente com a conversa atual para gerar uma resposta adequada e consistente
- A iteração da memória é o processo de obter um resumo consistente e atualizado para uso pelo chatbot
- Alguns estudos anteriores atualizam a memória aplicando “operações rígidas” ao resumo, como replace, append e delete
- Esses métodos dependem de conversas de alta qualidade com rótulos de operação, prejudicam a consistência semântica do resumo e também não são adequados para gerenciamento de longo prazo
- A abordagem proposta insere o contexto da conversa e a memória anterior juntos para que o LLM gere recursivamente a memória ou o resumo
- Ao aproveitar o resumo anterior, o modelo consegue digerir melhor o contexto da conversa atual e criar uma memória de alta qualidade
- No exemplo, uma memória inicial é criada após a primeira sessão e, após a segunda sessão, uma nova informação de personalidade — “o bot entrou recentemente em uma nova academia aberta 24 horas” — é integrada à memória anterior
Resultados dos experimentos e aplicabilidade
- Os experimentos foram implementados com LLMs recentes públicos e fechados, como Llama, ChatGLM e OpenAI GPT-3.5-Turbo
- O desempenho em conversas de longo prazo foi superior ao de abordagens populares existentes tanto em avaliações automáticas quanto em avaliações humanas
- O estudo valida o efeito de usar memória explícita em conversas de longo prazo e mostra que a memória gerada pelo método proposto é mais fácil de ser digerida por LLMs
- Ao combinar aprendizado em contexto (ICL), a qualidade das respostas pode ser aumentada ainda mais
- Várias amostras no formato
(conversa, memória, resposta correta)são apresentadas ao LLM - Isso permite que o LLM use a memória gerada de forma mais flexível
- Várias amostras no formato
- No text-davinci-003, a pontuação BLEU melhorou cerca de +3%
- A abordagem proposta complementa LLMs com janelas de contexto longas, como GPT-3.5-Turbo-16k e LongLoRA-8k, e LLMs aumentados por recuperação, como LLM-BM25 e LLM-DPR
- O código público está disponível em qingyue2014/Rsum
1 comentários
Comentários do Hacker News
Toda forma de acumular memória no “espaço de texto” parece bastante gambiarra
Para preservar integralmente o significado do modelo, parece mais natural armazenar em um espaço denso de embeddings do que usar um procedimento remendado de regenerar resumos continuamente
Além disso, o modelo deveria ser treinado para reconhecer e utilizar memória e, se possível, seria melhor que aprendesse nesse tipo de configuração desde o início
No fim, você está mandando acrescentar mais uma palavra à conversa fornecida e, quando em algum momento ele emite um token de encerramento, a aplicação devolve o controle ao usuário
Acho que o espaço latente e o espaço de texto não são tão distantes quanto parecem. LLMs são bem obtusos, mas muito bons em falar; escrever código é parecido, então eles se saem bem, mas desmoronam em áreas que exigem pensamento abstrato real, como matemática
Esses hacks no espaço de texto de fato tendem a funcionar bem, e é por isso que prompts como “pense passo a passo” se tornaram comuns
LoRA está mais próximo da direção mencionada e é excelente para comprimir muita compreensão em pouquíssimos dados. Porém, ajustar pesos para uma única conversa ainda não é realista, então, para esse uso, estamos explorando o espaço de texto
Resumir algo na cabeça pode parecer “gambiarra”, mas acho que uma grande parte de como a memória funciona de fato é parecida com isso
https://news.northwestern.edu/stories/2012/09/your-memory-is...
Pelo que entendo, embeddings são essencialmente uma forma de compressão com perdas. Com um resumo em texto, pelo menos o agente pode verificar se esse resumo representa corretamente a informação original
No CodeRabbit, já usamos esse tipo de abordagem para revisões incrementais de PR e conversas no contexto de mudanças de código
Isso faz o bot parecer ter muito mais contexto do que realmente tem, e é um dos vários truques que usamos para escalar revisões de código por IA até PRs grandes, com mais de 100 arquivos
Para cada commit, resumimos o diff por arquivo, depois criamos um resumo dos resumos e o atualizamos incrementalmente sempre que commits são adicionados ao PR. Esse resumo dos resumos fica armazenado de forma oculta dentro de um comentário do PR e é usado ao revisar cada arquivo ou responder a perguntas do usuário
Parte do código é open source, e o prompt relacionado que usamos para resumo recursivo está aqui: https://github.com/coderabbitai/ai-pr-reviewer/blob/main/src...
[0]: coderabbit.ai
Se sim, também queria saber se já tentaram usar function calling em vez de fazer parsing de saída em texto livre
Se ainda estamos na fase de “código e scripts serão divulgados depois”, hoje em dia fica difícil acreditar em qualquer afirmação
Pode ser verdade ou pode ser conversa fiada, mas, se não houver uma forma barata de reproduzir o experimento, encaro esse tipo de artigo como algo que os autores escreveram para colocar no currículo
Na área de LLMs, esperei mais de seis meses por artigos que diziam “o código será divulgado depois”, mas não há sinal de que isso vá acontecer. Alguns artigos chegam a ser descarados a ponto de incluir links quebrados que levam a domínios estacionados
Já passou da hora de a comunidade reconhecer adequadamente essa prática de não divulgar código
Há algum tempo experimentei uma ideia parecida mexendo manualmente apenas nos prompts no painel da API; havia potencial, mas não parecia valer o custo da API. Provavelmente uma abordagem com embeddings vetoriais seja muito melhor
Como exemplo pessoal, na empresa temos milhares de “Briefings”, painéis presenciais de uma hora e, às vezes, de um dia inteiro
Conseguimos resumir cada briefing, e transcrições bagunçadas foram bem organizadas em um resumo de cinco parágrafos
A parte mais relevante é que classificamos cada briefing em uma relação 1:N por tema e subtema. Dezenas de briefings foram agrupados em temas, cerca de uma dúzia em subtemas, e testamos amplamente resumindo de novo subconjuntos dos resumos relacionados; com LLMs, os resultados foram muito bons
No início eu estava cético quanto a isso funcionar, mas funcionou muito bem. Se houvesse uma janela de contexto grande o bastante, não teríamos feito assim, mas felizmente isso não foi um problema
Acho que dividir o problema como em MapReduce funciona muito melhor do que enfiar tudo em uma janela de contexto enorme de 32k e tentar resolver de uma vez
Alguns meses atrás, testei criar uma memória por resumo recursivo com um modelo open source, e, quando implementada de forma ingênua, era comum ela ficar presa para sempre em um determinado assunto
Isso acontece porque certos fragmentos sobrevivem a todas as rodadas de resumo
É impossível reduzir qualquer bloco de texto a um bloco menor sem perder nenhuma informação
Se isso fosse possível, significaria que compressão infinita seria possível, e qualquer dataset poderia ser reduzido a 1 bit e depois restaurado perfeitamente. Mas isso não dá
Ao comprimir uma conversa em um resumo, alguma informação necessariamente desaparece. Por mais que você ajuste, dobre e use métodos inteligentes, fundamentalmente haverá perda de informação
Além disso, o processo é recursivo, então em algum momento você passa a resumir um conjunto de resumos, e aí também se perde certa quantidade de informação
Portanto, pode ajudar em casos triviais, mas colocar resumos recursivos no prompt parece bem tolo e, se você tentar fazer algo realmente útil, quase certamente não vai funcionar direito. Quando você não usa muito resumo recursivo, parece funcionar porque perde pouca informação; ao usar de verdade, é provável que os limites apareçam rapidamente
Quando se pensa em como a mente humana pode sair dos trilhos facilmente só por trauma ou pelo processo de desenvolvimento, dá para sentir como a ideia de uma IA parecida com humanos é carregada de esperança
O artigo é meio decepcionante. Praticamente não há detalhes sobre a técnica; só há uma tabela dizendo que a metodologia que eles usaram produz bons resultados
Sei que isso é comum na ciência hoje em dia, mas, do ponto de vista de um desenvolvedor que trabalha com LLMs, o artigo tem pouquíssimo valor. Claro, a reputação acadêmica dos autores deve subir um pouco, e parece bem provável que esse fosse o objetivo
Dá até vontade de escrever alguns artigos assim com alguém. Fico me perguntando quantos seriam necessários para colocar o cargo “ML researcher” no topo do currículo
Deveriam ter dedicado muito mais tempo aos exemplos e aos prompts
Escrevi algo parecido há algumas semanas, mas as pessoas estão simplificando demais a parte de resumo: https://news.ycombinator.com/item?id=37117515
O valor da memória de longo prazo tem nuances diferentes para cada caso de uso
Se você está criando um assistente doméstico, precisa identificar nomes com NER e entender que tom de voz aquela pessoa prefere ao enviar mensagens a ela, além de lugares e formas de deslocamento
Se você está criando um bot de suporte ao cliente, precisa identificar consultas que se transformaram em conversas longas ou consultas que levaram a um abandono repentino de carrinho
Só com um nível genérico de resumo já dá para fazer demos chamativas, mas, para criar um produto realmente útil hoje, é preciso ir um passo além
Não tenho muita certeza do que há de novo aqui
Resumo de memória de histórico de chat baseado em LLM já é uma técnica bem conhecida, implementada em muitos frameworks de LLM. Resumir a cada mensagem, como no artigo, vira um grande gargalo de desempenho e adiciona bastante latência ao loop do chat
Muitas implementações usam um buffer de tamanho fixo e resumem gradualmente conjuntos de memórias antigas que saem do buffer. Idealmente, isso também é processado fora do loop do chat
Sou um dos autores do Zep, um repositório open source de memória de longo prazo, e implementamos o resumo dessa forma
0: https://github.com/getzep/zep
https://github.com/paul-gauthier/aider/blob/main/aider/histo...
https://www.deeplearning.ai/short-courses/langchain-for-llm-...
Isso foge um pouco do artigo e da discussão, mas memória curta é de fato uma limitação real
Ainda assim, acho que a maioria das críticas às capacidades do GPT-4 se aplica igualmente, ou até mais fortemente, aos humanos
Em uma situação de teste de Turing reverso, não acho que uma pessoa viva conseguiria me convencer de que ela é o GPT-4. Só as respostas rápidas e organizadas do GPT-4 já superam as capacidades humanas
Mesmo que uma equipe humana tivesse 60 minutos para responder a cada pergunta, talvez fosse difícil acompanhar as respostas do GPT-4 a perguntas interessantes. Seria uma competição divertida
A implementação do artigo, na prática, anexa o texto de memória como parte do prompt
Fico me perguntando por que não usar um sistema de armazenamento e busca que não consuma tokens da janela de contexto. Por exemplo, ao armazenar, isto é, quando o prompt do usuário chega, os dados poderiam ser classificados automaticamente por tags; e, na busca, o LLM poderia disparar uma consulta filtrada por tags estimadas antes de responder
Tenho a intuição de que, mesmo com algumas regras iniciais hardcoded, como nomes ou estilos de tags, isso poderia produzir resultados bem bons