paint-brush
LLMs de chamada de função: combinando SLIMs e DRAGON para melhor desempenho de RAGpor@shanglun
2,168 leituras
2,168 leituras

LLMs de chamada de função: combinando SLIMs e DRAGON para melhor desempenho de RAG

por Shanglun Wang12m2024/03/29
Read on Terminal Reader

Muito longo; Para ler

Apesar da enorme energia empreendedora investida nos LLMs, a maioria das aplicações de alto perfil ainda são limitadas pelo seu foco em interfaces semelhantes a chat.
featured image - LLMs de chamada de função: combinando SLIMs e DRAGON para melhor desempenho de RAG
Shanglun Wang HackerNoon profile picture
0-item
1-item

Em 2024, não faltarão aplicativos baseados em LLM. Grandes empresas de tecnologia como Microsoft e Google estão lançando versões cada vez mais poderosas de seus principais modelos ChatGPT e Gemini, e players especializados como a Anthropic estão promovendo ofertas concorrentes com integrações adicionais. No mundo do LLM aplicado, empresas e até governos estão experimentando aplicativos de chat para diversos contextos.


Apesar da enorme energia empreendedora investida nos LLMs, a maioria das aplicações de alto perfil ainda são limitadas pelo seu foco em interfaces semelhantes a chat que recebem e retornam texto legível por humanos. Isto é compreensível - afinal, um dos desenvolvimentos mais interessantes dos LLMs é a capacidade de compreender e gerar linguagem humana, permitindo uma interface de usuário conversacional. No entanto, as interfaces de chat ignoram outro caso de uso muito importante para LLMs – o processamento de texto como uma etapa intermediária em um pipeline de dados maior.


Hoje exploraremos esse caso de uso e veremos como os LLMs podem ser úteis como parte de um pipeline de dados, não apenas como gerador de linguagem natural.

LLMs de chamada de função

Para usar LLMs como parte de um pipeline de dados, precisamos alterar o formato de saída do LLM – em vez de gerar parágrafos para humanos lerem, o modelo precisa gerar algo que os computadores possam ler. Normalmente, isso significa saída estruturada em um formato de dados como JSON ou instruções em uma linguagem de programação como Python ou SQL. Esses formatos de saída são muito menos tolerantes do que a linguagem natural, já que a falta de aspas ou colchetes pode travar todo o pipeline. Portanto, precisaremos contar com métodos e recursos especializados que foram desenvolvidos para dar suporte a este caso de uso. Esses recursos são chamados coletivamente de chamada de função, uma vez que a saída tende a chamar funções ou ser consumida em chamadas de função.


Antes de nos aprofundarmos nesses métodos, vamos primeiro explorar um pouco mais profundamente por que os recursos de chamada de função foram desenvolvidos.

Casos de uso


Conectando-se a serviços externos

O caso de uso original e mais direto para chamada de função é a conexão com serviços externos. Quando a OpenAI lançou originalmente o GPT-4, ela também atualizou a API com um recurso que permitia ao usuário fornecer ao modelo um conjunto de funções no estilo python que o modelo poderia chamar para atingir seus objetivos. O modelo poderia, por exemplo, ser informado de que pode chamar uma função externa para calcular o preço de um título complexo. A partir dessas informações, o modelo seria capaz de escrever um código que calculasse o valor de uma carteira composta por esses títulos, sem a necessidade de possuir conhecimento especializado em precificação de títulos.


Chamar funções no estilo python é apenas a ponta do iceberg. Uma vez comprovada a importância da chamada de função no mercado, OpenAI e outros provedores de LLM começaram a oferecer suporte a outros formatos de saída, como JSON ou SQL. O importante era que esses modelos produzissem resultados legíveis por máquina, que pudessem ser lidos de forma confiável por outros processos.


Leitores astutos podem reconhecer que fizemos algo semelhante em artigos anteriores, usando LLM para gerar dados de treinamento , SQL ou JSON . Nestes artigos , conseguimos isso usando engenharia imediata e verificação de saída, mas agora que a chamada de função é um recurso amplamente suportado, podemos fazer isso mais facilmente contando com esses recursos em nível de modelo.


Encadeando LLMs


A chamada de função criou novas possibilidades para aplicativos multi-LLM, e logo os desenvolvedores estavam experimentando o encadeamento de LLMs para criar sistemas sofisticados. Alguns desses sistemas ficaram conhecidos como agentes , que podiam pesquisar na web de forma independente, coletar novos dados e chamar outro LLM com as novas informações. Esses pipelines são capazes de surpreendente autonomia e de resolver problemas sofisticados com muito pouca contribuição, embora ainda existam limitações, como custos de API e salvaguardas comportamentais, que impedem que os agentes sejam amplamente adotados.


