“午饭 32 元”是很适合大模型理解的一句话,但“这笔钱最终应该如何写入账本”不应该由大模型自由发挥。
这是我在开发 LarkLedger(飞账) 时逐渐明确的一条边界:AI 负责把非结构化输入翻译成候选业务动作,确定性的应用层负责校验、授权和落库。
从一句话到业务动作
对用户来说,记账入口可以很自然:文字、语音或账单图片。系统内部则需要金额、币种、分类、时间、账户和付款人等明确字段。
大模型适合完成第一步转换,但输出必须经过结构校验和业务规则。账户是否属于当前用户、家庭账本成员能否看到某个私人账户、转账是否被错误计入支出,这些都不能依赖模型“理解正确”。
用户输入
→ AI 解析候选动作
→ Schema 校验
→ 权限与业务规则
→ 确定性账本服务
→ PostgreSQL
风险越高,确认越明确
简单明确的单笔文字可以直接入账。图片、语音、批量操作或疑似重复则先生成待确认单,用户确认后才写入账本。
待确认单会冻结解析得到的结构化动作。确认时不会再次调用 AI,避免同一张小票在两次推理中得到不同金额或分类。
这种设计不是为了让交互变慢,而是让风险与摩擦匹配:低风险操作保持顺畅,高风险操作留下明确的人工确认点。
幂等是产品能力
聊天平台会重试事件,网络请求也可能超时。如果服务只是“收到请求就插入一行”,重复记账迟早会发生。
LarkLedger 对飞书事件使用事件 ID 认领,对 Client API 和 Web 写请求使用 Idempotency-Key。同一个键和相同请求可以安全重放;同一个键配上不同内容则返回冲突。幂等不仅是后端实现细节,它直接决定用户是否敢相信账本。
AI 不参与财务计算
预算使用率、账户余额、目标进度和周期账单都由确定性规则计算。AI 可以把结果改写成更自然的说明,但不访问数据库参与计算,也不能自动操作资金。
例如“本月支出比近三个月平均值更高”应该来自可重复计算的数据,而不是模型浏览几条交易之后给出的印象。
多入口,共用一个核心
飞书机器人、Web 页面和结构化 Client API 都只是适配器。它们共享同一个应用服务和领域结果,避免每增加一个入口就复制一套记账逻辑。
项目目前使用 FastAPI、React、PostgreSQL 和 Docker Compose 自托管。它仍在持续开发,也不会把“有幂等和重试”夸大成绝对不会重复或丢失;但把 AI 限制在合适的边界内,是让这类工具逐步变得可信的起点。
评论
评论 API 尚未配置。