Sitemap

Create A MRKL Autonomous Agent Using LangChain, OpenAI & SerpApi

MRKL is an acronym for Modular Reasoning, Knowledge & Language system. It is a modular architecture that combines Large Language Models (LLMs), external knowledge sources & discrete reasoning.

8 min readAug 17, 2023

--

I’m currently the Chief Evangelist @ HumanFirst. I explore & write about all things at the intersection of AI & language; ranging from LLMs, Chatbots, Voicebots, Development Frameworks, Data-Centric latent spaces & more.

This article covers the basics of what a MRKL agent is and how to build an MRKL agent making use of the LangChain framework.

Also in this article is working Python code to build a MRKL agent for a single and multiple input scenario.

Later in the article you will see how I also log the agents output to LangSmith for an in-depth and sequential view into how the LLM Chain is executed within the Agent; the populated prompt is also visible.

You will also notice the extent to which prompt templating is used, these prompts can also be manually submitted to LLMs for inspection via a playground.

And so really LLMs serve as a textual gateway to the universe of knowledge and perhaps should instead be called “language and knowledge” models.
- Source

In General, Default LLM limitations Are:

  1. Lack of access to current information
  2. Lack of access to proprietary information sources
  3. Lack of reasoning
  4. Easy Fine-Tuning

These shortcomings can be solved for, via prompt engineering, while the LLM can serve as the backbone of a task and tools driven autonomous agent.

One can argue that LLM zero-shot performance when supplied with highly accurate and contextual prompts can rival fine-tuned models. Hence a prompt engineering approach as opposed to fine-tuning lends more versatility.

A MRKL agent consists of three parts:

Tools: The tools the agent has available to use.
LLMChain: The LLMChain that produces the text that is parsed in a certain way to determine which action to take.
The agent Class: this parses the output of the LLMChain to determine which action to take.
- Source

The most of the work in creating the custom LLMChain comes down to creating a good prompt. The prompt also guides the agent in which way the data is presented to the LLM.

There is also an input variable called agent_scratchpad for storing notes from previous actions and observations.

The prompt at the heart of the agent can be customised and tweaked as necessary.

Below is the Python code which can be run within a Colab notebook, notice the description given to the search Tool. This helps the agent to know when to use the tool.

This description is particularly important if the agent has access to multiple tools and needs to distinguish when to use what tool.

Also notice the how the prompt template, which is at the heart of the agent, is defined. There is a prefix and suffix to the prompt, hence this is an implementation of composition.

pip install langchain
pip install -U langsmith
pip install openai
pip install google-search-results

from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.llms import OpenAI

import os
os.environ['OPENAI_API_KEY'] = str("xxxxxxxxxxxxxxxxxxxxxxxx")
os.environ["SERPAPI_API_KEY"] = str("xxxxxxxxxxxxxxxxxxxxxxxx")
llm = OpenAI(temperature=0,model_name='gpt-4')

from uuid import uuid4

unique_id = uuid4().hex[0:8]

os.environ["LANGCHAIN_TRACING_V2"]="true"
os.environ["LANGCHAIN_ENDPOINT"]="https://api.smith.langchain.com"
os.environ["LANGCHAIN_API_KEY"]="xxxxxxxxxxxxxxxxxxxxxxxx"
os.environ["LANGCHAIN_PROJECT"]="MRKL"

from langchain.agents import ZeroShotAgent, Tool, AgentExecutor
from langchain import OpenAI, SerpAPIWrapper, LLMChain

search = SerpAPIWrapper()
tools = [
Tool(
name="Search",
func=search.run,
description="useful for when you need to answer questions about current events",
)
]

prefix = """Answer the following questions as best you can, but speaking in a kind and informative manner. You have access to the following tools:"""
suffix = """Begin! Remember to speak in a friendly and helpful manner."

Question: {input}
{agent_scratchpad}"""

prompt = ZeroShotAgent.create_prompt(
tools, prefix=prefix, suffix=suffix, input_variables=["input", "agent_scratchpad"]
)

The prompt template, where the placeholders can be viewed by running the following command:

print(prompt.template)

The output from the print command, from where the prompt can be viewed.

Answer the following questions as best you can, but speaking in a kind and informative manner. You have access to the following tools:

Search: useful for when you need to answer questions about current events

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [Search]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Begin! Remember to speak in a friendly and helpful manner."

