開源模型應用落地-FastAPI-助力模型交互-WebSocket篇(五)

一、前言

? ? 使用 FastAPI 可以幫助我們更簡單高效地部署 AI 交互業務。FastAPI 提供了快速構建 API 的能力,開發者可以輕松地定義模型需要的輸入和輸出格式,并編寫好相應的業務邏輯。

? ? FastAPI 的異步高性能架構,可以有效支持大量并發的預測請求,為用戶提供流暢的交互體驗。此外,FastAPI 還提供了容器化部署能力,開發者可以輕松打包 AI 模型為 Docker 鏡像,實現跨環境的部署和擴展。

? ? 總之,使用 FastAPI 可以大大提高 AI 應用程序的開發效率和用戶體驗,為 AI 模型的部署和交互提供全方位的支持。

? ? LangChain基礎入門:開源模型應用落地-FastAPI-助力模型交互-WebSocket篇(一),本篇學習如何集成LangChain進行模型交互,并使用工具獲取實時信息


二、術語

2.1.FastAPI

? ? FastAPI 是一個用于構建 API 的現代、快速(高性能)的 Python Web 框架。它是基于標準 Python 類型注釋的 ASGI (Asynchronous Server Gateway Interface) 框架。

FastAPI 具有以下主要特點:

  1. 快速: FastAPI 使用 ASGI 服務器和 Starlette 框架,在性能測試中表現出色。它可以與 Uvicorn 一起使用,提供非常高的性能。

  2. 簡單: FastAPI 利用 Python 類型注釋,使 API 定義變得簡單且直觀。開發人員只需要定義輸入和輸出模型,FastAPI 會自動生成 API 文檔。

  3. 現代: FastAPI 支持 OpenAPI 標準,可以自動生成 API 文檔和交互式文檔。它還支持 JSON Schema 和數據驗證。

  4. 全功能: FastAPI 提供了路由、依賴注入、數據驗證、安全性、測試等功能,是一個功能齊全的 Web 框架。

  5. 可擴展: FastAPI 被設計為可擴展的。開發人員可以輕松地集成其他庫和組件,如數據庫、身份驗證等。

2.2.WebSocket

? ? 是一種計算機通信協議,它提供了在單個 TCP 連接上進行全雙工通信的機制。它是 HTML5 一個重要的組成部分。

WebSocket 協議主要有以下特點:

  1. 全雙工通信:WebSocket 允許客戶端和服務器之間進行雙向實時通信,即數據可以同時在兩個方向上流動。這與傳統的 HTTP 請求-響應模型不同,HTTP 中數據只能單向流動。

  2. 持久性連接:WebSocket 連接是一種持久性的連接,一旦建立就會一直保持,直到客戶端或服務器主動關閉連接。這與 HTTP 的連接是短暫的不同。

  3. 低開銷:相比 HTTP 請求-響應模型,WebSocket 在建立連接時需要較少的數據交換,因此網絡開銷較小。

  4. 實時性:由于 WebSocket 連接是持久性的,且數據可以雙向流動,因此 WebSocket 非常適用于需要實時、低延遲數據交互的應用場景,如聊天應用、實時游戲、股票行情等。

2.3.Tool

? ? Tool(工具)是為了增強其語言模型的功能和實用性而設計的一系列輔助手段,用于擴展模型的能力。例如代碼解釋器(Code Interpreter)和知識檢索(Knowledge Retrieval)等都屬于其工具。

2.4.langchain預置的tools

? ? https://github.com/langchain-ai/langchain/tree/v0.1.16/docs/docs/integrations/tools

? ?基本這些工具能滿足大部分需求,具體使用參見:


三、前置條件

3.1. 創建虛擬環境&安裝依賴

? 增加Google Search的依賴包

conda create -n fastapi_test python=3.10
conda activate fastapi_test
pip install fastapi websockets uvicorn
pip install --quiet  langchain-core langchain-community langchain-openai
pip install google-search-results

3.2. 注冊Google Search API賬號

1. 輸入注冊信息

可以使用Google賬號登錄,但仍要執行下面的認證操作

2. 需要認證郵箱

3. 需要認證手機

使用接碼平臺:https://sms-activate.io/cn

選擇Google服務

注意

1. 購買的虛擬號碼要與IP(科學上網)所在地一致,此處選擇美國

2. 使用支付寶充值,最低需要充值2美金

4. 認證成功

3.3. 生成Google Search API的KEY


四、技術實現

4.1. Google Search小試

# -*- coding: utf-8 -*-
import osfrom langchain_community.utilities.serpapi import SerpAPIWrapperos.environ["SERPAPI_API_KEY"] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
serp = SerpAPIWrapper()
result = serp.run("廣州的實時氣溫如何?")
print("實時搜索結果:", result)

