ManishThota commited on
Commit
267e47b
1 Parent(s): c82f10f

Create app2.py

Browse files
Files changed (1) hide show
  1. app2.py +314 -0
app2.py ADDED
@@ -0,0 +1,314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import base64
3
+ import os
4
+ from openai import OpenAI
5
+ import json
6
+
7
+ from doc2json import process_docx
8
+
9
+ dump_controls = False
10
+ log_to_console = False
11
+
12
+ # constants
13
+ image_embed_prefix = "🖼️🆙 "
14
+
15
+ def encode_image(image_data):
16
+ """Generates a prefix for image base64 data in the required format for the
17
+ four known image formats: png, jpeg, gif, and webp.
18
+
19
+ Args:
20
+ image_data: The image data, encoded in base64.
21
+
22
+ Returns:
23
+ A string containing the prefix.
24
+ """
25
+
26
+ # Get the first few bytes of the image data.
27
+ magic_number = image_data[:4]
28
+
29
+ # Check the magic number to determine the image type.
30
+ if magic_number.startswith(b'\x89PNG'):
31
+ image_type = 'png'
32
+ elif magic_number.startswith(b'\xFF\xD8'):
33
+ image_type = 'jpeg'
34
+ elif magic_number.startswith(b'GIF89a'):
35
+ image_type = 'gif'
36
+ elif magic_number.startswith(b'RIFF'):
37
+ if image_data[8:12] == b'WEBP':
38
+ image_type = 'webp'
39
+ else:
40
+ # Unknown image type.
41
+ raise Exception("Unknown image type")
42
+ else:
43
+ # Unknown image type.
44
+ raise Exception("Unknown image type")
45
+
46
+ return f"data:image/{image_type};base64,{base64.b64encode(image_data).decode('utf-8')}"
47
+
48
+ def add_text(history, text):
49
+ history = history + [(text, None)]
50
+ return history, gr.Textbox(value="", interactive=False)
51
+
52
+ def add_file(history, files):
53
+ for file in files:
54
+ if file.name.endswith(".docx"):
55
+ content = process_docx(file.name)
56
+ else:
57
+ with open(file.name, mode="rb") as f:
58
+ content = f.read()
59
+
60
+ if isinstance(content, bytes):
61
+ content = content.decode('utf-8', 'replace')
62
+ else:
63
+ content = str(content)
64
+
65
+ fn = os.path.basename(file.name)
66
+ history = history + [(f'```{fn}\n{content}\n```', None)]
67
+
68
+ gr.Info(f"File added as {fn}")
69
+
70
+ return history
71
+
72
+ def add_img(history, files):
73
+ for file in files:
74
+ if log_to_console:
75
+ print(f"add_img {file.name}")
76
+ history = history + [(image_embed_prefix + file.name, None)]
77
+
78
+ gr.Info(f"Image added as {file.name}")
79
+
80
+ return history
81
+
82
+ def submit_text(txt_value):
83
+ return add_text([chatbot, txt_value], [chatbot, txt_value])
84
+
85
+ def undo(history):
86
+ history.pop()
87
+ return history
88
+
89
+ def dump(history):
90
+ return str(history)
91
+
92
+ def load_settings():
93
+ # Dummy Python function, actual loading is done in JS
94
+ pass
95
+
96
+ def save_settings(acc, sec, prompt, temp, tokens, model):
97
+ # Dummy Python function, actual saving is done in JS
98
+ pass
99
+
100
+ def process_values_js():
101
+ return """
102
+ () => {
103
+ return ["oai_key", "system_prompt", "seed"];
104
+ }
105
+ """
106
+
107
+ def bot(message, history, oai_key, system_prompt, seed, temperature, max_tokens, model):
108
+ try:
109
+ client = OpenAI(
110
+ api_key=oai_key
111
+ )
112
+
113
+ seed_i = None
114
+ if seed:
115
+ seed_i = int(seed)
116
+
117
+ if log_to_console:
118
+ print(f"bot history: {str(history)}")
119
+
120
+ history_openai_format = []
121
+ user_msg_parts = []
122
+ if system_prompt:
123
+ history_openai_format.append({"role": "system", "content": system_prompt})
124
+ for human, assi in history:
125
+ if human is not None:
126
+ if human.startswith(image_embed_prefix):
127
+ with open(human.lstrip(image_embed_prefix), mode="rb") as f:
128
+ content = f.read()
129
+ user_msg_parts.append({"type": "image_url",
130
+ "image_url":{"url": encode_image(content)}})
131
+ else:
132
+ user_msg_parts.append({"type": "text", "text": human})
133
+
134
+ if assi is not None:
135
+ if user_msg_parts:
136
+ history_openai_format.append({"role": "user", "content": user_msg_parts})
137
+ user_msg_parts = []
138
+
139
+ history_openai_format.append({"role": "assistant", "content": assi})
140
+
141
+ if message:
142
+ user_msg_parts.append({"type": "text", "text": human})
143
+
144
+ if user_msg_parts:
145
+ history_openai_format.append({"role": "user", "content": user_msg_parts})
146
+
147
+ if log_to_console:
148
+ print(f"br_prompt: {str(history_openai_format)}")
149
+
150
+ response = client.chat.completions.create(
151
+ model=model,
152
+ messages= history_openai_format,
153
+ temperature=temperature,
154
+ seed=seed_i,
155
+ max_tokens=max_tokens
156
+ )
157
+
158
+ if log_to_console:
159
+ print(f"br_response: {str(response)}")
160
+
161
+ history[-1][1] = response.choices[0].message.content
162
+ if log_to_console:
163
+ print(f"br_result: {str(history)}")
164
+
165
+ except Exception as e:
166
+ raise gr.Error(f"Error: {str(e)}")
167
+
168
+ return "", history
169
+
170
+ def import_history(history, file):
171
+ with open(file.name, mode="rb") as f:
172
+ content = f.read()
173
+
174
+ if isinstance(content, bytes):
175
+ content = content.decode('utf-8', 'replace')
176
+ else:
177
+ content = str(content)
178
+
179
+ # Deserialize the JSON content to history
180
+ history = json.loads(content)
181
+ # The history is returned and will be set to the chatbot component
182
+ return history
183
+
184
+ with gr.Blocks() as demo:
185
+ gr.Markdown("# OAI Chat (Nils' Version™️)")
186
+
187
+ with gr.Accordion("Settings"):
188
+ oai_key = gr.Textbox(label="OpenAI API Key", elem_id="oai_key")
189
+ model = gr.Dropdown(label="Model", value="gpt-4-turbo-preview", allow_custom_value=True, elem_id="model",
190
+ choices=["gpt-4-turbo-preview", "gpt-4-1106-preview", "gpt-4", "gpt-4-vision-preview", "gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-1106"])
191
+ system_prompt = gr.TextArea("You are a helpful AI.", label="System Prompt", lines=3, max_lines=250, elem_id="system_prompt")
192
+ seed = gr.Textbox(label="Seed", elem_id="seed")
193
+ temp = gr.Slider(0, 1, label="Temperature", elem_id="temp", value=1)
194
+ max_tokens = gr.Slider(1, 4000, label="Max. Tokens", elem_id="max_tokens", value=800)
195
+ save_button = gr.Button("Save Settings")
196
+ load_button = gr.Button("Load Settings")
197
+
198
+ load_button.click(load_settings, js="""
199
+ () => {
200
+ let elems = ['#oai_key textarea', '#system_prompt textarea', '#seed textarea', '#temp input', '#max_tokens input', '#model'];
201
+ elems.forEach(elem => {
202
+ let item = document.querySelector(elem);
203
+ let event = new InputEvent('input', { bubbles: true });
204
+ item.value = localStorage.getItem(elem.split(" ")[0].slice(1)) || '';
205
+ item.dispatchEvent(event);
206
+ });
207
+ }
208
+ """)
209
+
210
+ save_button.click(save_settings, [oai_key, system_prompt, seed, temp, max_tokens, model], js="""
211
+ (oai, sys, seed, temp, ntok, model) => {
212
+ localStorage.setItem('oai_key', oai);
213
+ localStorage.setItem('system_prompt', sys);
214
+ localStorage.setItem('seed', seed);
215
+ localStorage.setItem('temp', document.querySelector('#temp input').value);
216
+ localStorage.setItem('max_tokens', document.querySelector('#max_tokens input').value);
217
+ localStorage.setItem('model', model);
218
+ }
219
+ """)
220
+
221
+ chatbot = gr.Chatbot(
222
+ [],
223
+ elem_id="chatbot",
224
+ show_copy_button=True,
225
+ height=350
226
+ )
227
+
228
+ with gr.Row():
229
+ btn = gr.UploadButton("📁 Upload", size="sm", file_count="multiple")
230
+ img_btn = gr.UploadButton("🖼️ Upload", size="sm", file_count="multiple", file_types=["image"])
231
+ undo_btn = gr.Button("↩️ Undo")
232
+ undo_btn.click(undo, inputs=[chatbot], outputs=[chatbot])
233
+
234
+ clear = gr.ClearButton(chatbot, value="🗑️ Clear")
235
+
236
+ with gr.Row():
237
+ txt = gr.TextArea(
238
+ scale=4,
239
+ show_label=False,
240
+ placeholder="Enter text and press enter, or upload a file",
241
+ container=False,
242
+ lines=3,
243
+ )
244
+ submit_btn = gr.Button("🚀 Send", scale=0)
245
+ submit_click = submit_btn.click(add_text, [chatbot, txt], [chatbot, txt], queue=False).then(
246
+ bot, [txt, chatbot, oai_key, system_prompt, seed, temp, max_tokens, model], [txt, chatbot],
247
+ )
248
+ submit_click.then(lambda: gr.Textbox(interactive=True), None, [txt], queue=False)
249
+
250
+ if dump_controls:
251
+ with gr.Row():
252
+ dmp_btn = gr.Button("Dump")
253
+ txt_dmp = gr.Textbox("Dump")
254
+ dmp_btn.click(dump, inputs=[chatbot], outputs=[txt_dmp])
255
+
256
+ txt_msg = txt.submit(add_text, [chatbot, txt], [chatbot, txt], queue=False).then(
257
+ bot, [txt, chatbot, oai_key, system_prompt, seed, temp, max_tokens, model], [txt, chatbot],
258
+ )
259
+ txt_msg.then(lambda: gr.Textbox(interactive=True), None, [txt], queue=False)
260
+ file_msg = btn.upload(add_file, [chatbot, btn], [chatbot], queue=False, postprocess=False)
261
+ img_msg = img_btn.upload(add_img, [chatbot, img_btn], [chatbot], queue=False, postprocess=False)
262
+
263
+ with gr.Accordion("Import/Export", open = False):
264
+ import_button = gr.UploadButton("History Import")
265
+ export_button = gr.Button("History Export")
266
+ export_button.click(lambda: None, [chatbot], js="""
267
+ (chat_history) => {
268
+ // Convert the chat history to a JSON string
269
+ const history_json = JSON.stringify(chat_history);
270
+ // Create a Blob from the JSON string
271
+ const blob = new Blob([history_json], {type: 'application/json'});
272
+ // Create a download link
273
+ const url = URL.createObjectURL(blob);
274
+ const a = document.createElement('a');
275
+ a.href = url;
276
+ a.download = 'chat_history.json';
277
+ document.body.appendChild(a);
278
+ a.click();
279
+ document.body.removeChild(a);
280
+ URL.revokeObjectURL(url);
281
+ }
282
+ """)
283
+ dl_button = gr.Button("File download")
284
+ dl_button.click(lambda: None, [chatbot], js="""
285
+ (chat_history) => {
286
+ // Attempt to extract content enclosed in backticks with an optional filename
287
+ const contentRegex = /```(\\S*\\.(\\S+))?\\n?([\\s\\S]*?)```/;
288
+ const match = contentRegex.exec(chat_history[chat_history.length - 1][1]);
289
+ if (match && match[3]) {
290
+ // Extract the content and the file extension
291
+ const content = match[3];
292
+ const fileExtension = match[2] || 'txt'; // Default to .txt if extension is not found
293
+ const filename = match[1] || `download.${fileExtension}`;
294
+ // Create a Blob from the content
295
+ const blob = new Blob([content], {type: `text/${fileExtension}`});
296
+ // Create a download link for the Blob
297
+ const url = URL.createObjectURL(blob);
298
+ const a = document.createElement('a');
299
+ a.href = url;
300
+ // If the filename from the chat history doesn't have an extension, append the default
301
+ a.download = filename.includes('.') ? filename : `${filename}.${fileExtension}`;
302
+ document.body.appendChild(a);
303
+ a.click();
304
+ document.body.removeChild(a);
305
+ URL.revokeObjectURL(url);
306
+ } else {
307
+ // Inform the user if the content is malformed or missing
308
+ alert('Sorry, the file content could not be found or is in an unrecognized format.');
309
+ }
310
+ }
311
+ """)
312
+ import_button.upload(import_history, inputs=[chatbot, import_button], outputs=[chatbot])
313
+
314
+ demo.queue().launch()