ERNIE-4.5-0.3B-PT Chainlit前端定制:添加历史记录导出与多会话管理功能
ERNIE-4.5-0.3B-PT Chainlit前端定制添加历史记录导出与多会话管理功能在实际使用大语言模型时一个好用的前端界面往往比模型本身更能影响日常体验。Chainlit作为轻量级、可定制的AI应用框架天然适合快速搭建对话界面。但开箱即用的Chainlit默认只提供基础聊天功能——没有历史记录导出、无法切换多个独立会话、对话内容无法本地留存。对于需要反复测试提示词、对比不同回答、或进行教学演示的用户来说这些缺失功能会明显拖慢效率。本文不讲模型原理也不重复部署步骤而是聚焦一个真实痛点如何让Chainlit前端真正“能用”、“好用”、“长期用”。我们将基于已部署的vLLM版ERNIE-4.5-0.3B-PT模型从零开始为Chainlit添加两项关键能力一键导出当前会话全部历史支持Markdown格式保留代码块、加粗等富文本样式独立多会话管理每个会话隔离上下文、独立命名、自由切换、关闭后不丢失所有改动均基于Chainlit官方API无需修改底层框架代码简洁、逻辑清晰、可直接复用。即使你刚接触Chainlit也能在30分钟内完成集成。1. 环境确认与基础准备在开始定制前请确保你的ERNIE-4.5-0.3B-PT模型已通过vLLM成功部署并且Chainlit前端可正常访问。这不是教程的重复而是为你节省排查时间的关键检查点。1.1 验证模型服务是否就绪打开WebShell终端执行以下命令查看日志cat /root/workspace/llm.log如果看到类似INFO: Uvicorn running on http://0.0.0.0:8000和vLLM engine started的输出说明服务已启动。若日志中出现ERROR或长时间无响应请先返回部署环节检查端口、GPU显存和模型路径。小贴士vLLM默认监听http://localhost:8000Chainlit需通过该地址调用。若你修改过vLLM端口如改为8080后续Chainlit配置中必须同步更新否则会显示“连接失败”。1.2 确认Chainlit项目结构Chainlit应用的核心是chainlit.py文件。请确认你的项目根目录下存在该文件并且其内容包含基础的cl.on_message装饰器逻辑。这是我们将要扩展的起点。如果你使用的是CSDN星图镜像广场提供的预置环境通常项目结构如下/workspace/ ├── chainlit.py ← 我们将在此文件中添加新功能 ├── requirements.txt └── .env ← 可存放vLLM API地址等配置注意不要在chainlit.py中硬编码vLLM地址如http://localhost:8000。建议通过环境变量读取便于后续迁移。我们将在代码中示范这一最佳实践。2. 实现多会话管理让每次对话互不干扰默认Chainlit将所有消息存入全局会话导致用户无法同时进行“写周报”、“改简历”、“查技术文档”三个任务。多会话管理的本质是为每组对话分配唯一ID并在内存中维护独立的消息列表。2.1 设计会话状态结构我们不依赖数据库而是利用Chainlit内置的cl.user_session对象——它为每个浏览器标签页提供独立的键值存储空间。我们将用它保存两个关键数据session_id: 当前会话唯一标识UUID生成messages: 当前会话的完整消息列表含角色、内容、时间戳这样用户新开一个浏览器标签就自动获得全新会话关闭标签后该会话数据自然释放不占用资源。2.2 添加会话创建与切换逻辑在chainlit.py开头添加以下导入和初始化代码import uuid import os from typing import Dict, List, Optional import chainlit as cl # 从环境变量读取vLLM API地址避免硬编码 VLLM_API_URL os.getenv(VLLM_API_URL, http://localhost:8000/v1/chat/completions) # 初始化用户会话首次访问时执行 cl.on_chat_start async def on_chat_start(): # 为本次会话生成唯一ID session_id str(uuid.uuid4()) # 在用户会话中保存ID和空消息列表 cl.user_session.set(session_id, session_id) cl.user_session.set(messages, []) # 向用户发送欢迎消息提示功能 await cl.Message( content 已创建新会话你可以随时点击左下角「 新会话」开启另一个独立对话。\n\n 小技巧每个会话的上下文完全隔离适合同时处理不同任务。, authorSystem ).send()2.3 构建会话控制UI按钮与状态栏Chainlit支持自定义侧边栏Sidebar我们在这里添加“新建会话”按钮和当前会话信息# 在 cl.on_chat_start 下方添加 cl.set_chat_profiles async def chat_profile(): return [ cl.ChatProfile( nameERNIE-4.5-0.3B-PT, markdown_description基于vLLM加速的轻量级中文大模型专注高效推理。, icon ) ] # 侧边栏添加会话管理控件 cl.on_settings_update async def setup_sidebar(settings): pass # 在 cl.on_chat_start 后添加此函数用于渲染侧边栏 cl.on_chat_resume async def on_chat_resume(): # 恢复会话时重新设置状态可选增强健壮性 session_id cl.user_session.get(session_id) if not session_id: await on_chat_start() # 侧边栏组件需放在 cl.on_chat_start 之后 cl.on_chat_start async def setup_sidebar(): # 创建侧边栏按钮 await cl.ChatSettings( [ cl.RadioGroup( idsession_action, label会话操作, values[new, export], description选择操作类型 ), ] ).send()为什么不用传统按钮Chainlit的cl.Action在v0.10版本中对异步支持不稳定。我们采用更可靠的cl.ChatSettingscl.RadioGroup组合用户点击后触发回调稳定且兼容性好。2.4 处理会话切换事件当用户点击“ 新会话”时我们需要清空当前消息、生成新ID、并刷新界面# 在文件末尾添加事件处理器 cl.action_callback(New Session) async def on_new_session(action): # 清空当前会话消息 cl.user_session.set(messages, []) # 生成新会话ID new_id str(uuid.uuid4()) cl.user_session.set(session_id, new_id) # 发送确认消息 await cl.Message( contentf 已切换至新会话{new_id[:8]}... \n现在可以开始全新对话了, authorSystem ).send()至此多会话管理的核心逻辑已完成。用户可无限次点击“ 新会话”每次都会获得干净、隔离的对话空间彻底告别上下文串扰。3. 实现历史记录导出一键保存为可读Markdown导出功能的价值在于把临时对话变成可复用的知识资产。我们不导出原始JSON而是生成带格式、易阅读、可直接粘贴到笔记软件的Markdown文件。3.1 定义导出内容结构一个高质量的导出文件应包含会话标题自动生成ERNIE对话 - 2025-03-15 14:23模型信息ERNIE-4.5-0.3B-PT vLLM完整对话流用户提问用引用块模型回复用普通段落代码块原样保留时间戳精确到分钟标注每条消息时间3.2 编写导出函数在chainlit.py中添加以下工具函数from datetime import datetime import re def format_message_for_export(message: cl.Message) - str: 将Chainlit Message对象格式化为Markdown字符串 role 用户 if message.author User else ERNIE timestamp message.created_at.strftime(%H:%M) if message.created_at else 未知时间 # 处理消息内容保留代码块、加粗、列表等Markdown语法 content message.content # 若内容含代码块确保其被正确包裹 if in content: # 简单处理不破坏原有代码块 pass # 构建Markdown行 if message.author User: return f **{role}{timestamp}**\n {content}\n else: return f**{role}{timestamp}**\n{content}\n def generate_export_content() - str: 生成完整的Markdown导出内容 messages cl.user_session.get(messages, []) session_id cl.user_session.get(session_id, unknown) # 生成标题 now datetime.now().strftime(%Y-%m-%d %H:%M) title f# ERNIE对话记录 - {now}\n\n # 添加模型信息 info f**模型**ERNIE-4.5-0.3B-PTvLLM加速\n**会话ID**{session_id}\n\n---\n\n # 拼接所有消息 content_lines [] for msg in messages: if hasattr(msg, content) and msg.content.strip(): content_lines.append(format_message_for_export(msg)) return title info \n.join(content_lines)3.3 添加导出按钮与下载逻辑Chainlit不直接支持文件下载但我们可以通过cl.Text组件将内容渲染为可复制文本并引导用户手动保存cl.action_callback(Export History) async def on_export_history(action): # 生成导出内容 md_content generate_export_content() # 创建Text元素设置为可复制 text_element cl.Text( nameernie-history.md, contentmd_content, displayinline, languagemarkdown ) # 发送消息附带Text元素 await cl.Message( content 历史记录已生成\n\n 点击下方「复制」按钮然后粘贴到任意文本编辑器如VS Code、Typora中保存为 .md 文件。\n\n 提示导出内容保留所有格式代码块、加粗、引用可直接用于知识沉淀。, elements[text_element], authorSystem ).send()为什么不强制下载浏览器安全策略限制前端JavaScript直接触发文件下载尤其跨域场景。cl.Text方案100%兼容所有环境且用户可自由编辑导出内容比一键下载更灵活、更可靠。4. 集成vLLM调用确保定制功能与模型无缝协作前面所有UI功能都依赖于模型的实际响应。我们需要确保cl.on_message逻辑既能正确调用vLLM又能将新消息存入当前会话的历史列表。4.1 改写消息处理函数替换原有的cl.on_message加入历史记录保存与错误处理import httpx cl.on_message async def main(message: cl.Message): # 获取当前会话消息列表 messages cl.user_session.get(messages, []) # 将用户消息加入历史注意Chainlit 1.0 中 message.content 是字符串 user_msg cl.Message( contentmessage.content, authorUser, created_atdatetime.now() ) messages.append(user_msg) # 发送用户消息到前端实时显示 await user_msg.send() # 构造vLLM请求体符合OpenAI兼容API格式 payload { model: ernie-4.5-0.3b-pt, messages: [ {role: user, content: message.content} ], temperature: 0.7, max_tokens: 1024 } try: # 异步调用vLLM async with httpx.AsyncClient() as client: response await client.post( VLLM_API_URL, jsonpayload, timeout120.0 ) if response.status_code 200: data response.json() assistant_reply data[choices][0][message][content] # 创建模型回复消息 ai_msg cl.Message( contentassistant_reply, authorERNIE-4.5-0.3B-PT, created_atdatetime.now() ) messages.append(ai_msg) # 更新用户会话中的消息列表 cl.user_session.set(messages, messages) # 发送回复 await ai_msg.send() else: error_msg f 模型调用失败{response.status_code}{response.text[:100]} await cl.Message(contenterror_msg, authorSystem).send() except Exception as e: error_msg f 请求超时或网络异常{str(e)} await cl.Message(contenterror_msg, authorSystem).send()4.2 关键细节说明消息持久化时机我们在收到用户输入后立即存入messages列表并在模型返回后追加AI回复。这样即使中途断网用户消息也不会丢失。vLLM兼容性ERNIE-4.5-0.3B-PT通过vLLM部署后暴露的是标准OpenAI格式API因此我们直接使用messages字段传参无需额外适配。错误降级体验当vLLM不可用时用户仍能看到清晰的错误提示而不是卡死或空白保障基础可用性。5. 运行与验证三步确认功能生效完成以上代码修改后只需三步即可验证全部功能5.1 重启Chainlit服务在WebShell中执行# 停止旧进程如有 pkill -f chainlit run # 启动新版本 chainlit run chainlit.py -w注意-w参数启用热重载修改代码后无需手动重启保存即生效。5.2 执行功能测试多会话测试打开两个浏览器标签页分别访问http://localhost:8000。在第一个标签中问“今天天气如何”在第二个中问“Python怎么读取CSV”。确认两个会话的回答互不影响。导出测试在任一会话中进行3轮以上问答点击侧边栏「Export History」。检查弹出的文本框是否包含完整对话、时间戳、格式标记。边界测试尝试发送空消息、超长文本2000字、含代码的提问如“写一个Python函数”确认系统不崩溃且导出内容格式正确。5.3 常见问题自查清单现象可能原因解决方案点击“New Session”无反应cl.Action未正确定义或ID不匹配检查cl.action_callback中的字符串是否与按钮ID一致导出内容缺少时间戳message.created_at为None在cl.Message()初始化时显式传入created_atdatetime.now()vLLM调用返回404VLLM_API_URL地址错误运行curl http://localhost:8000/docs确认vLLM Swagger UI可访问侧边栏不显示cl.set_chat_profiles或cl.on_chat_start位置错误确保所有装饰器函数定义在文件顶层且无缩进错误6. 总结让AI工具真正服务于人我们没有改动ERNIE-4.5-0.3B-PT模型本身也没有重写vLLM推理引擎。只是在Chainlit这个“对话窗口”上增加了两处看似微小却极大提升体验的功能多会话管理解决了“我同时有好几个想法要试但总被上一个对话带偏”的困扰历史导出把稍纵即逝的对话变成了可搜索、可归档、可分享的知识片段。这恰恰体现了工程实践的真谛最强大的技术不是参数量最大的模型而是让用户忘记技术存在的工具。你完全可以基于本文代码继续扩展→ 加入会话命名功能双击会话ID编辑→ 支持导出为PDF调用weasyprint库→ 添加会话搜索用SQLite本地存储全文索引所有这些都始于一个清晰的目标不为炫技只为好用。--- **获取更多AI镜像** 想探索更多AI镜像和应用场景访问 [CSDN星图镜像广场](https://ai.csdn.net/?utm_sourcemirror_blog_end)提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

