AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


大语言模型应用搭建和实施部署
发布日期:2024-04-29 08:07:24 浏览次数: 2291 来源:大雨滴AI


前面的文章中介绍了和AI大语言模型直接相关的一些主要功能点,这一篇就来介绍一下搭建这样一个LLM RAG应用还需要哪些组件和技术。


先用一个简单的架构图让大家有一个直观的印象,基本上就是一个标准的web应用架构,


前端 - 微信小程序

微信小程序大家都很熟悉了,它是腾讯一个了不起的创新,使移动端应用有了更轻量化的选择,各互联网大厂(包括阿里和Meta)都要竞相学去了。不过从去年下半年开始,微信小程序开始收年费了(300元年审费),真的是韭菜长高了就开始收割。


申请一个微信小程序只要在微信开发者平台注册即可。个人用户也需要提供身份证明进行ICP备案,相比企业用户过程简单很多。小程序申请好之后,可以在小程序管理平台(微信公众平台)的“开发管理”页面创建一个 appsecret 作为小程序自身的身份认证密钥,后面会用到。


微信小程序开发框架目前已经比较成熟了。对于原生的框架,我感觉它就是学习(照抄)Vue这个前端开发框架设计的。熟悉Vue的话,很容易上手,腾讯也提供了丰富的开发API包括http request、websocket、audio、file upload等,方便开发者直接调用。


这里就只简单说一下微信小程序的登录认证吧。因为基于小程序的应用肯定都是前后端分离的设计模式了,后端应用通常都有必要对客户端发送来的请求进行身份验证,确保是小程序客户端(必定是有微信身份的用户),而不是其它方式发送过来的请求。


微信小程序用户身份认证流程


如上图,小程序通过 wx.login() 调用获取一个 code,再通过 wx.request() 发送到后端。后端应用使用 python requests 包携带上小程序的 appsecret 到微信 API 服务获取用户的 openid。这个 openid 是微信小程序中一个重要的概念,它是微信小程序用户在微信平台上的唯一标识符,通常用它来鉴别小程序用户的身份。每个微信用户访问到任意一个小程序(或微信公众号)时都会产生一个唯一的 OpenID,也就是微信用户和小程序(或公众号)组合的唯一ID。


后端 - Python应用服务

应用后端的组件稍多一些,都运行在 AWS 云免费资源上。


后端是基于 Python Django 这个 Web 开发框架及其配套组件实现的。在开始这个应用开发前,我简单对比过 Django 和 Flask这两个主流的 Python Web 开发框架。总的来说 Django初始上手稍难一点儿,但上手后寻常的开发需求都够用了,而Flask 上手更容易,但中后期开发需要集成更多的第三方组件,难度可能更高。再考虑到大名鼎鼎的 Jumpserver 开源堡垒机系统就是基于 Django 开发的,最终我选择了 Django 框架。


Python Django 框架介绍

Django 是一个高级的 Python Web 框架,它以“batteries-included”(全包式)的理念著称。这意味着 Django 提供了完整的配套组件,包括一个 ORM(对象关系映射器)、一个内置的后台管理系统以及许多其他的功能组件。


Django 对传统的 MVC(Models + Views + Controller) 设计模式进行了修改,将视图分成 View模块和 Template 模块两部分,将动态的逻辑处理与静态的页面展现分离开。而 Model 采用了 ORM 对象关系映射技术,将关系型数据库表抽象成面向对象的 Python 类,将表操作转换成类操作,避免了复杂的 SQL 语句编写(这一点还是很赞的,尤其是对数据模型简单的应用来说,开发起来比较便捷)。MTV(Models + Views + Templates) 和 MVC 本质上是一样的,如下图,


在 Django 中的 Views 模块则更多的是扮演了 Controller 的角色,起应用逻辑处理作用。作为初学者,我对 Django 并没有很深入的认知,只是因其基于 python 语言开发,个人有所偏爱,学习它对日常工作中一些运维自动化场景有帮助。感兴趣的道友可以在B站找到大量关于Django 的教学视频来学习,这里我就不再继续展开。


Websocket Channels

WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据。以下是关于Websocket和HTTP的对比,可以比较容易理解为什么我们需要Websocket。


通信模型

