← Back
LangChain deep-dive (Live)
October 1 2023
This is a write-up which outlines the values of LangChain, a look into the very interesting LangGraph, and a positive look at the relationship between the projects. The goal of this article is to be informative, as well as critical on the worthiness of building a custom library for Agentive.
This project is not a library and moreso an implementation - so if LangChain offers everything I need to develop Agentive products that can self-learn and self-modify - that's what will be used!
Below is a distillation.
LangChain
LangChain (LC) is an open-source Python and JavaScript library. It's a group of tools for developers working with LLMs. It's purpose is for creating LLM applications.
Each LLM model (ChatGPT, LLama, etc) is implemented as separate classes. There is no strategy pattern or abstract base class to standardise models.
from langchain_openai import ChatOpenAI
gpt4 = ChatOpenAI(model="gpt-4", max_tokens=1024)
response = gpt4.predict("My name is Jack. What is my name?")
For example - OpenAI's awesome "tool caller" (give GPT knowledge of available implemented tools, and it will call them) is really neat. Each subsequent model therefore needs to implement their own tool caller, and LangChain needs to support that.
  • ✅ Message standardisation.
  • ✅ Model standardisation.
  • ✅ Message parsers (to-string, JSON, etc).
    • To note: JSON parser is just converting an output into JSON dict. It does not coerce the model to reply in JSON.
A Look At LangChain's Model Standardisation Model
Below is an analysis of the way which LangChain standardises models, looking specifically at the pathway which has been taken for the ChatOpenAI class.
The general class inheritence is as follows: ChatOpenAI > BaseChatOpenAI > BaseLanguageModel[OutputFormat = BaseModel].
BaseLanguageModel inherits: RunnableSerializable[LanguageModelInput, LanguageModelOutputVar]. RunnableSerializable is a combination class for Runnable and Serializable as described below.
LanguageModelInput is a union of PromptValue (union of BaseModel, str, some othermethods), a string, and a sequence of "message-like representations". LanguageModelOutputVar is a BaseMessage or a string.
RunnableSerializable inherits Serializable and Runnable.
Serializable is an ABC-like class which is a PyDantic model which implements Serializable properties. This acts like a Rust trait.
Runnable takes two input types - Input and Output, which are generics.
To recap, since that is a lot of information:
ChatOpenAI implements BaseChatOpenAI which defines the model, temperature, API key, and other features of using OpenAI. This class then implements the ABC BaseChatModel which handles invoking, streaming, prediction, and so-forth. This then implements BaseLanguageModel with the paramater type var LanguageModelOutputVar which indicates the output which this model will output. There are some other classes like serializable, runnable, and so-forth.
Below is a function-call-like breakdown, to hopefully help even more with comprehension.
ChatOpenAI(
   BaseChatOpenAI(
      BaseChatModel(
         BaseLanguageModel(
            RunnableSerializable(
               Serializable, # JSON serializable and deserializable.
               Runnable(
                  Input, # PromptValue, str, Sequence[MessageLikeRepresentation]
                  BaseModel(
                     Serializable
                  )
               )
            )
         ),
         ABC
      )
   )
)
Note: I've resolved some complicated generic trees. BaseModel is passed from BaseLanguageModel as a type var.
I hope this helps paint a picture of the standardisation which goes into LangChain. This absolutely works for the LangChain approach - and I am not going to be a maintainer, so I do not need to worry about the depth of abstraction.
LangChain Tooling
LC provides tooling for translating, re-creation (augmentation) of similar text for training, sentiment analysis, summarisation, document analysis, so-forth. These are tools, but we'll focus on the components and nodes.
LangChain Chains
Chains - combinations of components to solve more difficult tasks.
Chains can be built in LangChain using the | bitwise-or symbol. LangChain uses Python's dynmaic syntax to use this to put together a builder pattern. So, you can run the following:
parser = StrOutputParser()
chain = gpt4 | parser
my_name = chain.invoke(["My name is Jack. What is my name?"])
print(my_name) # Jack!
A simple way to invoke an LLM without going into the direct vendor API.
LangChain Templating
Templating can then be used to standardise the conversation's variables into template variables, so that chains can be called as simple dictionaries. Templates can be placed infront-of chains, in order to create a simple and invokable function.
Using the LLM Chain language example from LangChain's docs, the below can be done:
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_core.output_parsers import StrOutputParser

