04-从零搭建本地AI对话系统:Ollama + DeepSeek-R1:7B + Streamlit

1、pycharm的文件在哪?

在万WSL虚拟机中,去~就能找到文件

/mnt/f/26_01/python/test/py_code/

/mnt/本地目录

🚀 从零搭建本地AI对话系统:Ollama + DeepSeek-R1:7B + Streamlit

第一步:环境准备与Ollama部署

首先确保你的WSL Ubuntu环境就绪,然后安装核心工具Ollama。

  1. 安装Ollama

    在WSL终端中执行以下命令一键安装:

    复制代码
    curl -fsSL https://ollama.com/install.sh | sh

    安装完成后,验证是否成功:ollama --version

  2. 拉取DeepSeek-R1:7B模型

    从Ollama的模型库中拉取模型:

    复制代码
    ollama pull deepseek-r1:7b

    模型文件较大(约4.7GB),下载时间取决于你的网络速度。

  3. 启动Ollama服务

    启动Ollama服务,它将提供本地API:

    复制代码
    ollama serve

    此命令会启动服务并默认在 http://localhost:11434进行监听。请保持此终端窗口打开 ,或使用 ollama serve &在后台运行。

第二步:创建Python虚拟环境

为避免包冲突,为项目创建一个独立的虚拟环境。

  1. 创建并激活虚拟环境

    复制代码
    python3 -m venv ai_chat_env
    source ai_chat_env/bin/activate
  2. 安装必要的Python包

    复制代码
    pip install streamlit requests

第三步:开发Streamlit聊天应用

创建一个名为 app.py的Python文件,并写入以下代码。这段代码创建了Web界面并负责与Ollama API通信。

python 复制代码
import streamlit as st
import requests
import json
import time

# 页面设置
st.set_page_config(
    page_title="Ollama DeepSeek 对话",
    page_icon="🤖",
    layout="centered"
)

# 应用标题
st.title("🤖 Ollama + DeepSeek-R1:7B 对话")
st.markdown("---")

# 初始化会话状态
if 'messages' not in st.session_state:
    st.session_state.messages = []

if 'conversation_history' not in st.session_state:
    st.session_state.conversation_history = []


# 连接到 Ollama 的函数
def ask_ollama(user_message):
    """
    发送请求到本地 Ollama 服务
    """
    # Ollama API 地址(在 WSL 中运行)
    url = "http://localhost:11434/api/chat"

    # 构建消息历史
    messages = []

    # 添加系统提示
    messages.append({
        "role": "system",
        "content": "你是一个有帮助的AI助手,使用中文回答。"
    })

    # 添加历史对话(最近3轮)
    for msg in st.session_state.messages[-6:]:
        messages.append(msg)

    # 添加当前用户消息
    messages.append({"role": "user", "content": user_message})

    # 请求数据
    payload = {
        "model": "deepseek-r1:7b",
        "messages": messages,
        "stream": False,
        "options": {
            "temperature": 0.7,
            "num_predict": 256
        }
    }

    try:
        # 发送请求
        response = requests.post(
            url,
            json=payload,
            timeout=60
        )

        if response.status_code == 200:
            result = response.json()
            return result['message']['content']
        else:
            return f"❌ 请求失败 (状态码: {response.status_code})"

    except requests.exceptions.ConnectionError:
        return "⚠️ 无法连接到 Ollama 服务!\n\n请确保:\n1. 在 WSL 终端运行 `ollama serve`\n2. 模型已下载:`ollama pull deepseek-r1:7b`"
    except Exception as e:
        return f"❌ 发生错误: {str(e)}"


# 侧边栏 - 设置和信息
with st.sidebar:
    st.header("⚙️ 设置")

    # 清除对话按钮
    if st.button("🗑️ 清除对话历史", use_container_width=True):
        st.session_state.messages = []
        st.session_state.conversation_history = []
        st.rerun()

    st.divider()

    st.header("📊 状态信息")

    # 显示当前模型
    st.info(f"**模型:** deepseek-r1:7b")
    st.info(f"**对话轮次:** {len(st.session_state.messages) // 2}")

    st.divider()

    # 快速测试连接
    if st.button("🔗 测试连接", use_container_width=True):
        with st.spinner("测试连接中..."):
            test_result = ask_ollama("你好,请回复'连接成功'。")
            st.success(f"测试结果: {test_result[:50]}...")

# 显示对话历史
st.subheader("💭 对话历史")

# 如果还没有对话,显示提示
if not st.session_state.messages:
    st.info("👆 在下方输入框中输入消息开始对话")
else:
    # 显示所有消息
    for i, message in enumerate(st.session_state.messages):
        if i % 2 == 0:  # 用户消息
            with st.chat_message("user"):
                st.markdown(f"**你:** {message['content']}")
        else:  # AI消息
            with st.chat_message("assistant"):
                st.markdown(f"**AI:** {message['content']}")

# 输入区域
st.divider()
st.subheader("📝 输入你的消息")