相关新闻

GLM-Image模型量化:4倍显存优化实践

GLM-Image模型量化:4倍显存优化实践

GLM-Image模型量化:4倍显存优化实践 1. 为什么需要为GLM-Image做量化 在实际部署GLM-Image模型时,很多团队都遇到了一个现实问题:显存不够用。官方文档显示,完整精度的GLM-Image模型在推理时需要约16GB显存,这直接限…

2026/5/17 2:40:23 阅读更多 →
Atelier of Light and Shadow助力Git版本控制:智能代码审查与合并

Atelier of Light and Shadow助力Git版本控制:智能代码审查与合并

Atelier of Light and Shadow助力Git版本控制:智能代码审查与合并 1. 为什么你的团队需要更聪明的Git工作流 你有没有遇到过这样的场景:凌晨两点,一个紧急修复分支要合并进主干,但冲突提示密密麻麻,十几处文件需要手…

2026/5/17 2:40:21 阅读更多 →
QwQ-32B开源大模型:ollama中32B模型与7B/14B推理效果对比

QwQ-32B开源大模型:ollama中32B模型与7B/14B推理效果对比

QwQ-32B开源大模型:ollama中32B模型与7B/14B推理效果对比 1. 为什么QwQ-32B值得你多看一眼 你有没有试过让AI解一道逻辑题,结果它直接跳步骤、绕开关键矛盾,最后给出个似是而非的答案?或者写一段技术方案,它堆砌术语…

