django传统全栈开发一个ChatGPT应用

根据客户需求,开发一个能多人使用的ChatGPT平台,背后使用的是ChatGPTapi_key

需求

1、可多轮对话

2、可删除对话

3、流式显示对话

4、可多人使用

5、多个api_key均衡使用

在这里插入图片描述

技术分析

第一次接触openai的二次开发,看文档、看文章,技术点如下:

1、不同等级的api_key使用不同的model即模型,普通账号能使用text-davinci-003gpt-3.5-turbo模型,都是ChatGPT 3.5的;

2、api_key有限流,普通账号限流挺严的,每分钟3次请求每分钟40000的tokens,意味着需要搭建一个api_key池,维护多个账号,自己写算法动态调节避免被限流。不然少数的几个账号分分钟就能触碰每分钟3次请求的限制;

3、openai是官方提供的sdk,有同步接口,也有异步接口,由于时间短任务中,异步就不考虑了,直接上同步;

4、前端没写过vue,虽然有点跃跃欲试,最后还是选择了熟悉的layui,前端结构化的就不谈了,把功能写出来就完事了;

5、关于api_key,其实还有点,即key的状态,sdk里也没找到什么可用的接口来获取key的剩余额度、有效期等信息,暂时先放一放,让客户自行充值就好了,后面有办法了再解决。

api_key维护

简单来说写了三个类,算法也很简单,使用的数据结构如下:

[# API实现在下方{'key': <API object xxxxxx>, 'counter': 0}, {'key': <API object xxxxxx>, 'counter': 0},...
]

类实现分别为:

1、Singleton 单例的抽象基类

2、API主题类

3、ApiPool代理类

主要由ApiPool对外提供服务,继承抽象基类实现单例,确保全局数据的唯一性。

抽象基类
class Singleton(type):_instance = Nonedef __call__(cls, *args, **kwargs):if cls._instance is None:cls._instance = super().__call__(*args, **kwargs)return cls._instance

本想上redis维护api_key池的,又得多写代码,考虑也就十几号人同时用,要啥自行车,直接写单例模式来维护,上面的抽象基类就是为这个事服务的。

API主题类

class API:# 使用时间间隔为20秒 避免触发限流rqtl = 20 def __init__(self, key):self.key = keyself.__time = time.time() # 初始化时记录时间戳@propertydef last_time(self):return self.__time@last_time.setterdef last_time(self, value: float):self.__time = valuedef __repr__(self):return f'<{self.key} - {self.last_time}>'@propertydef can_use(self):return self.__bool__()def __bool__(self):"""调用时时间差大于20秒可用 反之不可用"""return bool((time.time() - self.last_time) >= API.rqtl)def __call__(self):return self.key

该类主要实现的是api_key是否可用,所有的api_key都保存在数据库,系统启动或重启时,从数据库加载所有的api_key,逐个使用API初始化,并保存时间戳,对外暴露can_use,当调用这个方法时,会使用当前时间戳和记录的时间戳做比,大于等于20秒就使用,在使用时就更新时间戳,所以也暴露了last_time.setter

ApiPool代理类
class ApiPool(metaclass=Singleton):"""1、从数据库里取出api2、每个api都是API类的实例 每个实例会记录上次使用的时间3、取api使用时 先判断是否can_use 能就取 反之取使用次数最少的"""def __init__(self, query):# django启动或重启时从数据库中加载api_keyself.__lst = self.init(query)def init(self, query):lst = []for api in query:lst.append({'key': API(api.api_key), 'counter': 0})return lst@propertydef lst(self):return self.__lst# 取一个可用的api_keydef get(self):_api = Nonefor api in self.__lst:if api.get('key').can_use:_api = api['key']# 使用一次就+1api['counter'] += 1# 更新时间戳api['key'].last_time = time.time()break# 如果所有的key的时间间隔都未超过20秒# 则使用第一个 因为它的使用次数最少if not _api:api = self.__lst[0]_api = api['key']# 使用一次就+1api['counter'] += 1# 更新时间戳api['key'].last_time = time.time()# 提取后重新排序 counter 升序self.__lst.sort(key=lambda api: api['counter'])return _api# django后台增加api_key或设置为可用时调用def add(self, key):s = False# 存在时不操作for api in self.__lst:_key = api.get('key').keyif key == _key:return s# 不存在时才增加    if isinstance(key, str):self.__lst.append({'key': API(key), 'counter': 0})s = Truereturn s# django后台删除api_key设置为不可用时调用def remove(self, key: str):k = Nonefor api in self.__lst:if api.get('key').key == key:k = apibreakif k:self.__lst.remove(k)return Truereturn Falsedef __repr__(self):return f'<ApiPool {len(self.__lst)}>'# 应对某些情况时使用@propertydef available(self):lst = []for api in self.__lst:if api.get('key').can_use:lst.append(api)return lst

