Desvendando a GenAI - Parte 9
Explorando Embedding e Fine Tuning com OpenAI: Exemplos Práticos em Python
Embedding com OpenAI
Cenário
Vamos criar um sistema de busca para um conjunto de documentos, onde a busca considera o contexto das palavras e não apenas a correspondência exata de termos.
Implementação
import os
import numpy as np
from openai import OpenAI
from dotenv import load_dotenv
# Carregando variáveis de ambiente a partir do arquivo .env
load_dotenv(r".env")
OPENAI_SERVICE_ACCOUNT_KEY = os.getenv("OPENAI_SERVICE_ACCOUNT_KEY")
# Configurar a chave da API
client = OpenAI(api_key=OPENAI_SERVICE_ACCOUNT_KEY)
# Lista de documentos
documents = [
"A máquina precisa de manutenção preventiva mensal.",
"O motor apresenta superaquecimento constante.",
"O filtro hidráulico deve ser trocado após 500 horas de operação.",
]
# Gerar embeddings para os documentos
document_embeddings = [
client.embeddings.create(input=doc, model="text-embedding-ada-002")
.data[0]
.embedding
for doc in documents
]
# Função para calcular similaridade (usando produto escalar)
def cosine_similarity(vec1, vec2):
return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
# Busca semântica
query = "Quando devo trocar o filtro hidráulico?"
query_embedding = (
client.embeddings.create(input=query, model="text-embedding-ada-002")
.data[0]
.embedding
)
# Encontrar o documento mais relevante
similarities = [
cosine_similarity(query_embedding, doc_emb) for doc_emb in document_embeddings
]
# > b = [0, 5, 2, 3, 4, 5]
# > np.argmax(b) # Only the first occurrence is returned.
# > 1
# argmax retorna o índice do maior valor de um vetor
most_similar_doc_index = np.argmax(similarities)
print("Documento mais relevante:", documents[most_similar_doc_index])
Resultado esperado
A busca semântica retornará o documento mais relevante com base no significado, como:
“O filtro hidráulico deve ser trocado após 500 horas de operação.”
Fine Tuning com OpenAI
Cenário
Vamos treinar um modelo para responder perguntas específicas sobre manutenção de máquinas, como interpretar códigos de erro ou fornecer orientações detalhadas.
Treinamento
O conjunto de dados deve ser preparado no formato JSONL (JSON Lines), onde cada linha contém um tríade de mensagens simulando system, user e assistant. Veja um exemplo para o contexto de manutenção. Crie um arquivo chamado finetune.jsonl com o seguinte conteúdo:
{"messages": [{"role": "system", "content": "Vocé um chatbot amigável que ajuda com respostas sobre manutenção preventiva."}, {"role": "user", "content": "O que significa o código de erro E102?\n\n###"}, {"role": "assistant", "content": " O código de erro E102 indica superaquecimento do motor. Verifique o nível de óleo e o sistema de resfriamento."}]}
{"messages": [{"role": "system", "content": "Vocé um chatbot amigável que ajuda com respostas sobre manutenção preventiva."}, {"role": "user", "content": "Como substituir o filtro hidráulico da prensa modelo X200?\n\n###"}, {"role": "assistant", "content": " Desligue a máquina, drene o óleo do sistema e instale um novo filtro modelo FH-300. Consulte o manual para etapas detalhadas."}]}
{"messages": [{"role": "system", "content": "Vocé um chatbot amigável que ajuda com respostas sobre manutenção preventiva."}, {"role": "user", "content": "Quais verificações fazer antes de ligar o torno CNC?\n\n###"}, {"role": "assistant", "content": " Certifique-se de que todas as ferramentas estão fixadas corretamente, o lubrificante está no nível adequado e o programa de operação foi carregado corretamente."}]}
{"messages": [{"role": "system", "content": "Você é um chatbot amigável que ajuda com respostas sobre manutenção preventiva."}, {"role": "user", "content": "Como verificar a tensão da correia do compressor?\n\n###"}, {"role": "assistant", "content": "Desligue o compressor e verifique a tensão pressionando a correia no meio. A tensão correta deve permitir um movimento de 1 a 2 cm. Ajuste conforme necessário."}]}
{"messages": [{"role": "system", "content": "Você é um chatbot amigável que ajuda com respostas sobre manutenção preventiva."}, {"role": "user", "content": "O que verificar antes de realizar a manutenção de uma máquina de solda?\n\n###"}, {"role": "assistant", "content": "Desligue a máquina e verifique as conexões elétricas, o nível de gás e a integridade do cabo de solda. Certifique-se de que a ventilação está funcionando corretamente."}]}
{"messages": [{"role": "system", "content": "Você é um chatbot amigável que ajuda com respostas sobre manutenção preventiva."}, {"role": "user", "content": "Qual a frequência para troca de óleo de um gerador de 20 kVA?\n\n###"}, {"role": "assistant", "content": "Recomenda-se trocar o óleo do gerador a cada 250 horas de operação ou a cada 6 meses, o que ocorrer primeiro. Verifique também o filtro de óleo a cada troca."}]}
{"messages": [{"role": "system", "content": "Você é um chatbot amigável que ajuda com respostas sobre manutenção preventiva."}, {"role": "user", "content": "Como fazer a calibração de uma balança industrial?\n\n###"}, {"role": "assistant", "content": "Para calibrar a balança, coloque pesos padrão sobre a plataforma e ajuste o visor para refletir o peso correto. Repita o processo em diferentes pontos de carga."}]}
{"messages": [{"role": "system", "content": "Você é um chatbot amigável que ajuda com respostas sobre manutenção preventiva."}, {"role": "user", "content": "O que devo verificar em um motor elétrico antes de colocá-lo em operação?\n\n###"}, {"role": "assistant", "content": "Verifique o nível de lubrificação, a integridade dos cabos de alimentação e a rotação do eixo manualmente. Certifique-se também de que o motor está limpo e sem obstruções."}]}
{"messages": [{"role": "system", "content": "Você é um chatbot amigável que ajuda com respostas sobre manutenção preventiva."}, {"role": "user", "content": "Como realizar a limpeza do filtro de ar de um compressor?\n\n###"}, {"role": "assistant", "content": "Desligue o compressor e retire o filtro de ar. Limpe-o com ar comprimido ou substitua-o, se necessário, para garantir uma boa performance do equipamento."}]}
{"messages": [{"role": "system", "content": "Você é um chatbot amigável que ajuda com respostas sobre manutenção preventiva."}, {"role": "user", "content": "O que deve ser inspecionado em uma empilhadeira antes de usá-la?\n\n###"}, {"role": "assistant", "content": "Verifique o nível de combustível ou carga da bateria, o funcionamento dos pneus, a integridade dos freios, a carga máxima permitida e os controles hidráulicos."}]}
O delimitador \n\n### no prompt ajuda o modelo a entender o início e o fim de cada pergunta.
A role user deve conter apenas a resposta sem detalhes extras.
São necessários no mínimo 10 exemplos. Não necessariamente mais exemplos melhor, pois você pode estar causando overfitting do modelo. Ou seja, criando um modelo enviesado a responder sempre com a mesma resposta sem poder de generalização.
Fine-tuning:
import os
from openai import OpenAI
from dotenv import load_dotenv
# Carregando variáveis de ambiente a partir do arquivo .env
load_dotenv(r".env")
OPENAI_SERVICE_ACCOUNT_KEY = os.getenv("OPENAI_SERVICE_ACCOUNT_KEY")
# Configurar a chave da API
client = OpenAI(api_key=OPENAI_SERVICE_ACCOUNT_KEY)
# Subir o arquivo de treinamento
file_obj = client.files.create(file=open("finetune.jsonl", "rb"), purpose="fine-tune")
# Criar modelo fine-tuned
job = client.fine_tuning.jobs.create(
training_file=file_obj.id,
# model="gpt-4o-mini-2024-07-18"
model="gpt-3.5-turbo-0125",
)
print(job.fine_tuned_model)
https://platform.openai.com/docs/guides/fine-tuning/
Você pode tunar o modelo Vision (para imagens!!!)
Pelo dashboard é possível acompanhar a evolução do treinamento, veja figura abaixo:
Ao final do treinamento pegue o id do modelo fine-tuned criado:
Ahhhhh tem custo! Quanto maior o volume de dados, maior o tempo de treinamento e consequentemente o custo pra gerar o modelo fine-tuned. Esse exemplo custou certa de $0,08 ou 40 centavos convertidos para moeda brasileira.
Utilização do modelo fine-tuned:
# O job demora uns 10min pra executar, é preciso acompanhar a evolução pelo dashboard: https://platform.openai.com/
# Quando o job finalizar você poderá acessar o nome do modelo criado para ser usado posteriormente
model_name = "ft:gpt-3.5-turbo-0125:iamferraz::AXdYDa3O"
completion = client.chat.completions.create(
model=model_name,
messages=[
{
"role": "system",
"content": "Vocé um chatbot amigável que ajuda com respostas sobre manutenção preventiva.",
},
{
"role": "user",
"content": "O que significa o código de erro E102?",
},
],
max_tokens=100,
)
print(completion.choices[0].message)
Resultado esperado
O modelo fornecerá respostas específicas baseadas nos dados de treinamento, como:
“O código de erro E102 indica superaquecimento do motor. Verifique o nível de óleo e o sistema de resfriamento.”
Esse resultado era esperado dado que passamos o seguinte dado de treinamento:
{"messages": [{"role": "system", "content": "Vocé um chatbot amigável que ajuda com respostas sobre manutenção preventiva."}, {"role": "user", "content": "O que significa o código de erro E102?\n\n###"}, {"role": "assistant", "content": " O código de erro E102 indica superaquecimento do motor. Verifique o nível de óleo e o sistema de resfriamento."}]}
Conclusão
Esses exemplos mostram como utilizar embeddings para busca semântica e fine tuning para personalizar respostas. Enquanto embeddings são úteis para tarefas que envolvem similaridade e organização de informações, o fine tuning é ideal para criar modelos ajustados às necessidades específicas do seu negócio. Ambas as abordagens oferecem soluções eficientes para problemas reais. Para saber mais sobre esses conceitos veja o post anterior.
Deixo um desafio: Incrementar a busca por similaridade para responder de forma “Humanizada“ usando uma LLM.
O código fonte pode ser encontrado aqui!