RAG (Geração Aumentada de Recuperação) na IA do Azure Search

Retrieval Augmented Generation (RAG) é uma arquitetura que aumenta os recursos de um Large Language Model (LLM) como ChatGPT, adicionando um sistema de recuperação de informações que fornece dados de aterramento. Adicionar um sistema de recuperação de informações dá a você controle sobre os dados de aterramento usados por um LLM ao formular uma resposta. Para uma solução empresarial, a arquitetura RAG significa que você pode restringir a IA generativa ao conteúdo corporativo proveniente de documentos e imagens vetorizados e outros formatos de dados, se você tiver modelos incorporados para esse conteúdo.

É crítico decidir qual sistema de recuperação de informações usar, porque isso determina as entradas no LLM. O sistema de recuperação de informações deve fornecer:

  • Estratégias de indexação que carregam e atualizam em escala, em todo o conteúdo, na frequência necessária.

  • Funcionalidades de consulta e ajuste de relevância. O sistema deve retornar resultados relevantes, em formatos curtos necessários para atender aos requisitos de comprimento do token de entradas do LLM.

  • Segurança, alcance global e confiabilidade para dados e operações.

  • Integração com modelos de incorporação para indexação e modelos de chat ou modelos de compreensão de linguagem para recuperação.

A IA do Azure Search é uma solução comprovada para recuperação de informações em uma arquitetura de RAG. Ela fornece recursos de indexação e consulta, com a infraestrutura e a segurança da nuvem do Azure. Por meio de código e outros componentes, é possível criar uma solução de RAG abrangente que inclui todos os elementos para IA generativa sobre seu conteúdo proprietário.

Observação

Novo nos conceitos de copiloto e RAG? Assista Busca em vetores e recuperação de última geração para aplicativos de IA generativa.

A Microsoft tem várias implementações internas para usar a IA do Azure Search em uma solução de RAG.

As abordagens selecionadas simplificam o início, mas para ter mais controle sobre a arquitetura, você precisa de uma solução personalizada. Esses modelos criam soluções ponta a ponta em:

O restante deste artigo explora como a IA do Azure Search se encaixa em uma solução de RAG personalizada.

Um resumo de alto nível do padrão é semelhante a este:

  • Comece com uma pergunta ou solicitação do usuário (prompt).
  • Envie isso para a IA do Azure Search a fim de encontrar informações relevantes.
  • Envie os resultados da pesquisa mais bem classificados para o LLM.
  • Use os recursos de reconhecimento e raciocínio de linguagem natural do LLM para gerar uma resposta ao prompt inicial.

A IA do Azure Search fornece entradas para o prompt do LLM, mas não treina o modelo. Não há treinamento extra na arquitetura de RAG. O LLM é pré-treinado usando dados públicos, mas gera respostas que são aumentadas por informações do recuperador.

Os padrões de RAG que incluem a IA do Azure Search têm os elementos indicados na ilustração a seguir.

Diagrama de arquitetura de recuperação de informações com pesquisa e ChatGPT.

  • UX do aplicativo (aplicativo Web) para a experiência do usuário
  • Servidor de aplicativos ou orquestrador (camada de integração e coordenação)
  • Pesquisa de IA do Azure (sistema de recuperação de informações)
  • OpenAI do Azure (LLM para IA generativa)

O aplicativo Web fornece a experiência do usuário, fornecendo a apresentação, o contexto e a interação do usuário. As perguntas ou solicitações de um usuário começam aqui. As entradas passam pela camada de integração, indo primeiro para a recuperação de informações para obter os resultados da pesquisa, mas também vão para o LLM para definir o contexto e a intenção.

O servidor de aplicativo ou o orquestrador é o código de integração que coordena as entregas entre a recuperação de informações e o LLM. Uma opção é usar LangChain para coordenar o fluxo de trabalho. O LangChain integra-se à Pesquisa de IA do Azure, facilitando a inclusão dela como um recuperador em seu fluxo de trabalho. Kernel Semântico é outra opção.

