Chatbot RAG con Pinecone y OpenAI

Bases de datos vectoriales para incrustaciones con Pinecone

James Chapman

Curriculum Manager, DataCamp

Retrieval Augmented Generation (RAG)

  1. Genera el embedding de la consulta
  2. Recupera documentos similares
  3. Añade documentos al prompt

generación aumentada por recuperación

Bases de datos vectoriales para incrustaciones con Pinecone

Inicializar Pinecone y OpenAI

from openai import OpenAI
from pinecone import Pinecone
import pandas as pd
from uuid import uuid4


client = OpenAI(api_key="OPENAI_API_KEY") pc = Pinecone(api_key="PINECONE_API_KEY")
index = pc.Index("semantic-search-datacamp")
Bases de datos vectoriales para incrustaciones con Pinecone

Transcripciones de YouTube

youtube_df = pd.read_csv('youtube_rag_data.csv')
| id | blob | channel_id | end | published | start | text | title | url |
|----|------|------------|-----|-----------|-------|------|-------|-----|
|int | dict | str        | int | datetime  | int   | str  | str   | str |
Bases de datos vectoriales para incrustaciones con Pinecone

Ingesta de documentos

batch_limit = 100


for batch in np.array_split(youtube_df, len(youtube_df) / batch_limit):
metadatas = [{"text_id": row['id'], "text": row['text'], "title": row['title'], "url": row['url'], "published": row['published']} for _, row in batch.iterrows()]
texts = batch['text'].tolist()
ids = [str(uuid4()) for _ in range(len(texts))]
response = client.embeddings.create(input=texts, model="text-embedding-3-small") embeds = [np.array(x.embedding) for x in response.data]
index.upsert(vectors=zip(ids, embeds, metadatas), namespace='youtube_rag_dataset')
Bases de datos vectoriales para incrustaciones con Pinecone

Función de recuperación

def retrieve(query, top_k, namespace, emb_model):

query_response = client.embeddings.create(input=query, model=emb_model) query_emb = query_response.data[0].embedding
retrieved_docs = [] sources = [] docs = index.query(vector=query_emb, top_k=top_k, namespace='youtube_rag_dataset', include_metadata=True)
for doc in docs['matches']: retrieved_docs.append(doc['metadata']['text']) sources.append((doc['metadata']['title'], doc['metadata']['url']))
return retrieved_docs, sources
Bases de datos vectoriales para incrustaciones con Pinecone

Salida de recuperación

query = "How to build next-level Q&A with OpenAI"
documents, sources = retrieve(query, top_k=3, namespace='youtube_rag_dataset',
                              emb_model="text-embedding-3-small")
Document: Para usar en Open Domain Question Answering. Vamos a empezar...
Source: How to build a Q&A AI in Python [...], https://youtu.be/w1dMEWm7jBc

Document: Aquí tenemos Google y podemos hacerle preguntas a Google...
Source: How to build next-level Q&A with OpenAI, https://youtu.be/coaaSxys5so

Document: Necesitamos una base de datos vectorial para mejorar la calidad de los sistemas de Q&A...
Source: How to Build Custom Q&A Transfo [...], https://youtu.be/ZIRmXKHp0-c
Bases de datos vectoriales para incrustaciones con Pinecone

Función para crear prompt con contexto

def prompt_with_context_builder(query, docs):
    delim = '\n\n---\n\n'
    prompt_start = 'Answer the question based on the context below.\n\nContext:\n'
    prompt_end = f'\n\nQuestion: {query}\nAnswer:'

    prompt = prompt_start + delim.join(docs) + prompt_end
    return prompt
Bases de datos vectoriales para incrustaciones con Pinecone

Salida del creador de prompt con contexto

query = "How to build next-level Q&A with OpenAI"
context_prompt = prompt_with_context_builder(query, documents)

La salida de la función prompt_with_context_builder

Bases de datos vectoriales para incrustaciones con Pinecone

Función de preguntas y respuestas

def question_answering(prompt, sources, chat_model):

sys_prompt = "You are a helpful assistant that always answers questions."
res = client.chat.completions.create( model=chat_model, messages=[{"role": "system", "content": sys_prompt}, {"role": "user", "content": prompt} ], temperature=0)
answer = res.choices[0].message.content.strip() answer += "\n\nSources:" for source in sources: answer += "\n" + source[0] + ": " + source[1] return answer
Bases de datos vectoriales para incrustaciones con Pinecone

Salida de preguntas y respuestas

query = "How to build next-level Q&A with OpenAI"
answer = question_answering(prompt_with_context, sources,
                            chat_model='gpt-4o-mini')

La salida de la función question_answering

Bases de datos vectoriales para incrustaciones con Pinecone

Todo junto

query = "How to build next-level Q&A with OpenAI"
documents, sources = retrieve(query, top_k=3, 
                              namespace='youtube_rag_dataset', 
                              emb_model="text-embedding-3-small")
prompt_with_context = prompt_with_context_builder(query, documents)
answer = question_answering(prompt_with_context, sources,
                            chat_model='gpt-4o-mini')
Bases de datos vectoriales para incrustaciones con Pinecone

¡Vamos a practicar!

Bases de datos vectoriales para incrustaciones con Pinecone

Preparing Video For Download...