day22-streamlit+agent sdk融合

Streamlit

简介

什么是streamlit

Streamlit是一个免费的开源框架,用于快速构建和共享漂亮的数据科学Web应用程序。它是一个基于Python的库,专为机器学习工程师设计。数据分析工程师不是网络开发人员,他们对花几周时间学习使用这些框架来构建网络应用程序不感兴趣。相反,他们需要一个更容易学习和使用的工具,只要它可以显示数据并收集分析/建模所需的参数。Streamlit允许您仅用几行代码创建一个外观惊艳的应用程序。

参考文档:http://cw.fumihubwiz.com/card/c/streamlit-manual/

数据科学家为何要使用Streamlit?

Streamlit最大的好处是,您甚至不需要了解Web开发的基础知识就可以开始或创建您的第一个Web应用程序。因此,如果你是一个对数据科学感兴趣的人,你想轻松、快速地部署你的模型,并且只需要几行代码,Streamlit是一个很好的选择。

优势:

  • 不需要具备前端知识即可应用streamlit。
  • 学习成本极低
    • 你不需要花费几天或几个月的时间来创建一个Web应用,你可以在几个小时甚至几分钟内创建一个非常漂亮的机器学习或数据科学应用。
  • 它兼容大多数Python库
    • 例如panda、matplotlib、seaborn、plotly、Keras、PyTorch等。

环境安装

pip install streamlit == 1.51.0 #目前最新版本

#cmd执行:测试安装是否正常:
streamlit hello

程序运行

streamlit run xxx.py

具体操作

1.write()函数

可以通过该函数向看板上输出显示指定内容

import pandas as pd
import streamlit as st

st.write("1. write()函数基本操作")
st.write(pd.DataFrame({
    '第一列': [1,2,3,4,5],
    '第二列': [6,7,8,9,10]}
))

2.滑块组件slider

"slider"的中文意思是"滑块"。它是一种用户界面元素,通常用于选择一个数值范围或从给定选项中选择一个值。滑块的外观通常是一个可拖动的滑块,用户可以通过移动滑块来选择所需的值。滑块可以在许多应用程序和网页中使用,例如调整音量、选择年龄范围或设置某个参数的值。

import streamlit as st

st.write("st.slider()滑块")
#slider参数为滑块自定义名称,返回值为滑动到的数值
num = st.slider("num")
st.write(num, "squred is", num*num)

3.文本框操作text_input

import streamlit as st

st.write("文本框操作")
#文本框输入,回车结束
st.text_input("your name", key="name")
st.text_input("your age", key="age")

# 显示输入的值
st.write(st.session_state.name,st.session_state.age)

密码框:

import streamlit as st

# 创建一个文本输入框,并将其类型设置为密码
password = st.text_input("请输入密码", type="password")

# 检查密码是否正确(这里假设正确密码是"123456")
if st.button("登录"):
    if password == "123456":
        st.success("登录成功!")
    else:
        st.error("密码错误,请重试。")

4.多选框checkbox

import streamlit as st
import pandas as pd
import numpy as np

st.write("checkbox()多选框")
# 点击checkbox后返回True,未点击为False
ex1 = st.checkbox('显示/不显示 表格')
if ex1:
    df = pd.DataFrame(
        np.random.randn(20, 3),
        columns=['a', 'b', 'c']
    )
    st.write(df)

ex2 = st.checkbox('显示/不显示 滑块')
if ex2:
    x = st.slider('x')

5.下拉框selectbox

import streamlit as st

#返回值为选中的内容信息
option = st.selectbox(
    label='请选择省份信息:',
    options=['河北','山东','河南','吉林']
)

st.write("您选择的是: ", option)

6.侧边栏sidebar

import streamlit as st

#侧边栏下拉框
add_selectbox = st.sidebar.selectbox(
    label="通讯方式选项",
    options=('微信','QQ','手机','邮件')
)
#获取下拉选项
st.write("下拉选项: ", add_selectbox)

