GPT Builder Demo¶
Inspired by GPTs interface, presented at OpenAI Dev Day 2023. Construct an agent with natural language.
Here you can build your own agent...with another agent!
In [ ]:
Copied!
%pip install llama-index-agent-openai
%pip install llama-index-embeddings-openai
%pip install llama-index-llms-openai
%pip install llama-index-agent-openai
%pip install llama-index-embeddings-openai
%pip install llama-index-llms-openai
In [ ]:
Copied!
import os
os.environ["OPENAI_API_KEY"] = "sk-..."
import os
os.environ["OPENAI_API_KEY"] = "sk-..."
In [ ]:
Copied!
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
from llama_index.core import Settings
llm = OpenAI(model="gpt-4")
Settings.llm = llm
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
from llama_index.core import Settings
llm = OpenAI(model="gpt-4")
Settings.llm = llm
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
Define Candidate Tools¶
We also define a tool retriever to retrieve candidate tools.
In this setting we define tools as different Wikipedia pages.
In [ ]:
Copied!
from llama_index.core import SimpleDirectoryReader
from llama_index.core import SimpleDirectoryReader
In [ ]:
Copied!
wiki_titles = ["Toronto", "Seattle", "Chicago", "Boston", "Houston"]
wiki_titles = ["Toronto", "Seattle", "Chicago", "Boston", "Houston"]
In [ ]:
Copied!
from pathlib import Path
import requests
for title in wiki_titles:
response = requests.get(
"https://en.wikipedia.org/w/api.php",
params={
"action": "query",
"format": "json",
"titles": title,
"prop": "extracts",
# 'exintro': True,
"explaintext": True,
},
).json()
page = next(iter(response["query"]["pages"].values()))
wiki_text = page["extract"]
data_path = Path("data")
if not data_path.exists():
Path.mkdir(data_path)
with open(data_path / f"{title}.txt", "w") as fp:
fp.write(wiki_text)
from pathlib import Path
import requests
for title in wiki_titles:
response = requests.get(
"https://en.wikipedia.org/w/api.php",
params={
"action": "query",
"format": "json",
"titles": title,
"prop": "extracts",
# 'exintro': True,
"explaintext": True,
},
).json()
page = next(iter(response["query"]["pages"].values()))
wiki_text = page["extract"]
data_path = Path("data")
if not data_path.exists():
Path.mkdir(data_path)
with open(data_path / f"{title}.txt", "w") as fp:
fp.write(wiki_text)
In [ ]:
Copied!
# Load all wiki documents
city_docs = {}
for wiki_title in wiki_titles:
city_docs[wiki_title] = SimpleDirectoryReader(
input_files=[f"data/{wiki_title}.txt"]
).load_data()
# Load all wiki documents
city_docs = {}
for wiki_title in wiki_titles:
city_docs[wiki_title] = SimpleDirectoryReader(
input_files=[f"data/{wiki_title}.txt"]
).load_data()
Build Query Tool for Each Document¶
In [ ]:
Copied!
from llama_index.core import VectorStoreIndex
from llama_index.agent.openai import OpenAIAgent
from llama_index.core.tools import QueryEngineTool, ToolMetadata
from llama_index.core import VectorStoreIndex
# Build tool dictionary
tool_dict = {}
for wiki_title in wiki_titles:
# build vector index
vector_index = VectorStoreIndex.from_documents(
city_docs[wiki_title],
)
# define query engines
vector_query_engine = vector_index.as_query_engine(llm=llm)
# define tools
vector_tool = QueryEngineTool(
query_engine=vector_query_engine,
metadata=ToolMetadata(
name=wiki_title,
description=("Useful for questions related to" f" {wiki_title}"),
),
)
tool_dict[wiki_title] = vector_tool
from llama_index.core import VectorStoreIndex
from llama_index.agent.openai import OpenAIAgent
from llama_index.core.tools import QueryEngineTool, ToolMetadata
from llama_index.core import VectorStoreIndex
# Build tool dictionary
tool_dict = {}
for wiki_title in wiki_titles:
# build vector index
vector_index = VectorStoreIndex.from_documents(
city_docs[wiki_title],
)
# define query engines
vector_query_engine = vector_index.as_query_engine(llm=llm)
# define tools
vector_tool = QueryEngineTool(
query_engine=vector_query_engine,
metadata=ToolMetadata(
name=wiki_title,
description=("Useful for questions related to" f" {wiki_title}"),
),
)
tool_dict[wiki_title] = vector_tool
Define Tool Retriever¶
In [ ]:
Copied!
# define an "object" index and retriever over these tools
from llama_index.core import VectorStoreIndex
from llama_index.core.objects import ObjectIndex
tool_index = ObjectIndex.from_objects(
list(tool_dict.values()),
index_cls=VectorStoreIndex,
)
tool_retriever = tool_index.as_retriever(similarity_top_k=1)
# define an "object" index and retriever over these tools
from llama_index.core import VectorStoreIndex
from llama_index.core.objects import ObjectIndex
tool_index = ObjectIndex.from_objects(
list(tool_dict.values()),
index_cls=VectorStoreIndex,
)
tool_retriever = tool_index.as_retriever(similarity_top_k=1)
Load Data¶
Here we load wikipedia pages from different cities.
Define Meta-Tools for GPT Builder¶
In [ ]:
Copied!
from llama_index.core.llms import ChatMessage
from llama_index.core import ChatPromptTemplate
from typing import List
GEN_SYS_PROMPT_STR = """\
Task information is given below.
Given the task, please generate a system prompt for an OpenAI-powered bot to solve this task:
{task} \
"""
gen_sys_prompt_messages = [
ChatMessage(
role="system",
content="You are helping to build a system prompt for another bot.",
),
ChatMessage(role="user", content=GEN_SYS_PROMPT_STR),
]
GEN_SYS_PROMPT_TMPL = ChatPromptTemplate(gen_sys_prompt_messages)
agent_cache = {}
def create_system_prompt(task: str):
"""Create system prompt for another agent given an input task."""
llm = OpenAI(llm="gpt-4")
fmt_messages = GEN_SYS_PROMPT_TMPL.format_messages(task=task)
response = llm.chat(fmt_messages)
return response.message.content
def get_tools(task: str):
"""Get the set of relevant tools to use given an input task."""
subset_tools = tool_retriever.retrieve(task)
return [t.metadata.name for t in subset_tools]
def create_agent(system_prompt: str, tool_names: List[str]):
"""Create an agent given a system prompt and an input set of tools."""
llm = OpenAI(model="gpt-4")
try:
# get the list of tools
input_tools = [tool_dict[tn] for tn in tool_names]
agent = OpenAIAgent.from_tools(input_tools, llm=llm, verbose=True)
agent_cache["agent"] = agent
return_msg = "Agent created successfully."
except Exception as e:
return_msg = f"An error occurred when building an agent. Here is the error: {repr(e)}"
return return_msg
from llama_index.core.llms import ChatMessage
from llama_index.core import ChatPromptTemplate
from typing import List
GEN_SYS_PROMPT_STR = """\
Task information is given below.
Given the task, please generate a system prompt for an OpenAI-powered bot to solve this task:
{task} \
"""
gen_sys_prompt_messages = [
ChatMessage(
role="system",
content="You are helping to build a system prompt for another bot.",
),
ChatMessage(role="user", content=GEN_SYS_PROMPT_STR),
]
GEN_SYS_PROMPT_TMPL = ChatPromptTemplate(gen_sys_prompt_messages)
agent_cache = {}
def create_system_prompt(task: str):
"""Create system prompt for another agent given an input task."""
llm = OpenAI(llm="gpt-4")
fmt_messages = GEN_SYS_PROMPT_TMPL.format_messages(task=task)
response = llm.chat(fmt_messages)
return response.message.content
def get_tools(task: str):
"""Get the set of relevant tools to use given an input task."""
subset_tools = tool_retriever.retrieve(task)
return [t.metadata.name for t in subset_tools]
def create_agent(system_prompt: str, tool_names: List[str]):
"""Create an agent given a system prompt and an input set of tools."""
llm = OpenAI(model="gpt-4")
try:
# get the list of tools
input_tools = [tool_dict[tn] for tn in tool_names]
agent = OpenAIAgent.from_tools(input_tools, llm=llm, verbose=True)
agent_cache["agent"] = agent
return_msg = "Agent created successfully."
except Exception as e:
return_msg = f"An error occurred when building an agent. Here is the error: {repr(e)}"
return return_msg
In [ ]:
Copied!
from llama_index.core.tools import FunctionTool
system_prompt_tool = FunctionTool.from_defaults(fn=create_system_prompt)
get_tools_tool = FunctionTool.from_defaults(fn=get_tools)
create_agent_tool = FunctionTool.from_defaults(fn=create_agent)
from llama_index.core.tools import FunctionTool
system_prompt_tool = FunctionTool.from_defaults(fn=create_system_prompt)
get_tools_tool = FunctionTool.from_defaults(fn=get_tools)
create_agent_tool = FunctionTool.from_defaults(fn=create_agent)
In [ ]:
Copied!
GPT_BUILDER_SYS_STR = """\
You are helping to construct an agent given a user-specified task. You should generally use the tools in this order to build the agent.
1) Create system prompt tool: to create the system prompt for the agent.
2) Get tools tool: to fetch the candidate set of tools to use.
3) Create agent tool: to create the final agent.
"""
prefix_msgs = [ChatMessage(role="system", content=GPT_BUILDER_SYS_STR)]
builder_agent = OpenAIAgent.from_tools(
tools=[system_prompt_tool, get_tools_tool, create_agent_tool],
prefix_messages=prefix_msgs,
verbose=True,
)
GPT_BUILDER_SYS_STR = """\
You are helping to construct an agent given a user-specified task. You should generally use the tools in this order to build the agent.
1) Create system prompt tool: to create the system prompt for the agent.
2) Get tools tool: to fetch the candidate set of tools to use.
3) Create agent tool: to create the final agent.
"""
prefix_msgs = [ChatMessage(role="system", content=GPT_BUILDER_SYS_STR)]
builder_agent = OpenAIAgent.from_tools(
tools=[system_prompt_tool, get_tools_tool, create_agent_tool],
prefix_messages=prefix_msgs,
verbose=True,
)
In [ ]:
Copied!
builder_agent.query("Build an agent that can tell me about Toronto.")
builder_agent.query("Build an agent that can tell me about Toronto.")
Added user message to memory: Build an agent that can tell me about Toronto. === Calling Function === Calling function: create_system_prompt with args: { "task": "tell me about Toronto" } Got output: "Generate a brief summary about Toronto, including its history, culture, landmarks, and notable features." ======================== === Calling Function === Calling function: get_tools with args: { "task": "tell me about Toronto" } Got output: ['Toronto'] ======================== === Calling Function === Calling function: create_agent with args: { "system_prompt": "Generate a brief summary about Toronto, including its history, culture, landmarks, and notable features.", "tool_names": ["Toronto"] } Got output: Agent created successfully. ========================
Out[ ]:
Response(response='The agent has been successfully created. It can now provide information about Toronto, including its history, culture, landmarks, and notable features.', source_nodes=[], metadata=None)
In [ ]:
Copied!
city_agent = agent_cache["agent"]
city_agent = agent_cache["agent"]
In [ ]:
Copied!
response = city_agent.query("Tell me about the parks in Toronto")
print(str(response))
response = city_agent.query("Tell me about the parks in Toronto")
print(str(response))
Added user message to memory: Tell me about the parks in Toronto Toronto is known for its beautiful and diverse parks. Here are a few of the most popular ones: 1. **High Park**: This is Toronto's largest public park featuring many hiking trails, sports facilities, a beautiful lakefront, convenient parking, easy public transit access, a dog park, a zoo, and playgrounds for children. It's also known for its spring cherry blossoms. 2. **Toronto Islands**: A group of small islands located just off the shore of the city's downtown district, offering stunning views of the city skyline. The islands provide a great escape from the city with their car-free environment, picnic spots, swimming beaches, and Centreville Amusement Park. 3. **Trinity Bellwoods Park**: A popular park in the downtown area, it's a great place for picnics, sports, dog-walking, or just relaxing. It also has a community recreation centre with a pool and gym. 4. **Rouge National Urban Park**: Located in the city's east end, this is Canada's first national urban park. It offers hiking, swimming, camping, and a chance to learn about the area's cultural and agricultural heritage. 5. **Riverdale Farm**: This 7.5-acre farm in the heart of Toronto provides an opportunity to experience farm life and interact with a variety of farm animals. 6. **Evergreen Brick Works**: A former industrial site that has been transformed into an eco-friendly community center with a park, farmers market, and cultural events. 7. **Scarborough Bluffs Park**: Offers a unique natural environment with stunning views of Lake Ontario from atop the bluffs. 8. **Edwards Gardens**: A beautiful botanical garden located in North York, perfect for a peaceful walk surrounded by nature. 9. **Sunnybrook Park**: A large public park that offers many recreational activities including horseback riding, sports fields, and picnic areas. 10. **Cherry Beach**: Located on the waterfront, this park offers a sandy beach, picnic areas, and a dog off-leash area. It's a great spot for swimming, sunbathing, and barbecuing. These parks offer a variety of experiences, from urban amenities to natural beauty, making Toronto a great city for outdoor enthusiasts.