Criar um pipeline de dados não estruturados para o RAG
Este artigo descreve como criar um pipeline de dados não estruturado para aplicativos gen AI. Os pipelines não estruturados são particularmente úteis para aplicativos RAG (Retrieval-Augmented Generation).
Saiba como converter conteúdo não estruturado, como arquivos de texto e PDFs, em um índice vetorial que os agentes do AI ou outros recuperadores podem consultar. Você também aprenderá a experimentar e ajustar o pipeline para otimizar a fragmentação, a indexação e a análise de dados, o que lhe permitirá solucionar problemas e fazer experiências com o pipeline para obter melhores resultados.
Não estruturado pipeline de dados Notebook
O Notebook a seguir mostra aos senhores como implementar as informações contidas neste artigo para criar um pipeline de dados não estruturado.
Databricks não estruturado pipeline de dados
Principais componentes do site pipeline de dados
A base de qualquer aplicativo RAG com dados não estruturados é o pipeline de dados. Esse pipeline é responsável pela curadoria e preparação dos dados não estruturados em um formato que o aplicativo RAG possa usar com eficiência. Embora esse pipeline de dados possa se tornar complexo dependendo do caso de uso, a seguir estão os key componentes que o senhor precisa considerar ao criar seu aplicativo RAG pela primeira vez:
-
Composição e ingestão de corpus: Selecionar a fonte de dados e o conteúdo corretos com base no caso de uso específico.
-
Pré-processamento de dados: Transformar os dados brutos em um formato limpo e consistente, adequado para incorporação e recuperação.
- Análise: Extrair informações relevantes do uso de dados brutos com técnicas de análise apropriadas.
- Enriquecimento: enriquecer dados com metadados adicionais e remover ruídos.
- Extração de metadados: extraia metadados úteis para implementar uma recuperação de dados mais rápida e eficiente.
- Desduplicação: analise os documentos para identificar e eliminar documentos duplicados ou quase duplicados.
- Filtragem: elimine documentos irrelevantes ou indesejados da coleção.
-
Fragmentação: divida os dados analisados em partes menores e gerenciáveis para uma recuperação eficiente.
-
Incorporação: converta os dados de texto fragmentados em uma representação vetorial numérica que capture seu significado semântico.
-
Indexação e armazenamento: Crie índices vetoriais eficientes para otimizar o desempenho da pesquisa.
Composição e ingestão do corpus
Seu aplicativo RAG não pode recuperar as informações necessárias para responder a uma consulta do usuário sem o corpus de dados correto. Os dados corretos dependem inteiramente dos requisitos e objetivos específicos do seu aplicativo, o que torna crucial dedicar tempo à compreensão das nuances dos dados disponíveis. Para obter mais informações, consulte Generative AI fluxo de trabalho do desenvolvedor de aplicativos.
Por exemplo, ao criar um bot de suporte ao cliente, você pode considerar incluir o seguinte:
- Documentos da base de conhecimento
- Perguntas frequentes (FAQs)
- manuais e especificações do produto
- Guia de solução de problemas
Envolva especialistas do domínio e partes interessadas desde o início de qualquer projeto para ajudar a identificar e selecionar conteúdo relevante que possa melhorar a qualidade e a cobertura do seu corpus de dados. Eles podem fornecer percepções sobre os tipos de consultas que os usuários provavelmente enviarão e ajudar a priorizar as informações mais importantes a serem incluídas.
A Databricks recomenda que o senhor faça a ingestão de dados de forma escalonável e incremental. Databricks oferece vários métodos para ingestão de dados, incluindo conectores totalmente gerenciados para aplicativos SaaS e integrações API. Como melhor prática, os dados brutos de origem devem ser ingeridos e armazenados em uma tabela de destino. Essa abordagem garante a preservação, a rastreabilidade e a auditoria dos dados. Consulte Ingerir dados em um lakehouse da Databricks.
Pré-processamento de dados
Após a ingestão dos dados, é essencial limpar e formatar os dados brutos em um formato consistente, adequado para incorporação e recuperação.
Análise
Depois de identificar a fonte de dados apropriada para seu aplicativo retriever, a próxima etapa é extrair as informações necessárias dos dados brutos. Esse processo, conhecido como análise, envolve a transformação dos dados não estruturados em um formato que o aplicativo RAG possa usar com eficácia.
As técnicas e ferramentas de análise específicas que você usa dependem do tipo de dados com os quais você está trabalhando. Por exemplo:
- Documentos de texto (PDFs, documentos do Word): Bibliotecas prontas para uso, como a unstructured e a PyPDF2, podem lidar com vários formatos de arquivo e oferecer opções para personalizar o processo de análise.
- Documentos HTML: A biblioteca de análise de HTML, como BeautifulSoup e lxml, pode ser usada para extrair conteúdo relevante de páginas da Web. Essas bibliotecas podem ajudar a navegar na estrutura HTML, selecionar elementos específicos e extrair o texto ou os atributos desejados.
- Imagens e documentos digitalizados: técnicas de reconhecimento óptico de caracteres (OCR) geralmente são necessárias para extrair texto de imagens. As bibliotecas populares de OCR incluem bibliotecas de código aberto, como o Tesseract, ou versões do SaaS, como Amazon Textract, Azure AI Vision OCR e Google Cloud Vision API.
Práticas recomendadas para analisar dados
A análise garante que os dados estejam limpos, estruturados e prontos para incorporar a geração e a pesquisa vetorial. Ao analisar seus dados, considere as seguintes práticas recomendadas:
- Limpeza de dados: Pré-processar o texto extraído para remover informações irrelevantes ou com ruído, como cabeçalhos, rodapés ou caracteres especiais. Reduzir a quantidade de informações desnecessárias ou malformadas que sua cadeia RAG precisa processar.
- Tratamento de erros e exceções: implemente mecanismos de gerenciamento e registro de erros para identificar e resolver quaisquer problemas encontrados durante o processo de análise. Isso ajuda você a identificar e corrigir problemas rapidamente. Fazer isso geralmente indica problemas iniciais com a qualidade dos dados de origem.
- Personalização da lógica de análise: Dependendo da estrutura e do formato dos seus dados, talvez seja necessário personalizar a lógica de análise para extrair as informações mais relevantes. Embora isso possa exigir um esforço adicional inicial, invista tempo para fazer isso, se necessário, pois isso geralmente evita muitos problemas de qualidade posteriores.
- Avaliação da qualidade da análise: avalie regularmente a qualidade dos dados analisados revisando manualmente uma amostra da saída. Isso pode ajudá-lo a identificar quaisquer problemas ou áreas de melhoria no processo de análise.
Enriquecimento
enriquecer dados com metadados adicionais e remover ruídos. Embora o enriquecimento seja opcional, ele pode melhorar drasticamente o desempenho geral do seu aplicativo.
Extração de metadados
A geração e a extração de metadados que capturam informações essenciais sobre o conteúdo, o contexto e a estrutura do documento podem melhorar significativamente a qualidade e o desempenho da recuperação de um aplicativo RAG. Os metadados fornecem sinais adicionais que melhoram a relevância, permitem a filtragem avançada e oferecem suporte aos requisitos de pesquisa específicos do domínio.
Embora as bibliotecas como LangChain e LlamaIndex forneçam analisadores integrados capazes de extrair automaticamente os metadados padrão associados, muitas vezes é útil complementá-los com metadados personalizados adaptados ao seu caso de uso específico. Essa abordagem garante que as informações críticas específicas do domínio sejam capturadas, melhorando a recuperação e a geração downstream. Você também pode usar grandes modelos de linguagem (LLMs) para automatizar o aprimoramento de metadados.
Os tipos de metadados incluem:
- Metadados em nível de documento: Nome do arquivo, URLs, informações do autor, carimbos de data e hora de criação e modificação, coordenadas de GPS e controle de versão do documento.
- Metadados baseados em conteúdo: Palavras-chave extraídas, resumos, tópicos, entidades nomeadas e tags específicas do domínio (nomes de produtos e categorias como PII ou HIPAA).
- Metadados estruturais: cabeçalhos de seção, sumário, números de página e limites de conteúdo semântico (capítulos ou subseções).
- Metadados contextuais: sistema de origem, data de ingestão, nível de confidencialidade dos dados, idioma original ou instruções transnacionais.
O armazenamento de metadados junto com os documentos em pedaços ou seus correspondentes embeddings é essencial para o desempenho ideal. Isso também ajudará a restringir as informações recuperadas e a melhorar a precisão e a escalabilidade do seu aplicativo. Além disso, a integração de metadados no pipeline de pesquisa híbrida, o que significa combinar a pesquisa de similaridade vetorial com a filtragem baseada em palavras-chave, pode aumentar a relevância, especialmente em cenários de grandes conjuntos de dados ou critérios de pesquisa específicos.
Desduplicação
Dependendo de suas fontes, você pode acabar com documentos duplicados ou quase duplicados. Por exemplo, se você extrair de um ou mais drives compartilhados, várias cópias do mesmo documento poderão existir em vários locais. Algumas dessas cópias podem ter modificações sutis. Da mesma forma, sua base de conhecimento pode ter cópias da documentação do seu produto ou cópias de rascunho da postagem no blog. Se essas duplicatas permanecerem no corpus, o senhor pode acabar com pedaços altamente redundantes no índice final, o que pode diminuir o desempenho do aplicativo.
Você pode eliminar algumas duplicatas usando apenas metadados. Por exemplo, se um item tiver o mesmo título e data de criação, mas várias entradas de fontes ou locais diferentes, você poderá filtrá-las com base nos metadados.
No entanto, isso pode não ser suficiente. Para ajudar a identificar e eliminar duplicatas com base no conteúdo dos documentos, você pode usar uma técnica conhecida como hashing sensível à localidade. Especificamente, uma técnica chamada MinHash funciona bem aqui, e uma implementação do Spark já está disponível no Spark ML. Ele funciona criando um hash para o documento com base nas palavras que ele contém e pode, então, identificar com eficiência duplicatas ou quase duplicatas unindo esses hashes. Em um nível muito alto, esse é um processo de quatro etapas:
- Criar um vetor de recurso para cada documento. Se necessário, considere aplicar técnicas como remoção de palavras interrompidas, derivação e lematização para melhorar os resultados e, em seguida, tokenizar em n-gramas.
- Ajuste um modelo MinHash e faça o hash dos vetores usando MinHash para a distância de Jaccard.
- executar uma similaridade join usando esses hashes para produzir um conjunto de resultados para cada documento duplicado ou quase duplicado.
- Filtre as duplicatas que você não quer manter.
Uma etapa básica de desduplicação pode selecionar arbitrariamente os documentos a serem mantidos (como o primeiro nos resultados de cada duplicata ou uma escolha aleatória entre as duplicatas). Uma melhoria potencial seria selecionar a “melhor” versão da duplicata usando outra lógica (como a atualização mais recente, o status da publicação ou a fonte mais confiável). Além disso, observe que talvez seja necessário experimentar a etapa de caracterização e o número de tabelas de hash usadas no modelo minHash para melhorar os resultados de correspondência.
Para obter mais informações, consulte a documentação Spark para hashing sensível à localidade.
Filtragem
Alguns dos documentos que você insere em seu corpus podem não ser úteis para seu agente, seja porque são irrelevantes para a finalidade, muito antigos ou não confiáveis, ou porque contêm conteúdo problemático, como linguagem prejudicial. Ainda assim, outros documentos podem conter informações confidenciais que o senhor não deseja expor por meio de seu agente.
Portanto, considere incluir uma etapa em seu pipeline para filtrar esses documentos usando qualquer metadado, como a aplicação de um classificador de toxicidade ao documento para produzir uma previsão que possa ser usada como filtro. Outro exemplo seria a aplicação de um algoritmo de detecção de informações de identificação pessoal (PII) aos documentos para filtrá-los.
Por fim, todas as fontes de documentos que você fornece ao seu agente são possíveis vetores de ataque para que agentes mal-intencionados iniciem ataques de envenenamento de dados. Você também pode considerar a adição de mecanismos de detecção e filtragem para ajudar a identificá-los e eliminá-los.
Desfragmentando
Depois de analisar os dados brutos em um formato mais estruturado, remover duplicatas e filtrar informações indesejadas, a próxima etapa é dividi-los em unidades menores e gerenciáveis, chamadas de chunks. A segmentação de documentos grandes em pedaços menores e semanticamente concentrados garante que os dados recuperados se encaixem no contexto do LLMe minimiza a inclusão de informações que distraem ou são irrelevantes. As escolhas feitas no chunking afetarão diretamente os dados recuperados que o LLM fornece, tornando-o uma das primeiras camadas de otimização em um aplicativo RAG.
Ao agrupar seus dados, considere os seguintes fatores:
- Estratégia de fragmentação: o método usado para dividir o texto original em partes. Isso pode envolver técnicas básicas, como a divisão por frases, parágrafos, contagens específicas de caracteres/tokens e estratégias mais avançadas de divisão específicas de documentos.
- Tamanho do bloco: Pedaços menores podem se concentrar em detalhes específicos, mas perdem algumas informações contextuais ao redor. Pedaços maiores podem capturar mais contexto, mas podem incluir informações irrelevantes ou ser computacionalmente caros.
- Sobreposição entre blocos: Para garantir que informações importantes não sejam perdidas ao dividir os dados em blocos, considere incluir alguma sobreposição entre os blocos adjacentes. A sobreposição pode garantir a continuidade e a preservação do contexto entre os blocos e melhorar os resultados da recuperação.
- Coerência semântica: Quando possível, procure criar blocos semanticamente coerentes que contenham informações relacionadas, mas que possam se manter independentemente como uma unidade significativa de texto. Isso pode ser feito considerando a estrutura dos dados originais, como parágrafos, seções ou limites de tópicos.
- Metadados: Metadados relevantes, como o nome do documento de origem, o título da seção ou os nomes dos produtos, podem melhorar a recuperação. Essas informações adicionais podem ajudar a combinar as consultas de recuperação com os chunks.
Estratégias de fragmentação de dados
Encontrar o método de fragmentação adequado é tanto iterativo quanto dependente do contexto. Não existe uma abordagem única para todos. O tamanho e o método ideais do bloco dependem do caso de uso específico e da natureza dos dados que estão sendo processados. Em linhas gerais, as estratégias de fragmentação podem ser vistas como as seguintes:
- Divisão de tamanho fixo: Dividir o texto em partes de um tamanho predeterminado, como um número fixo de caracteres ou tokens (por exemplo, LangChain CharacterTextSplitter). Embora a divisão por um número arbitrário de caracteres/tokens seja rápida e fácil de configurar, ela normalmente não resultará em blocos consistentes e semanticamente coerentes. Essa abordagem raramente funciona para aplicativos de nível de produção.
- Separação baseada em parágrafos: use os limites naturais do parágrafo no texto para definir partes. Esse método pode ajudar a preservar a coerência semântica dos blocos, pois os parágrafos geralmente contêm informações relacionadas (por exemplo, LangChain RecursiveCharacterTextSplitter).
- Fragmentação específica de formato: formatos como Markdown ou HTML têm uma estrutura inerente que pode definir limites de fragmentos (por exemplo, cabeçalhos de marcação). Ferramentas como o MarkdownHeaderTextSplitter da LangChain ou divisores baseadosem cabeçalho/seção HTML podemser usados para essa finalidade.
- Fragmentação semântica: técnicas como modelagem de tópicos podem ser aplicadas para identificar seções semanticamente coerentes no texto. Essas abordagens analisam o conteúdo ou a estrutura de cada documento para determinar os limites de partes mais apropriados com base nas mudanças de tópico. Embora mais complexo do que as abordagens básicas, o chunking semântico pode ajudar a criar pedaços mais alinhados com as divisões semânticas naturais do texto (consulte LangChain SemanticChunker, por exemplo).
Exemplo: fragmentação de tamanho fixo
Exemplo de chunking de tamanho fixo usando o RecursiveCharacterTextSplitter da LangChain com chunk_size=100 e chunk_overlap=20. O ChunkViz fornece uma maneira interativa de visualizar como diferentes tamanhos e valores de blocos se sobrepõem aos divisores de caracteres do Langchain afetam os blocos resultantes.
Incorporação
Depois de dividir seus dados, a próxima etapa é converter os pedaços de texto em uma representação vetorial usando um modelo de incorporação. Um modelo de incorporação converte cada pedaço de texto em uma representação vetorial que captura seu significado semântico. Ao representar partes como vetores densos, as incorporações permitem a recuperação rápida e precisa das partes mais relevantes com base em sua semelhança semântica com uma consulta de recuperação. A consulta de recuperação será transformada no momento da consulta usando o mesmo modelo de incorporação usado para incorporar pedaços no pipeline de dados.
Ao selecionar um modelo de incorporação, considere os seguintes fatores:
-
Escolha do modelo: cada modelo de incorporação tem nuances, e os benchmarks disponíveis podem não capturar as características específicas de seus dados. É crucial selecionar um modelo que tenha sido treinado com dados semelhantes. Também pode ser útil explorar quaisquer modelos de incorporação disponíveis que tenham sido projetados para tarefas específicas. Experimente diferentes modelos de incorporação prontos para uso, mesmo aqueles que podem ter uma classificação inferior em tabelas de classificação padrão, como o MTEB. Alguns exemplos a serem considerados:
-
Max tokens: Conheça o limite máximo de tokens para o modelo de incorporação escolhido. Se o senhor passar pedaços que excedam esse limite, eles serão truncados, podendo perder informações importantes. Por exemplo, o bge-large-en-v1.5 tem um limite máximo de 512 tokens.
-
Tamanho do modelo: Modelos de incorporação maiores geralmente têm melhor desempenho, mas exigem mais recursos computacionais. Com base no seu caso de uso específico e no recurso disponível, o senhor precisará equilibrar desempenho e eficiência.
-
Ajuste fino: se seu aplicativo RAG lida com linguagem específica de domínio (como siglas ou terminologia interna da empresa), considere ajustar o modelo de incorporação em dados específicos do domínio. Isso pode ajudar o modelo a capturar melhor as nuances e a terminologia de seu domínio específico e, muitas vezes, pode levar a um melhor desempenho de recuperação.
Indexação e armazenamento
A próxima etapa do pipeline é criar índices nos embeddings e nos metadados gerados nas etapas anteriores. Esse estágio envolve a organização de incorporações vetoriais de alta dimensão em estruturas de dados eficientes que permitem pesquisas de similaridade rápidas e precisas.
Mosaic AI Vector Search usa as mais novas técnicas de indexação quando o senhor implanta uma pesquisa vetorial endpoint e indexa para garantir pesquisas rápidas e eficientes para suas consultas de pesquisa vetorial. Você não precisa se preocupar em testar e escolher as melhores técnicas de indexação.
Depois que o índice for criado e implantado, ele estará pronto para ser armazenado em um sistema que ofereça suporte a consultas escalonáveis e de baixa latência. Para o pipeline RAG de produção com grandes conjuntos de dados, use um banco de dados vetorial ou um serviço de pesquisa escalável para garantir baixa latência e alta taxa de transferência. Armazene metadados adicionais junto com as incorporações para permitir uma filtragem eficiente durante a recuperação.