深圳信用网官网运营seo是什么意思
Python实战进阶 No.41: 使用 Streamlit 快速构建 ML 应用
摘要
Streamlit 是一个专为数据科学家和机器学习工程师设计的开源框架,它允许您在几分钟内创建精美的交互式应用程序。本文将介绍 Streamlit 的核心功能,并通过两个实战案例展示如何构建基于 ChatGPT API 的聊天助手以及结合 EasyOCR 的 AI 家庭教师应用。无论您是想快速展示机器学习模型的效果,还是为非技术用户提供友好的交互界面,Streamlit 都是一个理想的选择。
核心概念和知识点
Streamlit 的基本组件与布局
Streamlit 提供了丰富的组件,使您能够轻松创建交互式界面:
- 文本元素:
st.title()
,st.header()
,st.subheader()
,st.text()
,st.markdown()
- 输入组件:
st.text_input()
,st.number_input()
,st.slider()
,st.selectbox()
- 媒体元素:
st.image()
,st.audio()
,st.video()
- 布局组件:
st.sidebar
,st.columns()
,st.expander()
- 状态组件:
st.progress()
,st.spinner()
,st.success()
,st.error()
Streamlit 采用自上而下的布局方式,代码的执行顺序决定了界面元素的排列顺序。
import streamlit as stst.title("我的第一个Streamlit应用")
st.header("这是一个标题")
st.subheader("这是一个子标题")# 侧边栏
with st.sidebar:st.header("侧边栏")option = st.selectbox("选择一个选项", ["选项1", "选项2", "选项3"])# 列布局
col1, col2 = st.columns(2)
with col1:st.write("这是第一列")st.button("点击我")
with col2:st.write("这是第二列")st.checkbox("勾选我")
数据可视化与模型集成
Streamlit 支持多种数据可视化库,包括 Matplotlib、Plotly、Altair 等,使数据展示变得简单直观:
import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly.express as px# 创建示例数据
data = pd.DataFrame({'日期': pd.date_range('20230101', periods=100),'值': np.random.randn(100).cumsum()
})# Matplotlib 可视化
st.subheader("Matplotlib 图表")
fig, ax = plt.subplots()
ax.plot(data['日期'], data['值'])
ax.set_title("随机数据趋势")
st.pyplot(fig)# Plotly 可视化
st.subheader("Plotly 图表")
fig = px.line(data, x='日期', y='值', title="交互式数据趋势")
st.plotly_chart(fig)
对于机器学习模型的集成,Streamlit 提供了简单的方式来加载模型并处理用户输入:
import streamlit as st
import joblib
import pandas as pd# 加载预训练模型(示例)
@st.cache_resource
def load_model():return joblib.load('model.pkl')model = load_model()# 用户输入
st.header("预测界面")
feature1 = st.slider("特征1", 0.0, 10.0, 5.0)
feature2 = st.slider("特征2", 0.0, 10.0, 5.0)# 预测
if st.button("预测"):input_data = pd.DataFrame([[feature1, feature2]], columns=['特征1', '特征2'])prediction = model.predict(input_data)st.success(f"预测结果: {prediction[0]}")
应用部署与分享
Streamlit 应用可以通过多种方式部署和分享:
- 本地运行:
streamlit run app.py
- Streamlit Cloud:免费托管平台,直接连接到 GitHub 仓库
- Docker 容器化:便于在任何环境中部署
- 云服务提供商:如 AWS、GCP、Azure 等
部署示例(使用 Streamlit Cloud):
- 将代码推送到 GitHub 仓库
- 访问 Streamlit Cloud
- 连接您的 GitHub 账户并选择仓库
- 点击部署
实战案例
案例一:基于 ChatGPT API 的聊天助手
让我们构建一个简单但功能完整的 ChatGPT 聊天助手:
import streamlit as st
import openai
import time# 设置页面配置
st.set_page_config(page_title="ChatGPT 助手", page_icon="💬", layout="wide")# 初始化会话状态
if "messages" not in st.session_state:st.session_state.messages = []# 设置 OpenAI API 密钥
openai.api_key = st.secrets["openai_api_key"] # 在Streamlit Cloud中设置密钥# 页面标题
st.title("💬 ChatGPT 智能助手")
st.markdown("这是一个基于 ChatGPT API 的智能聊天助手,可以回答您的各种问题。")# 侧边栏配置
with st.sidebar:st.header("设置")model = st.selectbox("选择模型", ["gpt-3.5-turbo", "gpt-4"])temperature = st.slider("创造性 (Temperature)", min_value=0.0, max_value=1.0, value=0.7, step=0.1)st.header("会话")if st.button("清空会话"):st.session_state.messages = []st.experimental_rerun()# 显示聊天历史
for message in st.session_state.messages:with st.chat_message(message["role"]):st.markdown(message["content"])# 用户输入
prompt = st.chat_input("请输入您的问题...")# 处理用户输入
if prompt:# 添加用户消息到历史st.session_state.messages.append({"role": "user", "content": prompt})# 显示用户消息with st.chat_message("user"):st.markdown(prompt)# 显示助手消息(带加载动画)with st.chat_message("assistant"):message_placeholder = st.empty()full_response = ""# 调用 OpenAI APItry:response = openai.ChatCompletion.create(model=model,messages=[{"role": m["role"], "content": m["content"]} for m in st.session_state.messages],temperature=temperature,stream=True)# 模拟打字效果for chunk in response:if chunk.choices and chunk.choices[0].delta.get("content"):content = chunk.choices[0].delta.contentfull_response += contentmessage_placeholder.markdown(full_response + "▌")time.sleep(0.01)message_placeholder.markdown(full_response)# 添加助手回复到历史st.session_state.messages.append({"role": "assistant", "content": full_response})except Exception as e:st.error(f"发生错误: {str(e)}")
运行效果:
- 用户可以在输入框中输入问题
- ChatGPT 会实时生成回答,并显示打字效果
- 聊天历史会被保存,用户可以随时清空会话
- 侧边栏允许用户调整模型和创造性参数
案例二:基于 EasyOCR 和 Streamlit 的 AI 家庭教师
这个应用将结合 EasyOCR 进行图像文字识别,并使用 ChatGPT 回答关于识别内容的问题:
import streamlit as st
import easyocr
import numpy as np
import cv2
import openai
import tempfile
import os
from PIL import Image# 设置页面配置
st.set_page_config(page_title="AI 家庭教师", page_icon="🧠", layout="wide")# 初始化 OpenAI API
openai.api_key = st.secrets["openai_api_key"]# 初始化 EasyOCR
@st.cache_resource
def load_ocr_reader():return easyocr.Reader(['ch_sim', 'en']) # 支持中文和英文reader = load_ocr_reader()# 初始化会话状态
if "chat_history" not in st.session_state:st.session_state.chat_history = []
if "ocr_text" not in st.session_state:st.session_state.ocr_text = ""
if "current_image" not in st.session_state:st.session_state.current_image = None# 页面标题
st.title("🧠 AI 家庭教师")
st.markdown("上传图片或拍照,AI 将识别内容并回答您的问题!")# 创建两列布局
col1, col2 = st.columns([1, 1])# 第一列:图像上传和处理
with col1:st.header("图像输入")# 选项卡:上传图片或拍照tab1, tab2 = st.tabs(["上传图片", "拍照"])with tab1:uploaded_file = st.file_uploader("选择一张图片", type=["jpg", "jpeg", "png"])if uploaded_file is not None:# 保存上传的图片image = Image.open(uploaded_file)st.session_state.current_image = np.array(image)st.image(image, caption="上传的图片", use_column_width=True)with tab2:camera_image = st.camera_input("拍摄图片")if camera_image is not None:# 保存拍摄的图片image = Image.open(camera_image)st.session_state.current_image = np.array(image)st.image(image, caption="拍摄的图片", use_column_width=True)# 处理图像按钮if st.button("识别图像文字") and st.session_state.current_image is not None:with st.spinner("正在识别文字..."):# 使用 EasyOCR 识别文字results = reader.readtext(st.session_state.current_image)# 提取文本extracted_text = ""for (bbox, text, prob) in results:extracted_text += text + " "st.session_state.ocr_text = extracted_text# 在图像上标记识别的文字annotated_image = st.session_state.current_image.copy()for (bbox, text, prob) in results:# 转换坐标为整数top_left = tuple(map(int, bbox[0]))bottom_right = tuple(map(int, bbox[2]))# 在图像上绘制边界框cv2.rectangle(annotated_image, top_left, bottom_right, (0, 255, 0), 2)# 添加文本标签cv2.putText(annotated_image, text, (top_left[0], top_left[1] - 10),cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)# 显示标记后的图像st.image(annotated_image, caption="识别结果", use_column_width=True)# 显示识别的文字st.subheader("识别的文字")st.write(extracted_text)# 第二列:聊天界面
with col2:st.header("AI 助教聊天")# 显示识别的文字if st.session_state.ocr_text:with st.expander("识别的文字内容", expanded=False):st.write(st.session_state.ocr_text)# 显示聊天历史chat_container = st.container()with chat_container:for message in st.session_state.chat_history:if message["role"] == "user":st.markdown(f"**你**: {message['content']}")else:st.markdown(f"**AI 助教**: {message['content']}")# 用户输入user_question = st.text_input("请输入您的问题...", key="user_input")if st.button("发送") and user_question:# 添加用户问题到历史st.session_state.chat_history.append({"role": "user", "content": user_question})# 构建 ChatGPT 的系统提示system_prompt = "你是一位专业的AI家庭教师,擅长解答学生的问题。"if st.session_state.ocr_text:system_prompt += f"以下是从图像中识别的文字内容,请基于这些内容回答问题:\n{st.session_state.ocr_text}"# 构建消息列表messages = [{"role": "system", "content": system_prompt}]for message in st.session_state.chat_history:messages.append({"role": message["role"], "content": message["content"]})# 调用 ChatGPT APIwith st.spinner("AI 正在思考..."):try:response = openai.ChatCompletion.create(model="gpt-3.5-turbo",messages=messages,temperature=0.7,max_tokens=1000)# 获取回复ai_response = response.choices[0].message.content# 添加回复到历史st.session_state.chat_history.append({"role": "assistant", "content": ai_response})# 重新加载页面以显示新消息st.experimental_rerun()except Exception as e:st.error(f"发生错误: {str(e)}")# 侧边栏:设置和操作
with st.sidebar:st.header("操作")if st.button("清空聊天记录"):st.session_state.chat_history = []st.experimental_rerun()if st.button("清空图像和识别结果"):st.session_state.current_image = Nonest.session_state.ocr_text = ""st.experimental_rerun()st.header("关于")st.markdown("""**AI 家庭教师** 结合了:- EasyOCR 进行文字识别- ChatGPT 提供智能回答- Streamlit 构建交互界面适用于学生拍摄课本、作业等内容,获取即时解答和辅导。""")
运行效果:
- 用户可以上传图片或使用摄像头拍照
- EasyOCR 识别图片中的文字,并在图像上标记
- 用户可以基于识别的内容向 AI 助教提问
- AI 助教(ChatGPT)会根据识别的内容和用户问题提供回答
- 完整的聊天历史记录和清空功能
与 AI 大模型的相关性
Streamlit 与 AI 大模型的结合具有强大的协同效应:
-
快速原型开发:Streamlit 允许数据科学家和 AI 研究人员快速构建模型演示,无需前端开发经验。
-
模型可解释性:通过交互式界面,用户可以调整参数并实时观察模型输出,增强对 AI 模型的理解。
-
降低使用门槛:为非技术用户提供友好的界面,使他们能够轻松使用复杂的 AI 模型。
-
API 集成简化:如我们的案例所示,Streamlit 可以轻松集成 OpenAI、Hugging Face 等 AI 服务的 API。
-
多模态应用:支持文本、图像、音频等多种输入形式,适合构建多模态 AI 应用。
在我们的实战案例中,我们展示了如何将 ChatGPT 和 EasyOCR 这样的 AI 模型无缝集成到 Streamlit 应用中,创建了既实用又易用的 AI 工具。
总结
Streamlit 是一个强大而简洁的工具,特别适合数据科学家和机器学习工程师快速构建交互式应用。通过本文的学习,我们掌握了:
- Streamlit 的基本组件和布局系统
- 如何在 Streamlit 中集成数据可视化和机器学习模型
- 应用部署与分享的方法
- 如何构建实用的 AI 应用,如 ChatGPT 聊天助手和 OCR 识别助教
Streamlit 的优势在于其简单性和快速开发能力,使得从想法到应用的过程变得异常高效。对于想要展示 AI 模型或数据分析结果的开发者来说,Streamlit 是一个不可多少的工具。
扩展思考
Streamlit 在企业级应用中的局限性
虽然 Streamlit 非常适合原型开发和小型应用,但在企业级应用中可能面临一些挑战:
-
性能限制:Streamlit 应用在每次交互时会重新运行整个脚本,这可能导致大型应用的性能问题。
-
定制化限制:虽然 Streamlit 提供了丰富的组件,但与成熟的前端框架相比,定制化能力较弱。
-
并发处理:Streamlit 不是为高并发负载设计的,在多用户同时访问时可能出现性能瓶颈。
-
状态管理:复杂应用中的状态管理相对简单,可能不足以支持复杂的业务逻辑。
-
安全性考虑:企业级应用通常需要更严格的安全措施,而 Streamlit 在这方面的功能相对基础。
如何结合前端框架提升用户体验
为了克服 Streamlit 的一些限制,可以考虑以下策略:
-
混合架构:使用 Streamlit 作为快速原型和内部工具,而将面向客户的产品用 React、Vue 等框架开发。
-
API 后端:将 Streamlit 应用的核心功能封装为 API(使用 FastAPI 或 Flask),然后由前端框架调用。
-
组件扩展:利用 Streamlit 的自定义组件功能,集成 React 组件以增强交互性。
-
微前端架构:将 Streamlit 应用嵌入到更大的微前端架构中,各司其职。
-
渐进式迁移:随着应用成熟,可以逐步将关键功能迁移到更适合生产环境的技术栈。
示例:创建 React 组件并在 Streamlit 中使用:
import streamlit as st
import streamlit.components.v1 as components# 定义一个简单的 React 组件
react_component = """
<div id="react-root"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script>const e = React.createElement;class FancyButton extends React.Component {constructor(props) {super(props);this.state = { clicked: false };}render() {return e('button',{ onClick: () => {this.setState({ clicked: true });// 与 Streamlit 通信if (window.Streamlit) {window.Streamlit.setComponentValue('按钮被点击了');}},style: {padding: '10px 20px',background: this.state.clicked ? '#4CAF50' : '#2196F3',color: 'white',border: 'none',borderRadius: '4px',cursor: 'pointer',transition: 'all 0.3s'}},this.state.clicked ? '已点击!' : '点击我');}}ReactDOM.render(e(FancyButton),document.getElementById('react-root'));
</script>
"""# 在 Streamlit 中使用 React 组件
st.title("Streamlit 与 React 集成示例")# 显示 React 组件
component_value = components.html(react_component, height=100)# 显示组件返回的值
if component_value:st.write(f"组件返回值: {component_value}")
通过这种方式,我们可以在保持 Streamlit 简单性的同时,利用前端框架的强大功能来增强用户体验。
总之,Streamlit 是一个强大的工具,特别适合快速开发和原型设计。通过了解其优势和局限性,我们可以在适当的场景中充分发挥其价值,同时在必要时结合其他技术来构建更完善的应用。