O sistema de recuperação de informações fornece o índice pesquisável, a lógica de consulta e o conteúdo (resposta da consulta). O índice de pesquisa pode conter vetores ou conteúdo não vetorial. Embora a maioria dos exemplos e demonstrações incluam campos de vetor, isso não é um requisito. A consulta é executada usando o mecanismo de pesquisa existente na IA do Azure Search, que pode lidar com consultas de palavras-chave (ou termo) e de vetor. O índice é criado com antecedência, com base em um esquema definido por você e carregado com o conteúdo proveniente de arquivos, bancos de dados ou armazenamento.

O LLM recebe o prompt original, além dos resultados da IA do Azure Search. O LLM analisa os resultados e formula uma resposta. Se o LLM for o ChatGPT, a interação do usuário poderá ser uma conversa por meio de diálogo. Se você estiver usando o Davinci, o prompt poderá ser uma resposta totalmente composta. Uma solução do Azure provavelmente usa o OpenAI do Azure, mas não há nenhuma dependência definitiva nesse serviço específico.

A Pesquisa de IA do Azure não fornece integração nativa com LLM para prompt flows ou preservação de chat, portanto, você precisa escrever um código que lida com a orquestração e o estado. Você pode examinar a origem da demonstração (Azure-Samples/azure-search-openai-demo) para obter um blueprint do que envolve uma solução completa. Também recomendamos que o Estúdio de IA do Azure ou Azure OpenAI Studio criem soluções de Pesquisa de IA do Azure baseadas em RAG que se integram a LLMs.

Na IA do Azure Search, todo o conteúdo pesquisável é armazenado num índice de pesquisa hospedado no seu serviço de pesquisa. Um índice de pesquisa foi projetado para consultas rápidas com tempos de resposta de milissegundos, portanto, as estruturas de dados internas existem para dar suporte a esse objetivo. Para esse motivo, um índice de pesquisa armazena conteúdo indexado e não arquivos de conteúdo inteiros, como PDFs inteiros ou imagens. Internamente, as estruturas de dados incluem índices invertidos de texto com token, índices de vetor para inserções e texto inalterado para cadeias de caracteres em que a correspondência verbatim é necessária (por exemplo, em filtros, pesquisa difusa, consultas de expressão regular).

Ao configurar os dados para sua solução de RAG, use os recursos que criam e carregam um índice na IA do Azure Search. Um índice inclui campos que duplicam ou representam o conteúdo de origem. Um campo de índice pode ser de transferência simples (um título ou descrição em um documento de origem se torna um título ou descrição em um índice de pesquisa) ou um campo pode conter a saída de um processo externo, como vetorização ou processamento de habilidade que gera uma representação ou descrição de texto de uma imagem.

Como provavelmente você sabe que tipo de conteúdo deseja pesquisar, considere os recursos de indexação aplicáveis a cada tipo de conteúdo:

Tipo de conteúdo Indexado como Recursos
text tokens, texto inalterado Indexadores podem efetuar pull de texto sem formatação de outros recursos do Azure, como o Armazenamento do Azure e o Cosmos DB. Você também pode efetuar push de um conteúdo JSON para um índice. Para modificar texto em versão piloto, use analisadores e normalizadores para adicionar processamento léxico durante a indexação. Mapas de sinônimos são úteis se estiver faltando terminologia em documentos de origem que possa ser usada em uma consulta.
text vetores 1 O texto pode ser dividido em partes e vetorizado externamente e indexado como campos vetoriais em seu índice.
imagem tokens, texto inalterado 2 Habilidades para OCR e Análise de imagem podem processar imagens para reconhecimento de texto ou características de imagem. As informações da imagem são convertidas em texto pesquisável e adicionadas ao índice. As habilidades têm um requisito de indexador.
imagem vetores 1 As imagens podem ser vetorizadas externamente para uma representação matemática do conteúdo da imagem e indexadas como campos vetoriais em seu índice. Você pode usar um modelo de código aberto como OpenAI CLIP para vetorizar texto e imagens no mesmo espaço de incorporação.