調用結果:

4.2. 非流式輸出

? ? 本章代碼將開源模型應用落地-FastAPI-助力模型交互-WebSocket篇(三)基礎上進行拓展

服務端:

import uvicorn
import osfrom typing import Annotated
from fastapi import (Depends,FastAPI,WebSocket,WebSocketException,WebSocketDisconnect,status,
)
from langchain.agents import create_structured_chat_agent, AgentExecutor
from langchain_community.utilities import SerpAPIWrapperfrom langchain_core.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate
from langchain_core.tools import tool
from langchain_openai import ChatOpenAIos.environ["OPENAI_API_KEY"] = 'sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'    #你的Open AI Key
os.environ["SERPAPI_API_KEY"] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"class ConnectionManager:def __init__(self):self.active_connections: list[WebSocket] = []async def connect(self, websocket: WebSocket):await websocket.accept()self.active_connections.append(websocket)def disconnect(self, websocket: WebSocket):self.active_connections.remove(websocket)async def send_personal_message(self, message: str, websocket: WebSocket):await websocket.send_text(message)async def broadcast(self, message: str):for connection in self.active_connections:await connection.send_text(message)manager = ConnectionManager()app = FastAPI()async def authenticate(websocket: WebSocket,userid: str,secret: str,
):if userid is None or secret is None:raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION)print(f'userid: {userid},secret: {secret}')if '12345' == userid and 'xxxxxxxxxxxxxxxxxxxxxxxxxx' == secret:return 'pass'else:return 'fail'@tool
def search(query:str):"""只有需要了解實時信息或不知道的事情的時候才會使用這個工具,需要傳入要搜索的內容。"""serp = SerpAPIWrapper()result = serp.run(query)print("實時搜索結果:", result)return resultdef get_prompt():template='''Respond to the human as helpfully and accurately as possible. You have access to the following tools:{tools}Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).Valid "action" values: "Final Answer" or {tool_names}Provide only ONE action per $JSON_BLOB, as shown:```{{"action": $TOOL_NAME,"action_input": $INPUT}}```Follow this format:Question: input question to answerThought: consider previous and subsequent stepsAction:```$JSON_BLOB```Observation: action result... (repeat Thought/Action/Observation N times)Thought: I know what to respondAction:```{{"action": "Final Answer","action_input": "Final response to human"}}Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Format is Action:```$JSON_BLOB```then Observation'''system_message_prompt = SystemMessagePromptTemplate.from_template(template)human_template='''{input}{agent_scratchpad}(reminder to respond in a JSON blob no matter what)'''human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])return promptasync def chat(query):global llm,toolsagent = create_structured_chat_agent(llm, tools, get_prompt())agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True)result = agent_executor.invoke({"input": query})print(result['output'])yield result['output']@app.websocket("/ws")
async def websocket_endpoint(*,websocket: WebSocket,userid: str,permission: Annotated[str, Depends(authenticate)],):await manager.connect(websocket)try:while True:text = await websocket.receive_text()if 'fail' == permission:await manager.send_personal_message(f"authentication failed", websocket)else:if text is not None and len(text) > 0:async for msg in chat(text):await manager.send_personal_message(msg, websocket)except WebSocketDisconnect:manager.disconnect(websocket)print(f"Client #{userid} left the chat")await manager.broadcast(f"Client #{userid} left the chat")if __name__ == '__main__':tools = [search]llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0, max_tokens=512)uvicorn.run(app, host='0.0.0.0',port=7777)

客戶端:

<!DOCTYPE html>
<html><head><title>Chat</title></head><body><h1>WebSocket Chat</h1><form action="" onsubmit="sendMessage(event)"><label>USERID: <input type="text" id="userid" autocomplete="off" value="12345"/></label><label>SECRET: <input type="text" id="secret" autocomplete="off" value="xxxxxxxxxxxxxxxxxxxxxxxxxx"/></label><br/><button onclick="connect(event)">Connect</button><hr><label>Message: <input type="text" id="messageText" autocomplete="off"/></label><button>Send</button></form><ul id='messages'></ul><script>var ws = null;function connect(event) {var userid = document.getElementById("userid")var secret = document.getElementById("secret")ws = new WebSocket("ws://localhost:7777/ws?userid="+userid.value+"&secret=" + secret.value);ws.onmessage = function(event) {var messages = document.getElementById('messages')var message = document.createElement('li')var content = document.createTextNode(event.data)message.appendChild(content)messages.appendChild(message)};event.preventDefault()}function sendMessage(event) {var input = document.getElementById("messageText")ws.send(input.value)input.value = ''event.preventDefault()}</script></body>
</html>

調用結果:

