[控场AI]
· 7 分钟阅读· 3,755 字

Strukku:开源权重模型驱动的自由职业者收据记账工具

Strukku:开源权重模型驱动的自由职业者收据记账工具

Strukku 用 Gemma 开源权重视觉模型,把杂乱收据拍照变成可校验、可导出的账本数据。

Strukku 是一个面向自由职业者和小商户的收据记账工具,在 Hacktoberfest 开源 AI 挑战赛中提交。它针对通用 OCR 和记账 SaaS 忽视的长尾场景——印尼语/英语混用、手写便条、网约车收据——用 Gemma 开源权重视觉模型完成提取,经 Zod 校验后写入 Supabase,并支持 CSV 导出。AI 调用被隔离在单一 adapter 模块,更换模型只需改一行代码。作者选择开源权重的三大理由是零调用成本、无供应商锁定、财务数据可自托管。项目代码完成且构建通过,但尚未用真实收据验证准确率,作者如实说明了这一边界。

从鞋盒到CSV:收据记账的自动化突围

自由职业者和小店主每月都要面对一堆琐碎的收据——要么付费请会计手动录入,要么自己花一整个晚上敲键盘。Strukku 试图用一行代码流程解决这个问题:拍张照,剩余交给 AI。

这是一个基于 Gemma 开源权重视觉模型构建的收据记账工具,在 Hacktoberfest 开源 AI 挑战赛第二周中提交。它并非又一个泛用 OCR 包装,而是精准瞄准了一个被主流工具长期忽视的场景。

rss source: Strukku: Receipt Bookkeeping for Freelancers, Built on an Open-Weight Model

Gemma 是 Google 于 2024 年起陆续发布的一系列开源权重视觉-语言模型,涵盖 2B、7B、9B、27B 等参数规模,采用与 Gemini 系列同源的技术路线,但以开放权重形式发布,允许商用与本地部署。与纯文本 LLM 不同,Gemma 的多模态版本(如 Gemma 3 系列)可以直接接受图像输入并输出文本,因此适合收据识别这类"看图说话"任务。所谓"开源权重",指的是模型参数文件可公开下载、可自托管推理,这与只开放 API 的闭源模型(如 GPT-4、Claude)有本质区别。文章提到的 google/gemma-4-31b-it:free 是通过 OpenRouter 提供的免费推理端点,it 表示 instruction-tuned(指令微调版),适合按提示词完成结构化提取任务。

它到底在解决什么

通用 OCR 和记账 SaaS 几乎都针对整洁、印刷体、英语优先的收据训练。但真实世界里大量自由职业者和小商户面对的是:印尼小食摊(warung)的手写便条、Gojek/Grab 的打车收据、市场摊贩潦草的总价。这些非正式的、多语言混用的收据,正是主流工具的盲区。

Strukku 的提示词直接点明了这一目标:收据可能是印尼语、英语或两者混用,可能是印刷体、皱巴巴的手写便条或网约车收据。模型输出经 Zod 校验后才写入数据库——若模型不支持严格结构化输出,还有纯 JSON 回退解析,不信任任何未经校验的模型输出。

Zod 是一个 TypeScript 优先的运行时数据校验库。它允许开发者用声明式 schema 描述数据的期望结构(例如"金额必须是数字、日期必须是 ISO 字符串、商家名称为非空字符串"),然后在运行时对模型返回的 JSON 逐字段校验,若不匹配则抛出可捕获的错误。在 LLM 应用中,Zod 常被用作"输出契约":提示词要求模型按某 schema 输出,再用同一 schema 校验,能有效拦截模型幻觉或格式漂移。文章提到"若模型不支持严格结构化输出,还有纯 JSON 回退解析",指的是一些模型支持原生 JSON Schema 约束(structured output),可直接保证输出符合格式;而另一些只靠提示词约束,此时就需要回退到手动解析 JSON 字符串并用 Zod 校验,两条路径共同保证未经校验的模型输出不会污染数据库。

技术路径:一条清晰的流水线

技术栈上,这个项目选择了 TanStack 生态的完整方案:TanStack Start、TypeScript、TanStack Router、TanStack Query、TanStack AI(@tanstack/ai + @tanstack/ai-openrouter),后端使用 Supabase 提供 Postgres 与存储,模型调用经 OpenRouter 路由到 Gemma 免费层,样式用 Tailwind CSS。

处理流程相当直接:收据照片 → base64 编码 → 存入 Supabase Storage → 调用视觉模型 → 结构化 JSON 输出 → Zod 校验 → 写入 receipts 表 → 生成账本并支持 CSV 导出。