HTTP是一种基于请求-响应模式的协议,每次通信都需要客户端主动发起请求,服务器在收到请求后返回响应,之后连接断开;WebSocket是一种双向通信协议,客户端和服务器之间建立一次连接后可以持续通信,双方可以随时发送和接收数据。


数据传输方式

HTTP是在每次通信时建立新的连接,完成请求后立即关闭连接;WebSocket在客户端和服务器之间建立一条持久的连接,实现双向通信。


数据格式

HTTP传输的数据通常是文本或二进制数据,如HTML、JSON、XML等;WebSocket可以传输任意格式的数据,包括文本、二进制、JSON等。


应用场景

HTTP 适用于请求-响应模型的场景,例如 Web 页面的加载;WebSocket 适用于实时性要求高的应用,如在线聊天、实时游戏、股票市场数据等。

安全性

HTTP通常使用 TLS/SSL 进行加密通信;WebSocket 也支持 TLS/SSL 安全连接。


总结来说,WebSocket 提供了一种全双工的通信方式,适合于需要双向实时通信的应用场景,而 HTTP 则适用于基于请求-响应模型的应用场景。可以说有了 websocket,以往很多 CS 架构的软件体系都可以换成BS架构,比如 Jumpserver 堡垒机基于 websocket 实现了 webshell, web RDP,web 数据库客户端等,日常运维不再需要安装各种客户端软件,有浏览器就够了。


Python Channels 是一个基于 Django 框架的扩展,用于处理实时 Web 应用程序中的异步通信。它的设计目标是使 Django 能够处理 WebSocket 连接、异步任务、即时通知等实时性需求,而不仅仅是传统的HTTP请求。


Python Channels 库为 Django 应用程序提供了异步处理的能力,从而使开发者能够构建实时Web应用,而无需依赖其他复杂的框架或库。这正是一个 AI 大语言模型应用和语音功能所需要的,比如可以比较容易地实现 LLM 对话以 Stream 方式输出到 Web 页面和语音数据流传输等,以提升用户的交互体验。


要在生产环境中部署实时应用,可以使用ASGI服务器,例如 Daphne 或 uvicorn。这些服务器可以处理大量并发的 WebSocket 连接,并确保应用的稳定性和性能。我用的是 Daphne。


Python应用环境管理

部署一个软件应用,总是需要考虑系统的运行环境依赖项等,Python 应用也一样。


Anaconda 是一个用于科学计算的 Python 发行版,可以便捷获取包且对包能够进行管理,同时对环境可以统一管理的发行版本。Anaconda 包含了 Conda、Python 在内的超过180个科学包及其依赖项。


Miniconda是一个轻量级的Anaconda发行版,它只包含Conda和Python。相比于完整的Anaconda发行版,Miniconda的体积更小,安装速度更快,适合在资源受限的环境中使用,例如在某些嵌入式系统或容器中。同时,Miniconda也提供了与完整Anaconda相同的包管理功能和环境管理功能,用户可以通过conda命令来安装、更新、卸载软件包以及创建、切换和管理不同的环境。我这里用的是Miniconda。


Conda是一个开源的包管理和环境管理工具,用于安装多个版本的软件包及其依赖关系,并在它们之间轻松切换。它主要用于Python编程语言及其相关的数据科学、机器学习等应用领域。可以把Conda管理工具当做是Python的 pip 工具加上 virtualenv 。 


一个好的运行环境和依赖包管理工具对应用部署和管理相当重要,它可以大幅减少踩坑的几率和花费的时间。我第一次部署测试环境时,在一台CentOS7.9环境中,没有用conda,结果部署过程异常艰难,踩了很多坑,比如libstdc++ 版本兼容问题、Python3 不支持 sqlite3 而需要重新编译、重新编译后 sqlite3 版本过低需要重新安装 pysqlite3-binary、pysqlite3-binary和操作系统不兼容无法安装,最后不得不下载 sqlite3 源码编译一个静态链接库、等问题。虽然最后侥幸填平了各种坑,但填坑的方案都是一次性的,对后续其它工作并没有什么价值,因为那些坑以后几乎不会再遇到。


我觉得一个事情能简单做成,就应该坚持简单做,完全没必要人为增加难度,还美其名曰给自己一点儿挑战,锻炼解决问题的能力,那绝对是浪费时间浪费生命。所以后来在AWS上部署时,坚决先学习了Conda这个Python环境和包管理工具,并采用推荐的系统和软件版本进行部署,过程就比较顺利,之前遇到的坑也都没有再出现。


