Skip to content

Commit

Permalink
Update to make the process simpler
Browse files Browse the repository at this point in the history
  • Loading branch information
francislabountyjr committed Apr 3, 2023
1 parent 76dfd84 commit c9144ea
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 274 deletions.
95 changes: 3 additions & 92 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,100 +6,11 @@ Repo for giving ChatGPT the ability to use web browsing, python code execution,
- Open `plugins.ipynb`
- Insert your api key into the `api_key` variable in the first cell
- Run all of the setup cells
- Edit the example with your desired prompt. In the setup cell, there is a variable called `prompt` that defines the action loop and the tools to the model. So make sure that the prompt you are giving to the action loop looks like `prompt.format(prompt="Your prompt here")`
- Edit the example with your desired prompt.

# How to edit what the model can do
There is a cell that defines a variable called prompt that looks like this:
```python
prompt = """Respond to the following prompt as best as you can. You have access to the following tools:
Web Search: Searches the web for the given search query.
Get Readable Content: Returns the readable content of the given url.
Get Internal Links: Returns the internal links of the given url.
Run Python Code: Runs the given Python code. Must be one line.
Ask ChatGPT: Ask ChatGPT a question or give it a prompt for a response.
Use the following format:
Prompt: the prompt you are responding to
Thought: you should always think about what to do
Action: the action you want to take, must be one of [Web Search, Get Readable Content, Get Internal Links, Run Python Code, Ask ChatGPT]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Observation loop can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Prompt: {prompt}"""
```
You can edit this prompt to add more actions, change the names of the actions, or change the descriptions.
Examples:
- Remove the `Web Search` action
```python
prompt = """Respond to the following prompt as best as you can. You have access to the following tools:
Get Readable Content: Returns the readable content of the given url.
Get Internal Links: Returns the internal links of the given url.
Run Python Code: Runs the given Python code. Must be one line.
Ask ChatGPT: Ask ChatGPT a question or give it a prompt for a response.
Use the following format:
Prompt: the prompt you are responding to
Thought: you should always think about what to do
Action: the action you want to take, must be one of [Get Readable Content, Get Internal Links, Run Python Code, Ask ChatGPT]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Observation loop can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Prompt: {prompt}"""
```
Don't forget to change this line to remove the `Web Search` action:
```python
Action: the action you want to take, must be one of [Get Readable Content, Get Internal Links, Run Python Code, Ask ChatGPT]
```
- Add a new action called `Calculator`
```python
prompt = """Respond to the following prompt as best as you can. You have access to the following tools:
Web Search: Searches the web for the given search query.
Get Readable Content: Returns the readable content of the given url.
Get Internal Links: Returns the internal links of the given url.
Run Python Code: Runs the given Python code. Must be one line.
Ask ChatGPT: Ask ChatGPT a question or give it a prompt for a response.
Calculator: Calculates the given basic math expression.
Use the following format:
Prompt: the prompt you are responding to
Thought: you should always think about what to do
Action: the action you want to take, must be one of [Web Search, Get Readable Content, Get Internal Links, Run Python Code, Ask ChatGPT, Calculator]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Observation loop can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Prompt: {prompt}"""
```
Don't forget to change this line to add the `Calculator` action:
```python
Action: the action you want to take, must be one of [Web Search, Get Readable Content, Get Internal Links, Run Python Code, Ask ChatGPT, Calculator]
```
When adding an action, you also need to make the code to handle the action. There is a cell that defines a function called `parse_action`. There is an if, elif, else statement that you can add an elif to like this:
```python
if last_action.lower() == 'web search':
...
elif ...:
...
elif last_action.lower() == "calculator":
# calculator code here
# example
try:
answer = eval(last_action_input)
content = str(answer)
content = truncate_text(chatgpt, content.strip(), max_tokens) # truncate the text to the max tokens
cache[last_action+last_action_input] = content # cache the content
return content
except:
return "Invalid expression"
else:
...
```
It is important to note that you should add the truncate_text function and the cache to the end of your elif statement. The truncate_text will prevent eating up all of your tokens while the cache will prevent the model from having to recompute the same action over and over again. You do not have to change the truncate_text and cache lines, just make sure your final text is in a variable called `content`. Also try to make sure any errors are caught and returned as a string for the model to respond to.
- Create a function that takes the arguments (last_action_input, chatgpt, max_tokens) and outputs the result of the truncate_text function (Don't forget to validate the input string matches what your function logic expects) (example in notebook)
- Add the function `name`, `definition`, and the `function` as a dictionary to the `function_definitions` list (example in notebook)

# How to use assistant class
- The assistant class is a wrapper around chat style openai models. It has support for short term memory, long term memory, knowledge retrieval, memory summarization, and more. In order to use the action loop, make sure you do not use short or long term memory. If you want to use long term memory, you need to set up a docker container for (Qdrant)[https://qdrant.tech/] (free).
Expand Down
66 changes: 66 additions & 0 deletions chat_tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import re

from tools import python_runner, WebBrowser, WebSearch


def truncate_text(assistant, text, max_length=500, side='right'):
if side == 'right':
return assistant.enc.decode(assistant.enc.encode(text)[:max_length])
else:
return assistant.enc.decode(assistant.enc.encode(text)[-max_length:])


def remove_markdown_formatting(code: str) -> str:
code = re.sub(r'(```python)|(```)|(`)', '', code)
return code.strip()


def web_search(last_action_input, chatgpt=None, max_tokens=500):
search = WebSearch()
last_action_input = last_action_input.strip('\"') # remove quotes to receive better search results
print('Searching for: ' + last_action_input + '...')
results = search.search(keywords=last_action_input, safesearch='Off', time=None, max_results=10)
out = '{'
for result in results:
out += 'title: ' + result['title'] + ',\n\tbody: ' + result['body'] + ',\n\t' + 'url: ' + result['href'] + ',\n\t'
return truncate_text(chatgpt, out.strip(), max_tokens) + '}'


def ask_chatgpt(last_action_input, chatgpt, max_tokens):
print('Asking ChatGPT: ' + last_action_input + '...')
response = chatgpt.get_chat_response(last_action_input)
return truncate_text(chatgpt, response.choices[0].message.content.strip(), max_tokens)


def get_readable_content(last_action_input, chatgpt, max_tokens):
print(f'Getting readable content for {last_action_input}...')
browser = WebBrowser()
summarize_prompt = 'Summarize the following text while trying to stay under 500 words. Include all important and relevant information:\n{text}'
max_tokens_for_prompt = 3500
contents = str(browser.get_readable_content(url=last_action_input.strip()))
if chatgpt.calculate_num_tokens(contents) > max_tokens:
summary_prompt = summarize_prompt.format(text=contents)
# Trim to max_tokens_for_prompt to add padding for the response
summary_prompt = chatgpt.enc.decode(chatgpt.enc.encode(summary_prompt)[:max_tokens_for_prompt])
contents = '{summarized content: ' + chatgpt.get_chat_response(summary_prompt).choices[0].message.content.strip() + '}'
return truncate_text(chatgpt, contents[:-1], max_tokens) + '}'


def get_internal_links(last_action_input, chatgpt, max_tokens):
browser = WebBrowser()
contents = browser.get_internal_links(url=last_action_input.strip())['internal_links']
return truncate_text(chatgpt, str(contents), max_tokens)[:-1] + ']'


def get_external_links(last_action_input, chatgpt, max_tokens):
browser = WebBrowser()
contents = browser.get_external_links(url=last_action_input.strip())['external_links']
return truncate_text(chatgpt, str(contents), max_tokens)[:-1] + ']'


def run_python_code(last_action_input, chatgpt, max_tokens):
# Remove markdown formatting (triple backticks) if present
last_action_input = remove_markdown_formatting(last_action_input.strip())

print(f'Running Python code: {last_action_input}...')
return truncate_text(chatgpt, python_runner(last_action_input.strip('"')).strip(), max_tokens)
Loading

0 comments on commit c9144ea

Please sign in to comment.