一个卖米、木薯粉、Indomie方便面和鸡蛋的小摊主,一半老主顾都不付全款。Emeka今天拿两箱Indomie,说周五把剩下的钱带来。谁欠多少,记在一个练习本上、记在她和自己的WhatsApp聊天里,或者干脆记在脑子里。周六一忙,顾客在排队,她就跳过几笔不记。一周后,没人说得清Emeka到底付没付那第二笔。
![]()
那个本子,就是她漏钱的地方。
这是Hacktoberfest开源AI挑战赛第二周"副业"赛道的参赛作品,作者把它叫做SabiBook——一本你能对着说话的销售与欠款账本,面向尼日利亚做赊账生意的小商贩。
用法很直接:按住一个大按钮,用皮金语或英语说一句话——"我卖给Emeka两箱Indomie,两万,他付了一万五,剩下的明天带来。"几秒后屏幕上弹出一张草稿卡:销售、Emeka、2箱Indomie、总额₦20,000、已付₦15,000、还欠₦5,000。每个字段都能改。点"存入我的账本",Emeka就出现在欠款人页面上,名字旁边挂着₦5,000。到了该收钱的时候,SabiBook起草一条简短的礼貌提醒,直接打开WhatsApp。
此外还有按天分组的流水账、用语音或点金额记录的付款、以及任何已存条目的收据链接。它是一个PWA,可以装到手机主屏上。
谁会掏钱?有十到一百个赊账客户的小商贩。一个月只要追回一笔被遗忘的欠款,一笔小额奈拉订阅费就比省下的钱便宜。做副业的人也一样——比如一个顺手向同事卖香水的人,想知道这事到底赚不赚钱,又不想打开电子表格。托管版本才是生意所在。
说清楚一点:SabiBook还没有部署,也没有用户,所有东西都跑在作者自己的机器上。
两个开源模型,一个不碰算术的账本
AI部分由两个开放权重模型承担。Whisper large v3 turbo负责语音,由Speaches提供服务,在faster-whisper之上套了一个OpenAI风格的转写接口。Ollama上的Gemma 4 E4B读取转写文本,填进一个JSON结构:条目类型、客户、商品、总额、已付、以及这事发生在几天前。提醒文案也由Gemma写。
应用是Next.js,后端用Convex。一条语音的流程是这样的:
- 手机把音频上传到Convex,后台动作把它发给Speaches。商贩保存过的客户名会作为Whisper的提示词一起传过去,所以"Chiamaka"回来时就是她存的那个拼法。
- 转写文本带着同一批名字交给Gemma,这样它会复用Mama Ngozi,而不是再建一个。Gemma返回JSON。如果服务器不支持结构化输出,代码会退回到在提示词里索要JSON。
- Zod按结构校验JSON。
- 纯TypeScript把数字和实际说出口的内容对一遍。
- 草稿出现在屏幕上。在她点保存之前,什么都不会进账本。
第四步是作者最在意的部分。一个会在账本里猜数字的模型,比没有应用更糟,所以Gemma不做任何算术:余额由代码算,balance = total - paid。每一笔金额都必须被听到过——代码会把转写里所有数字抓出来,不管是说出来的"四万五"、简写的"45k"还是写出来的"₦45,000"。如果Gemma返回的金额不在其中,也不是它们的乘积或和,这个字段就会被标上"我没听到这个"。
省略单位是被允许的。商贩会说"四万五,她付了三万五",意思是35,000。代价是这种情况下检查抓不出10和10,000之间的混淆,所以草稿卡是最后一道防线。商品必须能加得起来,加不起来草稿会说明。赊账销售必须有名字——没有名字的欠款收不回来。不知道的就留空:如果她从没说过付了多少,这个字段就是null,保存按钮会告诉她原因。日期同理,Gemma返回daysAgo,代码用手机本地日期把它变成具体日期。
40句测试,5个漏网案例
作者按商贩说话的方式写了40个测试句:25句英语、10句皮金语、5句混了约鲁巴、豪萨或伊博语词汇。有些是故意写难的。评测脚本对每个字段单独打分。按语言分,英语84.0%(21/25),皮金语100.0%(10/10),混合语80.0%(4/5)。中位延迟2506毫秒,p90是10002毫秒。
五个案例没通过。其中一个让作者最担心:商贩列了价值80,000的商品,然后说"总共六万"。Gemma把总额和已付都改成了₦80,000,于是"商品加不起来"的标记根本没触发——因为80,000是听到过的金额之和,数字落地检查放它过去了。另一个案例里,Chidi为一箱₦12,000的Peak牛奶付了₦15,000,Gemma把已付封顶在₦12,000,多付标记没触发,该找给他的₦3,000消失了。作者认为,这两个问题的修复大概应该放在代码里:当总额是被说出来的,就拿它和模型给的总额比一比。
局限也列得明白:只测了Whisper large v3 turbo;约鲁巴语、豪萨语和伊博语还是beta;语音准确率评测没跑,仓库里有工具但没有数字可引用;一句话只生成一条记录,欠款按客户追踪,不按单笔销售追踪。
为什么开放创新重要?商贩的账本是私密的,它写着谁拖欠、周五店里有多少现金。用开放权重,这些数据可以留在商贩自己选的地方——Gemma、Whisper、Speaches、Ollama和Convex后端全跑在一台机器上,合作社可以把它跑在一台便宜服务器上,客户名单永远不出那个盒子。换模型是一行代码,评测能吃一个模型列表,所以可以在同样的40个案例上比较候选模型再决定换不换。成本也是自己的:一个忙碌的商贩一天能记很多笔销售,而一箱鸡蛋的利润很薄,每句话的硬件和电费由自己承担,没有哪家厂商的调价能改变这一点。
作者不认为闭源API解析不了"他付了一万五"。这个应用需要的是把记录搬离第三方服务器,以及一个自己定的按句成本,开放权重是同时拿到这两样最简单的办法。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.