Celery 异步任务

Celery是一个简单,灵活、可靠的分布式任务执行框架,可以支持大量任务的并发执行。在这个LLM RAG应用中,我用它来异步处理后端上传的文档。因为每一个文档上传后,视文档内容的多寡,平均需要几秒到几分钟不等的时间进行文本向量化处理。这个向量化处理过程如果在上传时同步处理,用户势必要等待较长时间,而Celery异步任务能很好的解决这个问题。


Celery采用典型生产者和消费者模型。生产者提交任务到任务队列,消费者从任务队列中取任务执行。Celery由以下三部分构成:消息中间件(Broker)、任务执行单元Worker、结果存储(Backend)。


任务调用提交任务执行请求给Broker队列,Worker会从队列中取出任务并执行,执行结果保存在Backend中。这里Broker 和 Backend都可以直接使用Redis,而我们把重心放在 Worker 程序的实现上即可。


Supervisord 应用进程管理 

Supervisord 是一个在Linux系统中运行的进程管理工具,能够监控和自动重启进程。比如Django开发的应用后端,通过 daphane 启动的多个服务进程,以及 celery 启动的异步任务进程都可以配置到 supervisord 中统一监控和管理,进程出现异常时可以自动重启等。


操作系统重启后如何让 supervisord 自动启动呢?有多种方法,而我采用的是添加 supervisord到systemd,由系统守护进程来管理 supervisord 这个用户级的守护进程。这种方式需要注意的是 systemd 配置文件中要设置正确的系统账号和环境变量,使 supervisord 进程正常启动并运行在正确的环境中。


Nginx

一个高性能的HTTP和反向代理web服务器,高级负载均衡器。我这里也是常规用法,作为静态文件,比如 js,css,image 的web服务器,和daphne异步web服务的反向代理。需要注意的是如果 nginx 配置文件中有特殊字符,比如中文引号分号等,是无法通过 [nginx -t] 检测出异常的,nginx 仍能正常启动,但无法正常提供服务,也是有点儿坑人的。


MySQL 数据库

免费、开源、最好的关系型数据库之一,在“大雨滴”这个应用中也是常规用法,作为后台文档管理、对话管理、用户管理等模块的数据存储,没啥好说的。我这里用的是AWS的MySQL RDS,20GB存储空间加1G内存足够使用,性能也相当好。


Redis 缓存

免费、开源、可基于内存亦可持久化的日志型、Key-Value非关系型数据库,通常作为应用的缓存。在这个应用中作为session和对话历史的缓存,以及celery的Broker和Backend等。

最初我是用 docker 方式部署安装的 redis(因为安装简单),结果 containerd 进程很快就把整个系统的内存吃光了(AWS免费EC2只提供1GB内存,安装的Amazon Linux 2023默认也没有SWAP缓存),然后造成整个EC2 实例 hang 住没有响应,最后不得不从AWS控制台重启EC2实例。这样造成的后果就是免费的EIP公网地址会在重启后改变,不得不再去修改公网域名DNS指向新的IP地址,很麻烦。

调查发现,containerd 进程默认就会占用1G内存,没研究出来如何调低,只好舍弃docker,改用直接安装部署Redis的方式。然后设置Redis 最大128M内存限制,这样正常情况下会有300M左右的空闲内存。再增加一个2G的SWAP以防万一,就妥妥的运行了几个月也没出问题了。


另外最近有消息说Redis免费许可要更改了,希望之后仍然有社区版供大家继续免费使用。


Chromadb + sqlite3

Chromadb是用来存储RAG应用的文档切片和embedding向量的,它由一个向量索引加一个sqlite3 轻量级数据库组成。我粗算了一下,存入几千万字的文档也不会占用超过5GB的空间。这种情况下 sqlite3 够用了,而且性能也不会差,毕竟使用场景够简单,不会产生不可控的复杂SQL查询或写入。


另外sqlite3 也可以通过 [pragma cache_size] 命令调整cache大小(默认只有8MB),以提升性能。


物理环境 - AWS免费12个月的资源

可以通过这个地址了解一下AWS的免费服务政策,并申请一个12个月免费试用的账号,