# 创建输入表单
with st.form(key="chat_form", clear_on_submit=True):
    user_input = st.text_area(
        "输入消息:",
        height=100,
        placeholder="输入你想问的问题...",
        key="user_input_area"
    )

    col1, col2 = st.columns([1, 1])
    with col1:
        submit_button = st.form_submit_button(
            "🚀 发送",
            use_container_width=True,
            type="primary"
        )
    with col2:
        example_button = st.form_submit_button(
            "💡 示例问题",
            use_container_width=True
        )

# 处理示例按钮
if example_button:
    example_questions = [
        "你好,请介绍一下你自己",
        "什么是人工智能?",
        "写一首关于秋天的诗",
        "解释一下机器学习的基本概念",
        "如何学习编程?"
    ]

    import random

    user_input = random.choice(example_questions)
    st.session_state.user_input_area = user_input
    st.rerun()

# 处理发送按钮
if submit_button and user_input.strip():
    # 添加用户消息到历史
    st.session_state.messages.append({
        "role": "user",
        "content": user_input
    })

    # 显示用户消息
    with st.chat_message("user"):
        st.markdown(f"**你:** {user_input}")

    # 获取AI响应
    with st.spinner("🤖 DeepSeek 正在思考..."):
        ai_response = ask_ollama(user_input)

    # 添加AI响应到历史
    st.session_state.messages.append({
        "role": "assistant",
        "content": ai_response
    })

    # 显示AI响应
    with st.chat_message("assistant"):
        st.markdown(f"**AI:** {ai_response}")

    # 滚动到最新消息
    st.rerun()

# 页脚信息
st.markdown("---")
st.caption("""
💡 **使用说明:**
1. 确保在 WSL 终端中运行 `ollama serve` 启动服务
2. 确保已下载模型: `ollama pull deepseek-r1:7b`
3. 输入问题后点击"发送"按钮
4. 使用侧边栏的"清除对话历史"按钮开始新的对话
""")

# 添加简单的 CSS 样式
st.markdown("""
<style>
    .stTextArea textarea {
        font-size: 16px;
    }
    .stButton button {
        font-weight: bold;
    }
    .stChatMessage {
        padding: 10px;
        border-radius: 10px;
        margin: 10px 0;
    }
    div[data-testid="stChatMessage"] {
        border-left: 4px solid #4CAF50;
        padding-left: 10px;
    }
    div[data-testid="stChatMessage"]:nth-child(even) {
        border-left: 4px solid #2196F3;
    }
</style>
""", unsafe_allow_html=True)

第四步:运行应用

在WSL终端中,确保位于 app.py所在目录,并且虚拟环境已激活,然后运行:

复制代码
streamlit run app.py

命令执行后,Streamlit通常会自动在你的默认浏览器中打开应用 (地址通常是 http://localhost:8501)。如果未自动打开,你可以手动在浏览器中输入这个地址。

第五步:开始对话与故障排查

现在应该能看到一个简洁的聊天界面。

  • 开始对话:在底部输入框输入问题,比如"介绍一下你自己",然后按回车或点击发送。

  • 故障排查

    • 如果连接失败 :首先检查运行 ollama serve的终端是否正常,没有报错信息。

    • 验证Ollama API :可以新开一个终端,用命令 curl http://localhost:11434/api/tags测试,如果返回包含模型名称的JSON信息,说明API服务正常。

    • 端口冲突:如果8501端口被占用,Streamlit会提示并使用新端口(如8502),按提示访问即可。

💡 核心要点与进阶技巧

环节 关键点/技巧 说明
Ollama服务 保持运行 运行Streamlit应用时,ollama serve必须始终在后台运行。
对话体验 上下文记忆 代码通过 st.session_state.messages自动维护对话历史,实现连续对话。
性能优化 硬件资源 如果拥有NVIDIA显卡并配置了CUDA,Ollama会自动利用GPU加速推理。
功能扩展 模型切换 可在侧边栏添加下拉框,集成 ollama list获取的模型列表,让用户自由切换不同模型。
部署分享 网络访问 除了本地访问,你还可以通过 http://<你的WSL IP>:8501在同局域网下的其他设备(如手机、平板)上访问此应用。
相关推荐
PTC2 小时前
做了个 EPUB 阅读器,被「阅读进度同步」折磨了一周,总结 4 个血泪教训
前端
Aaron_Feng2 小时前
适配Swift 6 Sendable:用AALock优雅解决线程安全与不可变引用难题
前端
大时光2 小时前
gsap 配置解读 --7
前端
念念不忘 必有回响3 小时前
前端判断文本是否溢出:单行与多行场景的完整解析
前端·javascript·css·vue.js
先做个垃圾出来………3 小时前
HTTP 请求中 Content-Type 常见取值
chrome·网络协议·http
css趣多多3 小时前
vue3的组件间通信ref子组件需要把父组件要的ref数据开放
前端·javascript·vue.js
我是伪码农3 小时前
Vue 2.10
前端·javascript·vue.js
AAA阿giao3 小时前
React 性能优化双子星:深入、全面解析 useMemo 与 useCallback
前端·javascript·react.js
不想秃头的程序员3 小时前
父传子全解析:从基础到实战,新手也能零踩坑
前端·vue.js·面试