LangChain is a framework for developing applications powered by language models.
LangChain helps
- Integration: bring external data, such as your files and other applications to your LLMs
- Agency: allow LLMs to interact with its environment via decision making
The basic data types/schemas that are used throughout the codebase:
-
Text: new programming language
-
Chat Messages: like text, but specified with a message type
- System: helpful background context that tell the AI what to do
- Human: messages that are intended to represent the user
- AI: messages that show what the AI responded with
-
Documents: a piece of text and metadata
Think of this like the brain of the system. It understands and creates sentences just like a person does.
There are two types of language models, which in LangChain are called:
-
LLMs: this is a language model which takes a string as input and returns a string, like sending a single text message to a friend and getting a reply back.
-
ChatModels: this is a language model which takes a list of messages as input and returns a message,like having a group chat with different people (or parts of a system) all sending messages. Each message needs to say who it's from (the role) and what it says (the content).
Text generally used as instructions to your model. These are like asking the brain specific questions. By asking the right questions, you can control what answers you get back.
-
Prompt Value: The class representing an input to a model.
-
Prompt Template: The class in charge of constructing a Prompt Value. An example is as shown below.
>>> from langchain.prompts import ChatPromptTemplate
>>> from langchain.prompts.chat import SystemMessage, HumanMessagePromptTemplate
>>> template = ChatPromptTemplate.from_messages(
... [
... SystemMessage(
... content=(
... "You are a helpful assistant that re-writes the user's text to "
... "sound more upbeat."
... )
... ),
... HumanMessagePromptTemplate.from_template("{text}"),
... ]
... )
>>>
>>> from langchain.chat_models import ChatOpenAI
>>> llm = ChatOpenAI()
>>> llm(template.format_messages(text="Work sucks"))
AIMessage(content='Work has its challenges, but it can also be an opportunity for growth and accomplishment!', additional_kwargs={}, example=False)
>>>
-
Example Selectors: Often times it is useful to include examples in prompts.
-
Output Parsers: Format (text) the output of a model.
Combining different LLM calls and action automatically.
The most commonly used type of chain is an LLMChain, which combines a PromptTemplate, a Model, and Guardrails to take user input, format it accordingly, pass it to the model and get a response, and then validate and fix (if necessary) the model output.
Some applications will require not just a predetermined chain of calls to LLMs/other tools, but potentially an unknown chain that depends on the user's input. In these types of chains, there is a “agent” which has access to a suite of tools. Depending on the user input, the agent can then decide which, if any, of these tools to call.
Basically you use the LLM not just for text output, but also for decision making.
There are several key components as shown below.
- Agent
This is the class responsible for deciding what step to take next.
- Tools
Tools are a 'capability' of an agent - functions that an agent calls.
These tools can be generic utilities (e.g. search), other chains, or even other agents.
- Toolkit
Group of tools that your agent can select from.
- AgentExecutor
The agent executor is the runtime for an agent. This is what actually calls the agent and executes the actions it chooses. Pseudocode for this runtime is below:
next_action = agent.get_action(...)
while next_action != AgentFinish:
observation = run(next_action)
next_action = agent.get_action(..., next_action, observation)
return next_action
Example
There are different types of agents, let's take Zero-shot ReAct agent as an example.
>>> llm = OpenAI(temperature=0)
>>> tools = load_tools(["serpapi", "llm-math"], llm=llm)
>>> agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
>>> agent.run("Who is Justin Bieber's wife? What is her age raised to the 0.43 power?")
> Entering new AgentExecutor chain...
I need to find out who Justin Bieber's wife is and then calculate her age raised to the 0.43 power.
Action: Search
Action Input: "Justin Bieber's wife"
Observation: Hailey Bieber
Thought: I need to find out Hailey Bieber's age
Action: Search
Action Input: "Hailey Bieber age"
Observation: 26 years
Thought: I need to calculate 26 raised to the 0.43 power
Action: Calculator
Action Input: 26^0.43
Observation: Answer: 4.059182145592686
Thought: I now know the final answer
Final Answer: Hailey Bieber is 26 years old and her age raised to the 0.43 power is 4.059182145592686.
> Finished chain.
'Hailey Bieber is 26 years old and her age raised to the 0.43 power is 4.059182145592686.'
ReAct is a simple yet effective method for synergizing reasoning and acting in large language models.
It explores the use of LLMs to generate both reasoning traces and task-specific actions in an interleaved manner, allowing for greater synergy between the two: reasoning traces help the model induce, track, and update action plans as well as handle exceptions, while actions allow it to interface with and gather additional information from external sources such as knowledge bases or environments.
Comparison of 4 prompting methods, (a) Standard, (b) Chain-of-thought (CoT, Reason Only), (c) Act-only, and (d) ReAct (Reason+Act) solving a question:
https://arxiv.org/pdf/2210.03629.pdf
https://www.youtube.com/watch?v=2xxziIWmaSA