""" 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( """ """, 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