Question: {input}
{agent_scratchpad}

Below llm_chain is defined, with tool_names etc.

llm_chain = LLMChain(llm=OpenAI(temperature=0), prompt=prompt)

tool_names = [tool.name for tool in tools]
agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names)

agent_executor = AgentExecutor.from_agent_and_tools(
agent=agent, tools=tools, verbose=True
)

The agent is executed with the run command below, and the question for the agent is inserted.

agent_executor.run("What is the year of birth of te founder of Apple Computers and where was this person born?")

And the run output, with the agent thought, action, action input, observation, thought and final answer:

> Entering new AgentExecutor chain...
Thought: I need to find out the year of birth and birthplace of the founder of Apple Computers.
Action: Search
Action Input: Year of birth and birthplace of the founder of Apple Computers
Observation: Steve Jobs was born on February 24, 1955, in San Francisco to Joanne Schieble (later Joanne Simpson) and Abdulfattah “John” Jandali, two University of Wisconsin graduate students. The couple gave up their unnamed son for adoption. As an infant, Jobs was adopted by Clara and Paul Jobs and named Steven Paul Jobs.
Thought: I now know the final answer.
Final Answer: Steve Jobs was born on February 24, 1955, in San Francisco.

> Finished chain.
Steve Jobs was born on February 24, 1955, in San Francisco.

Multiple Inputs

What happens if you have multiple inputs? Below we have three input variables for input, language and the agent scratchpad.

prefix = """Answer the following questions as best you can. You have access to the following tools:"""
suffix = """When answering, you MUST speak in the following language: {language}.

Question: {input}
{agent_scratchpad}"""

prompt = ZeroShotAgent.create_prompt(
tools,
prefix=prefix,
suffix=suffix,
input_variables=["input", "language", "agent_scratchpad"],
)

llm_chain = LLMChain(llm=OpenAI(temperature=0), prompt=prompt)

agent = ZeroShotAgent(llm_chain=llm_chain, tools=tools)

agent_executor = AgentExecutor.from_agent_and_tools(
agent=agent, tools=tools, verbose=True
)

Again the prompt can be viewed:

print(prompt.template)

And the output with the prompt template, with placeholders {language}, {input} and {agent_scratchpad}.

Answer the following questions as best you can. You have access to the following tools:

Search: useful for when you need to answer questions about current events

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [Search]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

When answering, you MUST speak in the following language: {language}.

Question: {input}
{agent_scratchpad}

The agent is run with the question as the input, and the response language defined as Afrikaans.

agent_executor.run(
input="How many people live in canada as of 2023?", language="Afrikaans"
)

And the agent output, with the correct answer and in the right langauge.

> Entering new AgentExecutor chain...
Thought: I need to find out the population of Canada in 2023
Action: Search
Action Input: Population of Canada in 2023
Observation: Demographic estimates for Canada, the provinces and the territories on April 1, 2023 are now available. These new data allow for an analysis of population growth during the first quarter. Canada's population was estimated at 39,858,480 on April 1, 2023, an increase of 292,232 people (+0.7%) from January 1, 2023.
Thought: I now know the final answer
Final Answer: Canada se bevolking is op 1 April 2023 geskat op 39 858 480 mense.

> Finished chain.
Canada se bevolking is op 1 April 2023 geskat op 39 858 480 mense.

LangSmith

Within LangSmith I created a project I reference from the code. This is included in Python code example above.

I ran the MRKL agent seven times, below is the Latency and tokens used for each run. with the input, output and timestamp.

Drilling down into the agent run, the full trace is visible, with latency and each step in the chain, and tokens used. It it also clear where the LLM was leveraged along the way.

What I really like is the fact that the prompt can be inspected from LangSmith.

The prompt with the completion is visible, LangSmith is an ideal tool to inspect and optimise agents.

⭐️ Follow me on LinkedIn for updates on Large Language Models ⭐️

I’m currently the Chief Evangelist @ HumanFirst. I explore & write about all things at the intersection of AI & language; ranging from LLMs, Chatbots, Voicebots, Development Frameworks, Data-Centric latent spaces & more.

LinkedIn

--

--

Cobus Greyling
Cobus Greyling

Written by Cobus Greyling

I’m passionate about exploring the intersection of AI & language. www.cobusgreyling.com

Responses (1)