使用fastapi搭建ChatGPT对话后台

使用fastapi搭建ChatGPT对话后台

参考资料:使用fastapi搭建ChatGPT对话后台
效果:在本地构建网页达成类似chatgpt的对话效果,一个字一个字的返回生成结果

ChatGPT初步调用

import os
import fastapi
import dotenv
from httpx import AsyncClient
from typing import List,Dict
dotenv.load_dotenv('./env')# print(os.getenv('OPENAI_API_BASE'))
async def request(val: List[dict[str,str]]):"""发起请求val: 对话内容"""url = "https://xiaoai.plus/v1/chat/completions"headers ={"Content-Type": "application/json","Authorization": "Bearer " + os.getenv("OPENAI_API_KEY")}params = {"model": "gpt-3.5-turbo","messages": val, # [{"role": "user", "content": "Say this is a test!"}]"temperature": 0.7,"n": 1,"max_tokens": 3000,"stream": False}async with AsyncClient() as clinet:response = await clinet.post(url, headers=headers,json=params,timeout=60)print(response.json())if __name__ == '__main__':import asyncioasyncio.run(request([{"role": "user", "content": "Hello!"}]))
{'id': 'chatcmpl-ABYGZNDqhtZn5igtaukBbLPWrdTPZ', 'object': 'chat.completion', 'created': 1727316691, 'model': 'gpt-3.5-turbo', 'choices': [{'index': 0, 'message': {'role': 'assistant', 'content': 'Hello! How can I assist you today?'}, 'finish_reason': 'stop'}], 'usage': {'prompt_tokens': 9, 'completion_tokens': 9, 'total_tokens': 18}, 'system_fingerprint': 'fp_808245b034'}

对回答进行解析, 这里的结果是一次性返回消息内容

{"id": "chatcmpl-ABYGZNDqhtZn5igtaukBbLPWrdTPZ",  # 唯一标识符,用于追踪请求"object": "chat.completion",  # 对象类型,表示这是一个聊天完成事件"created": 1727316691,  # 创建时间戳,表示响应创建的时间"model": "gpt-3.5-turbo",  # 使用的模型名称"choices": [  # 选择列表,可能包含多个回复,这里只有一个{"index": 0,  # 当前选择的索引"message": {  # 选择的消息内容"role": "assistant",  # 消息角色,这里是助手"content": "Hello! How can I assist you today?"  # 消息内容},"finish_reason": "stop"  # 完成原因,这里是"stop",表示模型决定停止生成更多内容}],"usage": {  # 使用情况,包括token使用情况"prompt_tokens": 9,  # 提示token的数量"completion_tokens": 9,  # 完成token的数量"total_tokens": 18  # 总token的数量},"system_fingerprint": "fp_808245b034"  # 系统指纹,用于识别请求的系统环境
}

流式调用ChatGPT

修改上述代码中的"stream": Trueprint(response.text)部分

import os
import fastapi
import dotenv
from httpx import AsyncClient
from typing import List,Dict
dotenv.load_dotenv('./env')# print(os.getenv('OPENAI_API_BASE'))
async def request(val: List[dict[str,str]]):"""发起请求val: 对话内容"""url = "https://xiaoai.plus/v1/chat/completions"headers ={"Content-Type": "application/json","Authorization": "Bearer " + os.getenv("OPENAI_API_KEY")}params = {"model": "gpt-3.5-turbo","messages": val, # [{"role": "user", "content": "Say this is a test!"}]"temperature": 0.7,"n": 1,"max_tokens": 3000,"stream": True}async with AsyncClient() as clinet:response = await clinet.post(url, headers=headers,json=params,timeout=60)print(response.text)if __name__ == '__main__':import asyncioasyncio.run(request([{"role": "user", "content": "Hello!"}]))

可以看到GPT的结果是一个词一个词的返回的

data: {"id":"chatcmpl-ABYJD1L22azzx2PK9IyqCaw2RrC7J","object":"chat.completion.chunk","created":1727316855,"model":"gpt-3.5-turbo","system_fingerprint":"fp_808245b034","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}data: {"id":"chatcmpl-ABYJD1L22azzx2PK9IyqCaw2RrC7J","object":"chat.completion.chunk","created":1727316855,"model":"gpt-3.5-turbo","system_fingerprint":"fp_808245b034","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}data: {"id":"chatcmpl-ABYJD1L22azzx2PK9IyqCaw2RrC7J","object":"chat.completion.chunk","created":1727316855,"model":"gpt-3.5-turbo","system_fingerprint":"fp_808245b034","choices":[{"index":0,"delta":{"content":"!"},"finish_reason":null}]}data: {"id":"chatcmpl-ABYJD1L22azzx2PK9IyqCaw2RrC7J","object":"chat.completion.chunk","created":1727316855,"model":"gpt-3.5-turbo","system_fingerprint":"fp_808245b034","choices":[{"index":0,"delta":{"content":" How"},"finish_reason":null}]}data: {"id":"chatcmpl-ABYJD1L22azzx2PK9IyqCaw2RrC7J","object":"chat.completion.chunk","created":1727316855,"model":"gpt-3.5-turbo","system_fingerprint":"fp_808245b034","choices":[{"index":0,"delta":{"content":" can"},"finish_reason":null}]}data: {"id":"chatcmpl-ABYJD1L22azzx2PK9IyqCaw2RrC7J","object":"chat.completion.chunk","created":1727316855,"model":"gpt-3.5-turbo","system_fingerprint":"fp_808245b034","choices":[{"index":0,"delta":{"content":" I"},"finish_reason":null}]}data: {"id":"chatcmpl-ABYJD1L22azzx2PK9IyqCaw2RrC7J","object":"chat.completion.chunk","created":1727316855,"model":"gpt-3.5-turbo","system_fingerprint":"fp_808245b034","choices":[{"index":0,"delta":{"content":" assist"},"finish_reason":null}]}data: {"id":"chatcmpl-ABYJD1L22azzx2PK9IyqCaw2RrC7J","object":"chat.completion.chunk","created":1727316855,"model":"gpt-3.5-turbo","system_fingerprint":"fp_808245b034","choices":[{"index":0,"delta":{"content":" you"},"finish_reason":null}]}data: {"id":"chatcmpl-ABYJD1L22azzx2PK9IyqCaw2RrC7J","object":"chat.completion.chunk","created":1727316855,"model":"gpt-3.5-turbo","system_fingerprint":"fp_808245b034","choices":[{"index":0,"delta":{"content":" today"},"finish_reason":null}]}data: {"id":"chatcmpl-ABYJD1L22azzx2PK9IyqCaw2RrC7J","object":"chat.completion.chunk","created":1727316855,"model":"gpt-3.5-turbo","system_fingerprint":"fp_808245b034","choices":[{"index":0,"delta":{"content":"?"},"finish_reason":null}]}data: {"id":"chatcmpl-ABYJD1L22azzx2PK9IyqCaw2RrC7J","object":"chat.completion.chunk","created":1727316855,"model":"gpt-3.5-turbo","system_fingerprint":"fp_808245b034","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}data: [DONE]

逐行处理流式响应

修改相应的代码

    # async with AsyncClient() as clinet:#     response = await clinet.post(url, headers=headers,json=params,timeout=60)#     print(response.text)async with AsyncClient() as clinet:async with clinet.stream("POST", url, headers=headers, json=params, timeout=60) as response:async for line in response.aiter_lines():print(line)
import os
import fastapi
import dotenv
from httpx import AsyncClient
from typing import List,Dict
import json
from collections import defaultdict
dotenv.load_dotenv('./env')# print(os.getenv('OPENAI_API_BASE'))
async def request(val: List[dict[str,str]]):"""发起请求val: 对话内容"""url = "https://xiaoai.plus/v1/chat/completions"headers ={"Content-Type": "application/json","Authorization": "Bearer " + os.getenv("OPENAI_API_KEY")}params = {"model": "gpt-3.5-turbo","messages": val, # [{"role": "user", "content": "Say this is a test!"}]"temperature": 0.7,"n": 1,"max_tokens": 3000,"stream": True}# async with AsyncClient() as clinet:#     response = await clinet.post(url, headers=headers,json=params,timeout=60)#     print(response.text)async with AsyncClient() as clinet:async with clinet.stream("POST", url, headers=headers, json=params, timeout=60) as response:async for line in response.aiter_lines():if line.strip() == "":continueline = line.replace("data: ","")if line.strip() == "[DONE]":returndata = json.loads(line)if data.get("choices") is None or len(data.get("choices")) == 0 or data.get("choices")[0].get("finish_reason") is not None:returnyield data.get("choices")[0]async def chat(inp: str):message = [{"role": "user", "content": inp}]async for i in request(message):print(i)
if __name__ == '__main__':import asyncioasyncio.run(chat("你好啊"))
{'index': 0, 'delta': {'role': 'assistant', 'content': ''}, 'finish_reason': None}
{'index': 0, 'delta': {'content': '你'}, 'finish_reason': None}
{'index': 0, 'delta': {'content': '好'}, 'finish_reason': None}
{'index': 0, 'delta': {'content': ','}, 'finish_reason': None}
{'index': 0, 'delta': {'content': '有'}, 'finish_reason': None}
{'index': 0, 'delta': {'content': '什'}, 'finish_reason': None}
{'index': 0, 'delta': {'content': '么'}, 'finish_reason': None}
{'index': 0, 'delta': {'content': '可以'}, 'finish_reason': None}
{'index': 0, 'delta': {'content': '帮'}, 'finish_reason': None}
{'index': 0, 'delta': {'content': '助'}, 'finish_reason': None}
{'index': 0, 'delta': {'content': '你'}, 'finish_reason': None}
{'index': 0, 'delta': {'content': '的'}, 'finish_reason': None}
{'index': 0, 'delta': {'content': '吗'}, 'finish_reason': None}
{'index': 0, 'delta': {'content': '?'}, 'finish_reason': None}

封装请求与chat方法

import os
import fastapi
import dotenv
from httpx import AsyncClient
from typing import List,Dict
import json
from collections import defaultdict
dotenv.load_dotenv('./env')# print(os.getenv('OPENAI_API_BASE'))
async def request(val: List[dict[str,str]]):"""发起请求val: 对话内容"""url = "https://xiaoai.plus/v1/chat/completions"headers ={"Content-Type": "application/json","Authorization": "Bearer " + os.getenv("OPENAI_API_KEY")}params = {"model": "gpt-3.5-turbo","messages": val, # [{"role": "user", "content": "Say this is a test!"}]"temperature": 0.7,"n": 1,"max_tokens": 3000,"stream": True}# async with AsyncClient() as clinet:#     response = await clinet.post(url, headers=headers,json=params,timeout=60)#     print(response.text)async with AsyncClient() as clinet:async with clinet.stream("POST", url, headers=headers, json=params, timeout=60) as response:async for line in response.aiter_lines():if line.strip() == "":continueline = line.replace("data: ","")if line.strip() == "[DONE]":returndata = json.loads(line)if data.get("choices") is None or len(data.get("choices")) == 0 or data.get("choices")[0].get("delta").get("finish_reason") is not None:returnyield data.get("choices")[0]async def chat(inp: str):message = [{"role": "user", "content": inp}]chat_msg = defaultdict(str)async for i in request(message):if i.get("delta").get("role"):chat_msg["role"] = i.get("delta").get("role")if i.get("delta").get("content"):chat_msg["content"] += i.get("delta").get("content")print(chat_msg)
if __name__ == '__main__':import asyncioasyncio.run(chat("你好啊"))
defaultdict(<class 'str'>, {'role': 'assistant', 'content': '你好!有什么我可以帮助你的吗?'}

使用fastapi进行封装

import os
import fastapi
import dotenv
from httpx import AsyncClient
from typing import List,Dict
from fastapi import FastAPI, WebSocket
from fastapi.middleware.cors import CORSMiddlewareimport json
from collections import defaultdict
from fastapi.responses import HTMLResponseapp = FastAPI()
dotenv.load_dotenv('./env')# app.add_middleware(
#     CORSMiddleware,
#     allow_origins=["*"],
#     allow_credentials=True,
#     allow_methods=["*"],
#     allow_headers=["*"],
# )@app.get("/")
async def root():return {"message": "Hello World"}# print(os.getenv('OPENAI_API_BASE'))
async def request(val: List[dict[str,str]]):"""发起请求val: 对话内容"""url = "https://xiaoai.plus/v1/chat/completions"headers ={"Content-Type": "application/json","Authorization": "Bearer " + os.getenv("OPENAI_API_KEY"),}params = {"model": "gpt-3.5-turbo","messages": val, # [{"role": "user", "content": "Say this is a test!"}]"temperature": 0.7,"n": 1,"max_tokens": 3000,"stream": True}# async with AsyncClient() as clinet:#     response = await clinet.post(url, headers=headers,json=params,timeout=60)#     print(response.text)async with AsyncClient() as clinet:async with clinet.stream("POST", url, headers=headers, json=params, timeout=60) as response:async for line in response.aiter_lines():if line.strip() == "":continueline = line.replace("data: ","")if line.strip() == "[DONE]":returndata = json.loads(line)if data.get("choices") is None or len(data.get("choices")) == 0 or data.get("choices")[0].get("delta").get("finish_reason") is not None:returnyield data.get("choices")[0]@app.websocket("/chat")
async def chat(websocket: WebSocket):await websocket.accept()message = []while True:data = await websocket.receive_text()if data == "quit": await websocket.close()breakmessage.append({"role": "user", "content": data})chat_msg = defaultdict(str)async for i in request(message):if i.get("delta").get("role"):chat_msg["role"] = i.get("delta").get("role")if i.get("delta").get("content"):chat_msg["content"] += i.get("delta").get("content")await websocket.send_text(i.get("delta").get("content"))message.append(chat_msg)if __name__ == '__main__':import uvicornuvicorn.run("main:app", host="127.0.0.1",port=8080,reload=True)

使用html界面调用

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Titile</title>
</head>
<body><p>连接状态: <span id="status">未连接</span></p><p>回复消息: <span id="message"></span></p><p><input id="inp"></p><button type="submit" id="submit">提交</button>
<script>let status = document.getElementById("status")let message = document.getElementById("message")let inp = document.getElementById("inp")let submit = document.getElementById("submit")let socket = new WebSocket("ws://127.0.0.1:8080/chat")socket.addEventListener("open", (event)=>{status.innerText = "已连接"})socket.addEventListener("error", (event)=>{status.innerText = "已失败"})socket.addEventListener("close", (event)=>{status.innerText = "已关闭"console.log("WebSocket closed:", event)})socket.addEventListener("message", (event)=>{message.innerText += event.data})submit.addEventListener("click", ()=>{socket.send(inp.value)})
</script>
</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/880783.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM(HotSpot):字符串常量池(StringTable)

文章目录 一、内存结构图二、案例讲解三、总结 一、内存结构图 JDK1.6 JDK1.8 我们发现&#xff0c;StringTable移入了Heap里面。所以&#xff0c;应该想到&#xff0c;StringTable将受到GC管理。 其实&#xff0c;1.6中&#xff0c;在方法区中的时候&#xff0c;也是受GC管…

从底层理解为什么常量区中的代码不能被修改?

目录 前言&#xff1a;一、了解虚拟地址二、页表映射三、常量区不能被修改的原理四、常量区不可修改的意义 前言&#xff1a; 平时我们在编写代码时都会用到或遇到所谓的常量区或者不可修改的代码&#xff0c;比如说用双引号包起来字符串&#xff08;“Hello World”&#xff…

微服务SpringSession解析部署使用全流程

目录 1、SpringSession简介 2、实现session共享的三种方式 1、修改Tomcat配置文件 2、Nginx负载均衡策略 3、redis统一存储 0、准备工作 1、本地服务添加依赖 2、修改本地服务配置文件 3、添加application.properties文件 4、添加nacos - redis配置 5、修改本地项目…

Linux启动mysql报错

甲方公司意外停电&#xff0c;所有服务器重启后&#xff0c;发现部署在Linux上的mysql数据库启动失败.再加上老员工离职&#xff0c;新接手项目&#xff0c;对Linux系统了解不多&#xff0c;解决起来用时较多&#xff0c;特此记录。 1.启动及报错 1.1 启动语句1 启动语句1&a…

全站最详细的Python环境配置步骤

1、官网下载IDE JetBrains下载 2、IDE下载、安装步骤 这里展示的是如何在Windows上下载、安装Pycharm工具&#xff0c;Linux的步骤类似。 2.1、选择开发者工具 选择开发者工具 2.2、选择Pycharm 选择Pycharm 2.3、选择下载 选择下载 2.4、选择社区版 一般而言&#xff…

基于SpringBoot+Vue的留守儿童爱心网站系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

MyBatis的注入问题

对之前文章的补充&#xff1a;MyBatis中的#{}与${}注入问题----原文链接 前言&#xff1a; MyBatis是一个流行的Java持久层框架&#xff0c;用于将对象与数据库中的数据进行映射。然而&#xff0c;如果不当使用&#xff0c;MyBatis也可能受到诸如SQL注入这类的安全问题的影响。…

解决VRM格式模型在Unity中运行出现头发乱飞等问题

1、问题 通过VRoidStudio制作导出的vrm格式的模型&#xff0c;放在unity中使用时&#xff0c;一运行就会出现头发乱飞&#xff0c;没有自然下垂的问题 2、解决方法 将模型下的secondary中的所有VRM Spring Bone脚本中的Drag Force改为1&#xff0c;Hit Radius改为0 修改后…

JAVA笔记 | 实际上用到的策略模式(可直接套用)

自己开发中用到了策略模式&#xff0c;这样写不一定是最好的&#xff0c;但是满足了业务场景跟使用要求&#xff0c;做个笔记&#xff0c;下次有用到可以快速复习跟套用 假设使用场景&#xff1a;有几只宠物&#xff0c;猫跟狗等&#xff0c;要求他们做各种动作&#xff0c;比如…

828华为云征文 | 华为云Flexus云服务器X实例搭建Zabbix网络设备监视系统(Ubuntu服务器运维)

前言 Flexus X实例内嵌智能应用调优算法&#xff0c;性能强悍&#xff0c;基础模式GeekBench单核及多核跑分可达同规格独享型实例的1.6倍&#xff0c;性能模式更是超越多系列旗舰型云主机&#xff0c;为企业业务提供强劲动力。 &#x1f4bc; Flexus X Zabbix&#xff1a;打造…

PWM驱动LED呼吸灯

背景知识&#xff1a;TIM输出比较-CSDN博客 stm32f10x_tim.h函数 // *** OC是Output Compare输出比较函数 void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); void TI…

苹果盛宴:iPhone 16系列领衔,智能穿戴新潮流来袭

在科技界备受瞩目的苹果秋季发布会上&#xff0c;众多新品悉数亮相&#xff0c;从全新的Apple Watch系列到AirPods系列&#xff0c;再到备受期待的iPhone 16系列&#xff0c;每一款产品都以其独特的创新和卓越的性能&#xff0c;再次定义了智能设备的高标准。 本文将带您领略这…

实验5 预备实验2-配置单个的路由器

配置单个的路由器 一、实验目的 此次试验目的是了解思科网络设备的配置基本特点及IOS命令基本操作方法。这些是配置思科设备的重要前提。 二、实验内容及结果 1、实验环境搭建 添加一个模块化的路由器&#xff0c;单击Packet Tracer 5.3的工作区中刚添加的路由器&#xff0c;…

Go实现RabbitMQ消息模式

【目标】 go实现RabbitMQ简单模式和work工作模式 go实现RabbitMQ 消息持久化和手动应答 go实现RabbitMQ 发布订阅模式 go使用MQ实现评论后排行榜更新 1. go实现简单模式 编写路由实现生产消息 实现生产消息 MQ消息执行为命令行执行&#xff0c;所以创建命令行执行函数mai…

【React】react项目中的redux使用

1. store目录结构设计 2. react组件中使用store中的数据——useSelector 3. react组件中修改store中的数据——useDispatch 4. 示例 react-basic\src\store\moduels\counterStore.js import { createSlice } from reduxjs/toolkitconst counterStore createSlice({name: cou…

Flutter屏幕适配

我们可以根据下面有适配属性的Widget来进行屏幕适配 1.MediaQuery 通过它可以直接获得屏幕的大小&#xff08;宽度 / 高度&#xff09;和方向&#xff08;纵向 / 横向&#xff09; Size screenSize MediaQuery.of(context).size; double width screenSize.width; double h…

【Linux:线程概念】

目录 概念&#xff1a; 创建线程的函数&#xff1a;​编辑 ​编辑 有多进程为什么还需要有多线程&#xff1f; 线程调度的成本为什么低&#xff1f; 进程与线程的区别&#xff1a; 概念&#xff1a; 线程是CPU的基本调度单位&#xff0c;在进程内部运行。在内核中&#xff…

CSS 效果:实现动态展示双箭头

最近写了一段 CSS 样式&#xff0c;虽然不难&#xff0c;但实现过程比较繁琐。这个效果结合了两个箭头&#xff0c;一个突出&#xff0c;一个内缩&#xff0c;非常适合用于步骤导航或选项卡切换等场景。样式不仅仅是静态的&#xff0c;还可以通过点击 click 或者 hover 事件&am…

Java的栈帧和动态链接是什么?

在 Java 的面试过程中&#xff0c;不可避免的一个面试题那就是 JVM&#xff0c;而 JVM 的面试题中&#xff0c;有各种&#xff0c;比如在堆中会被问到的关于垃圾回收机制的相关问题&#xff0c;在栈中会被问到入栈以及出栈的过程&#xff0c;来聊一下关于栈的相关问题&#xff…

C0008.Clion利用C++开发Qt界面,使用OpenCV时,配置OpenCV方法

安装OpenCV 配置环境 配置Clion中的CMakeLists.txt文件 # 设置OpenCV的安装路径 set(OpenCV_DIR "D:/OpenCv_Win/opencv/build/x64/vc16/lib"