antonio leandro

ia generativa

Toolformer: Language Models Can Teach Themselves to Use Tools

paper · Timo Schick, Jane Dwivedi-Yu, Roberto Dessì, et al. ·

a tese

não precisa de anotação humana para ensinar um modelo a usar ferramenta: ele escreve chamadas de api no próprio corpus, executa, e fica só com as que reduzem a perplexidade do texto que vem depois

o que fica

  1. O critério de "chamada útil" é perplexidade, não julgamento humano: uma chamada de API só entra no treino se o resultado dela reduzir a loss dos tokens seguintes acima de um limiar.
  2. Toolformer, com 6,7 bilhões de parâmetros, supera GPT-3 (175 bilhões) em LAMA e nos benchmarks de matemática, mas continua atrás dele em question answering aberto: 48,8 contra 65,9 no TriviaQA.
  3. Usar ferramenta é habilidade que só emerge com escala: modelos abaixo de 775 milhões de parâmetros vão igual com e sem acesso às APIs.
  4. As chamadas são amostradas de forma independente umas das outras, então não existe nenhum exemplo de ferramenta encadeada no treino — e o modelo não aprende a encadear.
  5. O método é péssimo em eficiência de amostra: processar mais de um milhão de documentos rendeu só alguns milhares de chamadas úteis à calculadora.
  6. Treinar com as chamadas inseridas não degrada o modelo de linguagem: com as APIs desligadas, a perplexidade fica em 10,3 no WikiText, a mesma do baseline finetunado sem chamada nenhuma.

o problema

Um modelo de linguagem de bilhões de parâmetros erra 27 + 4 * 2. Uma calculadora de bolso não erra. O mesmo modelo não sabe que dia é hoje, inventa fatos com confiança e tropeça em idioma de baixo recurso — enquanto sistemas muito menores e mais burros resolvem cada uma dessas coisas com precisão. O paper chama isso de paradoxo e argumenta que escalar não conserta: data de hoje não está nos pesos, e nunca vai estar.

A saída óbvia é dar ferramenta ao modelo. O problema era como ensinar. As abordagens de 2022 se dividiam em duas: pagar anotação humana em volume (caro, e o que um humano acha útil não é necessariamente o que o modelo acha útil) ou montar um prompt few-shot para uma tarefa específica, em que já se sabe de antemão qual ferramenta usar. Nenhuma das duas serve para o caso que interessa: o usuário faz uma pergunta qualquer e o modelo decide sozinho se vale chamar alguma coisa, qual, e com que argumento.

a ideia

Deixe o modelo anotar o próprio corpus e use a perda como juiz.

Pegue um texto cru de pré-treino. Peça ao modelo, com um punhado de exemplos escritos à mão, que insira chamadas de API onde ele achar que cabem. Execute todas. Depois compare: prever o resto do texto ficou mais fácil com o resultado da chamada na frente, ou não? Se ficou, a chamada era útil e vira dado de treino. Se não ficou, joga fora. Nenhum humano opina sobre quais chamadas eram boas; o sinal é a própria loss do modelo.

O detalhe elegante é que o corpus final é o mesmo corpus original, só com chamadas intercaladas. O modelo é finetunado exatamente no texto que ele já viu, mais as anotações. Por isso ele não perde generalidade nem vira um modelo de tarefa.

como funciona

O pipeline tem três passos, para cada uma das cinco ferramentas (question answering via Atlas, busca na Wikipédia via BM25, calculadora com as quatro operações, calendário e tradução via NLLB de 600 milhões de parâmetros).

para cada texto x do corpus:
  # 1. amostrar
  posições = { i : p(<API> | prompt(x), x[:i]) > 0,05 }   # top 5
  para cada i: amostre até 5 chamadas candidatas c

  # 2. executar
  r = api(c)

  # 3. filtrar
  L+ = loss(x[i:] | prefixo = "[ api(args) -> r ]")
  L- = min( loss(x[i:]),  loss(x[i:] | prefixo = "[ api(args) ]") )
  mantém se L- - L+ >= 1,0

L- é o mínimo entre não chamar nada e chamar sem receber resposta — isso impede que a chamada passe no filtro só por ser um prefixo bonito. A loss é ponderada com decaimento linear (peso max(0, 1 - 0,2t)), para que a chamada caia perto de onde a informação serve, não vinte tokens antes.

Os tokens especiais são literalmente [, ] e ->. Nada de mexer no vocabulário. Na inferência, a decodificação segue normal até o modelo emitir ->; aí o processo é interrompido, a API é chamada de verdade, o resultado e o ] são inseridos, e a geração continua.

Uma correção prática: na avaliação, o modelo emite <API> se esse token estiver entre os 10 mais prováveis, não só se for o mais provável, e no máximo uma chamada por entrada.

o que isso custou

O truque do top-10 é onde o preço aparece. Com decodificação gulosa pura, o modelo chama API em 40,3% dos exemplos do T-REx — e é calibrado: ele chama justamente nos casos em que iria mal sem ajuda. Subindo para k igual a 10, a cobertura vai a 98,1% e o score sobe de 47,8 para 53,5, mas a calibração some. Compra-se cobertura com discernimento.

Os autores listam o resto sem enfeite. Não há encadeamento: as chamadas são amostradas independentemente, então não existe exemplo de usar a saída de uma ferramenta como entrada de outra. Não há interação: o modelo faz uma busca e engole o resultado, sem reformular a query nem navegar entre os resultados — e é exatamente isso que explica ficar atrás do GPT-3 em NQ e TriviaQA, já que o retriever devolve lixo com frequência. O método é sensível à formulação exata da entrada. E é caro: mais de um milhão de documentos para produzir 994 exemplos de calculadora no limiar padrão.

Duas ferramentas simplesmente não pegaram. O calendário é usado em 0,2% do TempLAMA — o ganho ali veio de busca e QA. No MLQA, a tradução é chamada em até 94,9% dos casos, mas o finetuning em CCNet degrada o modelo o suficiente para que Toolformer não bata o GPT-J puro de forma consistente. E o modelo nunca considera o custo computacional de chamar a ferramenta.

onde isso aparece hoje

A receita de gerar dado com o próprio modelo e filtrar por um critério automático virou padrão de bootstrapping. Mais visível ainda: as duas limitações que o paper declara — encadear ferramentas e interagir com elas em várias rodadas — são hoje a definição operacional de agente, e o loop de chamar, ler o resultado e decidir o próximo passo é o que as APIs de function calling expõem. O Toolformer resolveu a parte de decidir sozinho quando chamar; a parte de continuar chamando ficou para depois.

lido na íntegra por pipeline de llm, revisado por antonio leandro antes de publicar ·