1 A funcionalidade geralmente disponível de suporte vetorial requer que você chame outras bibliotecas ou modelos para agrupamento e vetorização de dados. No entanto, a vetorização integrada (versão prévia) incorpora essas etapas. Para exemplos de código que mostram ambas as abordagens, veja repositório azure-search-vectors.

2Habilidades são suporte interno para enriquecimento de IA. Para análise de imagem e OCR, o pipeline de indexação faz uma chamada interna para as APIs da Visão de IA do Azure. Essas habilidades passam uma imagem extraída para a IA do Azure fazer o processamento e recebem a saída como texto indexado pela IA do Azure Search.

Os vetores fornecem a melhor acomodação para conteúdo diferente (vários formatos de arquivo e idiomas), pois o conteúdo é expresso universalmente em representações matemáticas. Os vetores também dão suporte à pesquisa de similaridade: correspondendo as coordenadas mais semelhantes à consulta de vetor. Comparando à pesquisa por palavra-chave (ou pesquisa de termos) que faz a correspondência em termos com token, a pesquisa por similaridade é mais sutil. É uma opção melhor caso existam requisitos de ambiguidade ou interpretação no conteúdo ou em consultas.

Depois que os dados estiverem em um índice de pesquisa, use os recursos de consulta da IA do Azure Search para recuperar o conteúdo.

Em um padrão não RAG, as consultas fazem uma viagem de ida e volta de um cliente de pesquisa. A consulta é enviada, é executada em um mecanismo de pesquisa e a resposta é retornada ao aplicativo cliente. A resposta ou os resultados da pesquisa consistem exclusivamente no conteúdo verbatim encontrado em seu índice.

Em um padrão de RAG, consultas e respostas são coordenadas entre o mecanismo de pesquisa e o LLM. A pergunta ou consulta de um usuário é encaminhada para o mecanismo de pesquisa e para o LLM como um prompt. Os resultados da pesquisa voltam do mecanismo de pesquisa e são redirecionados para um LLM. A resposta que volta para o usuário é a IA generativa, como um resumo ou uma resposta do LLM.

Não existe um tipo de consulta na IA do Azure Search, nem mesmo busca em vetores ou semântica, que componha novas respostas. Somente o LLM fornece a IA generativa. Confira estes recursos na IA do Azure Search que são usados para formular consultas:

Recurso de consulta Finalidade Por que usá-la
Sintaxe simples ou completa do Lucene Execução de consulta sobre texto e conteúdo numérico não vetorial A pesquisa de texto completo é melhor para correspondências exatas, em vez de correspondências semelhantes. As consultas de pesquisa de texto completo são classificadas usando o algoritmo BM25 e dão suporte ao ajuste de relevância por meio de perfis de pontuação. Elas também dão suporte a filtros e facetas.
Filtros e facetas Aplica-se somente a campos de texto ou numéricos (não vetoriais). Reduz a área da superfície de pesquisa com base nos critérios de inclusão ou exclusão. Adiciona precisão às suas consultas.
Classificação semântica Classifica novamente um conjunto de resultados BM25 usando modelos semânticos. Produz legendas e respostas curtas que são úteis como entradas de LLM. Mais fácil do que perfis de pontuação e, dependendo do conteúdo, uma técnica mais confiável para ajuste de relevância.
Busca em vetores Execução de consulta em campos vetoriais para pesquisa de similaridade, em que a cadeia de caracteres de consulta é um ou mais vetores. Os vetores podem representar todos os tipos de conteúdo, em qualquer linguagem.
Pesquisa híbrida Combina uma ou todas as técnicas de consulta acima. Consultas vetoriais e não vetoriais são executadas em paralelo e retornadas em um conjunto de resultados unificado. Os ganhos mais significativos em precisão e recall são obtidos por meio de consultas híbridas.

Estruturar a resposta da consulta

