Spaces:
Running
Running
Upload 6 files
Browse files- README.md +8 -11
- app.py +487 -0
- chatgpt.py +61 -0
- config.yaml +61 -0
- llm_icon.png +0 -0
- requirements.txt +15 -0
README.md
CHANGED
@@ -1,12 +1,9 @@
|
|
1 |
-
|
2 |
-
title: Diagram001
|
3 |
-
emoji: 📉
|
4 |
-
colorFrom: indigo
|
5 |
-
colorTo: indigo
|
6 |
-
sdk: streamlit
|
7 |
-
sdk_version: 1.33.0
|
8 |
-
app_file: app.py
|
9 |
-
pinned: false
|
10 |
-
---
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# 关于大型语言模型设计流程图、脑图、甘特图、时序图、关系图功能说明
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
+
1. 目前是通过Mermaid Markdown来输出流程图等。
|
4 |
+
1. 目前仅使用ChatGPT作为基座,千亿级国产模型也可以。
|
5 |
+
2. Mindmap脑图功能相对较弱,错误比较多。需要检查一下mindmap入口的语法syntax。
|
6 |
+
3. 目前支持导出MHTML文件和Mermaid Markdown代码,其中MHTML可以直接看到图例。
|
7 |
+
4. Mermaid Markdown代码可以在https://mermaid.live/ 网站支持后续的编辑。
|
8 |
+
5. 后续可以考虑寻找可以拖拽编辑的网站或者软件。
|
9 |
+
6. app是基础版本,只包含的一次性设计的内容。app_pro是高级版本,包括了持续修改能力,但是不能自动保存中间结果。
|
app.py
ADDED
@@ -0,0 +1,487 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
1. 用Mermaid Mardown来画各种图,包括:脑图、流程图、客户历程图、关系图等。
|
3 |
+
1. 目前ChatGPT级别和百度文星一言等级别的大模型都可以比较好的输出Mermaid Markdown格式图。
|
4 |
+
1. 注意Mermaid代码中,不需要任何的’‘’, ````,或者"",这里只需要直接写Mermaid代码即可。
|
5 |
+
1. 完成了regenerate功能。
|
6 |
+
1. 完成了历史记忆功能,可以对图进行持续优化。但是不能保存中间结果。
|
7 |
+
|
8 |
+
1. 已知问题和解决方法:
|
9 |
+
1. 已解决。尝试了多个方法,目前无法把HTML展现的内容用图片保存,目前不行。直接保存MHTML文件。
|
10 |
+
1. HTML文件本身可以保存。
|
11 |
+
1. 用html2image库,可以把HTML文件转换为图片,但是无法在streamlit中展示(内容为空白)。
|
12 |
+
1. 可以想到的workaround:把HTML页面保存下来。
|
13 |
+
1. HTML的高度只能手工制定,无法自动调整。可能垂直的页面会被截断。已经解决,通过设定scrolling=True, 可以实现滚动条。高度不在重要。
|
14 |
+
1. 已解决。点击下载button后,页面会刷新。采用一个特殊的extension,https://github.com/PaleNeutron/streamlit-ext
|
15 |
+
"""
|
16 |
+
####TODO:
|
17 |
+
|
18 |
+
import json
|
19 |
+
import pprint
|
20 |
+
import streamlit as st
|
21 |
+
import chatgpt
|
22 |
+
|
23 |
+
import markdown
|
24 |
+
import md_mermaid
|
25 |
+
# from streamlit import components
|
26 |
+
import requests
|
27 |
+
import re
|
28 |
+
from openai import OpenAI
|
29 |
+
import streamlit_authenticator as stauth
|
30 |
+
|
31 |
+
|
32 |
+
import streamlit_ext as ste ##TODO: 为了点击download button后保持页面。
|
33 |
+
|
34 |
+
from datetime import datetime
|
35 |
+
from pytz import timezone
|
36 |
+
|
37 |
+
### streamlit app title
|
38 |
+
st.set_page_config(layout="wide", page_icon='llm_icon.png') ## 必须是第一行
|
39 |
+
st.title(f"大语言模型 - 体系图 | 框架图 | 逻辑图 | 流程图 - 辅助设计中心", anchor='Title')
|
40 |
+
st.subheader("AI Flowchart - Mindmap - Relation Diagram Design for Professionals")
|
41 |
+
st.info('如果输出图例时遇见任何问题(如:syntax error)或者不满意当前结果,请在左侧重新提交您的问题即可。一般建议至少尝试3-10次。')
|
42 |
+
|
43 |
+
|
44 |
+
## toast effect.
|
45 |
+
# msg = st.toast('程序正在启动中,请稍等...',)
|
46 |
+
# msg.toast('大语言模型成功加载!', icon = "🥞")
|
47 |
+
# st.toast('大语言模型成功加载!', icon = "🥞")
|
48 |
+
# st.divider()
|
49 |
+
# st.markdown('_说明:如果输出图例遇见有任何问题,请刷新页面再重新提交您的问题即可!_')
|
50 |
+
# st.snow() ##可以在页面上显示雪花效果。
|
51 |
+
# st.balloons() ##可以在页面上显示气球效果。
|
52 |
+
|
53 |
+
|
54 |
+
### system prompt设置
|
55 |
+
openai_client = OpenAI()
|
56 |
+
|
57 |
+
# user_input = ""
|
58 |
+
system_prompt = f"""你是一个Mermaid Markdown方面的设计专家。你需要根据'我的要求'用Mermaid Markdown来画出对应的图。你仅需要提供Mermaid Markdown格式的代码,你不允许输出任何说明、解释或者提示的内容。"""
|
59 |
+
# system_prompt = f"""你是一个Mermaid Markdown方面的设计专家。你需要根据'我的要求'用Mermaid Markdown来画出对应的图。你仅需要提供Mermaid Markdown格式的代码,你不允许输出任何说明、解释或者提示的内容。
|
60 |
+
|
61 |
+
# '我的要求'如下:{user_input}"""
|
62 |
+
|
63 |
+
### 用户输入框
|
64 |
+
# Initialize chat history
|
65 |
+
if "messages" not in st.session_state:
|
66 |
+
st.session_state.messages = [] ### original code here.
|
67 |
+
# st.session_state.messages = [{"role": "system", "content": "你是一个Mermaid Markdown专家"}]
|
68 |
+
# st.session_state.messages = [{"role": "system", "content": system_prompt}]
|
69 |
+
|
70 |
+
# st.session_state.messages = [{"role": "system", "content": '你是一个Mermaid Markdown方面的设计专家。'},{"role": "user", "content": ''}]
|
71 |
+
|
72 |
+
|
73 |
+
user_input = st.chat_input("说点什么吧...") ### original code here.
|
74 |
+
# if user_input:
|
75 |
+
# with st.chat_message("user"):
|
76 |
+
# st.markdown(user_input) ## 这里只需要输出用户的prompt,而不是total prompt。
|
77 |
+
# st.session_state.messages.append({"role": "user", "content": user_input})
|
78 |
+
|
79 |
+
print('st.session_state.messages:')
|
80 |
+
pprint.pprint(st.session_state.messages)
|
81 |
+
# print('user_input:', json.dumps(user_input))
|
82 |
+
print('user_input now:')
|
83 |
+
pprint.pprint(user_input)
|
84 |
+
# print('user_input now', user_input)
|
85 |
+
# st.session_state.messages.append({"role": "user", "content": user_input})
|
86 |
+
### 设定一个历史信息的列表,用于存储用户的输入。为了regenerate按钮的功能。
|
87 |
+
# hist_msg = []
|
88 |
+
|
89 |
+
|
90 |
+
|
91 |
+
### 配置前端有关函数
|
92 |
+
# user_input = None
|
93 |
+
def clear_all():
|
94 |
+
st.session_state.conversation = None
|
95 |
+
st.session_state.chat_history = None
|
96 |
+
st.session_state.messages = []
|
97 |
+
message_placeholder = st.empty()
|
98 |
+
st.session_state["my_question"] = None
|
99 |
+
return None
|
100 |
+
|
101 |
+
|
102 |
+
|
103 |
+
### 重新生成按钮, regenerate, rerun(streamlit中的rerun是把整个页面重新加载一次?), resubmit.
|
104 |
+
def regenerate():
|
105 |
+
html_file = ""
|
106 |
+
## 因为可能没有历史,第一次的时候,所以需要处理异常。
|
107 |
+
try:
|
108 |
+
print('st.session_state.messages inside REGENERATE function:')
|
109 |
+
pprint.pprint(st.session_state.messages)
|
110 |
+
st.session_state.messages = st.session_state.messages[:-1]
|
111 |
+
html_file = main(input=st.session_state.messages[0]['content']) ### original code here.
|
112 |
+
# html_file = main(input=st.session_state.messages[-1]['content']) ### original code here.
|
113 |
+
except Exception as e:
|
114 |
+
print('Error:', e)
|
115 |
+
pass
|
116 |
+
|
117 |
+
return html_file
|
118 |
+
|
119 |
+
### authentication with a local yaml file.
|
120 |
+
import yaml
|
121 |
+
from yaml.loader import SafeLoader
|
122 |
+
with open('./config.yaml') as file:
|
123 |
+
config = yaml.load(file, Loader=SafeLoader)
|
124 |
+
authenticator = stauth.Authenticate(
|
125 |
+
config['credentials'],
|
126 |
+
config['cookie']['name'],
|
127 |
+
config['cookie']['key'],
|
128 |
+
config['cookie']['expiry_days'],
|
129 |
+
config['preauthorized']
|
130 |
+
)
|
131 |
+
|
132 |
+
user, authentication_status, username = authenticator.login('main')
|
133 |
+
# user, authentication_status, username = authenticator.login('用户登录', 'main')
|
134 |
+
|
135 |
+
|
136 |
+
### streamlit sidebar
|
137 |
+
if authentication_status:
|
138 |
+
with st.sidebar:
|
139 |
+
st.markdown(
|
140 |
+
"""
|
141 |
+
<style>
|
142 |
+
[data-testid="stSidebar"][aria-expanded="true"]{
|
143 |
+
min-width: 450px;
|
144 |
+
max-width: 450px;
|
145 |
+
}
|
146 |
+
""",
|
147 |
+
unsafe_allow_html=True,
|
148 |
+
)
|
149 |
+
### siderbar的题目。
|
150 |
+
### siderbar的题目。
|
151 |
+
# st.header(f'**大语言模型专家系统工作设定区**')
|
152 |
+
# st.header(f'**系统控制面板** ')
|
153 |
+
st.header(f'**欢迎 **{username}** 来到人工智能的世界** ♠')
|
154 |
+
# st.header(f'**欢迎 **{username}** 使用本系统** ') ## 用户登录显示。
|
155 |
+
st.write(f'_Large Language Model System Environment_')
|
156 |
+
authenticator.logout('登出', 'sidebar')
|
157 |
+
# st.divider()
|
158 |
+
|
159 |
+
st.sidebar.button("清除记录,重启一轮新对话", on_click=clear_all, use_container_width=True, type='primary')
|
160 |
+
re_btn = st.sidebar.button("重新生成答案", use_container_width=True, type='secondary')
|
161 |
+
# if re_btn:
|
162 |
+
# regenerate()
|
163 |
+
# re_btn = st.sidebar.button("重新生成答案", on_click=regenerate, use_container_width=True, type='primary')
|
164 |
+
|
165 |
+
## 在sidebar上的三个分页显示,用st.tabs实现。
|
166 |
+
# tab_1, tab_2, tab_4 = st.tabs(['使用须知', '模型参数', '角色设定'])
|
167 |
+
tab_1, tab_2, tab_3, tab_4 = st.tabs(['基本介绍', '大模型参数', '提示词示例', '使用技巧'])
|
168 |
+
|
169 |
+
# with st.expander(label='**使用须知**', expanded=False):
|
170 |
+
with tab_1:
|
171 |
+
# st.markdown("#### 快速上手指南")
|
172 |
+
# with st.text(body="说明"):
|
173 |
+
# st.markdown("* 重启一轮新对话时,只需要刷新页面(按Ctrl/Command + R)即可。")
|
174 |
+
with st.text(body="说明"):
|
175 |
+
st.markdown("""* **使用大型语言模型设计体系图、框架图、逻辑图、流程图、关系图主要有以下几个步骤:**
|
176 |
+
|
177 |
+
1. **明确目的和要表达的内容**
|
178 |
+
在开始之前,你需要明确你想用图表来表达什么内容, 以及它的目的是什么。这将为接下来的步骤提供指导。
|
179 |
+
|
180 |
+
2. **收集并组织相关信息**
|
181 |
+
根据你的目的,收集所有相关的信息、数据和要点。将它们按合理的方式分类和组织, 为后续生成图表做好准备。
|
182 |
+
|
183 |
+
3. **结构化输入**
|
184 |
+
将组织好的内容转化为语言模型可以理解的结构化输入。比如使用简单描述、列表、树状结构等形式。
|
185 |
+
|
186 |
+
4. **生成参考版本**
|
187 |
+
将结构化输入提交给大型语言模型, 让它尝试生成供参考的流程图、脑图或关系图。
|
188 |
+
|
189 |
+
* 需要注意的是, 尽管大型语言模型可以生成很好的草图和初始版本, 但最终结果的质量仍然取决于你对目标和输入的描述质量。人工审查和调整是必不可少的环节。模型只是辅助工具, 无法完全替代人的判断和创造力。""")
|
190 |
+
|
191 |
+
## 大模型参数
|
192 |
+
# with st.expander(label='**大语言模型参数**', expanded=True):
|
193 |
+
with tab_2:
|
194 |
+
max_tokens = st.slider(label='Max_Token(生成结果时最大字数)', min_value=100, max_value=4096, value=2048, step=100)
|
195 |
+
temperature = st.slider(label='Temperature (温度)', min_value=0.0, max_value=1.0, value=0.8, step=0.1)
|
196 |
+
top_p = st.slider(label='Top_P (核采样)', min_value=0.0, max_value=1.0, value=0.6, step=0.1)
|
197 |
+
frequency_penalty = st.slider(label='Frequency Penalty (重复度惩罚因子)', min_value=-2.0, max_value=2.0, value=1.0, step=0.1)
|
198 |
+
presence_penalty = st.slider(label='Presence Penalty (控制主题的重复度)', min_value=-2.0, max_value=2.0, value=1.0, step=0.1)
|
199 |
+
|
200 |
+
## reset password widget
|
201 |
+
# try:
|
202 |
+
# if authenticator.reset_password(st.session_state["username"], 'Reset password'):
|
203 |
+
# st.success('Password modified successfully')
|
204 |
+
# except Exception as e:
|
205 |
+
# st.error(e)
|
206 |
+
|
207 |
+
# with st.header(body="欢迎"):
|
208 |
+
# st.markdown("# 欢迎使用大语言模型商业智能中心")
|
209 |
+
# with st.expander(label=("**重要的使用注意事项**"), expanded=True):
|
210 |
+
# with st.container():
|
211 |
+
|
212 |
+
##NOTE: 在SQL场景去不需要展示这些提示词。
|
213 |
+
with tab_3:
|
214 |
+
# st.write("#### Prompt提示词参考资料")
|
215 |
+
st.code(body="你输出一个复杂的电子商务流程示意图,必须包含客户投诉退款环节。", language='plaintext')
|
216 |
+
st.code(body="给我一个复杂的业务需求分析流程图。", language='plaintext')
|
217 |
+
st.code(body="完整的Hermes客户体验流程图。", language='plaintext')
|
218 |
+
st.code(body="完整的苹果公司线下实体店客户历程图。", language='plaintext')
|
219 |
+
st.code(body="绘制一个横向的详细的IT运维流程示例。", language='plaintext')
|
220 |
+
st.code(body="画一个汽车4S店的用户历程的复杂流程(至少要包含:客户邀约,客户试驾等)。", language='plaintext')
|
221 |
+
st.code(body="绘制一张保险项目的甘特图。", language='plaintext')
|
222 |
+
st.code(body="画一个用户历程的复杂流程。", language='plaintext')
|
223 |
+
st.code(body="绘制一张复杂的绩效管理脑图。", language='plaintext')
|
224 |
+
st.code(body="给我一个复杂的客户体验脑图示例。", language='plaintext')
|
225 |
+
st.code(body="你给我一个全面质量管理的头脑风暴脑图。", language='plaintext')
|
226 |
+
st.code(body="给我一个全面且复杂的精益管理流程图,图上需要每一步的说明。", language='plaintext')
|
227 |
+
st.code(body="你做一个青少儿教育培训机构的完整电话邀约流程。", language='plaintext')
|
228 |
+
st.code(body="在上面流程的基础上,继续细化”系统设计“部分的内容。", language='plaintext')
|
229 |
+
|
230 |
+
with tab_4:
|
231 |
+
st.markdown('''
|
232 |
+
1. 使用`下载图例`按钮,可以直接下载MHTML格式的文件,大部分浏览器支持直接打开。
|
233 |
+
|
234 |
+
1. 使用`下载代码`按钮,可以下载原始的Markdown代码,然后可以在类似 `https://mermaid.live/` 网站手动编辑。
|
235 |
+
|
236 |
+
1. 目前支持持续修改流程版本,但不建议过度修改。修改的中间过程内容不会被保存。
|
237 |
+
''')
|
238 |
+
|
239 |
+
|
240 |
+
elif authentication_status == False:
|
241 |
+
st.error('⛔ 用户名或密码错误!')
|
242 |
+
elif authentication_status == None:
|
243 |
+
st.warning('⬆ 请先登录!')
|
244 |
+
|
245 |
+
|
246 |
+
### 得到当前的时间
|
247 |
+
def get_current_time():
|
248 |
+
beijing_tz = timezone('Asia/Shanghai')
|
249 |
+
beijing_time = datetime.now(beijing_tz)
|
250 |
+
current_time = beijing_time.strftime('%H:%M:%S')
|
251 |
+
return current_time
|
252 |
+
|
253 |
+
## 显示Mermaid图的核心函数
|
254 |
+
def mermaid(code: str):
|
255 |
+
# st.write(code) ### 检查输入的Mermaid Markdown代码。
|
256 |
+
from streamlit import components
|
257 |
+
|
258 |
+
### 以下返回的是HTML文件。
|
259 |
+
html_file = components.v1.html(
|
260 |
+
f"""
|
261 |
+
<pre class="mermaid">
|
262 |
+
{code}
|
263 |
+
</pre>
|
264 |
+
|
265 |
+
<script type="module">
|
266 |
+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
267 |
+
|
268 |
+
mermaid.initialize({{ startOnLoad: true }});
|
269 |
+
</script>
|
270 |
+
"""
|
271 |
+
,
|
272 |
+
height=400, ##NOTE: 这里可以有效改变HTML页面的高度。
|
273 |
+
scrolling=True, ##NOTE: 可以实现滚动条。高度不在重要。
|
274 |
+
)
|
275 |
+
|
276 |
+
## 以下是以字符串的形式返回HTML代码。
|
277 |
+
html_file = str(f"""
|
278 |
+
<pre class="mermaid">
|
279 |
+
{code}
|
280 |
+
</pre>
|
281 |
+
|
282 |
+
<script type="module">
|
283 |
+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
284 |
+
|
285 |
+
mermaid.initialize({{ startOnLoad: true }});
|
286 |
+
</script>
|
287 |
+
""")
|
288 |
+
|
289 |
+
## 以下是以字符串的形式, 且只返回code部分,为了可以在https://mermaid.live/ 编辑。
|
290 |
+
mermaid_str = code
|
291 |
+
|
292 |
+
return html_file, mermaid_str
|
293 |
+
# return html_file
|
294 |
+
|
295 |
+
|
296 |
+
def markdown_chart(input:str):
|
297 |
+
# """answer general questions."""
|
298 |
+
# final_prompt = f"""你是一个Mermaid Markdown方面的设计专家。你需要根据'我的要求'用Mermaid Markdown来画出对应的图。你仅需要提供Mermaid Markdown格式的代码,你不允许输出任何说明、解释或者提示的内容。
|
299 |
+
# '我的要求'如下:{user_input}"""
|
300 |
+
|
301 |
+
# print('user_input now', user_input)
|
302 |
+
# st.session_state.messages.append(
|
303 |
+
# {"role": "user", "content": user_input})
|
304 |
+
# final_prompt = system_prompt + user_input
|
305 |
+
|
306 |
+
if input:
|
307 |
+
# st.session_state.messages.append({"role": "user", "content": input})
|
308 |
+
# with st.chat_message("user"):
|
309 |
+
# st.markdown(user_input) ## 这里只需要输出用户的prompt,而不是total prompt。
|
310 |
+
|
311 |
+
with st.chat_message("assistant", avatar="./llm_icon.png"):
|
312 |
+
message_placeholder = st.empty()
|
313 |
+
full_response = ""
|
314 |
+
# llm_response = chatgpt.chatgpt(user_prompt=final_prompt) ### original code here.
|
315 |
+
print('st.session_state.messages:')
|
316 |
+
pprint.pprint(st.session_state.messages)
|
317 |
+
# llm_response = chatgpt.chatgpt(user_prompt=st.session_state.messages) ### original code here.
|
318 |
+
chatgpt_response = openai_client.chat.completions.create(model="gpt-3.5-turbo-16k",
|
319 |
+
messages=[
|
320 |
+
{"role": "system", "content": system_prompt},
|
321 |
+
{"role": "user", "content": json.dumps(st.session_state.messages, ensure_ascii=False)}, ##NOTE:注意这个形式。
|
322 |
+
],
|
323 |
+
# messages=[
|
324 |
+
# {"role": "system", "content": system_prompt},
|
325 |
+
# {"role": "user", "content": st.session_state.messages[0]['content']},
|
326 |
+
# ], ### original code here.
|
327 |
+
stream=False,
|
328 |
+
)
|
329 |
+
|
330 |
+
llm_response = chatgpt_response.choices[0].message.content
|
331 |
+
message_placeholder.markdown('结果如下:')
|
332 |
+
|
333 |
+
st.session_state.messages.append(
|
334 |
+
{"role": "assistant", "content": llm_response})
|
335 |
+
|
336 |
+
# llm_response = chatgpt.chatgpt(user_prompt=final_prompt) ### original code here.
|
337 |
+
|
338 |
+
###NOTE: 需要去除mermaid关键字,需要去除反引号。
|
339 |
+
try:
|
340 |
+
### 删除所有的非Mermaid格式的字符,反引号前后的文字。
|
341 |
+
# pattern = r"mermaid\n(.*?\n?)"
|
342 |
+
# match = re.search(pattern, llm_response, re.DOTALL)
|
343 |
+
# if match:
|
344 |
+
# md_input = match.group(1)
|
345 |
+
# md_input = str(re.split(r'^(.?)\nmermaid\n(.*?)\n*\n*(.*?)$', llm_response, flags=re.MULTILINE|re.DOTALL))
|
346 |
+
|
347 |
+
|
348 |
+
### 尝试各种正则式,为了只保留Mermaid Markdown格式的内容。
|
349 |
+
pattern = r'```mermaid([\s\S]*?)```'
|
350 |
+
match = re.search(pattern, llm_response)
|
351 |
+
|
352 |
+
if match:
|
353 |
+
md_input = match.group(1).strip()
|
354 |
+
# print(md_input)
|
355 |
+
|
356 |
+
if md_input:
|
357 |
+
md_input = md_input.replace('mermaid', '') ##! working!!!这里需要!
|
358 |
+
# md_input = md_input.replace('mermaid', ' ') ##! working!!!这里需要!
|
359 |
+
else:
|
360 |
+
md_input = llm_response.replace('mermaid', '') ##! working!!!这里需要!
|
361 |
+
md_input = md_input.replace("```", '') ###! working!注意这里需要去掉的是三个反引号(```),而不是一个。
|
362 |
+
except Exception as e:
|
363 |
+
print('Error:', e)
|
364 |
+
md_input = llm_response
|
365 |
+
|
366 |
+
# mermaid(md_input)
|
367 |
+
html_file = mermaid(md_input)
|
368 |
+
|
369 |
+
# ##保存HTML的方法
|
370 |
+
# html_file = mermaid(md_input)
|
371 |
+
# # print('type of html_file:', type(html_file))
|
372 |
+
# with open('output.html', 'w', encoding='utf-8') as f: ### 可以保存HTML文件。
|
373 |
+
# f.write(html_file)
|
374 |
+
|
375 |
+
# from html2image import Html2Image
|
376 |
+
|
377 |
+
# css_settings = '''
|
378 |
+
# .center {
|
379 |
+
# margin: auto;
|
380 |
+
# height: 500px;
|
381 |
+
# width: 500px;
|
382 |
+
# }
|
383 |
+
# body {
|
384 |
+
# background-color: lightgrey;
|
385 |
+
# height: 100%;
|
386 |
+
# display: grid;
|
387 |
+
# }
|
388 |
+
# '''
|
389 |
+
|
390 |
+
# css_settings = "body {background: grey;}"
|
391 |
+
|
392 |
+
|
393 |
+
###TODO:尝试将HTML文件转成图片,目前各种方法都不成功。
|
394 |
+
# hti = Html2Image()
|
395 |
+
# img_path = hti.screenshot(html_file='./output.html', save_as='html.png', size=(500, 200))
|
396 |
+
# img_path = hti.screenshot(html_file=html_file, save_as='html.png', css_str=css_settings, size=(500, 200))
|
397 |
+
# print('img path:', img_path)
|
398 |
+
|
399 |
+
# diagram_time = get_current_time()
|
400 |
+
# st.success(body=f'程序运行完成!当前时间:{diagram_time}。', icon='💯')
|
401 |
+
|
402 |
+
# return None
|
403 |
+
return html_file
|
404 |
+
|
405 |
+
### 测试prompt
|
406 |
+
# markdown_chart("画一个流程图,描述用户访问网站的流程。你只需要提供Mermaid Markdown格式的代码,不需要任何额外的说明或者解释")
|
407 |
+
|
408 |
+
|
409 |
+
|
410 |
+
## 给按键设置的CSS,据说可以把button放在一起更加紧密。参见: https://discuss.streamlit.io/t/st-button-in-one-line/25966/6
|
411 |
+
st.markdown("""
|
412 |
+
<style>
|
413 |
+
div[data-testid="column"] {
|
414 |
+
width: fit-content !important;
|
415 |
+
flex: unset;
|
416 |
+
}
|
417 |
+
div[data-testid="column"] * {
|
418 |
+
width: fit-content !important;
|
419 |
+
}
|
420 |
+
</style>
|
421 |
+
""", unsafe_allow_html=True)
|
422 |
+
|
423 |
+
## TODO:看看是否可以保持页面内容,在download button之后。
|
424 |
+
# user_input = st.chat_input("说点什么吧...")
|
425 |
+
def main(input):
|
426 |
+
# user_input = st.text_input(label='输入您的问题', placeholder='给我一个复杂的业务需求分析流程图。', label_visibility='visible')
|
427 |
+
if input:
|
428 |
+
# st.session_state.messages.append(user_input)
|
429 |
+
# with st.status('检索中...', expanded=False, state='running') as status:
|
430 |
+
with st.chat_message("user"):
|
431 |
+
st.markdown(input) ## 这里只需要输出用户的prompt,而不是total prompt。
|
432 |
+
st.session_state.messages.append({"role": "user", "content": input})
|
433 |
+
spinner = st.spinner('处理中...请耐心等待')
|
434 |
+
with spinner:
|
435 |
+
html_file, mermaid_code = markdown_chart(input=input)
|
436 |
+
diagram_time = get_current_time()
|
437 |
+
st.success(body=f'程序运行完成!当前时间:{diagram_time}。', icon='💯')
|
438 |
+
|
439 |
+
## 可以直接下载HTML文件。让可以展示所有的相关图片。
|
440 |
+
if html_file:
|
441 |
+
col1, col2, col3 = st.columns([1, 1, 8])
|
442 |
+
with col1:
|
443 |
+
ste.download_button(
|
444 |
+
label="下载图例",
|
445 |
+
data=html_file,
|
446 |
+
file_name='mydiagram.html',
|
447 |
+
# mime='text/markdown',
|
448 |
+
)
|
449 |
+
# st.download_button(
|
450 |
+
# label="下载上述图例",
|
451 |
+
# data=html_file,
|
452 |
+
# file_name='mydiagram.html',
|
453 |
+
# # mime='text/markdown',
|
454 |
+
# )
|
455 |
+
|
456 |
+
with col2:
|
457 |
+
ste.download_button(
|
458 |
+
label="下载代码",
|
459 |
+
data=mermaid_code,
|
460 |
+
file_name='mydiagram.txt',
|
461 |
+
# mime='text/markdown',
|
462 |
+
)
|
463 |
+
# st.download_button(
|
464 |
+
# label="下载上述图例",
|
465 |
+
# data=html_file,
|
466 |
+
# file_name='mydiagram.html',
|
467 |
+
# # mime='text/markdown',
|
468 |
+
# )
|
469 |
+
|
470 |
+
##NOTE:上面的download button的高度与一般的st.button不同。
|
471 |
+
# with col2:
|
472 |
+
# # st.button("重新生成答案")
|
473 |
+
# print('st.session_state.messages now', st.session_state.messages)
|
474 |
+
# st.button("重新生成答案", on_click=regenerate)
|
475 |
+
# if re_btn:
|
476 |
+
# regenerate()
|
477 |
+
|
478 |
+
return html_file
|
479 |
+
|
480 |
+
|
481 |
+
# user_input = st.text_input("说点什么吧...")
|
482 |
+
if __name__ == '__main__':
|
483 |
+
html_file = main(input=user_input)
|
484 |
+
|
485 |
+
##! working. 需要先在sidebar上设置re_btn,然后在这里调用regenerate函数。而不是在button里面直接用on-click来触发函数。
|
486 |
+
if re_btn:
|
487 |
+
regenerate()
|
chatgpt.py
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import requests
|
4 |
+
import streamlit as st
|
5 |
+
import openai
|
6 |
+
from openai import OpenAI
|
7 |
+
import os
|
8 |
+
from dotenv import load_dotenv
|
9 |
+
import numpy as np
|
10 |
+
import pandas as pd
|
11 |
+
import csv
|
12 |
+
import tempfile
|
13 |
+
from tempfile import NamedTemporaryFile
|
14 |
+
import pathlib
|
15 |
+
from pathlib import Path
|
16 |
+
import re
|
17 |
+
from re import sub
|
18 |
+
import matplotlib.pyplot as plt
|
19 |
+
from itertools import product
|
20 |
+
from tqdm import tqdm_notebook, tqdm, trange
|
21 |
+
import time
|
22 |
+
from time import sleep
|
23 |
+
import pretty_errors
|
24 |
+
import seaborn as sns
|
25 |
+
from matplotlib.pyplot import style
|
26 |
+
from rich import print
|
27 |
+
import warnings
|
28 |
+
warnings.filterwarnings('ignore')
|
29 |
+
|
30 |
+
load_dotenv()
|
31 |
+
### 设置openai的API key
|
32 |
+
os.environ["OPENAI_API_KEY"] = os.environ['user_token']
|
33 |
+
openai.api_key = os.environ['user_token']
|
34 |
+
|
35 |
+
##NOTE: 需要注意OpenAI的版本
|
36 |
+
def chatgpt(user_prompt, sys_prompt="You are professional consultant", openai_model="gpt-3.5-turbo-16k"):
|
37 |
+
# print('chatgpt mode starts!')
|
38 |
+
try:
|
39 |
+
openai_client = OpenAI()
|
40 |
+
chatgpt_response = openai_client.chat.completions.create(
|
41 |
+
model=openai_model,
|
42 |
+
messages=[
|
43 |
+
{"role": "system", "content": sys_prompt},
|
44 |
+
{"role": "user", "content": user_prompt},
|
45 |
+
],
|
46 |
+
stream=False,
|
47 |
+
)
|
48 |
+
|
49 |
+
full_response = chatgpt_response.choices[0].message.content
|
50 |
+
print(full_response)
|
51 |
+
except Exception as e:
|
52 |
+
print(e)
|
53 |
+
full_response = "Sorry, I don't have an answer for that yet."
|
54 |
+
|
55 |
+
# return chatgpt_response, full_response
|
56 |
+
return full_response
|
57 |
+
|
58 |
+
# user_prompt = "where is Shanghai?"
|
59 |
+
# system_prompt = "You are a helpful AI assistant."
|
60 |
+
# full_response = chatgpt(user_prompt=user_prompt, sys_prompt=system_prompt)
|
61 |
+
# print(full_response)
|
config.yaml
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
credentials:
|
2 |
+
usernames:
|
3 |
+
joeshi:
|
4 |
+
email: joe.joeshi@gmail.com
|
5 |
+
name: joeshi
|
6 |
+
password: '$2b$12$8Jbjy0Cvq4UnXksw2PUa8.BOmssCExwIS/SrSZX4JwGWu1zJJ5Jxu' # To be replaced with hashed password
|
7 |
+
cindyji:
|
8 |
+
email: joe.joeshi@gmail.com
|
9 |
+
name: cindyji
|
10 |
+
password: '$2b$12$CA3Kc0sL0jVax7Wx0bbC7Op3edhtxlFUJkHS6ABjZCBN/1kbS3yem' # To be replaced with hashed password
|
11 |
+
test:
|
12 |
+
email: joe.joeshi@gmail.com
|
13 |
+
name: test
|
14 |
+
password: '$2b$12$RfaFTOmCII1x7X.U6O9u6OFjTlqYSK88EZy5Yy80nV.uxaxILSmsC' # To be replaced with hashed password, test
|
15 |
+
temp:
|
16 |
+
email: joe.joeshi@gmail.com
|
17 |
+
name: temp
|
18 |
+
password: '$2b$12$AvcADYBmeN77qFQvZ.mIf.fjMzJRgk/HH5OkLxCax6x3NsAQWrHki' # To be replaced with hashed password, test
|
19 |
+
guojing:
|
20 |
+
email: 1234@gmail.com
|
21 |
+
name: guojing
|
22 |
+
password: '$2b$12$NOBKb.j/KJzX1SrN2f9yQunnW3aGZmvK1Km.Cdl70Pmpb.jslRh7m' # To be replaced with hashed password, test
|
23 |
+
chengrui:
|
24 |
+
email: 1234@gmail.com
|
25 |
+
name: chengrui
|
26 |
+
password: '$2b$12$yru/vqM1aNEkG8yFt/3mvuULC8tllGEP0ht.nwuH14SBxvsire7g6' # To be replaced with hashed password, test
|
27 |
+
austins:
|
28 |
+
email: 1234@gmail.com
|
29 |
+
name: austins
|
30 |
+
password: '$2b$12$Sfjuq84o8OXUrAzy945gN.WZBH2vBNW22T7LeZnIS.CmqXrZuKja.' # To be replaced with hashed password, test
|
31 |
+
lhj:
|
32 |
+
email: 1234@gmail.com
|
33 |
+
name: lhj
|
34 |
+
password: '$2b$12$YYt7FgQ.61SJ6U9m0JJUgesMXmYjz1oQG37PlrDA6kh3YIZmG6Aai' # To be replaced with hashed password, test
|
35 |
+
apples:
|
36 |
+
email: 1234@gmail.com
|
37 |
+
name: apples
|
38 |
+
password: '$2b$12$/6kuag4n0De3taSZiyBuPOr7APy3pz1O7Ms/ICZMy1kxwRpH9ucK.' # To be replaced with hashed password, test
|
39 |
+
carriec:
|
40 |
+
email: 1234@gmail.com
|
41 |
+
name: carriec
|
42 |
+
password: '$2b$12$A8gBPYSbDgFgAbr9QGANUeZx6J0jYq56yuesd6FeWDeyTQ0DLURRS' # To be replaced with hashed password, test
|
43 |
+
wuqijun:
|
44 |
+
email: 1234@gmail.com
|
45 |
+
name: wuqijun
|
46 |
+
password: '$2b$12$I8jYTti0r9cajzMbP6wgN.5Dx8mqE89ZFZYE9a0L107JdqzTNWEpu' # To be replaced with hashed password, test
|
47 |
+
sunzhifeng:
|
48 |
+
email: 1234@gmail.com
|
49 |
+
name: sunzhifeng
|
50 |
+
password: '$2b$12$oGvNcCTX/cdgPigUMd.vwekjQoKz4EPg87Nqh7.K/gHoFrKKHdVPi' # To be replaced with hashed password, test
|
51 |
+
pattern:
|
52 |
+
email: 1234@gmail.com
|
53 |
+
name: sunzhifeng
|
54 |
+
password: '$2b$12$uEy0iXQg4LuwTivV7JmcGuWSL.Gn21RY7iD/lNxsPBtT0PGRvjuxi' # To be replaced with hashed password, test
|
55 |
+
cookie:
|
56 |
+
expiry_days: 30
|
57 |
+
key: random_signature_key # Must be string
|
58 |
+
name: random_cookie_name
|
59 |
+
preauthorized:
|
60 |
+
emails:
|
61 |
+
- joe.joeshi@gmail.com
|
llm_icon.png
ADDED
![]() |
requirements.txt
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Markdown==3.1.1
|
2 |
+
matplotlib==3.7.2
|
3 |
+
md_mermaid==0.1.1
|
4 |
+
numpy==1.26.4
|
5 |
+
openai==1.14.3
|
6 |
+
pandas==2.2.1
|
7 |
+
pretty_errors==1.2.25
|
8 |
+
python-dotenv==1.0.1
|
9 |
+
pytz==2024.1
|
10 |
+
Requests==2.31.0
|
11 |
+
rich==13.7.1
|
12 |
+
seaborn==0.13.2
|
13 |
+
streamlit==1.32.2
|
14 |
+
streamlit_ext==0.1.10
|
15 |
+
tqdm==4.66.2
|