You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Streamlit应用中实现本地Ollama大模型的流式响应?

解决Streamlit本地大模型流式输出问题

问题核心:st.write_stream要求输入为生成器或类流对象,但当前llm_chain.run()直接返回完整字符串,且原回调仅输出到控制台,无法为Streamlit提供流式数据。


步骤1:自定义Streamlit流式回调处理器

创建回调类,收集模型输出的每个token,并提供生成器接口供st.write_stream调用:

from langchain.callbacks.base import BaseCallbackHandler

class StreamlitStreamingCallbackHandler(BaseCallbackHandler):
    def __init__(self):
        self.tokens = []
        self.finished = False

    def on_llm_new_token(self, token: str, **kwargs) -> None:
        self.tokens.append(token)

    def on_llm_end(self, response, **kwargs) -> None:
        self.finished = True

    def stream(self):
        while not self.finished or self.tokens:
            if self.tokens:
                yield self.tokens.pop(0)

步骤2:替换原回调并初始化LLM

用自定义回调替换原StreamingStdOutCallbackHandler,同时开启Ollama的流式输出模式:

# 替换原callback_manager初始化逻辑
callback_handler = StreamlitStreamingCallbackHandler()
callback_manager = CallbackManager([callback_handler])
llm = Ollama(model=st.session_state.selected_model, callbacks=callback_manager, streaming=True)

步骤3:修改聊天响应逻辑

在助理消息块中,通过回调生成器向st.write_stream喂数据,同时收集完整响应存入会话历史:

if prompt := st.chat_input(""):
    with st.chat_message(name="user", avatar="source/ai_user_2.png"):
        st.write(prompt)
        st.session_state.messages.append({"role": "user", "content": prompt})
    
    with st.chat_message(name="assistant", avatar="source/ai_bot_2.png"):
        # 重新初始化回调处理器,避免跨请求数据污染
        callback_handler = StreamlitStreamingCallbackHandler()
        # 更新LLM链的回调管理器
        st.session_state.llm_chain.llm.callbacks = CallbackManager([callback_handler])
        
        # 异步运行模型,避免阻塞UI
        import threading
        def run_model():
            st.session_state.llm_chain.run(input=prompt)
        
        threading.Thread(target=run_model).start()
        
        # 流式输出并收集完整响应
        full_response = ""
        for token in callback_handler.stream():
            full_response += token
            yield token
        
        # 将完整响应存入会话历史
        st.session_state.messages.append({"role": "assistant", "content": full_response})

额外修复:会话历史渲染的语法错误

原代码中elif缩进错误且使用is进行字符串判断,修正后:

for message in st.session_state.messages:
    if message["role"] == "user":
        with st.chat_message(name="user", avatar="source/ai_user_2.png"):
            st.write(message["content"])
    elif message["role"] == "assistant":
        with st.chat_message(name="assistant", avatar="source/ai_bot_2.png"):
            st.write(message["content"])

内容的提问来源于stack exchange,提问作者kostya ivanov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:00:07