A resposta de uma consulta fornece a entrada para o LLM, portanto, a qualidade dos resultados da pesquisa é fundamental para o sucesso. Os resultados são um conjunto de linhas tabulares. A composição ou estrutura dos resultados depende de:

  • Campos que determinam quais partes do índice estão incluídas na resposta.
  • Linhas que representam uma correspondência do índice.

Os campos aparecem nos resultados da pesquisa quando o atributo é "recuperável". Uma definição de campo no esquema de índice tem atributos e eles determinam se um campo é usado em uma resposta. Somente campos "recuperáveis" são retornados em texto completo ou resultados de consulta de vetor. Por padrão, todos os campos "recuperáveis" são retornados, mas você pode usar "SELECT" para especificar um subconjunto. Além de "recuperável", não há restrições no campo. Os campos podem ter qualquer comprimento ou tipo. Em relação ao comprimento, não há limite máximo de comprimento de campo na IA do Azure Search, mas há limites no tamanho de uma solicitação de API.

As linhas são correspondências à consulta, classificadas por relevância, similaridade ou ambas. Por padrão, os resultados são limitados às 50 principais correspondências para pesquisa de texto completo ou correspondências K-ésimo vizinhos mais próximos para busca em vetores. Você pode alterar os padrões para aumentar ou diminuir o limite até o máximo de mil documentos. Você também pode usar os parâmetros de paginação top e skip para recuperar resultados como uma série de resultados paginados.

Classificação por relevância

Quando você está trabalhando com processos complexos, uma grande quantidade de dados e expectativas para respostas de milissegundos, é fundamental que cada etapa adicione valor e melhore a qualidade do resultado final. No lado da recuperação de informações, o ajuste de relevância é uma atividade que melhora a qualidade dos resultados enviados para o LLM. Somente os documentos correspondentes mais relevantes ou mais semelhantes devem ser incluídos nos resultados.

A relevância se aplica à pesquisa por palavra-chave (não vetorial) e a consultas híbridas (nos campos não vetoriais). Na IA do Azure Search, não há ajuste de relevância para consultas de pesquisa de similaridade e vetor. A classificação BM25 é o algoritmo de classificação para pesquisa de texto completo.

Há suporte para ajuste de relevância por meio de recursos que aprimoram a classificação BM25. Essas abordagens incluem:

  • Perfis de pontuação que aumentam a pontuação de pesquisa se as correspondências forem encontradas em um campo de pesquisa específico ou em outros critérios.
  • Classificação semântica que classifica novamente um conjunto de resultados BM25, usando modelos semânticos do Bing para reordenar os resultados para obter um ajuste semântico melhor à consulta original.

Em testes de parâmetro de comparação, consultas híbridas com campos de texto e vetoriais, complementadas com classificação semântica sobre os resultados classificados em BM25, produzem os resultados mais relevantes.

Código de exemplo de uma consulta da IA do Azure Search para cenários de RAG

O código a seguir é copiado do arquivo retrievethenread.py de um site de demonstração. Ele produz content para o LLM com base nos resultados da pesquisa de consulta híbrida. Você pode gravar uma consulta mais simples, mas este exemplo inclui a busca em vetores e a pesquisa por palavras-chave com nova classificação semântica e verificação ortográfica. Na demonstração, essa consulta é usada para obter o conteúdo inicial.

# Use semantic ranker if requested and if retrieval mode is text or hybrid (vectors + text)
if overrides.get("semantic_ranker") and has_text:
    r = await self.search_client.search(query_text,
                                  filter=filter,
                                  query_type=QueryType.SEMANTIC,
                                  query_language="en-us",
                                  query_speller="lexicon",
                                  semantic_configuration_name="default",
                                  top=top,
                                  query_caption="extractive|highlight-false" if use_semantic_captions else None,
                                  vector=query_vector,
                                  top_k=50 if query_vector else None,
                                  vector_fields="embedding" if query_vector else None)
