File size: 22,495 Bytes
9431844
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
546ed9f
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
"""
1. 用Mermaid Mardown来画各种图,包括:脑图、流程图、客户历程图、关系图等。
1. 目前ChatGPT级别和百度文星一言等级别的大模型都可以比较好的输出Mermaid Markdown格式图。
1. 注意Mermaid代码中,不需要任何的’‘’, ````,或者"",这里只需要直接写Mermaid代码即可。
1. 完成了regenerate功能。
1. 完成了历史记忆功能,可以对图进行持续优化。但是不能保存中间结果。

1. 已知问题和解决方法:
    1. 已解决。尝试了多个方法,目前无法把HTML展现的内容用图片保存,目前不行。直接保存MHTML文件。
        1. HTML文件本身可以保存。
        1. 用html2image库,可以把HTML文件转换为图片,但是无法在streamlit中展示(内容为空白)。
        1. 可以想到的workaround:把HTML页面保存下来。
    1. HTML的高度只能手工制定,无法自动调整。可能垂直的页面会被截断。已经解决,通过设定scrolling=True, 可以实现滚动条。高度不在重要。
    1. 已解决。点击下载button后,页面会刷新。采用一个特殊的extension,https://github.com/PaleNeutron/streamlit-ext
"""
####TODO:

import json
import pprint
import streamlit as st
import chatgpt

import markdown
import md_mermaid
# from streamlit import components
import requests
import re
from openai import OpenAI
import streamlit_authenticator as stauth


import streamlit_ext as ste ##TODO: 为了点击download button后保持页面。

from datetime import datetime
from pytz import timezone

### streamlit app title
st.set_page_config(layout="wide", page_icon='llm_icon.png') ## 必须是第一行
st.title(f"大语言模型 - 体系图 | 框架图 | 逻辑图 | 流程图 - 辅助设计中心", anchor='Title')
st.subheader("AI Flowchart - Mindmap - Relation Diagram Design for Professionals")
st.info('如果输出图例时遇见任何问题(如:syntax error)或者不满意当前结果,请在左侧重新提交您的问题即可。一般建议至少尝试3-10次。')


## toast effect. 
# msg = st.toast('程序正在启动中,请稍等...',)
# msg.toast('大语言模型成功加载!', icon = "🥞")
# st.toast('大语言模型成功加载!', icon = "🥞")
# st.divider()
# st.markdown('_说明:如果输出图例遇见有任何问题,请刷新页面再重新提交您的问题即可!_')
# st.snow() ##可以在页面上显示雪花效果。
# st.balloons() ##可以在页面上显示气球效果。


### system prompt设置
openai_client = OpenAI()

# user_input = ""
system_prompt = f"""你是一个Mermaid Markdown方面的设计专家。你需要根据'我的要求'用Mermaid Markdown来画出对应的图。你仅需要提供Mermaid Markdown格式的代码,你不允许输出任何说明、解释或者提示的内容。"""
# system_prompt = f"""你是一个Mermaid Markdown方面的设计专家。你需要根据'我的要求'用Mermaid Markdown来画出对应的图。你仅需要提供Mermaid Markdown格式的代码,你不允许输出任何说明、解释或者提示的内容。

# '我的要求'如下:{user_input}"""

### 用户输入框
# Initialize chat history
if "messages" not in st.session_state:
    st.session_state.messages = [] ### original code here.
    # st.session_state.messages = [{"role": "system", "content": "你是一个Mermaid Markdown专家"}]
    # st.session_state.messages = [{"role": "system", "content": system_prompt}]

# st.session_state.messages = [{"role": "system", "content": '你是一个Mermaid Markdown方面的设计专家。'},{"role": "user", "content": ''}]


user_input = st.chat_input("说点什么吧...") ### original code here.
# if user_input:
#     with st.chat_message("user"):
#         st.markdown(user_input) ## 这里只需要输出用户的prompt,而不是total prompt。
#         st.session_state.messages.append({"role": "user", "content": user_input})

