[控场AI]
· 6 分钟阅读· 3,061 字

AI不做数学:我如何构建一个预算App

AI不做数学:我如何构建一个预算App

一名计算机学生用 Flutter 开发预算 App,让纯 Dart 引擎算钱、AI 只负责解释。

Flutter 开发者独自打造了 Android 预算应用 Budget Lover,核心不是记录开销,而是给出每日「安全可花」金额:用账户余额减去账单、订阅、计划付款、储蓄与安全缓冲,再除以距发薪日的天数。作者把全部计算逻辑放进无 Flutter/Firebase 依赖的纯 Dart 引擎层,可毫秒级跑单元测试。AI 只做解释不做算术,用户在提问时,应用先本地算出事实数字,再连同问题交给 Gemini,以此避免模型编造数字。API 密钥通过 Firebase AI Logic 代理,应用内不存密钥,并配合 App Check 限制来源。项目还包含收据扫描、订阅识别、行程预算、月度总结、经验徽章与 15 种语言支持,作者建议把逻辑抽离组件、用模型处理语言而非数字、测试枯燥的日期边界、并准备演示数据。

大多数预算App都在回答同一个问题:我花了多少钱? 但一个计算机科学学生真正想问的是:今天我能花多少,才不会在月底后悔?

为了解决这个问题,他独自开发了 Budget Lover,一个 Android 应用(Flutter + Firebase + Gemini)。这个应用的核心不是记录,而是给出一个数字——每日“安全可花”金额,外加一个可以追问的 AI 顾问。据作者在开发日志中介绍,这个项目目前尚未发布,所有测试均在模拟器上用演示数据完成。

Budget Lover 界面示例

一个数字:安全可花金额

应用的逻辑非常直接:用账户余额,减去所有在下次发薪日前已经“名花有主”的钱。

// 引擎简化逻辑
safe = balance
     - upcomingBills
     - subscriptions
     - plannedPayments
     - savingsContribution
     - safetyBuffer;

dailyAllowance = safe > 0 ? safe / daysUntilPayday : 0;

剩下的钱,才是可以自由支配的部分。再除以距离下次发薪的天数,就得到了每日允许额度。实际版本还会处理月度预算上限、旅行、债务还款,以及从历史记录中自动识别的订阅,但核心形态不变。

作者把这一切放在一个纯 Dart 的“引擎”层中,不引入任何 Flutter 或 Firebase 依赖。这被他称为项目中最正确的决定——引擎可以在毫秒级完成单元测试,而应用中充满了边界情况:月末、发薪日变动、明天到期的账单。

AI 负责解释,代码负责计算

作者想要一个能回答“我能买得起 80 欧元的这个东西吗?”的顾问。但他很清楚,语言模型在算术上并不可靠,而且乐于编造听起来合理的数字。

因此,AI 从不做数学。

当用户提问时,应用首先在本地计算出相关事实:当前安全可花金额、购买后的新数值、新的每日额度、即将到来的账单。只有拿到这些事实后,才会将问题连同数字一起发送给 Gemini,要求它用平实的语言解释结果。

截图中的顾问回答(“新的安全可花金额为 290 欧元,结论:紧张”)正是基于引擎产生的数字。模型的职责是语气和解释,而非会计。一个附带好处是:事实只包含总额和类别名称,模型永远不需要看到单笔交易。

同一个引擎还驱动着一个 “如果……会怎样?”模拟器。它会运行两次计算:一次使用真实数据,一次加入变化(花掉 150 欧元、取消订阅、收入减少),然后展示差异。任何数据都不会被保存。

所谓「概率性模型」,指的是大语言模型在生成回答时,并非从确定的事实库中检索答案,而是按概率分布逐个预测下一个词元。这带来两个直接后果:一是它没有内置的算术引擎,多位数的加减乘除容易出错;二是即使算错,它也会用自信、流畅的语气给出一个看起来合理的数字,也就是常说的「幻觉」。在金融类场景中,这种错误几乎不可接受,因此工程上的通行做法是把模型放进一条严格的数据管道:上游由确定性代码算出唯一正确的事实,下游只让模型负责措辞、语气和解释。Budget Lover 正是这一模式的典型样本,它把「算」和「说」拆成两个互不越界的角色。

