本地大模型編程實戰(32)用websocket顯示大模型的流式輸出

在與 LLM(大語言模型) 對話時,如果每次都等 LLM 處理完畢再返回給客戶端,會顯得比較卡頓,不友好。如何能夠像主流的AI平臺那樣:可以一點一點吐出字符呢?
本文將模仿后端流式輸出文字,前端一塊一塊的顯示文字。主要的實現路徑是:

  • LLM 采用 qwen3 ,使用 stream 方式輸出
  • 后端使用 langchain 框架
  • 使用 fastapi 實現后端接口
  • 前后端之間使用 websocket 長連接通信
  • 前端使用一個簡單的 html5 網頁做演示

下面是最終實現的效果:
顯示大模型的流式輸出

文章目錄

    • LLM流式輸出
    • 實現后端接口
    • 實現前端頁面
    • 見證效果
    • 總結
    • 代碼

LLM流式輸出

langchain 框架中,LLM(大語言模型) 可以用 stream 的方式一點一點吐出內容。請看代碼:

from langchain_ollama import ChatOllama
from langchain_core.messages import HumanMessage,AIMessagemodel_name = "qwen3"llm = ChatOllama(model=model_name,temperature=0.3,verbose=True)import asyncio
async def ask_stream(question,websocket=None):"""與大模型聊天,流式輸出"""for chunk in llm.stream([HumanMessage(content=question)]):if isinstance(chunk, AIMessage) and chunk.content !='':print(chunk.content,end="^")if websocket is not None:await websocket.send_json({"reply": chunk.content})await asyncio.sleep(0.1)    # sleep一下后,前端就可以一點一點顯示內容。

ask_stream 中使用 websocket 做參數只是為了演示便利,不適合用在實際生產環境。

實現后端接口

下面使用 fastapi 實現后端的 websocket 接口,前后端通信使用 json 格式,用 uvicorn 可以啟動api。

from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponseapp = FastAPI()@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):await websocket.accept()try:while True:data = await websocket.receive_json()user_message = data.get("message", "")print(f"收到用戶消息: {user_message}")await ask_stream(user_message,websocket=websocket)"""reply_message = ask(user_message)await websocket.send_json({"reply": reply_message})"""except Exception as e:print(f"連接關閉: {e}")import uvicornif __name__ == '__main__':# 交互式API文檔地址:# http://127.0.0.1:8000/docs/ # http://127.0.0.1:8000/redoc/uvicorn.run(app, host="0.0.0.0", port=8000)

從上面的代碼我們可以看出:fastapiwebsocket 支持的不錯,實現起來也比較簡潔。

實現前端頁面

為了方便演示,我們做了一個 html5 靜態網頁,并實現一個 get 方法將網頁發送給瀏覽器。

  • 發送網頁的接口
import os@app.get("/")
async def get():"""返回聊天頁面"""file_path = os.path.join(os.path.dirname(__file__), "chat.html")with open(file_path, "r", encoding="utf-8") as f:html_content = f.read()return HTMLResponse(content=html_content)
  • chat.html
<!DOCTYPE html>
<html><head><title>用WebSocket與大模型聊天</title><style>#chat-box {width: 90%;height: 600px;border: 1px solid #ccc;overflow-y: scroll;margin-bottom: 10px;padding: 10px;}#user-input {width: 80%;padding: 5px;}#send-button {padding: 5px 10px;}.user-message {color: blue;}.server-message {color: green;}</style>
</head><body><h1>WebSocket 聊天測試</h1><div id="chat-box"></div><input type="text" id="user-input" placeholder="請輸入你的消息..." /><button id="send-button" onclick="sendMessage()">發送</button><script>var ws = new WebSocket("ws://localhost:8000/ws");var chatBox = document.getElementById("chat-box");var input = document.getElementById("user-input");var currentServerMessageDiv = null; // 記錄正在追加的服務器消息元素ws.onmessage = function(event) {var data = JSON.parse(event.data);handleServerReply(data.reply);};function sendMessage() {var message = input.value.trim();if (message === "") return;appendMessage("你", message, "user-message");ws.send(JSON.stringify({ "message": message }));input.value = "";// 清空服務器回復正在構建的divcurrentServerMessageDiv = null;}function appendMessage(sender, message, className) {var messageElement = document.createElement("div");messageElement.className = className;messageElement.textContent = sender + ": " + message;chatBox.appendChild(messageElement);chatBox.scrollTop = chatBox.scrollHeight;return messageElement;}function handleServerReply(partialText) {if (!currentServerMessageDiv) {// 第一次,創建一個新的divcurrentServerMessageDiv = appendMessage("服務器", partialText, "server-message");} else {// 后續,直接在當前div后面追加currentServerMessageDiv.textContent += partialText;chatBox.scrollTop = chatBox.scrollHeight;}}// 按回車發送消息input.addEventListener("keydown", function(event) {if (event.key === "Enter") {sendMessage();}});</script></body></html>