#侧边栏滑块
add_slider = st.sidebar.slider(
    label="选择一个范围的值",
    min_value=0.0, max_value=100.0, value=(25.0, 75.0)
)
#获取滑块的值
st.write("值的范围: ", add_slider)

7.单选按钮radio

import streamlit as st

#columns参数表示列数
left_column, right_column = st.columns(2)
# 左边列设置
with left_column:
    #返回值为选中的选项值
    chosen = st.radio(
        label='电脑品牌',
        options=('苹果','华为','小米')
    )
    st.write(f'你选择的品牌是: {chosen}')
    
# 右边列设置
with right_column:
    # 返回值为选中的选项值
    chosen = st.radio(
        label='手机品牌',
        options=('苹果','华为','小米')
    )
    st.write(f'你选择的品牌是: {chosen}')

8.进度条progress

import streamlit as st
import time
st.write("模拟长时间的计算...")

# 创建一个动态显示数据的容器,用于动态显示进度条的进度数值
value = st.empty()
#创建进度条,进度条初始值为0
bar = st.progress(0)
for i in range(100):
    #这是动态显示的数值
    value.text(f'Iteration {i+1}')
    # 更新进度条
    bar.progress(i+1)
    time.sleep(0.1)
st.write('运行结束!')

9.文件上传

上传penguins.csv文件,然后选择不同的两个企鹅特征,用散点图观察其分布形式。

import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
st.write('上传penguins.csv文件,然后选择不同的两个企鹅特征,用散点图观察其分布形式。')

#创建文件上传组件,如果上传失败则返回None
upload_file = st.file_uploader(
    label = "上传数据集文件" #自定义文件上传提示信息
)

#判断上传文件是否成功
if upload_file is not None:
    df = pd.read_csv(upload_file)
    st.write('显示前5行数据:',df.head(5))
    st.success("上传文件成功!")
else:
    st.stop() # 退出

布局

1.st.columns - 并排布局多元素容器

通过调用 st.columns,您可以插入多个多元素容器,并将它们布局为并排的形式。返回的是一个容器对象的列表,每个对象都可以用来添加元素。您可以选择使用“with”语法(更推荐)或者直接在容器对象上调用方法来添加元素。

import streamlit as st

col1, col2, col3 = st.columns(3)

with col1:
   st.header("一只猫")
   st.image("https://static.streamlit.io/examples/cat.jpg")

with col2:
   st.header("一只狗")
   st.image("https://static.streamlit.io/examples/dog.jpg")

with col3:
   st.header("一只猫头鹰")
   st.image("https://static.streamlit.io/examples/owl.jpg")

2.st.tabs - 以选项卡形式布局多元素容器

通过调用 st.tabs,您可以插入多个多元素容器作为选项卡。每个选项卡都代表一组相关内容。返回的是一个容器对象的列表,每个对象都可以用来添加元素。与之前一样,您可以选择使用“with”语法或者直接在容器对象上调用方法来添加元素。

需要注意的是,每个选项卡的所有内容都会被一次性发送并渲染在前端。

import streamlit as st

tab1, tab2, tab3 = st.tabs(["猫", "狗", "猫头鹰"])

with tab1:
   st.header("一只猫")
   st.image("https://static.streamlit.io/examples/cat.jpg", width=200)

with tab2:
   st.header("一只狗")
   st.image("https://static.streamlit.io/examples/dog.jpg", width=200)

with tab3:
   st.header("一只猫头鹰")
   st.image("https://static.streamlit.io/examples/owl.jpg", width=200)

3.st.expander - 可展开/折叠的多元素容器

调用 st.expander,您可以插入一个可展开或折叠的容器,用于包含多个元素。容器的初始状态是折叠的,只显示提供的标签。用户可以点击标签来展开容器,查看其中的内容。

import streamlit as st

with st.expander("查看说明"):
    st.write("""
        上面的图表展示了我为您选择的一些数字。
        这些数字是通过真实的骰子摇出来的,所以它们*保证*是随机的。
    """)
    st.image("https://static.streamlit.io/examples/dice.jpg")

