用AI Agent搞定繁琐报销——小白也能懂的"自动填表"自动化方案
用AI Agent搞定繁琐报销——小白也能懂的"自动填表"自动化方案
月底,你打开公司OA系统。
面前是47张发票,有餐饮、有交通、有住宿,还有几张皱皱巴巴的出租车票。你深吸一口气,开始逐张翻看——日期、金额、类目、备注,一行一行手动输入。第23张的时候,你把1,280元打成了12,800元,没注意。三天后财务把单子打回来,备注两个字:金额有误。
你重新打开OA,一切从头再来。
这不是段子,这是中国几千万职场人每个月都在经历的"报销地狱"。有调研数据显示,职场人平均每月花在报销流程上的时间接近3小时——光是填表、对账、上传附件这些纯体力活,就能吃掉你大半个下午。
如果我告诉你,这整件事可以在你泡一杯咖啡的时间里自动完成呢?今天这篇文章,我会手把手带你搭建一个真正能用的AI报销助手:拍照→识别→自动填表→生成报销单,全程不超过3分钟,不需要任何编程基础也能跟着做。
---
一、方案全景图:AI Agent自动报销的底层逻辑
在开始写代码之前,先花两分钟搞清楚这套方案的工作原理。整个流水线只有五个环节:
📷 拍照/截图
↓
🔍 多模态大模型识别发票(OCR + 语义理解)
↓
📋 结构化提取关键字段(JSON输出)
↓
📊 自动写入Excel报销单(openpyxl)
↓
✅ 人工确认 → 一键提交
每个环节用到的工具都很轻量:多模态大模型(比如GPT-4o)负责"看懂"发票,Python脚本负责把各环节串起来,Excel/飞书表格负责最终输出。
很多人第一反应是"直接用OCR不就行了",但传统OCR方案有个致命问题:它只认字,不理解语义。遇到格式稍有变化的发票(比如手写票、境外票、非标准版式),识别率会断崖式下跌,而且你还得自己写规则去解析识别结果。
来看一下两种方案的实际差距:
| 对比维度 | 传统OCR方案 | 大模型方案 | | 识别准确率 | 85-90%(标准发票)| 95%+(含非标准格式)| | 开发成本 | 高(需训练/调参)| 低(写Prompt即可)| | 格式适配难度 | 高(每种格式写规则)| 低(自然语言描述)| | 维护成本 | 高(格式变了要改代码)| 低(改Prompt即可)| | 单张处理费用 | 约0.01-0.05元 | 约0.03元 |结论很清晰:对于报销这种"格式多变、字段语义复杂"的场景,大模型方案在准确率和开发效率上都完胜传统OCR。
---
二、实战搭建:从第一张发票到完整流水线
Step 1:调通API,让大模型"看懂"一张发票
首先安装依赖:
pip install openai openpyxl pillow
然后写第一段核心代码——让大模型识别单张发票:
import base64
import json
from openai import OpenAI
这里我用的是 api.884819.xyz 提供的中转API
一个key能调GPT-4o、Claude、Gemini,对国内用户非常友好
client = OpenAI(
api_key="你的API_KEY",
base_url="https://api.884819.xyz/v1"
)
def encode_image(image_path):
"""将图片转为base64编码"""
with open(image_path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")
普通发票识别Prompt(精调版)
INVOICE_PROMPT = """
你是一个专业的财务票据识别助手。请仔细分析这张发票图片,提取以下字段并以JSON格式返回:
{
"invoice_type": "发票类型(增值税专票/增值税普票/出租车票/火车票/其他)",
"invoice_number": "发票号码",
"invoice_date": "开票日期(格式:YYYY-MM-DD)",
"seller_name": "销售方名称",
"buyer_name": "购买方名称",
"amount_without_tax": "不含税金额(数字,保留两位小数)",
"tax_amount": "税额(数字,保留两位小数,无则填0)",
"total_amount": "价税合计/总金额(数字,保留两位小数)",
"category": "费用类别(餐饮/交通/住宿/办公用品/其他)",
"description": "商品或服务描述(简短概括)",
"confidence": "识别置信度(0-1之间的小数)"
}
注意:
1. 如果某个字段无法识别,填null
2. 所有金额字段只填数字,不含货币符号
3. 如果图片模糊或无法识别,在confidence字段填0.5以下并说明原因
"""
def recognize_invoice(image_path):
"""识别单张发票,返回结构化数据"""
base64_image = encode_image(image_path)
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": INVOICE_PROMPT},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{base64_image}",
"detail": "high"
}
}
]
}
],
response_format={"type": "json_object"},
max_tokens=1000
)
result = json.loads(response.choices[0].message.content)
return result
测试一张发票
result = recognize_invoice("invoice_001.jpg")
print(json.dumps(result, ensure_ascii=False, indent=2))
运行之后,你会看到类似这样的输出:
{
"invoice_type": "增值税普票",
"invoice_number": "12345678",
"invoice_date": "2025-01-15",
"seller_name": "北京某某餐饮有限公司",
"buyer_name": "XX科技有限公司",
"amount_without_tax": "188.68",
"tax_amount": "11.32",
"total_amount": "200.00",
"category": "餐饮",
"description": "工作餐",
"confidence": 0.97
}
第一步完成。大模型不只是"读"出了数字,还自动判断了费用类别——这是传统OCR永远做不到的事情。
---
Step 2:批量处理,一个文件夹的发票全部识别
单张能跑通,接下来批量处理整个文件夹:
import os
import time
from pathlib import Path
def process_invoice_folder(folder_path, output_json="results.json"):
"""批量处理文件夹中的所有发票图片"""
folder = Path(folder_path)
image_files = list(folder.glob(".jpg")) + list(folder.glob(".png"))
results = []
failed = []
print(f"📂 发现 {len(image_files)} 张发票,开始处理...\n")
for i, image_path in enumerate(image_files, 1):
print(f"[{i}/{len(image_files)}] 正在处理: {image_path.name}", end=" ")
try:
data = recognize_invoice(str(image_path))
data["file_name"] = image_path.name
# 置信度低于0.7时标记为需人工复核
if data.get("confidence", 1) < 0.7:
data["need_review"] = True
print(f"⚠️ 置信度低,建议人工复核")
else:
print(f"✅ 成功 | 金额: ¥{data.get('total_amount', 'N/A')}")
results.append(data)
except Exception as e:
print(f"❌ 失败: {e}")
failed.append(str(image_path.name))
# 避免触发API频率限制,每张间隔0.5秒
time.sleep(0.5)
# 保存结果
with open(output_json, "w", encoding="utf-8") as f:
json.dump(results, f, ensure_ascii=False, indent=2)
print(f"\n✨ 处理完成!成功 {len(results)} 张,失败 {len(failed)} 张")
if failed:
print(f"失败文件: {', '.join(failed)}")
return results
运行批量处理
all_results = process_invoice_folder("./invoices/")
---
Step 3:自动填表,生成标准报销Excel
最后一步,把识别结果写入Excel报销单:
import openpyxl
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from datetime import datetime
def generate_expense_report(results, output_file="报销单.xlsx"):
"""根据识别结果生成标准报销Excel"""
wb = openpyxl.Workbook()
ws = wb.active
ws.title = "报销明细"
# 设置表头
headers = ["序号", "文件名", "发票类型", "开票日期", "销售方",
"费用类别", "描述", "金额(元)", "是否需复核"]
header_fill = PatternFill(start_color="366092", end_color="366092", fill_type="solid")
header_font = Font(color="FFFFFF", bold=True, size=11)
for col, header in enumerate(headers, 1):
cell = ws.cell(row=1, column=col, value=header)
cell.fill = header_fill
cell.font = header_font
cell.alignment = Alignment(horizontal="center")
# 填入数据
total_amount = 0
for row_idx, item in enumerate(results, 2):
amount = float(item.get("total_amount") or 0)
total_amount += amount
row_data = [
row_idx - 1,
item.get("file_name", ""),
item.get("invoice_type", ""),
item.get("invoice_date", ""),
item.get("seller_name", ""),
item.get("category", ""),
item.get("description", ""),
amount,
"是" if item.get("need_review") else "否"
]
for col, value in enumerate(row_data, 1):
cell = ws.cell(row=row_idx, column=col, value=value)
cell.alignment = Alignment(horizontal="center")
# 需复核的行标红
if item.get("need_review"):
cell.fill = PatternFill(start_color="FFE0E0", end_color="FFE0E0", fill_type="solid")
# 添加合计行
total_row = len(results) + 2
ws.cell(row=total_row, column=7, value="合计").font = Font(bold=True)
ws.cell(row=total_row, column=8, value=round(total_amount, 2)).font = Font(bold=True, color="CC0000")
# 调整列宽
column_widths = [6, 20, 15, 12, 25, 10, 20, 12, 10]
for col, width in enumerate(column_widths, 1):
ws.column_dimensions[openpyxl.utils.get_column_letter(col)].width = width
wb.save(output_file)
print(f"📊 报销单已生成: {output_file}")
print(f"💰 报销总金额: ¥{round(total_amount, 2)}")
生成报销单
generate_expense_report(all_results)
三段代码,整个流水线就跑通了。
💰 成本核算:按 [api.884819.xyz](https://api.884819.xyz) 当前定价,GPT-4o识别一张发票(含图片token)大约花费0.03元。100张发票=3元。一年下来也就36元——可能还不够你打一次车去财务部。---
三、踩坑指南——我替你交过的"学费"
坑1:发票照片模糊,识别结果一塌糊涂
解法:在Prompt里加兜底逻辑,同时在代码里做置信度校验(上面的批量处理代码已经包含)。拍照时尽量保证光线充足、发票平铺,用手机"文档扫描"模式效果更好。坑2:金额大小写转换出错
import re
def validate_amount(amount_str):
"""校验金额格式,防止大小写混淆导致的错误"""
if amount_str is None:
return 0.0
# 移除所有非数字和小数点的字符
cleaned = re.sub(r'[^\d.]', '', str(amount_str))
try:
value = float(cleaned)
# 金额合理性校验:单张发票超过5万触发警告
if value > 50000:
print(f"⚠️ 金额异常警告: ¥{value},请人工核实")
return round(value, 2)
except ValueError:
return 0.0
坑3:增值税专票字段更多,普票Prompt不够用
专票需要额外提取税率、税号、开户行等字段。解法是根据发票类型切换Prompt模板:
PROMPTS = {
"专票": "...(专票专用Prompt,包含税号、税率等字段)...",
"普票": INVOICE_PROMPT, # 复用上面的Prompt
"出租车票": "...(出租车票专用Prompt)..."
}
坑4:API调用频率限制导致报错
import time
from functools import wraps
def retry_on_failure(max_retries=3, delay=2):
"""自动重试装饰器"""
def decorator(func):
@wraps(func)
def wrapper(args, *kwargs):
for attempt in range(max_retries):
try:
return func(args, *kwargs)
except Exception as e:
if attempt < max_retries - 1:
print(f"第{attempt+1}次失败,{delay}秒后重试...")
time.sleep(delay * (attempt + 1)) # 指数退避
else:
raise e
return wrapper
return decorator
@retry_on_failure(max_retries=3, delay=2)
def recognize_invoice(image_path):
# ... 原来的识别代码 ...
坑5:发票含公司敏感信息,不敢传云端
这是很多人的顾虑,给出两个建议:
1. 本地部署方案:用Ollama跑本地多模态模型(如LLaVA),完全离线处理
2. 脱敏后再传:用PIL对发票图片做局部遮罩,只保留金额、日期等必要字段区域
---
四、举一反三——报销只是开始
搞清楚这套"拍照→识别→结构化→填表"的Agent模式,你会发现它可以平移到几乎所有"重复性信息录入"场景:
- 合同关键条款提取:上传合同PDF,自动提取甲乙方、金额、交付日期、违约条款
- 简历批量筛选:100份简历丢进去,自动按技能标签分类排序
- 体检报告整理:把体检单拍照,自动生成健康数据趋势表
- 银行流水分类:导出流水CSV,自动按消费类别汇总统计
这些场景的代码骨架几乎一模一样,只需要换一个Prompt模板。
如果你想试试不同模型的效果——比如用Claude处理合同(逻辑推理更强)、用Gemini分析体检报告(多模态能力出色)——不需要分别注册三个平台。在 [api.884819.xyz](https://api.884819.xyz) 上切换一下model参数就行,其他代码一行不用改。
---
这套方案的本质,其实是一种思维方式的转变:把大模型当成一个永不疲倦的"信息理解引擎",把Python脚本当成连接各个环节的"胶水"。两者结合,你就拥有了一个可以处理任何重复性认知工作的自动化框架。报销只是最容易被量化的那个切口。真正有趣的,是当你开始用这套框架审视自己工作中所有"重复、低价值、消耗注意力"的环节,然后一个一个地把它们交给AI代劳。
那些省下来的时间,才是你真正的竞争力。
---
🔜 下一篇预告
>
今天我们搞定了"拍照→识别→填表",但这个流程还差最后一公里——你还得手动把Excel上传到OA系统。
>
下一篇,我们来做一个真正闭环的方案:让AI Agent自动登录你的公司OA系统,把报销单直接提交上去。我会用到Browser Use(浏览器自动化)+ 大模型决策的组合技——AI不只是帮你填表,而是帮你"办事"。这是2025年AI Agent最火的落地方向,也是从"自动化工具"进化为"数字员工"的关键一跳。
>
关注我,别错过。
---
本文由8848AI原创,转载请注明出处。