JohnSmith9982 commited on
Commit
677701d
1 Parent(s): aa49d7e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -54
app.py CHANGED
@@ -48,34 +48,36 @@ def parse_text(text):
48
  count += 1
49
  items = line.split('`')
50
  if count % 2 == 1:
51
- lines[i] = f'<pre><code class="{items[-1]}" style="display: block; white-space: pre; padding: 0 1em 1em 1em; color: #fff; background: #000;">'
52
  firstline = True
53
  else:
54
  lines[i] = f'</code></pre>'
55
  else:
56
  if i > 0:
57
  if count % 2 == 1:
58
- line = line.replace("&", "&amp;")
59
  line = line.replace("\"", "`\"`")
60
  line = line.replace("\'", "`\'`")
 
61
  line = line.replace("<", "&lt;")
62
  line = line.replace(">", "&gt;")
63
  line = line.replace(" ", "&nbsp;")
64
  line = line.replace("*", "&ast;")
65
  line = line.replace("_", "&lowbar;")
66
- line = line.replace("#", "&#35;")
67
  line = line.replace("-", "&#45;")
68
  line = line.replace(".", "&#46;")
69
  line = line.replace("!", "&#33;")
70
  line = line.replace("(", "&#40;")
71
  line = line.replace(")", "&#41;")
 
72
  lines[i] = "<br>"+line
73
  text = "".join(lines)
74
  return text
75
 
76
- def predict(inputs, top_p, temperature, openai_api_key, chatbot=[], history=[], system_prompt=initial_prompt, retry=False, summary=False): # repetition_penalty, top_k
77
 
78
- print(f"chatbot 1: {chatbot}")
 
79
 
