Para obtener ideas adicionales sobre cómo mejorar el rendimiento de su canalización RAG para que esté listo para producción, continúe leyendo aquí:
Esta sección analiza los paquetes necesarios y las claves API a seguir en este artículo.
Paquetes requeridos
Este artículo lo guiará a través de la implementación de una canalización RAG ingenua y avanzada utilizando LlamaIndex en pitón.
pip install llama-index
En este artículo, usaremos LlamaIndex v0.10. Si está actualizando desde una versión anterior de LlamaIndex, debe ejecutar los siguientes comandos para instalar y ejecutar LlamaIndex correctamente:
pip uninstall llama-index
pip install llama-index --upgrade --no-cache-dir --force-reinstall
LlamaIndex ofrece una opción para almacenar incrustaciones de vectores localmente en archivos JSON para un almacenamiento persistente, lo cual es excelente para crear rápidamente prototipos de una idea. Sin embargo, utilizaremos una base de datos vectorial para el almacenamiento persistente, ya que las técnicas RAG avanzadas apuntan a aplicaciones listas para producción.
Dado que necesitaremos almacenamiento de metadatos y capacidades de búsqueda híbrida además de almacenar las incrustaciones de vectores, utilizaremos la base de datos de vectores de código abierto. Weaviate (v3.26.2), que admite estas características.
pip install weaviate-client llama-index-vector-stores-weaviate
Claves API
Usaremos Weaviate integrado, que puede usar de forma gratuita sin registrarse para obtener una clave API. Sin embargo, este tutorial utiliza un modelo de incrustación y LLM de AbiertoAI, para lo cual necesitará una clave API de OpenAI. Para obtener una, necesita una cuenta OpenAI y luego “Crear nueva clave secreta” en Claves API.
A continuación, cree un local .env archivo en su directorio raíz y defina sus claves API en él:
OPENAI_API_KEY="<YOUR_OPENAI_API_KEY>"
Luego, puede cargar sus claves API con el siguiente código:
# !pip install python-dotenv
import os
from dotenv import load_dotenv,find_dotenvload_dotenv(find_dotenv())
Esta sección analiza cómo implementar una canalización RAG ingenua utilizando LlamaIndex. Puede encontrar todo el ingenuo proceso RAG en este Cuaderno Jupyter. Para la implementación usando LangChain, puede continuar en este artículo (canalización ingenua de RAG que utiliza LangChain).
Paso 1: definir el modelo de integración y el LLM
Primero, puede definir un modelo de incrustación y LLM en un objeto de configuración global. Hacer esto significa que no es necesario volver a especificar los modelos explícitamente en el código.
- Modelo de incrustación: se utiliza para generar incrustaciones de vectores para los fragmentos del documento y la consulta.
- LLM: se utiliza para generar una respuesta basada en la consulta del usuario y el contexto relevante.
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
from llama_index.core.settings import SettingsSettings.llm = OpenAI(model="gpt-3.5-turbo", temperature=0.1)
Settings.embed_model = OpenAIEmbedding()
Paso 2: cargar datos
A continuación, creará un directorio local llamado data en su directorio raíz y descargue algunos datos de ejemplo del Repositorio LlamaIndex GitHub (Licencia MIT).
!mkdir -p 'data'
!wget '<https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt>' -O 'data/paul_graham_essay.txt'
Luego, puede cargar los datos para su posterior procesamiento:
from llama_index.core import SimpleDirectoryReader# Load data
documents = SimpleDirectoryReader(
input_files=["./data/paul_graham_essay.txt"]
).load_data()
Paso 3: fragmentar documentos en nodos
Como el documento completo es demasiado grande para caber en la ventana contextual del LLM, deberá dividirlo en fragmentos de texto más pequeños, que se denominan Nodes en LlamaIndex. Puede analizar los documentos cargados en nodos utilizando el SimpleNodeParser con un tamaño de fragmento definido de 1024.
from llama_index.core.node_parser import SimpleNodeParsernode_parser = SimpleNodeParser.from_defaults(chunk_size=1024)
# Extract nodes from documents
nodes = node_parser.get_nodes_from_documents(documents)
Paso 4: crear índice
A continuación, creará el índice que almacena todo el conocimiento externo en Weaviateuna base de datos vectorial de código abierto.
Primero, deberá conectarse a una instancia de Weaviate. En este caso, estamos usando Weaviate integrado, que le permite experimentar en Notebooks de forma gratuita sin una clave API. Para obtener una solución lista para producción, implemente Weaviate usted mismo, por ejemplo, a través de ventana acoplable o utilizando un servicio gestionadoes recomendado.
import weaviate# Connect to your Weaviate instance
client = weaviate.Client(
embedded_options=weaviate.embedded.EmbeddedOptions(),
)
A continuación, construirá un VectorStoreIndex del cliente Weaviate para almacenar sus datos e interactuar con ellos.
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.weaviate import WeaviateVectorStoreindex_name = "MyExternalContext"
# Construct vector store
vector_store = WeaviateVectorStore(
weaviate_client = client,
index_name = index_name
)
# Set up the storage for the embeddings
storage_context = StorageContext.from_defaults(vector_store=vector_store)
# Setup the index
# build VectorStoreIndex that takes care of chunking documents
# and encoding chunks to embeddings for future retrieval
index = VectorStoreIndex(
nodes,
storage_context = storage_context,
)
Paso 5: configurar el motor de consultas
Por último, configurará el índice como motor de consultas.
# The QueryEngine class is equipped with the generator
# and facilitates the retrieval and generation steps
query_engine = index.as_query_engine()
Paso 6: Ejecute una consulta RAG ingenua sobre sus datos
Ahora, puede ejecutar una consulta RAG ingenua en sus datos, como se muestra a continuación:
# Run your naive RAG query
response = query_engine.query(
"What happened at Interleaf?"
)
En esta sección, cubriremos algunos ajustes simples que puede realizar para convertir el ingenuo proceso RAG anterior en uno avanzado. Este tutorial cubrirá la siguiente selección de técnicas RAG avanzadas:
Como aquí solo cubriremos las modificaciones, puede encontrar el canalización RAG avanzada completa de extremo a extremo en este Jupyter Notebook.
Para el técnica de recuperación de ventana de oración, debe realizar dos ajustes: primero, debe ajustar la forma en que almacena y posprocesa sus datos. En vez de SimpleNodeParserusaremos el SentenceWindowNodeParser.
from llama_index.core.node_parser import SentenceWindowNodeParser# create the sentence window node parser w/ default settings
node_parser = SentenceWindowNodeParser.from_defaults(
window_size=3,
window_metadata_key="window",
original_text_metadata_key="original_text",
)
El SentenceWindowNodeParser hace dos cosas:
- Separa el documento en oraciones individuales, que se incrustarán.
- Para cada oración, crea una ventana de contexto. Si especifica un
window_size = 3, la ventana resultante tendrá tres oraciones, comenzando en la oración anterior de la oración incrustada y abarcando la oración posterior. La ventana se almacenará como metadatos.
Durante la recuperación, se devuelve la frase que más se acerque a la consulta. Después de la recuperación, debe reemplazar la oración con la ventana completa de los metadatos definiendo un MetadataReplacementPostProcessor y usarlo en la lista de node_postprocessors.
from llama_index.core.postprocessor import MetadataReplacementPostProcessor# The target key defaults to `window` to match the node_parser's default
postproc = MetadataReplacementPostProcessor(
target_metadata_key="window"
)
...
query_engine = index.as_query_engine(
node_postprocessors = [postproc],
)
Implementar una búsqueda híbrida en LlamaIndex es tan fácil como cambiar dos parámetros en el query_engine si la base de datos de vectores subyacente admite consultas de búsqueda híbridas. El alpha El parámetro especifica la ponderación entre la búsqueda vectorial y la búsqueda basada en palabras clave, donde alpha=0 significa búsqueda basada en palabras clave y alpha=1 significa búsqueda vectorial pura.
query_engine = index.as_query_engine(
...,
vector_store_query_mode="hybrid",
alpha=0.5,
...
)
Agregar un reranker a su canal RAG avanzado solo requiere tres simples pasos:
- Primero, defina un modelo de reclasificación. Aquí estamos usando el
BAAI/bge-reranker-basede abrazar la cara. - En el motor de consultas, agregue el modelo de reranker a la lista de
node_postprocessors. - Aumenta el
similarity_top_ken el motor de consulta para recuperar más pasajes de contexto, que se pueden reducir atop_ndespués de reclasificar.
# !pip install torch sentence-transformers
from llama_index.core.postprocessor import SentenceTransformerRerank# Define reranker model
rerank = SentenceTransformerRerank(
top_n = 2,
model = "BAAI/bge-reranker-base"
)
...
# Add reranker to query engine
query_engine = index.as_query_engine(
similarity_top_k = 6,
...,
node_postprocessors = [rerank],
...,
)