print('st.session_state.messages:')
pprint.pprint(st.session_state.messages)
# print('user_input:', json.dumps(user_input))
print('user_input now:')
pprint.pprint(user_input)
# print('user_input now', user_input)
# st.session_state.messages.append({"role": "user", "content": user_input})
### 设定一个历史信息的列表,用于存储用户的输入。为了regenerate按钮的功能。
# hist_msg = []



### 配置前端有关函数
# user_input = None
def clear_all():
    st.session_state.conversation = None
    st.session_state.chat_history = None
    st.session_state.messages = []
    message_placeholder = st.empty()
    st.session_state["my_question"] = None
    return None



### 重新生成按钮, regenerate, rerun(streamlit中的rerun是把整个页面重新加载一次?), resubmit. 
def regenerate():
    html_file = ""
    ## 因为可能没有历史,第一次的时候,所以需要处理异常。
    try:
        print('st.session_state.messages inside REGENERATE function:')
        pprint.pprint(st.session_state.messages)
        st.session_state.messages = st.session_state.messages[:-1]
        html_file = main(input=st.session_state.messages[0]['content']) ### original code here.
        # html_file = main(input=st.session_state.messages[-1]['content']) ### original code here.
    except Exception as e:
        print('Error:', e)
        pass
        
    return html_file

### authentication with a local yaml file.
import yaml
from yaml.loader import SafeLoader
with open('./config.yaml') as file:
    config = yaml.load(file, Loader=SafeLoader)
authenticator = stauth.Authenticate(
    config['credentials'],
    config['cookie']['name'],
    config['cookie']['key'],
    config['cookie']['expiry_days'],
    config['preauthorized']
)

user, authentication_status, username = authenticator.login('main')
# user, authentication_status, username = authenticator.login('用户登录', 'main')