2026/5/17 2:40:20 阅读更多 →

最新新闻

Ubuntu 22.04 配置 NFS 服务端:3 步实现开发板免拷贝文件共享

Ubuntu 22.04 配置 NFS 服务端:3 步实现开发板免拷贝文件共享

Ubuntu 22.04 高效开发板文件共享:NFS服务端配置全指南在嵌入式开发和Linux系统管理中,频繁地在开发主机与开发板之间传输文件是一项常见但耗时的任务。传统方法如SCP、SFTP或U盘拷贝不仅效率低下,还会打断开发流程。本文将详细介绍如何在Ubu…

2026/7/6 21:36:29 阅读更多 →
learn-opengl入门

learn-opengl入门

opengl是一个大状态机 环境配置 1.下载GLFW源代码 2.创建librarel文件包含include目录和第三方库libs 3.include直接从GLFW的源代码中拿,libs里需要编译生成的库glfw3.lib。 4.通过CMake编译源代码拿到glfw3.lib。 5.将我们的librarel加入编辑器的包含文件和库目录里&#xff0…

2026/7/6 21:34:28 阅读更多 →
初入编程世界感觉眼花缭乱?

初入编程世界感觉眼花缭乱?

眼花缭乱有没有?抽象理解第一个C语言程序1. C语言是什么概括:多用于底层开发的,面向过程的编程语言2. 上来就写程序?我开始也觉得不合理,哪有上来就敲代码嘛...QAQ其实不然,一个最简单的“Hello world”程序…

