Lección 1 · 5 min · Gratis

Primeros pasos con Llama 3.1 en la nube

Open In Colab

Esta aplicación de demostración muestra:

  • Cómo ejecutar Llama 3.1 en la nube alojado en Replicate
  • Cómo usar LangChain para hacerle a Llama preguntas generales y preguntas de seguimiento
  • Cómo usar LangChain para cargar una página web reciente —la publicación del blog de Hugging Face sobre Llama 3.1— y conversar sobre ella. Este es el conocido método RAG (Generación Aumentada por Recuperación) para permitir que los LLM como Llama 3 puedan responder preguntas sobre datos no disponibles públicamente cuando Llama 3 fue entrenado, o sobre tus propios datos. RAG es una forma de prevenir la alucinación de los LLM.

Nota Usaremos Replicate para ejecutar los ejemplos aquí. Primero deberás iniciar sesión en Replicate con tu cuenta de GitHub, luego crear un token de API gratuito aquí que podrás usar por un tiempo. También puedes usar otros proveedores de la nube de Llama 3.1 como Groq, Together o Anyscale; consulta la Sección 2 del notebook "Getting to Know Llama" para más información.

Comencemos instalando los paquetes necesarios:

  • sentence-transformers para embeddings de texto
  • FAISS nos proporciona capacidades de base de datos
  • LangChain proporciona las herramientas RAG necesarias para esta demostración
!pip install langchain
!pip install sentence-transformers
!pip install faiss-cpu
!pip install bs4
!pip install replicate
!pip install langchain-community
from getpass import getpass
import os

REPLICATE_API_TOKEN = getpass()
os.environ["REPLICATE_API_TOKEN"] = REPLICATE_API_TOKEN

A continuación, llamamos al modelo de chat Llama 3.1 405b desde Replicate. También puedes usar el modelo Llama 3 8B o 70B reemplazando el nombre model con la(s) URL(s) del modelo respectivo.

from langchain_community.llms import Replicate
llm = Replicate(
    model="meta/meta-llama-3.1-405b-instruct",
    model_kwargs={"temperature": 0.0, "top_p": 1, "max_new_tokens":500}
)

Con el modelo configurado, ya estás listo para hacer algunas preguntas. Aquí tienes un ejemplo de la forma más sencilla de hacerle al modelo algunas preguntas generales.

question = "who wrote the book Innovator's dilemma?"
answer = llm.invoke(question)
print(answer)

Luego intentaremos seguir la respuesta con una pregunta pidiendo más información sobre el libro.

Dado que el historial de chat no se pasa, Llama no tiene el contexto y no sabe que esto es más sobre el libro, por lo que lo trata como una nueva consulta.

# chat history not passed so Llama doesn't have the context and doesn't know this is more about the book
followup = "tell me more"
followup_answer = llm.invoke(followup)
print(followup_answer)

Para solucionar esto, necesitaremos proporcionarle al modelo el historial del chat.

Para hacerlo, usaremos ConversationBufferMemory para pasar el historial del chat al modelo y darle la capacidad de manejar preguntas de seguimiento.

# using ConversationBufferMemory to pass memory (chat history) for follow up questions
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory()
conversation = ConversationChain(
    llm=llm, 
    memory = memory,
    verbose=False
)

Una vez configurado esto, repitamos los pasos anteriores y hagámosle al modelo una pregunta sencilla.

Luego pasamos la pregunta y la respuesta de vuelta al modelo para el contexto, junto con la pregunta de seguimiento.

# restart from the original question
answer = conversation.predict(input=question)
print(answer)
# pass context (previous question and answer) along with the follow up "tell me more" to Llama who now knows more of what
memory.save_context({"input": question},
                    {"output": answer})
followup_answer = conversation.predict(input=followup)
print(followup_answer)

A continuación, exploremos el uso de Llama 3.1 para responder preguntas utilizando documentos como contexto. Esto nos da la capacidad de actualizar el conocimiento de Llama 3.1, dándole así un mejor contexto sin necesidad de un fine-tuning.

from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader
import bs4

loader = WebBaseLoader(["https://huggingface.co/blog/llama3"])
docs = loader.load()