### streamlit sidebar
if authentication_status:
    with st.sidebar:
        st.markdown(
            """
            <style>
            [data-testid="stSidebar"][aria-expanded="true"]{
                min-width: 450px;
                max-width: 450px;
            }
            """,
            unsafe_allow_html=True,
        )
        ### siderbar的题目。
        ### siderbar的题目。
        # st.header(f'**大语言模型专家系统工作设定区**')
        # st.header(f'**系统控制面板** ')
        st.header(f'**欢迎 **{username}** 来到人工智能的世界** ♠')
        # st.header(f'**欢迎 **{username}** 使用本系统** ') ## 用户登录显示。
        st.write(f'_Large Language Model System Environment_')
        authenticator.logout('登出', 'sidebar')
        # st.divider()
        
        st.sidebar.button("清除记录,重启一轮新对话", on_click=clear_all, use_container_width=True, type='primary')
        re_btn = st.sidebar.button("重新生成答案", use_container_width=True, type='secondary')
        # if re_btn:
        #     regenerate()
        # re_btn = st.sidebar.button("重新生成答案", on_click=regenerate, use_container_width=True, type='primary')

        ## 在sidebar上的三个分页显示,用st.tabs实现。
        # tab_1, tab_2, tab_4 = st.tabs(['使用须知', '模型参数', '角色设定'])
        tab_1, tab_2, tab_3, tab_4 = st.tabs(['基本介绍', '大模型参数', '提示词示例', '使用技巧'])

        # with st.expander(label='**使用须知**', expanded=False):
        with tab_1:
            # st.markdown("#### 快速上手指南")
            # with st.text(body="说明"):
            #     st.markdown("* 重启一轮新对话时,只需要刷新页面(按Ctrl/Command + R)即可。")
            with st.text(body="说明"):
                st.markdown("""* **使用大型语言模型设计体系图、框架图、逻辑图、流程图、关系图主要有以下几个步骤:**

    1. **明确目的和要表达的内容**
    在开始之前,你需要明确你想用图表来表达什么内容, 以及它的目的是什么。这将为接下来的步骤提供指导。

    2. **收集并组织相关信息**
    根据你的目的,收集所有相关的信息、数据和要点。将它们按合理的方式分类和组织, 为后续生成图表做好准备。

    3. **结构化输入**
    将组织好的内容转化为语言模型可以理解的结构化输入。比如使用简单描述、列表、树状结构等形式。

    4. **生成参考版本**
    将结构化输入提交给大型语言模型, 让它尝试生成供参考的流程图、脑图或关系图。

* 需要注意的是, 尽管大型语言模型可以生成很好的草图和初始版本, 但最终结果的质量仍然取决于你对目标和输入的描述质量。人工审查和调整是必不可少的环节。模型只是辅助工具, 无法完全替代人的判断和创造力。""")

        ## 大模型参数
        # with st.expander(label='**大语言模型参数**', expanded=True):
        with tab_2:
            max_tokens = st.slider(label='Max_Token(生成结果时最大字数)', min_value=100, max_value=4096, value=2048, step=100)
            temperature = st.slider(label='Temperature (温度)', min_value=0.0, max_value=1.0, value=0.8, step=0.1)
            top_p = st.slider(label='Top_P (核采样)', min_value=0.0, max_value=1.0, value=0.6, step=0.1)
            frequency_penalty = st.slider(label='Frequency Penalty (重复度惩罚因子)', min_value=-2.0, max_value=2.0, value=1.0, step=0.1)
            presence_penalty = st.slider(label='Presence Penalty (控制主题的重复度)', min_value=-2.0, max_value=2.0, value=1.0, step=0.1)

        ## reset password widget
        # try:
        #     if authenticator.reset_password(st.session_state["username"], 'Reset password'):
        #         st.success('Password modified successfully')
        # except Exception as e:
        #     st.error(e)

        # with st.header(body="欢迎"):
        #     st.markdown("# 欢迎使用大语言模型商业智能中心")
        # with st.expander(label=("**重要的使用注意事项**"), expanded=True):
        # with st.container():

        ##NOTE: 在SQL场景去不需要展示这些提示词。
        with tab_3:
            # st.write("#### Prompt提示词参考资料")
            st.code(body="你输出一个复杂的电子商务流程示意图,必须包含客户投诉退款环节。", language='plaintext')
            st.code(body="给我一个复杂的业务需求分析流程图。", language='plaintext')
            st.code(body="完整的Hermes客户体验流程图。", language='plaintext')
            st.code(body="完整的苹果公司线下实体店客户历程图。", language='plaintext')
            st.code(body="绘制一个横向的详细的IT运维流程示例。", language='plaintext')
            st.code(body="画一个汽车4S店的用户历程的复杂流程(至少要包含:客户邀约,客户试驾等)。", language='plaintext')
            st.code(body="绘制一张保险项目的甘特图。", language='plaintext')
            st.code(body="画一个用户历程的复杂流程。", language='plaintext')
            st.code(body="绘制一张复杂的绩效管理脑图。", language='plaintext')
            st.code(body="给我一个复杂的客户体验脑图示例。", language='plaintext')
            st.code(body="你给我一个全面质量管理的头脑风暴脑图。", language='plaintext')
            st.code(body="给我一个全面且复杂的精益管理流程图,图上需要每一步的说明。", language='plaintext')
            st.code(body="你做一个青少儿教育培训机构的完整电话邀约流程。", language='plaintext')
            st.code(body="在上面流程的基础上,继续细化”系统设计“部分的内容。", language='plaintext')
        
        with tab_4:
            st.markdown('''
    1. 使用`下载图例`按钮,可以直接下载MHTML格式的文件,大部分浏览器支持直接打开。

    1. 使用`下载代码`按钮,可以下载原始的Markdown代码,然后可以在类似 `https://mermaid.live/` 网站手动编辑。

    1. 目前支持持续修改流程版本,但不建议过度修改。修改的中间过程内容不会被保存。
    ''')


elif authentication_status == False:
    st.error('⛔ 用户名或密码错误!')
elif authentication_status == None:
    st.warning('⬆ 请先登录!')


### 得到当前的时间
def get_current_time():
    beijing_tz = timezone('Asia/Shanghai')
    beijing_time = datetime.now(beijing_tz)
    current_time = beijing_time.strftime('%H:%M:%S')
    return current_time

