诞生、爆火、开源、抄袭、沉寂,一个产品的漂流。
一篇长长长长的流水账。
起源
故事起源于 2022 年 5 月的一个周末,我坐在北京昌平区的书店里,正在调试 Disco Diffusion 模型。此时 AI 绘画时代初露端倪、SD 尚未发布。画一张图,在一张性能良好的 V100 显卡上要 5 分钟。
我将开源代码封装成可以只加载一遍模型、暴露少数参数的接口,花 2000/月租了张显卡,并在朋友圈和社交媒体上发帖,想玩 AI 绘画的人可以给我句子描述,我在机器上跑完并把图发给他们。
朋友说,要不搭建一个网站让大家自己玩?于是就有了 6pen。我们在很短时间内有了 100 万用户,然后逐渐销声匿迹。这次“创业”不太成功,我自觉是我没有训练出差异化的模型占很大因素,但这里不展开了。如上所说,SD 发布之前的 AI 绘画速度极慢,我的大部分时间是在做模型加速,其中一个优化项就是 关于 CLIP 模型。
CLIP 是 OpenAI 2021 年发布的模型,它能比较任意一张图片和一句文本之间的相似度。在 Disco Diffusion 中,模型用 CLIP 来计算生成图像与用户prompt
之间的损失,不断优化损失从而实现绘画(详细原理)。使用越小的 CLIP 模型,绘图速度越快,但画面细节也会越差,我当时正在调试以平衡绘图速度和画面细节。
坐在书店里,突然一个想法闯进了脑子:既然可以比较图文相似度,那么可以用它来搜照片吗? 搜索后发现已经有人写了一个用 CLIP 搜图的工具,原理是将图片上传到服务器,统一提取特征,输入英文并计算文本与每一张图的相似度,排序就能实现搜图。
我开始尝试将我的 iPhone 相册上传到服务器,试了一番下来,我发现效果好得惊人!特别是搜一些虚无缥缈的东西,比如我输入"lonely"(孤独),它返回到前三张照片如下:
把照片放在服务器,这不是个好想法。我照片最多的地方就是 iPhone 本地相册。能否做一个完全运行在本地的 CLIP 搜图 App 呢? 我非常喜欢这个 idea,几次和朋友讨论起,但每次都无疾而终。
我心里太没底了:
- 我完全不懂 iOS 开发。
- Apple 底层可能不支持 CLIP 模型算子。
- 即使能跑起来,如果索引速度慢到 1 秒/张,或者搜一次 10 分钟,这个产品也没有意义。
直到 2024 年,端侧模型才逐渐被大家所关注,但在 2022 年,我在 App 市场上没找到一个运行在端侧的语言模型,应该…不太可行吧?我终于忘了这件事,继续投入到 6pen 的研发中。
回响
转折点是 2022 年 12 月初,因为一些变故,我突然到了一个语言完全不通的陌生国家(🇰🇷),与 6pen 的缘分也走到尽头。于是,在空旷的咖啡店,一台笔记本、一杯冰拿铁坐一整天。背景音乐放着 Kpop,窗外是厚厚的积雪,中午饿了吃店里的三明治,我每天就这样度过。
这里网速飞快、没有核酸、周围人的谈话因语言不通自动变成了白噪音,我好像突然活在真空之中。这种陌生的真空感让我兴奋:像流放的逃犯一样,我是谁、我的过去不再重要,在这里我能从头学习并完成任何事。是时候开始做点真正让我兴奋的产品了——这个 idea 再次抓住了我。
但这次,我不再恐惧验证可行性,我学习用 Swift 编写tokenizer
,研究应该如何计算并本地存储特征,学习用多核加速索引,对比不同相似度排序算法。期间在 StackOverflow 提了许多愚蠢的问题,有很多次挫败时刻。但我脑海里一直浮现这个画面:在手机输入"coffee and laptop
",点击搜索,旋转动画后,这张照片从 3 万张相册中跳出来,出现在我眼前。
这个幻想支撑我废寝忘食地干了 2 个星期 —— 字面意思,好几次忘记吃午饭,一杯拿铁喝到傍晚饿到胃疼、全身乏力。有个重要的时间节点,就是 ChatGPT 在那时刚刚发布。但我在开发中陷入太深,根本忽视了它的存在,那可能是我这辈子最后几次在 StackOverflow 提问。
总之,在 12 月 27 日,我终于完整做出了产品。我把模型中的文本模型和图像模型分拆成两个独立模型,分开加载:
为相册构建索引时只加载图像模型,计算索引并保存,搜索时只加载文本模型,并逐一计算与保存的索引之间的余弦距离,然后返回相似度最高的 topK 照片。
错开加载模型可以有效降低软件的内存占用,并且能加速构建索引;在构建索引时计算并保存所有照片的特征,使得搜索过程只是进行特征比较,而与图像无关;同时,用多核并行来加速这两个过程。这一系列的优化下来,可以做到在我的 iPhone 12 mini 上 以 2000 张/分钟速度为照片构建索引,而 10,000 张照片搜一次只要不到 1s。
这表明:算子是支持的、速度是可用的,我悬着的心终于落下了。
定价
作为一个定价小天才,我的设想是:
用户可以免费下载,并构建索引、任意搜索。当他未来有新照片、想更新索引,就要付费。
这个策略妙处在于:只有真正用上了、喜欢这个产品的人,才需要付费。那些来尝鲜的、或者试了下发现和预期不一样的人,不需要也不会掏钱,因而避免了用户花冤枉钱怒打差评。
但很快,在调试代码时我发现一个合理但又搞笑的事实:App 内购买需要联网。这简直是晴天霹雳,因为我从一开始就下决心:决不允许App在任何情形下弹出联网请求
。为什么?因为这是一个相册搜索应用,它会扫描你的整个相册,没有人知道联网后你会不会将用户的照片上传到地球某处的服务器。我知道可以在产品里解释为什么会弹窗请求联网权限
,但我不想陷入尴尬的自证境地。
我只好将它变成付费产品:用户必须购买,之后从打开 App、构建索引到完成搜索的过程中,只弹出一次相册权限请求
。我知道这么做很蠢——后续的教训也验证了,付费下载会带来大量差评:因为模型太吃算力,许多内存小的机型上构建索引会崩溃、卡顿,在 iPhone X 系列算子支持异常导致搜索结果全黑,这些都会被骂 Ripoff(诈骗);并且,用户根本不会在意不弹出联网请求这件事,一旦出现以上异常,他们就会删 App、打差评,质问我把他的相册偷偷上传到哪去了。
总之,最终我将其定价为 3.99 美元,一次购买、终身使用。
推向市场
我给产品取了名字:Queryable
,意为可查询的,并发了条很中二的动态:我觉得这个 app 可能会改变世界,我对此信心满满,甚至给 Tim Cook 写了一封邮件,希望苹果能收购这个产品(笑)。那时候我已经开始用 ChatGPT 了,可能因为太激动,我忘了替换掉自己的名字,点击发送之后,才看到邮件开头是:"Dear Mr. Cook, My name is [Your Name]"
。
当然最终也没有收到回信。
我又开始雄心勃勃地准备写篇产品介绍文章,反复斟词酌句、试图将它变成我心中 Hacker News 好文章的风格。在 12 月 29 日,App Store 审核通过的当天,我立刻在 Hacker News 提交了我的文章链接,但系统提示账号太新无法提交,我给他们发邮件反馈了这个问题,让朋友用他的账号帮我发帖。
帖子很快沉了,邮件也没收到回信。
我很难过,但由于收到许多用户请求支持中文输入,我来不及悲伤,便立即投入中文模型训练中。得益于分离了 CLIP 中文本模型和图像模型,我只需要找到中英文双语平行语料,训练一个中文文本模型,将其输出结果与英文模型对齐即可,这个过程本质上是蒸馏。
很快,2023 年 1 月 18 日,我做好了中文版,取名寻隐,来源是贾岛古诗《寻隐者不遇》,也暗含从相册中发现隐藏含义的意思。毕竟,我的初次震撼就是搜lonely
时意识到那几张照片原来代表孤独。
上线后,我用中文在少数派写了一篇文章介绍此产品,和英文版不同,除了讲述技术方案外,我还完整记录了心路历程,竟然进了当天的首页,这带来了大量下载,以及 1500 美元的收入。
2 月初,我收到了 Hacker News 编辑的回信,他说我的账户被系统误判为 SPAM,鼓励我重新发帖,说我的文章很符合社区精神(“the article is definitely fine HN material”),他将我的新帖子链接放在候选池(pool):池里的文章会随机进入首页底部,如果用户点赞,排名就会上升,否则再次沉下去。
我发现pool机制很有意思,社区似乎希望在去中心化的机制下,仍然维持黑客精神:
This is our long-running experiment in story re-upping. Moderators and a small number of reviewer users comb the depths of /newest looking for stories that got overlooked but which the community might find interesting. Those go into a second-chance pool from which stories are randomly selected and lobbed onto the bottom part of the front page. This guarantees them a few minutes of attention. If they don’t interest the community they soon fall off, but if they do, they get upvoted and stay on the front page.
这是我们长期进行的故事重演实验。版主和少数审阅者用户会深入寻找被忽视、但社区用户可能会感兴趣的故事。这些故事会进入第二次机会池,该池中的故事会被随机选择并放置到首页的底部。这保证了它们获得了几分钟的注意力。如果社区用户不感兴趣,它们很快就会下沉消失,但如果社区感兴趣,它们就会得到支持(upvote)并留在首页。
https://news.ycombinator.com/item?id=11662380
当晚 7 点,我的帖子冲到了 Hacker News 首页第二名。
那晚,我抱着手机每 10 秒刷新一次,兴奋感从十二点躺下持续到凌晨三点,我一直在回复帖子下的讨论、反馈 bug 的邮件。有人教我用 LSH 来提高搜索速度,有人给出如何在不联网的前提下,将照片经纬度映射到城市,有人讨论 iPhone X 上运行失败的原因。
这种感觉好像和产品有多少下载、赚多少钱无关:你创造了一个东西,得到了一大群同行的赞美、兴奋地讨论、给它出主意,这是人生少有的经历,一次就很知足了。
其中有一条评论引起了我的注意:
我阅读了作者的开发日志,发现我们像地球上随机的两个脑子产生相同想法的人,我甚至在 Testflight 试用了他还未上线的产品,有种莫名惺惺相惜的感觉。
Hacker News 是世界的公告牌
当晚,我很兴奋地睡着了,为自己产品被同行喜欢而激动,事实证明我远远低估了 Hacker News 的影响力:两天时间,Queryable 几乎横扫了欧洲所有国家的工具榜#1,美国 #2(仅次于小火箭),总收入是 2800 美元。之后的几天,我醒来第一件事就是看 Gmail,德国、法国、西班牙、美国,各个国家都有:有反馈 bug 的,有德国杂志社想报道的,有法国 iOS 社区的,有油管博主测评的。我的推特也会因为有人转发 Hacker News 热榜而不断收到通知。
甚至一位在 Apple Photos 组工作的朋友告诉我,他们组里也知道 Queryable。
以上这些都迫使我意识到某种世界性:Hacker News 并非只属于美国,它像世界中心区域一块虚拟的公告牌,每个作品在上面短暂停留,但总有来自各个国家、无数双眼睛盯着。 这个产品其实只支持英语,但不妨碍它在欧洲几乎所有国家付费工具榜#1。他们好像会天然接受一个只能用英语的产品,在美国行得通的产品往往欧洲人也能接受。
热度很快降了下来,随即而来的是很多恶评。
简单来说,Hacker News 的用户质量极高,我没看到任何令我感到不适的评论。但经过各种网站、YouTube 和社区的二次传播后,不那么友好的用户就浮出水面了。主要攻击的有两点:
- 害怕我会窃取他的相册隐私。
- 我是中国开发者。
在他们看来,第 2 点让第 1 点的情况变得更糟了。在 Hacker News 接二连三的余热结束以后,这个产品在欧美销量迅速变得惨淡,每天个位数的下载,几十块的收入。
在我的想象中,改变世界的东西是一骑绝尘的,怎么会突然停下了呢?我陷入了巨大的怀疑和悲观。
免费 & 开源
所幸国内的差评、果壳等公众号对寻隐的自来水曝光,这让我从 1 月份开始,每个月可以获得 1 万元左右的收入,并且因为模型运行在手机端,也就没有服务器成本。
从 4 月份起,没有任何流量曝光、不做任何更新的情形下,平均每月大概可以获得 3000 元的收入。
但是!我仍然觉得这是一个很有用的产品,只是我没办法让很多人知道。我进行过一次限时免费,当天下载量超过过往日均的 100 倍,我想,与其维持这样每月 3000 块的收入,可能阻止了 99%的人发现这个产品,不如让所有人都可以使用它,于是我决定让它一直免费。
既然免费了,源代码好像就并不是什么机密了,我在思考要不要把源代码放出来。最终,在 2023 年 7 月 10 日,我在 V2EX 发布的一条帖子决定免费&开源。很多人一听到开源就觉得莫名高大上,但对我而言,开源动机很简单:
- 我曾经收到过大量来自国内外开发者的邮件,询问 Queryable/寻隐的技术细节,我懒得解释,开源能让他们直接从源码中了解模型导出加载、计算加速、存储排序等细节。
- 开源能打消很多人对于相册隐私的顾虑。
- 我不擅长 Swift 开发,并且我认为这个产品中,我最想做的部分已经完成了,因此一直抗拒更新。但我会持续收到用户的邮件,希望增加多选删除、左右滑、Mac/NAS/Android 支持等等,我想借助社区的力量,让有能力的开发者打磨出更好的产品。
开源后,的确有人受此启发做出了 Android 版(#12)和Mac 版。
开源后,这个项目上了 Github Trending,我也因此白嫖了一年 Github Copilot,开心。
有关抄袭
谈抄袭之前,我想定义一下什么叫抄袭:
抄袭是指未经授权或未给予适当信用的情况下,直接或间接地使用他人的作品、创意、或内容,将其作为自己的作品或创意发表。
抄袭其实在开源前就出现了。有人做了 Android 版,发布在 Google Play,名字和产品介绍完全照搬 Queryable,我很生气,但这其实需要同时掌握机器学习和 iOS 开发,开源前我只遇到这样一个。
但开源之后,抄袭、套壳的人就多了。因为项目是 MIT 开源,所以即使套壳换图标,然后重新上架 App Store,我虽然有点无语,但也不会说什么,这是我见过最多的形式,开发者全是中文名。
我其实很支持在原项目的基础上,加上用户希望的功能,比如多选删除、按日期/地点筛选照片,UI 比我做得好看的产品——这也是我开源的初衷,但它们中也有让我感觉不爽的地方,比如在社区宣传产品的时候,不仅没有致谢,被用户提问与寻隐有什么不同时,还要踩一脚:我比寻隐多了 xx。
比较恶劣的是,用 Queryable 名字套壳上架,比如下面这个,收费模式是免费+广告。我很担心用户误以为这是 Queryable 的 Android 版,后续出事了找我麻烦。
我最开始会伤心,正如一位 v2er 在评论区预言得那样:肯定会有人编译后上架市场的,开源是好事情,但是我不希望看到你看到李鬼后伤心。但虱子多了不痒,后来也就慢慢看淡了。
重新变为付费
重新变成付费是在 2023 年 11 月份,除了生存压力增加之外,我发现:
开源并不能帮助我的产品变得更好。我原先希望借助开源+免费,让专业的移动开发者贡献代码,帮助寻隐/Queryable 打磨得更好,但事实就是,我看到一个一个新的套壳产品出现、宣传自己,交互和功能做得很精美,但它们从不会提交 PR。我的产品原地踏步,甚至因为免费的缘故,用户抱怨的邮件比过去更多。
每当用户发邮件向我提反馈/bug/建议时,我的第一反应是不耐烦(内心:免费给你用就不错了,还挑三拣四),我发现这种想法导致产品越来越落后,直到有天被淘汰。
可一旦收费,我就突然变得很心平气和了,面对用户的意见、产品反馈的第一反应是感激而不是厌烦,这会倒逼我不得不花费心血优化产品,最终让所有曾经付费的用户用上打磨更好的产品,而不是疏于维护过几年死掉。
我就这样不紧不慢、偶尔抽空更新产品,但其实只是修复 bug 以及提升模型效果,功能上值得做的很少:例如很多人希望可以搜人脸——这会引入人脸识别模型让 app 更慢,所以没有加。
尾声
Apple 在今年的 WWDC 终于宣布:iOS 18 即将支持相册语义搜索了,这比国内的厂商慢许多。不过,虽然我在 beta 版本还无法体验,但有理由相信苹果会做得比寻隐/Queryable 好,毕竟,它禁了第三方 App 跳转到系统相册。
我也没有闲着:上周,调研最新 paper并 重新设计、训练了中文文本模型,App 体积从原来的 232M 降低到 159M,索引速度翻倍,准确率更高,训练过程花了 3 天, 70 美元。
最近,终于将订阅了一年的 GPT-4 切换成了 Claude 3.5 Sonnet,它写代码能力过于逆天,之前靠 GPT-4 搞不定的多选删除,拖了一年半后,终于在上周开发完成并上线了。
从想法诞生、产品上线到现在快两年了,它陪伴我经历了人生的跌宕起伏、见证了好几家咖啡店的倒闭。我也陪它经历了诞生、高峰和低潮,并没有像最早幻想的那样赚到钱(100 万人下载每人给我 10 块钱我就…),生活依旧继续,我还是挺喜欢这个平淡的结尾。
俱往矣,迫不及待开始下一个让我废寝忘食的 idea、下一次流放到真空中。