有意思的是,整个 AI 调用被隔离在单一模块 src/server/ai/adapter.ts 中。这意味着更换模型或供应商只需改一行代码,而不是重构整个系统。对于快速迭代的独立开发者而言,这种架构上的克制是务实之选。

TanStack 是一套以类型安全和框架无关著称的前端/全栈工具集,最初以 TanStack Query(数据获取与缓存)和 TanStack Router(类型安全路由)闻名。文章提到的 TanStack Start 是其较新的全栈框架,提供 SSR、服务端函数与路由的一体化方案;@tanstack/ai 与 @tanstack/ai-openrouter 则是面向 AI 调用的封装,把模型请求抽象成类似 Query 的调用模式。选择这一生态的动机在于:Router、Query、AI 调用共享同一套类型系统与缓存语义,无需在多个库之间做状态同步。对于独立开发者,这意味着更少的胶水代码和更可预测的调试路径,但也意味着押注一个相对年轻的框架。

为什么坚持开源权重模型

作者给出了三个具体理由,都用开源权重模型(Google 的 Gemma,通过 OpenRouter 免费层调用 google/gemma-4-31b-it:free)而非闭源 API。

成本是首要因素。 整个商业逻辑建立在“比请会计便宜”之上。AI 环节的调用成本为零,是小额月费模式能成立的前提。如果模型调用本身产生持续费用,价格优势就被侵蚀。

没有锁定风险。 如果后续发现另一个开源权重模型对印尼手写收据识别更准,切换只是 adapter 里改一行。相比之下,切换闭源供应商意味着重新谈判 API 合同。

财务数据隐私。 收据本质是财务记录。坚持开源权重意味着未来可以将模型迁到自托管,而不是永久租用某家闭源供应商的推理服务。对于一个处理他人资金数据的工具,这是负责任的选择。

值得一提的是,作者特意选择了具体的 Gemma 端点而非通用的 openrouter/free 路由——后者可能在请求时静默路由到非开源模型,让“开源”承诺落空。这种细节上的诚实值得肯定。

OpenRouter 是一个聚合多家模型供应商的推理路由服务,开发者用统一的 API 格式即可访问 OpenAI、Anthropic、Google、Meta 等不同厂商的模型,并按调用量付费或使用部分免费额度。文章特别提到作者没有使用 openrouter/free 这个通用免费路由,原因是该路由可能在请求时动态选择任意免费模型,包括非开源权重的模型,从而使"使用开源权重"的承诺落空。指定具体的 Gemma 端点,等于把"用哪个模型"这一决定权牢牢握在自己手里,也让成本、隐私和可替换性三方面的论证成立。这一细节对任何依赖第三方路由的 AI 应用都有参考价值:默认路由的便利性往往以牺牲可预期性为代价。

坦诚的现状:代码完成,验证待续

作者没有声称一个尚未验证的演示。项目在挑战赛窗口内完成,类型检查和生产构建均通过,但尚未用真实拍摄的收据、在实时 Supabase + OpenRouter 环境下完整跑通。

换句话说,代码结构已经就绪,防御性编程到位,但真实场景下的提取准确率仍是未验证的。作者明确表示,下一步是把工具交给真正有一鞋盒收据的自由职业者,看它在具体纸张堆里哪里会出错。

AI 披露方面,作者承认在架构、实现和这篇总结中大量使用了 Claude Code 辅助,但审阅了代码和所有声明,只陈述了实际验证过的内容。

对独立开发者的启示

Strukku 的价值或许不在于它已经多完善,而在于它展示了一种务实的 AI 应用构建思路:窄场景 + 开源权重 + 防御性集成 + 诚实交付。

它没有试图做一个通用记账工具,而是专门优化一个被忽视的长尾场景。它没有追逐最新最大的闭源模型,而是选择成本可控、可替换、可自托管的开源权重方案。它没有把模型输出直接写库,而是用 Zod 严格校验。它也没有在验证之前就发布演示链接,而是如实说明了边界。

代码托管在 github.com/fatik07/strukku,README 中包含 Supabase 的 SQL 设置说明,采用 MIT 式许可。如果你想验证这个思路是否成立,门槛并不高:克隆仓库,接上免费的 Supabase 项目和 OpenRouter 密钥,然后喂给它一叠真实收据——这正是作者自己计划做的下一步。

对于处理敏感数据的 AI 应用,开源权重模型提供的不只是成本优势,更是一种架构上的自由:你可以在不重建系统的情况下更换模型,也可以在需要时为隐私而自托管。Strukku 是这个逻辑的一个具体注脚。

#Strukku#开源权重模型#收据记账#Gemma#自由职业者工具#AI记账#OpenRouter#OCR收据识别
分享:

相关推荐