rag_code.py•9.22 kB
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from tqdm import tqdm
from qdrant_client import models
from qdrant_client import QdrantClient
faq_text = """
**Pergunta 1: Qual é o primeiro passo antes de construir um modelo de aprendizado de máquina?**
Resposta 1: Entender o problema, definir o objetivo e identificar as métricas corretas para avaliação.
**Pergunta 2: Qual a importância da limpeza de dados em ML?**
Resposta 2: Extremamente importante. Dados limpos melhoram o desempenho do modelo e reduzem a chance de resultados enganosos.
**Pergunta 3: Devo normalizar ou padronizar meus dados?**
Resposta 3: Sim, especialmente para modelos sensíveis à escala das variáveis, como SVMs, KNN e redes neurais.
**Pergunta 4: Quando devo usar engenharia de atributos (feature engineering)?**
Resposta 4: Sempre considere isso. Atributos bem construídos frequentemente geram melhores resultados do que modelos complexos.
**Pergunta 5: Como lidar com valores ausentes?**
Resposta 5: Use técnicas de imputação como média/mediana, ou imputação baseada em modelos, dependendo do contexto.
**Pergunta 6: Devo balancear meu conjunto de dados para tarefas de classificação?**
Resposta 6: Sim, especialmente se as classes estiverem desbalanceadas. Técnicas incluem reamostragem, SMOTE e ponderação de classes.
**Pergunta 7: Como selecionar atributos para meu modelo?**
Resposta 7: Use conhecimento do domínio, análise de correlação ou técnicas como Eliminação Recursiva de Atributos (RFE) ou valores SHAP.
**Pergunta 8: É bom usar todos os atributos disponíveis?**
Resposta 8: Nem sempre. Atributos irrelevantes ou redundantes podem reduzir o desempenho e aumentar o sobreajuste (overfitting).
**Pergunta 9: Como evitar o sobreajuste (overfitting)?**
Resposta 9: Use técnicas como validação cruzada, regularização, poda (para árvores) e dropout (para redes neurais).
**Pergunta 10: Por que a validação cruzada é importante?**
Resposta 10: Ela fornece uma estimativa mais confiável do desempenho do modelo ao reduzir o viés de uma única divisão treino-teste.
**Pergunta 11: Qual é uma boa proporção para divisão treino-teste?**
Resposta 11: Proporções comuns são 80/20 ou 70/30, mas utilize validação cruzada para uma avaliação mais robusta.
**Pergunta 12: Devo ajustar hiperparâmetros?**
Resposta 12: Sim. Use grid search, random search ou otimização bayesiana para melhorar o desempenho do modelo.
**Pergunta 13: Qual a diferença entre conjuntos de treino e validação?**
Resposta 13: O conjunto de treino treina o modelo, o conjunto de validação ajusta os hiperparâmetros e o conjunto de teste avalia o desempenho final.
**Pergunta 14: Como saber se meu modelo está com subajuste (underfitting)?**
Resposta 14: Ele apresenta baixo desempenho tanto no treino quanto no teste, indicando que não aprendeu bem os padrões.
**Pergunta 15: Quais são os sinais de sobreajuste (overfitting)?**
Resposta 15: Alta precisão nos dados de treino, mas baixa generalização para os dados de teste ou validação.
**Pergunta 16: Modelos de comitê (ensemble) são úteis?**
Resposta 16: Sim. Modelos ensemble como Random Forests ou Gradient Boosting frequentemente superam modelos individuais.
**Pergunta 17: Quando devo usar aprendizado profundo (deep learning)?**
Resposta 17: Quando você tem grandes volumes de dados, padrões complexos ou tarefas como processamento de imagens e texto.
**Pergunta 18: O que é vazamento de dados (data leakage) e como evitá-lo?**
Resposta 18: É o uso de informações futuras ou relacionadas ao alvo durante o treino. Evite com divisões cuidadosas e pré-processamento adequado.
**Pergunta 19: Como medir o desempenho do modelo?**
Resposta 19: Escolha métricas apropriadas: acurácia, precisão, recall, F1, ROC-AUC para classificação; RMSE e MAE para regressão.
**Pergunta 20: Por que a interpretabilidade do modelo é importante?**
Resposta 20: Ela gera confiança, auxilia na depuração e garante conformidade — especialmente em áreas críticas como a saúde.
"""
# Preprocess the FAQ text
# Remove extra spaces and newlines
new_faq_text = [i.replace("\n", " ") for i in faq_text.split("\n\n")]
def batch_iterate(lst, batch_size):
for i in range(0, len(lst), batch_size):
yield lst[i : i + batch_size]
class EmbedData:
def __init__(self,
embed_model_name="nomic-ai/nomic-embed-text-v1.5",
batch_size=32):
self.embed_model_name = embed_model_name
self.embed_model = self._load_embed_model()
self.batch_size = batch_size
self.embeddings = []
def _load_embed_model(self):
embed_model = HuggingFaceEmbedding(model_name=self.embed_model_name,
trust_remote_code=True,
cache_folder='./hf_cache'
)
return embed_model
def generate_embedding(self, context):
return self.embed_model.get_text_embedding_batch(context)
def embed(self, contexts):
self.contexts = contexts
for batch_context in tqdm(batch_iterate(contexts, self.batch_size),
total=len(contexts)//self.batch_size,
desc="Embedding data in batches"):
batch_embeddings = self.generate_embedding(batch_context)
self.embeddings.extend(batch_embeddings)
class QdrantVDB:
def __init__(self, collection_name, vector_dim=768, batch_size=512):
self.collection_name = collection_name
self.batch_size = batch_size
self.vector_dim = vector_dim
self.define_client()
def define_client(self):
self.client = QdrantClient(url="http://localhost:6333",
prefer_grpc=True)
def create_collection(self):
if not self.client.collection_exists(collection_name=self.collection_name):
self.client.create_collection(collection_name=self.collection_name,
vectors_config=models.VectorParams(
size=self.vector_dim,
distance=models.Distance.DOT,
on_disk=True),
optimizers_config=models.OptimizersConfigDiff(
default_segment_number=5,
indexing_threshold=0)
)
def ingest_data(self, embeddata):
for batch_context, batch_embeddings in tqdm(zip(batch_iterate(embeddata.contexts, self.batch_size),
batch_iterate(embeddata.embeddings, self.batch_size)),
total=len(embeddata.contexts)//self.batch_size,
desc="Ingesting in batches"):
self.client.upload_collection(collection_name=self.collection_name,
vectors=batch_embeddings,
payload=[{"context": context} for context in batch_context])
self.client.update_collection(collection_name=self.collection_name,
optimizer_config=models.OptimizersConfigDiff(indexing_threshold=20000)
)
class Retriever:
def __init__(self, vector_db, embeddata):
self.vector_db = vector_db
self.embeddata = embeddata
def search(self, query):
query_embedding = self.embeddata.embed_model.get_query_embedding(query)
# select the top 3 results
result = self.vector_db.client.search(
collection_name=self.vector_db.collection_name,
query_vector=query_embedding,
search_params=models.SearchParams(
quantization=models.QuantizationSearchParams(
ignore=True,
rescore=True,
oversampling=2.0,
)
),
limit=3,
timeout=1000,
)
context = [dict(data) for data in result]
combined_prompt = []
for entry in context[:3]:
context = entry["payload"]["context"]
combined_prompt.append(context)
final_output = "\n\n---\n\n".join(combined_prompt)
return final_output