How to build tool-using agents with LangChain

Learn to use LangChain and Pinecone to build LLM agents that can access the internet and knowledge bases

Matt Tengtrakool
Artificial Corner

--

Photo by Google DeepMind on Unsplash

AI agents are revolutionizing how we approach problem-solving. Building LLMs that can understand, analyze, and leverage diverse data sources, we are beginning to scrape the surface of integrating agents into our routines. These tool wielding agents are essential to make deeper interations between us and our models.

Consider an LLM that can converse thoughtfully, utilizing its tools to offer insightful information. As an example, we can build extrapolating functions to access outside data including realtime searches and knowledge base queries.

Thought: This is an intriguing query. I might need to gather more information.

Action: Search Action

Input: “What is the history of artificial intelligence?”

Observation: The concept of artificial intelligence has its roots in the ancient world, but it wasn’t until the mid-20th century that AI, as we know it today, began to take shape. Scientists like Alan Turing and John McCarthy are credited with pioneering the field. It’s clear that the development of AI has been a gradual process.

Action: Knowledge Base

Input: “What are the key milestones in the development of artificial intelligence?”

Observation: Some of the key milestones in AI’s history include Alan Turing’s development of the Turing Machine, the Dartmouth Conference where John McCarthy coined the term ‘Artificial Intelligence’, the invention of the first neural network machine ‘Perceptron’ by Frank Rosenblatt, the introduction of Machine Learning algorithms, and more recently, the development of advanced AI models like OpenAI’s GPT-3. Final Answer: The history of artificial intelligence is vast and fascinating, evolving from theoretical beginnings to its present-day advanced capabilities. Notable milestones include Alan Turing’s Turing Machine, the coining of the term ‘Artificial Intelligence’ at the Dartmouth Conference, and the development of advanced AI models such as OpenAI’s GPT-3.

This ability to access a variety of information sources allows us to interact with our models in novel ways. We can extract more comprehensive, nuanced answers and build tailored agents for consumer use cases. In this tutorial, we’ll walk you through the process of building an LLM Agent using LangChain and Pinecone.

Step 1: Setting Up Your Environment

To start off, we’ll need to install the required Python libraries. If you haven’t already, install LangChain and Pinecone using pip:

pip install langchain pinecone-client

Now we have access to the libraries we need to construct our LLM agent.

Step 2: The LLM Base

The LLM base is the engine of our agent — it’s where the main thinking happens. For this, we’ll use OpenAI’s GPT-4.

from langchain.models import OpenAI

llm = OpenAI(temperature=0.7)

The temperature parameter influences the randomness of the model's output. A lower value, such as 0.2, results in more focused and deterministic outputs, while a higher value, such as 0.8, produces more diverse and unpredictable outputs. You can tune this according to your needs.

Step 3: Creating a Custom Prompt Template

Now that we have our LLM base ready, it’s time to customize our prompt template. This template allows us to frame the conversation in the way we want. For instance, we might want our agent to first think, then act, and finally observe the outcome.

from langchain.templates import CustomPromptTemplate

template_with_history = """
Thought: {{thought}}
Action: {{action}}
Action Input: {{action_input}}
{% for name, result in action_outputs.items() %}
Observation: {{result.observation}}
{% endfor %}
Final Answer: {{answer}}
"""

prompt_with_history = CustomPromptTemplate(
template=template_with_history,
tools=[],
input_variables=["input", "intermediate_steps", "history"]
)

With this prompt template, our LLM will provide a thoughtful observation, decide on an action, generate an action input, make an observation, and finally, provide an answer.

Step 4: Creating Tools and Setting Up Knowledge Base with Pinecone

Tools give our agent the ability to access diverse information sources. We’ll create two tools: a search tool and a knowledge base retrieval tool using Pinecone.

Let’s start by setting up the search tool. We’ll use the Bing Search API for this purpose:

from langchain.tools import Bing

# Create an instance of the Bing search tool
search_tool = Bing(api_key="<your-bing-api-key>")

The knowledge base tool is slightly more involved. We’ll use Pinecone for this purpose. Pinecone is a vector database service that enables us to perform efficient similarity search on high-dimensional data.

Now to create a new Pinecone service, you need to set up your Pinecone account and retrieve the API key.

import pinecone

# Initialize Pinecone
pinecone.init(api_key="<your-pinecone-api-key>")

# Create a new Pinecone service
index_name = "knowledge-base"
if index_name not in pinecone.list_indexes():
pinecone.create_index(name=index_name, dimension=300, metric="cosine")