見證效果

現在我們可以啟動后端接口,然后打開瀏覽器,輸入地址:http://127.0.0.1:8000 ,體驗與大語言模型聊天的快樂了。

總結

使用 qwen3langchianfastapiwebsockethtml5 實現一個像主流AI工具那樣與 LLM(大語言模型) 聊天的功能很有意思。
當我看到前端一塊一塊的顯示大語言模型的回復的時候,心底不由得涌出一點小震撼:沒錯,它在改變世界!


代碼

本文涉及的所有代碼以及相關資源都已經共享,參見:

  • github
  • gitee

為便于找到代碼,程序文件名稱最前面的編號與本系列文章的文檔編號相同。

🪐感謝您觀看,祝好運🪐

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79301.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79301.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79301.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

人工智能-深度學習之卷積神經網絡

深度學習 mlp弊端卷積神經網絡圖像卷積運算卷積神經網絡的核心池化層實現維度縮減卷積神經網絡卷積神經網絡兩大特點卷積運算導致的兩個問題&#xff1a;圖像填充&#xff08;padding&#xff09;結構組合問題經典CNN模型LeNet-5模型AlexNet模型VGG-16模型 經典的CNN模型用于新…

藍橋杯電子賽_繼電器和蜂鳴器

目錄 一 前言 二 繼電器和蜂鳴器實物 三 分析部分 &#xff08;1&#xff09;bsp_init.c &#xff08;2&#xff09;蜂鳴器和繼電器原理圖 &#xff08;3&#xff09;ULN2003 &#xff08;4&#xff09;他們倆所連接的鎖存器 四 代碼 在這里要特別說一點&#xff01;&…

仿騰訊會議——主界面設計創建房間加入房間客戶端實現

1、實現騰訊會議主界面 2、添加Qt類WeChatDialog 3、定義創建會議和加入會議的函數 4、實現顯示名字、頭像的函數 調用函數 5、在中間者類中綁定函數 6、實現創建房間的槽函數 7、實現加入房間的槽函數 8、設置界面標題 9、服務器定義創建和進入房間函數 10、服務器實現創建房間…

網絡編程初識

注&#xff1a;此博文為本人學習過程中的筆記 1.socket api 這是操作系統提供的一組api&#xff0c;由傳輸層向應用層提供。 2.傳輸層的兩個核心協議 傳輸層的兩個核心協議分別是TCP協議和UDP協議&#xff0c;它們的差別非常大&#xff0c;編寫代碼的風格也不同&#xff0c…

【質量管理】現代TRIZ問題識別中的功能分析——功能模型

功能模型的定義 功能模型是對工程系統進行功能分析的一個階段&#xff0c;目的是建立工程系統的功能模型。功能模型描述了工程系統和超系統組件的功能&#xff0c;包括有用功能、性能水平和成本等。 在文章【質量管理】現代TRIZ中問題識別中的功能分析——相互接觸分析-CSDN博客…

廣告事件聚合系統設計

需求背景 廣告事件需要進行統計&#xff0c;計費&#xff0c;分析等。所以我們需要由數據接入&#xff0c;數據處理&#xff0c;數據存儲&#xff0c;數據查詢等多個服務模塊去支持我們的廣告系統 規模上 10000 0000個點擊&#xff08;10000 00000 / 100k 1wQPS&#xff09; …

C語言中,sizeof關鍵字(詳細介紹)

目錄 ?1. 基本用法?(1) ?基本數據類型?(2) ?變量?(3) ?數組?(4) ?指針? ?2. 特殊用法?(1) ?結構體與內存對齊?(2) ?動態內存分配?(3) ?表達式? ?3. 注意事項??1&#xff09;sizeof 與 strlen 的區別?&#xff1a;?2&#xff09;變長數組&#xff08;VLA…

ADK 第三篇 Agents (LlmAgent)

Agents 在智能體開發套件&#xff08;ADK&#xff09;中&#xff0c;智能體&#xff08;Agent&#xff09;是一個獨立的執行單元&#xff0c;旨在自主行動以實現特定目標。智能體能夠執行任務、與用戶交互、使用外部工具&#xff0c;并與其他智能體協同工作。 在ADK中&#x…

【深度學習】典型的 CNN 網絡

目錄 一、LeNet-5 &#xff08;1&#xff09;LeNet-5 網絡概覽 &#xff08;2&#xff09;網絡結構詳解 &#xff08;3&#xff09;關鍵組件與數學原理 3.1 局部感受野與卷積運算 3.2 權重共享 3.3 子采樣&#xff08;Pooling&#xff09; 3.4 激活函數 &#xff08;4…

4.8/Q1,中山大學用NHANES:膳食煙酸攝入量與非酒精性脂肪肝之間的關聯

