网络绿化网站建设哪家专业WordPress影视采集
网络绿化网站建设哪家专业,WordPress影视采集,网络营销推广引流方式,昆山哪里做网站好GLM-4-9B-Chat-1M实战教程#xff1a;Chainlit中添加流式响应打字机效果
你是不是也遇到过这种情况#xff1a;调用大模型接口#xff0c;输入问题后#xff0c;屏幕一片空白#xff0c;等了好一会儿#xff0c;答案才“唰”一下全部显示出来。等待的过程不仅枯燥#…GLM-4-9B-Chat-1M实战教程Chainlit中添加流式响应打字机效果你是不是也遇到过这种情况调用大模型接口输入问题后屏幕一片空白等了好一会儿答案才“唰”一下全部显示出来。等待的过程不仅枯燥而且完全不知道模型“思考”到哪一步了体验感大打折扣。今天我们就来解决这个问题。我将手把手教你如何为基于vLLM部署的GLM-4-9B-Chat-1M大模型在Chainlit前端中实现流式响应和打字机效果。简单来说就是让模型的回答像真人打字一样一个字一个字地“流”出来实时看到生成过程体验瞬间提升几个档次。1. 准备工作与环境确认在开始动手之前我们需要确保两件事模型服务已经跑起来了并且你知道怎么和它对话。1.1 确认vLLM服务状态我们的GLM-4-9B-Chat-1M模型是通过vLLM部署的。首先打开终端比如WebShell检查服务是否正常。输入以下命令查看服务日志cat /root/workspace/llm.log如果看到类似下面的输出特别是出现了Uvicorn running on和model loaded这样的关键信息就说明模型服务已经成功启动并在8000端口监听请求了。INFO: Started server process [1] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRLC to quit) INFO 07-10 10:00:00 llm_engine.py:721] Initializing an LLM engine (v0.5.2) with config: model/root/workspace/models/glm-4-9b-chat-1m, ... INFO 07-10 10:00:05 llm_engine.py:850] Model loaded in 125.34 s.1.2 了解基础调用方式服务起来后最基础的调用方式是通过HTTP接口。模型通常提供了一个/v1/chat/completions的端点我们用类似下面的代码就能拿到回复import requests url http://localhost:8000/v1/chat/completions headers {Content-Type: application/json} data { model: glm-4-9b-chat-1m, messages: [{role: user, content: 你好请介绍一下你自己。}], stream: False # 注意这里非流式 } response requests.post(url, jsondata, headersheaders) result response.json() print(result[choices][0][message][content])这种方式是一次性获取全部回复。而我们今天要做的就是把上面代码中的stream: False改成True并让Chainlit能处理这种“数据流”。2. 理解流式响应与打字机效果在动手改代码前花两分钟搞清楚原理后面会顺利很多。流式响应是什么想象一下用吸管喝饮料饮料是源源不断流出来的而不是一下子把整杯倒进嘴里。技术上说就是服务器不是等生成完所有文本再一次性发送给你而是每生成一小段比如一个词或几个词就立刻发送这一小段数据。这样客户端就能实时收到并展示。打字机效果则是流式响应在前端的一种直观呈现。它利用收到的一小段一小段数据通过JavaScript动态地、逐字地添加到网页的对话框里模拟出有人在打字的视觉效果。这不仅能缓解等待焦虑还能让你观察到模型的“思考”路径有时候挺有趣的。所以整个流程的链条是这样的你在Chainlit界面输入问题。Chainlit后端将问题以“流式”请求发送给vLLM服务。vLLM服务开始生成回答并一段段地往回发送数据流。Chainlit后端收到数据流再一段段地推送给前端浏览器。前端浏览器收到一段就在对话框里“打印”一段形成打字机效果。接下来我们就来搭建这个链条。3. 改造Chainlit后端支持流式请求默认的Chainlit示例可能用的是非流式调用。我们需要修改后端的逻辑让它能处理流式数据。3.1 创建或修改Chainlit应用文件在你的项目目录下创建一个名为app.py的文件如果已有直接修改。我们将编写一个完整的、支持流式对话的Chainlit应用。import chainlit as cl import aiohttp import json import sys # 配置vLLM服务器的地址和端口 VLLM_SERVER_URL http://localhost:8000/v1/chat/completions MODEL_NAME glm-4-9b-chat-1m async def query_llm_stream(messages): 以流式方式查询LLM返回一个异步生成器每次yield一个文本块。 headers {Content-Type: application/json} # 关键设置 streamTrue payload { model: MODEL_NAME, messages: messages, stream: True, max_tokens: 2048, # 你可以根据需要调整 temperature: 0.7, } async with aiohttp.ClientSession() as session: try: async with session.post(VLLM_SERVER_URL, jsonpayload, headersheaders) as resp: if resp.status ! 200: error_text await resp.text() yield f请求模型服务失败状态码{resp.status}错误信息{error_text} return # 逐行读取服务器返回的Server-Sent Events (SSE) 数据流 async for line in resp.content: line line.decode(utf-8).strip() if not line or line.startswith(:) or not line.startswith(data:): continue # SSE格式为 “data: {...}”需要去掉前缀 if line.startswith(data: ): json_str line[6:] # 去掉 “data: ” else: json_str line if json_str [DONE]: break try: data json.loads(json_str) if choices in data and len(data[choices]) 0: delta data[choices][0].get(delta, {}) content delta.get(content, ) if content: yield content except json.JSONDecodeError as e: # 忽略非JSON行或解析错误继续处理后续数据 print(f解析JSON行时出错: {e}, 原始行: {json_str}, filesys.stderr) continue except aiohttp.ClientConnectorError: yield 无法连接到模型服务请检查vLLM服务是否已启动。 except Exception as e: yield f调用模型时发生未知错误{str(e)} cl.on_message async def main(message: cl.Message): 处理用户发送的消息。 # 1. 准备对话历史。Chainlit会自动管理当前会话的消息历史。 # 我们获取历史消息并格式化成模型需要的结构。 history cl.user_session.get(message_history, []) history.append({role: user, content: message.content}) # 2. 发送一个初始的空消息用于后续流式更新内容 msg cl.Message(content) await msg.send() full_response # 3. 调用我们上面写的流式查询函数 async for chunk in query_llm_stream(history): # 4. 将收到的每个文本块chunk累加到完整回复中 full_response chunk # 5. 关键步骤流式更新前端显示的消息内容 await msg.stream_token(chunk) # 6. 流式更新完成后发送最终消息这一步很重要确保消息状态完成 await msg.update() # 7. 将本轮对话加入历史并保存回会话 history.append({role: assistant, content: full_response}) # 控制历史记录长度避免超出模型上下文这里示例保留最近10轮 if len(history) 20: # 10轮对话每轮user和assistant各一条 history history[-20:] cl.user_session.set(message_history, history) cl.on_chat_start async def start_chat(): 聊天开始时初始化一些设置。 # 初始化一个空的历史记录列表 cl.user_session.set(message_history, []) # 可以发送一个欢迎消息 await cl.Message(content你好我是基于GLM-4-9B-Chat-1M模型的助手支持流式回复哦。请问有什么可以帮您).send()代码关键点解析query_llm_stream函数这是核心。它使用aiohttp库异步地发送一个streamTrue的请求到vLLM服务器。服务器返回的是一个SSEServer-Sent Events数据流我们通过async for line in resp.content:逐行读取。数据解析每行数据格式是data: {...}我们需要去掉data:前缀然后将里面的JSON解析出来提取choices[0].delta.content字段这就是模型新生成的一小段文本。cl.Message.stream_token()这是Chainlit提供的“魔法”方法。它允许我们逐步更新一条消息的内容。每次收到一个文本块chunk就调用await msg.stream_token(chunk)前端就会实时显示这个块。await msg.update()流式发送完成后必须调用此方法来最终化消息状态。对话历史管理我们使用cl.user_session来为每个用户会话存储消息历史实现多轮对话。同时做了简单的长度限制防止超出模型1M上下文的处理能力实际项目中需要更精细的管理。3.2 安装依赖确保你的环境安装了必要的Python包。在终端执行pip install chainlit aiohttpaiohttp用于进行异步HTTP请求这是实现高效流式处理的关键。4. 运行并体验流式效果后端代码准备好了现在让我们启动它看看效果。4.1 启动Chainlit应用在包含app.py的目录下运行chainlit run app.py如果一切正常终端会输出类似下面的信息告诉你应用正在运行默认在http://localhost:8000注意不要和vLLM的8000端口冲突Chainlit默认是7860如果冲突可用--port指定其他端口。Your app is available at http://localhost:80004.2 在浏览器中访问打开浏览器访问http://localhost:8000或你指定的端口。你会看到Chainlit的聊天界面。初始欢迎根据我们的代码你会先收到一条欢迎消息。提问测试在底部的输入框里问一个需要一定长度回答的问题比如“请详细解释一下量子计算的基本原理。”观察效果按下回车后你应该会立刻看到回复区域出现一个光标然后文字开始一个词一个词地、一行一行地“打”出来而不是等待很久后一次性出现全文。这就是我们实现的流式响应和打字机效果5. 进阶优化与问题排查基本的流式效果已经实现了但你可能还想让它更好用。这里提供几个常见的优化方向和问题解决方法。5.1 如何调整“打字”速度Chainlit前端的打字机效果速度是自动的与后端发送数据块chunk的频率和大小有关。vLLM模型本身决定了生成和返回数据块的速度。通常情况下这个速度是自然且舒适的。如果你觉得太快或太慢可以尝试后端聚合在query_llm_stream函数中不每收到一个词就yield而是累积几个词或一小句再yield这样前端“打字”的间隔会变长但每次出现的字符数变多。# 示例简单聚合每收到3个chunk发送一次实际应根据内容判断如遇到标点 buffer count 0 async for chunk in query_llm_stream(history): buffer chunk count 1 if count 3 or chunk in [。, , , \n, ., !, ?]: if buffer: await msg.stream_token(buffer) buffer count 0 if buffer: # 发送最后剩余的内容 await msg.stream_token(buffer)5.2 遇到连接错误怎么办如果启动Chainlit后无法收到回复或者提示连接失败请按以下步骤检查检查vLLM服务确保cat /root/workspace/llm.log显示服务正常运行并且监听在0.0.0.0:8000。检查URL配置确认app.py中的VLLM_SERVER_URL是否正确。如果vLLM服务运行在其他机器或容器需要将localhost替换为正确的IP地址。检查端口冲突确保Chainlit和vLLM没有使用相同的端口。查看Chainlit日志启动Chainlit的终端会打印错误信息这是最重要的排查依据。5.3 流式中断或内容不完整如果打字效果中途停止或者最后的内容缺失网络稳定性检查服务器网络是否稳定。异常处理我们的query_llm_stream函数已经有了基本的异常处理try...except它会将错误信息以文本形式yield出去你会在聊天窗口看到错误提示。上下文长度GLM-4-9B-Chat-1M支持1M上下文但如果你发送的历史记录新问题非常长仍然可能达到极限。确保历史管理逻辑有效必要时清理早期历史。6. 总结恭喜你通过以上步骤你已经成功地将一个静态的“一问一答”式AI对话前端升级为具备实时流式响应和优雅打字机效果的交互式应用。我们来回顾一下核心要点原理是根本流式响应Server-Sent Events允许数据分块传输打字机效果是前端对这种数据流的可视化呈现。后端是关键使用aiohttp向vLLM发送streamTrue的请求并异步处理返回的SSE数据流通过msg.stream_token()分块发送给前端。Chainlit简化了前端我们无需编写任何JavaScriptChainlit框架已经为我们处理了前端的复杂更新逻辑。体验提升显著用户不再面对“空白等待”而是可以实时观察生成过程交互感更强等待感更弱。现在你的GLM-4-9B-Chat-1M助手不仅能力强大1M上下文而且交互体验也变得非常流畅和现代。你可以在此基础上继续探索更多Chainlit的功能比如文件上传、自定义UI元素、集成工具调用等打造更强大的AI应用。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。