Pular para o conteúdo principal

RAG versus ajuste fino: Um tutorial abrangente com exemplos práticos

Aprenda as diferenças entre as técnicas RAG e Fine-Tuning para personalizar o desempenho do modelo e reduzir as alucinações nos LLMs.
Actualizado 29 de jul. de 2024  · 13 min de leitura

A maioria dos LLMs (Large Language Models), como o GPT-4, é treinada em conjuntos de dados generalizados e, muitas vezes, desatualizados. Embora sejam excelentes em responder a perguntas gerais, eles têm dificuldades com consultas sobre notícias recentes, desenvolvimentos mais recentes e tópicos específicos do domínio. Nesses casos, eles podem ter alucinações ou fornecer respostas imprecisas. 

Apesar do surgimento de modelos de melhor desempenho, como o Claude 3.5 Sonnet, ainda precisamos modelar o ajuste fino para gerar respostas personalizadas ou usar os sistemas Retrieval-Augmented Generation (RAG) para fornecer contexto extra ao modelo básico.

Neste tutorial, exploraremos o RAG e o ajuste fino, duas técnicas distintas usadas para melhorar as respostas do LLM. Examinaremos suas diferenças e colocaremos a teoria em prática, avaliando os resultados. 

Além disso, vamos nos aprofundar em técnicas híbridas que combinam modelos ajustados com sistemas RAG para aproveitar o melhor dos dois mundos. Por fim, aprenderemos a escolher entre essas três abordagens com base em casos de uso e requisitos específicos.

Visão geral do RAG e ajuste fino

As técnicas de RAG e de ajuste fino melhoram a geração de respostas para consultas específicas de domínio, mas são inerentemente técnicas completamente diferentes. Vamos aprender sobre eles.

Geração Aumentada por Recuperação (RAG)

O Retrieval-Augmented Generation é um processo em que grandes modelos de linguagem, como o GPT-4o, tornam-se conscientes do contexto usando fontes de dados externas. Ele é uma combinação de um retriever e um gerador. O recuperador obtém dados da Internet ou de um banco de dados vetorial e os fornece ao gerador com a consulta do usuário original. O gerador usa contexto adicional para gerar uma resposta altamente precisa e relevante.  

Para saber mais, leia nosso artigo, O que é Retrieval Augmented Generation (RAG)? A Guide to the Basics e entender o funcionamento interno do aplicativo RAG e vários casos de uso .

Ajuste fino

O ajuste fino é o processo de ajuste do modelo pré-treinado usando o conjunto de dados específico do domínio. O modelo pré-treinado é treinado em vários corpos grandes de conjuntos de dados gerais retirados da Internet. Eles são bons em responder a perguntas gerais, mas terão dificuldades ou até mesmo alucinações ao responder a perguntas específicas do domínio. 

Por exemplo, um modelo pré-treinado pode ser proficiente em habilidades gerais de conversação, mas pode produzir respostas erradas quando perguntado sobre procedimentos médicos complexos ou precedentes jurídicos. 

O ajuste fino em um conjunto de dados médicos ou jurídicos permite que o modelo compreenda e responda a perguntas nesses campos com maior precisão e relevância.

Siga o Guia introdutório para ajuste fino de LLMs para saber mais sobre como personalizar o modelo pré-treinado com guias visuais.

RAG vs. Ajuste fino

Aprendemos sobre cada metodologia para melhorar a geração de respostas dos LLMs. Vamos examinar as diferenças para que você possa entendê-las melhor. 

1. Estilo de aprendizagem

O RAG usa um estilo de aprendizado dinâmico, que permite que os modelos de linguagem acessem e usem os dados mais recentes e precisos de bancos de dados, da Internet ou até mesmo de APIs. Essa abordagem garante que as respostas geradas estejam sempre atualizadas e sejam relevantes.

Ajuste fino envolve aprendizado estático, em que o modelo aprende por meio de um novo conjunto de dados durante a fase de treinamento. Embora esse método permita que o modelo se adapte à geração de respostas específicas do domínio, ele não pode integrar novas informações pós-treinamento sem retreinamento.

2. Adaptabilidade

O RAG é melhor para generalizações. Ele usa o processo de recuperação para extrair informações de diferentes fontes de dados. O RAG não altera a resposta do modelo; ele apenas fornece informações adicionais para orientar o modelo. 

Fine-tuning personaliza a saída do modelo e melhora o desempenho do modelo em um domínio especial que está intimamente associado ao conjunto de dados de treinamento. Ele também muda o estilo de geração de respostas e, às vezes, fornece respostas mais relevantes do que os sistemas RAG. 

