基于OpenAI的自动记账工具:从一句话到结构化账目

发布时间:2026/10/17 10:19:21
基于OpenAI的自动记账工具:从一句话到结构化账目 简介这是一份面向Python开发者与财务自动化爱好者的智能记账工具源码包基于OpenAI的自然语言处理能力解决账单、发票等财务文档的自动识别与录入问题适合具备一定Python基础、希望实践AI应用的中级学习者。资源共51个文件以36个py源码为核心辅以yaml、yml配置、json与ini参数文件、makefile构建脚本及pylintrc代码规范文件压缩包约37KB结构轻量便于快速上手。项目围绕数据获取、预处理、信息抽取、结构化、整合验证与报告可视化六个环节展开涵盖邮件与PDF解析、OpenAI接口调用、Notion数据对接及日志与错误处理等模块并配有测试用例与提示词配置。目前已有238人学习下载读者可借此掌握从财务文档解析到结构化入库的完整链路理解API调用策略、敏感信息加密与模型优化思路并参考其目录组织方式搭建自己的自动化记账方案。1. 自动记账这件事卡住你的从来不是记账本身记账这件事很多人不是不想做是坚持不下来。手动记账的流程是消费完掏出手机、打开 App、选分类、填金额、写备注一套动作下来十几秒一天三五次一周就放弃了。真正的问题不在意志力在于「记录」这个动作的成本太高。基于 OpenAI 实现的自动记账工具思路就是把这条链路反过来你只管把消费信息丢进去解析、分类、入库全部交给模型和脚本。它适合两类人——一类是有点 Python 基础、想给自己搭一套私人记账流水线的开发者另一类是手里已经有一堆支付宝、微信导出的 CSV 账单但懒得一条条归类的人。核心逻辑其实很朴素用大模型把「非结构化的一句话消费描述」翻译成「结构化的 JSON 记录」再落库。难点不在调用 API而在怎么让模型稳定输出、怎么处理它偶尔的胡言乱语、以及怎么把这件事做成一个你愿意天天用的东西。2. 为什么用大模型做解析而不是正则和规则引擎2.1 规则引擎的天花板在哪传统自动记账方案基本靠正则匹配加关键词分类。比如看到「星巴克」就归到「餐饮」看到「滴滴」就归到「交通」。这套东西在消费场景固定的时候能用但真实账单的文本是脏的。举几个我实际处理过的例子「楼下那家兰州拉面 18」「给娃买了个乐高 299」「充话费 100」「同事结婚随礼 600」。这些描述里没有商户名、没有标准分类词正则根本写不出来。更麻烦的是同一个商户在不同场景下分类可能不同比如「超市」买的是日用品还是食材规则引擎没法判断上下文。大模型的优势在于它能理解语义。「给娃买了个乐高」这句话模型能推断出这是「玩具」或者「子女支出」金额是 299甚至能猜出这是非日常消费。这种模糊推理能力是规则引擎给不了的。但代价是模型输出不稳定同样的输入两次调用可能给你两种格式这是后面要重点解决的问题。2.2 最小可跑通的解析链路先说整体架构一条消费记录从输入到入库要经过四步原始文本输入 → 提示词组装 → 模型调用 → JSON 解析与校验 → 写库。我一般会把模型调用封装成一个独立函数输入是自然语言输出是固定 schema 的字典。import json from openai import OpenAI client OpenAI(api_key你的key, base_url你的endpoint) # 定义输出 schema强制模型按这个结构返回 SYSTEM_PROMPT 你是一个记账解析助手。用户会给你一句消费描述 你需要提取以下字段并以 JSON 返回不要输出任何其他内容 { amount: 数字消费金额, category: 字符串从[餐饮,交通,购物,居住,娱乐,医疗,教育,人情,其他]中选一个, merchant: 字符串商户或场景描述没有就填未知, date: 字符串格式YYYY-MM-DD没提到就填, note: 字符串原始描述 } def parse_expense(text: str) - dict: resp client.chat.completions.create( modelgpt-4o-mini, # 解析任务用轻量模型足够 messages[ {role: system, content: SYSTEM_PROMPT}, {role: user, content: text}, ], temperature0, # 关键温度设0减少随机性 response_format{type: json_object}, # 强制JSON输出 ) raw resp.choices[0].message.content return json.loads(raw)这段代码有三个关键点。第一temperature0是必须的记账解析要的是确定性不是创造力温度调高会让模型在分类上反复横跳。第二response_format{type: json_object}是 OpenAI 提供的结构化输出能力能大幅降低模型返回「好的我来帮你解析{...}」这种带废话的概率但注意它只保证是合法 JSON不保证字段符合你的 schema。第三模型选择上解析这种任务用轻量模型就够成本能压到很低一条记录大概几厘钱没必要上大模型。2.3 字段设计和分类体系怎么定分类体系是整个工具的地基定错了后面全要返工。我的建议是分类不要超过 10 个粒度太细模型容易分错你自己统计的时候也看不出规律。上面 schema 里那 9 个分类是我用过比较稳的餐饮、交通、购物、居住、娱乐、医疗、教育、人情、其他。其中「人情」这一类专门收红包、随礼、请客很多人会漏掉但这块支出占比不小。金额字段要特别注意模型有时候会把「18 块」解析成字符串 18有时候解析成数字 18。解决办法是在提示词里明确写「数字」并且在代码里做一次强制转换兜底。日期字段同理用户说「昨天」「上周五」的时候模型需要结合当前日期推算所以提示词里最好把今天的日期也塞进去否则模型不知道「昨天」是哪天。提示分类体系一旦上线就别频繁改改一次意味着历史数据要重新归类成本很高。前期宁可多留「其他」这个兜底类。3. 把一句话变成一条账完整落地流程3.1 环境准备和依赖安装先把环境搭起来。Python 版本建议 3.9 以上主要是为了类型注解和字典合并语法用着舒服。依赖就三个openai 官方 SDK、sqlite3标准库自带不用装、还有可选的 pandas 用来做后续统计。python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install openai pandas数据库我选 SQLite理由是零配置、单文件、够用。个人记账的数据量一年撑死几千条SQLite 完全扛得住没必要上 MySQL 或者 PostgreSQL 给自己找麻烦。建表语句很简单核心就是一张流水表。import sqlite3 def init_db(pathexpenses.db): conn sqlite3.connect(path) conn.execute( CREATE TABLE IF NOT EXISTS records ( id INTEGER PRIMARY KEY AUTOINCREMENT, amount REAL NOT NULL, category TEXT NOT NULL, merchant TEXT, date TEXT, note TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ) conn.commit() return connamount用 REAL 存浮点数个人记账精度到分就够了不用纠结 decimal。created_at记录入库时间和消费日期date区分开后面排查问题的时候有用。3.2 解析结果的校验和兜底模型输出不能直接信必须过一道校验。最常见的三种翻车金额解析成负数或者 0、分类不在你定义的枚举里、日期格式乱七八糟。校验函数要能识别这些情况并给出降级方案。VALID_CATEGORIES {餐饮,交通,购物,居住,娱乐,医疗,教育,人情,其他} def validate(record: dict, raw_text: str) - dict: # 金额兜底转不成数字就置0并标记 try: amt float(record.get(amount, 0)) if amt 0: amt 0.0 except (TypeError, ValueError): amt 0.0 # 分类兜底不在枚举里就归到其他 cat record.get(category, 其他) if cat not in VALID_CATEGORIES: cat 其他 return { amount: amt, category: cat, merchant: record.get(merchant) or 未知, date: record.get(date) or , note: raw_text, }这个校验函数看着简单但它是整个工具稳定性的关键。没有它模型偶尔抽风返回一个amount: 十八块你的入库代码就直接抛异常了。有了它最坏情况是这条记录金额记成 0你事后能通过note字段找到原始描述手动修正不至于丢数据。3.3 批量导入历史账单真正体现效率的是批量处理。支付宝和微信都能导出 CSV 账单字段格式各家不一样但核心就是「时间、金额、描述」三列。写个脚本读 CSV逐条丢给解析函数批量入库。import csv def import_csv(csv_path: str, conn): with open(csv_path, encodingutf-8) as f: reader csv.DictReader(f) for row in reader: # 不同平台列名不同这里按需映射 text f{row.get(交易时间,)} {row.get(交易对方,)} {row.get(商品说明,)} {row.get(金额,)} try: parsed parse_expense(text) clean validate(parsed, text) conn.execute( INSERT INTO records (amount,category,merchant,date,note) VALUES (?,?,?,?,?), (clean[amount], clean[category], clean[merchant], clean[date], clean[note]), ) except Exception as e: print(f跳过一条{text}原因{e}) conn.commit()批量导入要注意两点。一是加异常捕获单条失败不能中断整个流程否则几百条账单跑到一半崩了很崩溃。二是控制调用频率几百条记录连续请求可能触发限流稳妥做法是每处理 20 条 sleep 一秒。这个脚本跑一次你过去半年的账单就全归类好了这是手动记账永远做不到的效率。4. 避坑与常见问题排查4.1 模型返回的 JSON 解析失败现象json.loads报错提示Expecting value或者返回内容里带 markdown 代码块标记。原因通常是模型没遵守json_object格式或者你的提示词里没有明确禁止输出解释性文字。解决办法是双保险提示词里写死「只返回 JSON」代码里加一层清洗把可能的json 和去掉再解析。如果还不行就退化成用正则从返回文本里抠出第一个{...}块。4.2 分类结果前后不一致现象同一句「买咖啡」今天归到「餐饮」明天归到「购物」。原因是温度没设 0或者提示词里分类定义有歧义。解决温度锁死 0并且在提示词里给每个分类加一句简短说明比如「餐饮正餐、外卖、饮品、零食」。定义越清晰模型越稳定。4.3 金额识别错误现象「满100减20」被解析成 100 或者 20实际支付 80。原因模型对优惠场景理解不到位。解决在提示词里加一条规则「如果描述中有优惠、满减、折扣amount 填实际支付金额」。如果账单 CSV 里本身就有实付金额列优先用那一列别让模型去猜。4.4 日期推算错误现象「昨天吃饭」被解析成空日期或者错误日期。原因模型不知道今天是几号。解决在 system prompt 里动态注入当前日期格式写清楚「今天是 2025-01-15请据此推算相对日期」。这个坑很隐蔽不注入日期的话模型只能瞎猜。4.5 批量导入触发限流现象跑到一半报 429 错误。原因请求太密集。解决加 sleep 节流或者用指数退避重试。更省事的做法是把批量任务拆成小批每次处理几十条跑完手动再跑下一批反正历史账单是一次性工作。5. 让这套工具真正好用的两个进阶技巧第一个技巧是加一层「记忆」。模型每次解析都是无状态的它不知道你上个月把「楼下便利店」归到了「购物」。解决办法是维护一张商户到分类的映射表解析前先查表命中就直接用历史分类没命中再调模型调完把结果写回表。这样用一段时间后你的高频商户基本都能命中缓存既省钱又稳定。实现上就是一张merchant_map表解析函数开头查一下几行代码的事。第二个技巧是做一个极简的输入入口。工具再好输入麻烦照样没人用。最省事的方案是用一个命令行脚本python add.py 午饭 25直接入库稍微讲究点可以用 Flask 起个本地页面手机浏览器存个书签点开输入框一贴就完事。我自己的习惯是配合手机的快捷指令把选中的文本直接 POST 到本地服务全程不用打开任何 App。验证这套工具是否靠谱有个简单办法拿你过去一个月的真实账单跑一遍然后人工抽查 20 条看分类准确率。如果准确率低于 85%说明提示词或者分类体系要调高于 90% 就可以放心日常用了。我踩过最大的坑是一开始分类定太细搞了二十多个类结果模型天天分错后来砍到 9 个类准确率立刻上来了。分类这件事少即是多。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询