
LLM Chat 应用大家应该都不陌生,这类应用也逐渐称为了我们日常的得力助手,如果只是个人使用,那么目前市面上有很多方案可以快速的构建出一个LLM Chat应用,但是如果要用在企业生产级别的项目中,那对整体部署架构,使用组件的性能,健壮性,扩展性要求还是比较高的。本文带大家了解一下如何使用阿里云Serverless计算产品函数计算构建生产级别的LLM Chat应用。
该最佳实践会指导大家基于开源WebChat组件LobeChat[1]和阿里云函数计算(FC)[2]构建企业生产级别LLM Chat应用。实现同一个WebChat中既可以支持自定义的Agent,也支持基于Ollama部署的开源模型场景。
生产级别应该具备哪些能力
Cloud Native
LLM Chat应用是一个典型的前后端分离的应用,前端主要是Web Chat服务,后端是和向量数据库,LLM,其他下游服务交互的服务,也可以说是若干个Agent。我们分开来看。Web Chat
我认为生产级别的Web Chat组件至少应该具备以下几点能力:
所有信息需要持久化,也就是说肯定是需要有一套数据库结构来支撑的:存储所有配置信息存储所有对话信息存储所有对话窗口信息,也就是类似每一个聊天助手的信息用户体系,权限认证体系。可以对接多种LLM,无论是商业LLM还是开源LLM,亦或是自定义的Agent(比如遵循OpenAI接口范式的自定义API)。支持temperature,top_p,presence_penalty,frequency_penalty等设置支持多模态交互。(除文本聊天外,可以上传图片,文件,甚至语音)支持移动端。支持插件扩展。请求Web Chat服务的安全性和健壮性。请求流量防护Header重写超时保护后端服务
后端服务包括与向量数据库,关系型数据库交互的Agent,与商业LLM交互的Agent,与开源LLM交互的Agent,托管开源LLM的服务等。这些服务要上生产,本质上和传统应用后端服务是一样的,需要具备以下几点:
稳定性,健壮性,高可靠性多可用区部署灰度发布高性能支撑高并发灵活构建和调整业务流程工作流编排支持各类主流编程语言Java,Go,Python,NodeJS,.Net Core等支持异构计算既支持CPU,也支持GPU成本更优资源按需所取,按量付费Web Chat 组件 LobeChat
Cloud Native
为什么选择LobeChat?毫无疑问,因为LobeChat满足上述我列出的Web Chat组件应该具备的能力。我们来一步一步探索。结构化数据持久化
LobeChat支持数据库版本(PostgreSQL),也就意味着Web Chat中的大部分核心信息都可以持久化存储,无论用哪种浏览器,在哪里使用,使用电脑端还是移动端,都可以无缝衔接。
创建PostgreSQL数据库打开阿里云RDS控制台[3],创建PostgreSQL实例,数据库引擎选择PostgreSQL,数据库产品系列、产品类型、存储类型、实例规格按照业务实际需求选择。该最佳实践中选择最低配置。

等待数据库实例启动成功后,进入实例详情页,创建数据库用户。


用户名密码自行填写,帐号类型选择高权限帐号。
创建数据库创建数据库。


授权帐号选择刚才创建的用户,其他默认即可。
PG链接地址进入数据库链接菜单,找到内网地址,后续在函数中会配置。

进入白名单与安全组菜单,点击白名单设置页签。

点击右侧修改,根据实际需求添加白名单IP或者网段。在POC时,可以添加0.0.0.0/0,白名单IP段设置为0.0.0.0/0意味着对公网开放,请谨慎使用。若为了测试连接设置,测试后请立即修改。
非结构化数据持久化
LobeChat支持上传文件(图片,视频,PDF,MD等),上传的文件都会保存在配置的OSS中。
创建对象存储(OSS)Bucket打开阿里云对象存储OSS控制台[4],点击左侧Bucket列表菜单,点击创建Bucket按钮。

