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

这篇具有很好参考价值的文章主要介绍了django传统全栈开发一个ChatGPT应用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

需求

1、可多轮对话

2、可删除对话

3、流式显示对话

4、可多人使用

5、多个api_key均衡使用

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

技术分析

第一次接触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 = None

    def __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 = key
        self.__time = time.time() # 初始化时记录时间戳

    @property
    def last_time(self):
        return self.__time

    @last_time.setter
    def last_time(self, value: float):
        self.__time = value
    
    def __repr__(self):
        return f'<{self.key} - {self.last_time}>'
    
    @property
    def 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、从数据库里取出api
    2、每个api都是API类的实例 每个实例会记录上次使用的时间
    3、取api使用时 先判断是否can_use 能就取 反之取使用次数最少的
    """
    
    def __init__(self, query):
        # django启动或重启时从数据库中加载api_key
        self.__lst = self.init(query)

    def init(self, query):
        lst = []
        for api in query:
            lst.append(
                {'key': API(api.api_key), 'counter': 0}
            )
        return lst

    @property
    def lst(self):
        return self.__lst
    
    # 取一个可用的api_key
    def get(self):
        _api = None
        for api in self.__lst:
            if api.get('key').can_use:
                _api = api['key']
                # 使用一次就+1
                api['counter'] += 1
                # 更新时间戳
                api['key'].last_time = time.time()
                break
        
        # 如果所有的key的时间间隔都未超过20秒
        # 则使用第一个 因为它的使用次数最少
        if not _api:
            api = self.__lst[0]
            _api = api['key']
            # 使用一次就+1
            api['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').key
            if key == _key:
                return s
        # 不存在时才增加    
        if isinstance(key, str):
            self.__lst.append({'key': API(key), 'counter': 0})
            s = True

        return s
    
    # django后台删除api_key设置为不可用时调用
    def remove(self, key: str):
        k = None
        for api in self.__lst:
            if api.get('key').key == key:
                k = api
                break
        if k:
            self.__lst.remove(k)
            return True
        return False

    def __repr__(self):
        return f'<ApiPool {len(self.__lst)}>'
    
    # 应对某些情况时使用
    @property
    def 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部署,如果时机合适,值得再改造一番。文章来源地址https://www.toymoban.com/news/detail-476251.html

到了这里,关于django传统全栈开发一个ChatGPT应用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 5分钟开发一个AI论文抓取和ChatGPT提炼应用

    5分钟开发一个AI论文抓取和ChatGPT提炼应用

    点击“即刻开始” -选择模板 python -修改标题 “AIPaper”,项目标识“AIPaper”,点击“创建项目” 在编程区域右侧AI区域,输入框输入以下内容: 打开左侧main.py文件,将AI区生成的代码插入到文件中。 打开左侧文件”requirements.txt“,输入下面的两行,用来加载安装arxiv的ap

    2024年02月16日
    浏览(14)
  • Rust Web 全栈开发之编写 WebAssembly 应用

    MDN Web Docs:https://developer.mozilla.org/zh-CN/docs/WebAssembly 官网:https://webassembly.org/ Web App 教师注册 - WebService - WebAssembly App 课程管理 WebAssembly 是一种新的编码方式,可以在现代浏览器中运行 它是一种低级的类汇编语言 具有紧凑的二进制格式 可以接近原生的性能运行 并为 C/C ++ 、

    2024年02月07日
    浏览(23)
  • 全球首个 AI 超级工程师:拥有全栈技能,一个指令就能完成整个开发过程

    全球首个 AI 超级工程师:拥有全栈技能,一个指令就能完成整个开发过程

    全球首位AI软件工程师Devin是由初创公司Cognition推出的,它被认为是世界上第一个完全自主的AI软件工程师[2][15]。Devin具备强大的编程和软件开发能力,能够在多个方面协助或完全独立地完成软件开发任务[15]。它的核心能力包括自学新语言、开发迭代App、自动Debug等[8][10],并且

    2024年04月09日
    浏览(12)
  • Django(2)-编写你的第一个 Django 应用

    Django(2)-编写你的第一个 Django 应用

    本教程的目的是创建一个网络投票应用程序。 它将由两部分组成: 一个让人们查看和投票的公共站点。 一个让你能添加、修改和删除投票的管理站点。 每一个应用是一个python包,一个项目可以包含多个应用。 可以看到生成了一个polls文件夹,包含如下文件 polls/views polls/u

    2024年02月11日
    浏览(11)
  • Django后端开发——Django应用及分布式路由

    Django后端开发——Django应用及分布式路由

    B站网课:点击蓝色字体跳转 或者复制链接在浏览器打开:https://www.bilibili.com/video/BV1vK4y1o7jH?p=14vd_source=597e21cf34ffcdce468ba00be2177e8a 终端: 在settings.py的INSTALLED_APPS中添加应用名即可 news开头的交由news管理 music开头的交由music管理 Step1 - 主路由中调用include函数 语法:include(‘app名

    2024年02月19日
    浏览(43)
  • 基于 python+django,我开发了一个外卖点餐系统

    基于 python+django,我开发了一个外卖点餐系统

    学习过程中,如遇问题可咨询作者 功能介绍 平台采用B/S结构,后端采用主流的Python语言进行开发,前端采用主流的Vue.js进行开发。 整个平台包括前台和后台两个部分。 前台功能包括:首页、菜品详情页、订单中心、用户中心模块。 后台功能包括:总览、订单管理、菜品管

    2024年01月19日
    浏览(12)
  • 通过PyCharm平台开发Django应用程序

    通过PyCharm平台开发Django应用程序

    学会使用命令行工具开发Django应用程序是基础,不过更多的时候还是要借助平台开发工具。目前,最好的Django应用程序开发工具就是jetBrains公司推出的PyCharm平台了。 借助PyCharm开发平台,可以极大提高开发Django应用程序的效率,同时可以使用到很多非常实用的第三方插件。不

    2024年04月26日
    浏览(10)
  • ChatExcel:ChatGPT后又一个有趣的应用!

    ChatExcel:ChatGPT后又一个有趣的应用!

    自ChatBCG(一键生成PPT),excelformulabot(一键生成 excel 函数)等AIGC产品面世后,我们日常的办公需求得到满足的同时也有新的惊喜了。只要输入一段query,就能生成相关的目标物。如果不满意,还可以修改query,与它交互,不断更新生成的效果。 今天和大家分享一个有趣的应

    2024年02月09日
    浏览(13)
  • 开发一个ChatGPT都需要什么?

    开发像 ChatGPT 这样的聊天机器人一般需要以下组件: 1. 大型语言模型:像 ChatGPT 这样的聊天机器人的骨干是一个大型语言模型,这个模型已经在大量文本数据上进行了训练。该模型应该能够生成类似人类真实语言的文本并根据上下文回答问题。 语言模型的目的是预测一个给

    2024年01月17日
    浏览(10)
  • 构建一个 Java 应用程序来与 ChatGPT 对话

    文末附 完整代码 的免费下载链接 您需要做的第一件事是获取 API 密钥。您可以使用OpenAI 提供的免费版 ChatGPT来访问它。注册后,您将可以免费访问 3.5 版本。(版本 4 目前仍需要订阅费。)  拥有帐户并登录后,您可以生成新的 API 密钥。将其保存在安全的地方;我们稍后会

    2024年02月12日
    浏览(10)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包