Skip to content

Commit 67460a2

Browse files
committed
Store and use the full conversation history in proper chat mode. This way, referring to previous code is simpler.
1 parent 773cf4f commit 67460a2

File tree

2 files changed

+56
-79
lines changed

2 files changed

+56
-79
lines changed

frontend/src/App.tsx

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ function App() {
4141
let [messages, setMessages] = useState<Array<MessageDict>>(
4242
Array.from([
4343
{
44-
text: "Hello! I'm a GPT Code assistant. Ask me to do something for you! Pro tip: you can upload a file and I'll be able to use it.",
45-
role: "system",
44+
text: "Hello! I am a GPT Code assistant. Ask me to do something for you! Pro tip: you can upload a file and I'll be able to use it.",
45+
role: "generator",
4646
type: "message",
4747
},
4848
{
@@ -169,19 +169,6 @@ function App() {
169169
});
170170

171171
setWaitingForSystem(WaitingStates.Idle);
172-
173-
// Inform prompt server
174-
fetch(`${Config.WEB_ADDRESS}/inject-context`, {
175-
method: "POST",
176-
headers: {
177-
"Content-Type": "application/json",
178-
},
179-
body: JSON.stringify({
180-
prompt: message,
181-
}),
182-
})
183-
.then(() => {})
184-
.catch((error) => console.error("Error:", error));
185172
}
186173

187174
function startUpload(_: string) {

gpt_code_ui/webapp/main.py

Lines changed: 54 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
import openai
1010
import pandas as pd
1111

12-
from collections import deque
13-
1412
from flask_cors import CORS
1513
from flask import Flask, request, jsonify, send_from_directory, Response
1614
from dotenv import load_dotenv
@@ -40,25 +38,56 @@
4038
APP_PORT = int(os.environ.get("WEB_PORT", 8080))
4139

4240

43-
class LimitedLengthString:
44-
def __init__(self, maxlen=2000):
45-
self.data = deque()
46-
self.len = 0
47-
self.maxlen = maxlen
41+
class ChatHistory():
42+
def __init__(self):
43+
self._buffer = list()
4844

49-
def append(self, string):
50-
self.data.append(string)
51-
self.len += len(string)
52-
while self.len > self.maxlen:
53-
popped = self.data.popleft()
54-
self.len -= len(popped)
45+
self.append(
46+
"system",
47+
"""Write Python code, in a triple backtick Markdown code block, that answers the user prompts.
5548
56-
def get_string(self):
57-
result = ''.join(self.data)
58-
return result[-self.maxlen:]
49+
Notes:
50+
Do not use your own knowledge to answer the user prompt. Instead, focus on generating Python code for doing so.
51+
First, think step by step what you want to do and write it down in English.
52+
Then generate valid Python code in a single code block.
53+
Do not add commands to install packages.
54+
Make sure all code is valid - it will e run in a Jupyter Python 3 kernel environment.
55+
Define every variable before you use it.
56+
For data processing, you can use
57+
'numpy', # numpy==1.24.3
58+
'dateparser' #dateparser==1.1.8
59+
'pandas', # matplotlib==1.5.3
60+
'geopandas' # geopandas==0.13.2
61+
'tabulate' # tabulate==0.9.0
62+
For pdf extraction, you can use
63+
'PyPDF2', # PyPDF2==3.0.1
64+
'pdfminer', # pdfminer==20191125
65+
'pdfplumber', # pdfplumber==0.9.0
66+
For data visualization, you can use
67+
'matplotlib', # matplotlib==3.7.1
68+
Be sure to generate charts with matplotlib. If you need geographical charts, use geopandas with the geopandas.datasets module.
69+
If the user requests to generate a table, produce code that prints a markdown table.
70+
If the user has just uploaded a file, focus on the file that was most recently uploaded (and optionally all previously uploaded files)
71+
72+
If the code modifies or produces a file, at the end of the code block insert a print statement that prints a link to it as HTML string: <a href='/download?file=INSERT_FILENAME_HERE'>Download file</a>. Replace INSERT_FILENAME_HERE with the actual filename.""")
73+
74+
def append(self, role: str, content: str):
75+
if role not in ("user", "assistant", "system"):
76+
raise ValueError(f"Invalid role: {role}")
5977

78+
self._buffer.append({
79+
"role": role,
80+
"content": content,
81+
})
6082

61-
message_buffer = LimitedLengthString()
83+
def upload_file(self, filename: str, file_info: str = None):
84+
self.append("user", f"In the following, I will refer to the file {filename}.\n{file_info}")
85+
86+
def __call__(self):
87+
return self._buffer
88+
89+
90+
chat_history = ChatHistory()
6291

6392

6493
def allowed_file(filename):
@@ -92,47 +121,15 @@ def inspect_file(filename: str) -> str:
92121
return '' # file reading failed. - Don't want to know why.
93122

94123

95-
async def get_code(user_prompt, user_openai_key=None, model="gpt-3.5-turbo"):
96-
97-
prompt = f"""First, here is a history of what I asked you to do earlier.
98-
The actual prompt follows after ENDOFHISTORY.
99-
History:
100-
{message_buffer.get_string()}
101-
ENDOFHISTORY.
102-
Write Python code, in a triple backtick Markdown code block, that does the following:
103-
{user_prompt}
104-
105-
Notes:
106-
First, think step by step what you want to do and write it down in English.
107-
Then generate valid Python code in a code block
108-
Make sure all code is valid - it be run in a Jupyter Python 3 kernel environment.
109-
Define every variable before you use it.
110-
For data munging, you can use
111-
'numpy', # numpy==1.24.3
112-
'dateparser' #dateparser==1.1.8
113-
'pandas', # matplotlib==1.5.3
114-
'geopandas' # geopandas==0.13.2
115-
For pdf extraction, you can use
116-
'PyPDF2', # PyPDF2==3.0.1
117-
'pdfminer', # pdfminer==20191125
118-
'pdfplumber', # pdfplumber==0.9.0
119-
For data visualization, you can use
120-
'matplotlib', # matplotlib==3.7.1
121-
Be sure to generate charts with matplotlib. If you need geographical charts, use geopandas with the geopandas.datasets module.
122-
If the user has just uploaded a file, focus on the file that was most recently uploaded (and optionally all previously uploaded files)
123-
124-
Teacher mode: if the code modifies or produces a file, at the end of the code block insert a print statement that prints a link to it as HTML string: <a href='/download?file=INSERT_FILENAME_HERE'>Download file</a>. Replace INSERT_FILENAME_HERE with the actual filename."""
124+
async def get_code(messages, user_openai_key=None, model="gpt-3.5-turbo"):
125125

126126
if user_openai_key:
127127
openai.api_key = user_openai_key
128128

129129
arguments = dict(
130130
temperature=0.7,
131131
headers=OPENAI_EXTRA_HEADERS,
132-
messages=[
133-
# {"role": "system", "content": system},
134-
{"role": "user", "content": prompt},
135-
]
132+
messages=messages,
136133
)
137134

138135
if openai.api_type == 'open_ai':
@@ -240,16 +237,6 @@ def download_file():
240237
return send_from_directory(os.path.join(os.getcwd(), 'workspace'), file, as_attachment=True)
241238

242239

243-
@app.route('/inject-context', methods=['POST'])
244-
def inject_context():
245-
user_prompt = request.json.get('prompt', '')
246-
247-
# Append all messages to the message buffer for later use
248-
message_buffer.append(user_prompt + "\n\n")
249-
250-
return jsonify({"result": "success"})
251-
252-
253240
@app.route('/generate', methods=['POST'])
254241
def generate_code():
255242
user_prompt = request.json.get('prompt', '')
@@ -259,12 +246,14 @@ def generate_code():
259246
loop = asyncio.new_event_loop()
260247
asyncio.set_event_loop(loop)
261248

249+
chat_history.append("user", user_prompt)
250+
262251
code, text, status = loop.run_until_complete(
263-
get_code(user_prompt, user_openai_key, model))
252+
get_code(chat_history(), user_openai_key, model))
264253
loop.close()
265254

266-
# Append all messages to the message buffer for later use
267-
message_buffer.append(user_prompt + "\n\n")
255+
if status == 200:
256+
chat_history.append("assistant", text)
268257

269258
return jsonify({'code': code, 'text': text}), status
270259

@@ -283,6 +272,7 @@ def upload_file():
283272
file_target = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
284273
file.save(file_target)
285274
file_info = inspect_file(file_target)
275+
chat_history.upload_file(file.filename, file_info)
286276
return jsonify({'message': f'File {file.filename} uploaded successfully.\n{file_info}'}), 200
287277
else:
288278
return jsonify({'error': 'File type not allowed'}), 400

0 commit comments

Comments
 (0)