Now, let’s create a Pinecone retriever tool to interact with this service. We’ll use a chain called RetrievalQA from langchain:

from langchain.chains import RetrievalQA
from langchain import OpenAI

# Initialize an OpenAI agent
llm = OpenAI(temperature=0)

# Create a Pinecone retriever tool
knowledge_base_tool = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=index_name)

Now that we have our tools ready, we can add them to the toolset:

expanded_tools = [
Tool(
name="Search",
func=search_tool.run,
description="useful for when you need to answer questions about current events"
),
Tool(
name='Knowledge Base',
func=knowledge_base_tool.run,
description="Useful for general questions about how to do things and for details on interesting topics. Input should be a fully formed question."
)
]

Step 5: Constructing the LLM Chain

With the LLM base, prompt template, and tools ready, it’s time to create our LLM chain. The chain is essentially the flow of thought and action that our agent will follow.

Here’s how to set it up:

from langchain import LLMChain

# Create the LLM Chain
llm_chain = LLMChain(llm=llm, prompt_template=prompt_template, tools=expanded_tools)The LLMChain constructor takes three arguments: the LLM base, the prompt template, and a list of tools.

Step 6: Defining the Output Parser

Our agent now has a solid base and a set of powerful tools. However, to understand the output of our agent effectively, we need to parse it properly. We’ll do this by defining an output parser:

from langchain.agents import LLMSingleActionAgent
from langchain.executors import AgentExecutor
from langchain.memory import ConversationBufferWindowMemory

# List of tool names
tool_names = [tool.name for tool in expanded_tools]

# Create the custom agent
custom_agent = LLMSingleActionAgent(
llm_chain=llm_chain,
output_parser=output_parser,
stop=["\nObservation:"],
allowed_tools=tool_names
)

# Define the memory for the agent
agent_memory = ConversationBufferWindowMemory(k=2)

# Build the Agent Executor
agent_executor = AgentExecutor.from_agent_and_tools(
agent=custom_agent,
tools=expanded_tools,
verbose=True,
memory=agent_memory
)

The OutputParser takes the raw output from the LLM base and formats it according to the prompt template. This makes it easy to read and understand the final output.

Step 7: Building the Agent Executor

Finally, it’s time to bring it all together and build the agent executor. The executor is the central component that integrates the LLM base, the tools, and the output parser to facilitate meaningful conversations.

Here’s how to initialize it:

from langchain.agents import LLMSingleActionAgent
from langchain.executors import AgentExecutor
from langchain.memory import ConversationBufferWindowMemory

# List of tool names
tool_names = [tool.name for tool in expanded_tools]

# Create the custom agent
custom_agent = LLMSingleActionAgent(
llm_chain=llm_chain,
output_parser=output_parser,
stop=["\nObservation:"],
allowed_tools=tool_names
)

# Define the memory for the agent
agent_memory = ConversationBufferWindowMemory(k=2)

# Build the Agent Executor
agent_executor = AgentExecutor.from_agent_and_tools(
agent=custom_agent,
tools=expanded_tools,
verbose=True,
memory=agent_memory
)

Congratulations, your LLM agent is now ready to converse intelligently!

Conclusion

In this tutorial, we’ve shown how you can use LangChain to build a sophisticated LLM agent capable of utilizing various tools to provide nuanced and accurate responses. From setting up your environment to creating the agent executor, we’ve walked you through each step to create an agent that can navigate complex conversational landscapes.

Let’s take an example of how our agent would operate in a complex discussion about the ethical implications of artificial intelligence:

Thought: This is a complex topic requiring a balanced understanding. Action: Knowledge Base

Input: “What are the arguments for and against AI ethics?”

Observation: The arguments for AI ethics include the necessity to prevent bias in AI systems, protect privacy, and ensure transparency in AI decision-making. The arguments against center around the stifling of innovation, the potential for over-regulation, and the difficulty in defining universal ethical standards.

Action: Search

Input: “What are some notable incidents where AI ethics were questioned?”

Observation: A few instances include the Cambridge Analytica scandal where personal data was used for targeted political advertising, or the controversy around facial recognition technology being potentially biased and infringing on personal privacy. These incidents underscore the importance of ethics in AI. Final Answer: AI ethics is a complex field with arguments on both sides. It’s crucial to consider these perspectives and recent incidents before forming an opinion.

Building an AI agent is an iterative process. There is a lot of room to experiment with different tools, adjust the prompt template, and fine-tune the LLM base to suit your specific needs.

--

--