ChatGPT has definitely made me spoiled over the last year.
It is my go to tool for everything, from getting code snippets to making memes, EXCEPT for internet research.
I mean, here's this cutting-edge AI, but for some reason whenever I need it to grab some info off the web for me, I feel I'm having a conversation with a confused chimp ๐คทโโ๏ธ
Yesterday I decided that enough is enough, rolled up my sleeves and got to work. Enter my new project: an AI assistant that doesn't just sit there spitting out the few first Bing results at you.
We're talking real-time, up-to-the-minute web access.
And now I'll show you how to build it yourself
Just a quick word about Pezzo: It is the fastest growing open source LLMOps platform, and the only one built for full stack developers with first class TypeScript Support.
Like our mission? Check Pezzo out and give us a star. We're building for developers, by developers ๐งโโ๏ธ
The setup
For best performance we will build this assistant with the newest GPT model gpt-4-1106-preview
and Tavily API, both require an API key.
Getting the API keys
- Tavily API is free up to 1,000 requests a month, you just need to register with your Google account. Click here for Tavily API key.
- Get OpenAI API key here.
Project setup
- Create a new folder and inside it make a
main.py
and aconfig.py
files. - Install the latest OpenAI SDK ```
pip install --upgrade openai
- Install the Tavily SDK
pip install tavily-python
> How to fix `error: can't find Rust compiler` when installing Tavily:
> - Paste this in the terminal to install Rust.
> ```
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
>
- Than, paste this in the terminal to configure your shell to recognize the Rust compiler. ```
source $HOME/.cargo/env
Let's get to work!
Config file
We will save all of the API keys here and import them into the other file to be used. This is how your config.py
should look like:
OPENAI_API_KEY= "OPENAI_API_KEY"
TAVILY_API_KEY = "TAVILY_API_KEY"
Main file
Imports and clients init
First, import all of the libraries we'll need and initialize clients with API keys.
import json
import time
from config import OPENAI_API_KEY, TAVILY_API_KEY
from openai import OpenAI
from tavily import TavilyClient
client = OpenAI(api_key=OPENAI_API_KEY)
tavily_client = TavilyClient(api_key=TAVILY_API_KEY)
Creating a new assistant
To keep the function creating the assistant simpler to understand we will create the assistant instructions in a separate variable and pass it to creation function.
assistant_instruction = """You an analyst specializing in open-source intelligence,
Your role is to gather and analyze publicly available information for market research and competitive analysis.
You will provide insights, trends, and data-driven answers.
Never use your own knowledge to answer questions.
Always include the relevant urls for the sources you got the data from.`
"""
assistant = client.beta.assistants.create(
instructions=assistant_instruction,
model="gpt-4-1106-preview",
tools=[{
"type": "function",
"function": {
"name": "tavily_search",
"description": "Get information on recent events from the web.",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "The search query to use. For example: 'Provide a competitive analysis of Open Source survey tools'"},
},
"required": ["query"]
}
}
}]
)
```
### Real time internet access
If you look closely at the creation function you can see I gave the assistant a tool to brows the web, lets add it in!
#### Tavily search
```py
def tavily_search(query):
search_result = tavily_client.get_search_context(query, search_depth="advanced", max_tokens=8000)
return search_result
```
#### Tavily output handler
```py
def submit_tool_outputs(thread_id, run_id, tools_to_call):
tool_output_array = []
for tool in tools_to_call:
output = None
tool_call_id = tool.id
function_name = tool.function.name
function_args = tool.function.arguments
if function_name == "tavily_search":
output = tavily_search(query=json.loads(function_args)["query"])
if output:
tool_output_array.append({"tool_call_id": tool_call_id, "output": output})
return client.beta.threads.runs.submit_tool_outputs(
thread_id=thread_id,
run_id=run_id,
tool_outputs=tool_output_array
)
```
### Managing conversation
The last thing we need to do is build a way for us to pass real time input to the assistant and a way to keep general track of what is going on. the code below does all of that. **To start the assistant just run the `main.py` file, the conversation will take place inside the terminal window. To end the conversation type `exit` in the terminal.**
```py
# Wait for a run to complete
def wait_for_run_completion(thread_id, run_id):
while True:
time.sleep(1)
run = client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run_id)
print(f"Current run status: {run.status}")
if run.status in ['completed', 'failed', 'requires_action']:
return run
# Print messages from a thread
def print_messages_from_thread(thread_id):
messages = client.beta.threads.messages.list(thread_id=thread_id)
for msg in messages:
print(f"{msg.role}: {msg.content[0].text.value}")
assistant_id = assistant.id
print(f"Assistant ID: {assistant_id}")
# Create a thread
thread = client.beta.threads.create()
print(f"Thread: {thread}")
# Conversation loop
while True:
user_input = input("User input: ")
if user_input.lower() == 'exit':
break
# Create a message
message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content=user_input,
)
# Create a run
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant_id,
)
print(f"Run ID: {run.id}")
# Wait for run to complete
run = wait_for_run_completion(thread.id, run.id)
if run.status == 'failed':
print(run.error)
continue
elif run.status == 'requires_action':
run = submit_tool_outputs(thread.id, run.id, run.required_action.submit_tool_outputs.tool_calls)
run = wait_for_run_completion(thread.id, run.id)
# Print messages from the thread
print_messages_from_thread(thread.id)
```
This is what you should see in the terminal when running this file, the assistant is up and waiting for your input-
```
Assistant ID: asst_niCFSyEx6EVq1IQ32byEjLDn
Thread: Thread(id='thread_VjKfyeGpVWII05bALc1Arxdk', created_at=1700259453, metadata={}, object='thread')
User input: how can you help?
Run ID: run_46vRzPA40BPXaZ4Y68qSzuRn
Current run status: in_progress
Current run status: in_progress
Current run status: in_progress
Current run status: in_progress
Current run status: in_progress
Current run status: in_progress
Current run status: in_progress
Current run status: completed
assistant: As an open-source intelligence analyst, I can assist you by gathering and analyzing publicly available information to provide insights on various topics. This can include but is not limited to:
1. Market research: Compiling data on market trends, consumer behavior, industry analysis, and competitive landscapes.
2. Competitive analysis: Comparing products, services, and strategies of competitors within a market.
3. Technology tracking: Monitoring developments in technology, new product releases, and innovations.
4. Event tracking: Keeping up to date with recent events, announcements, and news related to specific industries or topics.
5. Sentiment analysis: Analyzing public opinion and sentiment towards brands, products, or topics on social media and other online platforms.
Based on the task at hand, I can utilize various tools available to me, such as running searches for recent events or conducting tailored research using specific queries.
Let me know how I can assist you today!
User input:
```
---
![end, remote](https://media.giphy.com/media/xUPOqo6E1XvWXwlCyQ/giphy.gif)
That's All Folks!
I've tested this assistant vs. chatGPT and this one is so much better!
Now make your on spin on this- play around with it and let me know all the ways you find to make the most of this ๐ช
Top comments (0)