2026/7/6 21:34:28 阅读更多 →
@Async异步线程:Spring 自带的异步解决方案

@Async异步线程:Spring 自带的异步解决方案

前言 在项目应用中,使用MQ异步调用来实现系统性能优化,完成服务间数据同步是常用的技术手段。如果是在同一台服务器内部,不涉及到分布式系统,单纯的想实现部分业务的异步执行,这里介绍一个更简单的异步方法调…

2026/7/6 21:30:26 阅读更多 →
揭秘HQTrack核心架构:InternT-MSDeAOTL-V2模型如何实现高精度实时追踪?

揭秘HQTrack核心架构:InternT-MSDeAOTL-V2模型如何实现高精度实时追踪?

揭秘HQTrack核心架构:InternT-MSDeAOTL-V2模型如何实现高精度实时追踪? 【免费下载链接】HQTrack Tracking Anything in High Quality 项目地址: https://gitcode.com/gh_mirrors/hq/HQTrack 你是否曾想过,如何让计算机像人类一样精准…

2026/7/6 21:28:26 阅读更多 →
从 0 新增一个 has.echo:我如何理解小程序容器里的 API 调用链路

从 0 新增一个 has.echo:我如何理解小程序容器里的 API 调用链路

从 0 新增一个 has.echo:我如何理解小程序容器里的 API 调用链路说明:本文是一次脱敏后的学习复盘。文中的 has.echo、EchoModule、system.demo 都是为了讲清楚调用链路而设计的最小示例,不包含公司内部源码、真实业务接口、真实模块路径和敏…

2026/7/6 21:28:26 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