PolarSPARC |
Quick Primer on LangChain
Bhaskar S | 07/13/2024 |
Overview
LangChain is a popular, open-source, orchestration framework that provides a standardized abstraction for developing AI applications by hiding the complexities of working with the different Large Language models (or LLMs for short).
LangChain provides a collection of core component abstractions (or modular building blocks) that could be linked or "Chained" together to create complex AI workflows (or applications) to solve a plethora of tasks.
The following are the list of some of the important component modules from LangChain:
Models :: are standardized abstractions for interacting with AI models and are primarily of three types:
LLM Models are designed for interacting with the various LLMs, which take text input and generate text output
Chat Models are designed for interacting with the various LLMs using a chat style interaction in which the previous chat input is used as the context
Embedding Models are designed to convert an input text to a numerical embedding vector (see Word Embeddings )
Prompts :: are a set of instructions (or contextual inputs) provided by a user to guide the model to generate relevant response (or output). There are three types of standardized prompt abstractions:
Prompt Templates are reusable string templates with placeholders for contexts and instructions (or inputs), which can be dynamically set by a user at runtime, to generate specific prompt instructions for interacting with various LLMs
Example Selectors are a way to pass specific and relevant examples along with the input prompt to the LLMs in order to control the response (or output) from the LLMs
Output Parsers are responsible for taking the text response (or output) from the LLMs and transforming them to a specific structured format
Retrieval :: are related to how one can pass large amounts of user specific contextual data along with the instruction prompt to the LLMs. There are four types of standardized retrieval abstractions:
Document Loaders are useful for loading data documents from different sources, such as files (.txt, .pdf, .mp4, etc), from the web, or any other available sources.
Text Splitters are useful for splitting long documents into smaller semantically meaningful chunks so that they can be within the limits of the LLMs context window size
Vector Stores are used for storing vector embeddings of user specific documents and for later retrieval of similar documents (see Vector Database)
Retrievers are generic interfaces which are useful for querying embedded documents from various vectors sources including Vector Stores
Memory :: are used for preserving user prompts and responses from the LLMs so that they can be used for providing the context for future interactions with the LLMs
The intent of this article is NOT to be exhaustive, but a primer to get started quickly.
Installation and Setup
The installation and setup will be on a Ubuntu 22.04 LTS based Linux desktop. Ensure that Ollama is installed and setup on the desktop (see instructions).
In addition, ensure that the Python 3.x programming language as well as the Jupyter Notebook package is installed and setup on the desktop.
For the LLM model, we will be using the recently released Microsoft Phi-3 Mini model.
To install the necessary Python modules for this primer, execute the following command:
$ pip install chromadb dotenv langchain lanchain-chroma langchain-community langchain-ollama
This completes all the installation and setup for the LangChain hands-on demonstrations.
Hands-on with LangChain
Create a file called .env with the following environment variables defined:
OLLAMA_MODEL='phi3:mini' OLLAMA_BASE_URL='http://192.168.1.25:11434' CHROMA_DB_DIR='/home/bswamina/.chromadb' BOOKS_DATASET='./leadership_books.csv'
To load the environment variables and assign them to Python variable, execute the following code snippet:
from dotenv import load_dotenv, find_dotenv import os load_dotenv(find_dotenv()) ollama_model = os.getenv('OLLAMA_MODEL') ollama_base_url = os.getenv('OLLAMA_BASE_URL') chroma_db_dir = os.getenv('CHROMA_DB_DIR') books_dataset = os.getenv('BOOKS_DATASET')
To initialize an instance of Ollama running the desired LLM model phi3:mini, execute the following code snippet:
from langchain_community.llms import Ollama ollama_llm = Ollama(base_url=ollama_base_url, model=ollama_model, temperature=0)
The temperature parameter in the above code is a value that is between 0.0 and 1.0. It determines whether the output from the LLM model should be more "creative" or be more "predictive". A higher value means more "creative" and a lower value means more "predictive".
The PromptTemplate class allows one to create an instance of an LLM prompt using a string template with placeholders (word surrounded by curly braces). To create an instance of a prompt from a string template, execute the following code snippet:
from langchain_core.prompts import PromptTemplate template = """ Question: {question} Answer: Summarize in less than {tokens} words. """ prompt = PromptTemplate.from_template(template=template)
Executing the above Python code generates no output.
To test the prompt instance with some test values for the placeholders, execute the following code snippet:
prompt.format(question='describe a leader', tokens=50)
Executing the above Python code generates the following typical output:
'\nQuestion: describe a leader\n\nAnswer: Summarize in less than 50 words.\n'
To create our first simple chain (using the pipe '|' operator) for sending the prompt to our LLM model, execute the following code snippet:
chain = prompt | ollama_llm
Executing the above Python code generates no output.
To run the just created simple chain by providing actual values for the placeholders in the prompt, execute the following code snippet:
print(chain.invoke({'question': 'describe a leader', 'tokens': 50}))
Executing the above Python code generates the following typical output:
A leader is an individual who inspires and guides others towards achieving common goals, demonstrating integrity, empathy, decisiveness, and the ability to motivate through visionary thinking and effective communication skills. They foster collaboration and empower their team members while navigating challenges with resilience and adaptability.
In the above simple chain, the LLM model generated a unstructured text response (or output). There are situations when one would require a more structured response, like a list, or json, etc. This is where the Output Parsers come in handy. LangChain provides a collection of pre-built output parsers as follows:
CommaSeparatedListOutputParser
JsonOutputParser
PandasDataFrameOutputParser
XMLOutputParser
YamlOutputParser
For this demonstration, we will leverage the CommaSeparatedListOutputParser output parser. First, we will need to change the prompt a little bit. To create a new instance of a prompt from a string template that instructs the LLM to generate a list of items, execute the following code snippet:
from langchain_core.prompts import PromptTemplate template2 = """ Generate a list of top five qualities about {subject}, with each feature using less than {tokens} words. {format_instructions} """ prompt2 = PromptTemplate.from_template(template=template2)
Executing the above Python code generates no output.
To create a simple chain that sends the new prompt to our LLM model, execute the following code snippet:
chain2 = prompt2 | ollama_llm
Executing the above Python code generates no output.
To run the just created simple chain by providing actual values for the placeholders in the prompt, execute the following code snippet:
output = chain2.invoke({'subject': 'a leader', 'format_instructions': format_instructions, 'tokens': 5}) print(output)
Executing the above Python code generates the following typical output:
Inspiration, decisiveness, empathy, integrity, visionary
To create an instance of the output parser, execute the following code snippet:
from langchain.output_parsers import CommaSeparatedListOutputParser output_parser = CommaSeparatedListOutputParser()
Executing the above Python code generates no output.
To create a new chain that sends the response from our LLM model to the output parser, execute the following code snippet:
chain3 = prompt2 | ollama_llm | output_parser
Executing the above Python code generates no output.
To run the just created chain by providing actual values for the placeholders in the prompt, execute the following code snippet:
output2 = chain3.invoke({'subject': 'a leader', 'format_instructions': format_instructions, 'tokens': 5}) print(output2)
Executing the above Python code generates the following typical output:
['Inspiration', 'decisiveness', 'empathy', 'integrity', 'visionary']
Even though the LLM model(s) have been trained on vast amounts of data, one needs to provide an appropriate context to the LLM model(s) for better response (or output). To get better results, one can augment the LLM model's knowledge by providing additional context from external data sources, such as vector stores. This is where the Retrieval Augmented Generation (or RAG for short) comes into play.
To demonstrate the power of RAG, we will create a new instance of a prompt from a string template that instructs the LLM to generate a list of books on a given subject by executing the following code snippet:
from langchain_core.prompts import PromptTemplate prompt3 = PromptTemplate.from_template(template='Generate a numbered list of top three books on {subject}')
Executing the above Python code generates no output.
To create a simple chain that sends the new prompt to our LLM model, execute the following code snippet:
chain4 = prompt3 | ollama_llm
Executing the above Python code generates no output.
To run the just created simple chain by providing actual values for the placeholders in the prompt, execute the following code snippet:
output3 = chain4.invoke({'subject': 'leadership'}) print(output3)
Executing the above Python code generates the following typical output:
1. "Leaders Eat Last: Why Empathetic Leadership is the Only Way Forward" by Simon Sinek 2. "The Five Dysfunctions of a Team: A Leader's Manual for Building Accountability, Trust and Extraordinary Results" by Patrick Lencioni 3. "Dare to Win: Creating a Culture of Winners at Work and in Life" by Tony Alessandrini
We will leverage the Chroma as the vector store for the RAG demo. In addition, we will handcraft as small dataset with 15 popular leadership books.
The following illustration depicts the truncated contents of the small leadership books dataset:
The pipe-separated leadership books dataset can be downloaded from HERE !!!
To load the pipe-separated leadership books dataset into a pandas dataframe, execute the following code snippet:
import pandas as pd books_df = pd.read_csv(books_dataset, sep='|') books_df
Executing the above Python code generates the typical output as shown in Figure.1 above.
The Document class allows one to encapsulate the textual content with metadata, which can be stored in a vector store for later searches.
To create a collection of documents from the rows of the pandas dataframe, execute the following code snippet:
from langchain_core.documents import Document documents = [] for i in range(0, len(books_df)): doc = Document(page_content=books_df.iloc[i]['Summary'], metadata={'Title': books_df.iloc[i]['Title'], 'Author': books_df.iloc[i]['Author']}) documents.append(doc) documents
The following illustration depicts the partial collection of documents:
To store the documents (with textual content) into a vector store (as embeddings), we need to create an instance of vector embedding class corresponding to the LLM model. To create an instance of Ollama embedding, execute the following code snippet:
from langchain_community.embeddings import OllamaEmbeddings ollama_embedding = OllamaEmbeddings(base_url=ollama_base_url, model=ollama_model, temperature=0)
Executing the above Python code generates no output.
To create an instance of the Chroma vector store with Ollama embedding, execute the following code snippet:
from langchain_community.vectorstores import Chroma vector_store = Chroma(embedding_function=ollama_embedding, persist_directory=chroma_db_dir)
Executing the above Python code generates no output.
To persist the collection of documents into the Chroma vector store, execute the following code snippet:
vector_store.add_documents(documents)
The following illustration depicts the list of document IDs stored in the vector store:
To create an instance of a vector store retriever that will return at most 2 similar documents, execute the following code snippet:
n_top = 2 retriever = vector_store.as_retriever(search_kwargs={'k': n_top})
Executing the above Python code generates no output.
To perform a query on similar documents from the Chroma vector store, execute the following code snippet:
query = 'a leaders guide to managing teams' similar_docs = retriever.invoke(query) similar_docs
The following illustration depicts the list of document IDs stored in the vector store:
To create a new prompt from a string template, with a placeholder for the contextual info from the vector store to instruct the LLM to generate a list of books by executing the following code snippet:
from langchain_core.prompts import PromptTemplate template3 = """ Generate a numbered list of top three books on {subject} that are similar to the following: {document} """ prompt4 = PromptTemplate.from_template(template=template3)
Executing the above Python code generates no output.
To create a simple chain that sends the new prompt to our LLM model, execute the following code snippet:
chain5 = prompt4 | ollama_llm
Executing the above Python code generates no output.
To run the just created simple chain by providing the contextual info from the vector store into the prompt, execute the following code snippet:
output4 = chain5.invoke({'subject': 'leadership', 'document': similar_docs[0]}) print(output4)
Executing the above Python code generates the following typical output:
1. "The Five Dysfunctions of a Team: A Leadership Fable for Your Business Life" by Patrick Lencioni - This book delves into common pitfalls that can hinder team performance and offers strategies to overcome them, fostering an environment where leaders focus on developing their employees' strengths rather than solely relying on skills or experience. 2. "Leaders Eat Last: Extreme Results from the Leadership Secrets of Admiral Peck" by Dr. Amy Edmondson - This book explores how a leader can create an inclusive and psychologically safe environment, where employees feel valued and empowered to contribute their best work. It emphasizes building trust among team members as essential for effective leadership. 3. "Drive: The Surprising Truth About What Motivates Us" by Daniel H. Pink - This book examines the science behind motivation, challenging traditional ideas about rewards and punishments in management practices. It highlights how leaders can inspire their teams to achieve exceptional results through autonomy, mastery, and purpose – focusing on individual strengths rather than weaknesses or experience alone.
The reponse in Output.6 above is much more inline with what one would expect given the additional context.
Moving on to the example on memory, to initialize an instance of the chat model for Ollama running the LLM model phi3:mini, execute the following code snippet:
from langchain.chat_models.ollama import ChatOllama ollama_chat_llm = ChatOllama(model=ollama_model, temperature=0)
Executing the above Python code generates no output.
To initialize an instance of memory to preserve responses from the previous LLM model interaction(s), execute the following code snippet:
from langchain.memory import ConversationBufferMemory ollama_llm_memory = ConversationBufferMemory()
Executing the above Python code generates no output.
To create a chain that sends user request to the chat LLM model and captures the responses into the memory, execute the following code snippet:
from langchain.chains import ConversationChain chain6 = ConversationChain(llm=ollama_chat_llm, memory=ollama_llm_memory, verbose=True)
Executing the above Python code generates no output.
To run the just created chain by providing an user prompt, execute the following code snippet:
output5 = chain6.invoke('Suggest only top 3 leadership quotes') print(output5)
Executing the above Python code generates the following typical output:
> Entering new ConversationChain chain... Prompt after formatting: The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. Current conversation: Human: Suggest only top 3 leadership quotes AI: > Finished chain. {'input': 'Suggest only top 3 leadership quotes', 'history': '', 'response': ' Certainly! Here are three influential leadership quotes that have inspired many leaders and individuals alike over time:\n\n1. "The greatest leader is the one who knows how to delegate." - Laurence J. Peter (This quote emphasizes the importance of trusting others with responsibilities, which ultimately leads to better teamwork and efficiency.)\n\n2. "Leadership and learning are indispensable to each other" - John F. Kennedy (Kennedy\'s words highlight that leaders must continuously learn from their experiences in order to grow as individuals and improve the performance of those they lead.)\n\n3. "A leader is best when people barely know he exists, not so much when he\'s seen." - Hilaire Belloc (This quote suggests a leadership style where actions speak louder than words; leaders who are humble yet effective in their roles often achieve better results without seeking attention or recognition.)'}
To demonstrate that the chain remembers and uses the previous response(s) as a context in the next interaction, execute the following code snippet:
output6 = chain6.invoke('Quotes are not inspiring, try again') print(output6)
Executing the above Python code generates the following typical output:
> Entering new ConversationChain chain... Prompt after formatting: The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. Current conversation: Human: Suggest only top 3 leadership quotes AI: Certainly! Here are three influential leadership quotes that have inspired many leaders and individuals alike over time: 1. "The greatest leader is the one who knows how to delegate." - Laurence J. Peter (This quote emphasizes the importance of trusting others with responsibilities, which ultimately leads to better teamwork and efficiency.) 2. "Leadership and learning are indispensable to each other" - John F. Kennedy (Kennedy's words highlight that leaders must continuously learn from their experiences in order to grow as individuals and improve the performance of those they lead.) 3. "A leader is best when people barely know he exists, not so much when he's seen." - Hilaire Belloc (This quote suggests a leadership style where actions speak louder than words; leaders who are humble yet effective in their roles often achieve better results without seeking attention or recognition.) Human: Quotes are not inspiring, try again AI: > Finished chain. {'input': 'Quotes are not inspiring, try again', 'history': 'Human: Suggest only top 3 leadership quotes\nAI: Certainly! Here are three influential leadership quotes that have inspired many leaders and individuals alike over time:\n\n1. "The greatest leader is the one who knows how to delegate." - Laurence J. Peter (This quote emphasizes the importance of trusting others with responsibilities, which ultimately leads to better teamwork and efficiency.)\n\n2. "Leadership and learning are indispensable to each other" - John F. Kennedy (Kennedy\'s words highlight that leaders must continuously learn from their experiences in order to grow as individuals and improve the performance of those they lead.)\n\n3. "A leader is best when people barely know he exists, not so much when he\'s seen." - Hilaire Belloc (This quote suggests a leadership style where actions speak louder than words; leaders who are humble yet effective in their roles often achieve better results without seeking attention or recognition.)', 'response': 'I apologize if my previous suggestions did not resonate with you. Here\'s another set of three leadership quotes that might be more inspirational for you to consider:\n\n1. "The art of leading is taking people where they don\'t want to go and moving them when they don\'t want to be moved." - Colin Powell (This quote emphasizes the importance of a leader being able to guide their team through challenges, even if it means pushing beyond comfort zones.)\n\n2. "A good leader inspires loyalty, not by demanding obedience but by showing trust and respect for his followers." - John Maxwell (Maxwell\'s words highlight the significance of building strong relationships based on mutual trust and respect in order to effectively lead a team or organization.)\n\n3. "The greatest leaders are those who can make others want to be better, not just do what they say is right." - Michelle Obama (This quote emphasizes that true leadership involves empowering individuals within your sphere of influence to strive for personal growth and excellence.)'}
This concludes the hands-on demonstration of using the various LangChain components !!!
References