else:
    r = await self.search_client.search(query_text,
                                  filter=filter,
                                  top=top,
                                  vector=query_vector,
                                  top_k=50 if query_vector else None,
                                  vector_fields="embedding" if query_vector else None)
if use_semantic_captions:
    results = [doc[self.sourcepage_field] + ": " + nonewlines(" . ".join([c.text for c in doc['@search.captions']])) async for doc in r]
else:
    results = [doc[self.sourcepage_field] + ": " + nonewlines(doc[self.content_field]) async for doc in r]
content = "\n".join(results)

Código de integração e LLMs

Uma solução de RAG que inclui a IA do Azure Search exige outros componentes e código para criar uma solução completa. Enquanto as seções anteriores abordam a recuperação de informações por meio da IA do Azure Search e quais recursos são usados para criar e consultar conteúdo pesquisável, esta seção apresenta a integração e a interação do LLM.

Os notebooks nos repositórios de demonstração são um ótimo ponto de partida porque mostram padrões para passar os resultados da pesquisa para um LLM. A maior parte do código em uma solução de RAG consiste em chamadas para o LLM, portanto, é necessário desenvolver uma compreensão de como essas APIs funcionam e isso está fora do escopo deste artigo.

O bloco de células a seguir notebook chat-read-retrieve-read.ipynb mostra chamadas de pesquisa no contexto de uma sessão de chat:

# Execute this cell multiple times updating user_input to accumulate chat history
user_input = "Does my plan cover annual eye exams?"

# Exclude category, to simulate scenarios where there's a set of docs you can't see
exclude_category = None

if len(history) > 0:
    completion = openai.Completion.create(
        engine=AZURE_OPENAI_GPT_DEPLOYMENT,
        prompt=summary_prompt_template.format(summary="\n".join(history), question=user_input),
        temperature=0.7,
        max_tokens=32,
        stop=["\n"])
    search = completion.choices[0].text
else:
    search = user_input

# Alternatively simply use search_client.search(q, top=3) if not using semantic ranking
print("Searching:", search)
print("-------------------")
filter = "category ne '{}'".format(exclude_category.replace("'", "''")) if exclude_category else None
r = search_client.search(search, 
                         filter=filter,
                         query_type=QueryType.SEMANTIC, 
                         query_language="en-us", 
                         query_speller="lexicon", 
                         semantic_configuration_name="default", 
                         top=3)
results = [doc[KB_FIELDS_SOURCEPAGE] + ": " + doc[KB_FIELDS_CONTENT].replace("\n", "").replace("\r", "") for doc in r]
content = "\n".join(results)

prompt = prompt_prefix.format(sources=content) + prompt_history + user_input + turn_suffix

completion = openai.Completion.create(
    engine=AZURE_OPENAI_CHATGPT_DEPLOYMENT, 
    prompt=prompt, 
    temperature=0.7, 
    max_tokens=1024,
    stop=["<|im_end|>", "<|im_start|>"])

prompt_history += user_input + turn_suffix + completion.choices[0].text + "\n<|im_end|>" + turn_prefix
history.append("user: " + user_input)
history.append("assistant: " + completion.choices[0].text)

print("\n-------------------\n".join(history))
print("\n-------------------\nPrompt:\n" + prompt)

Como começar

  • Revisar os conceitos e estratégias de indexação para determinar como você deseja ingerir e atualizar dados. Decida se deseja usar busca em vetores, pesquisa por palavras-chave ou pesquisa híbrida. O tipo de conteúdo que você precisa pesquisar e o tipo de consultas que você deseja executar determina o design do índice.

  • Revisar a criação de consultas para saber mais sobre a sintaxe e os requisitos da solicitação de pesquisa.

Observação

Alguns recursos da IA do Azure Search são direcionados à interação humana e não são úteis em um padrão de RAG. Especificamente, você pode ignorar o preenchimento automático e as sugestões. Outros recursos, como facetas e orderby, podem ser úteis, mas seriam incomuns em um cenário de RAG.

Confira também