Usando LLM como entrada e processamento intermediário


Outro caso de uso para LLMs de chamada de função é o processamento de dados de entrada e intermediários. LLMs podem ser usados para analisar entradas não estruturadas em dados estruturados que podem ser usados para processamento downstream. Embora muitas dessas tarefas tendam a ser relegadas às tecnologias “tradicionais” de PNL, a natureza flexível dos modelos baseados em transformadores significa que um modelo especificamente treinado pode ter um desempenho muito melhor nessas tarefas do que outras tecnologias de PNL. Como resultado, muitos desenvolvedores estão tentando aproveitar esses modelos especializados em seus pipelines de dados.

Agora que estamos familiarizados com a teoria por trás da chamada de funções, vamos dar uma olhada no aplicativo que construiremos hoje.

Aplicativo de demonstração

Analisador de relacionamento de entidades CB Insights

Em um artigo anterior , criei um aplicativo RAG simples para responder perguntas em linguagem natural sobre o popular boletim informativo CB Insights. No artigo de hoje, construiremos um aplicativo de resposta a perguntas semelhante, mas em vez de depender da incorporação de pesquisa e GPT3.5, usaremos o reconhecimento de entidade como método de indexação principal. Além disso, usaremos DRAGON como mecanismo de resumo para que possamos executar o aplicativo inteiro em nosso laptop, sem a necessidade de serviços em nuvem.


Por que usar o reconhecimento de entidade?

Antes de nos aprofundarmos na implementação, vamos primeiro explorar as vantagens de usar NER como tecnologia de recuperação em vez de incorporar pesquisa. Embora na produção desejemos utilizar cada técnica de acordo com as demandas da situação específica, o NER oferece diversas vantagens em relação a um sistema que depende de pesquisa incorporada.


  1. Depuração: como o reconhecimento de entidade é uma tarefa facilmente verificável, todo o pipeline é muito mais depurável. É fácil verificar se o modelo identifica corretamente todas as entidades e é fácil construir e melhorar um algoritmo de correspondência baseado nessas entidades. Comparativamente, é muito mais difícil verificar se o algoritmo de incorporação identifica adequadamente semelhanças e diferenças nas passagens.


  2. Flexibilidade: Ao separar o reconhecimento e a filtragem, tornamos o pipeline muito mais flexível do que um algoritmo de pesquisa baseado em incorporação. Podemos adicionar metadados adicionais, alterar algoritmos de pesquisa com base no tipo de entidade e até mesmo usar algoritmos de incorporação nos resultados de pesquisa baseados em NER. Isso permite que recursos muito mais poderosos sejam desenvolvidos com base em combinações de tecnologias.


    1. Por exemplo, um pipeline baseado em NER pode usar pesquisa baseada em entidade para restringir um conjunto de documentos e, em seguida, usar um algoritmo de incorporação para restringir ainda mais o espaço de pesquisa. Isso tende a tornar a busca muito mais rápida e eficiente.


  3. Poder de identificação: Devido ao nível de controle manual possível, os pipelines NER são muito mais adequados para determinadas tarefas de pesquisa e recuperação. As pesquisas de incorporação baseiam-se na proximidade de passagens nos dados de treinamento, o que calcula a probabilidade de dois documentos provirem do mesmo documento maior. Em alguns casos de uso, isso fará com que a pesquisa incorporada perca documentos importantes.


    1. Por exemplo, se estivéssemos tentando compreender a estratégia de IA da Microsoft, poderíamos não apenas querer recuperar informações sobre as atividades da Microsoft no espaço de software de IA, mas também informações sobre investimentos em fabricação de chips, data centers e robótica. Um algoritmo de incorporação de uso geral não será capaz de identificar essas conexões, enquanto um algoritmo baseado em NER será capaz de desenhar essas conexões.


Agora que entendemos os benefícios de usar NER em um pipeline RAG, vamos examinar mais profundamente as tecnologias específicas que estamos usando em nossa aplicação.

Tecnologias Utilizadas

Reconhecimento de Entidade LLM

O reconhecimento de entidade é uma tecnologia “tradicional” de PNL para extrair dados estruturados de dados de linguagem não estruturados. Os dados extraídos podem então ser usados no processamento descendente ou como metadados para a passagem que está sendo analisada.


Historicamente, isso foi realizado usando pequenos algoritmos de aprendizado de máquina criados especificamente para esse fim, que primeiro marcam as partes do discurso, seguido por uma segunda passagem que determina se os nomes próprios identificados são entidades nomeadas.


