引言

在本地部署大语言模型(LLM)已成为趋势的今天,如何快速搭建一个带界面交互的聊天机器人,是许多开发者关心的问题。
本文将从工程化角度出发,带您完成一个模块化设计的Streamlit + Ollama聊天机器人项目,并实现一键启动脚本。我们将完整剖析项目中的5个核心文件,并修复一个常见的类型Bug

技术栈:Python 3.8+ | Streamlit | Ollama | Qwen2.5-0.5B


一、项目整体架构

1.1 文件结构一览

项目目录/
├── 智能聊天机器人.py             # 主程序:UI交互层
├── module_chat.py              # 后端模块:封装Ollama调用
└── run_st.py                   # 一键启动脚本

1.2 模块职责划分

文件 职责
智能聊天机器人.py Streamlit前端界面,管理会话状态(session_state
module_chat.py 封装Ollama客户端,提供chat_module()函数
run_st.py 通过os.system()自动启动Streamlit应用

二、后端模块:module_chat.py 解析

2.1 原始代码(含Bug)

import ollama

new_ollama = ollama.Client(host='http://127.0.0.1:11434')

def chat_module(msg):  
    res = new_ollama.chat(
        model='qwen2.5:0.5b',
        messages=msg   # 期望接收列表,但测试时传入了字符串
    )
    return res['message']['content']

if __name__ == '__main__':
    res_test = chat_module('你好')   # ❌ Bug:传入字符串,但Ollama需要列表
    print(res_test)

2.2 Bug分析与修复

问题ollama.chat()messages参数必须是一个消息列表(格式为[{"role": "user", "content": "..."}]),而测试代码直接传入了字符串'你好',导致类型错误

修复方案(两种):

方案一:修正测试调用(推荐)
if __name__ == '__main__':
    test_messages = [{'role': 'user', 'content': '你好'}]
    res_test = chat_module(test_messages)
    print(res_test)
方案二:在函数内部做兼容处理
def chat_module(msg):
    # 如果传入的是字符串,自动转为列表
    if isinstance(msg, str):
        msg = [{'role': 'user', 'content': msg}]
    res = new_ollama.chat(model='qwen2.5:0.5b', messages=msg)
    return res['message']['content']

2.3 正确版完整代码

import ollama

# 建立与Ollama服务的连接
new_ollama = ollama.Client(host='http://127.0.0.1:11434')

def chat_module(msg_list):
    """
    调用Ollama模型进行对话
    :param msg_list: 消息列表,格式如 [{"role": "user", "content": "你好"}]
    :return: 模型回复内容
    """
    res = new_ollama.chat(
        model='qwen2.5:0.5b',
        messages=msg_list
    )
    return res['message']['content']

if __name__ == '__main__':
    # 正确测试
    test_messages = [{'role': 'user', 'content': '你好'}]
    res_test = chat_module(test_messages)
    print(res_test)

三、前端主程序:智能聊天机器人.py 解析

3.1 完整代码

import streamlit as st
from module_chat import chat_module

st.title('智能聊天机器人')
st.divider()

# 初始化会话状态(实现多轮对话记忆)
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'])

# 获取用户输入
prompt = st.chat_input('请输入你的问题')

if prompt:
    # 显示用户消息
    st.chat_message('user').write(prompt)
    st.session_state['messages'].append({'role': 'user', 'content': prompt})
    
    # 调用后端模型(传入完整对话历史)
    with st.spinner('思考中~~'):
        res = chat_module(st.session_state['messages'])  # 传入整个消息列表
    
    # 显示助手回复
    st.chat_message('assistant').write(res)
    st.session_state['messages'].append({'role': 'assistant', 'content': res})

3.2 核心机制解读

组件 作用
st.session_state['messages'] 存储完整对话历史,实现上下文记忆
st.chat_input() 获取用户输入框内容
st.chat_message().write() 按角色(user/assistant)显示气泡消息
st.spinner() 模型响应时的加载动画
chat_module(st.session_state['messages']) 全部对话历史传给模型,保证多轮连贯性

四、一键启动脚本:run_st.py

4.1 代码实现

import os

# 通过系统命令启动Streamlit应用
os.system('streamlit run 智能聊天机器人.py')

4.2 使用方式

在终端中执行:

python run_st.py

即可自动启动Streamlit服务,并在浏览器中打开聊天界面。

4.3 进阶优化(可选)

如果需要指定端口、禁用自动打开浏览器等,可扩展为:

import os

# 启动时指定端口并禁止自动打开浏览器
os.system('streamlit run 智能聊天机器人.py --server.port 8502 --server.headless true')

五、完整项目运行流程

5.1 前置条件

  1. 安装Ollama并拉取模型:
    ollama pull qwen2.5:0.5b
    
  2. 安装Python依赖
    pip install streamlit ollama
    
  3. 确保Ollama服务运行中
    ollama serve
    

5.2 启动应用

python run_st.py

5.3 交互效果

  • 页面标题为“智能聊天机器人”
  • 首次进入显示助手欢迎语
  • 输入问题后,模型会基于完整对话历史生成回复
  • 所有消息自动保存在session_state中,刷新页面不丢失(会话期间)

六、常见问题与解决方案

问题 原因 解决
ConnectionError Ollama服务未启动 执行 ollama serve
TypeError: list expected 传入字符串而非列表 按2.2节修复调用方式
模型无响应 模型未下载或名称错误 执行 ollama list 确认模型名
端口被占用 Streamlit默认8501端口冲突 启动时添加 --server.port 端口号

七、总结与扩展

7.1 项目亮点

  • 模块化设计:前端UI与后端推理分离,易于维护与扩展
  • 多轮对话记忆:基于st.session_state实现上下文连贯性
  • 一键启动:通过run_st.py简化运行流程
  • 本地化部署:完全离线,数据不外传

7.2 扩展建议

  • 支持切换不同模型(如llama2、mistral)
  • 增加对话历史导出/导入功能
  • 接入RAG(检索增强生成)实现知识库问答
  • 使用st.sidebar添加参数调节面板(temperature、top_p等)

本文完整项目代码已附于各章节,复制即用。欢迎在评论区留言交流!

📌 如果本文对您有帮助,请点赞收藏,您的支持是我持续创作的动力!

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