cbg342 commited on
Commit
c2f1d15
1 Parent(s): 2c52f77

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +177 -0
app.py ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re, subprocess, openai, random
2
+ import pandas as pd
3
+ import numpy as np
4
+ import streamlit as st
5
+ from streamlit_chat import message
6
+
7
+ # some helper vars and functions
8
+ if 'displayChat' not in st.session_state:
9
+ st.session_state['displayChat'] = False
10
+ if 'followup' not in st.session_state:
11
+ st.session_state['followup'] = False
12
+ if 'followupPrompt' not in st.session_state:
13
+ st.session_state['followupPrompt'] = ''
14
+ if 'command' not in st.session_state:
15
+ st.session_state['command'] = ''
16
+ if 'acceptreject' not in st.session_state:
17
+ st.session_state['acceptreject'] = False
18
+ if 'history' not in st.session_state:
19
+ st.session_state['history'] = []
20
+ if 'running' not in st.session_state:
21
+ st.session_state['running'] = False
22
+ regx = [r'[A-Z]+\((?:[^()]*|\([^()]*\))*\)', r'''(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\b[^,]+)'''] #parsing commands, parsing arguments
23
+ 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.'
24
+
25
+ def formatTable(table):
26
+ lines = ''
27
+ for x, i in enumerate(table['GPT Commands']):
28
+ lines += '{} - {}\n'.format(table['GPT Commands'][x],table['GPT Explanations'][x])
29
+ return(lines)
30
+
31
+ # WEB APP
32
+ st.markdown('# GPT-4 + CUSTOM PLUGINS')
33
+ 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.')
34
+
35
+ #User inputs
36
+ st.markdown('### OpenAI Settings')
37
+ openaikey = st.text_input('OpenAI API Key', type='password')
38
+ modelV = st.selectbox('Model', ('GPT-4', 'GPT-3.5-Turbo'))
39
+ 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.')
40
+ d = {'GPT Commands': ['GOOGLE("question")', 'PYTHON(script.py)', 'MAKEFILE("content\\nhere", filename.txt)', 'READFILE(filename.txt)', 'LISTFILES()'],
41
+ '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'],
42
+ 'Raw Translation': ['python plugins/google.py {}', 'python files/{}', 'echo {} > files/{}', 'cat files/{}', 'ls files']
43
+ }
44
+ df = pd.DataFrame(data=d, dtype='string')
45
+ commandTable = st.experimental_data_editor(df, use_container_width=True, num_rows='dynamic')
46
+ st.markdown('### Chat')
47
+ prompt = st.text_input('Message')
48
+ col1, col2, col3, col4 = st.columns(4)
49
+ with col1:
50
+ if st.button('Send'):
51
+ st.session_state['running'] = True
52
+ with col2:
53
+ newSession = st.checkbox('New Session', True)
54
+ with col3:
55
+ showAll = st.checkbox('Show Commands And Outputs', False)
56
+ with col4:
57
+ manualApproval = st.checkbox('Require Manual Approval', True)
58
+
59
+ def askGPT(input):
60
+ st.session_state['history'].append({'role': 'user', 'content': input})
61
+ with st.spinner('Talking to OpenAI...'):
62
+ r = openai.ChatCompletion.create(model=modelV.lower(), messages=st.session_state['history'])
63
+ resp = r['choices'][0]['message']['content']
64
+ st.session_state['history'].append({'role': 'assistant', 'content': resp})
65
+ return resp
66
+
67
+ def runCmd(flag):
68
+ if flag:
69
+ with st.spinner('Running command \'' + st.session_state['command'] + '\''):
70
+ try:
71
+ p = subprocess.Popen(st.session_state['command'], shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
72
+ st.session_state['followupPrompt'] = 'Response: ' + p.communicate()[0].decode("utf-8")
73
+ except subprocess.CalledProcessError as e:
74
+ st.session_state['followupPrompt'] = 'Response: ' + e.output.decode("utf-8")
75
+ else:
76
+ st.session_state['followupPrompt'] = "Response: User rejected this command"
77
+ st.session_state['followup'], st.session_state['running'] = True, True
78
+ st.session_state['followup'], st.session_state['running'] = True, True
79
+ st.experimental_rerun()
80
+
81
+ if st.session_state['running']:
82
+ st.session_state['running'] = False
83
+ if prompt != '' and openaikey != '':
84
+ if (newSession or st.session_state['history'] == []) and (not st.session_state['followup']):
85
+ st.session_state['history'] = [{'role': 'system', 'content': sysPrompt.format(formatTable(commandTable))}]
86
+
87
+ if not st.session_state['displayChat']:
88
+ st.session_state['displayChat'] = True
89
+
90
+ openai.api_key = openaikey
91
+ if (st.session_state['followup']):
92
+ response = askGPT(st.session_state['followupPrompt'])
93
+ st.session_state['followup'] = False #completed, so reset this flag
94
+ else:
95
+ response = askGPT(prompt)
96
+
97
+ #parse GPT commands, possible recursion
98
+ if len(re.findall(regx[0], response)) >= 1:
99
+ cmd = re.findall(regx[0], response)[0]
100
+ stem = ''
101
+ rawArgs = ''
102
+ cmdId = -1
103
+ for x, i in enumerate(cmd):
104
+ if i == '(':
105
+ stem = cmd[:x]
106
+ rawArgs = cmd[x+1:][:-1]
107
+ break
108
+ rawArgs.replace('\n','\\n')
109
+ rawArgs.replace('\\\n', '\\n')
110
+ for x, i in enumerate(commandTable['GPT Commands']):
111
+ if stem in i:
112
+ cmdId = x
113
+ break
114
+
115
+ if cmdId == -1:
116
+ st.session_state['followupPrompt'] = 'Response: Unrecognized command'
117
+ st.session_state['followup'], st.session_state['running'] = True, True
118
+ st.experimental_rerun()
119
+ elif "'''" in rawArgs:
120
+ st.session_state['followupPrompt'] = 'Response: Error parsing multi-line string (\'\'\') Use a single line with escaped newlines instead (")'
121
+ st.session_state['followup'], st.session_state['running'] = True, True
122
+ st.experimental_rerun()
123
+ elif '"""' in rawArgs:
124
+ st.session_state['followupPrompt'] = 'Response: Error parsing multi-line string (\"\"\") Use a single line with escaped newlines instead (")'
125
+ st.session_state['followup'], st.session_state['running'] = True, True
126
+ st.experimental_rerun()
127
+ else:
128
+ st.session_state['command'] = commandTable['Raw Translation'][cmdId]
129
+ args = []
130
+ if rawArgs != '':
131
+ args = re.findall(regx[1], rawArgs)
132
+ st.session_state['command'] = st.session_state['command'].format(*args)
133
+ singleQuotes = False
134
+ for i in args:
135
+ if i.startswith("'"):
136
+ singleQuotes = True
137
+ st.session_state['followupPrompt'] = "Response: Error parsing argument in single quotes. Use double quotes around the argument instead"
138
+ st.session_state['followup'], st.session_state['running'] = True, True
139
+ st.experimental_rerun()
140
+ break
141
+ if not singleQuotes:
142
+ if manualApproval:
143
+ st.session_state['acceptreject'] = True
144
+ else:
145
+ runCmd(1)
146
+
147
+ else:
148
+ st.warning('Make sure OpenAI key and prompt entered', icon='⚠️')
149
+
150
+ col5, col6 = st.columns(2)
151
+ if st.session_state['acceptreject']:
152
+
153
+ st.warning('GPT is trying to run the following command: ' + st.session_state['command'] + '\nPlease approve or deny this request.')
154
+
155
+ with col5:
156
+ if st.button('Approve'):
157
+ st.session_state['acceptreject'] = False
158
+ runCmd(1)
159
+ with col6:
160
+ if st.button('Reject'):
161
+ st.session_state['acceptreject'] = False
162
+ runCmd(0)
163
+
164
+ if st.session_state['displayChat']:
165
+ for i in st.session_state['history']:
166
+ if i['role'] == 'user':
167
+ if not showAll:
168
+ if 'Response:' not in i['content']:
169
+ message(i['content'], is_user=True)
170
+ else:
171
+ message(i['content'], is_user=True)
172
+ elif i['role'] == 'assistant':
173
+ if not showAll:
174
+ if 'COMMAND' not in i['content']:
175
+ message(i['content'])
176
+ else:
177
+ message(i['content'])