Com LLMs de chamada de função, podemos realizar a mesma tarefa, com diversas vantagens adicionais.


  1. Como a arquitetura do transformador é capaz de compreender melhor a estrutura da linguagem do que modelos menores de PNL, o desempenho provavelmente será mais robusto, por exemplo, em casos em que a passagem está formatada incorretamente.


  2. Como os LLMs estão sendo atualizados com os dados de treinamento mais recentes, é provável que o sistema de reconhecimento de entidades permaneça mais atualizado do que outros modelos de reconhecimento de entidades de código aberto.


  3. Técnicas de engenharia imediata podem ser usadas para incorporar dados adicionais e fornecer instruções adicionais, permitindo um comportamento mais flexível, mesmo em modelos prontos para uso.


DRAGON Abordamos o Dragon em um artigo anterior, onde destacamos seu desempenho impressionante no resumo de dados de linguagem natural. Utilizaremos o Dragon para realizar a etapa final da análise, onde resumiremos todos os artigos relevantes para as entidades selecionadas.


SLIMs SLIMs são uma nova família de modelos miniaturizados e executáveis localmente da LLMWare - não é nenhum segredo que sou um fã de seu trabalho de miniaturização - especializados em chamadas de funções. Esses modelos foram ajustados especificamente para gerar resultados que podem ser interpretados por máquinas, permitindo que os usuários aproveitem os desenvolvimentos recentes na arquitetura de chamada de funções sem precisar depender de APIs externas.


Hoje utilizaremos o modelo SLIMs-NER, que realizará o Reconhecimento de Entidade Nomeada nos artigos da newsletter. Além do NER, também existem modelos SLIMs para análise de sentimento, geração de SQL e agentes multietapas.

Agora que entendemos a tecnologia, vamos implementar a aplicação!

Implementação

Download e processamento de dados

Vamos começar baixando os artigos do CB Insights. Vamos importar as dependências:

 import requests from bs4 import BeautifulSoup import os import pandas as pd import json import re


E agora o código para baixar o arquivo da newsletter:


 res = requests.get('https://www.cbinsights.com/newsletter/') soup = BeautifulSoup(res.text) article_links = [[i.text, i['href']] for i in soup.find_all('a') if 'campaign-archive' in i['href'] ] article_soups = [BeautifulSoup(requests.get(link).text) for title, link in article_links]


Agora que baixamos o arquivo do boletim informativo, vamos processá-lo no formato JSON


 result_json = {} for soup_meta, soup_art in zip(article_links, article_soups): article_tables = [] cur_article = [] for table in soup_art.find_all('table'): if table.attrs.get('mc:variant') == 'Section_Divider': article_tables.append(get_deduped_article_tables(cur_article)) cur_article = [] else: cur_article.append(table.text) article_tables.append(get_deduped_article_tables(cur_article)) result_json[soup_meta[0]] = article_tables articles_with_meta = [] for name, tables in result_json.items(): print(name, pd.to_datetime(tables[0][1].strip())) articles_with_meta.append({ 'name': name, 'date': pd.to_datetime(tables[0][1].strip()).strftime('%Y-%m-%d'), 'tables': tables }) df = pd.DataFrame(articles_with_meta)


Agora estamos no mesmo lugar que estávamos no artigo anterior. Em vez de ir direto para a construção do RAG criando embeddings, executaremos uma etapa de reconhecimento de entidade.


Primeiro, vamos importar as dependências para execução de SLIMs, um novo conjunto de modelos do LLMWare que nos permite realizar o reconhecimento de entidades localmente em nossa máquina:


 from llmware.agents import LLMfx from llmware.parsers import WikiParser from collections import defaultdict # define a function for identifying all the named entities def run_ner(text): agent = LLMfx() agent.load_work(text) agent.load_tool("ner") named_entities = agent.ner() ner_dict= named_entities["llm_response"] return ner_dict


Agora podemos executar o reconhecimento da entidade nomeada em todos os artigos:


 date_entities = defaultdict(dict) for _, row in df.iterrows(): for idx, t in enumerate(row['tables'][1:]): if 'Start Your Free Trial' in t: t = t[:t.index('Start Your Free Trial')] date_entities[row['date']][idx] = run_ner('\n'.join(t))


Pode levar alguns minutos para que o pipeline do NER seja concluído, mas isso é tudo que você precisa para reconhecer entidades usando um LLM miniaturizado de última geração.


Você pode verificar o dicionário date_entities imprimindo alguns itens de teste. Por exemplo, o código:


 date_entities[list(date_entities.keys())[0]]