Streamlit+大模型

简易聊天系统

import streamlit as st  
from openai import OpenAI  
  
# 设置页面标题  
st.title("💬 DeepSeek Chatbot")  
  
# 在侧边栏添加配置选项  
with st.sidebar:  
    # 提供一个文本输入框让用户可以手动输入API Key(可选)  
    openai_api_key = st.text_input("DeepSeek API Key", key="chatbot_api_key", type="password")  
    
    "[获取 DeepSeek API key](https://platform.deepseek.com/api_keys)"  
    
    if st.button("开启新对话"):  
        st.session_state.messages = [{"role": "assistant", "content": "欢迎使用对话机器人,你想知道什么?"}] 
  
#检查API Key是否已提供  
if not openai_api_key:  
    st.info("请添加新的API Key")  
else:  
    base_url = "https://api.deepseek.com"  
    client = OpenAI(api_key=openai_api_key, base_url=base_url)  
  
    # 初始化对话历史记录  
    if "messages" not in st.session_state:  
        st.session_state.messages = [{"role": "assistant", "content": "欢迎使用对话机器人,你想知道什么?"}]  
  
    # 显示对话历史  
    for msg in st.session_state.messages:  
        st.chat_message(msg["role"]).write(msg["content"])  
  
    # 获取用户输入  
    if prompt := st.chat_input():  
        st.session_state.messages.append({"role": "user", "content": prompt})  
        st.chat_message("user").write(prompt)  
  
        # 调用DeepSeek API  
        response = client.chat.completions.create(  
            model="deepseek-chat",  
            messages=st.session_state.messages,  
            stream=False  
        )  
        #追加聊天记录
        assistant_reply = response.choices[0].message.content  
        st.session_state.messages.append({"role": "assistant", "content": assistant_reply})  
        st.chat_message("assistant").write(assistant_reply)

多角色聊天

import streamlit as st
import asyncio
from openai import AsyncOpenAI
from agents import OpenAIChatCompletionsModel, Agent, Runner, set_default_openai_client

# 页面配置
st.set_page_config(
   page_title="三国人物聊天室",
   page_icon="🤖",
   layout="wide"
)

# 初始化模型和智能体
@st.cache_resource #核心作用是缓存那些需要被共享的、不可变的资源对象,从而避免在应用每次重新运行时重复执行昂贵的初始化操作。
def initialize_agents():
   """初始化模型和智能体"""
   # 自定义模型对象
   external_client = AsyncOpenAI(
       base_url="https://api.deepseek.com",
       api_key="sk-4b79f3a3ff334a15a1935366ebb425b3", 
   )
   
   # 将自定义模型设置为默认模型
   set_default_openai_client(external_client)

   # 创建模型客户端
   deepseek_model = OpenAIChatCompletionsModel(
       model="deepseek-chat",
       openai_client=external_client
   )

   # 创建张飞智能体
   zhangfei_agent = Agent(
       name="张飞",
       instructions="""你是三国时期的张飞,性格豪爽、勇猛、直率。
       回复时要体现以下特点:
       - 说话直接,充满力量感
       - 喜欢用"俺"、"大哥"等称呼
       - 对战斗、喝酒等话题特别感兴趣
       - 偶尔会有点暴躁但心地善良""",
       handoff_description="当用户提到'勇猛'、'战斗'、'喝酒'、'战场'等关键词时,适合由我来回应。",
       model=deepseek_model
   )

   # 创建诸葛亮智能体
   zhuge_agent = Agent(
       name="诸葛亮",
       instructions="""你是三国时期的诸葛亮,智慧超群、谋略深远。
       回复时要体现以下特点:
       - 说话文雅,富有智慧
       - 善于分析和策略思考
       - 对治国、谋略、历史有深刻见解
       - 语气沉稳,思路清晰""",
       handoff_description="如果用户询问策略、计谋、智慧、治国安邦等内容,请把我引入对话。",
       model=deepseek_model
   )

   # 创建分诊智能体
   triage_agent = Agent(
       name="分诊助手",
       instructions="""你是智能分诊助手,负责将用户问题转交给最合适的专家。
       根据用户问题的内容决定由张飞还是诸葛亮来回答:
       - 涉及武力、勇气、战斗、喝酒等 -> 转给张飞
       - 涉及谋略、智慧、策略、治国等 -> 转给诸葛亮
       - 不确定时 -> 根据你的判断选择最合适的
       
       在回复时请明确说明是由哪位专家回答的。""",
       handoffs=[zhangfei_agent, zhuge_agent],
       model=deepseek_model
   )
   
   return {
       "triage": triage_agent,
       "zhangfei": zhangfei_agent,
       "zhuge": zhuge_agent
   }