3. Intensidade de recursos

O RAG consome muitos recursos porque é realizado durante a inferência do modelo. Em comparação com LLMs simples sem RAG, o RAG requer mais memória e computação. 

O ajuste fino do exige muita computação, mas é realizado uma vez. Ele requer várias GPUs e muita memória durante o processo de treinamento, mas, depois disso, é bastante econômico em termos de recursos em comparação com os sistemas RAG. 

4. Custo

O RAG requer modelos de incorporação e LLMs de primeira linha para uma melhor geração de respostas. Ele também precisa de um banco de dados vetorial rápido. Os custos de API e de operação podem aumentar rapidamente.

Ajuste fino terá um custo alto apenas uma vez durante o processo de treinamento, mas, depois disso, você pagará pela inferência do modelo, que é bem mais barata que o RAG.

Em geral, em média, o ajuste fino custa mais do que o RAG se tudo for considerado. 

5. Complexidade de implementação

Os sistemas RAG podem ser criados por engenheiros de software e exigem conhecimento técnico médio. Você precisa aprender sobre projetos LLM, bancos de dados vetoriais, embeddings, prompt engineers e muito mais, o que requer tempo, mas é fácil de aprender em um mês. 

Ajuste fino o modelo exige alto conhecimento técnico. Desde a preparação do conjunto de dados até a definição dos parâmetros de ajuste e o monitoramento do desempenho do modelo, são necessários anos de experiência no campo do processamento de linguagem natural. 

Colocando a teoria à prova com exemplos práticos

Vamos testar nossa teoria fornecendo o mesmo prompt a um modelo ajustado, ao aplicativo RAG e a uma abordagem híbrida e, em seguida, avaliar os resultados. A abordagem híbrida combinará o modelo ajustado com o aplicativo RAG. Para este exemplo, usaremos o arquivo ruslanmv/ai-medical-chatbot do Hugging Face, que contém conversas entre pacientes e médicos sobre várias condições de saúde.

Criação do aplicativo RAG usando o Llama 3

Começaremos criando o aplicativo RAG usando o ecossistema Llama 3 e LangChain. 

Você também pode aprender a criar um aplicativo RAG usando o LlamaIndex seguindo o código, Geração aumentada de recuperação com o LlamaIndex.

1. Instale todos os pacotes Python necessários.

%%capture
%pip install -U langchain langchainhub langchain_community langchain-huggingface faiss-gpu transformers accelerate

2. Carregue as funções necessárias das bibliotecas LangChain e Transformers.

from langchain.document_loaders import HuggingFaceDatasetLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import FAISS
from transformers import AutoTokenizer, AutoModelForCausalLM,pipeline
from langchain_huggingface import HuggingFacePipeline
from langchain.chains import RetrievalQA

3. Para acessar modelos e conjuntos de dados restritos, é recomendável que você faça login no hub Hugging Face usando a chave de API.

from huggingface_hub import login
from kaggle_secrets import UserSecretsClient
user_secrets = UserSecretsClient()

hf_token = user_secrets.get_secret("HUGGINGFACE_TOKEN")
login(token = hf_token)

4. Carregue o conjunto de dados fornecendo o nome do conjunto de dados e o nome da coluna para HuggingFaceDatasetLoader. As colunas "Doctor" serão nosso documento principal, e o restante das colunas serão os metadados. 

5. Limitando nosso conjunto de dados às primeiras 1.000 linhas. A redução do conjunto de dados nos ajudará a reduzir o tempo de armazenamento de dados no banco de dados vetorial. 

# Specify the dataset name
dataset_name = "ruslanmv/ai-medical-chatbot"


# Create a loader instance using dataset columns
loader_doctor = HuggingFaceDatasetLoader(dataset_name,"Doctor")

# Load the data
doctor_data = loader_doctor.load()

# Select the first 1000 entries
doctor_data = doctor_data[:1000]

doctor_data[:2]

Como você pode ver, a coluna "Doctor" é o conteúdo da página, e as demais são consideradas metadados. 

saída do conjunto de dados HuggingFaceDatasetLoader

6. Carregue o modelo de incorporação do Hugging Face usando parâmetros específicos, como a ativação da aceleração da GPU.

7. Teste o modelo de incorporação fornecendo a ele o texto de amostra.

# Define the path to the embedding model
modelPath = "sentence-transformers/all-MiniLM-L12-v2"

# GPU acceleration
model_kwargs = {'device':'cuda'}

# Create a dictionary with encoding options
encode_kwargs = {'normalize_embeddings': False}

