
10月的某个周五晚上九点半我还在客户会议室里没走。财务经理把三个Excel表格同时摊开ERP导出的应收账款、银行对账单、销售助理手工维护的开票台账。三份数据里同一笔“客户A回款¥48,600”ERP里记的是“货款-2023-XX-088”银行流水里只有“客户A公司转账”台账里有发票号但付款日期差了两天。“这一笔怎么都对不上我们三个小姑娘从月初对到现在。”他说话时桌上的加班饭已经凉透了。这就是我最熟悉的场景——企业不是缺业务系统而是系统之间根本不说话。每个系统都有自己的录入入口和台账逻辑同一条业务数据要在ERP、CRM、财务系统、Excel表里各录一遍到了月底对账三四个来源的数据格式、口径、时间粒度全不一致人工比对几千行流水不出错才见鬼。当时我给他们做的方案不是上线一个更重的ERP模块也不是花钱买RPA而是一套轻型AI中台——用OCR替代人工录入、用大模型处理非结构化账单、用规则引擎搭配AI做自动对账。这篇文章想把整个设计和部署过程完整写出来包括为什么选型、怎么搭Docker Compose、模型怎么量化、对账引擎怎么设计、哪些坑必须提前知道。适合正在处理“多系统数据割裂、录入重复、对账困难”的中小企业IT人员也适合想低成本落地AI能力的数字化负责人。1. 90%的数字化项目失败不是因为“没上系统”而是“系统在互相制造麻烦”很多企业老板有个朴素认知多买几套软件数据不就全了吗结果恰恰相反。每多一套系统就多一个录入入口数据就在每个系统里以不同格式、不同粒度、不同时间戳被重复存储一遍。这种“数据烟囱”结构下重复录入和对账困难不是偶然出现的bug而是必然结果。1.1 重复录入的根源系统各自为政没有一个共享的数据中枢我调研过不少制造、贸易、连锁零售企业发现录入重复的链条几乎一模一样销售在CRM里录了客户订单录完要再到ERP里补一张销售订单仓库发货后库管要在ERP里录出库单物流部门又要在自己的TMS里再录一遍同样的单号财务收到银行回单要把收款金额、付款方、备注手工敲进财务系统跟ERP里的应收单去匹配。每个人都在“打字”但打的是同一笔业务在不同视角下的投影。没有一套机制把“这笔业务只有一份真实主数据”这件事固化下来重复录入就永远存在。传统做法是上主数据管理平台但那通常是集团级项目实施周期按年算中小企业根本扛不住。轻型AI中台的思路完全不同——它不改变你已有的系统边界而是在系统之上加一个共享的智能数据接入层单据到了中台OCR自动识别、大模型自动抽取关键字段、归一化后生成唯一业务ID再分发到下游系统。录入这件事从“人敲键盘”变成“机器读单据”源头消灭重复。1.2 对账困难的三层原因格式、口径、时效对账之所以比录入更痛苦是因为它同时踩了三层坑格式层银行流水是CSVERP导出是Excel带合并单元格台账可能是PDF打印版。格式不统一Excel的VLOOKUP先趴下一半。口径层一笔回款银行按“收妥入账日”记账销售按“开票日期”登记ERP按“确认收入日”入账。三边时间口径不同光时间匹配就永远对不齐。时效层银行流水按天更新但ERP应收模块月底才关账中间差出十几天当月匹配必然有未达账项。传统对账靠Excel筛选、靠老会计的记忆硬扛。可数据量一旦过千行人眼匹配的准确率就会断崖式下跌。AI中台在这里做的事不是替代财务判断而是把“匹配”这个纯计算活交给规则引擎和大模型把“例外情况”留给财务做最终决策。1.3 “轻型”到底意味着什么不推翻、不重构、半小时止损一听到“中台”很多人第一反应是几十个微服务、一套K8s集群、专人运维。这恰恰背离了中小企业的现实。我做的这套方案从第一天起就定义清楚“轻型”的含义轻在部署一台普通服务器或边缘小主机就能跑Docker Compose编排不引入K8s轻在模型本地部署7B~8B参数的量化大模型OCR用轻量模型不强求A100轻在介入不改变现有业务系统的登录和操作习惯中台只做“数据进来了、字段抽好了、该传哪儿传哪儿”的活轻在交付先解决“单据录入自动对账”这一个高频痛点跑通后再扩展不搞大而全。这个定位很关键它决定了后面整个技术选型。下面具体说。2. 为什么我不买现成RPA也不直接上ERP的智能模块聊方案时客户问过一个问题“市面上RPA不是也能自动录单吗你们跟RPA差在哪”我当时的回答是RPA治标AI中台治本。2.1 RPA录的是“操作路径”AI中台建的是“数据语义”RPA的原理是模拟人点击鼠标、复制粘贴把你手工操作键盘的步骤固化下来。问题在于只要原系统页面改版、按钮位置变了、Excel标题行多了一列RPA直接失灵。而且RPA是“一个流程写一个机器人”你有十个录入场景就要维护十个机器人成本不低。而AI中台的核心是数据语义OCR识别单据后大模型根据字段含义抽取“收款方”“金额”“日期”然后通过一步归一化生成标准JSON。下游系统怎么接收是调API还是写Excel由中台负责适配。系统的页面怎么改、Excel长什么样跟中台无关——中台只认“这张单据表达的钱、时间、业务主体”。一句话总结RPA模仿人手AI中台理解业务。前者抗不了界面变动后者天然抗系统迭代。维度传统RPA方案轻型AI中台核心逻辑模拟鼠标键盘操作OCR大模型抽取字段语义抗界面变化差页面一改流程就断强识别对象是单据内容而非按钮处理非结构化单据基本不行只认文本能读PDF、图片、盖章模糊件对账能力无只做录入自动化规则引擎LLM匹配置信度标记运维成本机器人数量随场景线性增长模型和规则统一维护数据不出内网可以但需额外配置全组件本地化天然满足2.2 ERP厂商的智能模块绑定太深灵活度太低也有人说现在主流ERP都有OCR识票和供应商对账功能了。这个我承认但问题在于ERP的智能模块只服务于自己的数据口径跨系统数据它天生处理不了。你最大的对账矛盾是ERP、银行、销售台账三边对不平而ERP的智能模块只认自己系统里的那一边。它既拉不到银行的流水格式也看不懂别的系统导出的私有表头。本质上ERP厂商做的还是“自己闭环”不是“全局打通”。AI中台站在所有业务系统之上天然是中立角色。每个系统通过接口或文件跟中台交互中台不偏袒任何一方三方数据在中台内部完成归一化和匹配生成的对账结论再回写给需要它的系统。这种“中立数据枢纽”的定位业务系统厂商做不了因为没人愿意把自己的数据地盘让给竞争对手。2.3 自研还是开源拼装我的选择顺序有些团队提过既然这么复杂不如全自研。我坚决反对中小企业全自研大语言模型相关能力理由很现实大模型底座直接选开源权重模型本地化部署Qwen3等不碰训练只做推理RAG知识库和Agent工作流用Dify这类开源平台快速搭而不是自己写全套向量库编排引擎OCR识别用开源的PaddleOCR而不是自己训检测识别模型业务逻辑对账匹配、归一化、异常标记这部分必须自研因为它代表你们企业的个性化业务规则任何平台都给不了现成方案。这个选择顺序的核心逻辑是通用引擎用开源生态轮子业务逻辑写在自己手里。前者让你不用从零造大模型后者让你不被任何厂商绑架。3. 系统架构四个模块各管一段互不越界确认选型后我把整个中台拆成了四个模块边界非常清晰。这里不画标准架构图我用顺序描述的方式讲清楚数据是怎么流起来的。3.1 数据接入层解决“原始数据怎么进来”的问题接入层的核心指标是格式宽容度。现实里你会收到Excel、PDF、扫描件、图片、甚至手写备注的转账回单所以接入层要做三件事文件标准化统一转成图片/PDF后进OCR管线。PaddleOCR做版面分析把表格区域、字段区域切出来优先识别金额、日期、交易对方、摘要这些高危字段。结构化数据接入银行导出的CSV、ERP导出的Excel走另一条路——直接用Python的pandas读入自动嗅探表头映射到统一字段模型。这里最容易遇到的坑是同一个字段在不同文件里叫不同名字“付款方”“客户名称”“对方户名”需要做一个字段别名映射表。API接入对于有开放接口的系统直接对接其OpenAPI定时拉取增量数据省去人工导出上传。接入层输出的产品是一份统一数据模型的JSON记录record_id全局唯一业务ID、source_system来源系统、business_date业务日期、amount金额统一到分、counterparty交易对手归一化名称、raw_content原始单据原文以及confidence识别置信度。3.2 智能处理层OCR LLM RAG的配合关系很多人误以为大模型来了OCR就不需要了。这是完全错误的。在单据识别场景里OCR负责“看清字”大模型负责“看懂话”两者是串联关系第一步PaddleOCR识别单据上的文字和表格结构输出带坐标的文本块第二步把文本块组装成结构化上下文送给本地大模型第三步大模型根据预设的Schema抽取字段。比如付款摘要里写“货款-8月-合同尾款”大模型要能理解这是“业务摘要”并映射到对账备注。这里有个重要的设计取舍为什么不让大模型直接读图而要先用OCR因为目前多模态大模型在中文表格、异形排版、扫描模糊件上的稳定性还不足以支撑生产级对账且推理成本高好几倍。先OCR出文本再让纯文本模型抽取既快又省精度还高。RAG检索增强生成在这个场景的用法是维护一本“企业对账知识手册”。比如客户自己的简称、历史异常账目的处理结论、特定合同编号的规则都做成向量知识库。LLM抽取字段时遇到模糊内容先检索知识库里的历史处理方式再决定字段归属减少瞎猜。实测下来RAG介入后复杂备注的字段抽取准确率能提升一到两个点。3.3 对账引擎层规则是主力AI只做例外判定对账引擎是整产品价值最集中的地方也是我坚持要自己写、不交给通用平台的部分。它的核心是一套多级匹配流水线逻辑分四层硬匹配金额完全一致 交易对手归一化名称相同 业务日期误差在±3天内直接命中。这层跑最快用内存Hash索引完成100万行数据也能秒级处理。模糊匹配金额一致但名称有差异“ABC公司上海分公司”vs“上海ABC分公司”或日期差异超过3天但金额和摘要关键词吻合用编辑距离和simhash做相似度计算算出候选集。LLM辅助判定前面两层都可能出现“一对多”一笔回款对应多张发票或“账目备注异常”的情况。这时候把原单据说明、上下文、历史对账规则送到LLM让它给出“该挂哪一笔应收”的建议和理由。人工复核队列置信度大于等于90%的自动入账60%~89%的进入半自动队列60%以下的人工处理。半自动队列会显示LLM给出的匹配建议和理由财务人员只需点确认或改选。这套设计最关键的理念是AI负责把可能性缩小到1~3个把决策权始终留在人手里。既享受了自动化效率又保住了对账的审计责任感。财务经理不会接受一个“黑盒说能对平”的系统但会接受“系统给我三个候选我点一下就行”。3.4 展示与反馈层让财务愿意用让IT能运维很多AI项目死在最后一步——业务人员不爱用。我的经验是界面上一定给业务人员“掌控感”而不是“黑盒感”。对账看板今日流水、已自动匹配、待复核、异常件数量一屏看清例外原因解释每笔进入待复核的账目展示LLM给出的分析财务能看出“为什么系统没直接配上”反馈按钮如果财务改选了正确匹配这个正确答案要被记录进知识库和规则库形成持续优化闭环运维日志IT这边看得到每条管道识别耗时、模型调用Token数、各环节失败率避免“系统好用但没人知道哪里要调”。4. 本地部署实操一台服务器 Docker Compose 跑通全家下面进入最核心的实操环节。这套中台我部署过的最小配置是一台双路Xeon E5、128G内存、一张RTX 4000 SFF Ada20G显存的二手服务器跑全链路没压力。更低配也试过——不带GPU、纯CPU跑量化模型单笔对账慢一些但也能用。4.1 硬件与资源评估先算清楚你要多少“算力存款”先给一个快速评估公式不用拍脑袋OCR推理大约占 2~4GB 显存PaddleOCR轻量模型7B~8B量化模型的KV Cache 权重在GGUF Q4量化下大概占 4~6GB 显存如果并发对话数多再加 2~4GB如果还要跑Embedding模型RAG用再加 1GB 左右数据库、Dify、Nginx这些常规容器内存10GB足够。所以最低建议是16GB显存 64GB内存的整机可以跑完整产品。如果你手头正好有Jetson Orin比如64GB版本的AGX也完全够——它板载显存统一能跑量化8B模型功耗还低适合放在分支机构或边缘侧。如果纯CPU方案模型建议降到4B量化Qwen3-4B或类似单条对账耗时会到10~30秒适合日流水几千笔的小团队先跑起来。先把业务验证通再换GPU是OK的。4.2 基础编排docker-compose.yml的组成与分工我不推荐一把梭把全家都扔进一个Compose里但中小企业也没必要拆成K8s。折中方案是两个Compose文件分两层管理第一层跑基础设施Nginx入口代理、PostgreSQL业务数据、Redis缓存和队列。第二层跑AI组件Ollama模型服务、DifyRAG和Agent工作流、PaddleOCR API容器、对账引擎自研Python服务。Compose的编排逻辑很简单贴一个关键段落version: 3.8 services: # 入口网关统一路由到前端、API、模型服务 nginx: image: nginx:1.25-alpine ports: - 80:80 - 443:443 volumes: - ./nginx/conf.d:/etc/nginx/conf.d - ./certs:/etc/nginx/certs depends_on: - dify - ocr-api # 自研对账引擎核心业务逻辑所在 reconciliation: build: ./reconciliation container_name: reconciliation-api environment: - DB_HOSTpostgres - REDIS_HOSTredis - OLLAMA_HOSThttp://ollama:11434 - OCR_HOSThttp://ocr-api:8866 depends_on: - postgres - redis - ollama - ocr-api # LLM推理服务OpenAI兼容接口 ollama: image: ollama/ollama:latest volumes: - ./models:/root/.ollama environment: - OLLAMA_KEEP_ALIVE24h deploy: resources: reservations: devices: - driver: nvidia count: all capabilities: [gpu] # OCR识别服务PaddleOCR的API封装 ocr-api: build: ./ocr-api ports: - 8866:8866 deploy: resources: reservations: devices: - driver: nvidia count: all capabilities: [gpu] # RAG和Agent平台 dify: image: langgenius/dify-api:latest environment: - SECRET_KEY${DIFY_SECRET_KEY} depends_on: - postgres - redis有几个细节必须提醒OLLAMA_KEEP_ALIVE24h要设大否则模型会被卸载每笔对账都重新加载延迟高到离谱。Nginx配置里大文件上传大小要放开OCR单据经常是好几MB的扫描件默认1MB限制直接断传。如果内网完全隔离没有公网镜像源得提前在内网搭一个Docker Registry把ollama、nginx这些镜像先推进去再让Compose从内网Registry拉取。这一步骤别最后再做我就是吃过亏部署到一半发现拉不动镜像整个节奏全乱。4.3 模型本地化Ollama拉取 量化精度选择LLM部分我用Ollama做服务因为它自带OpenAI兼容API对账引擎用OpenAI SDK就能连改动成本极低。拉模型的命令# 在Ollama所在主机上执行 ollama pull qwen3:8b # 或者体积更小、速度更快的4B版本 ollama pull qwen3:4b # 如果用Ollama跑知识库的Embedding ollama pull nomic-embed-text模型选择上我建议优先考虑Qwen3系列而非更老的Llama。原因倒不是崇洋媚外而是Qwen3的中文表格理解、金额与单位的解析能力在同等参数规模下明显更好。对账场景里有大量中文简称、公司全称、备注术语英文模型的训练数据根本覆盖不了。这里重点说下量化精度的取舍。Ollama默认可能拉的是Q4_K_M量化我觉得生产环境可以接受。你可能会遇到一个诱惑拉到原版FP16权重“精度更高”。但FP16权重显存占用翻倍推理速度下降三成以上换取的那点模型困惑度改善在对账这种“字典有限”的任务上几乎无感。对账本质是结构化抽取和匹配不是写诗Q4_K_M足够。如果你要稳定复现“离线环境部署大模型”我建议把模型文件提前下载好拷到装了Ollama的机器上用ollama create从本地Modelfile导入避开公网下载。不过这个操作前提是你得有一台能访问公网的机器先拉好模型再搬运过去。注意安全合规只搬运正规模型权重文件不做任何不合规的网络操作。4.4 OCR服务封装从PaddleOCR到HTTP APIPaddleOCR本身是Python库直接内部调用也行但生产上我建议用一个FastAPI包一层HTTP服务这样别的模块对账引擎、Dify都能按需调用。封装的核心接口就一个# ocr-api/main.py from fastapi import FastAPI, UploadFile from paddleocr import PaddleOCR app FastAPI() ocr PaddleOCR(use_angle_clsTrue, langch, show_logFalse) app.post(/v1/ocr) async def ocr_image(file: UploadFile): content await file.read() # 实际生产中要落盘或读内存这里简写 result ocr.ocr(img_path, clsTrue) lines [{text: res[1][0], box: res[0]} for res in result[0]] return {lines: lines}这里值得说的几个生产细节PaddleOCR的表格识别要单独开如果单据里有复杂合并单元格普通OCR返回的只是文字块没有表格结构。对账时经常需要还原“表头-单元格”的对应关系建议用PaddleOCR的PP-Structure或至少加一个表格重建模块不然金额列和日期列容易错位。图像增强要前置扫描件发灰、有印章遮挡直接送OCR识别率会掉。建议在OCR之前做灰度化、自适应二值化、去噪。这几个操作用几千行数据集的测试结果平均能把识别率提升3~5个百分点。OCR置信度字段一定要保留识别结果里自带置信度分数这个分数要一直传到对账引擎参与最终匹配的置信度加权。如果一个字段OCR置信度低即使匹配上了也要标记为待复核。4.5 对接Dify搭建RAG和Agent流程Dify在这个方案里的角色是低代码的RAG与Agent编排层。它的安装有些人觉得麻烦其实就是标准Composegit clone https://github.com/langgenius/dify.git cd dify/docker cp .env.example .env docker compose up -d部署完进界面做两件事创建知识库把企业历史对账案例、客户简称映射、异常处理说明、合同编号规则传进去选向量模型用前面拉的nomic-embed-text分段粒度按“一个对账案例一块”设置。创建Agent设计一个“对账助手”接收对账引擎传来的待复核案件先检索知识库中相似案例再结合当前单据上下文生成解释和匹配建议。需要注意Dify的Agent是异步编排对账引擎调用它的API后要处理好回调或轮询逻辑别让同步请求干等超时。我在项目里用的是异步消息队列方案对账引擎把待复核案件塞进Redis队列Dify流程从队列消费处理完再把结果写回Redis对账引擎轮询拿结果体验上就是前端提交后几秒返回建议不会卡死。5. 对账引擎的核心实现归一化、多级匹配、置信度三重门部署只是把架子搭起来真正决定方案能不能扛住业务检验的是对账引擎的实现细节。这章把核心代码逻辑和踩过的坑拆开讲。5.1 数据归一化所有字段先过“标准格式关”归一化做不好后面匹配全是空中楼阁。我最崩溃的一次经历是客户银行流水里金额用“48,600.00”字符串ERP里是数字48600台账里是“48600元整”三条数据肉眼看着一样程序匹配怎么都对不上。所以归一化必须做三件事金额归一化去掉货币符号、千分位逗号、中文单位“元整”“万元”统一转为以“分”为单位的整数。用Decimal或分单位避免浮点误差。日期归一化统一转化为ISOYYYY-MM-DD。遇到“2023.10.15”“10/15/2023”“2023年10月15日”统一规则清洗同时保留原始日期字段备用。交易对手归一化这是最微妙的。建议维护一个“别名表”ABC公司上海分公司、上海ABC公司、ABC上海都指向同一个主键。初版可以人工维护跑一段时间后用LLM根据历史匹配记录自动补别名人工确认后入库。实战里我发现多数对账匹配失败不是算法不行而是归一化没做彻底。宁可多花一周时间把归一化规则打磨好也别急于上匹配。下面是一段归一化的核心逻辑示意# reconciliation/normalize.py from decimal import Decimal import re def normalize_amount(raw_value: str) - int: 统一金额到分避免浮点误差 if raw_value is None: return -1 s str(raw_value).strip() s s.replace(, ).replace(¥, ).replace(,, ) s s.replace(元整, ).replace(元, ).replace( , ) # 中文万元 → 数字 if 万 in s: s s.replace(万, ) return int(Decimal(s) * 10000 * 100) if . in s: return int(Decimal(s) * 100) return int(Decimal(s) * 100)5.2 多级匹配先Hash精确再模糊候选再LLM定夺匹配引擎的设计原则是**“能算出来的不用AIAI只用在该用的地方”**。这个原则帮我省了大量Token费用和延迟第一级精确匹配。把已审核的应收单按金额的哈希分桶同一金额桶内的单据再按业务日期和交易对手做复合索引查询。命中率取决于数据质量数据干净的时候可以达到70%。第二级模糊匹配。精确没中的进入模糊匹配候选集。按金额±0.01元、日期±5天、交易对手的编辑距离≤2这几个条件放宽搜索。这里最怕的是候选集太大所以必须做倒排索引把“金额”作为主键才能秒级返回。第三级LLM辅助判定。到了这一级通常是真问题一笔回款对应多张发票、跨期付款、摘要里带了外号或部门名称。把原始单据文本、候选单据列表、知识库检索结果一并打包成Prompt让LLM给出“匹配建议理由”。这里我给出一个实际用过的Prompt模板结构你是企业财务对账助手。现有以下银行回单 金额48600.00 付款方客户A公司 摘要货款8月合同尾款含税 日期2025-10-15 请从下列应收单据中选择最可能对应的一笔或多笔 1. 金额48600单号XS-088开票日期2025-09-28 2. 金额48600单号XS-089开票日期2025-08-30 3. 金额48800单号XS-090开票日期2025-10-05 请指出匹配哪一笔如果你认为存在“一笔回款对应多笔应收”请分别列明并给出理由。实测下来这三级流水线能把自动对平率从纯规则引擎的55%左右拉到80%以上。剩余20%进入人工队列但因为AI已经给出候选和理由财务处理单笔时间从原来的几分钟压到十几秒。5.3 置信度与“三重门”系统不背锅但要会甩锅对账系统有很强的审计属性所以结果不能只给一个“对上了”就完事。我给每笔匹配打三个维度的置信度OCR置信度原始单据字符识别分低于0.85的自动标记匹配置信度命中算法难度的度量硬匹配给0.95以上模糊匹配按相似度递减LLM置信度大模型判断时的自称置信度它说“不确定”就直接进人工队列。三个分数相乘得到最终置信度。≥0.9自动入账0.6~0.89推送待确认0.6直接挂人工。这个阈值可以根据企业数据质量调但我不建议一上来就定高自动入账比例。先让财务体验一两周把误判案例投喂回系统完善知识库再逐步放宽阈值。这样设计还有个隐藏好处领导问“这账自动对的能信吗”时你能拿三层置信度说话而不是拍脑袋保证。系统不背锅但也绝不当黑盒埋雷。5.4 人工复核流程别让“复核”变成“重录”很多AI项目死在“自动化的最后一公里”系统给了一堆待复核项结果财务要一张张打开原始单据照片、手动回填原因比手工对账还累。所以复核界面必须做到三条一屏呈现左边原始单据图片或原文右边候选匹配列表和理由下面直接是确认/改选按钮预填结论LLM建议的匹配关系默认打勾财务只要看有没有疑问一键反哺财务做出选择后这个“问题正确答案”要自动进知识库下回同类账目直接命中不重复打扰。这套机制跑起来后有一个意外收获财务人员开始利用“反馈按钮”不断教系统识别他们公司的特殊业务模式一个月下来待复核比例持续下降。系统不是一次交付的而是越用越准。6. 部署与上线之后那些文档里不会写的坑和真实效果最后一部分写写这套系统实际跑起来后的效果、我踩过的几个大坑、以及真正值得你担心的边界。6.1 客户实施三个月后的量化结果客户是一家做工业品分销的贸易公司月流水约1.2万笔三个业务系统加一个ERP。上线前财务部四个人月底对账要忙8~9天上线后月底对账压缩到3天其中大部分时间在复核异常件。指标上线前上线后单据录入人工耗时每天约6人·小时每天0.5人·小时OCRLLM自动识别准确率无92%剩余8%进人工自动对平率手工约50%82%自动8%半自动对账周期月结8~9天2~3天跨系统差异件处理时长每人每笔3~5分钟平均15秒/笔当然这个效果不是免费来的。投入包括一台约三万的服务器、一个半月的实施周期其中两周在撕字段映射和别名表、以及IT人员每天抽两小时盯着前两周的识别报表。总体算下来半年的人力成本节约就覆盖了投入。6.2 坑一OCR识别对了但金额单位错位这个坑我记忆犹新。PaddleOCR识别一张增值税发票数字全对但“价税合计小写”那一栏识别成了“¥48600.00”后面又跟着“大写肆万捌仟陆佰元整”。归一化时如果只取第一个金额恰好对。但如果发票排版两栏并排就会把含税金额和无税金额拿混导致对账差出税额。解决办法OCR出的表格结构信息必须参与字段映射不能按“第一个金额就是总额”的粗暴逻辑。我的做法是让版面分析先定位“价税合计”“合计大写”等锚点词再取锚点附近的值。锚点词不匹配直接降置信度进人工。总而言之——锚点词是字段抽取的护栏宁可多写几十个锚点正则也不要裸奔抓字段。6.3 坑二LLM在“知识库查到类似案例”时会幻觉式编造理由RAG接入后出现过一次非常危险的幻觉一批差旅报销对账LLM误把知识库里另一家公司的处理结论当成现成答案生成了一段“理由充分但张冠李戴”的解释差点让财务误判。我排查后发现Dify的检索召回里向量相似度阈值设太低了混入了太多不相关段落。调整方法非常直接把检索top_k从5降到2同时把向量检索阈值提高到0.75以上只保留强相关的历史案例。另外Prompt里明确写了“如果知识库内容与当前单据主题不一致必须明确说‘知识库无匹配案例’不要猜测”这能阻断绝大多数幻觉。生产环境一定要给大模型的输出加一层校验规则涉及金额的推荐必须从单据原文选禁止凭空生成数字。6.4 坑三内网部署的环境隔离问题客户总部在内网环境不能访问公网容器镜像仓库这差点让整个项目卡死。经验是部署前先在一台有公网的同一架构机器上打好所有镜像docker save存成tar包拷到内网再docker load。注意架构必须一致x86服务器上备份的镜像不能直接load到ARM机器上跑。模型权重同样处理公网机器拉好Ollama模型拷到内网用ollama create从本地Modelfile导入。如果内网还有等保要求记得把容器内的非必要端口全部关掉Nginx只暴露必要端口数据库和Redis不映射宿主端口外部一律访问不到。6.4 稳定运行一年后的维护心得这套系统上线一年最深的体会是AI中台不是一个“项目”而是一个“持续喂养的业务流程”。模型偶尔要更新版本、别名的维护要有人管、知识库每季度要清洗一遍旧案例、每月的对账异常反馈要看。但它带来的收益是实打实的——财务部门从月初的地狱模式里解放出来IT部门也有了一套可扩展的智能数据底座。后续如果要加采购订单识别、合同关键条款抽取、甚至经营分析问答都是在这个底座上加模块的事不用另起炉灶。如果你也正在被“多系统重复录入、月底对不平账”折磨我建议别一上来就追求大模型多模态一步到位先搭建这套“OCR轻量LLM规则引擎人工复核”的轻型中台把对账这一条业务线打通再谈扩展。AI落地的价值从来不是跑分多高而是让财务少加一次班。