Necesitamos almacenar nuestro documento en un almacén vectorial. LangChain soporta más de 30 almacenes vectoriales (DBs). Para este ejemplo usaremos FAISS, un popular almacén vectorial de código abierto de Facebook. Para otros almacenes vectoriales, especialmente si necesitas almacenar una gran cantidad de datos, consulta aquí.

También importaremos HuggingFaceEmbeddings y RecursiveCharacterTextSplitter para ayudar a almacenar los documentos.

# Split the document into chunks with a specified chunk size
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
all_splits = text_splitter.split_documents(docs)

# Store the document into a vector store with a specific embedding model
vectorstore = FAISS.from_documents(all_splits, HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2"))

Para almacenar los documentos, necesitaremos dividirlos en fragmentos usando RecursiveCharacterTextSplitter y crear representaciones vectoriales de estos fragmentos usando HuggingFaceEmbeddings antes de almacenarlos en nuestra base de datos vectorial.

En general, debes usar tamaños de fragmento más grandes para texto altamente estructurado como código y tamaños más pequeños para texto menos estructurado. Es posible que necesites experimentar con diferentes tamaños de fragmento y valores de superposición para encontrar los mejores números.

Luego usamos RetrievalQA para recuperar los documentos de la base de datos vectorial y darle al modelo más contexto sobre Llama 3.1, aumentando así su conocimiento. ¡3.1 también brilla realmente con el nuevo contexto de 128k!

Para cada pregunta, LangChain realiza una búsqueda de similitud semántica en la base de datos vectorial, luego pasa los resultados de la búsqueda como contexto a Llama para responder la pregunta.

# use LangChain's RetrievalQA, to associate Llama 3 with the loaded documents stored in the vector db
from langchain.chains import RetrievalQA

qa_chain = RetrievalQA.from_chain_type(
    llm,
    retriever=vectorstore.as_retriever()
)

question = "What's new with Llama 3?"
result = qa_chain({"query": question})
print(result['result'])

Ahora, unámoslo todo incorporando preguntas de seguimiento.

Primero hacemos una pregunta de seguimiento sin darle al modelo el contexto de la conversación anterior. Sin este contexto, la respuesta que obtenemos no se relaciona con nuestra pregunta original.

# no context passed so Llama 3 doesn't have enough context to answer so it lets its imagination go wild
result = qa_chain({"query": "Based on what architecture?"})
print(result['result'])

Como hicimos antes, usemos el paquete ConversationalRetrievalChain para darle al modelo el contexto de nuestra pregunta anterior y así poder añadir preguntas de seguimiento.

# use ConversationalRetrievalChain to pass chat history for follow up questions
from langchain.chains import ConversationalRetrievalChain
chat_chain = ConversationalRetrievalChain.from_llm(llm, vectorstore.as_retriever(), return_source_documents=True)
# let's ask the original question What's new with Llama 3?" again
result = chat_chain({"question": question, "chat_history": []})
print(result['answer'])
# this time we pass chat history along with the follow up so good things should happen
chat_history = [(question, result["answer"])]
followup = "Based on what architecture?"
followup_answer = chat_chain({"question": followup, "chat_history": chat_history})
print(followup_answer['answer'])
# further follow ups can be made possible by updating chat_history like this:
chat_history.append((followup, followup_answer["answer"]))
more_followup = "What changes in vocabulary size?"
more_followup_answer = chat_chain({"question": more_followup, "chat_history": chat_history})
print(more_followup_answer['answer'])

Nota: Si los resultados se cortan, puedes establecer "max_new_tokens" en la llamada a Replicate anterior a un número mayor (como se muestra a continuación) para evitar el corte.

model_kwargs={"temperature": 0.01, "top_p": 1, "max_new_tokens": 1000}
Lección del curso «Llama Cookbook (getting started)» de Meta, publicado con licencia MIT. Traducción y adaptación al español de IA con Clase. IA con Clase no está afiliado a Meta. Ver el original · Licencia
Esta lección es gratuita. El resto del curso se abre con la Membresía de IA con Clase, que incluye todos los cursos del catálogo. Ver precios