按需填写Bucket名称,其他配置保持默认即可。然后点击完成创建。

创建好Bucket后,点击Bucket名称进入Bucket概览页。

在概览页中可以看到该Bucket的地域级Endpoint和Bucket级Endpoint。在下文中配置LobeChat环境变时会用到。

点击左侧权限控制/阻止公共访问菜单,开启阻止公共访问。

点击左侧权限控制/读写权限菜单,保证Bucket ACL 为私有。

部署LobeChat
该章节介绍如何将 LobeChat 数据库版部署到阿里云函数计算。
创建阿里云镜像仓库ACR虽然LobeChat是开源项目,但是如果没有非常企业定制化的功能需要自行修改的话,还是建议直接使用Dockerhub上的镜像进行部署。所以需要将镜像推送到ACR,以便后续和函数计算FC做联动。
打开阿里云镜像管理服务ACR控制台[5],创建容器镜像服务实例,生产中建议创建企业版实例,在该最佳实践中,可以创建个人版。

点击创建个人版。

创建完个人版实例后,设置登录密码。


创建镜像仓库的命名空间。进入命名空间菜单,点击创建命名空间按钮。

按实际需求输入命名空间名称。
命名空间全局唯一,如果提示命名空间已被占用,请重新填写,请替换新的名称。

进入镜像仓库菜单,点击创建镜像仓库。



代码源选择本地仓库,然后点击创建镜像仓库按钮。
拉取 LobeChat 镜像推送到 ACRLobeChat的镜像[6]托管在Dockerhub上,所以在国内无法访问,这里可以使用自己的方式Pull镜像。
docker pull lobehub/lobe-chat-database建议:可以购买一台Region的ECS,安装Docker,将LobeChat镜像拉取下来,然后在推送到ACR。
推送镜像到ACR
进入到上文步骤中创建的镜像仓库详情页,可以看到将镜像推送到ACR的命令。

依次执行以下3行命令。
docker login --username=[阿里云帐号邮箱] registry.cn-beijing.aliyuncs.comdocker tag [LobeChat镜像的ImageId] registry.cn-beijing.aliyuncs.com/[命名空间]/[仓库名称]:[镜像版本号]docker push registry.cn-beijing.aliyuncs.com/[命名空间]/[仓库名称]:[镜像版本号]创建LobeChat函数打开函数计算控制台[7],点击创建函数。

函数创建方式选择Web函数。

函数名称按需填写,这里填写lobechat-database-fc。



其他配置项暂时保持默认,然后点击下方创建按钮。
LobeChat函数环境变量设置点击函数列表中的lobechat-database-fc函数,进入函数详情页。

点击配置页签,点击左侧环境变量菜单,点击编辑,添加该LobeChat函数需要的环境变量。

选择使用JSON格式编辑。

点击配置页签,点击左侧网络菜单。

点击编辑,添加VPC,VS信息。配置的VPC需要和上文中创建的PostgreSQL所在的VPC保持一致,这样LobeChat函数就可以通过内网地址访问PostgreSQL,提高网络访问效率和稳定性。

因为是函数计算中的LobeChat服务访问PG数据库,所以可以将LobeChat函数的交换机网段配置到PG的白名单中。这样就可以去掉设置PG白名单中配置的0.0.0.0/0,增加安全性。
增加访问LLM Chat应用的健壮性
在生产级项目中,路由策略,流量访问控制策略等是必不可少的,所以这里会引入阿里云云原生API网关来增强访问LLM Chat应用的健壮性。
创建云原生API网关打开云原生API网关控制台[10]。

点击创建实例按钮,创建云原生API网关实例。

点击云原生API网关实例ID,进入概览页。


在概览页的基本信息中可以可以看到云原生API网关的入口地址。下文中多处需要用到。
配置网关自定义域名进入左侧域名菜单。

点击创建域名按钮,添加域名。

