Web/移动个人 AI CFO
Source: Dev.to
FinTrack
技术性高层次概述,讲解如何构建一个结合传统 CRUD 与 AI 功能的个人理财应用,以及我为何将服务拆分。
问题
我想打造一个个人理财应用,它不仅仅是记录交易。我希望它能够 理解 你的财务状况:
- 用自然语言回答问题,
- 自动对支出进行分类,且
- 甚至支持语音输入,就像真正的个人助理(向 Finny 提问)。
挑战是什么?大多数 AI 工作都是用 Python 完成的,而典型的网页后端则使用 Node.js。如何在不产生混乱的情况下兼顾两者的优势?
注意: 有不止一种解决方案。正确的选择取决于并发量、业务规模、成本以及你的应用运行的具体环境。
高级架构
I chose a dual‑backend architecture: one service for the core application, another dedicated entirely to AI.

| 组件 | 技术栈 | 职责 |
|---|---|---|
| 前端 | React + TypeScript + Vite | UI、路由、状态,以及单一的 API 抽象层 |
| ExpressoTS API | Node.js(ExpressoTS 框架)+ PostgreSQL | 所有非 AI 操作:交易、账户、目标、预算、认证 |
| Python AI 服务 | Python(FastAPI/Flask)+ OpenRouter(LLM 提供商)+ 向量存储(例如 Pinecone) | RAG 聊天、交易分类、语音转录解析、文档提取 |
为什么要拆分后端?
-
保持 API 密钥在服务器端
AI 提供商需要保密密钥。Python 服务保存这些凭证并代理所有 AI 请求,这样浏览器永远不会直接与提供商通信。 -
Python 在 AI 方面的优势
分类、嵌入和 RAG 流水线天然适合 Python 成熟的生态系统(NumPy、pandas、OpenAI SDK 等)。在 Node 中复现这些功能会增加自定义代码和维护负担。 -
独立的扩展与并发
CRUD 流量和 AI 流量的负载特性不同。通过两个服务我们可以分别独立扩展——聊天使用的峰值不会影响核心事务 API。 -
明确的关注点分离
业务数据与 CRUD 位于 ExpressoTS;AI/ML 位于 Python。这使得新人上手、调试和重构都更加容易。
Source: …
前端结构
该应用遵循清晰的分层模式:
| 层 | 位置 | 责任 |
|---|---|---|
| UI | components/, pages/ | 仅呈现组件 |
| State | contexts/, hooks/ | 全局状态和可复用逻辑 |
| Data | api/ | 所有数据获取和 API 调用 |
| Utils | utils/ | 纯函数,无副作用 |
api/ 文件夹是 后端通信的唯一入口。它抽象了请求是发送到 ExpressoTS 还是 Python 服务,提供 fetchTransactions()、classifyTransactions()、askFinny() 等函数。应用的其他部分无需了解双后端的设置。
Source: …
Python AI 服务:它的功能
1. 用于金融问答的 RAG
用户会提出类似 “我上个月在杂货上的花费是多少?” 或 “我的餐饮预算还剩多少?” 的问题。RAG 服务的工作流程:
- 为用户的问题生成嵌入向量。
- 在向量库中搜索相关的交易、目标和支出上限。
- 将这些上下文注入到 LLM 提示中。
- 返回基于用户真实数据的答案。
交易、类别、目标和预算的嵌入都会被存储。向量搜索返回最相关的数据片段,避免出现数字方面的幻觉。
2. 批量交易分类
当用户上传银行的 CSV 文件时,会出现数十甚至数百条未分类的交易。分类器:
- 使用用户已有的类别层级结构。
- 从过去的分类中学习(例如 “Starbucks” → 咖啡)。
- 返回包含
categoryId和subcategoryId的结构化 JSON。
交易会被批量处理,以保持在 token 限制之内,并采用异步方式提升速度。前端会显示进度,并在完成后刷新列表。
3. 语音输入
用户可以口述一笔交易:“在加油站加油,花了五十美元。” 语音解析器会将其转换为结构化对象:
{
"amount": 50,
"description": "Gas station",
"category": "Transportation",
"subcategory": "Fuel"
}
转录文本会发送到 Python 服务,服务返回一个交易对象,用户可以在保存前进行确认或编辑。
Patterns That Worked
- Context‑Aware AI – RAG 服务从认证令牌中获取
user_id和household_id,将每个查询限定在该用户的数据范围内,防止跨家庭泄漏。 - Rate Limiting & Usage Tiers – AI 调用成本高。我们对每个用户实施限制(例如 X 次聊天查询、Y 次语音会话、Z 次分类),以控制费用并确保公平使用。
- Asynchronous Job Queue – 长时间运行的 AI 任务(批量分类、语音解析)使用工作者系统(如 Celery 或 RQ)排队。前端轮询作业状态,使 UI 保持响应。
- Caching Embeddings – 对经常访问的嵌入(如最近的交易)在 Redis 中缓存,降低向量存储的延迟并降低供应商费用。
- Observability – 结构化日志、OpenTelemetry 跟踪和 Prometheus 指标提供对请求延迟、错误率以及两个服务的 token 使用情况的可视化。
TL;DR
- 将后端拆分为 Node/ExpressoTS 服务,用于快速并发的 CRUD,和 Python 服务用于 AI 重负载工作。
- 将 API 密钥保存在服务器端,利用 Python 的 AI 生态系统,并独立扩展每个服务。
- 干净的前端分层和单一的
api/抽象将双后端的复杂性隐藏在 UI 之上。
结果是一个响应迅速、AI 增强的个人理财应用,能够在不牺牲性能或安全性的前提下处理真实世界的流量。
3. 在适当场景下进行缓存
Stateless questions like “What’s my total income this year?” can be cached. We cache by query + user_id with a short TTL. Conversational threads aren’t cached—they’re too dynamic.
4. 工具调用用于操作
聊天不仅仅是问答。用户可以说 “为午餐添加二十美元”,AI 会触发一个创建交易的工具。
- 我们定义工具模式(
add_transaction、get_balance等)。 - 大语言模型决定何时调用它们。
- Python 服务执行调用并返回结果,供模型进行概括。
我会做得不同的地方
从第一天起就采用双后端拆分。
我曾尝试使用单体架构,随后再拆分。构建过程中期迁移非常痛苦。
尽早统一错误处理。
ExpressoTS 和 Python 返回的错误形态不同。我后来才加入共享的错误格式层——如果一开始就做好会省下很多时间。
更早投入嵌入管道的建设。
RAG 的质量依赖于优秀的嵌入。我们反复试验嵌入内容(完整交易文本 vs. 摘要)以及重新索引的时机。若能更早完成这些工作,聊天体验会更快提升。
还有更多(显然我不能透露所有使用的策略),但这已经是一个不错的起点。 :)
要点
构建一个 AI 驱动的应用并不意味着把所有东西都塞进同一个技术栈,尤其是当你在“随意编码”(要小心)时。将后端拆分——使用 ExpressoTS 处理 CRUD,使用 Python 处理 AI——让我获得了:
- 对 API 密钥和 AI 逻辑的明确所有权
- 为每项任务选择合适的工具
- 独立的扩展性、并发性和部署方式
- 可维护的代码库
如果你正在考虑为已有应用添加 AI,或从一开始就以 AI 为目标进行开发,使用专门的 Python、Rust 或 C++ 服务来处理所有 AI 工作负载是一种可良好扩展的模式。
性能与成本:为什么在起步阶段这很重要
当你在构建第一个产品或自助启动一个副项目时,每一美元都很重要。托管应用和运行 AI 的费用会很快飙升。这种架构在这两个方面都能提供帮助。
并发而不需要过度配置
双后端拆分意味着 CRUD 和 AI 在不同的进程中运行。ExpressoTS API 可以在一台普通实例上处理成千上万的轻量请求(事务、账户获取、身份验证检查),而 Python 服务则异步运行 AI 任务。我们不需要为一台等待 AI 调用而闲置的高配服务器买单——我们为每个服务量身定制规模。一个小型 Node 实例用于 API,另一个小型 Python 实例用于 AI,通常比尝试同时完成两者的单一大型单体更便宜。
降低基础设施成本
通过将 AI 工作负载隔离,我们避免在聊天使用量激增时对整个应用进行扩容。免费层或低成本的 Python 主机可以在早期承担 AI 服务。随着使用量增长,只需对该服务进行扩容。CRUD API 则保持稳定且成本低廉。
从第一天起就具成本效益
我深刻理解到托管必须具备成本效益,尤其是对刚起步的开发者来说。你不需要 Kubernetes 或一整套容器来上线。两个小服务、明确的边界以及能够独立扩展的能力——这是一条在验证产品的同时保持账单低廉的道路。
I’m the developer behind FinTrack, a personal finance app with an AI called Finny as your best advisor. If you’re building something similar, I’d love to hear how you approached it—drop a comment below.