李博!你最近是不是又在折腾什么奇奇怪怪的开源项目?
哈哈被你发现了。不过这次不是我折腾的,是Simon Willison发的一个新工具,我觉得特别有意思。
Simon Willison?Django那个联合创始人?他不是搞Datasette那套数据工具的吗?
对对对,就是他。这次他发了个叫inaturalist-clumper的小工具,0.1版本。你知道iNaturalist吧?
知道啊,就是那个拍花拍鸟上传上去,然后AI帮你认物种的平台嘛。我同事有个在上面记录了两千多条观察记录的。
对,全球最大的公民科学平台之一,超过2亿条观察记录,40万个物种。这个clumper工具干的事情其实很简单——它把你在iNaturalist上的观察记录按时间和地理位置自动聚类。
等等,聚类是什么意思?就是帮你分组?
你可以这么理解。比如你周六去了趟植物园,拍了十几种植物,这些记录时间上很近、GPS坐标也很近,工具就自动把它们归成一个clump——一次出行。
哦!这不就是帮你自动整理相册嘛,按出行来分组。那它用的什么算法?DBSCAN?
嘿,你居然知道DBSCAN。
得了吧,产品经理也是要看论文的好吗。
哈哈好好好。但其实他没用DBSCAN,用的是更简单的阈值方案。就是设一个时间窗口和距离阈值,满足条件的就归到一组。
这也太朴素了吧?为什么不用更高级的算法?
这恰恰是我觉得这个项目最有意思的地方。你想啊,iNaturalist的数据有个天然特征——你一次出行集中拍,不同出行之间有很明显的时空间隔。
这种数据分布下,简单阈值就够用了。逻辑透明、好调试,用户一看就懂为什么这几条被分到一起。
懂了懂了,就是说场景决定了不需要大炮打蚊子。
对!而且你知道最让我惊讶的是什么吗?他的数据存储方案。
什么方案?
他把聚类结果输出成一个JSON文件,直接扔在GitHub仓库里。没有数据库,没有后端服务,Git就是他的数据库。
真的假的?!就一个JSON文件放GitHub上?那别人怎么用这个数据?
直接用GitHub的raw文件URL就能拿到最新数据啊!每次更新就是一次Git commit,自带完整版本历史,还能diff比较。
等会儿让我想想……这不就是把GitHub当免费CDN用了吗?
没错!而且这种Git-as-a-database模式其实业界有不少人在用。Netlify CMS就是这么干的,Kubernetes的GitOps也是类似思路。
但这有个问题吧,高并发写入怎么办?数据量大了呢?
你们产品经理就是爱操心扩展性。
这叫专业素养好吗!
哈哈,其实你说的没错,这方案确实不适合高频写入和复杂查询。但个人观察记录就几千条,每天最多更新一次,完全够用。
嗯,场景匹配就行。那这工具最终是怎么用的?配合博客自动发布?
对,典型的Jamstack玩法。你设个GitHub Actions定时任务,每天跑一次聚类脚本,JSON文件更新后触发静态网站重新构建,全自动部署。
哦这个我熟!我们组之前也用类似的流程做过文档站点的自动更新。从数据获取到页面上线,全程不用人管。
对,而且你注意到没有,这个工具只管聚类这一件事。获取数据是另一个工具,展示是另一个工具,部署又是另一个。
Unix哲学嘛,每个程序只做好一件事。
就是这个!Simon Willison整个工具生态都是这个思路。他围绕Datasette建了几十个小工具,每个解决一个具体问题,通过SQLite和JSON文件串起来。
我觉得这其实挺值得我们产品经理学习的。很多时候我们总想做一个大而全的东西,但其实小工具组合起来反而更灵活。
而且他还有一点我特别佩服——这个工具是为个人需求开发的,但他在自己的生产环境跑了好几周才发布0.1版本。
Dogfooding嘛。自己先吃自己的狗粮。
对。而且发布出来README写得清清楚楚,有使用示例、有输出样本。他说过一句话我印象特别深——开源不是把代码扔到GitHub上就完了,得让别人能理解、能用、能贡献。
这话说得好。我见过太多开源项目,代码是开了,但README写得跟天书一样,根本没人敢用。
所以你看,一个小工具背后其实藏着很多设计决策。选什么算法、怎么存数据、怎么跟其他工具配合,每一步都有讲究。
嗯,而且把个人兴趣和技术能力通过工具链无缝接起来,这种状态其实挺让人羡慕的。好了,今天又从你这学到东西了,下次请你喝咖啡。
行,记着啊,别又忘了。