## 显示Mermaid图的核心函数
def mermaid(code: str):
    # st.write(code) ### 检查输入的Mermaid Markdown代码。
    from streamlit import components
    
    ### 以下返回的是HTML文件。
    html_file = components.v1.html(
        f"""
        <pre class="mermaid">
            {code}
        </pre>

        <script type="module">
            import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
            
            mermaid.initialize({{ startOnLoad: true }});
        </script>
        """
    ,
    height=400, ##NOTE: 这里可以有效改变HTML页面的高度。
    scrolling=True, ##NOTE: 可以实现滚动条。高度不在重要。
    )
    
    ## 以下是以字符串的形式返回HTML代码。
    html_file = str(f"""
        <pre class="mermaid">
            {code}
        </pre>

        <script type="module">
            import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
            
            mermaid.initialize({{ startOnLoad: true }});
        </script>
        """)
    
    ## 以下是以字符串的形式, 且只返回code部分,为了可以在https://mermaid.live/ 编辑。
    mermaid_str = code
    
    return html_file, mermaid_str
    # return html_file


def markdown_chart(input:str):
    # """answer general questions.""" 
    # final_prompt = f"""你是一个Mermaid Markdown方面的设计专家。你需要根据'我的要求'用Mermaid Markdown来画出对应的图。你仅需要提供Mermaid Markdown格式的代码,你不允许输出任何说明、解释或者提示的内容。
    # '我的要求'如下:{user_input}"""
    
    # print('user_input now', user_input)
    # st.session_state.messages.append(
    #                 {"role": "user", "content": user_input})
    # final_prompt = system_prompt + user_input

    if input:
        # st.session_state.messages.append({"role": "user", "content": input})
        # with st.chat_message("user"):
        #     st.markdown(user_input) ## 这里只需要输出用户的prompt,而不是total prompt。

        with st.chat_message("assistant", avatar="./llm_icon.png"):
            message_placeholder = st.empty()
            full_response = ""
            # llm_response = chatgpt.chatgpt(user_prompt=final_prompt) ### original code here.
            print('st.session_state.messages:')
            pprint.pprint(st.session_state.messages)
            # llm_response = chatgpt.chatgpt(user_prompt=st.session_state.messages) ### original code here.
            chatgpt_response = openai_client.chat.completions.create(model="gpt-3.5-turbo-16k",
            messages=[
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": json.dumps(st.session_state.messages, ensure_ascii=False)}, ##NOTE:注意这个形式。
            ],
            # messages=[
            #     {"role": "system", "content": system_prompt},
            #     {"role": "user", "content": st.session_state.messages[0]['content']},
            # ], ### original code here.
            stream=False,
        )
        
            llm_response = chatgpt_response.choices[0].message.content
            message_placeholder.markdown('结果如下:')
            
        st.session_state.messages.append(
        {"role": "assistant", "content": llm_response})
    
    # llm_response = chatgpt.chatgpt(user_prompt=final_prompt) ### original code here.
    
    ###NOTE: 需要去除mermaid关键字,需要去除反引号。
    try:
        ### 删除所有的非Mermaid格式的字符,反引号前后的文字。
        # pattern = r"mermaid\n(.*?\n?)"
        # match = re.search(pattern, llm_response, re.DOTALL)
        # if match:
        #     md_input = match.group(1)
        # md_input = str(re.split(r'^(.?)\nmermaid\n(.*?)\n*\n*(.*?)$', llm_response, flags=re.MULTILINE|re.DOTALL))
        
        
        ### 尝试各种正则式,为了只保留Mermaid Markdown格式的内容。
        pattern = r'```mermaid([\s\S]*?)```'
        match = re.search(pattern, llm_response)

        if match:
            md_input = match.group(1).strip()
        # print(md_input)
        
        if md_input:
            md_input = md_input.replace('mermaid', '') ##! working!!!这里需要!
            # md_input = md_input.replace('mermaid', ' ') ##! working!!!这里需要!
        else:
            md_input = llm_response.replace('mermaid', '') ##! working!!!这里需要!
        md_input = md_input.replace("```", '') ###! working!注意这里需要去掉的是三个反引号(```),而不是一个。
    except Exception as e:
        print('Error:', e)
        md_input = llm_response
    
    # mermaid(md_input)
    html_file = mermaid(md_input)
    
    # ##保存HTML的方法
    # html_file = mermaid(md_input)
    # # print('type of html_file:', type(html_file))
    # with open('output.html', 'w', encoding='utf-8') as f: ### 可以保存HTML文件。
    #     f.write(html_file)
    
    # from html2image import Html2Image
    
    # css_settings = '''
    # .center {
    # margin: auto;
    # height: 500px;
    # width: 500px;
    # }
    # body {
    #     background-color: lightgrey;
    #     height: 100%;
    #     display: grid;
    # }
    # '''

    # css_settings = "body {background: grey;}"
    
    
    ###TODO:尝试将HTML文件转成图片,目前各种方法都不成功。
    # hti = Html2Image()
    # img_path = hti.screenshot(html_file='./output.html', save_as='html.png', size=(500, 200))
    # img_path = hti.screenshot(html_file=html_file, save_as='html.png', css_str=css_settings, size=(500, 200))
    # print('img path:', img_path)
    
    # diagram_time = get_current_time()
    # st.success(body=f'程序运行完成!当前时间:{diagram_time}。', icon='💯')
    
    # return None
    return html_file