# Initialize an instance of HuggingFaceEmbeddings with the specified parameters
embeddings = HuggingFaceEmbeddings(
    model_name=modelPath,     
    model_kwargs=model_kwargs, 
    encode_kwargs=encode_kwargs
)
text = "Why are you a doctor?"
query_result = embeddings.embed_query(text)
query_result[:3]
[-0.059351932257413864, 0.08008933067321777, 0.040729623287916183]

8. Converta os dados em embeddings e salve-os no banco de dados de vetores.

9. Salve o banco de dados de vetores no diretório local.

10. Faça uma pesquisa de similaridade usando o prompt de amostra.

vector_db = FAISS.from_documents(doctor_data, embeddings)
vector_db.save_local("/kaggle/working/faiss_doctor_index")
question = "Hi Doctor, I have a headache, help me."
searchDocs = vector_db.similarity_search(question)
print(searchDocs[0].page_content)

resultado de pesquisa de similaridade.

11. Converta a instância do banco de dados vetorial em um retriever. Isso nos ajudará a criar a cadeia RAG.

retriever = vector_db.as_retriever()

12. Carregue o tokenizador e o modelo usando o modelo do Llama 3 8B Chat.

13. Use-os para criar o pipeline de geração de testes.

14. Converta o pipeline no cliente LangChain LLM.

import torch
base_model = "/kaggle/input/llama-3/transformers/8b-chat-hf/1"

tokenizer = AutoTokenizer.from_pretrained(base_model)

model = AutoModelForCausalLM.from_pretrained(
        base_model,
        return_dict=True,
        low_cpu_mem_usage=True,
        torch_dtype=torch.float16,
        device_map="auto",
        trust_remote_code=True,
)

pipe = pipeline(
    "text-generation", 
    model=model, 
    tokenizer=tokenizer,
    max_new_tokens=120
)

llm = HuggingFacePipeline(pipeline=pipe)

15. Crie uma cadeia de perguntas e respostas usando o retriever, a consulta do usuário, o prompt do RAG e o LLM.

from langchain import hub
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough


rag_prompt = hub.pull("rlm/rag-prompt")




qa_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | rag_prompt
    | llm
    | StrOutputParser()
)

16. Teste a cadeia de perguntas e respostas fazendo perguntas ao médico.

question = "Hi Doctor, I have a headache, help me."
result = qa_chain.invoke(question)
print(result.split("Answer: ")[1])

Ele é bastante semelhante ao conjunto de dados, mas não capta o estilo. Você entendeu o contexto e o utilizou para escrever a resposta em seu próprio estilo. 

Resultado da cadeia RAG

Vamos tentar novamente com outra pergunta. 

question = "Hello doctor, I have bad acne. How do I get rid of it?"
result = qa_chain.invoke(question)
print(result.split("Answer: ")[1])

Essa é uma resposta muito direta. Talvez seja necessário ajustar o modelo em vez de usar a abordagem RAG para o chatbot do médico e do paciente. 

Resultado da cadeia RAG

Se você estiver encontrando dificuldades para executar o código, consulte o notebook do Kaggle: Criação do aplicativo RAG usando o Llama 3.

Saiba como melhorar o desempenho do sistema RAG com técnicas como Chunking, Reranking e Query Transformations seguindo o site How to Improve RAG Performance: 5 técnicas principais com exemplos tutorial.

Ajuste fino do Llama 3 em dados médicos

Não faremos o ajuste fino do modelo no conjunto de dados do médico e do paciente porque já fizemos isso em um tutorial anterior: Ajustando o Llama 3 e usando-o localmente: Um guia passo a passo. O que faremos é carregar o modelo ajustado e fornecer a ele a mesma pergunta para avaliar os resultados. O modelo ajustado está disponível no Hugging Face e no Kaggle.

Se estiver interessado em fazer o ajuste fino do modelo GPT-4 usando a API da OpenAI, você pode consultar o tutorial fácil de seguir do DataCamp Fine-Tuning OpenAI's GPT-4: Um guia passo a passo.

modelo ajustado em Hugging Face

Fonte: kingabzpro/llama-3-8b-chat-doctor

1. Carregue o tokenizador e o modelo usando a biblioteca do transformador.

2. Certifique-se de que você use os parâmetros corretos para carregar o modelo no ambiente GPU T4 x2 do Kaggle.

from transformers import AutoTokenizer,AutoModelForCausalLM,pipeline
import torch

base_model = "/kaggle/input/fine-tuned-adapter-to-full-model/llama-3-8b-chat-doctor/"

