作者:计缘
LLM Chat 应用大家应该都不陌生,这类应用也逐渐称为了我们日常的得力助手,如果只是个人使用,那么目前市面上有很多方案可以快速的构建出一个LLM Chat应用,但是如果要用在企业生产级别的项目中,那对整体部署架构,使用组件的性能,健壮性,扩展性要求还是比较高的。本文带大家了解一下如何使用阿里云Serverless计算产品函数计算构建生产级别的LLM Chat应用。
该最佳实践会指导大家基于开源WebChat组件LobeChat [ 1] 和阿里云函数计算(FC) [ 2] 构建企业生产级别LLM Chat应用。实现同一个WebChat中既可以支持自定义的Agent,也支持基于Ollama部署的开源模型场景。
生产级别应该具备哪些能力
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
为什么选择LobeChat?毫无疑问,因为LobeChat满足上述我列出的Web Chat组件应该具备的能力。我们来一步一步探索。
结构化数据持久化
LobeChat支持数据库版本(PostgreSQL),也就意味着Web Chat中的大部分核心信息都可以持久化存储,无论用哪种浏览器,在哪里使用,使用电脑端还是移动端,都可以无缝衔接。
创建PostgreSQL数据库
打开阿里云RDS控制台 [ 3] ,创建PostgreSQL实例,数据库引擎选择PostgreSQL,数据库产品系列、产品类型、存储类型、实例规格按照业务实际需求选择。该最佳实践中选择最低配置。
创建数据库用户
等待数据库实例启动成功后,进入实例详情页,创建数据库用户。
用户名密码自行填写,帐号类型选择高权限帐号。
创建数据库
创建数据库。
授权帐号选择刚才创建的用户,其他默认即可。
PG链接地址
进入数据库链接菜单,找到内网地址,后续在函数中会配置。
设置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 Endpoint
创建好Bucket后,点击Bucket名称进入Bucket概览页。
在概览页中可以看到该Bucket的地域级Endpoint和Bucket级Endpoint。在下文中配置LobeChat环境变时会用到。
Bucket 安全性设置
点击左侧权限控制/阻止公共访问菜单,开启阻止公共访问。
点击左侧权限控制/读写权限菜单,保证Bucket ACL 为私有。
部署LobeChat
该章节介绍如何将 LobeChat 数据库版部署到阿里云函数计算。
创建阿里云镜像仓库ACR
虽然LobeChat是开源项目,但是如果没有非常企业定制化的功能需要自行修改的话,还是建议直接使用Dockerhub上的镜像进行部署。所以需要将镜像推送到ACR,以便后续和函数计算FC做联动。
打开阿里云镜像管理服务ACR控制台 [ 5] ,创建容器镜像服务实例,生产中建议创建企业版实例,在该最佳实践中,可以创建个人版。
点击创建个人版。
创建完个人版实例后,设置登录密码。
创建镜像仓库的命名空间。进入命名空间菜单,点击创建命名空间按钮。
按实际需求输入命名空间名称。
命名空间全局唯一,如果提示命名空间已被占用,请重新填写,请替换新的名称。
进入镜像仓库菜单,点击创建镜像仓库。
- 命名空间:选择刚才创建好的命名空间。
- 仓库名称:按照实际需求自行填写。
- 仓库类型:选择私有
- 摘要:按照实际需求自行填写
代码源选择本地仓库,然后点击创建镜像仓库按钮。
拉取 LobeChat 镜像推送到 ACR
LobeChat的镜像 [ 6] 托管在Dockerhub上,所以在国内无法访问,这里可以使用自己的方式Pull镜像。
docker pull lobehub/lobe-chat-database
建议:可以购买一台Region的ECS,安装Docker,将LobeChat镜像拉取下来,然后在推送到ACR。
推送镜像到ACR
进入到上文步骤中创建的镜像仓库详情页,可以看到将镜像推送到ACR的命令。
依次执行以下3行命令。
docker login --username=[阿里云帐号邮箱] registry.cn-beijing.aliyuncs.com
docker tag [LobeChat镜像的ImageId] registry.cn-beijing.aliyuncs.com/[命名空间]/[仓库名称]:[镜像版本号]
docker push registry.cn-beijing.aliyuncs.com/[命名空间]/[仓库名称]:[镜像版本号]
创建LobeChat函数
打开函数计算控制台 [ 7] ,点击创建函数。
函数创建方式选择Web函数。
函数名称按需填写,这里填写lobechat-database-fc。
- 运行环境:选择自定义容器镜像。
- 镜像选择方式:选择使用 ACR 中的镜像。
- 点击选择 ACR 中的镜像,选择上文中创建好的ACR中的LobeChat镜像
- 监听端口:填写3210。
- 是否使用GPU:选择不使用GPU。
- 规格方案:选择1 vCPU,2048 MB。
- 执行超时时间:填写300。
- 函数角色:选择AliyunFcDefaultRole。
其他配置项暂时保持默认,然后点击下方创建按钮。
LobeChat函数环境变量设置
点击函数列表中的lobechat-database-fc函数,进入函数详情页。
点击配置页签,点击左侧环境变量菜单,点击编辑,添加该LobeChat函数需要的环境变量。
选择使用JSON格式编辑。
{
"DATABASE_URL": "postgres连接地址",
"KEY_VAULTS_SECRET": "随机的 32 位字符串",
"NEXT_PUBLIC_S3_DOMAIN": "OSS Bucket Endpoint",
"NEXT_PUBLIC_SERVICE_MODE": "server",
"S3_ACCESS_KEY_ID": "阿里云帐号AK",
"S3_BUCKET": "OSS Bucket名称",
"S3_ENDPOINT": "OSS 地域级 Endpoint",
"S3_REGION": "阿里云地域ID",
"S3_SECRET_ACCESS_KEY": "阿里云帐号SK"
}
- DATABASE_URL:参见上文中的PG链接地址。
- 格式为postgres://username:password@host:port/database
- KEY_VAULTS_SECRET:考虑到用户会存储自己的 API Key 和 baseURL 等敏感信息到数据库中,因此我们需要一个密钥来加密这些信息,避免数据库被爆破 / 脱库时这些关键信息被泄露。 因此有了 KEY_VAULTS_SECRET 环境变量,用于加密用户存储的 API Key 等敏感信息。
- 你可以使用 openssl rand -base64 32 命令生成一个随机的 32 位字符串作为 KEY_VAULTS_SECRET 的值
- NEXT_PUBLIC_SERVICE_MODE:LobeChat 同时支持了客户端数据库和服务端数据库,因此我们提供了一个环境变量用于切换模式,这个变量为 NEXT_PUBLIC_SERVICE_MODE。使用数据库版本需要将该环境变量设置为server。
- NEXT_PUBLIC_S3_DOMAIN:使用Bucket Endpoint中的Bucket域名。
- S3_ENDPOINT:使用Bucket Endpoint中的地域级域名。
- S3_BUCKET:Bucket 名称。
- S3_REGION:阿里云地域ID。参见:阿里云地域ID说明 [ 8] 。
- 函数计算,OSS,PostgreSQL 需要保持在同一地域,同一帐号下
- S3_ACCESS_KEY_ID:阿里云帐号AK。登录阿里云帐号,打开AK管理控制台 [ 9] 获取AK。
- S3_SECRET_ACCESS_KEY:阿里云帐号SK。登录阿里云帐号,打开AK管理控制台获取SK。
LobeChat函数网络设置
点击配置页签,点击左侧网络菜单。
点击编辑,添加VPC,VS信息。配置的VPC需要和上文中创建的PostgreSQL所在的VPC保持一致,这样LobeChat函数就可以通过内网地址访问PostgreSQL,提高网络访问效率和稳定性。
- 允许访问VPC:选择是。
- 配置方式:选择自定义配置。
- 专有网络:选择已存在的VPC,和PostgreSQL所在VPC保持一致。
- 交换机:选择已存在的交换机,和PostgreSQL所在交换机保持一致。
- 安全组:选择已存在的安全组,如果没有安全组,可以点击创建新的安全组。
- 安全组是用于对入方向和出方向的IP,端口,协议做管控的策略。在POC或者Demo中,可以将入方向策略的协议设置为全部,授权对象设置为所有
-
- 在正式生产项目中,根据实际需求设置不同协议,不同授权对象,不同端口的策略
配置PG白名单
因为是函数计算中的LobeChat服务访问PG数据库,所以可以将LobeChat函数的交换机网段配置到PG的白名单中。这样就可以去掉设置PG白名单中配置的0.0.0.0/0,增加安全性。
增加访问LLM Chat应用的健壮性
在生产级项目中,路由策略,流量访问控制策略等是必不可少的,所以这里会引入阿里云云原生API网关来增强访问LLM Chat应用的健壮性。
创建云原生API网关
打开云原生API网关控制台 [ 10] 。
点击创建实例按钮,创建云原生API网关实例。
- 地域:根据实际项目需求选择地域,该实践中的所有产品应该处于统一地域。
- 网关名称:根据实际项目情况填写。
- 网关规格:根据实际QPS,客户端最大连接数选择不同的规格。
- 网络访问类型:选择公网。
- 专有网络:选择已有的VPC。需要和PostgreSQL的VPC,函数计算FC设置的VPC保持一致。
- 交换机:选择已有的交换机。需要和PostgreSQL的交换机,函数计算FC设置的交换机保持一致。
云原生API网关地址
点击云原生API网关实例ID,进入概览页。
在概览页的基本信息中可以可以看到云原生API网关的入口地址。下文中多处需要用到。
配置网关自定义域名
进入左侧域名菜单。
点击创建域名按钮,添加域名。
根据实际情况选择HTTP或HTTPS,填写已经备案的域名。如果没有备案的域名,在测试场景下可以填写 *。
域名解析(可选步骤)
如果在配置网关自定义域名时配置了 *。则不需要参考这一步。
打开域名服务商控制台,进入域名管理页面,对域名进行解析。这里以阿里云域名管理为例,打开域名管理控制台 [ 11] 。进入域名列表,找到在配置网关自定义域名中配置的域名。
点击右侧解析,进入域名解析页面。
点击添加记录按钮。
- 记录类型:选择CNAME。
- 主机记录:根据实际需求填写。
- 记录值:填写云原生API网关的入口地址。参见云原生API网关地址。
添加服务来源
创建好云原生API网关后,点击网关名称,进入网关详情页。
点击左侧路由菜单,选择服务页签。
点击创建服务按钮,添加服务。
- 服务来源:选择 FC 函数计算。
- 函数名称:选择创建LobeChat函数中创建的函数。
- 函数别名或版本:选择LATEST。
创建成功后,可以在列表中看到LobeChat函数,并且等到健康检查状态变为健康。
创建路由
点击路由页签,进入路由管理页面,选择普通路由。
点击创建路由按钮。
- 路由名称:根据实际需求填写。
- 域名:如果在配置网关自定义域名中配置了备案域名,且域名完成了解析,则选择自定义域名。如果没有则选择在配置网关自定义域名中创建的*域名。
- 路径:条件为前缀是,路径为/
- 使用场景:选择单服务。
- 后端服务:选择添加服务来源中添加的来源为函数计算的LobeChat函数服务。
其他设置保持默认,然后点击保存并发布。
增加路由健壮性
如果希望增加路由健壮性,可以针对路由设置各种策略,比如流控策略。在路由列表页中点击路由名称进入路由详情页。
然后进入策略配置页签,可以按需进行配置。具体可参见云原生API网关策略文档 [ 12] 。
用户身份管理
LobeChat 集成了 next-auth,一个灵活且强大的身份验证库,支持多种身份验证方式,包括 OAuth、邮件登录、凭证登录等。通过 next-auth,可以轻松实现以下功能:
- 用户注册和登录:支持多种认证方式,满足不同用户的需求。
- 会话管理:高效管理用户会话,确保安全性。
- 社交登录:支持多种社交平台的快捷登录。
- 数据安全:保障用户数据的安全性和隐私性。
LobeChat用户身份管理目前的缺陷
- 目前还没有实现 next-auth 与服务端数据库的集成,如果需要使用服务端数据库,可以使用 LobeChat 集成的 Clerk。但是使用Clerk又引入了一个三方组件,对于企业用户来说可能不是一个好的选择。
- 目前还没有提供原生和企业内部用户管理体系集成的方案,比如单点登录方案。站在企业生产级这个前提下,和企业内部用户管理系统对接应该是刚需。如果要实现,可以参考以下三种方式:
- LobeChat是开源组件,用户可以自行实现,以满足自身企业的需求。
- 可以使用Auth0实现和企业内部用户管理系统的SSO单点登录。
- 后续CAP来补充这部分方案。
Next Auth 实现用户身份管理
目前支持的身份验证服务有:
- Auth0
- Microsoft Entra ID
- Authentik
- Github
- ZITADEL
本文以Auth0和Github为例。
基于Auth0实现用户身份管理
创建 Auth0 应用
注册并登录 Auth0 [1****3] ,点击左侧导航栏的「Applications」,切换到应用管理界面,点击右上角「Create Application」以创建应用。
填写你想向组织用户显示的应用名称,可选择任意应用类型,点击「Create」。
创建成功后,点击相应的应用,进入应用详情页,切换到「Settings」标签页,就可以看到相应的配置信息。
在应用配置页面中,还需要配置 Allowed Callback URLs,在此处填写:
http(s)://[your-domain]/api/auth/callback/auth0
只需要变更[your-domain]部分:
- 如果在云原生API网关中配置了备案域名,并且对域名设置了解析,那么此处配置的就是解析域名。
- 如果在云原生API网关中配置了*域名,那么此处配置云原生API网关的入口地址。参见云原生API网关地址。
新增Auth0用户
点击左侧导航栏的「Users Management」,进入用户管理界面,可以为你的组织新建用户,用以登录 LobeChat。
更新LobeChat函数的环境变量
参照LobeChat函数环境变量设置中找到配置LobeChat函数环境变量的地方,增加以下环境变量信息。
{
"DATABASE_URL": "postgres连接地址",
"KEY_VAULTS_SECRET": "随机的 32 位字符串",
"NEXT_PUBLIC_S3_DOMAIN": "OSS Bucket Endpoint",
"NEXT_PUBLIC_SERVICE_MODE": "server",
"S3_ACCESS_KEY_ID": "阿里云帐号AK",
"S3_BUCKET": "OSS Bucket名称",
"S3_ENDPOINT": "OSS 地域级 Endpoint",
"S3_REGION": "阿里云地域ID",
"S3_SECRET_ACCESS_KEY": "阿里云帐号SK"
"NEXT_AUTH_SECRET": "随机的 32 位字符串",
"NEXT_AUTH_SSO_PROVIDERS": "auth0",
"AUTH0_CLIENT_ID": "Auth0 应用程序的 Client ID",
"AUTH0_CLIENT_SECRET": "Auth0 应用程序的 Client Secret",
"AUTH0_ISSUER": "Auth0 应用程序的 Domain",
"ACCESS_CODE": "添加访问此服务的密码,你可以设置一个足够长的随机密码以 “禁用” 访问码授权",
"NEXTAUTH_URL": "http(s)://your-domain.com/api/auth"
}
- NEXT_AUTH_SECRET:你可以使用 openssl rand -base64 32 命令生成一个随机的 32 位字符串作为 NEXT_AUTH_SECRET 的值。
- NEXT_AUTH_SSO_PROVIDERS:auth0
- AUTH0_CLIENT_ID:Auth0 应用程序的 Client ID,参见创建 Auth0 应用。
- AUTH0_CLIENT_SECRET:Auth0 应用程序的 Client Secret,参见创建 Auth0 应用。
- AUTH0_ISSUER:Auth0 应用程序的 Domain,参见创建 Auth0 应用。
- Domain需要带着https://
- ACCESS_CODE:你可以使用 openssl rand -base64 32 命令生成一个随机的 32 位字符串作为 ACCESS_CODE 的值。
- NEXTAUTH_URL:http(s) 标签:网关,LLM,创建,域名,点击,API,Chat,LobeChat From: https://www.cnblogs.com/alisystemsoftware/p/18399005