根据实际情况选择HTTP或HTTPS,填写已经备案的域名。如果没有备案的域名,在测试场景下可以填写 *。
域名解析(可选步骤)如果在配置网关自定义域名时配置了 *。则不需要参考这一步。
打开域名服务商控制台,进入域名管理页面,对域名进行解析。这里以阿里云域名管理为例,打开域名管理控制台[11]。进入域名列表,找到在配置网关自定义域名中配置的域名。

点击右侧解析,进入域名解析页面。

点击添加记录按钮。


创建好云原生API网关后,点击网关名称,进入网关详情页。

点击左侧路由菜单,选择服务页签。

点击创建服务按钮,添加服务。


创建成功后,可以在列表中看到LobeChat函数,并且等到健康检查状态变为健康。
创建路由点击路由页签,进入路由管理页面,选择普通路由。

点击创建路由按钮。

其他设置保持默认,然后点击保存并发布。
增加路由健壮性如果希望增加路由健壮性,可以针对路由设置各种策略,比如流控策略。在路由列表页中点击路由名称进入路由详情页。

然后进入策略配置页签,可以按需进行配置。具体可参见云原生API网关策略文档[12]。

用户身份管理
LobeChat 集成了 next-auth,一个灵活且强大的身份验证库,支持多种身份验证方式,包括 OAuth、邮件登录、凭证登录等。通过 next-auth,可以轻松实现以下功能:
用户注册和登录:支持多种认证方式,满足不同用户的需求。会话管理:高效管理用户会话,确保安全性。社交登录:支持多种社交平台的快捷登录。数据安全:保障用户数据的安全性和隐私性。LobeChat用户身份管理目前的缺陷目前还没有实现 next-auth 与服务端数据库的集成,如果需要使用服务端数据库,可以使用 LobeChat 集成的 Clerk。但是使用Clerk又引入了一个三方组件,对于企业用户来说可能不是一个好的选择。目前还没有提供原生和企业内部用户管理体系集成的方案,比如单点登录方案。站在企业生产级这个前提下,和企业内部用户管理系统对接应该是刚需。如果要实现,可以参考以下三种方式:LobeChat是开源组件,用户可以自行实现,以满足自身企业的需求。可以使用Auth0实现和企业内部用户管理系统的SSO单点登录。后续CAP来补充这部分方案。Next Auth 实现用户身份管理目前支持的身份验证服务有:
Auth0Microsoft Entra IDAuthentikGithubZITADEL本文以Auth0和Github为例。
基于Auth0实现用户身份管理创建 Auth0 应用注册并登录 Auth0[13],点击左侧导航栏的「Applications」,切换到应用管理界面,点击右上角「Create Application」以创建应用。

填写你想向组织用户显示的应用名称,可选择任意应用类型,点击「Create」。

创建成功后,点击相应的应用,进入应用详情页,切换到「Settings」标签页,就可以看到相应的配置信息。

在应用配置页面中,还需要配置 Allowed Callback URLs,在此处填写:
http(s)://[your-domain]/api/auth/callback/auth0只需要变更[your-domain]部分:
如果在云原生API网关中配置了备案域名,并且对域名设置了解析,那么此处配置的就是解析域名。如果在云原生API网关中配置了*域名,那么此处配置云原生API网关的入口地址。参见云原生API网关地址。
点击左侧导航栏的「Users Management」,进入用户管理界面,可以为你的组织新建用户,用以登录 LobeChat。


参照LobeChat函数环境变量设置中找到配置LobeChat函数环境变量的地方,增加以下环境变量信息。

Auth0 和其他任务的单点登录可以参考LobeChat的文档[14]。
基于Github实现用户身份管理创建 Github 应用点击这里[15]创建一个新的 Github App。填写 Github App name、Homepage URL、Callbak URL。



设置读取邮件地址权限。

设置公开访问还是仅自己访问。