用戶輸入:你好

?

不需要觸發工具調用

模型輸出:你好!有什么我可以幫忙的嗎?

?

用戶輸入:廣州現在天氣如何?

?

需要調用工具

模型輸出:The current weather in Guangzhou is partly cloudy with a temperature of 95°F, 66% chance of precipitation, 58% humidity, and wind speed of 16 mph. This information was last updated on Monday at 1:00 PM.

?

PS:

1. 在AI交互中,LangChain框架并不是必須引入,此處引用僅用于簡化Openai的交互流程。

2. 頁面輸出的樣式可以根據實際需要進行調整,此處僅用于演示效果。

3. 目前還遺留兩個問題,一是如何實現流式輸出,二是如何更好維護prompt模版,篇幅有限,下回分解


五、附帶說明

5.1. 如何避免模型用英文回復

在提示詞模版加入:Remember to answer in Chinese.? 暗示模型一定要以中文進行回復。

修改后的提示語為:

Respond to the human as helpfully and accurately as possible. You have access to the following tools:{tools}Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).Valid "action" values: "Final Answer" or {tool_names}Provide only ONE action per $JSON_BLOB, as shown:```{{"action": $TOOL_NAME,"action_input": $INPUT}}```Follow this format:Question: input question to answerThought: consider previous and subsequent stepsAction:```$JSON_BLOB```Observation: action result... (repeat Thought/Action/Observation N times)Thought: I know what to respondAction:```{{"action": "Final Answer","action_input": "Final response to human"}}Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Remember to answer in Chinese.Format is Action:```$JSON_BLOB```then Observation

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

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

相關文章

【圖論】樹鏈剖分

樹鏈剖分詳解 - 自為風月馬前卒 - 博客園 (cnblogs.com) P3384 【模板】重鏈剖分/樹鏈剖分 - 洛谷 | 計算機科學教育新生態 (luogu.com.cn) #include<iostream> using namespace std;void dfs1(int u,int father){ fa[u]father; dep[u]dep[father]1; sz[u]1;for(int ih…

SpringBoot中整合ONLYOFFICE在線編輯

SpringBoot整合OnlyOffice SpringBoot整合OnlyOffice實現在線編輯1. 搭建私有的OnlyOffice的服務2. SpringBoot進行交互2.1 環境2.2 我們的流程2.3 接口規劃2.3.1 獲取編輯器配置的接口2.3.2 文件下載地址2.3.3 文件下載地址 3. 總結4. 注意4.1 你的項目的地址一定一定要和only…

Java中的單元測試與集成測試最佳實踐

Java中的單元測試與集成測試最佳實踐 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01;今天我們將深入探討Java中的單元測試與集成測試最佳實踐。在軟件開發中&am…

三層交換基礎

一、什么是三層交換 三層交換是一種在OSI模型第三層&#xff0c;即網絡層上工作的網絡設備技術&#xff0c;它整合了二層交換機的功能和路由器的部分功能&#xff0c;以實現更高效的網絡數據轉發和路由選擇。三層交換技術的核心在于結合了二層交換技術和三層轉發技術&#xff…

【RabbitMQ實戰】Springboot 整合RabbitMQ組件,多種編碼示例,帶你實踐 看完這一篇就夠了

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、對RabbitMQ管理界面深入了解1、在這個界面里面我們可以做些什么&#xff1f; 二、編碼練習&#xff08;1&#xff09;使用direct exchange(直連型交換機)&a…

2024 年的 13 個 AI 趨勢

2024 年的 13 個 AI 趨勢 人工智能對環境的影響和平人工智能人工智能支持的問題解決和決策針對人工智能公司的訴訟2024 年美國總統大選與人工智能威脅人工智能、網絡犯罪和社會工程威脅人工智能治療孤獨與對人工智能的情感依賴人工智能影響者中國爭奪人工智能霸主地位人工智能…

Java中的機器學習模型集成與訓練

Java中的機器學習模型集成與訓練 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01;今天我們將探討在Java中如何進行機器學習模型的集成與訓練。隨著人工智能和機器…

【Lua小知識】Vscode中Emmylua插件大量報錯的解決方法

起因 Vscode寫Lua用的好好的&#xff0c;最近突然出現了大量報錯。 看報錯是有未定義的全局變量&#xff0c;這里查日志才發現是由于0.7.5版本新增診斷啟用配置&#xff0c;所以導致了原先好的代碼&#xff0c;現在出現了大量的報錯。 解決方案一 最直接的方法當然是在配置中直…

用攝像頭實現識別道路中的車道線、行人與車輛檢測(級聯分類器、HOG+SVM、行人檢測)

基于樹莓派的智能小車&#xff0c;用攝像頭實現識別道路中的車道線識別、行人檢測與車輛檢測。 本項目旨在開發一套基于攝像頭的智能道路環境感知系統&#xff0c;該系統能夠實時識別道路中的車道線、行人與車輛&#xff0c;為自動駕駛汽車、智能交通管理以及輔助駕駛系統提供關…

LeetCode熱題100刷題3:3. 無重復字符的最長子串、438. 找到字符串中所有字母異位詞、560. 和為 K 的子數組

3. 無重復字符的最長子串 滑動窗口、雙指針 class Solution { public:int lengthOfLongestSubstring(string s) {//滑動窗口試一下//英文字母、數字、符號、空格,ascii 一共包含128個字符vector<int> pos(128,-1);int ans 0;for(int i0,j0 ; i<s.size();i) {//s[i]…

python 中的生成器

目錄 生成器示例基本生成器示例無限序列生成器使用生成器表達式實用示例&#xff1a;按行讀取大文件生成器的 send、throw 和 close 方法 生成器和迭代器迭代器&#xff08;Iterator&#xff09;定義創建使用示例 生成器&#xff08;Generator&#xff09;定義創建使用示例 主要…

【python學習】自定義函數的一些高級用法-2

8. 生成器函數 生成器函數允許你定義一個可以“記住”其當前執行狀態的函數&#xff0c;并在下次調用時從上次離開的位置繼續執行。生成器函數使用yield關鍵字而不是return。 def simple_generator(): yield 1 yield 2 yield 3 gen simple_generator() print(next(gen)) # …

隱私計算實訓營第二期第十課:基于SPU機器學習建模實踐

隱私計算實訓營第二期-第十課 第十課&#xff1a;基于SPU機器學習建模實踐1 隱私保護機器學習背景1.1 機器學習中隱私保護的需求1.2 PPML提供的技術解決方案 2 SPU架構2.1 SPU前端2.2 SPU編譯器2.3 SPU運行時2.4 SPU目標 3 密態訓練與推理3.1 四個基本問題3.2 解決數據來源問題…

全新升級!中央集中式架構功能測試為新車型保駕護航

“軟件定義汽車”新時代下&#xff0c;整車電氣電氣架構向中央-區域集中式發展已成為行業共識&#xff0c;車型架構的變革帶來更復雜的整車功能定義、更多的新技術的應用&#xff08;如SOA服務化、智能配電等&#xff09;和更短的車型研發周期&#xff0c;對整車和新產品研發的…

OkHttp的源碼解讀1

介紹 OkHttp 是 Square 公司開源的一款高效的 HTTP 客戶端&#xff0c;用于與服務器進行 HTTP 請求和響應。它具有高效的連接池、透明的 GZIP 壓縮和響應緩存等功能&#xff0c;是 Android 開發中廣泛使用的網絡庫。 本文將詳細解讀 OkHttp 的源碼&#xff0c;包括其主要組件…

Qt實現手動切換多種布局

引言 之前寫了一個手動切換多個布局的程序&#xff0c;下面來記錄一下。 程序運行效果如下&#xff1a; 示例 需求 通過點擊程序界面上不同的布局按鈕&#xff0c;使主工作區呈現出不同的頁面布局&#xff0c;多個布局之間可以通過點擊不同布局按鈕切換。支持的最多的窗口…

如何使用 AppML

如何使用 AppML AppML(Application Markup Language)是一種輕量級的標記語言,旨在簡化Web應用的創建和部署過程。它允許開發者通過XML或JSON格式的配置文件來定義應用的結構和行為,從而實現快速開發和靈活擴展。AppML特別適用于構建數據驅動的企業級應用,它可以與各種后端…

pytorch跑手寫體實驗

目錄 1、環境條件 2、代碼實現 3、總結 1、環境條件 pycharm編譯器pytorch依賴matplotlib依賴numpy依賴等等 2、代碼實現 import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms import matpl…

burpsuite 設置監聽窗口 火狐利用插件快速切換代理狀態

一、修改burpsuite監聽端口 1、首先打開burpsuite&#xff0c;點擊Proxy下的Options選項&#xff1a; 2、可以看到默認的監聽端口為8080&#xff0c;首先選中我們想要修改的監聽&#xff0c;點擊Edit進行編輯 3、將端口改為9876&#xff0c;并保存 4、可以看到監聽端口修改成功…

typescript學習回顧(五)

今天來分享一下ts的泛型&#xff0c;最后來做一個練習 泛型 有時候&#xff0c;我們在書寫某些函數的時候&#xff0c;會丟失一些類型信息&#xff0c;比如我下面有一個例子&#xff0c;我想提取一個數組的某個索引之前的所有數據 function getArraySomeData(newArr, n:numb…