Web/移动个人 AI CFO

发布: (2026年2月21日 GMT+8 18:00)
12 分钟阅读
原文: Dev.to

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.

High level arch

组件技术栈职责
前端React + TypeScript + ViteUI、路由、状态,以及单一的 API 抽象层
ExpressoTS APINode.js(ExpressoTS 框架)+ PostgreSQL所有非 AI 操作:交易、账户、目标、预算、认证
Python AI 服务Python(FastAPI/Flask)+ OpenRouter(LLM 提供商)+ 向量存储(例如 Pinecone)RAG 聊天、交易分类、语音转录解析、文档提取

为什么要拆分后端?

  1. 保持 API 密钥在服务器端
    AI 提供商需要保密密钥。Python 服务保存这些凭证并代理所有 AI 请求,这样浏览器永远不会直接与提供商通信。

  2. Python 在 AI 方面的优势
    分类、嵌入和 RAG 流水线天然适合 Python 成熟的生态系统(NumPy、pandas、OpenAI SDK 等)。在 Node 中复现这些功能会增加自定义代码和维护负担。

  3. 独立的扩展与并发
    CRUD 流量和 AI 流量的负载特性不同。通过两个服务我们可以分别独立扩展——聊天使用的峰值不会影响核心事务 API。

  4. 明确的关注点分离
    业务数据与 CRUD 位于 ExpressoTS;AI/ML 位于 Python。这使得新人上手、调试和重构都更加容易。

Source:

前端结构

该应用遵循清晰的分层模式:

位置责任
UIcomponents/, pages/仅呈现组件
Statecontexts/, hooks/全局状态和可复用逻辑
Dataapi/所有数据获取和 API 调用
Utilsutils/纯函数,无副作用

api/ 文件夹是 后端通信的唯一入口。它抽象了请求是发送到 ExpressoTS 还是 Python 服务,提供 fetchTransactions()classifyTransactions()askFinny() 等函数。应用的其他部分无需了解双后端的设置。

Source:

Python AI 服务:它的功能

1. 用于金融问答的 RAG

用户会提出类似 “我上个月在杂货上的花费是多少?”“我的餐饮预算还剩多少?” 的问题。RAG 服务的工作流程:

  1. 为用户的问题生成嵌入向量。
  2. 在向量库中搜索相关的交易、目标和支出上限。
  3. 将这些上下文注入到 LLM 提示中。
  4. 返回基于用户真实数据的答案。

交易、类别、目标和预算的嵌入都会被存储。向量搜索返回最相关的数据片段,避免出现数字方面的幻觉。

2. 批量交易分类

当用户上传银行的 CSV 文件时,会出现数十甚至数百条未分类的交易。分类器:

  • 使用用户已有的类别层级结构。
  • 从过去的分类中学习(例如 “Starbucks” → 咖啡)。
  • 返回包含 categoryIdsubcategoryId 的结构化 JSON。

交易会被批量处理,以保持在 token 限制之内,并采用异步方式提升速度。前端会显示进度,并在完成后刷新列表。

3. 语音输入

用户可以口述一笔交易:“在加油站加油,花了五十美元。” 语音解析器会将其转换为结构化对象:

{
  "amount": 50,
  "description": "Gas station",
  "category": "Transportation",
  "subcategory": "Fuel"
}

转录文本会发送到 Python 服务,服务返回一个交易对象,用户可以在保存前进行确认或编辑。

Patterns That Worked

  1. Context‑Aware AI – RAG 服务从认证令牌中获取 user_idhousehold_id,将每个查询限定在该用户的数据范围内,防止跨家庭泄漏。
  2. Rate Limiting & Usage Tiers – AI 调用成本高。我们对每个用户实施限制(例如 X 次聊天查询、Y 次语音会话、Z 次分类),以控制费用并确保公平使用。
  3. Asynchronous Job Queue – 长时间运行的 AI 任务(批量分类、语音解析)使用工作者系统(如 Celery 或 RQ)排队。前端轮询作业状态,使 UI 保持响应。
  4. Caching Embeddings – 对经常访问的嵌入(如最近的交易)在 Redis 中缓存,降低向量存储的延迟并降低供应商费用。
  5. 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_transactionget_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.

0 浏览
Back to Blog

相关文章

阅读更多 »

Subnetting 详解

什么是 Subnetting?可以把它想象成把一栋大型公寓楼拆分成不同的楼层。每层 subnet 拥有自己的编号主机(hosts),以及建筑……