点击「Create Github App」。创建成功后,点击「Generate a new client secret」创建客户端 Secret。

创建成功后,将客户端 ID 和客户端 Secret 保存下来。
更新LobeChat函数的环境变量参照LobeChat函数环境变量设置中找到配置LobeChat函数环境变量的地方,增加以下环境变量信息。

其他服务的认证管理接入方式可以参考LobeChat的文档[16]。
访问LobeChat
访问配置网关自定义域名中配置的域名或者云原生API网关地址,便可打开LobeChat。

点击左上角的图标。

点击登录/注册。

会跳转到Auth0的登录界面。输入你在新增Auth0用户中创建的用户名密码进行登录。

登录成功后可以看到帐号信息。

查看LobeChat表结构
进入创建PostgreSQL数据库中创建的PG数据库详情页。

点击右上角登录数据库按钮,进入DMS控制台。

可以看到当第一访问LobeChat时,会初始化若干表,有兴趣的同学可以自行查看表结构。
后端服务
Cloud Native
在该最佳实践中,后端服务涉及2类:和LLM交互的服务。自定义的Agent服务(有客户自己的业务逻辑)。这两类后端服务都会使用阿里云函数计算实现,可以提供更细粒度资源规格(0.05C 128MB),更高性能(稳定支撑100w-150w QPS),更高弹性效率(百毫秒拉起实例)的CPU算力,也可以提供多种稳定的GPU资源。同时还自带完善的可观测,灰度发布等能力。使传统应用,AI应用的后端服务更健壮。
和LLM交互的服务(Ollama)
阿里云函数计算提供了构建Ollama服务的应用模板,可以快速创建出包含GPU算力的Ollama服务。
创建函数计算Ollama应用打开函数计算控制台,进入应用菜单。

点击创建应用按钮。选择通过模板创建应用,选择人工智能页签,可以看到Ollama应用。

点击详情按钮,可以查看该应用的详细信息。

点击立即创建按钮可以快速开始创建应用。


建议选择其中一个模型,因为初始的模型是打在镜像里的,如果选择多个模型集成,会使镜像过大,影响Ollama函数弹性速度。后续可以挂载NAS,使用Ollama的API下载其他模型。
GPU实例类型:T4:fc.gpu.tesla.18C,32GB内存,16GB显存A10:fc.gpu.ampere.18C 32GB内存,24GB显存显存大小,内存大小,GPU核数根据实际情况填写,建议使用整卡(保持默认值),否则会影响推理效率。设置完后点击左下方创建应用按钮,开始创建应用。

等待片刻后,便可以看到Ollama应用部署成功。

点击左下角Ollama函数,可以进入Ollama函数详情页面。
Ollama服务访问地址进入Ollama函数详情页面,点击配置页签,进入左侧触发器菜单。可以看到公网访问地址和内网访问地址。

可以通过给Ollama函数挂载NAS,通过API将其他所需的模型下载到NAS中,既不影响镜像大小,也可以灵活使用更多种的开源模型。
挂载NAS点击左侧网络菜单,点击编辑按钮,添加VPC。


点击左侧存储菜单,点击NAS 文件系统右侧的编辑按钮。


进入配置页签,点击左侧环境变量菜单,点击环境变量右侧的编辑按钮。

增加如下2个环境变量。

可以使用Postman或者终端访问Ollama API[17]下载模型,模型会直接下载到NAS中。
curl http://Ollama服务地址/api/pull -d '{ "name": "llama3.1:8b"}'Ollama服务地址:参见Ollama服务访问地址。模型名称:可以从Ollama支持的模型[18]中选择。比如下载llama3.1:8b。自定义Agent服务
创建函数打开函数计算控制台,进入左侧函数菜单。

点击创建函数按钮。

其他设置保持默认。
代码示例点击代码页签,在WebIDE中,删除app.py中的默认代码,将以下代码复制进app.py中。

