Phi-3-Mini-128K代码实例:基于session_state实现多轮对话记忆的Streamlit实践

发布时间:2026/7/3 12:13:34

Phi-3-Mini-128K代码实例:基于session_state实现多轮对话记忆的Streamlit实践 Phi-3-Mini-128K代码实例基于session_state实现多轮对话记忆的Streamlit实践想体验一个能记住对话上下文的本地AI助手吗今天我们就来动手搭建一个。基于微软开源的轻量级大模型Phi-3-mini-128k-instruct我将带你一步步实现一个拥有多轮对话记忆的聊天应用。整个过程完全本地运行无需联网只需几行代码就能在你的电脑上复现类似ChatGPT的交互体验。这个项目的核心是解决一个常见痛点很多开源模型部署后每次对话都是独立的模型“记不住”之前的聊天内容。我们将利用Streamlit框架的session_state功能巧妙地让模型拥有“记忆”实现真正的连续对话。无论你是想深入理解大模型部署还是需要一个私密的本地AI助手这篇文章都能给你清晰的指引和可运行的代码。1. 项目核心为什么需要多轮对话记忆在开始写代码之前我们先搞清楚要解决什么问题。你可能有这样的经历部署了一个本地模型第一次问“今天的天气怎么样”它回答“我是AI无法获取实时天气”。接着你再问“那我该穿什么”它很可能一脸茫然因为它根本不记得你刚才问过天气。这就是单轮对话的局限。模型每次推理都只基于当前输入的提示词Prompt历史对话被丢弃了。而多轮对话记忆意味着模型能将整个对话历史作为上下文来理解你的新问题从而给出连贯、符合逻辑的回复。这对于代码调试、故事接龙、复杂问题分解等场景至关重要。我们的解决方案技术栈非常清晰模型核心微软 Phi-3-mini-128k-instruct。它小巧38亿参数但能力不俗最关键的是支持长达128K token的上下文为长对话提供了可能。推理框架Hugging Face Transformers。使用其pipeline工具可以省去我们手动拼接复杂对话格式的麻烦。交互界面Streamlit。用Python快速构建Web应用的利器其session_state功能是实现“记忆”的关键。记忆机制利用Streamlit的session_state在服务器会话中持久化存储对话历史列表。简单来说session_state就像一个在页面刷新期间也不会丢失的“记事本”我们把每一轮对话都记在上面每次提问时就把整个“记事本”的内容都交给模型作为上下文。接下来我们就看看具体怎么实现。2. 环境搭建与模型准备工欲善其事必先利其器。我们先来准备好运行所需的一切。2.1 创建环境与安装依赖首先建议创建一个独立的Python虚拟环境避免包版本冲突。打开你的终端或命令行工具执行以下步骤# 1. 创建并激活虚拟环境以conda为例你也可以使用venv conda create -n phi3-chatbot python3.10 conda activate phi3-chatbot # 2. 安装PyTorch请根据你的CUDA版本选择合适的命令以下为CUDA 11.8示例 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 3. 安装核心依赖 pip install transformers streamlit accelerate关键依赖说明torch模型运行的底层框架。transformersHugging Face库用于加载和运行Phi-3模型。streamlit用于构建Web交互界面。accelerate帮助优化模型在GPU上的加载和运行特别是device_mapauto功能可以让模型智能分配在不同GPU或CPU上。2.2 获取与加载Phi-3模型Phi-3-mini-128k-instruct模型已经在Hugging Face Model Hub上开源。我们不需要手动下载transformers库会在第一次运行时自动从网络下载。但为了国内更快的速度你可以考虑先通过镜像站下载。这里我们直接使用transformers.pipeline来加载模型这是最简单的方式。pipeline会自动处理模型加载、分词、生成等全套流程。创建一个名为app.py的Python文件我们先写入模型加载的代码。为了优化显存占用我们采用bfloat16半精度格式这能将显存需求从约14GB降低到7-8GB。# app.py - 第一部分导入库和模型加载函数 import torch from transformers import AutoTokenizer, pipeline import streamlit as st st.cache_resource # Streamlit缓存装饰器避免重复加载模型 def load_model(): model_id microsoft/Phi-3-mini-128k-instruct print(正在加载分词器...) tokenizer AutoTokenizer.from_pretrained(model_id) print(正在通过Pipeline加载模型这可能需要几分钟请耐心等待...) # 使用bfloat16半精度以节省显存device_mapauto自动分配GPU/CPU pipe pipeline( text-generation, modelmodel_id, tokenizertokenizer, torch_dtypetorch.bfloat16, device_mapauto, ) print(模型加载成功) return pipe # 尝试加载模型 try: model_pipeline load_model() st.success(Phi-3 模型已就绪) except Exception as e: st.error(f模型加载失败: {e}) st.stop()把这段代码保存后在终端运行streamlit run app.py你会看到Streamlit启动并开始在后台下载模型。首次下载需要一定时间模型约8GB请保持网络通畅。加载成功后页面会显示“Phi-3 模型已就绪”。3. 构建交互界面与聊天逻辑模型准备好之后我们来打造聊天界面和核心的对话逻辑。这部分是用户体验的关键。3.1 初始化聊天历史与界面布局我们使用Streamlit的session_state来存储聊天记录。session_state是Streamlit为每个用户会话提供的持久化字典刷新页面不会丢失除非关闭浏览器标签。# app.py - 第二部分初始化session_state和页面布局 # 初始化session_state中的聊天历史如果不存在则创建空列表 if messages not in st.session_state: st.session_state.messages [] # 设置页面标题和图标 st.set_page_config(page_titlePhi-3 本地聊天助手, page_icon) st.title( Phi-3 Mini 本地聊天助手) st.caption(纯本地运行 · 支持128K长上下文 · 拥有多轮对话记忆) # 在侧边栏显示一些信息和控制项 with st.sidebar: st.header(关于) st.markdown( **模型**: Phi-3-mini-128k-instruct **参数**: 38亿 **上下文**: 128K tokens **运行**: 本地GPU/CPU ) st.divider() # 提供一个清空对话历史的按钮 if st.button(清空对话历史, use_container_widthTrue): st.session_state.messages [] st.rerun() # 清空后立即刷新界面 # 显示聊天历史记录 for message in st.session_state.messages: # 根据角色user/assistant显示不同的头像和样式 with st.chat_message(message[role]): st.markdown(message[content])这段代码做了几件事确保st.session_state.messages这个列表存在用来存所有的对话消息。设置了一个好看的页面标题和说明。在侧边栏添加了模型信息和一个非常重要的“清空对话历史”按钮。没有这个按钮对话会一直累积直到超出模型上下文长度。遍历messages列表将之前所有的对话记录都显示在页面上。st.chat_message会自动根据角色渲染出类似ChatGPT的气泡样式。3.2 实现用户输入与模型响应现在我们来处理最核心的部分接收用户输入调用模型生成回复并把这一轮对话保存到历史中。# app.py - 第三部分处理用户输入和模型生成 # 显示一个聊天输入框等待用户输入 if prompt : st.chat_input(请输入您的问题...): # 1. 将用户输入立刻显示在聊天界面上 with st.chat_message(user): st.markdown(prompt) # 2. 将用户消息添加到session_state的历史记录中 st.session_state.messages.append({role: user, content: prompt}) # 3. 准备调用模型生成回复先显示一个“思考中”的占位符 with st.chat_message(assistant): message_placeholder st.empty() # 创建一个空占位符 message_placeholder.markdown(Phi-3 正在飞速思考...) # 4. 构建模型所需的对话格式 # pipeline会自动将我们的消息列表转换为模型需要的格式 # 我们直接传入整个对话历史即可 try: # 调用模型管道生成回复 # max_new_tokens控制生成文本的最大长度temperature控制随机性 response model_pipeline( st.session_state.messages, # 传入完整的历史消息 max_new_tokens512, temperature0.7, do_sampleTrue, ) # 从返回结果中提取生成的文本 full_response response[0][generated_text][-1][content] except Exception as e: full_response f抱歉生成回复时出错了: {e} # 5. 将模型回复的“思考中”占位符替换为实际内容 message_placeholder.markdown(full_response) # 6. 将助手的回复也添加到历史记录中完成本轮对话的保存 st.session_state.messages.append({role: assistant, content: full_response})代码逻辑解读st.chat_input会渲染一个位于页面底部的输入框类似微信。用户输入内容并按下回车后prompt变量就获取到了输入文本。我们立刻将用户的问题用st.chat_message显示出来并存入session_state.messages。紧接着我们准备显示模型的回复。先创建一个assistant角色的消息气泡并放入一个“思考中...”的占位文本。这给了用户即时的反馈知道模型正在工作。关键步骤调用model_pipeline时我们传入的是st.session_state.messages即包含当前用户问题和所有历史对话的完整列表。模型正是基于这个完整的上下文来生成回复的。max_new_tokens和temperature是控制生成文本长度和创造性的参数你可以按需调整。生成完成后我们用实际回复内容替换掉之前的“思考中...”占位符。最后将模型的回复也存入session_state.messages。这样下一轮对话时历史记录就包含了本轮的所有内容。至此一个具备完整记忆功能的多轮对话系统就实现了。你可以连续问它问题比如第一轮“用Python写一个计算斐波那契数列的函数。”第二轮“优化一下这个函数的时间复杂度。”第三轮“为优化后的函数添加详细的注释。”模型在回答第二、第三个问题时会参考之前的代码和对话给出连贯的回应。4. 功能增强与实用技巧基础功能已经完成但我们可以让它更好用、更健壮。下面是一些实用的增强技巧。4.1 处理长上下文与性能优化Phi-3支持128K上下文但我们的对话历史会越来越长。直接传入超长的历史列表可能会导致生成速度变慢甚至超出模型处理能力。我们需要一个截断策略。# 在调用模型生成之前可以添加一个历史记录截断函数 def prepare_chat_history(messages, max_history_turns10): 保留最近N轮对话避免上下文过长。 在实际应用中更科学的做法是根据token数量来截断。 # 简单示例只保留最近10轮对话即20条消息一问一答为一轮 return messages[-(max_history_turns * 2):] if len(messages) max_history_turns * 2 else messages # 然后在调用model_pipeline时使用截断后的历史 truncated_messages prepare_chat_history(st.session_state.messages, max_history_turns10) response model_pipeline( truncated_messages, # 使用截断后的历史 max_new_tokens512, temperature0.7, )更高级的截断策略上述方法按轮数截断不够精确。更好的方法是使用分词器计算token数量。你可以尝试在prepare_chat_history函数中使用tokenizer将消息内容转换为token并计数确保总token数不超过一个安全阈值如120K为生成留出空间。4.2 添加流式输出效果目前是等模型全部生成完再一次性显示。我们可以实现像ChatGPT那样的逐字输出效果体验更佳。# 修改模型调用和显示部分实现流式输出 with st.chat_message(assistant): message_placeholder st.empty() full_response # 注意这里使用模型的generate方法并设置streamer参数而非直接调用pipeline # 为简化示例以下为概念代码。实际需根据pipeline的具体streamer配置调整。 # 通常需要从model_pipeline中取出底层的model和tokenizer inputs tokenizer.apply_chat_template(st.session_state.messages, return_tensorspt).to(model.device) # 创建一个文本流生成器 from transformers import TextStreamer streamer TextStreamer(tokenizer, skip_promptTrue) # 生成 tokens generated_ids model.generate( inputs, max_new_tokens512, streamerstreamer, do_sampleTrue, temperature0.7, ) # 在Streamlit中我们需要自定义一个流式渲染逻辑 # 一个简单的模拟流式效果的方法是分块更新placeholder for chunk in simulated_streamer(full_response): # simulated_streamer需要你自己实现将生成文本分块 full_response chunk message_placeholder.markdown(full_response ▌) # 添加光标效果 message_placeholder.markdown(full_response) # 最终移除光标流式输出实现起来稍复杂因为它需要直接操作模型底层的generate方法和分词器。上面的代码提供了一个思路。一个更简单的替代方案是即使不使用真正的token流也可以用循环模拟出一种“正在打字”的效果提升用户体验。4.3 错误处理与用户体验优化让应用更稳定提供更好的反馈。# 在模型加载和生成部分添加更细致的错误处理和状态提示 import sys # 在页面顶部添加一个状态区域 status_area st.empty() # 在load_model函数和生成回复的try-catch块中更新状态信息 with status_area: with st.status(正在初始化模型和组件..., expandedFalse) as status: st.write(检查环境...) # ... 执行一些检查 st.write(加载分词器...) # ... 加载tokenizer st.write(加载模型权重...) # ... 加载模型 status.update(label加载完成, statecomplete, expandedFalse) # 在生成回复时如果遇到特定错误如显存不足给出友好提示 try: response model_pipeline(...) except torch.cuda.OutOfMemoryError: st.error(显存不足建议尝试1. 减少max_new_tokens2. 清空对话历史3. 重启应用释放显存。) st.session_state.messages.pop() # 移除刚才添加的用户消息避免卡住 st.rerun() except Exception as e: st.error(f生成过程发生错误: {e}) # 可以选择记录日志5. 总结与完整代码让我们回顾一下整个项目的核心要点并提供一个整合后的、可直接运行的app.py完整代码。5.1 核心要点回顾记忆的本质多轮对话记忆的核心在于持久化存储完整的对话历史。我们利用Streamlit的session_state在服务器端实现了这一点。上下文的传递每次生成回复时将st.session_state.messages这个包含所有历史的列表整个传递给模型的pipeline。transformers的chat模板会自动将其处理成模型能理解的格式。显存优化通过torch.bfloat16半精度加载模型将显存占用减半让更多设备可以运行。简易的交互Streamlit极大地简化了Web界面的开发让我们能专注于对话逻辑本身。5.2 完整代码示例将前面所有部分整合并做适当简化得到一个可直接运行的版本# app.py - 完整可运行版本 import torch from transformers import AutoTokenizer, pipeline import streamlit as st # 设置页面 st.set_page_config(page_titlePhi-3 本地聊天助手, page_icon) st.title( Phi-3 Mini 本地聊天助手) st.caption(纯本地运行 · 支持128K长上下文 · 拥有多轮对话记忆) # 初始化对话历史 if messages not in st.session_state: st.session_state.messages [] # 侧边栏信息和控制 with st.sidebar: st.header(控制面板) if st.button(清空对话历史, typesecondary, use_container_widthTrue): st.session_state.messages [] st.rerun() st.divider() st.header(模型信息) st.markdown( - **名称**: Phi-3-mini-128k-instruct - **来源**: Microsoft - **上下文**: 128,000 tokens - **精度**: bfloat16 (显存优化) - **运行状态**: 本地推理 ) # 加载模型使用缓存避免重复加载 st.cache_resource def load_phi3_model(): model_id microsoft/Phi-3-mini-128k-instruct tokenizer AutoTokenizer.from_pretrained(model_id) # 使用pipeline简化调用自动处理对话格式 pipe pipeline( text-generation, modelmodel_id, tokenizertokenizer, torch_dtypetorch.bfloat16, device_mapauto, model_kwargs{trust_remote_code: True} ) return pipe # 主程序开始 try: model_pipe load_phi3_model() except Exception as e: st.error(f模型加载失败请检查: {e}) st.stop() # 显示历史聊天记录 for msg in st.session_state.messages: with st.chat_message(msg[role]): st.markdown(msg[content]) # 处理用户输入 if user_input : st.chat_input(和 Phi-3 对话...): # 显示并保存用户消息 with st.chat_message(user): st.markdown(user_input) st.session_state.messages.append({role: user, content: user_input}) # 生成助手回复 with st.chat_message(assistant): message_placeholder st.empty() message_placeholder.markdown(思考中...) try: # 关键将整个对话历史传入模型 response model_pipe( st.session_state.messages, max_new_tokens1024, # 生成文本的最大长度 temperature0.7, # 控制随机性0.0为确定性输出1.0更随机 do_sampleTrue, ) # 提取助手的回复内容 assistant_reply response[0][generated_text][-1][content] except Exception as e: assistant_reply f生成回复时遇到错误: {str(e)} # 显示回复 message_placeholder.markdown(assistant_reply) # 保存助手回复到历史 st.session_state.messages.append({role: assistant, content: assistant_reply})5.3 如何运行与下一步运行将上述代码保存为app.py在激活的虚拟环境中运行streamlit run app.py。首次运行会自动从Hugging Face下载模型约8GB请耐心等待。加载成功后浏览器会自动打开应用界面。开始对话在底部输入框提问体验多轮对话。清空历史点击侧边栏的“清空对话历史”按钮。你可以在此基础上继续探索调整参数修改max_new_tokens、temperature来改变生成文本的长度和创造性。添加上下文管理实现更智能的历史截断逻辑基于token数而非轮数。扩展功能添加文件上传让模型处理本地文档集成语音输入输出部署到服务器供团队使用。这个项目不仅是一个可用的工具更是一个理解大模型本地部署、对话系统构建和Streamlit应用的绝佳起点。动手试试吧感受一下在本地电脑上运行一个“有记忆”的AI助手是什么体验。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

相关新闻