ApiPool对外提供服务,在django启动时就得实例化,在settings.py中初始化不可行,因为那时django的app都未完成初始化,所以最后在某个views.py中实例化,前端请求达到views.py调用openai接口前,先调用get方法拿到一个api_key。演示如下:

# 实例化ApiPool
from . apikey import ApiPool
api_pool = ApiPool(ApiKey.objects.filter(status=True))@login_required
@require_POST
def conversation(request):"""省略其他代码"""key = api_pool.get()if key is None:return JsonResponse({'code': 400, 'msg': '暂无可用的key'})ret = sync_stream_ChatCompletion(messages, uuid, q, key())return StreamingHttpResponse(ret, content_type='application/octet-stream')

前端技术点

前端没使用古老的XMLHttpRequest也没使用jquery.ajax,使用了浏览器原生的fetch(fetch不好的地方就是要两次then才能拿到数据)和后端交互,因为它用来接收steam数据流相对方便些,大概的结构如下:


fetch(url, {options})
.then(response=>{// 判断下响应是否为'application/octet-stream'// 因为后端也写了json的响应再无api_key可用的情况下// 1、'application/octet-stream'时,直接闭包处理let reader = response.body.getReader();function read(){return reader.read().then(//拿到流式数据写到页面)// 因为是流式,所以需要递归调用};return read()// 2、'application/json'时let ret = response.json()function bad(){return ret.then(//友好提示无key可用)};return bad;
})

有待完善的地方

1、上下文维护不容易,目前是简单粗暴地采用前三轮对话和当前提问一起提交给openai,对于tokens的消耗其实是个问题;但暂时也没有很好的解决方案,值得关注;

2、并没有真正维护到api_key的状态,因为不清楚api_key还有多少额度,只能让客户自己关注并及时充值了;后面时机合适可以完善好这方面;

3、全部基于同步。openai提供了异步接口,其实也写了一部分,但时间有限,如果写异步,那么还需要配套的异步视图uvicorn部署,如果时机合适,值得再改造一番。

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

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

相关文章

3DMAX导出fbx到unity设置

1.选中需要导出的模型&#xff0c;在Hierarchy面板Adjust Pivot中点击Affect Pivot Only。 2.接着在下方的Alignment中点击Align to World。 3.按F12弹出TransformType窗口,切换到Select And Rotate(选择并旋转)工具 4.在Offset:Local栏的Y与Z中分别输出-90之后&#xff0c;按回…

3DMAX、C4D、Maya导出fbx到Unity设置

3DMAX 1.选中需要导出的模型&#xff0c;在Hierarchy面板Adjust Pivot中点击Affect Pivot Only。 2.接着在下方的Alignment中点击Align to World。 3.按F12弹出TransformType窗口,切换到Select And Rotate(选择并旋转)工具 4.在Offset:Local栏的Y与Z中分别输出-90之后&#xff…

3D MAX模型导出gltf格式数据

1、首先参照上一篇我微信公众号中3DMAX制作3DTIlesObj格式的数据。 2、下载OpenCollada插件&#xff08;https://github.com/KhronosGroup/OpenCOLLADA/wiki/OpenCOLLADA-Tools&#xff09;打开网址以后下载下图中的插件。&#xff08;插件要与3dmax版本相对应&#xff0c;暂时…

常见3DMAX插件导出模型丢失贴图问题

作者&#xff1a;为梦齐舞 在使用超图3DMAX插件导出模型时&#xff0c;时常出现全部或局部区域出现贴图丢失的情况&#xff0c;本文收集了几种常见的贴图丢失问题&#xff0c;并且提供解决方案。 1、 模型中所有贴图不在一个文件夹下&#xff0c;或贴图文件夹中存在子文件夹&a…

【Unity】XPS模型导入Unity(支持VRChat)

所需要的资源 &#xff08;百度云&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1kyCs_HLUJ5j02ENbHgvzCQ 提取码&#xff1a;1234 &#xff09;可以使用该方法&#xff0c;将xps模型制作成VRChat的模型 cats-blender-plugin-master &#xff08;可选&#xff0c;用与…

3dmax工具开发

工作需要&#xff0c;学习了一些3dmax相关的脚本&#xff0c;在这里整理一下 1.软件架构和类视图 2.语言选择 1&#xff09; maxScrpit:3dmax 官方语言。 2&#xff09; python:官方已经将maxScript的功能集合入了python当中 3&#xff09; C&#xff1a;sdk语言&#xff0c;…

3dmax软件怎么贴图

3dmax软件怎么贴图 3dmax软件怎么贴图?3dmax是一款功能非常强大的三维模型制作软件&#xff0c;利用该软件我们可以制作任何你能够想到的模型&#xff0c;在模型创建时方法灵活多样&#xff0c;那么&#xff0c;小编就来和大家说一下&#xff0c;3dmax软件怎么贴图?方法简单赶…

3Ds MAX 软件介绍