# Create the prompt template, model to use, and parser.
prompt_template = ChatPromptTemplate.from_messages(
    [
      ("system", "Translate the following into {language}:"), 
      ("user", "{text}")
   ]
)
gpt4 = ChatOpenAI(model="gpt-4")
parser = StrOutputParser()

# Assemble the chain.
chain = prompt_template | gpt4 | parser

# Invoke the translated.
translated = chain.invoke({
   "language": "italian",
   "text": "I'm flying to Milan right now!"
})
print(translated) # Sto volando a Milano adesso!
(Their demo references Italian, and I am literally on a plane flying to Milan as I'm writing this section of this LangChain breakdown.)
This can then be combined with langserve to create a robust FastAPI endpoint for this function.
LangChain Tooling
When moving to building agents, they require tools. These tools are a standard implementation (don't worry - I won't break it down as much as above) which can be called by a given model, or Agent, in a loop. An example is the TavilySearchResults tool which defines it's name, description, api wrapper, argument schema (normally a PyDantic model). It also defines it's runners, sync and async.
The question I am trying to answer is: whether or not tooling is defined extrinsically (a workflow to determine what tools to use), or if this is a response from the models themselves for "tool-calls".
LangChain Agents
Agents - an assortment of chains, or independent people with access to chains and APIs.
Embeddings for the 10,000th time
The AI community won't stop talking about embeddings (and therefore RAG), and they need to show their head here. What are AI embeddings? They're a conversion of raw data into an array of temperatures, or classifications. So if you put DOG in and get [1,1,0], and CAT you'd get [1,0,0] - index 0 might be "animal", and index 2 might be "isDog" - who knows.
Quick fact: embeddings maps (text -> embedding) are used as the translation layer in LLMs, and are a byproduct of training a large LLM using the transformer architecture.
Embeddings are more complicated than that - but the above is all you need to know for the scope of this article. Input in, numeric list (vector) out. Then, search can be done over the list, rather than the content.
Pinecone
Pinecone is a popular vector (embedding) database for storing information and attributing semantic information to objects in order to better query for information. It's a blend of Mongo with vector-similarity (BYO vectors to classify documents) and filtering. It's a great tool to store vectors and do similarity out-of-the-box.
LangGraph
Compiles to Pregel, some form of research language for efficient graph operations.
Overview
LangChain aims to reduce model hallucination and improves response accuracy.
Required Andrej Karpathy Opinion Review
Andrej Karpathy notes here that LangChain could be used to coordinate language models into organisations, to complete more complex tasks. The connotation of the word "organisation" resembles a company, or a website interface - and I think it can be interpreted that way. It can also be interpreted as a general series of nodes assembled into a workflow.
Resources
  • https://www.youtube.com/watch?v=uki2acokYjQ
  • https://www.langchain.com/
  • https://python.langchain.com/v0.1/docs/langgraph/
  • https://github.com/langchain-ai/langgraph
  • https://tavily.com/
  • https://x.com/karpathy/status/1616111789238018049?lang=en
  • https://www.geeksforgeeks.org/introduction-to-langchain/
  • https://medium.com/around-the-prompt/what-is-langchain-and-why-should-i-care-as-a-developer-b2d952c42b28
  • https://aws.amazon.com/what-is/langchain/#:~:text=LangChain%20is%20an%20open%20source,images%20from%20text%2Dbased%20prompts.
  • https://medium.com/@cplog/introduction-to-langgraph-a-beginners-guide-14f9be027141#:~:text=While%20LangChain%20allows%20you%20to,what%20action%20to%20take%20next.
  • https://www.reddit.com/r/MachineLearning/comments/184qeuo/reading_list_for_andrej_karpathys_busy_persons/
Further to digest
  • https://www.reddit.com/r/MachineLearning/comments/184qeuo/reading_list_for_andrej_karpathys_busy_persons/
  • https://youtu.be/zjkBMFhNj_g?si=fPvPyOVmV-FCTFEx
  • https://www.oxen.ai/blog/reading-list-for-andrej-karpathys-intro-to-large-language-models-video
Sincerely, thanks for reading!
Any questions or comments, reach out!
jack@dataology.com.au