Generazione avanzata di recupero avanzato: dalla teoria all’implementazione di LlamaIndex |  di Leonie Monigatti |  Febbraio 2024

 | Intelligenza-Artificiale

Per ulteriori idee su come migliorare le prestazioni della pipeline RAG per renderla pronta per la produzione, continua a leggere qui:

In questa sezione vengono illustrati i pacchetti e le chiavi API richiesti da seguire in questo articolo.

Pacchetti richiesti

Questo articolo ti guiderà attraverso l’implementazione di una pipeline RAG ingenua e avanzata utilizzando LlamaIndex in Pitone.

pip install llama-index

In questo articolo utilizzeremo LlamaIndex v0.10. Se stai eseguendo l’aggiornamento da una versione precedente di LlamaIndex, devi eseguire i seguenti comandi per installare ed eseguire LlamaIndex correttamente:

pip uninstall llama-index
pip install llama-index --upgrade --no-cache-dir --force-reinstall

LlamaIndex offre un’opzione per archiviare incorporamenti di vettori localmente in file JSON per l’archiviazione persistente, il che è ottimo per prototipare rapidamente un’idea. Tuttavia, utilizzeremo un database vettoriale per l’archiviazione persistente poiché le tecniche RAG avanzate mirano ad applicazioni pronte per la produzione.

Poiché avremo bisogno di archiviazione di metadati e funzionalità di ricerca ibrida oltre all’archiviazione degli incorporamenti vettoriali, utilizzeremo il database vettoriale open source Tessitura (v3.26.2), che supporta queste funzionalità.

pip install weaviate-client llama-index-vector-stores-weaviate

Chiavi API

Utilizzeremo Weaviate embedded, che puoi utilizzare gratuitamente senza registrarti per una chiave API. Tuttavia, questa esercitazione utilizza un modello di incorporamento e LLM da OpenAIper il quale avrai bisogno di una chiave API OpenAI. Per ottenerne uno è necessario un account OpenAI e poi “Crea nuova chiave segreta” sotto Chiavi API.

Successivamente, crea un local .env file nella directory root e definisci le tue chiavi API al suo interno:

OPENAI_API_KEY="<YOUR_OPENAI_API_KEY>"

Successivamente, puoi caricare le tue chiavi API con il seguente codice:

# !pip install python-dotenv
import os
from dotenv import load_dotenv,find_dotenv

load_dotenv(find_dotenv())

In questa sezione viene illustrato come implementare una pipeline RAG ingenua utilizzando LlamaIndex. Puoi trovare l’intera ingenua pipeline RAG in questo Taccuino di Giove. Per l’implementazione utilizzando LangChain, puoi continuare questo articolo (pipeline RAG ingenua che utilizza LangChain).

Passaggio 1: definire il modello di incorporamento e LLM

Innanzitutto è possibile definire un modello di incorporamento e un LLM in un oggetto delle impostazioni globali. Ciò significa che non è necessario specificare nuovamente i modelli esplicitamente nel codice.

  • Modello di incorporamento: utilizzato per generare incorporamenti di vettori per i blocchi di documento e la query.
  • LLM: utilizzato per generare una risposta in base alla query dell’utente e al contesto pertinente.
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
from llama_index.core.settings import Settings

Settings.llm = OpenAI(model="gpt-3.5-turbo", temperature=0.1)
Settings.embed_model = OpenAIEmbedding()

Passaggio 2: caricare i dati