Deve produzir a saída abaixo:


 {0: {'people': ['Yahoo!'], 'place': [], 'company': ['Databricks', 'MosaicML'], 'misc': []}, 1: {'people': [], 'place': ['New York'], 'company': ['CB Insights'], 'misc': []}}


Que mostra todas as diversas entidades que foram detectadas pelo modelo SLIMs.

Resposta a perguntas com DRAGON

Agora que as entidades foram detectadas, vamos criar um fluxo de trabalho de resposta a perguntas que demonstre o poder desta técnica. Para nosso exemplo, usaremos a pergunta de teste: Qual o papel do OpenAI na estratégia de IA da Microsoft?


Vamos começar importando os pacotes adequados para executar o DRAGON:

 from llmware.prompts import Prompt query = "What role does OpenAI play in Microsoft's AI strategy?" model_name = "llmware/dragon-llama-7b-gguf" prompter = Prompt().load_model(model_name)


Agora podemos construir a função que responde à pergunta usando o reconhecimento de entidade. Para aproveitar nossos dados NER, desejaremos implementar o seguinte fluxo de trabalho:


  1. Identifique as entidades na consulta do usuário. Podemos usar a mesma função SLIMs que usamos na etapa anterior.
  2. Realizamos uma pesquisa com base nos resultados da pesquisa, ou seja, buscamos artigos no corpus que falem das mesmas entidades.
  3. Assim que encontrarmos esses artigos, podemos fornecê-los ao modelo de resposta a perguntas para extrair as informações relevantes.


Esta é a aparência do fluxo de trabalho em forma de código:


 def answer_question_with_ner(query): ner_results = run_ner(query) # run NER on the user query search_entities = [] for ent_type, ent_list in ner_results.items(): search_entities.extend(ent_list) # create a list of entities to search for search_entities = list(set(search_entities)) # now perform a lookup for articles that mention the identified entities, using set arithmetic. articles = set(entity_to_place_map[search_entities[0]]) for se in search_entities: articles &= set(entity_to_place_map[se]) # now process the corpus into a prompt and feed it to the question-answering LLM. article_content = [] for article in articles: article_content.extend(df[df['date'] == article[0]].iloc[0]['tables'][article[1]+1]) response = prompter.prompt_main(query, context='\n'.join(article_content), prompt_name="default_with_context", temperature=0.3) return response # return the response.


Execute a função, com a consulta do primeiro bloco de código, e você verá o seguinte resultado:


 Microsoft has poured billions of dollars into ChatGPT developer OpenAI. However, it's also placed a number of bets on other GenAI startups across computing, mapping, and gaming.


Você também pode ver na seção “evidência” do objeto de resposta que, de fato, os dois artigos do arquivo CB Insights que mencionam Microsoft e OpenAI foram recuperados, e que a resposta do LLM é baseada diretamente nas evidências.


Observe que, como estamos fazendo o reconhecimento explícito de entidades, o processo de recuperação é extremamente transparente e depurável. Caso surja alguma dúvida sobre por que o modelo recuperou essas informações específicas do corpus - basta uma simples declaração impressa para ver que o modelo escolheu o artigo porque a consulta menciona “Microsoft” e “OpenAI”, e o duas seções recuperadas do boletim informativo são as únicas seções que mencionam ambas as entidades.


Além disso, quando comparado com a pesquisa vetorial baseada em incorporação, o método de pesquisa NER fornece respostas muito mais precisas. Em meus testes, os artigos selecionados estavam entre os 10 artigos mais relevantes classificados pelo algoritmo ada da OpenAI, mas não foi aquele identificado como tendo a maior proximidade com a questão em questão. Portanto, é possível que um aplicativo que usa pesquisa de incorporação não tenha respondido corretamente à pergunta, e a falta de capacidade de depuração apenas contribuiria para a confusão.


E com isso construímos um aplicativo de esclarecimento de dúvidas utilizando pesquisas NER, melhorando a qualidade do pipeline no processo!

Conclusão

Hoje, construímos um aplicativo usando chamada de função, um novo e interessante recurso do LLM. Modelos de chamada de função miniaturizados e executáveis localmente são um desenvolvimento revolucionário que abre uma nova classe de aplicações de IA, e estamos vendo apenas a primeira iteração dessas tecnologias. Será emocionante ver o que os desenvolvedores de aplicativos criarão com essas tecnologias nos próximos meses.


Se você tem uma ideia no espaço de IA que deseja ver implementada ou simplesmente deseja conversar sobre tecnologia, não hesite em entrar em contato no Github ou LinkedIn .


Se você quiser saber mais sobre LLMWare, a empresa por trás de SLIMs e DRAGON, você pode encontrá-los em HugginFace ou Github .