File size: 24,627 Bytes
5255efb e023114 5255efb e023114 5255efb e023114 5255efb e023114 2aef356 686b2e4 e023114 5255efb e023114 5255efb e023114 5255efb e023114 5255efb |
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 |
'''
1. 大模型以Qwen API形式提供。
1. 重塑了Qwen作为大语言模型做Text2SQL的提示词:
sys_prompt = """
1. 你是一个将文字转换成SQL语句的人工智能。
2. 你需要注意:你只需要用纯文本回复代码的内容,即你不允许回复代码以外的任何信息。
3. SQL变量默认是中文,而且只能从如下的名称列表中选择,你不可以使用这些名字以外的变量名:"长度","宽度","价格","产品ID","比率","类别","*"
4. 你不能写IF, THEN的SQL语句,需要使用CASE。
5. 我需要你转换的文字如下:"""
total_prompt = sys_prompt + "在数据表格table01中," + prompt
'''
##TODO: 2. 账号功能。
import time
import os
import pandas as pd
import streamlit as st
from code_editor import code_editor
import streamlit_authenticator as stauth
# from utils.setup import setup_connexion, setup_session_state
# from utils.vanna_calls import (
# generate_questions_cached,
# run_sql_cached,
# generate_plotly_code_cached,
# generate_plot_cached,
# generate_followup_cached,
# )
# import chatsql003 ### 本地ChatGLT 版本。
import chatsql004 ###Qwen API 版本。
import sql_command
# from streamlit_pandas_profiling import st_profile_report
import dashscope
from dotenv import load_dotenv
load_dotenv()
### 设置openai的API key
dashscope.api_key = os.environ['dashscope_api_key']
st.set_page_config(layout="wide", page_icon="🧩", page_title="本地化国产大模型数据库查询演示")
# setup_connexion()
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
## 原始的控制面板
# st.sidebar.title("大模型控制面板")
# st.sidebar.checkbox("Show SQL", value=True, key="show_sql")
# st.sidebar.checkbox("Show Table", value=True, key="show_table")
# st.sidebar.checkbox("Show Plotly Code", value=True, key="show_plotly_code")
# st.sidebar.checkbox("Show Chart", value=True, key="show_chart")
# st.sidebar.checkbox("Show Follow-up Questions", value=True, key="show_followup")
# st.sidebar.button("清除记录,重启一轮新对话", on_click=setup_session_state, use_container_width=True, type='primary')
st.title("本地化国产大模型数据库查询演示")
# st.title("大语言模型SQL数据库查询中心")
# st.info("声明:内容由人工智能生成,仅供参考。如果您本人使用或对外传播本服务生成的输出,您应当主动核查输出内容的真实性、准确性,避免传播虚假信息。") ## 颜色比较明显。
st.markdown("_声明:内容由人工智能生成,仅供参考。如果您本人使用或对外传播本服务生成的输出,您应当主动核查输出内容的真实性、准确性,避免传播虚假信息。_")
### 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')
print('登录的用户:', username)
### Streamlit Sidebar 左侧工具栏
# st.sidebar.write(st.session_state)
if authentication_status:
with st.sidebar:
st.markdown(
"""
<style>
[data-testid="stSidebar"][aria-expanded="true"]{
min-width: 500px;
max-width: 500px;
}
""",
unsafe_allow_html=True,
)
# st.header(f'**大语言模型专家系统工作设定区**')
st.header(f'**欢迎 **{username}** 使用本系统** ')
st.write(f'_Large Language Model Expert System Working Environment_')
# st.write(f'_Welcome and Hope U Enjoy Staying Here_')
authenticator.logout('登出', 'sidebar')
### siderbar的题目。
### siderbar的题目。
# st.header(f'**大语言模型专家系统工作设定区**')
# st.header(f'**欢迎 **{username}** 使用本系统** ') ## 用户登录显示。
st.sidebar.button("清除记录,重启一轮新对话", on_click=clear_all, use_container_width=True, type='primary')
# st.sidebar.button("清除记录,重启一轮新对话", on_click=setup_session_state, use_container_width=True, type='primary')
### 展示当前数据库
# st.markdown("#### 当前数据库中的数据:")
with st.expander("#### 当前数据库中的数据", expanded=True):
my_db = pd.read_sql_table('table01', 'sqlite:///myexcelDB.db')
st.dataframe(my_db, width=400)
## 在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("""* 简介
本系统使用大模型技术,将自然语言描述转换为SQL查询语句。用户可以输入自然语言问题,系统会自动生成相应的SQL语句,并返回查询结果。
* 使用步骤
在文本框中输入您的自然语言问题。
系统会自动生成相应的SQL语句,并显示在下方。
点击“满意,请执行语句”选项,可查看查询结果。点击”不满意,需要改正语句“可以手动修改SQL语句。
* 注意事项
本系统仍在开发中,可能会存在一些错误或不准确的地方。
自然语言描述越清晰,生成的SQL语句越准确。
系统支持的SQL语法有限,请尽量使用简单易懂的语法。
""")
# with st.text(body="说明"):
# st.markdown("""在构建大语言模型本地知识库问答系统时,需要注意以下几点:
# LLM的选择:LLM的选择应根据系统的应用场景和需求进行。对于需要处理通用问题的系统,可以选择通用LLM;对于需要处理特定领域问题的系统,可以选择针对该领域进行微调的LLM。
# 本地知识库的构建:本地知识库应包含系统所需的所有知识。知识的组织方式应便于LLM的访问和处理。
# 系统的评估:系统应进行充分的评估,以确保其能够准确地回答用户问题。
# 大语言模型本地知识库问答系统具有以下优势:
# 准确性:LLM和本地知识库的结合可以提高系统的准确性。
# 全面性:LLM和本地知识库的结合可以使系统能够回答更广泛的问题。
# 效率:LLM可以快速生成候选答案,而本地知识库可以快速评估候选答案的准确性。
# """)
# with st.text(body="说明"):
# st.markdown(
# "* “数据分析模式”暂时只支持1000个单元格以内的数据分析,单元格中的内容不支持中文数据(表头也尽量不使用中文)。一般运行时间在1至10分钟左右,期间需要保持网络畅通。")
# with st.text(body="说明"):
# st.markdown("* “数据分析模式”推荐上传csv格式的文件,部分Excel文件容易出现数据不兼容的情况。")
## 大模型参数
# 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.markdown("#### Prompt提示词参考资料")
# # with st.expander(label="**大语言模型基础提示词Prompt示例**", expanded=False):
# st.code(
# body="继续用中文写一篇关于 [文章主题] 的文章,以下列句子开头:[文章开头]。", language='plaintext')
# st.code(body="将以下文字概括为 100 个字,使其易于阅读和理解。避免使用复杂的句子结构或技术术语。",
# language='plaintext')
# st.code(body="给我出一个迪奥2023春季发布会活动策划。", language='plaintext')
# st.code(body="帮我按照正式会议结构写一个会邀:主题是xx手机游戏立项会议。", language='plaintext')
# st.code(body="帮我写一个车内健康监测全场景落地的项目计划,用表格。", language='plaintext')
# st.code(
# body="同时掷两枚质地均匀的骰子,则两枚骰子向上的点数之和为 7 的概率是多少。", language='plaintext')
# st.code(body="写一篇产品经理的演讲稿,注意使用以下词汇: 赋能,抓手,中台,闭环,落地,漏斗,沉淀,给到,同步,对齐,对标,迭代,拉通,打通,升级,交付,聚焦,倒逼,复盘,梳理,方案,联动,透传,咬合,洞察,渗透,兜底,解耦,耦合,复用,拆解。", language='plaintext')
# with st.expander(label="**数据分析模式的专用提示词Prompt示例**", expanded=False):
# # with st.subheader(body="提示词Prompt"):
# st.code(body="分析此数据集并绘制一些'有趣的图表'。", language='python')
# st.code(
# body="对于这个文件中的数据,你需要要找出[X,Y]数据之间的寻找'相关性'。", language='python')
# st.code(body="对于这个文件中的[xxx]数据给我一个'整体的分析'。", language='python')
# st.code(body="对于[xxx]数据给我一个'直方图',提供图表,并给出分析结果。", language='python')
# st.code(body="对于[xxx]数据给我一个'小提琴图',并给出分析结果。", language='python')
# st.code(
# body="对于[X,Y,Z]数据在一个'分布散点图 (stripplot)',所有的数据在一张图上展现, 并给出分析结果。", language='python')
# st.code(body="对于[X,Y]数据,进行'T检验',你需要展示图表,并给出分析结果。",
# language='python')
# st.code(body="对于[X,Y]数据给我一个3个类别的'聚类分析',并给出分析结果。",
# language='python')
with tab_4:
st.text_area(label='系统角色设定', value='你是一个人工智能,你需要回答我提出的问题,或者完成我交代的任务。你需要使用我提问的语言(如中文、英文)来回答。', height=200, label_visibility='hidden')
myavatar = "./2D.png"
def set_question(question):
st.session_state["my_question"] = question
assistant_message_suggested = st.chat_message(
"assistant", avatar=myavatar
)
##! 注意在填写列名时,最佳的选择是使用双引号将名字框出来。否则LLM会不认识。
if assistant_message_suggested.button("点击这里可以查看参考问题示例 ℹ️"):
questions = [
'你查一下长度超过10的数据有哪些?',
'你告诉我长度超过30且宽度超过10的数据有哪些?',
'宽度超过20且价格超过25的数据有哪些?',
'”长度“超过10且”宽度“超过15且”类别“是”甲“的数据有哪些?',
'长度超过10以上的价格的总和是多少?',
'长度排名前三的产品ID和价格和长度?',
]
st.session_state["my_question"] = None
# questions = generate_questions_cached() ## orignal.
for i, question in enumerate(questions):
time.sleep(0.05)
button = st.button(
question,
on_click=set_question,
args=(question,),
)
my_question = st.session_state.get("my_question", default=None)
if my_question is None:
my_question = st.chat_input(
"请在这里提交您的查询问题",
)
if my_question:
st.session_state["my_question"] = my_question
user_message = st.chat_message("user")
user_message.write(f"{my_question}")
# sql = generate_sql_cached(question=my_question) ## original. 核心函数。用ChatGPT输出SQL语句。
# sql = chatsql003.main(prompt=my_question) ## 通过本地LLM输出SQL语句。
sql = chatsql004.main(prompt=my_question) ## 通过本地LLM输出SQL语句。
if sql:
if st.session_state.get("show_sql", True):
assistant_message_sql = st.chat_message(
"assistant", avatar=myavatar
)
assistant_message_sql.code(sql, language="sql", line_numbers=True)
user_message_sql_check = st.chat_message("user")
user_message_sql_check.write(f"您是否满意上面的SQL查询语句答案?")
with user_message_sql_check:
happy_sql = st.radio(
# "Happy",
label="您的反馈:",
options=["未决定", "满意,请执行语句", "不满意,需要改正语句"], ## 去掉第一个happy选项。
# options=["", "yes", "no"], ## original。
key="radio_sql",
index=0,
horizontal=True,
label_visibility='visible',
)
# ## 非original。后期添加内容。Working.
if happy_sql == "未决定":
df = None
st.session_state["df"] = None
if happy_sql == "不满意,需要改正语句":
st.warning(
"请您手动修正SQL语句,按Shift + Enter提交"
)
sql_response = code_editor(sql, lang="sql")
fixed_sql_query = sql_response["text"]
if fixed_sql_query != "":
# df = run_sql_cached(sql=fixed_sql_query) ## original. 核心函数。
df = sql_command.llm_query(sql_command=fixed_sql_query)
else:
df = None
elif happy_sql == "满意,请执行语句":
# df = run_sql_cached(sql=sql) ## original. 核心函数。
df = sql_command.llm_query(sql_command=sql) ## working.
else:
df = None
if df is not None:
st.session_state["df"] = df
if st.session_state.get("df") is not None:
## 显示查询的结果汇总信息
# with st.container():
query_info_describe = st.chat_message("assistant", avatar=myavatar)
if df is not None:
with query_info_describe:
metric_col1, metric_col2, metric_col3, metric_col4 = st.columns(4)
metric_col1.metric(label='查询结果中的行数', value=f"{df.shape[0]} 行", delta=None)
metric_col2.metric(label='查询结果中的列数', value=f"{df.shape[1]} 列", delta=None)
metric_col3.metric(label='查询结果中的单元格数', value=f"{df.size} 个", delta=None)
metric_col4.metric(label='查询结果中的缺失值', value=f"{df.isnull().sum().sum()} 个", delta=None)
if st.session_state.get("show_table", True):
df = st.session_state.get("df")
assistant_message_table = st.chat_message(
"assistant",
avatar=myavatar
)
### 目前是最佳显示方式
if len(df) > 10:
assistant_message_table.markdown("**查询结果较多,当前只显示前10行数据**") ##TODO: 看看是否有其他更好的显示方式。
assistant_message_table.dataframe(df.head(10), hide_index=True)
# assistant_message_table.dataframe(df.head(100), use_container_width=True)
else:
assistant_message_table.dataframe(df, hide_index=True)
# assistant_message_table.dataframe(df,use_container_width=True)
## 以下是其他datafram的显示方式,均不理想。
# st.dataframe(df, use_container_width=True, height=100)
## streamlit AwesomeTable, Dark模式下显示有问题。可以在sidebar上显示内容。
# from awesome_table import AwesomeTable
# AwesomeTable(df,show_order=True, show_search=True, show_search_order_in_sidebar=True)
# # AwesomeTable(pd.json_normalize(df))
# ## 展示图形
# # code = generate_plotly_code_cached(question=my_question, sql=sql, df=df) ## orignal. 用LLM来构建统计图表:https://github.com/vanna-ai/vanna/blob/main/src/vanna/mistral/mistral.py
# if st.session_state.get("show_plotly_code", False):
# assistant_message_plotly_code = st.chat_message(
# "assistant",
# avatar=myavatar,
# )
# assistant_message_plotly_code.code(
# code, language="python", line_numbers=True
# )
# user_message_plotly_check = st.chat_message("user")
# user_message_plotly_check.write(
# f"Are you happy with the generated Plotly code?"
# )
# with user_message_plotly_check:
# happy_plotly = st.radio(
# "Happy",
# options=["", "yes", "no"],
# key="radio_plotly",
# index=0,
# )
# if happy_plotly == "no":
# st.warning(
# "Please fix the generated Python code. Once you're done hit Shift + Enter to submit"
# )
# python_code_response = code_editor(code, lang="python")
# code = python_code_response["text"]
# elif happy_plotly == "":
# code = None
# if code is not None and code != "":
# if st.session_state.get("show_chart", True):
# assistant_message_chart = st.chat_message(
# "assistant",
# avatar=myavatar,
# )
# fig = generate_plot_cached(code=code, df=df)
# if fig is not None:
# assistant_message_chart.plotly_chart(fig)
# else:
# assistant_message_chart.error("I couldn't generate a chart")
## Data Visualization: Ydata_profiling (pandas_profiling)
# from ydata_profiling import ProfileReport
# pr = ProfileReport(df)
# # with st.expander(label='**数据汇总信息**', expanded=False):
# with st.container():
# st_profile_report(pr)
# # st.stop()
## 数据可视化内容,高级版。
## pywalker: https://github.com/Kanaries/pygwalker/tree/main
user_message_plot_check = st.chat_message("user")
user_message_plot_check.write(f"您是否希望基于上述查询结果进行数据可视化?")
with user_message_plot_check:
happy_plot = st.radio(
# "Happy",
label="您的反馈:",
options=["未决定", "是,需要进行数据可视化", "否,不需要进行数据可视化"], ## 去掉第一个happy选项。
# options=["", "yes", "no"], ## original。
key="radio_plot",
index=0,
horizontal=True,
label_visibility='visible',
)
if happy_plot == "是,需要进行数据可视化":
import pygwalker as pyg
import streamlit.components.v1 as components
import streamlit as st
from pygwalker.api.streamlit import init_streamlit_comm, get_streamlit_html
# Initialize pygwalker communication
init_streamlit_comm()
# When using `use_kernel_calc=True`, you should cache your pygwalker html, if you don't want your memory to explode
@st.cache_resource
def get_pyg_html(df: pd.DataFrame) -> str:
# When you need to publish your application, you need set `debug=False`,prevent other users to write your config file.
# If you want to use feature of saving chart config, set `debug=True`
html = get_streamlit_html(df, spec="./gw0.json", use_kernel_calc=True, debug=False)
return html
# walker = pyg.walk(df)
components.html(get_pyg_html(df), width=1200, height=800, scrolling=True)
### streamlit echarts: https://github.com/andfanilo/streamlit-echarts
# from streamlit_echarts import st_echarts
# from streamlit_echarts import st_pyecharts
# st_pyecharts(df)
### Follow-up questions session.
# if st.session_state.get("show_followup", True):
# assistant_message_followup = st.chat_message(
# "assistant",
# avatar=myavatar,
# )
# followup_questions = generate_followup_cached(
# question=my_question, df=df
# )
# st.session_state["df"] = None
# if len(followup_questions) > 0:
# assistant_message_followup.text(
# "Here are some possible follow-up questions"
# )
# # Print the first 5 follow-up questions
# for question in followup_questions[:5]:
# time.sleep(0.05)
# assistant_message_followup.write(question)
else:
assistant_message_error = st.chat_message(
"assistant", avatar=myavatar
)
assistant_message_error.error("我无法回答您的问题,请重新提问,谢谢!")
|