Langchain + RAG cheat sheet
Introduction to LangChain: Building Efficient LLM Applications
LangChain is a powerful ecosystem designed to simplify the development of applications based on Large Language Models (LLMs). Whether you're an experienced developer or new to artificial intelligence, LangChain offers tools and predefined chains to streamline your workflow. In this article, we'll explore the main features of LangChain, accompanied by code examples to help you get started.
1. Setting Up Hugging Face
Before diving in, make sure you have an account on Hugging Face. You'll need an API access token to interact with hosted models. Here's how to set it up:
Create an account on Hugging Face if you haven't already. Generate an API access token by visiting your settings page. Keep your token secure; you'll need it for API calls. Note: Never share your access token publicly.
2. Basic API Call to Hugging Face
Let's use an LLM hosted on Hugging Face for a simple prediction:
from langchain.llms import HuggingFaceEndpoint
# Replace with your API access token
= 'hf_your_access_token'
huggingfacehub_api_token
# Define the LLM
= HuggingFaceEndpoint(
llm endpoint_url='https://api-inference.huggingface.co/models/tiiuae/falcon-7b-instruct',
huggingfacehub_api_token=huggingfacehub_api_token
)
# Ask a question to the model
= 'What can I do to improve my productivity?'
question = llm.invoke(question)
output
print(output)
3. Using Prompt Templates
Prompt templates allow you to structure your queries flexibly. Here's how to create a simple template:
from langchain.prompts import PromptTemplate
from langchain.llms import HuggingFaceEndpoint
# Create a prompt template
= "You are an artificial intelligence assistant. Answer the following question: {question}"
template = PromptTemplate(template=template, input_variables=["question"])
prompt
# Integrate the template with the LLM
= HuggingFaceEndpoint(
llm endpoint_url='https://api-inference.huggingface.co/models/tiiuae/falcon-7b-instruct',
huggingfacehub_api_token=huggingfacehub_api_token
)= prompt | llm
llm_chain
= "How does LangChain simplify LLM application development?"
question print(llm_chain.invoke({"question": question}))
4. Managing Memory in Chat Models
LangChain offers several ways to manage conversation history:
a. ChatMessageHistory This class stores all messages exchanged during a conversation.
from langchain.memory import ChatMessageHistory
from langchain.chat_models import ChatOpenAI
= ChatOpenAI(model_name="gpt-4", temperature=0)
llm
# Create the conversation history
= ChatMessageHistory()
history "Hello! Ask me any question about Python programming.")
history.add_ai_message("What is a list comprehension in Python?")
history.add_user_message(= llm.invoke(history.messages)
response print(response.content)
b. ConversationBufferMemoryclass stores a defined number of recent messages.
This
```python
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain
from langchain.chat_models import ChatOpenAI
= ChatOpenAI(model_name="gpt-4", temperature=0)
llm
# Define the buffer memory
= ConversationBufferMemory(k=4)
memory
# Create the conversation chain
= ConversationChain(llm=llm, memory=memory)
buffer_chain
# Interact with the model
input="Explain decorators in Python.")
buffer_chain.predict(input="Can you give an example with @staticmethod?")
buffer_chain.predict(
5. Sequential Chains
Sequential chains allow you to link multiple processing steps. For example, creating a learning plan:
from langchain.prompts import PromptTemplate
# Template for the activity
= PromptTemplate(
learning_prompt input_variables=["activity"],
template="I want to learn how to {activity}. Can you suggest steps to achieve this?"
)
# Template for the time constraint
= PromptTemplate(
time_prompt input_variables=["learning_plan"],
template="I only have one week. Can you create a plan to reach this goal: {learning_plan}."
)
# Chain the templates
from langchain.chains import SequentialChain
= SequentialChain(chains=[learning_prompt, time_prompt])
chain
# Execute the chain
= chain.invoke({"activity": "play the piano"})
output print(output)
6. Agents
Agents make decisions based on the tools available to them. LangChain provides pre-built agents like the ReAct agent:
from langchain.agents import load_tools, initialize_agent
from langchain.chat_models import ChatOpenAI
# Load tools
= load_tools(["wikipedia"])
tools
# Define the LLM
= ChatOpenAI(model_name="gpt-4", temperature=0)
llm
# Create the agent
= initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)
agent
# Use the agent
= agent.run("Summarize key facts about London, England.")
response print(response)
7. Creating Custom Tools for Agents
You can create your own tools to extend the capabilities of agents.
from langchain.agents import tool
# Example tool function
@tool
def retrieve_customer_info(name: str) -> str:
"""Retrieve customer information based on their name."""
# Simulate a database
= {
customers "Peak Performance Co.": "Information about Peak Performance Co...",
"Innovatech Ltd.": "Information about Innovatech Ltd..."
}return customers.get(name, "Customer not found.")
# Create the agent with the custom tool
= initialize_agent([retrieve_customer_info], llm, agent="zero-shot-react-description", verbose=True)
agent
# Use the agent
= agent.run("Create a summary for our customer: Peak Performance Co.")
response print(response)
8. Integrating Document Loaders
Document loaders allow you to import various types of data into your application.
a. Loading PDFs
from langchain.document_loaders import PyPDFLoader
# Load the PDF document
= PyPDFLoader("rag_vs_fine_tuning.pdf")
loader = loader.load()
data print(data[0])
b. Loading CSVs
from langchain.document_loaders import CSVLoader
# Load the CSV file
= CSVLoader("fifa_countries_audience.csv")
loader = loader.load()
data print(data[0])
c. Loading HTML
from langchain.document_loaders import UnstructuredHTMLLoader
# Load the HTML file
= UnstructuredHTMLLoader("white_house_executive_order_nov_2023.html")
loader = loader.load()
data print(data[0])
9. Splitting Data for Retrieval
Splitting documents into smaller chunks facilitates data management and information retrieval.
a. CharacterTextSplitter
from langchain.text_splitter import CharacterTextSplitter
= 'Words are flowing out like endless rain into a paper cup,\nthey slither while they pass,\nthey slip away across the universe.'
text = 24
chunk_size = 10
chunk_overlap
# Create an instance of the splitter
= CharacterTextSplitter(
splitter separator="\n",
chunk_size=chunk_size,
chunk_overlap=chunk_overlap
)
# Split the text and print the chunks
= splitter.split_text(text)
chunks print(chunks)
print([len(chunk) for chunk in chunks])
b. RecursiveCharacterTextSplitter
from langchain.text_splitter import RecursiveCharacterTextSplitter
= 'Words are flowing out like endless rain into a paper cup,\nthey slither while they pass,\nthey slip away across the universe.'
text = 24
chunk_size = 10
chunk_overlap
# Create an instance of the splitter
= RecursiveCharacterTextSplitter(
splitter separators=["\n"," ",""],
chunk_size=chunk_size,
chunk_overlap=chunk_overlap
)
# Split the text and print the chunks
= splitter.split_text(text)
chunks print(chunks)
print([len(chunk) for chunk in chunks])
c. Splitting an HTML Document
from langchain.document_loaders import UnstructuredHTMLLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# Load the HTML document
= UnstructuredHTMLLoader("white_house_executive_order_nov_2023.html")
loader = loader.load()
data
= 300
chunk_size = 100
chunk_overlap
# Split the HTML
= RecursiveCharacterTextSplitter(
splitter chunk_size=chunk_size,
chunk_overlap=chunk_overlap,
separators='.'
)
= splitter.split_documents(data)
docs print(docs)
10. RAG Storage and Retrieval Using a Vector Database
Retrieval-Augmented Generation (RAG) improves accuracy by using an external knowledge base.
a. Using ChromaDB
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.prompts import ChatPromptTemplate
from langchain.chains import RunnableMap, RunnablePassthrough
from langchain.chat_models import ChatOpenAI
import os
# Load and split your documents
= PyPDFLoader('rag_vs_fine_tuning.pdf')
loader = loader.load()
data = RecursiveCharacterTextSplitter(chunk_size=300, chunk_overlap=50)
splitter = splitter.split_documents(data)
docs
# Create the vector database
= OpenAIEmbeddings(openai_api_key='your_openai_api_key')
embedding_function = Chroma.from_documents(
vectorstore
docs,embedding=embedding_function,
persist_directory=os.getcwd()
)
# Configure the retriever
= vectorstore.as_retriever(
retriever search_type="similarity",
search_kwargs={"k": 3}
)
# Create the prompt template
= """
message Answer the following question using the context provided:
Context:
{context}
Question:
{question}
Answer:
"""
= ChatPromptTemplate.from_messages([("human", message)])
prompt_template
# Define the LLM
= ChatOpenAI(model_name="gpt-4", temperature=0)
llm
# Create the RAG chain
= RunnableMap({
rag_chain "context": retriever,
"question": RunnablePassthrough()
| prompt_template | llm
})
# Execute the chain
= rag_chain.invoke("Which popular LLMs were considered in the paper?")
response print(response.content)
Conclusion LangChain is a powerful tool for developing complex LLM applications with simplicity and efficiency. By leveraging its features such as prompt templates, memory management, custom agents, and external data integration, you can create intelligent solutions tailored to your specific needs.
Start today and unlock the full potential of language models with LangChain!