文章題目&#xff1a;Association between Dietary Niacin Intake and Nonalcoholic Fatty Liver Disease: NHANES 2003-2018 DOI&#xff1a;10.3390/nu15194128 中文標題&#xff1a;膳食煙酸攝入量與非酒精性脂肪肝之間的關聯&#xff1a;NHANES 2003-2018 發表雜志&#xf…

高效管理遠程服務器Termius for Mac 保姆級教程

以下是 Termius for Mac 保姆級教程&#xff0c;涵蓋安裝配置、核心功能、實戰案例及常見問題解決方案&#xff0c;助你高效管理遠程服務器&#xff08;如Vultr、AWS等&#xff09;。 一、Termius 基礎介紹 1. Termius 是什么&#xff1f; 跨平臺SSH客戶端&#xff1a;支持Ma…

理解數學概念——支集(支持)(support)

1. 支集(support)的定義 在數學中&#xff0c;一個實函數 f 的支集(support)是函數的不被映射到 0 的元素域(即定義域)的子集。若 f 的(定義)域(domain)是一個拓撲空間(即符合拓撲的集合)&#xff0c;則 f 的支集則定義為包含( f 的元素域中)不被映射到0的所有點之最小閉集…

Vue 3 Element Plus 瀏覽器使用例子

Element Plus 是一個基于 Vue 3 的流行開源 UI 庫&#xff0c;提供了一系列的組件&#xff0c;幫助開發者快速構建現代化的用戶界面。它的設計簡潔、現代&#xff0c;包含了許多可定制的組件&#xff0c;如按鈕、表格、表單、對話框等&#xff0c;適合用于開發各種 Web 應用。 …

SSR vs SSG:前端渲染模式終極對決(附 Next.js/Nuxt.js 實戰案例)

一、引言&#xff1a;前端渲染模式的進化之路 隨著互聯網的發展&#xff0c;用戶對于網頁的加載速度和交互體驗要求越來越高。前端渲染技術作為影響網頁性能的關鍵因素&#xff0c;也在不斷地發展和演進。從最初的客戶端渲染&#xff08;CSR&#xff09;&#xff0c;到后來的服…

算法筆記.分解質因數

代碼實現&#xff1a; #include<iostream> using namespace std; void breakdown(int x) {int t x;for(int i 2;i < x/i;i){if(t%i 0){int counts 0;while(t % i 0){t/i;counts;}cout << i <<" "<< counts<<endl;}}if(t >…

CUDA Error: the provided PTX was compiled with an unsupported toolchain

CUDA程序編譯時生成的PTX代碼與系統上的CUDA驅動版本不兼容 CUDA 編譯器版本&#xff1a; CUDA 12.6 (nvcc 編譯器版本) CUDA 驅動版本&#xff1a; CUDA 12.3 (nvidia-smi 驅動版本) 解決方法&#xff1a; 驅動版本下載參考&#xff1a;Your connected workspace for wiki…

計算機組成原理實驗(7) 堆指令部件模塊實驗

實驗七 堆指令部件模塊實驗 一、實驗目的 1、掌握指令部件的組成方式。 2、熟悉指令寄存器的打入操作&#xff0c;PC計數器的設置和加1操作&#xff0c;理解跳轉指令的實現過程。 二、實驗要求 按照實驗步驟完成實驗項目&#xff0c;掌握數據打入指令寄存器IR1、PC計數器的…

2022 年 6 月大學英語四級考試真題(第 2 套)——閱讀版——仔細閱讀題

&#x1f3e0;個人主頁&#xff1a;fo安方的博客? &#x1f482;個人簡歷&#xff1a;大家好&#xff0c;我是fo安方&#xff0c;目前中南大學MBA在讀&#xff0c;也考取過HCIE Cloud Computing、CCIE Security、PMP、CISP、RHCE、CCNP RS、PEST 3等證書。&#x1f433; &…

磁盤文件系統

磁盤文件系統 一、磁盤結構1.1 認識一下基礎的硬件設備以及真實的機房環境1.2 磁盤物理結構與存儲結構1、磁盤物理結構2、磁盤的存儲結構3、CHS地址定位4、磁盤的邏輯結構&#xff08;LBA&#xff09;5 磁盤真實過程5 CHS && LBA地址 二、理解分區、格式化1 引?"…

基于LangChain 實現 Advanced RAG-后檢索優化(下)-上下文壓縮與過濾

摘要 Advanced RAG 的后檢索優化&#xff0c;是指在檢索環節完成后、最終響應生成前&#xff0c;通過一系列策略與技術對檢索結果進行深度處理&#xff0c;旨在顯著提升生成內容的相關性與質量。在這些優化手段中&#xff0c;上文壓縮與過濾技術是提升檢索結果質量的重要手段。…