### 测试prompt
# markdown_chart("画一个流程图,描述用户访问网站的流程。你只需要提供Mermaid Markdown格式的代码,不需要任何额外的说明或者解释")



## 给按键设置的CSS,据说可以把button放在一起更加紧密。参见: https://discuss.streamlit.io/t/st-button-in-one-line/25966/6
st.markdown("""
            <style>
                div[data-testid="column"] {
                    width: fit-content !important;
                    flex: unset;
                }
                div[data-testid="column"] * {
                    width: fit-content !important;
                }
            </style>
            """, unsafe_allow_html=True)

## TODO:看看是否可以保持页面内容,在download button之后。
# user_input = st.chat_input("说点什么吧...")
def main(input):
    # user_input = st.text_input(label='输入您的问题', placeholder='给我一个复杂的业务需求分析流程图。', label_visibility='visible')
    if input:
        # st.session_state.messages.append(user_input)
        # with st.status('检索中...', expanded=False, state='running') as status:
        with st.chat_message("user"):
            st.markdown(input) ## 这里只需要输出用户的prompt,而不是total prompt。
            st.session_state.messages.append({"role": "user", "content": input})
        spinner = st.spinner('处理中...请耐心等待')
        with spinner:
            html_file, mermaid_code = markdown_chart(input=input)
            diagram_time = get_current_time()
            st.success(body=f'程序运行完成!当前时间:{diagram_time}。', icon='💯')

            ## 可以直接下载HTML文件。让可以展示所有的相关图片。
            if html_file:
                col1, col2, col3 = st.columns([1, 1, 8])
                with col1:
                    ste.download_button(
                        label="下载图例",
                        data=html_file,
                        file_name='mydiagram.html',
                        # mime='text/markdown',
                    )
                    # st.download_button(
                    #     label="下载上述图例",
                    #     data=html_file,
                    #     file_name='mydiagram.html',
                    #     # mime='text/markdown',
                    # )
                    
                with col2:
                    ste.download_button(
                        label="下载代码",
                        data=mermaid_code,
                        file_name='mydiagram.txt',
                        # mime='text/markdown',
                    )
                    # st.download_button(
                    #     label="下载上述图例",
                    #     data=html_file,
                    #     file_name='mydiagram.html',
                    #     # mime='text/markdown',
                    # )

                ##NOTE:上面的download button的高度与一般的st.button不同。
                # with col2:
                #     # st.button("重新生成答案")
                #     print('st.session_state.messages now', st.session_state.messages)
                #     st.button("重新生成答案", on_click=regenerate)
                #     if re_btn:
                #         regenerate()

        return html_file


# user_input = st.text_input("说点什么吧...")
if __name__ == '__main__':
    html_file = main(input=user_input)
    
    ##! working. 需要先在sidebar上设置re_btn,然后在这里调用regenerate函数。而不是在button里面直接用on-click来触发函数。

    # if re_btn:
    #     regenerate()

    try:
        if re_btn:
            regenerate()
    except Exception as e:
        print('Error:', e)
        pass