Successivamente, creerai una directory locale denominata data nella directory principale e scarica alcuni dati di esempio dal file Repository GitHub di LlamaIndex (licenza 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'

Successivamente è possibile caricare i dati per un’ulteriore elaborazione:

from llama_index.core import SimpleDirectoryReader

# Load data
documents = SimpleDirectoryReader(
input_files=("./data/paul_graham_essay.txt")
).load_data()

Passaggio 3: suddividere i documenti in nodi

Poiché l’intero documento è troppo grande per adattarsi alla finestra di contesto di LLM, sarà necessario suddividerlo in parti di testo più piccole, chiamate Nodes in LlamaIndex. È possibile analizzare i documenti caricati in nodi utilizzando il file SimpleNodeParser con una dimensione del blocco definita pari a 1024.

from llama_index.core.node_parser import SimpleNodeParser

node_parser = SimpleNodeParser.from_defaults(chunk_size=1024)

# Extract nodes from documents
nodes = node_parser.get_nodes_from_documents(documents)

Passaggio 4: crea l’indice

Successivamente, creerai l’indice in cui archivia tutta la conoscenza esterna Tessituraun database vettoriale open source.

Innanzitutto, dovrai connetterti a un’istanza Weaviate. In questo caso, stiamo utilizzando Weaviate incorporatoche ti consente di sperimentare gratuitamente su Notebook senza una chiave API. Per una soluzione pronta per la produzione, distribuire Weaviate da soli, ad esempio, tramite Docker o utilizzando a servizio gestitoè raccomandato.

import weaviate

# Connect to your Weaviate instance
client = weaviate.Client(
embedded_options=weaviate.embedded.EmbeddedOptions(),
)

Successivamente, costruirai un file VectorStoreIndex dal client Weaviate per archiviare i tuoi dati e con cui interagire.

from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.weaviate import WeaviateVectorStore

index_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,
)

Passaggio 5: imposta il motore di query

Infine, imposterai l’indice come motore di query.

# The QueryEngine class is equipped with the generator
# and facilitates the retrieval and generation steps
query_engine = index.as_query_engine()

Passaggio 6: esegui una query RAG ingenua sui tuoi dati

Ora puoi eseguire una query RAG ingenua sui tuoi dati, come mostrato di seguito:

# Run your naive RAG query
response = query_engine.query(
"What happened at Interleaf?"
)

In questa sezione, tratteremo alcune semplici modifiche che puoi apportare per trasformare la pipeline RAG ingenua di cui sopra in una pipeline avanzata. Questa procedura dettagliata coprirà la seguente selezione di tecniche RAG avanzate:

Poiché qui tratteremo solo le modifiche, puoi trovare il file pipeline RAG avanzata end-to-end completa in questo Jupyter Notebook.

Per il tecnica di recupero della finestra di frasedevi apportare due modifiche: in primo luogo, devi modificare il modo in cui archivi e post-elabora i tuoi dati. Invece del SimpleNodeParseruseremo il 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",
)

IL SentenceWindowNodeParser fa due cose:

  1. Separa il documento in singole frasi, che verranno incorporate.
  2. Per ogni frase, crea una finestra di contesto. Se specifichi a window_size = 3la finestra risultante sarà lunga tre frasi, iniziando dalla frase precedente della frase incorporata e attraversando la frase successiva. La finestra verrà archiviata come metadati.

Durante il recupero, viene restituita la frase che corrisponde maggiormente alla query. Dopo il recupero, è necessario sostituire la frase con l’intera finestra dai metadati definendo a MetadataReplacementPostProcessor e utilizzarlo nell’elenco di 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),
)

Implementare una ricerca ibrida in LlamaIndex è facile come modificare due parametri nel file query_engine se il database vettoriale sottostante supporta query di ricerca ibride. IL alpha Il parametro specifica la ponderazione tra la ricerca vettoriale e la ricerca basata su parole chiave, dove alpha=0 significa ricerca basata su parole chiave e alpha=1 significa ricerca vettoriale pura.

query_engine = index.as_query_engine(
...,
vector_store_query_mode="hybrid",
alpha=0.5,
...
)

L’aggiunta di un reranker alla tua pipeline RAG avanzata richiede solo tre semplici passaggi:

  1. Innanzitutto, definire un modello di riclassificazione. Qui stiamo usando il BAAI/bge-reranker-baseda Il viso che abbraccia.
  2. Nel motore di query, aggiungi il modello di riclassificazione all’elenco di node_postprocessors.
  3. Aumentare il similarity_top_k nel motore di query per recuperare più passaggi di contesto, che possono essere ridotti a top_n dopo la riclassificazione.
# !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),
...,
)

Fonte: towardsdatascience.com

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *