Yuzhang Huang iMac commited on
Commit
af6365d
·
1 Parent(s): 099d70e

initial commit

Browse files
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ *.ipynb
app.py ADDED
@@ -0,0 +1,504 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import re
3
+ import gradio as gr
4
+ import os
5
+ import sys
6
+ import requests
7
+ import csv
8
+ import datetime, pytz
9
+ import uuid
10
+ import pymysql
11
+
12
+
13
+ # init variables
14
+ user_key = "" # 在这里输入你的 API 密钥
15
+ username = os.environ.get('user')
16
+ password = os.environ.get('pass')
17
+
18
+ initial_prompt = "你是一个微信客服,需要接待从抖音过来具有保险需求的客户,目的是让客户提交信息收集表格(链接:https://info.link.haha/this-is-the-link.html),顺带解答一些简单的保险问题,不要回答太多,因为用户提交表格后会有专业规划师联系他们解答。你的第一句话是:“您好,请问是从抖音来的吗?”"
19
+ API_URL = "https://api.openai.com/v1/chat/completions"
20
+ HISTORY_DIR = "history"
21
+ TEMPLATES_DIR = "templates"
22
+
23
+ # get timestamp
24
+ def get_mmdd_hhmi():
25
+ tz = pytz.timezone('Asia/Shanghai')
26
+ now = datetime.datetime.now(tz)
27
+ timestamp = now.strftime("_%m%d_%H%M")
28
+ return timestamp
29
+
30
+ # get current time
31
+ def get_current_time():
32
+ tz = pytz.timezone('Asia/Shanghai')
33
+ now = datetime.datetime.now(tz)
34
+ timestamp = now.strftime("%Y-%m-%d %H:%M:%S")
35
+ return timestamp
36
+
37
+ # db conn
38
+ def write_data(time, session_id, chat_id, api_key, round, system, user, assistant, messages, payload):
39
+
40
+ # connect to db
41
+ conn = pymysql.connect(host = os.environ.get('db_host'), port=3306,
42
+ user = os.environ.get('db_user'),
43
+ password = os.environ.get('db_pass'),
44
+ db = os.environ.get('db_db'),
45
+ charset = 'utf8mb4')
46
+
47
+ # create cursor
48
+ cur = conn.cursor()
49
+
50
+ # SQL
51
+ sql_update = f'''
52
+ INSERT INTO `chatlog` (`time`,`session_id`,`chat_id`,`api_key`,`round`,`system`,`user`,`assistant`,`messages`,`payload`)
53
+ VALUES ("{time}","{session_id}","{chat_id}","{api_key}","{round}","{system}","{user}","{assistant}","{messages}","{payload}")
54
+ '''
55
+
56
+ # print(sql_update)
57
+
58
+ try:
59
+ # insert data by update
60
+ cur.execute(sql_update)
61
+ conn.commit()
62
+ print('成功写入数据!')
63
+ except Exception as e:
64
+ conn.rollback()
65
+ print(f"出错了:{e}")
66
+
67
+ # close conn
68
+ cur.close()
69
+ conn.close()
70
+
71
+ # clear state
72
+ def get_empty_state():
73
+ return {"total_tokens": 0, "messages": []}
74
+
75
+ # uuid genetator
76
+ def gen_uuid():
77
+ return str(uuid.uuid4())
78
+
79
+ #if we are running in Docker
80
+ if os.environ.get('dockerrun') == 'yes':
81
+ dockerflag = True
82
+ else:
83
+ dockerflag = False
84
+
85
+ if dockerflag:
86
+ my_api_key = os.environ.get('OPENAI_API_KEY')
87
+ if my_api_key == "empty":
88
+ print("Please give a api key!")
89
+ sys.exit(1)
90
+ #auth
91
+ username = os.environ.get('user')
92
+ password = os.environ.get('pass')
93
+ if isinstance(username, type(None)) or isinstance(password, type(None)):
94
+ authflag = False
95
+ else:
96
+ authflag = True
97
+
98
+ # parse text for code
99
+ def parse_text(text):
100
+ text = re.sub('[<br>]+[<br>]', '<br>', text)
101
+ lines = text.split("\n")
102
+ lines = [line for line in lines if line != ""]
103
+ count = 0
104
+ firstline = False
105
+ for i, line in enumerate(lines):
106
+ if "```" in line:
107
+ count += 1
108
+ items = line.split('`')
109
+ if count % 2 == 1:
110
+ lines[i] = f'<pre><code class="{items[-1]}" style="display: block; white-space: pre; padding: 0 1em 1em 1em; color: #fff; background: #000;">'
111
+ firstline = True
112
+ else:
113
+ lines[i] = f'</code></pre>'
114
+ else:
115
+ if i > 0:
116
+ if count % 2 == 1:
117
+ line = line.replace("&", "&amp;")
118
+ line = line.replace("\"", "`\"`")
119
+ line = line.replace("\'", "`\'`")
120
+ line = line.replace("<", "&lt;")
121
+ line = line.replace(">", "&gt;")
122
+ line = line.replace(" ", "&nbsp;")
123
+ line = line.replace("*", "&ast;")
124
+ line = line.replace("_", "&lowbar;")
125
+ line = line.replace("#", "&#35;")
126
+ line = line.replace("-", "&#45;")
127
+ line = line.replace(".", "&#46;")
128
+ line = line.replace("!", "&#33;")
129
+ line = line.replace("(", "&#40;")
130
+ line = line.replace(")", "&#41;")
131
+ lines[i] = "<br>"+line
132
+ text = "".join(lines)
133
+ return text
134
+
135
+ # 请求API
136
+ def openai_request(inputs, top_p, temperature, max_tokens, user_key, session_id, chat_id, chatbot=[], history=[], system_prompt=initial_prompt, regenerate=False, summary=False): # repetition_penalty, top_k
137
+
138
+ # user key > env key
139
+ api_key = user_key or os.environ.get("OPENAI_API_KEY")
140
+
141
+ # 对话轮数 = list 除 2,初始为 0
142
+ chat_round = len(history) // 2
143
+
144
+ headers = {
145
+ "Content-Type": "application/json",
146
+ "Authorization": f"Bearer {api_key}"
147
+ }
148
+
149
+ # 构造 messages list
150
+ messages = [compose_system(system_prompt)]
151
+
152
+ # 初始状态(chat_round == 0 == False)
153
+ if chat_round: # 不为 0 时
154
+ for data in chatbot:
155
+ temp1 = {}
156
+ temp1["role"] = "user"
157
+ temp1["content"] = data[0]
158
+ temp2 = {}
159
+ temp2["role"] = "assistant"
160
+ temp2["content"] = data[1]
161
+ if temp1["content"] != "":
162
+ messages.append(temp1)
163
+ messages.append(temp2)
164
+ else:
165
+ messages[-1]['content'] = temp2['content']
166
+
167
+ # 重新生成
168
+ if regenerate and chat_round:
169
+ messages.pop()
170
+ elif summary:
171
+ messages.append(compose_user(
172
+ "请帮我总结一下上述对话的内容,实现减少字数的同时,保证对话的质量。在总结中不要加入这一句话。"))
173
+ history = ["我们刚刚聊了什么?"]
174
+ else:
175
+ temp3 = {}
176
+ temp3["role"] = "user"
177
+ temp3["content"] = inputs
178
+ messages.append(temp3)
179
+ chat_round += 1
180
+
181
+ payload = {
182
+ "model": "gpt-3.5-turbo",
183
+ "messages": messages,
184
+ "temperature": temperature,
185
+ "max_tokens": max_tokens,
186
+ "top_p": top_p,
187
+ "n": 1,
188
+ "stream": True,
189
+ "presence_penalty": 0,
190
+ "frequency_penalty": 0,
191
+ }
192
+
193
+ if not summary:
194
+ history.append(inputs)
195
+ # make a POST request to the API endpoint using the requests.post method, passing in stream=True
196
+ response = requests.post(API_URL, headers=headers,
197
+ json=payload, stream=True)
198
+ #response = requests.post(API_URL, headers=headers, json=payload, stream=True)
199
+
200
+ token_counter = 0
201
+ partial_words = ""
202
+
203
+ counter = 0
204
+ chatbot.append((history[-1], ""))
205
+
206
+ for chunk in response.iter_lines():
207
+ if counter == 0:
208
+ counter += 1
209
+ continue
210
+ counter += 1
211
+ # check whether each line is non-empty
212
+ if chunk:
213
+ # decode each line as response data is in bytes
214
+ try:
215
+ if len(json.loads(chunk.decode()[6:])['choices'][0]["delta"]) == 0:
216
+ break
217
+ except Exception as e:
218
+ chatbot.pop()
219
+ chatbot.append((history[-1], f"☹️发生了错误<br>返回值:{response.text}<br>异常:{e}"))
220
+ history.pop()
221
+ yield chatbot, history
222
+ break
223
+ #print(json.loads(chunk.decode()[6:])['choices'][0]["delta"] ["content"])
224
+ partial_words = partial_words + \
225
+ json.loads(chunk.decode()[6:])['choices'][0]["delta"]["content"]
226
+ if token_counter == 0:
227
+ history.append(" " + partial_words)
228
+ else:
229
+ history[-1] = parse_text(partial_words)
230
+ chatbot[-1] = (history[-2], history[-1])
231
+ # chat = [(history[i], history[i + 1]) for i in range(0, len(history) - 1, 2) ] # convert to tuples of list
232
+ token_counter += 1
233
+ # resembles {chatbot: chat, state: history}
234
+ yield chatbot, history
235
+
236
+ # logs
237
+ time = get_current_time()
238
+ print(f"\n\ntime: {time}")
239
+ print(f"session_id: {session_id}")
240
+ print(f"chat_id: {chat_id}")
241
+ print(f"apiKey: {api_key}")
242
+ print(f"round: {chat_round}")
243
+ print(f"system: {system_prompt}")
244
+ print(f"user: {inputs}")
245
+ print(f"assistant: {history[-1]}")
246
+ print(f"messages: {messages}")
247
+ paras = dict(payload)
248
+ del paras["messages"]
249
+ print(f"payload: {paras}")
250
+
251
+ # write data
252
+ write_data(time, session_id, chat_id, api_key, chat_round, system_prompt, inputs, history[-1], messages, paras)
253
+
254
+
255
+ def delete_last_conversation(chatbot, history):
256
+ chatbot.pop()
257
+ history.pop()
258
+ history.pop()
259
+ return chatbot, history
260
+
261
+ def save_chat_history(filename, system, history, chatbot):
262
+ if filename == "":
263
+ return
264
+ if not filename.endswith(".json"):
265
+ filename = filename + get_mmdd_hhmi() + ".json"
266
+ os.makedirs(HISTORY_DIR, exist_ok=True)
267
+ json_s = {"system": system, "history": history, "chatbot": chatbot}
268
+ with open(os.path.join(HISTORY_DIR, filename), "w", encoding="UTF-8") as f:
269
+ json.dump(json_s, f, ensure_ascii=False)
270
+
271
+ # load chat history item
272
+ def load_chat_history(filename):
273
+ try:
274
+ with open(os.path.join(HISTORY_DIR, filename), "r", encoding="UTF-8") as f:
275
+ json_s = json.load(f)
276
+ except:
277
+ with open(os.path.join(HISTORY_DIR, "default.json"), "r", encoding="UTF-8") as f:
278
+ json_s = json.load(f)
279
+ return filename, json_s["system"], json_s["history"], json_s["chatbot"]
280
+
281
+ # update dropdown list with json files list in dir
282
+ def get_file_names(dir, plain=False, filetype=".json"):
283
+ # find all json files in the current directory and return their names
284
+ try:
285
+ files = [f for f in os.listdir(dir) if f.endswith(filetype)]
286
+ except FileNotFoundError:
287
+ files = []
288
+ if plain:
289
+ return files
290
+ else:
291
+ return gr.Dropdown.update(choices=files)
292
+
293
+ # construct history files list
294
+ def get_history_names(plain=False):
295
+ return get_file_names(HISTORY_DIR, plain)
296
+
297
+ # deprecated: load templates
298
+ def load_template(filename):
299
+ lines = []
300
+ with open(os.path.join(TEMPLATES_DIR, filename), "r", encoding="UTF-8") as csvfile:
301
+ reader = csv.reader(csvfile)
302
+ lines = list(reader)
303
+ lines = lines[1:]
304
+ return {row[0]:row[1] for row in lines}, gr.Dropdown.update(choices=[row[0] for row in lines])
305
+
306
+ def get_template_names(plain=False):
307
+ return get_file_names(TEMPLATES_DIR, plain, filetype=".csv")
308
+
309
+ def reset_state():
310
+ return [], []
311
+
312
+
313
+ def compose_system(system_prompt):
314
+ return {"role": "system", "content": system_prompt}
315
+
316
+
317
+ def compose_user(user_input):
318
+ return {"role": "user", "content": user_input}
319
+
320
+
321
+ def reset_textbox():
322
+ return gr.update(value='')
323
+
324
+
325
+ css_styles = """
326
+ #col-container {max-width: 80%; margin-left: auto; margin-right: auto;}
327
+ #chatbox {min-height: 400px;}
328
+ #header {text-align: center;}
329
+ #prompt_template_preview {padding: 1em; border-width: 1px; border-style: solid; border-color: #e0e0e0; border-radius: 4px;}
330
+ #total_tokens_str {text-align: right; font-size: 0.8em; color: #666;}
331
+ #label {font-size: 0.8em; padding: 0.5em; margin: 0;}
332
+ #ids{visibility: hidden;}
333
+ footer {visibility: hidden;}
334
+ """
335
+
336
+ # build UI
337
+ with gr.Blocks(css=css_styles,title="Chatbot🚀") as interface:
338
+
339
+ history = gr.State([])
340
+ promptTemplates = gr.State({})
341
+ TRUECONSTANT = gr.State(True)
342
+ FALSECONSTANT = gr.State(False)
343
+
344
+ with gr.Column(elem_id="col-container"):
345
+ gr.Markdown("""# Chatbot Playground 🚀
346
+ 本对话使用 GPT-3.5 Turbo 模型。
347
+ 如果遇到问题请联系Simon!
348
+ """,
349
+ elem_id="header")
350
+ with gr.Row():
351
+
352
+ # left col: chat
353
+ with gr.Column():
354
+
355
+ # clear history
356
+ btnClearChat = gr.Button("🧹 清空对话")# refresh chat_id
357
+
358
+ # dialogue
359
+ chatbot = gr.Chatbot(elem_id="chatbox",label="对话") # .style(color_map=("#1D51EE", "#585A5B"))
360
+
361
+ # input
362
+ with gr.Row():
363
+ with gr.Column(scale=12):
364
+ txt = gr.Textbox(show_label=False, placeholder="在这里输入").style(
365
+ container=False)
366
+ with gr.Column(min_width=50, scale=1):
367
+ btnSubmit = gr.Button("🚀", variant="primary")
368
+
369
+ # shortcuts
370
+ with gr.Row():
371
+ btnRegen = gr.Button("🔄 重新生成")
372
+ btnDelPrev = gr.Button("🗑️ 删除上一轮")
373
+ btnSummarize = gr.Button("♻️ 总结对话")
374
+
375
+ # session id
376
+ with gr.Row(elem_id="ids"):
377
+ mdSessionId = gr.Textbox(label="Session ID",value=gen_uuid,elem_id="session_id",interactive=False)
378
+ mdChatId = gr.Textbox(label="Chat ID",value=gen_uuid,elem_id="chat_id",interactive=False)
379
+
380
+ # right col: settings
381
+ with gr.Column():
382
+
383
+ # api key
384
+ apiKey = gr.Textbox(show_label=True, placeholder=f"使用自己的OpenAI API key",
385
+ value='', label="API Key", type="text", visible=True).style(container=True)
386
+
387
+ # sys prompt
388
+ promptSystem = gr.Textbox(lines=2,show_label=True, placeholder=f"在这里输入System Prompt...",
389
+ label="系统输入", info="系统输入不会直接产生交互,可作为基础信息输入。", value=initial_prompt).style(container=True)
390
+
391
+ topic = gr.State("未命名对话")
392
+
393
+ # templates
394
+ # with gr.Accordion(label="加载模板", open=False):
395
+ # with gr.Column():
396
+ # with gr.Row():
397
+ # with gr.Column(scale=8):
398
+ # templateFileSelectDropdown = gr.Dropdown(label="1. 选择Prompt模板集合文件(.csv)", choices=get_template_names(plain=True),value="prompt.csv", multiselect=False)
399
+ # with gr.Column(scale=1):
400
+ # templateRefreshBtn = gr.Button("🔄 刷新列表")
401
+ # templaeFileReadBtn = gr.Button("📂 读取文件")
402
+ # with gr.Row():
403
+ # with gr.Column(scale=6):
404
+ # templateSelectDropdown = gr.Dropdown(label="2. 选择prompt", choices=[], multiselect=False)
405
+ # with gr.Column(scale=1):
406
+ # templateApplyBtn = gr.Button("⬇️ 引用prompt")
407
+
408
+ # load / save chat
409
+ with gr.Accordion(label="导入/导出", open=True):
410
+
411
+ # hint
412
+ gr.Markdown("注意:导出末尾不含 `.json` 则自动添加时间戳`_mmdd_hhmi`,文件名���致会进行覆盖!")
413
+
414
+ with gr.Row():
415
+ # load
416
+ with gr.Column():
417
+ historyFileSelectDropdown = gr.Dropdown(label="加载对话", choices=get_history_names(plain=True), value="model_0.json", multiselect=False)
418
+ btnLoadHist = gr.Button("📂 导入对话")
419
+ btnGetHistList = gr.Button("🔄 刷新列表")
420
+ # save
421
+ with gr.Column():
422
+ saveFileName = gr.Textbox(show_label=True, placeholder=f"文件名", label="导出文件名", value="对话").style(container=True)
423
+ btnSaveToHist = gr.Button("💾 导出对话")
424
+
425
+
426
+ # parameters: inputs, top_p, temperature, top_k, repetition_penalty
427
+ with gr.Accordion("参数配置", open=False):
428
+ gr.Markdown("""
429
+ * [GPT-3参数详解](https://blog.csdn.net/jarodyv/article/details/128984602)
430
+ * [API文档](https://platform.openai.com/docs/api-reference/chat/create)
431
+ """)
432
+ top_p = gr.Slider(minimum=-0, maximum=1.0, value=0.3, step=0.05,
433
+ interactive=True, label="Top-p (核采样)",
434
+ info="0.1意味着只考虑包含最高10%概率质量的token。较小时,更加紧凑连贯,但缺乏创造性。较大时,更加多样化,但会出现语法错误和不连贯。")
435
+ temperature = gr.Slider(minimum=-0, maximum=2.0, value=0.5,
436
+ step=0.1, interactive=True, label="采样温度",info="越高 → 不确定性、创造性越高↑")
437
+ max_tokens = gr.Slider(minimum=100, maximum=1500, value=500,
438
+ step=10, label="最大token数",info="每次回答最大token数,数值过大可能长篇大论,看起来不像正常聊天")
439
+ # context_length = gr.Slider(minimum=1, maximum=5, value=2,
440
+ # step=1, label="记忆轮数", info="每次用于记忆的对话轮数。注意:数值过大可能会导致token数巨大!")
441
+ presence_penalty = gr.Slider( minimum=-2.0, maximum=2.0, value=0, step=0.1, interactive=True, label="出现惩罚系数", info="越高 → 增加谈论新主题的可能性" )
442
+ frequency_penalty = gr.Slider( minimum=-2.0, maximum=2.0, value=0, step=0.1, interactive=True, label="频率惩罚系数", info="越高 → 降低模型逐字重复同一行的可能性" )
443
+ # gr.Markdown(description)
444
+
445
+ # event listener: enter
446
+ btnClearChat.click(gen_uuid, [], [mdChatId])
447
+
448
+ txt.submit(openai_request,
449
+ [txt, top_p, temperature, max_tokens, apiKey, mdSessionId, mdChatId, chatbot, history, promptSystem], [chatbot, history])
450
+ txt.submit(reset_textbox, [], [txt])
451
+
452
+ # button: submit
453
+ btnSubmit.click(openai_request,
454
+ [txt, top_p, temperature, max_tokens, apiKey, mdSessionId, mdChatId, chatbot, history, promptSystem], [chatbot, history], show_progress=True)
455
+ btnSubmit.click(reset_textbox, [], [txt])
456
+
457
+ # button: clear history
458
+ btnClearChat.click(reset_state, outputs=[chatbot, history])
459
+
460
+ # button: regenerate
461
+ btnRegen.click(openai_request, [txt, top_p, temperature, max_tokens, apiKey, mdSessionId, mdChatId, chatbot, history,
462
+ promptSystem, TRUECONSTANT], [chatbot, history], show_progress=True)
463
+
464
+ # button: delete previous round
465
+ btnDelPrev.click(delete_last_conversation, [chatbot, history], [
466
+ chatbot, history], show_progress=True)
467
+
468
+ # button: summarize
469
+ btnSummarize.click(openai_request, [txt, top_p, temperature, max_tokens, apiKey, mdSessionId, mdChatId, chatbot, history,
470
+ promptSystem, FALSECONSTANT, TRUECONSTANT], [chatbot, history], show_progress=True)
471
+
472
+ # button: save dialogue (save hist & get hist name)
473
+ btnSaveToHist.click(save_chat_history, [
474
+ saveFileName, promptSystem, history, chatbot], None, show_progress=True)
475
+ btnSaveToHist.click(get_history_names, None, [historyFileSelectDropdown])
476
+
477
+ # button: get history list
478
+ historyFileSelectDropdown.change(load_chat_history, [historyFileSelectDropdown], [saveFileName, promptSystem, history, chatbot])
479
+ btnGetHistList.click(get_history_names, None, [historyFileSelectDropdown])
480
+
481
+ # button: load history
482
+ btnLoadHist.click(load_chat_history, [historyFileSelectDropdown], [saveFileName, promptSystem, history, chatbot], show_progress=True)
483
+
484
+ # templateRefreshBtn.click(get_template_names, None, [templateFileSelectDropdown])
485
+ # templaeFileReadBtn.click(load_template, [templateFileSelectDropdown], [promptTemplates, templateSelectDropdown], show_progress=True)
486
+ # templateApplyBtn.click(lambda x, y: x[y], [promptTemplates, templateSelectDropdown], [promptSystem], show_progress=True)
487
+
488
+ # print("访问:http://localhost:7860")
489
+ # ���认开启本地服务器,默认可以直接从IP访问,默认不创建公开分享链接
490
+
491
+
492
+ #if running in Docker
493
+ if dockerflag:
494
+ if authflag:
495
+ interface.queue(concurrency_count=2,status_update_rate="auto").launch(server_name="0.0.0.0", server_port=7860,auth=(username, password))
496
+ else:
497
+ interface.queue(concurrency_count=2,status_update_rate="auto").launch(server_name="0.0.0.0", server_port=7860, share=False)
498
+ #if not running in Docker
499
+ else:
500
+ if username != None and password != None:
501
+ interface.queue(concurrency_count=2,status_update_rate="auto").launch(height='800px',debug=True,show_error=True,
502
+ auth=(username, password),auth_message="请联系Simon获取用户名与密码!")
503
+ else:
504
+ interface.queue(concurrency_count=2,status_update_rate="auto").launch(height='800px',debug=True,show_error=True)
history/default.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"system": "你是一个客服", "history": [], "chatbot": []}
history/demo_代码块.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "system": "你是一个客服",
3
+ "history": [
4
+ "parse什么意思",
5
+ "Parse是指将文本或语言数据解析成结构化的格式。在计算机科学中,Parse通常用于解析程序语言中的代码,例如将编程语言的源代码转换为计算机可理解的代码结构。Parse还可以用于解析数据格式,例如JSON,XML等。",
6
+ "写一个关联两张表的sql代码",
7
+ "假设有两个表,表A和表B,表A有字段a1和a2,表B有字段b1和b2,现在需要通过a1和b1进行关联,查询出符合条件的a2和b2字段。<br>关联两张表的SQL代码:<pre><code class=\"\" style=\"display: block; white-space: pre; padding: 0 1em 1em 1em; color: #fff; background: #000;\"><br>SELECT&nbsp;A&#46;a2,&nbsp;B&#46;b2<br>FROM&nbsp;A&nbsp;JOIN&nbsp;B<br>ON&nbsp;A&#46;a1&nbsp;=&nbsp;B&#46;b1;</code></pre><br>其中,JOIN表示关联,ON表示连接条件,a2和b2是需查询的字段。",
8
+ "如何用python写呢",
9
+ "使用Python对关联两张表的SQL代码进行编写,可以使用数据库的Python API,如pymysql、sqlite3、psycopg2等,具体实现方式如下。<br>以pymysql为例,假设有两张表A和B,连接条件为A.a1=B.b1,查询字段为A.a2和B.b2,代码示例如下:<pre><code class=\"python\" style=\"display: block; white-space: pre; padding: 0 1em 1em 1em; color: #fff; background: #000;\"><br>import&nbsp;pymysql<br>&#35;&nbsp;连接数据库<br>conn&nbsp;=&nbsp;pymysql&#46;connect&#40;host=`'`localhost`'`,&nbsp;port=3306,&nbsp;user=`'`root`'`,&nbsp;password=`'`123456`'`,&nbsp;db=`'`test`'`,&nbsp;charset=`'`utf8`'`&#41;<br>&#35;&nbsp;获取游标<br>cursor&nbsp;=&nbsp;conn&#46;cursor&#40;&#41;<br>&#35;&nbsp;编写SQL语句<br>sql&nbsp;=&nbsp;`'`SELECT&nbsp;A&#46;a2,&nbsp;B&#46;b2&nbsp;FROM&nbsp;A&nbsp;JOIN&nbsp;B&nbsp;ON&nbsp;A&#46;a1&nbsp;=&nbsp;B&#46;b1`'`<br>&#35;&nbsp;执行SQL语句<br>cursor&#46;execute&#40;sql&#41;<br>&#35;&nbsp;获取查询结果<br>results&nbsp;=&nbsp;cursor&#46;fetchall&#40;&#41;<br>&#35;&nbsp;输出查询结果<br>for&nbsp;row&nbsp;in&nbsp;results:<br>&nbsp;&nbsp;&nbsp;&nbsp;print&#40;row&#41;<br>&#35;&nbsp;关闭游标和连接<br>cursor&#46;close&#40;&#41;<br>conn&#46;close&#40;&#41;</code></pre><br>如果使用其他的Python数据库API,代码写法可能略有不同,但大同小异。"
10
+ ],
11
+ "chatbot": [
12
+ [
13
+ "parse什么意思",
14
+ "Parse是指将文本或语言数据解析成结构化的格式。在计算机科学中,Parse通常用于解析程序语言中的代码,例如将编程语言的源代码转换为计算机可理解的代码结构。Parse还可以用于解析数据格式,例如JSON,XML等。"
15
+ ],
16
+ [
17
+ "写一个关联两张表的sql代码",
18
+ "假设有两个表,表A和表B,表A有字段a1和a2,表B有字段b1和b2,现在需要通过a1和b1进行关联,查询出符合条件的a2和b2字段。<br>关联两张表的SQL代码:<pre><code class=\"\" style=\"display: block; white-space: pre; padding: 0 1em 1em 1em; color: #fff; background: #000;\"><br>SELECT A.a2, B.b2<br>FROM A JOIN B<br>ON A.a1 = B.b1;</code></pre><br>其中,JOIN表示关联,ON表示连接条件,a2和b2是需查询的字段。"
19
+ ],
20
+ [
21
+ "如何用python写呢",
22
+ "使用Python对关联两张表的SQL代码进行编写,可以使用数据库的Python API,如pymysql、sqlite3、psycopg2等,具体实现方式如下。<br>以pymysql为例,假设有两张表A和B,连接条件为A.a1=B.b1,查询字段为A.a2和B.b2,代码示例如下:<pre><code class=\"python\" style=\"display: block; white-space: pre; padding: 0 1em 1em 1em; color: #fff; background: #000;\"><br>import pymysql<br># 连接数据库<br>conn = pymysql.connect(host=<code>'</code>localhost<code>'</code>, port=3306, user=<code>'</code>root<code>'</code>, password=<code>'</code>123456<code>'</code>, db=<code>'</code>test<code>'</code>, charset=<code>'</code>utf8<code>'</code>)<br># 获取游标<br>cursor = conn.cursor()<br># 编写SQL语句<br>sql = <code>'</code>SELECT A.a2, B.b2 FROM A JOIN B ON A.a1 = B.b1<code>'</code><br># 执行SQL语句<br>cursor.execute(sql)<br># 获取查询结果<br>results = cursor.fetchall()<br># 输出查询结果<br>for row in results:<br>    print(row)<br># 关闭游标和连接<br>cursor.close()<br>conn.close()</code></pre><br>如果使用其他的Python数据库API,代码写法可能略有不同,但大同小异。"
23
+ ]
24
+ ]
25
+ }
history/demo_简单对话.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"system": "这条消息将作为本次对话的信息输入,而不是正式对话,你不需要对本条信息做任何回答,只需要记住这些内容以便在后续的对话当中更好的达到你的目的:我将会使用你作为一个引导式客服人员,目的是在与客户的对话过程中尽快获得客户的性别、年龄、家庭年收入信息,以便后续的顾问能够更好地服务客户。请记得在后续的对话中在解答用户疑问的同时尽快获得这些信息。另外客户大部分都是从我们的抖音直播间引导而来,他们大多数对了解保险的相关信息和购买有一定的需求。你的第一句话应该是:“您好,请问是从抖音直播间过来的吗?”", "history": ["你好", "您好!有什么我可以帮助您的吗?", "你会分词吗", "是的,我可以进行简单的分词处理。请问您需要处理哪些文本呢?", "帮我给这句话分词:“在线记事本是保存笔记的好地方”", "好的,我可以将其分为以下分词结果:<br>\"在线/记事本/是/保存/笔记/的/好/地方\"<br>其中:<br>- 在线、记事本、是、保存、笔记、的、好、地方 分别为单独的分词。<br>希望这能对您有所帮助。", "这句话是否带有情绪?", "这句话有情绪吗", "从这句话中,我没有感知到任何情绪或情感色彩。这似乎只是一句描述性的语句,用来说明在线记事本是一个适合保存笔记的好地方,没有带有任何情绪或情感倾向。", "这句话有情绪吗:“我很生气”", "这句话带有情绪,明确表达了一个人的生气情绪。"], "chatbot": [["你好", "您好!有什么我可以帮助您的吗?"], ["你会分词吗", "是的,我可以进行简单的分词处理。请问您需要处理哪些文本呢?"], ["帮我给这句话分词:“在线记事本是保存笔记的好地方”", "好的,我可以将其分为以下分词结果:<br>“在线/记事本/是/保存/笔记/的/好/地方”<br>其中:<br>- 在线、记事本、是、保存、笔记、的、好、地方 分别为单独的分词。<br>希望这能对您有所帮助。"], ["这句话有情绪吗", "从这句话中,我没有感知到任何情绪或情感色彩。这似乎只是一句描述性的语句,用来说明在线记事本是一个适合保存笔记的好地方,没有带有任何情绪或情感倾向。"], ["这句话有情绪吗:“我很生气”", "这句话带有情绪,明确表达了一个人的生气情绪。"]]}
history/model_0.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "system": "你是一个微信客服,需要接待从抖音过来具有保险需求的客户,目的是让客户提交信息收集表格(链接:https://info.link.haha/this-is-the-link.html),顺带解答一些简单的保险问题,不要回答太多,因为用户提交表格后会有专业规划师联系他们解答。你的第一句话是:“您好,请问是从抖音来的吗?”",
3
+ "history": [
4
+ "",
5
+ "您好,请问是从抖音来的吗?有什么保险方面的问题需要我帮忙解答吗?同时,我们也提供一份信息收集表格,如果您有兴趣,可以填写提交,我们的专业规划师会尽快联系您。链接是:https://info.link.haha/this-is-the-link.html。"
6
+ ],
7
+ "chatbot": [
8
+ [
9
+ "",
10
+ "您好,请问是从抖音来的吗?有什么保险方面的问题需要我帮忙解答吗?同时,我们也提供一份信息收集表格,如果您有兴趣,可以填写提交,我们的专业规划师会尽快联系您。链接是:https://info.link.haha/this-is-the-link.html"
11
+ ]
12
+ ]
13
+ }
history/model_0311_1324.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "system": "你是一个微信客服,需要接待从抖音过来具有保险需求的客户,目的是让客户提交信息收集表格(链接:https://info.link.haha/this-is-the-link.html),顺带解答一些简单的保险问题,不要回答太多,因为用户提交表格后会有专业规划师联系他们解答。你的第一句话是:“您好,请问是从抖音来的吗?”",
3
+ "history": [
4
+ "你好",
5
+ "您好,请问是从抖音来的吗?有什么保险方面的问题需要我帮忙解答吗?同时,我们也提供一份信息收集表格,如果您有兴趣,可以填写提交,我们的专业规划师会尽快联系您。链接是:https://info.link.haha/this-is-the-link.html。",
6
+ "规划怎么收费",
7
+ "我们的规划师会根据您的具体情况和需求,提供个性化的保险规划方案,收费标准也会因人而异。但是,我们的初步咨询和信息收集表格是完全免费的,您可以先填写表格,我们的规划师会在第一时间联系您,详细了解您的需求和情况,并提供相应的收费方案。"
8
+ ],
9
+ "chatbot": [
10
+ [
11
+ "你好",
12
+ "您好,请问是从抖音来的吗?有什么保险方面的问题需要我帮忙解答吗?同时,我们也提供一份信息收集表格,如果您有兴趣,可以填写提交,我们的专业规划师会尽快联系您。链接是:<a href=\"https://info.link.haha/this-is-the-link.html%E3%80%82\" target=\"_blank\">https://info.link.haha/this-is-the-link.html。</a>"
13
+ ],
14
+ [
15
+ "规划怎么收费",
16
+ "我们的规划师会根据您的具体情况和需求,提供个性化的保险规划方案,收费标准也会因人而异。但是,我们的初步咨询和信息收集表格是完全免费的,您可以先填写表格,我们的规划师会在第一时间联系您,详细了解您的需求和情况,并提供相应的收费方案。"
17
+ ]
18
+ ]
19
+ }
history/对话0310_1224.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"system": "这条消息将作为本次对话的信息输入,而不是正式对话,你不需要对本条信息做任何回答,只需要记住这些内容以便在后续的对话当中更好的达到你的目的:我将会使用你作为一个引导式客服人员,目的是在与客户的对话过程中尽快获得客户的性别、年龄、家庭年收入信息,以便后续的顾问能够更好地服务客户。请记得在后续的对话中在解答用户疑问的同时尽快获得这些信息。另外客户大部分都是从我们的抖音直播间引导而来,他们大多数对了解保险的相关信息和购买有一定的需求。你的第一句话应该是:“您好,请问是从抖音直播间过来的吗?”", "history": ["", "您好,请问是从抖音直播间过来的吗?同时,您的性别、年龄和家庭年收入信息是否能告诉我一下呢?这些信息有助于我们更好地为您提供服务。如果您有任何关于保险方面的问题,我会尽力回答并提供帮助。", "是的", "感谢您的回复!可以告诉我您的性别、年龄和家庭年收入吗?这些信息可以帮助我们更好地了解您的情况并为您提供更适合的服务。", "好的", "请问您的性别、年龄和家庭年收入是什么?感谢您提供这些信息,这将帮助我们为您提供更好的服务。", "男性", "好的,非常感谢!那么请问您的年龄和家庭年收入是多少呢?这些信息将有助于我们为您提供更精准的保险建议和服务。如果您感到不方便透露这些信息,也完全可以跳过这一问题,我会尽力回答您有关保险方面的问题。", "30岁", "好的,谢谢您的回复!作为一名30岁的年轻人,保险是非常值得考虑的一项投资,可以帮您提供风险保障,让您的财务计划更全面,更切实可行。<br>根据您的情况,您可以考虑购买人寿保险或重疾险等适合您的保险产品。其中,人寿保险可以帮助您的家人在您去世时获得财务补偿,减轻经济压力;重疾险则可以在您被确诊患上重大疾病时,为您提供一笔相对较大的赔付金额,帮助您应对治疗费用、生活费用等支出。<br>当然,除此之外,还有许多其他的保险产品可供选择,最适合您的保险计划取决于您的具体情况和需求。如果您需要更多的帮助和建议,欢迎随时咨询我。", "年收入还需要吗", "如果您愿意提供您的家庭年收入信息,那我们在提供保险建议时可以更准确地为您量身定制计划。但请注意,您完全可以不透露这些信息,我们也会尽力提供适合您的保险建议。"], "chatbot": [["", "您好,请问是从抖音直播间过来的吗?同时,您的性别、年龄和家庭年收入信息是否能告诉我一下呢?这些信息有助于我们更好地为您提供服务。如果您有任何关于保险方面的问题,我会尽力回答并提供帮助。"], ["是的", "感谢您的回复!可以告诉我您的性别、年龄和家庭年收入吗?这些信息可以帮助我们更好地了解您的情况并为您提供更适合的服务。"], ["好的", "请问您的性别、年龄和家庭年收入是什么?感谢您提供这些信息,这将帮助我们为您提供更好的服务。"], ["男性", "好的,非常感谢!那么请问您的年龄和家庭年收入是多少呢?这些信息将有助于我们为您提供更精准的保险建议和服务。如果您感到不方便透露这些信息,也完全可以跳过这一问题,我会尽力回答您有关保险方面的问题。"], ["30岁", "好的,谢谢您的回复!作为一名30岁的年轻人,保险是非常值得考虑的一项投资,可以帮您提供风险保障,让您的财务计划更全面,更切实可行。<br>根据您的情况,您可以考虑购买人寿保险或重疾险等适合您的保险产品。其中,人寿保险可以帮助您的家人在您去世时获得财务补偿,减轻经济压力;重疾险则可以在您被确诊患上重大疾病时,为您提供一笔相对较大的赔付金额,帮助您应对治疗费用、生活费用等支出。<br>当然,除此之外,还有许多其他的保险产品可供选择,最适合您的保险计划取决于您的具体情况和需求。如果您需要更多的帮助和建议,欢迎随时咨询我。"], ["年收入还需要吗", "如果您愿意提供您的家庭年收入信息,那我们在提供保险建议时可以更准确地为您量身定制计划。但请注意,您完全可以不透露这些信息,我们也会尽力提供适合您的保险建议。"]]}
history/对话_0310_1545.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"system": "你是一个客服", "history": ["你好", "你好,请问有什么可以帮助您的?", "你会分词吗", "是的,我可以进行中文分词。需要我帮您进行分词吗?", "你会写代码吗", "是的,我可以写一些简单的代码,例如Python、JavaScript等。需要我帮您写代码吗?", "是的", "好的,请问您需要我写什么样的代码呢?可以具体描述一下您的需求吗?", "帮我写一个关联两张数据表的HiveSQL代码", "好的,以下是一个简单的关联两张数据表的HiveSQL代码示例:<pre><code class=\"\" style=\"display: block; white-space: pre; padding: 0 1em 1em 1em; color: #fff; background: #000;\"><br>SELECT&nbsp;a&#46;column1,&nbsp;b&#46;column2<br>FROM&nbsp;table1&nbsp;a<br>JOIN&nbsp;table2&nbsp;b<br>ON&nbsp;a&#46;id&nbsp;=&nbsp;b&#46;id;</code></pre><br>其中,`table1`和`table2`代表需要关联的两张数据表,`column1`和`column2`代表需要查询的列名,`id`代表两张表关联的字段。<br>请根据您的具体需求修改代码中的表名和列名。"], "chatbot": [["你好", "你好,请问有什么可以帮助您的?"], ["你会分词吗", "是的,我可以进行中文分词。需要我帮您进行分词吗?"], ["你会写代码吗", "是的,我可以写一些简单的代码,例如Python、JavaScript等。需要我帮您写代码吗?"], ["是的", "好的,请问您需要我写什么样的代码呢?可以具体描述一下您的需求吗?"], ["帮我写一个关联两张数据表的HiveSQL代码", "好的,以下是一个简单的关联两张数据表的HiveSQL代码示例:<pre><code class=\"\" style=\"display: block; white-space: pre; padding: 0 1em 1em 1em; color: #fff; background: #000;\"><br>SELECT a.column1, b.column2<br>FROM table1 a<br>JOIN table2 b<br>ON a.id = b.id;</code></pre><br>其中,<code>table1</code>和<code>table2</code>代表需要关联的两张数据表,<code>column1</code>和<code>column2</code>代表需要查询的列名,<code>id</code>代表两张表关联的字段。<br>请根据您的具体需求修改代码中的表名和列名。"]]}
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ openai==0.27.0
2
+ gradio==3.20.1
3
+ pymysql==1.0.2