3Ds MAX 软件介绍 什么是3Ds MAX3Ds MAX软件界面介绍3Ds MAX的主要功能3Ds MAX建模功能3Ds MAX动画控制功能3Ds MAX动力学功能3Ds MAX模拟效果功能3Ds MAX渲染功能数据交换角色动画 结语 3Ds MAX2022下载&#xff1a;请点击 什么是3Ds MAX 3DS MAX 是世界上应用最广泛的三维建…

3dmax 建模插件 Rappa Tools 3 笔记

1功能概述&#xff1a; RappaTools3是一个高级工具箱&#xff0c;为在3ds Max中工作的艺术家提供了各种各样的工具。主要的重点是加快工作流程和减少点击量。它提供了各种各样的工具&#xff0c;从选择工具到渲染工具。它可以帮助您完成创建3D艺术作品的整个过程。 它带有3个…

3dmax 视图切换

4个视图中的任何一个均可最大化&#xff1b; 在某个视图中按下F3键&#xff0c;可使物体在线框模式和实体模式之间转换&#xff1b; 透视图换成线框模式是这样&#xff1b; 物体变为实体模式之后&#xff0c;可按下F4键&#xff0c;使实体附上一层线框&#xff0c;再按F4则取消…

Max22——导出FBX让windows默认3D查看器可见模型和贴图

1随着商店资源可查看方式越来越强大&#xff0c;小伙伴们经常会遇到这样的需求&#xff0c;就是你得FBX文件&#xff0c;要让windows默认得3D查看器看到模型跟贴图&#xff0c;这样很多资源在网页上就可以不经过max或者maya等软件&#xff0c;就能直接在网页上查看。 然后发现项…

3dmax导出fbx模型到unity

目录 1、功能描述 2、模型导出 2.1模型检查 2.2导出fbx模型 3、导入unity 3.1 导入fbx模型 3.2 材质设置 3.3 检查结果 1、功能描述 本文介绍3dmax模型导出fbx模型&#xff0c;并导入至unity中&#xff0c;包含材质的方法。 软件版本&#xff1a; 3dmax2021 unity20…

在线的max文件转换fbx网站,Unity打开.max文件

Unity不可以打开.max文件&#xff0c;只有在电脑上安装了3dmax后&#xff0c;才可以导入.max文件&#xff0c;本质上进行了自动转换。 很不错 可以转换小模型 在线的max文件转换fbx网站 http://www.3dwhere.com/conv/all2fbx

通过3dmax将max文件导出为unity3d可用的带贴图的fbx文件

原料 max文件 map文件夹内部 在3ds max软件内情况 关键点 有帽子、上衣、裤子、鞋子、人体五个组成部分人体颜色大约为163、112、85鞋子颜色大约为43、43、43上衣颜色大约为77、98、128裤子颜色大约为68、85、112帽子颜色大约为226、107、27 导出步骤 点击导出按钮 选择…

3Dmax已经贴好图的文件如何导入unity3D中

3Dmax已经贴好图的文件如何导入unity3D中&#xff0c;对于初学者而言&#xff0c;有时候在3Dmax中贴好图&#xff0c;配好颜色的模型导入unity3D中会丢失贴图的问题。 解决方法&#xff1a; 1.在3Dmax中建好模型、贴图完成。 2.点击在左上角&#xff1a;文件-导出-导出 3.选择…

一文让你了解数据采集

随着云计算、大数据、人工智能的发展&#xff0c;数据采集作为数据的重要手段&#xff0c;成为广大企业的迫切需求。 所谓“得数据者&#xff0c;得人工智能”&#xff0c;如今人工智能早已在我们的生活中屡见不鲜。如“人脸识别”、“语音唤醒音响”等都属于人工智能的范畴。…

ChatGPT 插件Plugin集合

ChatGPT的插件功能推出一段时间了&#xff0c;陆陆续续的上架了得有200了。 但是其中大部分都不是很好用&#xff0c;并且找起来也复杂。 推荐一个不知名热心人做的导航页。 ChatGPT Plugins Overview 基本上集合了所有的插件&#xff0c;并且还在实时更新中。 不过说实话&am…

Xshell登录服务器后输入命令非常卡顿

重新设置登录属性&#xff0c;将下面设置中默认的√去掉后重新连接

这三个命令,最后一个命令慎用,搞不好得准备跑路

▲ 关注并标星【爱开发】 与更多开发者 一路同行 每晚10点&#xff0c;捕获技术思考和创业资源洞察 ▲ 文|洪生鹏 编辑|静子 菜鸟学Linux命令2 1. find 基本语法参数如下&#xff1a; find [PATH] [option] [action]# 与时间有关的参数&#xff1a; -mtime n : n为数字&#x…

Linux 最常用命令:能解决 95% 以上的问题

点击上方“Java基基”&#xff0c;选择“设为星标” 做积极的人&#xff0c;而不是积极废人&#xff01; 每天 14:00 更新文章&#xff0c;每天掉亿点点头发... 源码精品专栏 原创 | Java 2021 超神之路&#xff0c;很肝~中文详细注释的开源项目RPC 框架 Dubbo 源码解析网络应…