“美术狮 AI 绘画”(以下简称“美术狮”),是我们小团队的一次尝试,定位是人人都可以上手的,充满创意的,理解中文和中国文化的图片生成工具。
在完善图像模型和论证核心问题之后,我们开始构建 MVP(最小化可行产品)。MVP 的构建需要:
- 实现快,开发周期较短
- 模式轻,产品重点突出
- 成本低,只投入较少的人力、物力
这些目标,对于我们而言都是不小的挑战。得益于 Laf 的使用,从开发到第一个版本上线,只用了一周时间;小程序功能精简、目标清晰;主体服务成本(杭州+新加坡)在 100 元 / 月以内(含有优化空间)。
下面会结合“美术狮”MVP 构建的全过程,和大家交流使用 Laf 这个平台(技术)的思考。
原文链接:https://forum.laf.run/d/984
技术选型过程
函数即服务,是目前我们对 Laf范式的思考和理解。也是“美术狮”选择 Laf 作为服务端的主要因素。
我在 2015 年就接触了“类似”的 BaaS 平台 LeanCloud,并做过两次实践。第一次是对爬取的小红书内容做维护,第二次是给一个中科院的朋友做化学试剂编号的管理。
LeanCloud,偏向于数据库即服务这种范式,对数据增删改查,提供基于数据的丰富的查询、聚合运算方法是这个范式的核心。
范式无优劣之分,取决于需要解决的问题场景、复杂度和规模。对于以数据库为中心的,包含简单鉴权的系统比如 CRM、甚至是 ERP,LeanCloud 都可以很好地适应和匹配。
我们还尝试和了解过主打实时性的野狗云(已下线),以及后来上线一段时间又被字节跳动下线的轻服务(已下线)。也尝试过跟着教程使用 Firebase。
“美术狮”或者其他的 AI 应用的实际使用场景中,数据库的操作只是一个部分,复杂的内容生成逻辑、多平台资源调度、相对密集的计算是这类场景中的重心。
小程序本身,虽然运行在客户端内拥有一定的计算能力,但是把它看作一个增强的 BS 结构通用性会更好,我们需要把大量地生成逻辑和计算处理流程剥离出来放在服务端由多平台协同完成;同时为了减小分发包的大小,当需要包含其他 SDK 文件时,我们也会格外谨慎。
因此,数据库即服务,并不能很好地解决我们所面临的问题,可能并不是 AICG 应用优先会选择的范式。
腾讯云函数(Serverless)
接下来尝试了使用腾讯云函数,能满足了我们的一部分需求。
但是对于单次计算相对密集,调用资源繁多,访问量不稳定的应用而言。冷启动是可怕的,服务被冷却后,再一次被拉起来需要较长地等待时间。在并发和访问量不大时,云函数被频繁地冷却,对用户体验伤害较大,较为致命。这个对于每一个从 0 到 1 的独立开发者可能都是个头疼的问题。
对存储桶、数据库,腾讯云函数并没有做深度地整合,单独配置云数据库、存储桶,会在 MVP 阶段增加不必要的时间和费用的开销。
微信云开发
微信云开发可以通过微信开发者工具一键开通。在“美术狮”迁移的 Laf 之前,我们在微信云开发中做了大量的尝试。
放弃使用微信云开发,主要是下面一些原因:
- 基础库 Node 版本过低,对第三方包支持不好;
- IDE 开发体验不好,写代码像是看 PPT,本地调试不够方便直观;
- 计费系统诡异,虽然我们是腾讯云的老用户,小程序无法在原有账户中开通服务,必须以小程序的维度新开通账户,付费和管理维护不方便;
- 对跨区域、跨服务支持不佳;
- 冷启动延迟依然明显。
通过内置的鉴权机制快速获取 openid,是微信云开发宣称的优势。
在“美术狮”产品迁移后到 Laf 后,结合社区教程,也可以在“3 分钟”内,实现实现这些功能。
从 0 写一个微信小程序对接 Laf 云开发获取用户 openid - Sealos 开发者社区
Supabase、Vercel、Cloudflare
Verce、Cloudflare 是我特别喜欢的两个平台,这里一笔带过。主要原因是无法整合到国内的网络环境中。
最终我们选择了 Laf。在使用 Laf 的过程中,我们获得几乎等同于 Woker、EdgeFunction 的使用体验和开发效率。
为什么选择 Laf?
函数即服务
Laf 最吸引我们的,是通过云函数的构建应用的方式。
函数即服务在一定程度上,是可以包容(包含)数据库即服务这个范式的。
传统的 Server 端开发,通过 Router
和 Controller
去组织代码,利于管理和维护。但是,从另一个层面看,会在一定程度上,降低了 MVP 产品的开发效率,阻碍了创新的落地。
“美术狮”在第一个版本上线前半个小时,决定添加一个每日签到的功能。
通过云函数,我们更聚焦新特性、新功能,而不是困在这个签到功能应该放在哪个 Router 下,哪个 Controller 下这些工程管理的思考中。通过定义一个 task_user_daily_check_in
,我们很快地实现了这个功能。
云函数调用云函数,是另外一个我喜欢的特性,我们定义了若干个“内部”云函数(同时关闭了所有 HTTP 方法),来为其他云函数服务。比如获取第三方服务的 access token
并在本地持久化。一方面,代码能够解耦和复用,另一方,安全性也大大提升。
例如这段代码,获取百度云服务的 access token
,关闭请求方法后,仅能被内部调用。
import cloud from '@lafjs/cloud'
export default async function (ctx: FunctionContext) {
const ret = await cloud.fetch({
url: "https://aip.baidubce.com//oauth/2.0/token?",
method: "get",
params: {
'grant_type': 'client_credentials',
'client_id': process.env.BAE_CLIENT_ID,
'client_secret': process.env.BAE_CLIENT_SECRET
},
});
cloud.shared.set('bae_access_tooen', ret.data.access_token)
}
当然,云函数过多后,仅能通过修改函数名去人为地调整云函数的排序,目录结构会显得凌乱,如果能按照 Tag(虚拟文件夹)去聚合、管理云函数,对我而言,会更清晰和直观。
技术栈友好
Laf 使用 Typescript
( Javascript
)进行开发,与 web 端、小程序开发属于同一技术栈。大大降低了全栈开发的难度,同时绝大多数代码可以在两端进行复用。
在避免讨论“谁是世界上最好的编程语言”的前提下,仅从团队、成本、开发效率几个方面讨论,一致的技术栈是 MVP 开发的一个好选择。
良好地第三方支持
Laf 对 第三方 NPM
包的支持很好。我尝试过引用 moment
等这些第三方库处理时间数据,七牛等第三方服务处理图片资源,同时内置了大量常用的第三方库。
如同乐高拼图,云函数可以不断地、从不同维度地整合和丰富。存在大量第三方依赖的项目,迁移时成本较低。
实测,秒下各类第三方 NPM 包,精准版本控制,不需要“魔法”。
开箱即用的数据库
Laf 内置了对 Mongodb
的良好支持,提供了一个开箱即用的数据库。够用,好用。
Laf 除了提供大量封装后的查询、聚合方法外,也提供了与原生 Mongo
交互的接口。
例如:通过与原生数据库交互创建索引。
import cloud from "@lafjs/cloud";
const db = cloud.database()
export async function main(ctx: FunctionContext) {
let res = await cloud.mongo.db.collection('users').createIndex({ "openid": 1})
const resIndexs = await cloud.mongo.db.collection("users").indexes()
return resIndexs
};
便利、直观的在线调试
在 Laf 中通过控制台、日志,可以完成绝大部分的调试工作。复杂一点的操作可以通过内置的极简的 Postman(接口调试)去完成。
这种极简、干练的风格贯穿 Laf 的功能(也包括上面提到的数据库设计)、UI,是我们 fancy Laf 的另一个重要原因。
实际的使用过程中,除了“存储”这个功能,其他所有的功能区,面板都能被我们高频地使用到。聚焦目标,专注效率,冗余度低。
杭州、新加坡两地部署
在“美术狮”的开发过程中,我们在 laf.run(杭州)、laf.dev(新加坡)分别购买和部署了 Laf。多服务交融、跨区域的开发是一种奇妙的体验。
“美术狮”在图片的生成过程中,利用了腾讯云在新加坡的 GPU,图片的存储、优化又在国内完成,最终由七牛提供持久化和 CDN 服务。
Laf 在杭州与新加坡之间通信通畅,可用性高,与其他第三方平台能够完美地整合。
一键弹性伸缩
得益于同门的 Sealos
等项目和 Laf
在云计算方面的深耕,Laf 可以一键配置应用规格和弹性伸缩。
虽然,无数的产品默默地消失了,除非被 DDOS,很多产品很难触发弹性伸缩的条件(比如“美术狮”),但是梦想总是要有的。
短时间的高平发需要专业的运维,极快地做出水平拓展,对于小团队而言,在技术、资金方面都很难做到。Laf 很好地解决了这个后顾之忧,给我们提供了莫大的安全感,这个方面,我会在后面的部分继续补充。
开源、开放
Laf 与我使用过的其他 BaaS 不同,是一个开源项目。
之前有幸和 @ 马斯洛 有过一次对话,马老板是一个深邃、有远见的 Leader。
如果一个项目只隶属于一个公司,那么这个项目的命运大致会捆绑在这个公司的命运上。而一个项目属于社群,哪怕公司没有了,项目仍然能发展、完善。
开源的决定让 Laf 拥有了更长的生命周期和可靠性。用户再也不用担心像“轻服务”突然下线这种事情的发生,可以更放心地实践和使用平台和技术。
另外,不到万不得已,我不会去尝试部署 Laf 的服务。我有一堆自己的理由:
- 可靠和稳定能够节省更多的成本,自部署相当于自己承担服务的可靠性,很多人的专业性和运维能力并不足以完成这个工作;
- 项目的维护者们更了解项目,也能更好、更快地解决突发问题;
- Laf 的部分特性,是靠集群发挥的,购买和维护集群的成本会更高;
- 向开源项目付费、贡献代码,是对开发者很好地鼓励和支持。
良好用户运营和收费
在使用了 Laf 的过程中,曾遇到一个无法为文档创建索引的故障。@ 白夜 帮忙联系了 @ 马斯洛 后,很快解决了我的问题。绝大多数问题可以在文档和社区找到解答和代码片段。
我们反馈过希望有一个“回收站”的功能。Laf 迭代更新后,回收站如期而至,作为用户,想法被倾听、尊重并实现真是一件开心的事情。
之前对 Laf 的配置缺乏了解,在后台调整了过高的配置。马老板 会把实际资源消耗情况和建议调整值告诉我,每一次沟通都能让我们感受到技术大牛的魅力和一颗为用户着想的心。
合计下来,价廉物美,比一台中等配置的云服务器性价比高很多,同时,我也不用担心可能会到来的流量高峰,我相信 Laf 专业的运维一定会解决“美术狮”未来会遇到的问题。
番外篇
我们是 Midjourney 和 SD 的忠实粉丝。“美术狮”这个名称是 GPT-4 出谋划策的,小程序 Logo 和部分图片资源也是由“美术狮”生成的。
在使用 Mid 和 SD 的过程中,我们发现两个问题:
- 准确的 Prompts 需要使用英文书写,特定的英文词汇需要记忆、积累(比如风格、镜头、视角等);
- Prompts 需要通过结构化排列,关键词的顺序也会影响出图质量,同时创作者需要具备一定的美术、摄影方面的专业素养。
身边能把 Mid 或者 SD 用好的人少之又少;一个是语言问题,一个是专业问题。
我们以 Dalle2 模型,作为训练起点,没错,就是画面惨不忍睹的 Dalle2,虽然如此,Dalle 是目前绘画模型中最懂自然语言的。
Prompts 是文字,由图片 describe
出的 Tag
也是文字,语言文字是信息沟通最重要的媒介,大语言模型更是这次 AI 浪潮的基石。
我们通过 3 个多月,提升了“美术狮”对自然语言特别是中文的理解,让它更灵动、更懂你,尽管还有诸多不完美,过程中仍然带给我们许多惊喜。
我们团队在以后的实践中,会继续使用 Laf,使用 Laf 是快乐的事情。希望越来越多的人能够感受到 Laf 的魅力。也希望 Laf 明天会更好。