点击配置页签,进入左侧触发器菜单,可以看到公网访问地址和内网访问地址。

配置 LobeChat
Cloud Native
登录LobeChat后,点击立即开始。
点击右上角会话设置。

点击左侧语言模型菜单。

可以看到LobeChat已经集成了几乎市面上所有主流的LLM服务,所有可以实现在一个Web Chat中可以和多家LLM进行交互,也就是不同的会话可以配置不同的模型,灵活性非常高。
本文开头说过,该最佳实践主要实现Ollama服务托管的模型和自定义的Agent,所以在语言模型设置页面,我们主要会设置OpenAI(用于配置自定义Agent)和Ollama。
配置自定义Agent

开打OpenAI开关,配置自定义Agent信息:
API Key:随意填写。API 代理地址:填写自定义Agent访问地址的公网地址。使用客户端请求模式:开启。模型列表:因为是自定义Agent,所以可以删掉OpenAI默认的模型名称,自行输入名称并创建。联通性检查:点击检查按钮进行检测。如果都按照文档内容实操的话,会出现检查通过的信息。
关闭模型配置窗口,回到主窗口,点击上方模型,切换到custom-agent,也就相当于会请求到自定义Agent服务中。

进行聊天对话,可以看到会响应自定义Agent中写死的内容。

配置Ollama服务
点击会话设置,进入语言模型,开启Ollama服务。


回到主窗口,在上方可以切换到llama3.1:8b模型。

在同一个窗口再次进行对话。

配置聊天助手
LobeChat支持创建不同的聊天助手,不同的聊天助手可以是不同的模型,所以我们可以根据业务需求或自己的需求灵活的使用不同的模型或者自定义Agent。
创建翻译助手点击左上角创建聊天助手。

进入聊天助手对话界面,点击右上角的聊天助手设置。

设置聊天助手基本信息,比如头像,头像颜色,聊天助手名称,聊天助手描述等。

设置聊天助手的角色设定。

在聊天偏好中可以设置用户输入预处理等信息。

设置聊天助手的模型,这里选择llama3.1:8b。

回到翻译助手聊天窗口,可以让其进行翻译。

同理,可以创建和自定义Agent交互的聊天助手。

相关链接:
[1] LobeChat
https://github.com/lobehub/lobe-chat
[2] 阿里云函数计算(FC)
https://help.aliyun.com/zh/functioncompute/product-overview/what-is-function-compute
[3] 阿里云RDS控制台
https://yaochi.console.aliyun.com/rds/rdsList/cn-beijing
[4] 阿里云对象存储OSS控制台
https://oss.console.aliyun.com/bucket
[5] 阿里云镜像管理服务ACR控制台
https://cr.console.aliyun.com/cn-beijing/instances
[6] LobeChat的镜像
https://hub.docker.com/r/lobehub/lobe-chat-database
[7] 函数计算控制台
https://fcnext.console.aliyun.com/cn-beijing/functions
[8] 阿里云地域ID说明
https://help.aliyun.com/zh/drp/support/region-ids
[9] AK管理控制台
https://ram.console.aliyun.com/manage/ak
[10] 云原生API网关控制台
https://apigw.console.aliyun.com/#/cn-beijing/gateway
[11] 域名管理控制台
https://dc.console.aliyun.com/next/index
[12] 云原生API网关策略文档
https://help.aliyun.com/zh/api-gateway/cloud-native-api-gateway/user-guide/routing-policy/
[13] Auth0
https://manage.auth0.com/dashboard
[14] LobeChat的文档
https://lobehub.com/zh/docs/self-hosting/advanced/auth/next-auth/auth0
[15] 这里
https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fsettings%2Fapps%2Fnew
[16] LobeChat的文档
https://lobehub.com/zh/docs/self-hosting/advanced/auth
[17] Ollama API
https://github.com/ollama/ollama/blob/main/docs/api.md
[18] Ollama支持的模型
https://ollama.com/library