https://aws.amazon.com/free/

申请免费账号需要一个真实的邮箱,和一个Visa或万事达信用卡(注册时需要验证)。只使用免费资源的话,不会产生费用。


EC2 + RDS + CloudFront

免费服务中有EC2 虚拟机、RDS(MySQL) 数据库 和 CloudFront(CDN加速)可以在这个应用中使用到。其中CloudFront不是必须,因为这个AI对话应用的功能单一,没有很多可以通过CDN缓存的静态内容。用户对话请求是动态的,必定需要100% 透传到后端服务器。

EC2 和 Database 提供免费的方式是每月750小时,意思是如果你开一台限定规格的实例,就可以全月使用,如果开两台同时运行,就只能跑375小时,也就是只能开机半个月,以此类推。

这里用CloudFront 纯属因为免费,想要学习一下。对比阿里云的“全站加速” CDN服务,个人感觉AWS的使用更加复杂一些,有些概念比较模糊,不像阿里云的CDN服务容易理解(我对CDN使用较浅,未深入了解高级用法)。尤其是当CloudFront提供的URL和它的Origin配置的目标地址不同,且要通过HTTPS访问目标地址时,默认情况会出现如下错误,
这个错误很难让人理解为什么。而通过在后端服务器上抓包才了解到,在这种场景下,CloudFront默认会把自身的URL地址放到request的Host Header里面,如果后端web服务使用的证书不包含CloudFront的URL在其SAN列表时(通常都不包含,毕竟URL不同),Cloudfront就无法信任这个Origin,导致报错。解决的办法也很容易,把Cloudfront的Origin Request Policy修改成 AllViewerExceptHostHeader,这样会把除了 Host Header 之外的其它Request 参数转发到origin站点(或者不使用HTTPS, 或者在Origin站点使用包含CloudFront URL的SSL证书),就可以了。

域名 + 证书

在阿里云注册一个公网域名,大概每年七八十块钱的费用;在AWS的Certificate Manager服务申请一个免费的SSL通配符证书。该证书是整个公网信任的(使用的是公网信任的根证书),并非仅AWS内部信任。


唯一的缺点是AWS不允许导出证书安装到别的地方(否则那些公网CA机构要跟Amazon急了,毕竟一个SSL证书从几十到几千刀不等,而且每年都需要 renew 付费,真的是靠许可一本万利的买卖)。


总结

写“大雨滴”这个LLM RAG应用的微信小程序是一个学习的过程。这几篇文章中的技术介绍都比较粗浅,一方面我习惯于技术应用而欠缺理论总结讲解的经验,另一方面也是因为现学现卖,包括LLM、Django框架,小程序开发等都是首次学习和使用,缺乏深入的认知。写这些文章是作为学习过程的阶段性复习总结,同时也给感兴趣想要开始的道友们一个参考。


作为IT民工,保持持续学习的习惯,提升自学习的能力是很必要的。随着AI的发展,很多行业的学习和进入门槛都将被进一步拉低,当然也包括IT领域,不学习的迟早被学习的卷出去。就我个人的教训来说,学习技术还得重视理论,梳理框架,这样才有利于交流时思路清晰,有利于建立自己的知识体系(相比七零八落的孤立知识点),在后续学习相关或相通的新知识时能举一反三、触类旁通。


关于学习资料,尤其是想要系统的学习某个领域的知识时,可以找一些视频来看。比如B站上就有很多高质量的教学视频,看视频比只看技术文档要高效的多。学习python Django,Vue和小程序,我就是看B站银角大王武沛齐老师的系列教学视频来的。武老师讲课思路清晰,由浅入深,层层递进,听武老师的课不仅不会打瞌睡,还会上瘾(武老师,要是有幸被你看到这篇文章,请联系我支付一下广告费  )。如果实在看累了,看看B站《凡人修仙传》这样的国漫天花板级的作品调剂一下也是不错的。(说凡人是国漫天花板,相信各位道友没有意见吧?


最后,回到AI大语言模型。虽然目前大模型存在无法给出确定性回答的问题,让人开始对其产生质疑,但我坚信随着进一步的发展,它必将改变越来越多的行业生态。保持对AI大模型的持续关注和学习,对我们每个人来说都是一件重要的事情。



53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询