tokenizer = AutoTokenizer.from_pretrained(base_model)

model = AutoModelForCausalLM.from_pretrained(
        base_model,
        return_dict=True,
        low_cpu_mem_usage=True,
        torch_dtype=torch.float16,
        device_map="auto",
        trust_remote_code=True,
)

3. Aplique o modelo de bate-papo às mensagens.

4. Crie um pipeline de geração de texto usando o modelo e o tokenizador.

5. Forneça ao objeto do pipeline um prompt e gere a resposta.

messages = [{"role": "user", "content": "Hi Doctor, I have a headache, help me."}]

prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
pipe = pipeline(
    "text-generation",
    model=model,
    tokenizer=tokenizer,
    torch_dtype=torch.float16,
    device_map="auto",
)

outputs = pipe(prompt, max_new_tokens=120, do_sample=True)
print(outputs[0]["generated_text"])

A resposta é bastante semelhante ao conjunto de dados. O estilo é o mesmo, mas em vez de dar uma resposta direta, ele sugere que o paciente faça mais exames.

resultado gerado a partir do modelo Llama3 ajustado

6. Vamos fazer a segunda pergunta.

messages = [{"role": "user", "content": "Hello doctor, I have bad acne. How do I get rid of it?"}]

prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
outputs = pipe(prompt, max_new_tokens=120, do_sample=True)
print(outputs[0]["generated_text"])

O estilo é o mesmo, e a resposta é bastante empática e explicativa. 

resultado gerado a partir do modelo Llama3 ajustado

Se você estiver encontrando dificuldades para executar o código, consulte o notebook do Kaggle: Inferência de alta frequência da Llama 3 com ajuste fino.

Abordagem híbrida (RAG + ajuste fino)

Agora, forneceremos ao modelo ajustado um contexto adicional para ajustar ainda mais a resposta e encontrar o equilíbrio. 

Em vez de escrever todo o código novamente, vamos nos aprofundar diretamente na geração de respostas usando a cadeia de perguntas e respostas. Se você quiser ver o código completo de como combinamos um modelo de ajuste fino com uma cadeia RAG de perguntas e respostas, dê uma olhada em Abordagem híbrida (RAG + ajuste fino) Caderno do Kaggle.

Forneça à cadeia as mesmas perguntas que fizemos ao RAG e ao modelo ajustado.

question = "Hi Doctor, I have a headache, help me."
result = qa_chain.invoke(question)
print(result.split("Answer: ")[1])

A resposta é bastante precisa, e a resposta é gerada no estilo do médico. 

resultado gerado a partir da abordagem híbrida (RAG + ajuste fino)

Vamos fazer a segunda pergunta.

question = "Hello doctor, I have bad acne. How do I get rid of it?"
result = qa_chain.invoke(question)
print(result.split("Answer: ")[1])

Isso é estranho. Nunca fornecemos contexto adicional sobre o fato de a acne estar cheia de pus ou não. Talvez o modelo Hybrid não se aplique a algumas consultas. 

resultado gerado a partir da abordagem híbrida (RAG + ajuste fino)

No caso de um chatbot médico-paciente, o modelo ajustado é excelente em termos de adoção de estilo e precisão. No entanto, isso pode variar para outros casos de uso, e é por isso que é importante realizar testes extensivos para determinar o melhor método para seu caso de uso específico.

O termo oficial para a abordagem híbrida é RAFT (Retrieval Augmented Fine-Tuning). Para saber mais sobre o assunto, leia . O que é RAFT? Combinando RAG e ajuste fino para adaptar LLMs a domínios especializados blog.

Como escolher entre RAG, ajuste fino ou RAFT

Tudo depende do seu caso de uso e dos recursos disponíveis. Se você for uma startup com recursos limitados, tente criar uma prova de conceito de RAG usando a API Open AI e a estrutura LangChain. Para isso, você precisará de recursos, conhecimentos e conjuntos de dados limitados. 

Se você for uma empresa de nível médio e quiser fazer um ajuste fino para melhorar a precisão da resposta e implantar o modelo de código aberto na nuvem, precisará contratar especialistas como cientistas de dados e engenheiros de operações de machine learning. O ajuste fino requer GPUs de primeira linha, memória grande, um conjunto de dados limpo e uma equipe técnica que entenda de LLMs. 

Uma solução híbrida consome muitos recursos e computação. Isso também requer um engenheiro de LLMOps que possa equilibrar o ajuste fino e o RAG. Você deve considerar isso quando quiser melhorar ainda mais a geração de respostas, aproveitando as boas qualidades do RAG e de um modelo ajustado. 

