Spaces:
Runtime error
Runtime error
File size: 12,478 Bytes
fffe233 c2f1d15 86ebbd6 c2f1d15 d75ada5 9ee6bd8 fffe233 a70d6e9 fffe233 9ee6bd8 17081bd 9ee6bd8 71e7cb2 17081bd 71e7cb2 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 71e7cb2 c2f1d15 1c1a76e c2f1d15 71e7cb2 0ac99df c2f1d15 1c1a76e 71e7cb2 df7ab32 71e7cb2 ae44014 71e7cb2 1c1a76e df7ab32 1c1a76e 71e7cb2 1c1a76e 71e7cb2 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 71e7cb2 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e 71e7cb2 c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e c2f1d15 1c1a76e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
import re, os, subprocess, openai, random, regex, shutil, requests, datetime
import pandas as pd
import numpy as np
import streamlit as st
from streamlit_chat import message
# some helper vars and functions
thispath = os.path.realpath(os.path.dirname(__file__))
if 'displayChat' not in st.session_state:
with st.spinner('Setting up plugins...'):
os.system('mkdir files')
thishour = str(datetime.datetime.now().hour)
if os.path.isfile(os.path.join(thispath, 'timestamp.txt')):
with open(os.path.join(thispath, 'timestamp.txt')) as f:
stampHour = f.readline().strip('\n')
if thishour != stampHour:
os.system('rm -rf files/*')
os.system('echo '+thishour+' > timestamp.txt')
else:
os.system('echo '+thishour+' > timestamp.txt')
os.system('mkdir plugins')
googleS = requests.get('https://raw.githubusercontent.com/d3n7/GPT-4-Unlimited-Tools/main/plugins/google.py').content
googlePath = os.path.join(thispath, 'plugins', 'google.py')
with open(googlePath, 'wb') as f:
f.write(googleS)
blipS = requests.get('https://raw.githubusercontent.com/d3n7/GPT-4-Unlimited-Tools/main/plugins/blip3.py').content
blipPath = os.path.join(thispath, 'plugins', 'blip2.py')
with open(blipPath, 'wb') as f:
f.write(blipS)
st.session_state['running'] = False # Triggers main GPT loop
st.session_state['followup'] = False # Follow flag for the main loop
st.session_state['prompt'] = ''
st.session_state['command'] = '' #command to be run locally
st.session_state['acceptreject'] = False #shows accept/reject buttons for when commands are called
st.session_state['history'] = [] #OpenAI convrsation history stored here
st.session_state['displayChat'] = False
st.session_state['displayCost'] = False
st.session_state['download'] = False #display download button
st.session_state['totalCost'] = 0 # total cost of API calls
regx = [r"([A-Z]+\(((?:[^()\"']|(?:\"[^\"]*\")|(?:'[^']*')|\((?1)*\))*)\))",
r'''(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\b[^,]+)'''] #parsing commands, parsing arguments (thanks GPT-4)
#system message
sysPrompt = 'You now have access to some commands to help complete the user\'s request. ' \
'You are able to access the user\'s machine with these commands. In every message you send, ' \
'include "COMMAND: " with your command at the end. Here is a list of commands with ' \
'explanations of how they are used:\n{}\n When you use a command, the user will respond ' \
'with "Response: " followed by the output of the commmand. Use this output to help the ' \
'user complete their request.'
#format command table for GPT-4
def formatTable(table):
lines = ''
for x, i in enumerate(table['GPT Commands']):
lines += '{} - {}\n'.format(table['GPT Commands'][x],table['GPT Explanations'][x])
return(lines)
#Ask GPT a prompt, update history and total cost, return a response
def askGPT(input, version):
st.session_state['history'].append({'role': 'user', 'content': input})
with st.spinner('Talking to OpenAI...'):
r = openai.ChatCompletion.create(model=version, messages=st.session_state['history'])
resp = r['choices'][0]['message']['content']
costFactor = [0.03, 0.06] if version == 'gpt-4' else [0.002, 0.002]
st.session_state['totalCost'] += r['usage']['prompt_tokens']/1000*costFactor[0]+r['usage']['completion_tokens']/1000*costFactor[1]
st.session_state['history'].append({'role': 'assistant', 'content': resp})
return resp
#restart main loop with followup flag
def followup():
st.session_state['followup'], st.session_state['running'] = True, True
st.experimental_rerun()
#run a GPT command or reject it
def runCmd(flag):
if flag:
with st.spinner('Running command \'' + st.session_state['command'] + '\''):
try:
p = subprocess.Popen(st.session_state['command'], shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
p.wait()
st.session_state['prompt'] = 'Response: ' + p.communicate()[0].decode("utf-8")
except subprocess.CalledProcessError as e:
st.session_state['prompt'] = 'Response: ' + e.output.decode("utf-8")
else:
st.session_state['prompt'] = "Response: User rejected this command"
followup()
# WEB APP
st.markdown('# GPT-4 UNLIMITED PLUGINS')
st.markdown('Made by [d3nt](https://github.com/d3n7) to give GPT-4 access to any commands/scripts you want via the command line. This unlocks the ability for GPT-4 to interact with the internet, APIs, and any applications that you could with a CLI. Basically it\'s open source, flexible, plugins for GPT-4.')
#User inputs
st.markdown('### OpenAI Settings')
openaikey = st.text_input('OpenAI API Key', type='password')
replicatekey = st.text_input('(OPTIONAL) Replicate API Key', type='password')
modelV = st.selectbox('Model', ('GPT-4', 'GPT-3.5-Turbo'))
st.markdown('### Editable Knowledge Base\nDelete any commands will not need to save tokens and increase accuracy.\n\nBe careful with the Raw Translation column. This is code that gets executed by your machine.')
d = {'GPT Commands': ['GOOGLE("question")', 'PYTHON(script.py)', 'MAKEFILE("content\\nhere", filename.txt)', 'READFILE(filename.txt)', 'LISTFILES()', 'BLIP("What\'s in this image?", img1.jpg)'],
'GPT Explanations': ['Search Google with the given text and return the results', 'Run a python script with the given file name. Do not use quotes for the filename argument.', 'Make a file with the given content and file name.', 'Read the content of a given filename', 'List the files you have access to', 'Ask BLIP-2, a vision model, a given question about a given image'],
'Raw Translation': ['python plugins/google.py {}', 'cd files && python {} && cd ../', 'echo {} > files/{}', 'cat files/{}', 'ls files', 'python plugins/blip2.py {} {}']
}
df = pd.DataFrame(data=d, dtype='string')
commandTable = st.experimental_data_editor(df, use_container_width=True, num_rows='dynamic')
st.markdown('### Upload/Download Files')
uploadFile = st.file_uploader('')
cola, colb, colc = st.columns(3)
with cola:
if st.button('Upload'):
if uploadFile:
fname = uploadFile.name
st.markdown(fname)
with open(os.path.join(thispath, 'files', fname), 'wb') as f:
f.write(uploadFile.getbuffer())
st.write('Success')
with colb:
if st.button('Download'):
shutil.make_archive(os.path.join(thispath, 'files'), 'zip', os.path.join(thispath, 'files'))
st.session_state['download'] = True
with colc:
if st.session_state['download']:
with open(os.path.join(thispath, 'files.zip'), 'rb') as f:
st.download_button('Download Zip', f, file_name='file.zip', key='filezip')
st.markdown('### Chat')
prompt = st.text_input('Message')
col1, col2, col3, col4 = st.columns(4)
#this button triggers main loop
with col1:
if st.button('Send'):
st.session_state['running'] = True
with col2:
newSession = st.checkbox('New Session', True)
with col3:
showAll = st.checkbox('Show Commands And Outputs', False)
with col4:
manualApproval = st.checkbox('Require Manual Approval', True)
#MAIN GPT LOOP
if st.session_state['running']:
st.session_state['running'] = False #reset running flag
#get user prompt
if not st.session_state['followup']:
st.session_state['prompt'] = prompt
os.environ['REPLICATE_API_TOKEN'] = replicatekey
if openaikey != '':
#set system prompt or update system prompt
if (newSession or st.session_state['history'] == []) and (not st.session_state['followup']):
st.session_state['history'] = [{'role': 'system', 'content': sysPrompt.format(formatTable(commandTable))}]
else:
st.session_state['history'][0] = {'role': 'system', 'content': sysPrompt.format(formatTable(commandTable))}
st.session_state['followup'] = False #reset followup flag
#turn on display for chat and cost if it's not already on
if not st.session_state['displayChat']:
st.session_state['displayChat'] = True
if not st.session_state['displayCost']:
st.session_state['displayCost'] = True
#ask GPT-4
openai.api_key = openaikey
response = askGPT(st.session_state['prompt'], modelV.lower())
#parse GPT commands, possibly trigger this loop again
if len(regex.findall(regx[0], response)) >= 1:
cmd = regex.findall(regx[0], response)[0][0]
stem = ''
rawArgs = ''
cmdId = -1
#seperate command into stem and arguments
for x, i in enumerate(cmd):
if i == '(':
stem = cmd[:x]
rawArgs = cmd[x+1:][:-1]
break
#identify command
for x, i in enumerate(commandTable['GPT Commands']):
if stem in i:
cmdId = x
break
#Handle incorrect command usage, or run the command
rawArgs.replace('\n', '\\n')
rawArgs.replace('\\\n', '\\n')
if cmdId == -1:
st.session_state['prompt'] = 'Response: Unrecognized command'
followup()
elif "'''" in rawArgs:
st.session_state['prompt'] = 'Response: Error parsing multi-line string (\'\'\') Use a single line with escaped newlines instead (")'
followup()
elif '"""' in rawArgs:
st.session_state['prompt'] = 'Response: Error parsing multi-line string (\"\"\") Use a single line with escaped newlines instead (")'
followup()
else:
# Fetch command, turn raw argument string into a list of arguments, and format command
st.session_state['command'] = commandTable['Raw Translation'][cmdId]
args = []
if rawArgs != '':
args = re.findall(regx[1], rawArgs)
st.session_state['command'] = st.session_state['command'].format(*args)
# No single quote arguments allowed. Messes up MAKEFILE() and probably other commands.
singleQuotes = False
for i in args:
if i.startswith("'"):
singleQuotes = True
st.session_state['prompt'] = "Response: Error parsing argument in single quotes. Use double quotes around the argument instead"
followup()
break
#If none of the above was a problem, run the command
if not singleQuotes:
if manualApproval:
st.session_state['acceptreject'] = True
else:
runCmd(1)
else:
st.warning('Make sure OpenAI key is entered', icon='⚠️')
#UI for accepting/rejecting commands
col5, col6 = st.columns(2)
if st.session_state['acceptreject']:
st.warning('GPT is trying to run the following command: ' + st.session_state['command'] + '\nPlease accept or reject this request.')
with col5:
if st.button('Accept'):
st.session_state['acceptreject'] = False
runCmd(1)
with col6:
if st.button('Reject'):
st.session_state['acceptreject'] = False
runCmd(0)
#display cost for the user
if st.session_state['displayCost']:
st.info('Total OpenAI cost: $'+str(round(st.session_state['totalCost'],2)), icon='💸')
#display chat for the user
if st.session_state['displayChat']:
for i in st.session_state['history']:
if i['role'] == 'user':
if not showAll:
if 'Response:' not in i['content']:
message(i['content'], is_user=True, key=random.randint(1,9999))
else:
message(i['content'], is_user=True, key=random.randint(1,9999))
elif i['role'] == 'assistant':
if not showAll:
if 'COMMAND' not in i['content']:
message(i['content'], key=random.randint(1,9999))
else:
message(i['content'], key=random.randint(1,9999)) |