# 智能体调用函数
async def get_agent_response(agent, message, history):
   """获取智能体回复的异步函数"""
   input_items = history + [{"content": message, "role": "user"}]
   result = await Runner.run(agent, input_items)
   return result.final_output, result.to_input_list()

def main():
   st.title("🎭 三国人物智能聊天室")
   st.markdown("与张飞、诸葛亮等三国人物进行有趣的对话!")
   
   # 侧边栏 - 角色选择
   st.sidebar.title("角色选择")
   chat_mode = st.sidebar.radio(
       "选择聊天模式:",
       ["智能分诊", "直接对话张飞", "直接对话诸葛亮"]
   )
   
   # 初始化智能体
   agents = initialize_agents()
   
   # 根据模式选择智能体
   if chat_mode == "智能分诊":
       current_agent = agents["triage"]
       st.sidebar.info("🤖 分诊模式:系统会自动选择最适合的角色回答您的问题")
   elif chat_mode == "直接对话张飞":
       current_agent = agents["zhangfei"]
       st.sidebar.info("⚔️ 直接与张飞对话")
   else:
       current_agent = agents["zhuge"]
       st.sidebar.info("🎯 直接与诸葛亮对话")
   
   # 显示角色介绍
   st.sidebar.markdown("---")
   st.sidebar.subheader("角色介绍")
   st.sidebar.markdown("""
   **张飞**:勇猛武将,性格豪爽
   - 擅长:战斗、勇气话题
   - 特点:说话直接有力
   
   **诸葛亮**:智慧军师,谋略深远  
   - 擅长:策略、智慧话题
   - 特点:说话文雅睿智
   """)
   
   # 初始化对话历史
   if "messages" not in st.session_state:
       st.session_state.messages = []
   
   # 清空对话按钮
   if st.sidebar.button("清空对话历史", use_container_width=True):
       st.session_state.messages = []
       st.rerun()
   
   # 显示对话历史
   chat_container = st.container()
   with chat_container:
       for message in st.session_state.messages:
           with st.chat_message(message["role"]):
               st.markdown(message["content"])
   
   # 用户输入
   if prompt := st.chat_input("请输入您的问题..."):
       # 添加用户消息
       st.session_state.messages.append({"role": "user", "content": prompt})
       
       # 显示用户消息
       with st.chat_message("user"):
           st.markdown(prompt)
       
       # 显示助手回复(带加载动画)
       with st.chat_message("assistant"):
           with st.spinner("思考中..."):
               try:
                   # 运行异步函数获取回复
                   response, new_history = asyncio.run(
                       get_agent_response(current_agent, prompt, st.session_state.messages[:-1])
                   )
                   
                   # 显示回复
                   st.markdown(response)
                   
                   # 更新对话历史
                   st.session_state.messages.append({"role": "assistant", "content": response})
                   
               except Exception as e:
                   error_msg = f"抱歉,出现了错误:{str(e)}"
                   st.error(error_msg)
                   st.session_state.messages.append({"role": "assistant", "content": error_msg})

if __name__ == "__main__":
   main()
posted @ 2025-11-05 09:22  凫弥  阅读(6)  评论(0)    收藏  举报