• Streamlit 构建大语言模型 (LLM) web 界面


    Streamlit 构建大语言模型 (LLM) web 界面

    选择Streamlit的原因

    1. 易用性:Streamlit 提供了一个直观且易于使用的环境,让数据科学家和机器学习工程师能够快速构建数据驱动的应用程序,而不需要专业的前端开发技能。对于大语言模型这类复杂模型,Streamlit 可以帮助开发者迅速搭建展示模型效果及交互界面的Web应用,方便用户输入查询、模型预测及结果展示。

    2. 实时互动:通过Streamlit,可以将大语言模型集成到Web应用中,实现实时交互式体验,用户可以直接在浏览器中与模型进行对话或提交请求,并立即得到模型生成的结果。

    3. 简化部署:Streamlit 应用可以通过一行命令部署到云端服务,大大降低了将大语言模型部署为Web服务的门槛,便于模型的分享和使用。

    原理

    • 基于Python API:Streamlit 库基于Python编写,允许用户用Python脚本描述UI元素和数据处理逻辑。
    • 响应式设计:Streamlit 应用是动态生成的,每当用户交互或数据发生变化时,都会重新渲染整个页面,更新结果显示。
    • 集成模型调用:在Streamlit应用中,开发者可以方便地调用大语言模型API或本地模型来处理用户输入,然后将模型输出结果展示在网页上。

    流程

    1. 安装Streamlit:首先确保Python环境中已安装Streamlit库。
    2. 创建应用脚本:编写Python脚本,定义UI组件(如文本输入框、按钮、文本显示区域等)。
    3. 集成大语言模型:在脚本中添加调用大语言模型的方法,通常是封装好模型预测API调用。
    4. 处理用户输入:监听用户在界面上的操作,如点击按钮或输入问题,触发模型调用。
    5. 展示模型输出:将模型返回的结果通过Streamlit的API显示在网页上。
    6. 运行应用:使用 streamlit run your_script.py 命令启动应用,Streamlit会自动在本地开启一个Web服务器,并在浏览器中打开应用。

    streamlit布局示例代码

    以下展示了如何自定义你的 Streamlit 应用布局:

    import streamlit as st
    
    st.set_page_config(layout="wide")
    
    st.title('How to layout your Streamlit app')
    
    with st.expander('About this app'):
      st.write('This app shows the various ways on how you can layout your Streamlit app.')
      st.image('https://streamlit.io/images/brand/streamlit-logo-secondary-colormark-darktext.png', width=250)
    
    st.sidebar.header('Input')
    user_name = st.sidebar.text_input('What is your name?')
    user_emoji = st.sidebar.selectbox('Choose an emoji', ['', '😄', '😆', '😊', '😍', '😴', '😕', '😱'])
    user_food = st.sidebar.selectbox('What is your favorite food?', ['', 'Tom Yum Kung', 'Burrito', 'Lasagna', 'Hamburger', 'Pizza'])
    
    st.header('Output')
    
    col1, col2, col3 = st.columns(3)
    
    with col1:
      if user_name != '':
        st.write(f'👋 Hello {user_name}!')
      else:
        st.write('👈  Please enter your **name**!')
    
    with col2:
      if user_emoji != '':
        st.write(f'{user_emoji} is your favorite **emoji**!')
      else:
        st.write('👈 Please choose an **emoji**!')
    
    with col3:
      if user_food != '':
        st.write(f'🍴 **{user_food}** is your favorite **food**!')
      else:
        st.write('👈 Please choose your favorite **food**!')
    
    • 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
    • 逐行解释

    创建 Streamlit 应用时要做的第一件事就是将 streamlit 库导入为 st

    import streamlit as st
    
    • 1

    我们首先令页面的显示模式变为宽屏模式,页面内容将占据浏览器的全部宽度进行显示。

    st.set_page_config(layout="wide")
    
    • 1

    接下来,我们为这个 Streamlit 应用设置一个标题。

    st.title('How to layout your Streamlit app')
    
    • 1

    在应用标题下方创建一个标题名为 About this app 的可折叠区域。在展开时,我们可以看到其其中包含的额外细节。

    with st.expander('About this app'):
      st.write('This app shows the various ways on how you can layout your Streamlit app.')
      st.image('https://streamlit.io/images/brand/streamlit-logo-secondary-colormark-darktext.png', width=250)
    
    • 1
    • 2
    • 3

    通过在 text_inputselectbox 之前加上 st.sidebar 命令,我们将用于接收用户输入的组件放入侧边栏内。用户输入或选择的数值将被赋值并存储在 user_nameuser_emojiuser_food 变量之中。

    st.sidebar.header('Input')
    user_name = st.sidebar.text_input('What is your name?')
    user_emoji = st.sidebar.selectbox('Choose an emoji', ['', '😄', '😆', '😊', '😍', '😴', '😕', '😱'])
    user_food = st.sidebar.selectbox('What is your favorite food?', ['', 'Tom Yum Kung', 'Burrito', 'Lasagna', 'Hamburger', 'Pizza'])
    
    • 1
    • 2
    • 3
    • 4

    最后,我们使用 st.columns 命令创建三列,分别名为 col1col2col3。然后我们使用独立的 with 语句将内容放入每列之中。其中我们创建了三个条件分支语句,根据用户是否在侧边栏中提供了输入来显示不同的文字。默认情况下显示的均为 else 语句下的内容。如果用户提供了对应的输入,则会显示在 Output 标题下方。

    st.header('Output')
    
    col1, col2, col3 = st.columns(3)
    
    with col1:
      if user_name != '':
        st.write(f'👋 Hello {user_name}!')
      else:
        st.write('👈  Please enter your **name**!')
    
    with col2:
      if user_emoji != '':
        st.write(f'{user_emoji} is your favorite **emoji**!')
      else:
        st.write('👈 Please choose an **emoji**!')
    
    with col3:
      if user_food != '':
        st.write(f'🍴 **{user_food}** is your favorite **food**!')
      else:
        st.write('👈 Please choose your favorite **food**!')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    值得注意的是,这里我们用 f-字符串来将固定的信息与用户的输入数值相结合。

    聊天机器人示例代码(简化版)

    import streamlit as st
    from transformers import pipeline
    
    # 加载预训练的大语言模型
    model = pipeline('text-generation', model="gpt-2")
    
    def generate_text(prompt):
        response = model(prompt=prompt, max_length=100, num_return_sequences=1)
        return response[0]['generated_text']
    
    # 创建Web界面组件
    st.title("大语言模型交互界面")
    user_input = st.text_input("请输入您的问题或话题:")
    
    if st.button("生成文本"):
        generated_text = generate_text(user_input)
        st.write("模型生成的回答:", generated_text)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这个例子中,我们使用了Hugging Face Transformers库加载了GPT-2模型,并通过Streamlit创建了一个简单的文本输入框和按钮。当用户输入问题并点击“生成文本”按钮时,模型会生成对应的回复,并在页面上显示结果。

    Streamlit在ChatGLM3-6B中的应用

    """
    This script is a simple web demo based on Streamlit, showcasing the use of the ChatGLM3-6B model. For a more comprehensive web demo,
    it is recommended to use 'composite_demo'.
    
    Usage:
    - Run the script using Streamlit: `streamlit run web_demo_streamlit.py`
    - Adjust the model parameters from the sidebar.
    - Enter questions in the chat input box and interact with the ChatGLM3-6B model.
    
    Note: Ensure 'streamlit' and 'transformers' libraries are installed and the required model checkpoints are available.
    """
    
    import os
    import streamlit as st
    import torch
    from transformers import AutoModel, AutoTokenizer
    
    MODEL_PATH = os.environ.get('MODEL_PATH', 'THUDM/chatglm3-6b')
    TOKENIZER_PATH = os.environ.get("TOKENIZER_PATH", MODEL_PATH)
    
    st.set_page_config(
        page_title="ChatGLM3-6B Streamlit Simple Demo",
        page_icon=":robot:",
        layout="wide"
    )
    
    
    @st.cache_resource
    def get_model():
    
        tokenizer = AutoTokenizer.from_pretrained(TOKENIZER_PATH, trust_remote_code=True)
        model = AutoModel.from_pretrained(MODEL_PATH, trust_remote_code=True, device_map="auto").eval()
        return tokenizer, model
    
    
    # 加载Chatglm3的model和tokenizer
    tokenizer, model = get_model()
    
    if "history" not in st.session_state:
        st.session_state.history = []
    if "past_key_values" not in st.session_state:
        st.session_state.past_key_values = None
    
    max_length = st.sidebar.slider("max_length", 0, 32768, 8192, step=1)
    top_p = st.sidebar.slider("top_p", 0.0, 1.0, 0.8, step=0.01)
    temperature = st.sidebar.slider("temperature", 0.0, 1.0, 0.6, step=0.01)
    
    buttonClean = st.sidebar.button("清理会话历史", key="clean")
    if buttonClean:
        st.session_state.history = []
        st.session_state.past_key_values = None
        if torch.cuda.is_available():
            torch.cuda.empty_cache()
        st.rerun()
    
    for i, message in enumerate(st.session_state.history):
        if message["role"] == "user":
            with st.chat_message(name="user", avatar="user"):
                st.markdown(message["content"])
        else:
            with st.chat_message(name="assistant", avatar="assistant"):
                st.markdown(message["content"])
    
    with st.chat_message(name="user", avatar="user"):
        input_placeholder = st.empty()
    with st.chat_message(name="assistant", avatar="assistant"):
        message_placeholder = st.empty()
    
    prompt_text = st.chat_input("请输入您的问题")
    if prompt_text:
        input_placeholder.markdown(prompt_text)
        history = st.session_state.history
        past_key_values = st.session_state.past_key_values
        for response, history, past_key_values in model.stream_chat(
                tokenizer,
                prompt_text,
                history,
                past_key_values=past_key_values,
                max_length=max_length,
                top_p=top_p,
                temperature=temperature,
                return_past_key_values=True,
        ):
            message_placeholder.markdown(response)
        st.session_state.history = history
        st.session_state.past_key_values = past_key_values
    
    
    • 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

    这段代码是一个基于Streamlit构建的与预训练大语言模型ChatGLM3-6B交互的简单演示应用。以下是代码逐段解析:

    1. 导入所需库:

      • os: 用于从操作系统环境变量获取模型路径。
      • streamlit as st: 引入Streamlit库,用于构建Web应用程序界面。
      • torch: PyTorch深度学习框架,用于模型的加载和计算。
      • transformers: Hugging Face Transformers库,提供了预训练模型和tokenizer的加载接口。
    2. 定义环境变量:

      • MODEL_PATHTOKENIZER_PATH 从环境变量获取,如果没有设置则使用默认值。
    3. 设置Streamlit页面配置:

      • st.set_page_config 设置页面标题、图标以及布局方式。
    4. 使用装饰器 @st.cache_resource 缓存资源函数 get_model(),以避免每次调用时都重新加载模型和tokenizer:

      • 函数内部使用 AutoTokenizer.from_pretrainedAutoModel.from_pretrained 加载预训练的tokenizer和模型,同时设定模型处于评估模式 (model.eval())。
    5. 初始化会话状态(session state):

      • 存储聊天历史记录 history 和模型需要的过去关键值 past_key_values
    6. 创建侧边栏滑块控制最大生成长度 max_length、采样策略中的 top_p 和温度参数 temperature

    7. 清理会话历史功能:

      • 当用户点击清理按钮时,清空历史记录、过去关键值,并尝试释放GPU缓存,然后刷新页面。
    8. 展示聊天历史:

      • 遍历 history 列表,分别按照用户消息和助手(模型生成)消息样式展示过去的聊天内容。
    9. 用户输入区域:

      • 创建两个空白占位符,分别用于接收用户输入和展示模型生成的回答。
    10. 用户输入事件处理:

      • 获取用户输入的文字内容 prompt_text
      • 将用户输入加入到聊天历史 history 中。
      • 调用模型的 stream_chat 方法,传入用户输入、历史记录、参数设置等,生成模型回复。
      • 将模型回复添加到聊天历史并更新会话状态中的历史记录和过去关键值。

    整体而言,该代码实现了一个具有记忆功能的在线聊天应用,用户可以在其中与预训练的大规模语言模型ChatGLM3-6B进行交互,模型根据用户的输入生成相应的回答,并以聊天形式展示在界面上。同时,用户还可以调整模型生成文本的参数,如最大生成长度、采样策略和随机性温度等。

  • 相关阅读:
    R语言使用DALEX包对h2o包构建的机器学习模型进行解释分析:总结及实战
    量化交易中的资金管理模型分享
    自媒体新人,如何快速积累粉丝,我的业余Python能帮助我干些什么
    SpringCloudAlibaba SpringCloud SpringBoot 版本对照
    初探802.11协议(5)——MIMO/MU-MIMO/OFDMA概念介绍
    Echarts 雷达图的详细配置过程
    C++&QT 作业9
    InnoDB引擎之flush脏页
    区块链:去中心化革命下的创新与发展!
    揭秘未来:用线性回归模型预测一切的秘密武器!
  • 原文地址:https://blog.csdn.net/qq_39813001/article/details/137320635