Streamlit 教程 Streamlit 是一个专门针对机器学习和数据科学团队的应用开发框架,无需前端经验, 几行代码就能构建出一个精美的在线 app 应用。使用 Streamlit 构建交互式应用程序,让人工智能工程师和数据科学家可以更轻松地将他们的模型展示给其他人。
前段时间打语言模型爆火的时候,很多优秀的开源项目都是使用 Streamlit 构建的, 比如清华开源的 ChatGLM,以及 15K star 的明星项目 LangChain-Chatchat (Langchain-ChatGLM)。
如果你对人工智能感兴趣,希望构建一个可交互的应用,但是又不会 Web 编程,那太好了,今天这篇文章就带你学会使用 Streamlit 构建人工智能应用的一切。
大纲
今天先后介绍了 Streamlit 安装、运行、按钮、万能 Write、图表、布局、表单、数据展示,以及一个仿 ChatGPT 的示例。
安装
还是先安装好 conda ,然后创建一个 conda 环境来管理所有 Python 库依赖,运行今天 streamlit 代码。
使用 Python 3.9 版本创建一个新的环境:
conda create -n streamlit python=3.9
激活上一步刚创建好的名为 streamlit 的 conda 环境:
conda activate streamlit
安装 Streamlit 库
激活环境之后就是时候安装 streamlit 库了:
pip install streamlit
启动示例 Streamlit 应用
用如下指令来启动示例 Streamlit 应用:
streamlit hello
看看效果是不是还不错:
手写第一个应用
几乎所有语言框架的入门应用都是 Hello World,那我们看看 Streamlit 的 Hello World 怎么写。
新建一个文件 tour.py,然后在里面输入下面代码:
import streamlit as st
st.write('你好世界!')
使用 streamlit run tour.py 来运行,运行成功会自动打开浏览器:
重新运行
Streamlit 有一个很棒的特性,就是当我们修改代码之后,不需要重新启动服务,Streamlit 会检测到代码变化并重新执行。重新刷新浏览器,或者在界面上点击 Rerun 即可。
我们增加一行代码:
st.write('来自未来的某某某!')
可以看到网页上出现了提示, 文件发生变化,以及 Rerun 按钮,点击重新运行即可看到新的界面:
演示折叠组件
因为此次涉及的内容较多,为了更好的演示效果,我们使用 Expander 组件来把所有的章节组织起来:
# 设置内容宽度和网页标题
st.set_page_config(layout="wide", page_title='数翼 Streamlit 教程')
# 网页内标题
st.title('数翼 Streamlit 教程')
# 展开的变量
expanded = True
title = "Hello World"
with st.expander(title, expanded):
st.write('你好世界!')
st.write('来自未来的某某某!')
看看效果,我们刚刚的内容被一个手风琴组件包裹了起来,可以点击标题折叠和展开:
按钮
接下来我们看看按钮怎么使用,在 title = "Hello World" 之上增加代码。
expanded = False 这一行关掉上一个示例的代码:
title = "按钮示例"
with st.expander(title, expanded):
expanded = False
st.header(title)
if st.button('问个好'):
st.write('你好,大爷')
else:
st.write('啥也不是')
title = "Hello World"
...
我们看看效果:
• 没有点击按钮的时候输出:
啥也不是• 点击按钮输出:
你好,大爷
代码解释
上面代码展示了如何处理按钮逻辑,直接 if 判断是否点击了按钮,是不是很简单。
if st.button('问个好')
st.write('你好,大爷')
万能 write 方法
Steamlit 提供了一个很强大的 write 方法,可以写文本、数字、表格、图片、图表。
代码如下:
title = "万能写方法(write)"
with st.expander(title, expanded):
expanded = False
st.header(title, divider='rainbow')
st.subheader('字符串')
st.write('你好, *老王!* :sunglasses:')
st.subheader('数字')
st.write(1234)
st.subheader('表格')
df = pd.DataFrame({
'排名': [1, 2, 3, 4],
'速度': [10, 20, 30, 40]
})
st.write(df)
st.subheader('文本+表格')
st.write('这是一个数据表格:', df, '上面是一个数据表格.')
st.subheader('可视化图表')
df2 = pd.DataFrame(
np.random.randn(200, 3),
columns=['a', 'b', 'c'])
c = alt.Chart(df2).mark_circle().encode(
x='a', y='b', size='c', color='c', tooltip=['a', 'b', 'c'])
st.write(c)
看看效果:
代码解释
使用 divider='rainbow' 参数在标题下面增加一个彩虹线:
st.header(title, divider='rainbow')
滑条组件
接下来看看滑条组件怎么用。
默认
默认的滑条组件:
from datetime import time, datetime
st.subheader('默认')
age = st.slider('你多大了?', 0, 130, 25)
st.write("我今年", age, '岁')
使用滑条来关联输出:
范围
范围选择:
st.subheader('范围')
values = st.slider(
'请选择你可以接受的价格范围',
0.0, 100.0, (25.0, 75.0))
st.write('我可以接受的价格是:', values)
使用范围组件来选择价格范围:
时间范围
来选择下你的摸鱼时间吧:
st.subheader('时间范围')
appointment = st.slider(
"请选择你的摸鱼时间:",
value=(time(11, 30), time(12, 45)))
st.write("你可以在下面时间摸鱼:", appointment)
日期范围
当然也可以选择日期:
st.subheader('日期时间')
start_time = st.slider(
"选择你的项目开始时间?",
value=datetime(2023, 9, 1, 9, 30),
format="MM/DD/YY - hh:mm")
st.write("开始时间:", start_time)
图表
接下来我们来看看人工智能和数据科学家最常用的组件:图表组件。
首先定义一个数据源
chart_data = pd.DataFrame(
np.random.randn(20, 3),
columns=['a', 'b', 'c'])
画一个线图
st.subheader('线')
col1, col2 = st.columns(2)
st.line_chart(chart_data)
区域图
st.subheader('区域')
st.area_chart(chart_data)
柱图
st.subheader('柱')
st.bar_chart(chart_data)
使用 matplotlib 工具
st.subheader('使用 matplotlib')
import matplotlib.pyplot as plt
arr = np.random.normal(1, 1, size=100)
fig, ax = plt.subplots()
ax.hist(arr, bins=20)
st.pyplot(fig)
使用 altair 工具
st.subheader('使用 altair')
c = alt.Chart(chart_data).mark_circle().encode(
x='a', y='b', size='c', color='c', tooltip=['a', 'b', 'c'])
st.altair_chart(c, use_container_width=True)
使用 vega lite 绘图
st.subheader('使用 vega lite')
st.vega_lite_chart(chart_data, {
'mark': {'type': 'circle', 'tooltip': True},
'encoding': {
'x': {'field': 'a', 'type': 'quantitative'},
'y': {'field': 'b', 'type': 'quantitative'},
'size': {'field': 'c', 'type': 'quantitative'},
'color': {'field': 'c', 'type': 'quantitative'},
},
})
使用 plotly
st.subheader('使用 plotly')
import plotly.figure_factory as ff
# Add histogram data
x1 = np.random.randn(200) - 2
x2 = np.random.randn(200)
x3 = np.random.randn(200) + 2
# Group data together
hist_data = [x1, x2, x3]
group_labels = ['Group 1', 'Group 2', 'Group 3']
# Create distplot with custom bin_size
fig = ff.create_distplot(
hist_data, group_labels, bin_size=[.1, .25, .5])
# Plot!
st.plotly_chart(fig, use_container_width=True)
使用 pydeck 绘图
st.subheader('使用 pydeck')
import pydeck as pdk
chart_data = pd.DataFrame(
np.random.randn(1000, 2) / [50, 50] + [37.76, -122.4],
columns=['lat', 'lon'])
st.pydeck_chart(pdk.Deck(
map_style=None,
initial_view_state=pdk.ViewState(
latitude=37.76,
longitude=-122.4,
zoom=11,
pitch=50,
),
layers=[
pdk.Layer(
'HexagonLayer',
data=chart_data,
get_position='[lon, lat]',
radius=200,
elevation_scale=4,
elevation_range=[0, 1000],
pickable=True,
extruded=True,
),
pdk.Layer(
'ScatterplotLayer',
data=chart_data,
get_position='[lon, lat]',
get_color='[200, 30, 0, 160]',
get_radius=200,
),
],
))
绘制地图
st.subheader('地图')
df = pd.DataFrame(
np.random.randn(1000, 2) / [50, 50] + [37.76, -122.4],
columns=['lat', 'lon'])
st.map(df)
布局
接下来是写一个界面必要的功能:『布局』。
Streamlit 提供了简单但是实用的布局方案:
• 折叠
• 列组件
• Tab组件
折叠
折叠我们前面展示过了,不过需要注意一点: expander 组件不支持嵌套。
列布局
我们使用三列来布局:
st.subheader('个人信息分栏展示')
col1, col2, col3 = st.columns(3)
with col1:
st.write('请输入你的 **昵称**!')
with col2:
st.write('请选择你的心情')
with col3:
st.write('请选择你的目标')
自定义列宽
我们使用 2:3:5 的宽度来定义三列:
st.subheader('自定义宽度列')
col1, col2, col3 = st.columns( [2, 3, 5])
with col1:
st.write('请输入你的 **昵称**!')
with col2:
st.write('请选择你的心情')
with col3:
st.write('请选择你的目标')
Tab页布局
定义三个 Tab 页:
st.subheader('Tab 布局')
tab1, tab2, tab3 = st.tabs(["兴趣爱好", "工作经历", "作品连接"])
with tab1:
st.header(":rainbow[我的兴趣爱好。。。]")
with tab2:
st.header(":rainbow[我的工作经历。。。]")
with tab3:
st.header(":rainbow[我的作品连接。。。]")
侧边栏
使用侧边栏方式一个表单和三个输入框,看看完整页面。
表单的具体用法下个小节讲。
st.sidebar.header('个性设置')
user_name = st.sidebar.text_input('你的昵称')
user_emoji = st.sidebar.selectbox('当前的心情', ['', '😄', '😆', '😊', '😍', '😴', '😕', '😱'])
user_food = st.sidebar.selectbox('你今天的目标是什么?',
['', '学会 Streamlit', '构建一个人工智能应用'])
表单
先看看按钮、选项、下拉组件:
以及文本、数字、上传组件:
col1, col2, col3 = st.columns(3)
with col1:
st.subheader('按钮')
if st.button('付款', type='primary'):
st.write('付款成功!')
else:
st.write('请付款')
with col2:
st.subheader('下载按钮')
@st.cache_resource
def convert_df(df):
return df.to_csv().encode('utf-8')
chart_data = pd.DataFrame(
np.random.randn(20, 3),
columns=['a', 'b', 'c'])
csv = convert_df(chart_data)
st.download_button(
label="导出 Excel",
data=csv,
file_name='年度报表.csv',
mime='text/csv',
)
with col3:
st.subheader('复选框')
agree = st.checkbox('自动登录')
if agree:
st.write('我们下次将为您自动登录')
col1, col2, col3 = st.columns(3)
with col1:
st.subheader('开关')
on = st.toggle('启用GPT4')
if on:
st.write('已经为您启动 GPT4')
with col2:
st.subheader('单选')
llm = st.radio(
"请选择你要使用的大语言模型",
[":rainbow[ChatGPT]", "Claude 2", "Bard"],
captions=["来自 OpenAI", "来自 Anthropic", "来自 Google"])
if llm == ':rainbow[ChatGPT]':
st.write('你选择了 ChatGPT')
else:
st.write("你选择了其他")
with col3:
st.subheader('下拉框')
option = st.selectbox(
'选择您的付费方式',
('支付宝', '微信', '银行卡'))
st.write('你选择了:', option)
st.subheader('多选下拉')
options = st.multiselect(
'请选择你要启用的工具',
['天气预报', '项目管理', '编程导师', '文章助手'],
['项目管理', '编程导师'])
表单
最后看一下表单组件。
需要注意的是,表单内的数据变化只能通过提交按钮拿到。
st.subheader('表单')
with st.form('myform'):
st.text_input('Name')
st.text_input('Password')
submitted = st.form_submit_button('登录')
提示
Streamlit 提供了简单有效的提示:
使用也很简单。
col1, col2, col3 = st.columns(3)
with col1:
st.subheader('效果')
if st.button('气球'):
st.balloons()
if st.button('下雪'):
st.snow()
with col2:
st.subheader('提示')
st.error('错误提示', icon="🚨")
st.warning('warning 提示', icon="⚠️")
st.info('info 提示', icon="ℹ️")
st.success('成功!', icon="✅")
with col3:
st.subheader('异常')
e = RuntimeError('This is an exception of type RuntimeError')
st.exception(e)
col1, col2, col3 = st.columns(3)
with col1:
st.subheader('进度条')
my_bar = st.progress(100)
def start():
my_bar.progress(0)
time.sleep(1)
for percent_complete in range(100):
time.sleep(0.01)
my_bar.progress(percent_complete + 1)
if st.button('重新开始'):
start()
with col2:
st.subheader('进度圈')
with st.spinner('Wait for it...'):
time.sleep(1)
st.success('Done!')
with col3:
st.subheader('提示')
if st.button('提示'):
st.toast('耶!', icon='🎉')
time.sleep(0.3)
st.toast('耶!', icon='🎉')
time.sleep(0.3)
st.toast('耶!', icon='🎉')
time.sleep(0.3)
st.toast('耶!', icon='🎉')
数据展示
代码较多,放在了 Github 上,大家文末查看。
综合示例
看到现在,大家估计都看累了,我们用已经学到的知识来创建一个仿 ChatGPT 的应用吧,先看效果。
Github 代码
https://github.com/iDigitalWings/shuyi-streamlit-tour[1]
相关资源推荐
• Streamlit 官网[2]
• Steamlit 组件库[3]
• 官方文档可以当字典去查[4]
引用链接
[1]: https://github.com/iDigitalWings/shuyi-streamlit-tour[2] Streamlit 官网: https://streamlit.io/[3] Steamlit 组件库: https://streamlit.io/components[4] 官方文档可以当字典去查: https://docs.streamlit.io/
--- END ---