不在应用中存放 API 密钥

作者早期犯过一个错误:把 AI 密钥打包在应用里。但 APK 中的任何内容都可以被提取。后来他转向了 Firebase AI Logic,它位于应用和 Gemini 之间,因此应用内完全不包含密钥。结合 App Check,请求只能来自真实应用。

代价也存在:免费层限制很低,所以顾问功能设有每日消息计数器(截图中可以看到“剩余 10 条”),并且作者使用更轻量、更便宜的模型来处理小任务,比如读取收据。

Firebase AI Logic 是 Google 推出的一项服务,它在移动应用与 Gemini 之间充当中介:应用不直接调用 Gemini 的 REST 接口,而是通过 Firebase SDK 发请求,由后端持有并注入真正的 API 密钥。这样做解决了移动端一个长期痛点——任何打包进 APK 或 IPA 的密钥,只要被逆向工具反编译就能提取出来,进而被滥用产生账单。与之配套的 App Check 则负责验证请求确实来自被授权的正版应用,例如通过 Play Integrity、DeviceCheck 或 App Attest 校验设备与应用签名,从而挡掉脚本伪造的调用。二者的组合在成本与安全之间取得平衡,代价是免费额度通常低于直连,因此常需要配合消息计数和模型分级使用。

那些教会他最多的小功能

  • 收据扫描:照片发送给轻量级 Gemini 模型,返回金额、商家和类别。对模型返回结果的解析采用带验证的常规代码,因此错误答案不会污染数据。
  • 订阅管理:定期付款集中展示,并计算年度成本。应用根据名称在手机上自行判断类型(流媒体、音乐、云服务……),从而能发现重叠——比如三个流媒体服务——并告知 AI 类别信息,而不暴露具体名称。
  • 旅行:按行程、按天、按人计算预算,并支持实时货币换算。
  • 月度总结:故事风格的卡片,可导出为 PDF。
  • 经验值与徽章:为良好习惯设置的小奖励。
  • 15 种语言,包括从右到左的阿拉伯语。作者自己写了小型翻译层和布局测试,当翻译文本超出框体时测试会失败。

订阅自动识别之所以可行,是因为现代 Android 和 iOS 的通知系统允许应用读取已授权范围内的通知内容。Budget Lover 并不直接解析金额,而是从通知文本中抽取商家或服务名称,用一个本地的名称到类别的映射表判断类型,例如把「Netflix」「Disney+」归为流媒体,把「Spotify」归为音乐,把「iCloud」归为云服务。映射在设备本地完成,意味着具体的品牌名称不会离开手机,只有「存在三个流媒体订阅」这样的类别聚合信息才会传给模型。这种「本地分类、聚合上报」的思路,是隐私敏感型应用在功能与合规之间常见的折中方案。

给过去的自己的建议

作者总结了四条经验,对于任何在应用中集成 AI 的开发者都有参考价值:

  1. 把逻辑留在组件之外。引擎层在一周内就收回了成本。
  2. 不要让模型做函数能做的事。用模型处理语言,而不是数字。
  3. 测试无聊的部分。项目有超过 50 个测试文件,发现的大多数错误是日期边界情况,而非界面问题。
  4. 演示数据很重要。构建演示账户,以便在不触碰真实数据的情况下截图和测试。

技术栈

Flutter 和 Dart,Provider 管理状态,Firebase Authentication 和 Firestore,Firebase AI Logic 搭配 Gemini,以及 Flutter 的 PDF 和打印包。

这个项目展示了一种务实且安全的 AI 集成思路:让概率性的语言模型处理它擅长的表达,让确定性的代码处理它擅长的计算。对于金融、医疗等对准确性要求高的领域,这种分工尤其值得借鉴。

分享:

相关推荐