1. 一个会计转行做 AI 工具,为什么偏偏盯上了"会计师"这个岗位
第一次看到"前会计师用 AI 打造 Tabby,要让会计师消失"这个说法,我的反应是:又是一个标题党。但把这件事拆开看,它其实踩中了两个非常真实的行业痛点——重复性财务工作的自动化,以及AI Agent 在垂直专业领域的落地。Tabby 这个名字在开发者圈子里其实有另一层含义,指的是那个很流行的终端工具,但这里说的 Tabby 是另一个方向的东西:一个面向财务、会计场景的 AI 助手/Agent 产品。名字撞车不影响理解,反而说明"Tabby"这个词在技术圈有记忆点。
先说清楚这个项目到底在做什么。核心逻辑是:会计日常工作中,有大量动作是高度结构化、可被规则和模型共同处理的——发票信息提取、银行流水对账、科目归类、凭证草稿生成、报表勾稽检查、税务口径的初步校验。这些活儿不是不需要专业判断,而是专业判断只占 20%,剩下 80% 是搬运、比对、录入、核对。Tabby 这类工具要吃掉的就是这 80%。它不是一个"替代会计师"的魔法盒子,而是一个把会计师从机械劳动里拽出来的 AI Agent。
适合谁看这篇内容?三类人。第一类是做财务、会计、审计一线工作,想搞清楚 AI 到底能帮自己干什么、会不会把自己干掉的人;第二类是想做垂直领域 AI 应用开发的技术人,想知道财务场景的 Agent 该怎么设计、坑在哪里;第三类是对 AI Agent 落地感兴趣的产品和创业者,想看看一个"前从业者做本行业工具"的路径长什么样。我会把技术选型、场景拆解、实操步骤、踩坑经验都摊开讲,尽量做到你看完能自己动手复现一个最小可用版本。
需要提前说明的是,下面涉及的具体实现细节,有一部分是基于当前主流 AI 应用开发实践做的合理补全,因为原始信息里没有给出完整的技术栈。我会明确标注哪些是常见做法、哪些是我的经验判断,你按自己实际情况调整就行。
2. 拆解 Tabby 这类财务 AI Agent 的核心设计思路
2.1 为什么是"Agent"而不是"聊天机器人"
很多人一听 AI 做财务,第一反应是"不就是接个大模型,把发票丢进去让它读吗"。这个理解停留在 2023 年。单纯的对话式大模型有几个致命问题:它记不住你的账套结构,它不知道你公司的科目体系,它没法主动去调你的银行流水接口,它更不会在发现一笔异常时自己跑去核对合同。Agent 和聊天机器人的本质区别在于:Agent 有目标、有工具、有记忆、能多步执行。
放到财务场景里,一个对账 Agent 的完整链路是这样的:读取银行流水 → 读取系统内记账凭证 → 按金额、日期、摘要做模糊匹配 → 对匹配不上的生成差异清单 → 调用规则引擎判断差异类型 → 输出对账报告和待人工确认项。这一串动作里,大模型负责的是"理解摘要语义""判断两笔记录是否可能是同一笔""生成人类可读的说明",而精确的金额比对、日期计算这些必须交给确定性代码。把大模型当大脑,把代码当手脚,这才是 Agent 的正确姿势。
Tabby 这类产品的设计哲学,我判断大概率是"LLM 做语义层,规则和数据库做事实层"。为什么这么设计?因为财务数据对准确性要求是 100%,大模型有幻觉,你让它直接算账迟早出事。但大模型的语义理解能力又是传统规则引擎给不了的——比如"支付宝-某某科技"和"某某科技有限公司-服务费"这两条记录,规则引擎很难判断它们是同一笔,但大模型一眼就能看出关联。这就是分工的价值。
2.2 场景选型的取舍:先啃哪块骨头
财务工作链条很长,从原始凭证到最终报表,中间环节几十个。一个初创产品不可能全做,必须选切入点。从 Tabby 的定位看,它优先啃的应该是高频、结构化、容错率相对可控的环节。我按落地难度和商业价值做了个排序,你可以参考:
| 场景 | 结构化程度 | 容错要求 | 落地难度 | 商业价值 |
|---|---|---|---|---|
| 发票/票据信息提取 | 高 | 高 | 低 | 中 |
| 银行流水对账 | 高 | 极高 | 中 | 高 |
| 科目自动归类 | 中 | 高 | 中 | 高 |
| 凭证草稿生成 | 中 | 中 | 中 | 高 |
| 报表勾稽检查 | 高 | 极高 | 低 | 中 |
| 税务口径初筛 | 低 | 极高 | 高 | 高 |
发票提取是最容易起步的,因为 OCR 加结构化输出已经比较成熟,大模型在这里主要做字段纠错和语义补全。对账和科目归类是价值最高的,因为它们最耗时。税务口径最难,因为涉及政策理解和责任边界,AI 只能做提示不能做决策。Tabby 如果聪明,应该从发票和对账切入,用高频场景建立信任,再往纵深走。
2.3 "让会计师消失"这句话该怎么正确理解
标题里"让会计师消失"是传播话术,但背后有个真实的行业趋势:基础核算岗位在萎缩,财务分析和业务财务岗位在扩张。这不是 AI 造成的,是自动化和信息化二十年一直在做的事,AI 只是加速了。一个只会做凭证录入、发票认证、简单对账的会计,确实危险;但一个懂业务、能做预算、能看穿数据背后经营问题的财务,AI 反而是他的放大器。
所以 Tabby 这类工具的真实价值,不是消灭岗位,而是把会计的时间从"操作"转移到"判断"。我见过太多财务同事,月底加班到凌晨,做的全是复制粘贴和核对。如果这些能自动化,他们就有时间去分析为什么这个月毛利率掉了三个点,这才是财务该干的事。理解这一点,你才不会对这类工具产生无谓的恐惧,也不会对它抱有不切实际的幻想。
3. 核心技术点逐个拆:从票据识别到 Agent 编排
3.1 票据与文档的结构化提取
财务场景的输入五花八门:增值税发票、银行回单、合同、报销单、Excel 台账、PDF 报表。要把它们变成 AI 能处理的数据,第一步是结构化提取。这里的技术栈通常是"OCR + 版面分析 + 大模型字段抽取"三层。
OCR 负责把图片变成文字,但财务票据的难点在于版面复杂——发票有固定模板,但各家开票系统略有差异;银行回单格式更是千奇百怪。所以纯 OCR 不够,需要版面分析模型先识别出"这是金额区""这是日期区""这是购销方区",再针对性提取。现在很多方案直接用多模态大模型一步到位,把票据图片丢进去,让它输出 JSON。实测下来,对于标准增值税发票,多模态大模型准确率能到 95% 以上;对于手写报销单或模糊扫描件,会掉到 80% 左右,必须加人工复核环节。
字段抽取的提示词设计很关键。我常用的结构是这样的:
extract_prompt = """ 你是一个财务票据信息提取助手。请从以下票据内容中提取字段,严格按 JSON 输出。 字段要求: - invoice_code: 发票代码,字符串,找不到填 null - invoice_number: 发票号码,字符串 - date: 开票日期,格式 YYYY-MM-DD - amount: 价税合计金额,数字,保留两位小数 - tax_amount: 税额,数字 - seller_name: 销售方名称 - buyer_name: 购买方名称 - items: 货物或服务明细,数组,每项含 name/quantity/unit_price/amount 注意: 1. 金额只保留数字,不要带货币符号和千分位 2. 如果同一字段出现多次,以票面主区域为准 3. 无法确定的字段填 null,不要编造 """注意:提示词里一定要明确"不要编造",否则大模型在字段模糊时会自己脑补,这在财务场景是灾难。另外金额字段务必在代码层再做一次正则校验和数值范围检查,不能全信模型输出。
3.2 对账逻辑:模糊匹配 + 规则兜底
对账是财务最耗时的工作之一。传统做法是 Excel 里用 VLOOKUP 硬匹配,匹配不上的手工找。AI 对账的思路是多级匹配策略:第一级精确匹配(金额+日期完全一致),第二级模糊匹配(金额一致、日期允许±3天、摘要语义相似),第三级人工介入。
语义相似度这块,可以用向量嵌入来做。把银行流水的摘要和记账凭证的摘要都转成向量,算余弦相似度,超过阈值就认为是潜在匹配。但这里有个坑:纯语义匹配会误判。比如"支付货款"和"收到货款"语义很近,但方向完全相反。所以必须叠加金额符号、借贷方向这些硬约束。
我建议的对账流程是这样的:
- 数据清洗:统一日期格式、金额精度、去除空格和特殊字符
- 精确匹配:金额相等且日期相等,直接配对
- 金额匹配 + 日期容差:金额相等,日期差在设定范围内,按摘要相似度排序
- 一对多/多对一匹配:一笔流水对应多笔凭证,或反之,用金额组合求和判断
- 剩余项输出差异报告,标注可能原因(时间性差异、未达账项、记账错误)
每一步的匹配结果都要留痕,方便回溯。对账最怕的是"悄悄匹配错了",比匹配不上还危险。所以系统设计上,宁可多报差异让人工确认,也不要自作主张。
3.3 科目自动归类的实现路径
科目归类是会计的专业活,但其中也有大量规律。比如"办公用品采购"通常进"管理费用-办公费","差旅费报销"进"管理费用-差旅费"。AI 做这件事有两条路:一是基于历史凭证的相似度检索,找到过去类似业务用的科目,推荐给用户;二是基于规则的分类模型,用摘要文本训练一个分类器。
实践中效果最好的是两者结合:先用检索找到 Top-K 相似历史凭证,把它们的科目作为候选,再用大模型结合业务上下文做最终判断。为什么检索优先?因为企业自己的历史数据是最贴合它科目体系的训练集,比通用模型靠谱得多。一家制造业企业和一家互联网公司,同样的"服务费"可能进完全不同的科目,通用模型学不到这种企业特异性。
这里有个实操心得:冷启动阶段,让用户先手工标注 200-500 条历史凭证作为种子数据,检索效果会好很多。别指望零样本就能准,财务科目体系太个性化了。另外,归类结果一定要给置信度,低置信度的强制人工确认,高置信度的可以批量采纳但保留撤销入口。
3.4 Agent 编排:把上面这些串起来
单个功能做好不难,难的是让它们协同工作。这就是 Agent 编排层要解决的。一个财务 Agent 的典型架构是:意图识别 → 任务规划 → 工具调用 → 结果整合 → 人工确认。
用户说"帮我把这个月的账对一下",Agent 需要:识别出这是对账任务 → 规划出"取流水、取凭证、执行匹配、生成报告"的步骤 → 依次调用对应工具 → 把结果整理成报告 → 把不确定项列出来让用户确认。这个过程中,大模型负责意图理解和任务规划,具体执行交给封装好的函数。
工具调用的设计要点是每个工具职责单一、输入输出明确。比如get_bank_transactions(month)只负责取流水,match_transactions(transactions, vouchers)只负责匹配。不要让一个工具干太多事,否则出错难定位。工具的描述要写清楚,因为大模型是靠描述来决定调哪个工具的。
tools = [ { "name": "get_bank_transactions", "description": "获取指定月份的银行流水记录", "parameters": {"month": "格式 YYYY-MM,字符串"} }, { "name": "get_vouchers", "description": "获取指定月份的记账凭证", "parameters": {"month": "格式 YYYY-MM,字符串"} }, { "name": "match_transactions", "description": "对银行流水和记账凭证执行匹配,返回匹配结果和差异清单", "parameters": {"transactions": "流水列表", "vouchers": "凭证列表"} } ]提示:工具数量别一次给太多,超过 10 个模型就容易选错。可以按场景分组,对账场景只挂对账相关的工具。另外每个工具都要有超时和异常处理,财务系统接口经常不稳定。
4. 从零搭一个最小可用财务 Agent 的实操过程
4.1 环境准备与技术选型
假设你要自己复现一个类似 Tabby 的最小版本,我建议的技术栈是这样的:后端用 Python(生态最全),大模型用支持函数调用的主流模型(本地部署或 API 都行),向量库用轻量的方案(数据量不大时甚至可以用内存计算),前端先用 Streamlit 快速验证,别一上来就搞复杂的前后端分离。
为什么这么选?因为财务 AI 应用的核心难点在业务逻辑和准确性,不在工程架构。你花两周搭个微服务架构,不如花两天把对账逻辑跑通。等验证了价值再重构不迟。我见过太多项目死在过度设计上。
依赖安装大致是这些:
pip install openai pandas numpy scikit-learn streamlit pip install pdfplumber python-docx openpyxl pip install sentence-transformers faiss-cpu如果你要处理票据图片,再加 OCR 相关的库或者直接调多模态模型接口。数据库先用 SQLite 或直接读 Excel,别急着上 PostgreSQL。
4.2 数据准备与清洗
这一步最枯燥但最重要。你需要准备三类数据:银行流水(CSV 或 Excel)、记账凭证(从财务系统导出)、历史科目对照(用于训练归类)。清洗的要点:
- 日期统一成
YYYY-MM-DD,注意 Excel 日期序列号的坑 - 金额统一成两位小数的浮点数,注意千分位和货币符号
- 摘要去除多余空格、全角半角统一
- 借贷方向明确标识,别用正负号混着来
我踩过的一个坑:银行流水的金额正负号和会计借贷方向不是一回事。银行流水里支出是负数,但会计上可能是借方也可能是贷方,取决于科目。所以对账时不能简单用金额符号匹配,要结合科目性质判断。这个坑让我第一次对账结果错得离谱,后来加了科目方向映射才解决。
4.3 核心对账模块的实现
下面是一个简化版的对账核心逻辑,你可以直接参考:
import pandas as pd from datetime import timedelta def match_transactions(transactions, vouchers, date_tolerance=3): """ transactions: DataFrame, 含 date, amount, summary vouchers: DataFrame, 含 date, amount, summary, subject 返回: matched列表, unmatched_transactions, unmatched_vouchers """ matched = [] used_vouchers = set() # 第一级:精确匹配 for idx, t in transactions.iterrows(): candidates = vouchers[ (vouchers['amount'] == t['amount']) & (vouchers['date'] == t['date']) & (~vouchers.index.isin(used_vouchers)) ] if len(candidates) == 1: matched.append((idx, candidates.index[0], 'exact')) used_vouchers.add(candidates.index[0]) # 第二级:金额匹配 + 日期容差 + 语义相似 for idx, t in transactions.iterrows(): if any(m[0] == idx for m in matched): continue candidates = vouchers[ (vouchers['amount'] == t['amount']) & (~vouchers.index.isin(used_vouchers)) & (abs((vouchers['date'] - t['date']).dt.days) <= date_tolerance) ] if len(candidates) >= 1: # 按摘要相似度排序,取最高的 best = candidates.iloc[0] matched.append((idx, best.name, 'fuzzy')) used_vouchers.add(best.name) matched_tx = {m[0] for m in matched} unmatched_transactions = transactions[~transactions.index.isin(matched_tx)] unmatched_vouchers = vouchers[~vouchers.index.isin(used_vouchers)] return matched, unmatched_transactions, unmatched_vouchers这段代码是骨架,实际用的时候要加语义相似度计算、一对多匹配、异常处理。但你可以看到核心思路:分级匹配,先严后松,每级都留痕。跑通这个骨架,你就能看到对账自动化的雏形了。
4.4 接入大模型做语义增强
上面的代码里,摘要相似度还是空的。这里用大模型或嵌入模型补上:
from sentence_transformers import SentenceTransformer import numpy as np model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2') def semantic_similarity(text1, text2): emb = model.encode([text1, text2]) cos = np.dot(emb[0], emb[1]) / (np.linalg.norm(emb[0]) * np.linalg.norm(emb[1])) return float(cos)把相似度阈值设在 0.75 左右比较稳妥,低于这个值就交给人工。阈值别设太低,宁可多报差异。我试过 0.6,误匹配明显增多,反而增加了核对成本。
如果你要用大模型做更复杂的判断,比如"这两笔记录是否可能是同一笔业务",可以这样设计提示词:
judge_prompt = """ 判断以下两条财务记录是否可能是同一笔业务: 记录A(银行流水):日期{date_a},金额{amount_a},摘要{summary_a} 记录B(记账凭证):日期{date_b},金额{amount_b},摘要{summary_b} 请回答:是/否/不确定,并给出简短理由。 注意:金额必须一致才可能是同一笔;日期差异超过7天需谨慎。 """4.5 用 Streamlit 快速搭个界面
验证阶段别搞复杂前端,Streamlit 足够:
import streamlit as st st.title("财务对账助手") uploaded_tx = st.file_uploader("上传银行流水", type=['xlsx', 'csv']) uploaded_vc = st.file_uploader("上传记账凭证", type=['xlsx', 'csv']) if uploaded_tx and uploaded_vc: tx = pd.read_excel(uploaded_tx) vc = pd.read_excel(uploaded_vc) if st.button("开始对账"): matched, un_tx, un_vc = match_transactions(tx, vc) st.write(f"匹配成功 {len(matched)} 笔") st.write("未匹配流水:") st.dataframe(un_tx) st.write("未匹配凭证:") st.dataframe(un_vc)这个界面丑但能用,重点是让你快速看到效果。等逻辑验证没问题了,再考虑做成正式产品。
5. 实操中踩过的坑与常见问题排查
5.1 大模型幻觉在财务场景的致命性
这是最大的坑,没有之一。大模型在提取金额时,如果票面模糊,它可能"猜"一个看起来合理的数字。在别的场景这可能无所谓,在财务场景这是事故。我的应对策略是三重校验:模型输出后,用正则从原始文本里再提取一遍金额,两者比对;再用数值范围检查(比如单张发票金额不会超过某个上限);最后对低置信度的强制人工确认。
还有一个隐蔽的幻觉:科目推荐时编造不存在的科目。企业科目表是固定的,模型可能推荐一个听起来合理但系统里没有的科目。解决办法是把科目表作为约束传给模型,让它只能从给定列表里选。
5.2 数据格式的千奇百怪
财务数据来自不同系统,格式混乱程度超出想象。日期有2024/1/5、2024-01-05、20240105、Excel 序列号45296各种形态;金额有带千分位的、带货币符号的、用括号表示负数的。清洗环节要花整个项目 30% 以上的时间,别低估。
我整理了一个常见格式对照表:
| 问题类型 | 常见表现 | 处理方式 |
|---|---|---|
| 日期格式 | 多种分隔符、Excel序列号 | 统一转 datetime,序列号用 origin 转换 |
| 金额格式 | 千分位、货币符号、括号负数 | 正则去除非数字字符,括号转负号 |
| 编码问题 | 中文乱码 | 统一 UTF-8,读文件时指定编码 |
| 合并单元格 | Excel 表头跨行 | 用 openpyxl 处理或要求用户规范模板 |
| 空值 | 空白、NULL、N/A | 统一成 None,后续判断处理 |
5.3 对账匹配的边界情况
一对多匹配是最容易出错的。比如一笔银行流水 10000 元,对应三笔凭证 3000、3000、4000。简单匹配匹配不上,需要做子集求和。但子集求和是 NP 问题,数据量大时不能暴力枚举。我的做法是限制组合数量(比如最多 3 笔组合),并且只在金额差异较小时触发。实际业务中,一对多超过 3 笔的情况很少。
另一个边界是跨月对账。月底的流水可能下月初才记账,严格按月份对账会漏掉。所以对账时要允许前后各一个月的凭证参与匹配,但要在报告里标注时间性差异。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方向 |
|---|---|---|
| 匹配率异常低 | 数据未清洗、格式不一致 | 检查日期金额格式是否统一 |
| 匹配率异常高 | 阈值太松、误匹配 | 提高相似度阈值,检查是否金额符号问题 |
| 模型输出字段缺失 | 提示词不明确、票面模糊 | 完善提示词,加字段校验 |
| 科目推荐不准 | 种子数据太少 | 增加历史凭证标注量 |
| 处理速度慢 | 逐条调用模型 | 批量处理,加缓存 |
| 金额对不上 | 精度问题 | 统一用 Decimal 或整数分处理 |
注意:金额计算千万别用浮点数直接比较,
0.1 + 0.2 != 0.3这个坑在财务场景会要命。统一转成整数分,或者用 Decimal 类型。
5.5 关于"让会计师消失"的冷思考
做这类工具久了,我反而觉得"消失"是个伪命题。工具越强,对使用者的判断力要求越高。AI 能帮你把 1000 笔流水对完,但差异分析、异常判断、和业务部门沟通为什么这笔账对不上,还是得人来。AI 替代的是操作,不是责任。财务报表是要签字负责的,这个责任 AI 担不了。
所以如果你是一线财务,别慌,去学怎么用这些工具,把自己从操作里解放出来。如果你是开发者,别想着做个全自动的"无人财务",那既不现实也不合规,做"人机协作"的工具才是正道。Tabby 这类产品的天花板,不是替代会计师,而是让一个会计师能干过去三个人的活,且干得更准。
6. 这类财务 AI 工具后续还能怎么扩展
把对账和票据提取跑通之后,往上游可以接合同管理——从合同里提取付款条款、账期、金额,自动生成付款计划;往下游可以接报表分析——基于结构化数据自动生成管理报表和异常预警。再往深走,可以接预算控制——在费用发生前就做合规校验和预算占用检查。
技术上,下一步值得投入的是多 Agent 协作。对账 Agent、归类 Agent、报表 Agent 各司其职,由一个调度 Agent 协调。这样每个 Agent 可以独立优化,整体能力又能组合。但别一上来就搞多 Agent,单 Agent 跑不顺的时候,多 Agent 只会让问题更难定位。
数据层面,积累足够多的历史处理记录后,可以做企业专属的微调或检索增强,让工具越来越懂这家公司的业务习惯。这是通用工具做不到的护城河。我个人的经验是,一个财务 AI 工具在同一个企业跑满三个月,准确率能比刚上线时提升 15 到 20 个百分点,靠的就是这种数据沉淀。
最后分享一个我自己的判断:财务 AI 的竞争,短期看模型能力,中期看场景理解,长期看数据积累和信任建立。前会计师做 Tabby 这类产品,最大的优势不是技术,是他真的知道会计每天在烦什么。这个"知道",比任何大模型都值钱。