80
  headers = {
81
  "Content-Type": "application/json",
@@ -88,24 +90,25 @@ def predict(inputs, top_p, temperature, openai_api_key, chatbot=[], history=[],
88
 
89
  messages = [compose_system(system_prompt)]
90
  if chat_counter:
91
- for data in chatbot:
92
  temp1 = {}
93
  temp1["role"] = "user"
94
- temp1["content"] = data[0]
95
  temp2 = {}
96
  temp2["role"] = "assistant"
97
- temp2["content"] = data[1]
98
  if temp1["content"] != "":
99
- messages.append(temp1)
100
- messages.append(temp2)
 
101
  else:
102
  messages[-1]['content'] = temp2['content']
103
  if retry and chat_counter:
104
  messages.pop()
105
  elif summary:
 
106
  messages.append(compose_user(
107
  "请帮我总结一下上述对话的内容,实现减少字数的同时,保证对话的质量。在总结中不要加入这一句话。"))
108
- history = ["我们刚刚聊了什么?"]
109
  else:
110
  temp3 = {}
111
  temp3["role"] = "user"
@@ -119,61 +122,82 @@ def predict(inputs, top_p, temperature, openai_api_key, chatbot=[], history=[],
119
  "temperature": temperature, # 1.0,
120
  "top_p": top_p, # 1.0,
121
  "n": 1,
122
- "stream": True,
123
  "presence_penalty": 0,
124
  "frequency_penalty": 0,
125
  }
126
 
127
  if not summary:
128
  history.append(inputs)
129
- print(f"payload is - {payload}")
 
130
  # make a POST request to the API endpoint using the requests.post method, passing in stream=True
131
  response = requests.post(API_URL, headers=headers,
132
  json=payload, stream=True)
133
- #response = requests.post(API_URL, headers=headers, json=payload, stream=True)
134
 
135
  token_counter = 0
136
  partial_words = ""
137
 
138
  counter = 0
139
- chatbot.append((history[-1], ""))
140
- for chunk in response.iter_lines():
141
- if counter == 0:
 
 
 
142
  counter += 1
143
- continue
144
- counter += 1
145
- # check whether each line is non-empty
146
- if chunk:
147
- # decode each line as response data is in bytes
148
- try:
149
- if len(json.loads(chunk.decode()[6:])['choices'][0]["delta"]) == 0:
 
 
 
 
 
 
 
 
 
 
150
  break
151
- except Exception as e:
152
- chatbot.pop()
153
- chatbot.append((history[-1], f"☹️发生了错误<br>返回值:{response.text}<br>异常:{e}"))
154
- history.pop()
155
- yield chatbot, history
156
- break
157
- #print(json.loads(chunk.decode()[6:])['choices'][0]["delta"] ["content"])
158
- partial_words = partial_words + \
159
- json.loads(chunk.decode()[6:])[
160
- 'choices'][0]["delta"]["content"]
161
- if token_counter == 0:
162
- history.append(" " + partial_words)
163
- else:
164
- history[-1] = parse_text(partial_words)
165
- chatbot[-1] = (history[-2], history[-1])
166
- # chat = [(history[i], history[i + 1]) for i in range(0, len(history) - 1, 2) ] # convert to tuples of list
167
- token_counter += 1
168
- # resembles {chatbot: chat, state: history}
169
- yield chatbot, history
 
 
 
 
170
 
171
 
172
 
173
  def delete_last_conversation(chatbot, history):
174
- chatbot.pop()
 
 
 
175
  history.pop()
176
  history.pop()
 
177
  return chatbot, history
178
 
179
  def save_chat_history(filename, system, history, chatbot):
@@ -183,6 +207,7 @@ def save_chat_history(filename, system, history, chatbot):
183
  filename += ".json"
184
  os.makedirs(HISTORY_DIR, exist_ok=True)
185
  json_s = {"system": system, "history": history, "chatbot": chatbot}
 
186
  with open(os.path.join(HISTORY_DIR, filename), "w") as f:
187
  json.dump(json_s, f)
188
 
@@ -190,13 +215,14 @@ def save_chat_history(filename, system, history, chatbot):
190
  def load_chat_history(filename):
191
  with open(os.path.join(HISTORY_DIR, filename), "r") as f:
192
  json_s = json.load(f)
 
193
  return filename, json_s["system"], json_s["history"], json_s["chatbot"]
194
 
195
 
196
  def get_file_names(dir, plain=False, filetype=".json"):
197
  # find all json files in the current directory and return their names
198
  try:
199
- files = [f for f in os.listdir(dir) if f.endswith(filetype)]
200
  except FileNotFoundError:
201
  files = []
202
  if plain:
@@ -207,13 +233,16 @@ def get_file_names(dir, plain=False, filetype=".json"):
207
  def get_history_names(plain=False):
208
  return get_file_names(HISTORY_DIR, plain)
209
 
210
- def load_template(filename):
211
  lines = []
212
  with open(os.path.join(TEMPLATES_DIR, filename), "r", encoding="utf8") as csvfile:
213
  reader = csv.reader(csvfile)
214
  lines = list(reader)
215
  lines = lines[1:]
216
- return {row[0]:row[1] for row in lines}, gr.Dropdown.update(choices=[row[0] for row in lines])
 
 
 
217
 
218
  def get_template_names(plain=False):
219
  return get_file_names(TEMPLATES_DIR, plain, filetype=".csv")
@@ -236,14 +265,41 @@ def reset_textbox():
236
  title = """<h1 align="center">川虎ChatGPT 🚀</h1>"""
237
  description = """<div align=center>
238
 
239
- 由Bilibili [土川虎虎虎](https://space.bilibili.com/29125536) 开发
240
 
241
  访问川虎ChatGPT的 [GitHub项目](https://github.com/GaiZhenbiao/ChuanhuChatGPT) 下载最新版脚本
242
 
243
  此App使用 `gpt-3.5-turbo` 大语言模型
244
  </div>
245
  """
246
- with gr.Blocks() as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  gr.HTML(title)
248
  gr.HTML('''<center><a href="https://huggingface.co/spaces/JohnSmith9982/ChuanhuChatGPT?duplicate=true"><img src="https://bit.ly/3gLdBN6" alt="复制 Space"></a>强烈建议点击上面的按钮复制一份这个Space,在你自己的Space里运行,响应更迅速、也更安全👆</center>''')
249
  keyTxt = gr.Textbox(show_label=True, placeholder=f"在这里输入你的OpenAI API-key...",
@@ -266,6 +322,7 @@ with gr.Blocks() as demo:
266
  retryBtn = gr.Button("🔄 重新生成")
267
  delLastBtn = gr.Button("🗑️ 删除上条对话")
268
  reduceTokenBtn = gr.Button("♻️ 总结对话")
 
269
  systemPromptTxt = gr.Textbox(show_label=True, placeholder=f"在这里输入System Prompt...",
270
  label="System prompt", value=initial_prompt).style(container=True)
271
  with gr.Accordion(label="加载Prompt模板", open=False):
@@ -278,7 +335,7 @@ with gr.Blocks() as demo:
278
  templaeFileReadBtn = gr.Button("📂 读入模板")
279
  with gr.Row():
280
  with gr.Column(scale=6):
281
- templateSelectDropdown = gr.Dropdown(label="从Prompt模板中加载", choices=[], multiselect=False)
282
  with gr.Column(scale=1):
283
  templateApplyBtn = gr.Button("⬇️ 应用")
284
  with gr.Accordion(label="保存/加载对话历史记录(在文本框中输入文件名,点击“保存对话”按钮,历史记录文件会被存储到Python文件旁边)", open=False):
@@ -307,18 +364,18 @@ with gr.Blocks() as demo:
307
 
308
 
309
  txt.submit(predict, [txt, top_p, temperature, keyTxt,
310
- chatbot, history, systemPromptTxt], [chatbot, history])
311
  txt.submit(reset_textbox, [], [txt])
312
  submitBtn.click(predict, [txt, top_p, temperature, keyTxt, chatbot,
313
- history, systemPromptTxt], [chatbot, history], show_progress=True)
314
  submitBtn.click(reset_textbox, [], [txt])
315
  emptyBtn.click(reset_state, outputs=[chatbot, history])
316
  retryBtn.click(predict, [txt, top_p, temperature, keyTxt, chatbot, history,
317
- systemPromptTxt, TRUECOMSTANT], [chatbot, history], show_progress=True)
318
  delLastBtn.click(delete_last_conversation, [chatbot, history], [
319
  chatbot, history], show_progress=True)
320
  reduceTokenBtn.click(predict, [txt, top_p, temperature, keyTxt, chatbot, history,
321
- systemPromptTxt, FALSECONSTANT, TRUECOMSTANT], [chatbot, history], show_progress=True)
322
  saveBtn.click(save_chat_history, [
323
  saveFileName, systemPromptTxt, history, chatbot], None, show_progress=True)
324
  saveBtn.click(get_history_names, None, [historyFileSelectDropdown])
@@ -343,3 +400,4 @@ else:
343
  demo.queue().launch(share=False) # 改为 share=True 可以创建公开分享链接
344
  #demo.queue().launch(server_name="0.0.0.0", server_port=7860, share=False) # 可自定义端口
345
  #demo.queue().launch(server_name="0.0.0.0", server_port=7860,auth=("在这��填写用户名", "在这里填写密码")) # 可设置用户名与密码
 
 
48
  count += 1
49
  items = line.split('`')
50
  if count % 2 == 1:
51
+ lines[i] = f'<pre><code class="{items[-1]}">'
52
  firstline = True
53
  else:
54
  lines[i] = f'</code></pre>'
55
  else:
56
  if i > 0:
57
  if count % 2 == 1:
58
+ line = line.replace("`", "\`")
59
  line = line.replace("\"", "`\"`")
60
  line = line.replace("\'", "`\'`")
61
+ # line = line.replace("&", "&amp;")
62
  line = line.replace("<", "&lt;")
63
  line = line.replace(">", "&gt;")
64
  line = line.replace(" ", "&nbsp;")
65
  line = line.replace("*", "&ast;")
66
  line = line.replace("_", "&lowbar;")
 
67
  line = line.replace("-", "&#45;")
68
  line = line.replace(".", "&#46;")
69
  line = line.replace("!", "&#33;")
70
  line = line.replace("(", "&#40;")
71
  line = line.replace(")", "&#41;")
72
+ line = line.replace("$", "&#36;")
73
  lines[i] = "<br>"+line
74
  text = "".join(lines)
75
  return text
76
 
77
+ def predict(inputs, top_p, temperature, openai_api_key, chatbot=[], history=[], system_prompt=initial_prompt, retry=False, summary=False, summary_on_crash = False, stream = True): # repetition_penalty, top_k
78
 
79
+ if summary:
80
+ stream = False
81
 
82
  headers = {
83
  "Content-Type": "application/json",
 
90
 
91
  messages = [compose_system(system_prompt)]
92
  if chat_counter:
93
+ for index in range(0, 2*chat_counter, 2):
94
  temp1 = {}
95
  temp1["role"] = "user"
96
+ temp1["content"] = history[index]
97
  temp2 = {}
98
  temp2["role"] = "assistant"
99
+ temp2["content"] = history[index+1]
100
  if temp1["content"] != "":
101
+ if temp2["content"] != "" or retry:
102
+ messages.append(temp1)
103
+ messages.append(temp2)
104
  else:
105
  messages[-1]['content'] = temp2['content']
106
  if retry and chat_counter:
107
  messages.pop()
108
  elif summary:
109
+ history = [*[i["content"] for i in messages[-2:]], "我们刚刚聊了什么?"]
110
  messages.append(compose_user(
111
  "请帮我总结一下上述对话的内容,实现减少字数的同时,保证对话的质量。在总结中不要加入这一句话。"))
 
112
  else:
113
  temp3 = {}
114
  temp3["role"] = "user"
 
122
  "temperature": temperature, # 1.0,
123
  "top_p": top_p, # 1.0,
124
  "n": 1,
125
+ "stream": stream,
126
  "presence_penalty": 0,
127
  "frequency_penalty": 0,
128
  }
129
 
130
  if not summary:
131
  history.append(inputs)
132
+ else:
133
+ print("精简中...")
134
  # make a POST request to the API endpoint using the requests.post method, passing in stream=True
135
  response = requests.post(API_URL, headers=headers,
136
  json=payload, stream=True)
 
137
 
138
  token_counter = 0
139
  partial_words = ""
140
 
141
  counter = 0
142
+ if stream:
143
+ chatbot.append((parse_text(history[-1]), ""))
144
+ for chunk in response.iter_lines():
145
+ if counter == 0:
146
+ counter += 1
147
+ continue
148
  counter += 1
149
+ # check whether each line is non-empty
150
+ if chunk:
151
+ # decode each line as response data is in bytes
152
+ try:
153
+ if len(json.loads(chunk.decode()[6:])['choices'][0]["delta"]) == 0:
154
+ break
155
+ except Exception as e:
156
+ traceback.print_exc()
157
+ print("Context 过长,正在尝试精简……")
158
+ chatbot.pop()
159
+ chatbot, history, status_text = next(predict(inputs, top_p, temperature, openai_api_key, chatbot, history, system_prompt, retry, summary=True, summary_on_crash=True, stream=False))
160
+ yield chatbot, history, status_text
161
+ if not "ERROR" in status_text:
162
+ print("精简完成,正在尝试重新生成……")
163
+ yield next(predict(inputs, top_p, temperature, openai_api_key, chatbot, history, system_prompt, retry, summary=False, summary_on_crash=True, stream=False))
164
+ else:
165
+ print("精简出错了,可能是网络原因。")
166
  break
167
+ chunkjson = json.loads(chunk.decode()[6:])
168
+ status_text = f"id: {chunkjson['id']}, finish_reason: {chunkjson['choices'][0]['finish_reason']}"
169
+ partial_words = partial_words + \
170
+ json.loads(chunk.decode()[6:])[
171
+ 'choices'][0]["delta"]["content"]
172
+ if token_counter == 0:
173
+ history.append(" " + partial_words)
174
+ else:
175
+ history[-1] = partial_words
176
+ chatbot[-1] = (parse_text(history[-2]), parse_text(history[-1]))
177
+ token_counter += 1
178
+ yield chatbot, history, status_text
179
+ else:
180
+ try:
181
+ responsejson = json.loads(response.text)
182
+ content = responsejson["choices"][0]["message"]["content"]
183
+ history.append(content)
184
+ chatbot.append((parse_text(history[-2]), parse_text(content)))
185
+ status_text = "精简完成"
186
+ except:
187
+ chatbot.append((parse_text(history[-1]), "☹️发生了错误,请检查网络连接或者稍后再试。"))
188
+ status_text = "status: ERROR"
189
+ yield chatbot, history, status_text
190
 
191
 
192
 
193
  def delete_last_conversation(chatbot, history):
194
+ if "☹️发生了错误" in chatbot[-1][1]:
195
+ chatbot.pop()
196
+ print(history)
197
+ return chatbot, history
198
  history.pop()
199
  history.pop()
200
+ print(history)
201
  return chatbot, history
202
 
203
  def save_chat_history(filename, system, history, chatbot):
 
207
  filename += ".json"
208
  os.makedirs(HISTORY_DIR, exist_ok=True)
209
  json_s = {"system": system, "history": history, "chatbot": chatbot}
210
+ print(json_s)
211
  with open(os.path.join(HISTORY_DIR, filename), "w") as f:
212
  json.dump(json_s, f)
213
 
 
215
  def load_chat_history(filename):
216
  with open(os.path.join(HISTORY_DIR, filename), "r") as f:
217
  json_s = json.load(f)
218
+ print(json_s)
219
  return filename, json_s["system"], json_s["history"], json_s["chatbot"]
220
 
221
 
222
  def get_file_names(dir, plain=False, filetype=".json"):
223
  # find all json files in the current directory and return their names
224
  try:
225
+ files = sorted([f for f in os.listdir(dir) if f.endswith(filetype)])
226
  except FileNotFoundError:
227
  files = []
228
  if plain:
 
233
  def get_history_names(plain=False):
234
  return get_file_names(HISTORY_DIR, plain)
235
 
236
+ def load_template(filename, plain=False):
237
  lines = []
238
  with open(os.path.join(TEMPLATES_DIR, filename), "r", encoding="utf8") as csvfile:
239
  reader = csv.reader(csvfile)
240
  lines = list(reader)
241
  lines = lines[1:]
242
+ if plain:
243
+ return sorted([row[0] for row in lines])
244
+ else:
245
+ return {row[0]:row[1] for row in lines}, gr.Dropdown.update(choices=sorted([row[0] for row in lines]))
246
 
247
  def get_template_names(plain=False):
248
  return get_file_names(TEMPLATES_DIR, plain, filetype=".csv")
 
265
  title = """<h1 align="center">川虎ChatGPT 🚀</h1>"""
266
  description = """<div align=center>
267
 
268
+ 由Bilibili [土川虎虎虎](https://space.bilibili.com/29125536) 和 [明昭MZhao](https://space.bilibili.com/24807452)开发
269
 
270
  访问川虎ChatGPT的 [GitHub项目](https://github.com/GaiZhenbiao/ChuanhuChatGPT) 下载最新版脚本
271
 
272
  此App使用 `gpt-3.5-turbo` 大语言模型
273
  </div>
274
  """
275
+ customCSS = """
276
+ code {
277
+ display: inline;
278
+ white-space: break-spaces;
279
+ border-radius: 6px;
280
+ margin: 0 2px 0 2px;
281
+ padding: .2em .4em .1em .4em;
282
+ background-color: rgba(175,184,193,0.2);
283
+ }
284
+ pre {
285
+ display: block;
286
+ white-space: pre;
287
+ background-color: hsla(0, 0%, 0%, 72%);
288
+ border: solid 5px var(--color-border-primary) !important;
289
+ border-radius: 8px;
290
+ padding: 0 1.2rem 1.2rem;
291
+ margin-top: 1em !important;
292
+ color: #FFF;
293
+ box-shadow: inset 0px 8px 16px hsla(0, 0%, 0%, .2)
294
+ }
295
+ pre code, pre code code {
296
+ background-color: transparent !important;
297
+ margin: 0;
298
+ padding: 0;
299
+ }
300
+ """
301
+
302
+ with gr.Blocks(css=customCSS) as demo:
303
  gr.HTML(title)
304
  gr.HTML('''<center><a href="https://huggingface.co/spaces/JohnSmith9982/ChuanhuChatGPT?duplicate=true"><img src="https://bit.ly/3gLdBN6" alt="复制 Space"></a>强烈建议点击上面的按钮复制一份这个Space,在你自己的Space里运行,响应更迅速、也更安全👆</center>''')
305
  keyTxt = gr.Textbox(show_label=True, placeholder=f"在这里输入你的OpenAI API-key...",
 
322
  retryBtn = gr.Button("🔄 重新生成")
323
  delLastBtn = gr.Button("🗑️ 删除上条对话")
324
  reduceTokenBtn = gr.Button("♻️ 总结对话")
325
+ statusDisplay = gr.Markdown("status: ready")
326
  systemPromptTxt = gr.Textbox(show_label=True, placeholder=f"在这里输入System Prompt...",
327
  label="System prompt", value=initial_prompt).style(container=True)
328
  with gr.Accordion(label="加载Prompt模板", open=False):
 
335
  templaeFileReadBtn = gr.Button("📂 读入模板")
336
  with gr.Row():
337
  with gr.Column(scale=6):
338
+ templateSelectDropdown = gr.Dropdown(label="从Prompt模板中加载", choices=load_template(get_template_names(plain=True)[0], plain=True), multiselect=False)
339
  with gr.Column(scale=1):
340
  templateApplyBtn = gr.Button("⬇️ 应用")
341
  with gr.Accordion(label="保存/加载对话历史记录(在文本框中输入文件名,点击“保存对话”按钮,历史记录文件会被存储到Python文件旁边)", open=False):
 
364
 
365
 
366
  txt.submit(predict, [txt, top_p, temperature, keyTxt,
367
+ chatbot, history, systemPromptTxt], [chatbot, history, statusDisplay])
368
  txt.submit(reset_textbox, [], [txt])
369
  submitBtn.click(predict, [txt, top_p, temperature, keyTxt, chatbot,
370
+ history, systemPromptTxt], [chatbot, history, statusDisplay], show_progress=True)
371
  submitBtn.click(reset_textbox, [], [txt])
372
  emptyBtn.click(reset_state, outputs=[chatbot, history])
373
  retryBtn.click(predict, [txt, top_p, temperature, keyTxt, chatbot, history,
374
+ systemPromptTxt, TRUECOMSTANT], [chatbot, history, statusDisplay], show_progress=True)
375
  delLastBtn.click(delete_last_conversation, [chatbot, history], [
376
  chatbot, history], show_progress=True)
377
  reduceTokenBtn.click(predict, [txt, top_p, temperature, keyTxt, chatbot, history,
378
+ systemPromptTxt, FALSECONSTANT, TRUECOMSTANT], [chatbot, history, statusDisplay], show_progress=True)
379
  saveBtn.click(save_chat_history, [
380
  saveFileName, systemPromptTxt, history, chatbot], None, show_progress=True)
381
  saveBtn.click(get_history_names, None, [historyFileSelectDropdown])
 
400
  demo.queue().launch(share=False) # 改为 share=True 可以创建公开分享链接
401
  #demo.queue().launch(server_name="0.0.0.0", server_port=7860, share=False) # 可自定义端口
402
  #demo.queue().launch(server_name="0.0.0.0", server_port=7860,auth=("在这��填写用户名", "在这里填写密码")) # 可设置用户名与密码
403
+ #demo.queue().launch(auth=("在这里填写用户名", "在这里填写密码")) # 适合Nginx反向代理