Consulte a tabela abaixo para obter uma visão geral das soluções RAG, de ajuste fino e RAFT.

 

RAG

Ajuste fino

RAFT

Vantagens

Compreensão contextual, minimiza alucinações, adapta-se facilmente a novos dados, é econômico.

Conhecimento específico da tarefa, personalização, precisão aprimorada, maior robustez.

Combina os pontos fortes do RAG e do ajuste fino, com compreensão e contexto mais profundos.

Desvantagens

Gerenciamento de fontes de dados, complexidade.

Viés de dados, uso intensivo de recursos, altos custos de computação, requisitos substanciais de memória, uso intensivo de tempo e conhecimento.

Complexidade na implementação, requer o equilíbrio dos processos de recuperação e ajuste fino.

Complexidade de implementação

Superior à engenharia imediata.

Superior ao RAG. Requer especialistas altamente técnicos.

O mais complexo dos três.

Estilo de aprendizagem

Dinâmico

Estático

Dinâmico + Estático

Adaptabilidade

Adapta-se facilmente a novos dados e fatos em evolução.

Personalize os resultados para tarefas e domínios específicos.

Adapta-se a dados em tempo real e a tarefas específicas.

Custo

Baixa

Moderado

Alta

Intensidade de recursos

Baixo. Os recursos são usados durante a Inferência. 

Moderado. Os recursos são usados durante o ajuste fino. 

Alta

Conclusão

Os modelos de linguagem grandes estão no centro do desenvolvimento da IA atualmente. As empresas estão procurando várias maneiras de aprimorar e personalizar esses modelos sem gastar milhões de dólares em treinamento. Eles começam com a otimização de parâmetros e a engenharia imediata. Eles selecionam o RAG ou ajustam o modelo para obter uma resposta ainda melhor e reduzir as alucinações. Embora existam outras técnicas para melhorar a resposta, essas são as opções mais populares disponíveis.

Neste tutorial, aprendemos sobre as diferenças entre RAG e ajuste fino por meio de teoria e exemplos práticos. Também exploramos modelos híbridos e comparamos qual método pode funcionar melhor para você.

Para saber mais sobre a implementação de LLMs e as várias técnicas envolvidas, confira nosso code-along sobre RAG com LLaMAIndex e nosso curso sobre implantação de aplicativos LLM com LangChain.

Temas

Principais cursos da DataCamp

curso

Developing LLM Applications with LangChain

3 hr
7.8K
Discover how to build AI-powered applications using LLMs, prompts, chains, and agents in LangChain.
Ver DetalhesRight Arrow
Iniciar curso
Ver maisRight Arrow
Relacionado

tutorial

Guia de Introdução ao Ajuste Fino de LLMs

O ajuste fino dos grandes modelos de linguagem (LLMs, Large Language Models) revolucionou o processamento de linguagem natural (PLN), oferecendo recursos sem precedentes em tarefas como tradução de idiomas, análise de sentimentos e geração de textos. Essa abordagem transformadora aproveita modelos pré-treinados como o GPT-2, aprimorando seu desempenho em domínios específicos pelo processo de ajuste fino.
Josep Ferrer's photo

Josep Ferrer

12 min

tutorial

Como fazer o ajuste fino do GPT 3.5: Liberando todo o potencial da IA

Explore o GPT-3.5 Turbo e descubra o potencial transformador do ajuste fino. Saiba como personalizar esse modelo de linguagem avançado para aplicativos de nicho, aprimorar seu desempenho e entender os custos associados, a segurança e as considerações de privacidade.
Moez Ali's photo

Moez Ali

11 min

tutorial

IA explicável - Entendendo e confiando nos modelos de aprendizado de máquina

Mergulhe na IA explicável (XAI) e saiba como criar confiança em sistemas de IA com LIME e SHAP para interpretabilidade de modelos. Entenda a importância da transparência e da justiça nas decisões baseadas em IA.
Zoumana Keita 's photo

Zoumana Keita

12 min

tutorial

Tutorial de regressão Lasso e Ridge em Python

Saiba mais sobre as técnicas de regressão lasso e ridge. Compare e analise os métodos em detalhes.
DataCamp Team's photo

DataCamp Team

10 min

tutorial

Como treinar um LLM com o PyTorch

Domine o processo de treinamento de grandes modelos de linguagem usando o PyTorch, desde a configuração inicial até a implementação final.
Zoumana Keita 's photo

Zoumana Keita

8 min

Ver maisVer mais