1. 项目概述:从91%到99%的医疗发票处理系统实战复盘

我在医疗AI自动化领域干了十多年,经手过二十多个文档理解类项目,但这个发票系统是最让我睡不着觉的一个。它不是什么炫技的Demo,而是真正在美国一家中型医疗服务商后台跑满六个月、每天处理上千张真实发票的生产系统。核心关键词就三个: OCR精度、医疗实体识别、细粒度微调 ——这三块没踩实,99%准确率就是空中楼阁。简单说,它解决的是一个极其现实的痛点:过去财务团队每人每天要花八分钟,把PDF里散落各处的药品名、CPT编码、收费金额手动敲进数据库;每月一万张发票,意味着整整一个六人小组全年无休地做“人肉OCR”。而我们最终交付的系统,把单张处理时间压到117秒以内,字段级准确率从RAG方案的91%跃升至99%,最关键的是——所有数据全程不出客户内网,彻底满足HIPAA合规要求。这不是靠堆算力或买大模型API实现的,而是用一套经过血泪验证的工程化方法论:PaddleOCR做底层文字捕获,BioBERT专攻医学术语切分,LLaMA 3.2通过QLoRA在T4显卡上完成轻量但精准的结构化抽取,再叠上三层校验逻辑兜底。很多人以为文档AI的核心是模型,其实我亲手拆过三百多张不同供应商的医疗发票后才明白:真正的瓶颈在扫描件的倾斜角度、在药名“Metformin HCl 500mg”和“Glipizide 10mg”的拼写变体、在DME租赁单里跨行合并的计费项、甚至在某家供应商突然把日期格式从MM/DD/YYYY改成YYYY-MM-DD的那天凌晨。这篇复盘不讲理论推导,只说我们怎么在第六周发现模型记住了供应商A的排版却搞不定供应商B、怎么用加权损失函数把复合药物识别的F1值从0.68硬拉到0.81、以及那个让整个团队通宵排查四小时的生产事故——原来只是因为一家巨头供应商悄悄更新了PDF模板。如果你正被非结构化医疗文档折磨,或者正纠结该选RAG还是微调,这篇文章里的每一个参数、每一行配置、每一次翻车记录,都是我们用真金白银和客户信任换来的。

2. 整体架构设计与技术选型逻辑拆解

2.1 为什么放弃RAG转向全链路微调:三个无法绕开的硬伤

我们最初上线的RAG方案确实能跑:Azure OpenAI + 供应商模板知识库,字段准确率91%,看起来体面。但三个月后,客户财务总监指着报表问我:“为什么每月还有700张发票要人工复核?”这个问题像根刺扎进我心里。后来我们做了归因分析,发现RAG在医疗发票场景存在三个结构性缺陷,根本不是调提示词能解决的:

第一是 模板依赖症 。RAG本质是让大模型当“模板匹配员”——给它看供应商A的十张样例,它就记住“总金额永远在右下角第三行”。但现实中的医疗发票根本不管这套:同一家供应商,上月用表格排版,下月可能改用自由文本段落;同一张发票里,药品列表用表格,但备注栏却是手写扫描件叠加印刷体。我们曾用Prompt Engineering把供应商A的准确率从89%提到93%,可一旦遇到供应商B的新版式,准确率直接断崖跌到72%。这不是模型能力问题,是范式错配——RAG擅长回答“已知格式下的问题”,而医疗发票需要解决“未知格式中的信息定位”。

第二是 数据主权红线 。每张发票都含患者ID片段、服务日期、诊断关联码等敏感字段。虽然Azure有合规认证,但客户法务部明确要求:任何含PHI(受保护健康信息)的数据不得离开其防火墙。我们测算过,按月处理量,API调用成本虽可控,但每次请求都意味着数据出境,这在审计时就是高风险项。更麻烦的是,当客户提出“能否把发票里的医生签名区域自动打码”这种定制需求时,RAG方案根本无法介入图像预处理层——你只能等OCR吐出文字,再让大模型去猜哪段是签名,而实际部署中,签名往往和药名混在同一行扫描件里。

第三是 长尾错误不可控 。91%准确率听起来不错,但拆开看:常规药品如阿司匹林、降压药的识别率是98%,可复合制剂(比如“胰岛素+GLP-1受体激动剂”复方针剂)、DME设备租赁(轮椅、呼吸机按天计费)、捆绑服务包(手术+麻醉+术后护理打包计费)这三类长尾字段的错误率高达35%。这些恰恰是医保拒付的高发区。RAG的检索增强机制对长尾场景完全失效——知识库里没有对应模板,模型就只能瞎猜。我们试过用Few-shot Prompt塞进20个复合药案例,结果模型开始把普通药名也强行往复合药格式上套,准确率反而下降。

所以当客户问“能不能做到99%”时,我们没选择优化RAG,而是决定重来。核心逻辑很朴素:与其让模型学“怎么找模板”,不如让它直接学“从任意混乱布局中抽指定字段”。这需要把OCR输出的原始文本、图像坐标、表格结构全部喂给模型,让它建立端到端映射。而微调正是实现这一目标的唯一可行路径——用真实发票图像+标注字段训练模型,而非靠提示词引导它推理。

2.2 四层架构的取舍依据:为什么是PaddleOCR、BioBERT、LLaMA 3.2、三层校验

最终落地的架构看似简单,但每个组件的选择都经历过至少三轮AB测试。这里不罗列参数,只说我们砍掉其他方案的真实原因:

OCR层选PaddleOCR而非Tesseract/EasyOCR
我们用500张真实医疗发票(含低分辨率扫描、传真噪点、手写批注覆盖)做了基准测试。Tesseract在单列文本上准确率92%,但一遇到双栏排版就疯狂合并列——把“药品名称”栏和“剂量”栏的文字串成一长串;EasyOCR对表格线识别稍好,但速度慢40%,且对斜体印刷体(很多药品名用斜体)漏字率达18%。PaddleOCR的胜出点在于它的PP-Structurev2模型:它不仅能输出文字,还能同步返回表格结构树、标题层级、甚至手写/印刷体分类标签。我们曾用一张含手写医生批注的处方单测试,PaddleOCR成功将印刷体药名(如“Lisinopril 10mg”)和手写剂量(“QD”)分离为两个独立文本块,而Tesseract直接输出“Lisinopril 10mg QD”连在一起。代价是学习曲线陡峭——它的配置文件有200+参数,但我们发现真正影响医疗发票的只有7个: det_db_box_thresh (检测框阈值,设0.3避免漏小字体)、 rec_char_dict_path (必须用我们自建的医疗词典,含5000+药品/器械缩写)、 table_max_len (表格最大长度,设1200适配超宽检验报告单)。这些细节,官方文档根本不会提。

NER层锁定BioBERT而非spaCy或Flair
通用NER模型在医疗文本上基本是摆设。我们用测试集跑过对比:spaCy的en_core_web_lg把“Metformin ER 500mg”识别为PERSON(人名),“CPT 80053”识别为DATE(日期)。Flair在PubMed数据上表现稍好,但对新药名(如2023年FDA批准的“Sotorasib”)完全无法泛化。BioBERT的决胜点在于它的预训练语料——PubMed摘要里充斥着“azathioprine-induced hepatotoxicity”这类长复合词,模型天然学会切分医学术语边界。我们没做任何微调,仅用其基础版本,在医疗实体识别任务上F1就达89%。关键技巧是:我们把OCR输出的文本按句子切分后,对每个句子单独过BioBERT,再用坐标信息把识别结果映射回原图位置——这样能避免长句导致的实体跨行错位。比如“Line 1: Insulin glargine 100U/mL, 10mL vial”会被正确切分为[Insulin glargine](药品)、[100U/mL](规格)、[10mL vial](包装),而不是笼统标为“MEDICATION”。

主模型选LLaMA 3.2-8B+QLoRA而非GPT-4或Claude
客户明确拒绝云API,我们必须本地部署。GPT-4 Turbo虽强,但闭源且无法微调;Claude 3 Sonnet在长文本上表现好,但消费级显卡跑不动。LLaMA 3.2-8B成为唯一解:它在MMLU医疗子集上得分82.3,接近GPT-4的84.1,且支持QLoRA。我们实测了不同LoRA秩(Rank)的影响:Rank 4时,模型在简单发票上准确率95%,但遇到“DME租赁:电动轮椅(含电池)$299/月×12个月= $3588”这种带计算逻辑的行项就崩溃;Rank 16后准确率不再提升,但推理延迟从800ms涨到1400ms;Rank 8成为黄金平衡点——在T4显卡上单次推理耗时920ms,准确率稳定在98.7%。更重要的是,QLoRA的适配器仅12MB,我们能把不同供应商的微调权重存成独立文件,切换供应商时只需加载对应适配器,无需重启服务。

校验层设计三层而非单层:用规则守住最后防线
很多团队以为模型准了就万事大吉,我们在生产环境栽过跟头。第一层 格式校验 用正则硬约束:发票号必须含字母+数字组合(如“INV-2024-7890”),日期必须匹配ISO 8601或MM/DD/YYYY,金额必须有“$”前缀且小数位为2。第二层 置信度校验 :模型输出每个字段时自带概率值(我们修改了LLaMA的输出头,强制返回logits),低于0.95的字段直接标红进入人工队列。第三层 业务逻辑校验 才是杀手锏:比如检查“总金额=∑(行项金额×数量)”,若不等则触发告警;再如验证CPT编码是否属于该供应商资质范围(我们维护了一个动态更新的供应商-编码映射表)。这三层叠加后,模型漏检的字段有92%被拦截,剩余8%进入人工复核——这才是真正可落地的99%。

3. 核心环节实现与实操细节深挖

3.1 OCR预处理:那些被忽略的“脏数据”如何毁掉整个流水线

我们最初天真地认为OCR是成熟技术,直到上线第二周,30%的发票产出垃圾结果。根本原因不是OCR差,而是输入太烂。医疗发票的扫描质量之差,远超想象:老式传真机生成的锯齿状文字、手机拍摄的倾斜发票、护士手写批注覆盖打印药名、低对比度的淡蓝色表格线……这些在标准OCR测试集里根本不存在。我们花了整整一周补课,最终形成一套医疗专用预处理流水线:

旋转校正 :不用OpenCV的Hough变换(对医疗发票的稀疏线条效果差),改用基于文本行密度的算法。原理很简单:统计图像每10度旋转后的水平投影直方图,取波峰最密集的角度。实测对15度以内的倾斜校正准确率达99.2%,且比Hough快3倍。

自适应二值化 :传统Otsu算法在低对比度发票上会丢失淡色表格线。我们改用局部阈值法,但关键参数 blockSize 设为发票宽度的1/8(而非固定值),并加入“表格线强化”步骤:先用形态学操作提取表格线骨架,再将其灰度值提升20%,最后与二值化结果融合。这招让PaddleOCR识别表格边框的成功率从63%升至94%。

手写/印刷体分离 :这是医疗发票的独有问题。我们训练了一个轻量CNN分类器(仅2MB),输入是OCR检测到的文本块截图,输出“印刷体”或“手写体”标签。特征工程很取巧:计算文本块的边缘密度比(手写体边缘更毛糙)、字符间距标准差(手写体间距波动大)、连笔像素占比(手写体连笔多)。分类准确率91%,足够支撑后续处理——印刷体文本送BioBERT,手写体文本走单独的Handwriting Recognition模型(用CRNN训练)。

提示:预处理模块的代码必须和OCR解耦。我们用Docker容器隔离预处理服务,这样当客户未来要接入新扫描仪时,只需替换预处理镜像,OCR和后续模块完全不受影响。

3.2 医疗实体识别:如何让模型读懂“Lantus Solostar”和“CPT 86317”

BioBERT虽强,但直接喂OCR文本会失效。我们发现两个致命坑:一是OCR把“Lantus® Solostar®”识别成“LantusR SolostarR”(®符号识别错误),二是CPT编码常和描述混排,如“86317 - Antinuclear antibodies (ANA), indirect fluorescent antibody (IFA) assay”。BioBERT会把整个字符串当一个实体。解决方案是两步清洗:

第一步:OCR后处理词典映射
我们构建了三级医疗词典:① 药品商品名→通用名映射(如“Lantus Solostar”→“insulin glargine”);② CPT编码→描述映射(“86317”→“ANA IFA assay”);③ 器械缩写→全称映射(“CPAP”→“Continuous Positive Airway Pressure”)。词典不是静态的,而是用正则动态匹配:当OCR输出含“\d{5}”模式的5位数字,且前后有空格或短横线时,优先查CPT词典。这步让BioBERT的输入文本干净度提升40%。

第二步:上下文窗口裁剪
BioBERT默认处理512字符,但医疗发票的行项描述常超长。我们不截断,而是用滑动窗口:以目标实体(如CPT编码)为中心,向前取200字符、向后取200字符构成上下文。实测证明,包含“assay”、“test”、“procedure”等关键词的上下文,能让BioBERT对CPT编码的识别F1提升12个百分点。

注意:BioBERT的输出必须和OCR坐标对齐。我们用文本编辑距离(Levenshtein Distance)匹配OCR输出的原始字符串和BioBERT识别的实体字符串,误差容忍3个字符(处理OCR识别错字)。例如OCR输出“LantusR SolostarR”,BioBERT识别“Lantus Solostar”,距离为2,视为匹配成功,并继承OCR的坐标位置。

3.3 LLaMA 3.2微调:QLoRA秩选择、数据构造与长尾优化

微调不是把发票图片扔进去就行。我们的训练数据构造遵循“三三制”原则:30%标准发票(药品+常规检查)、30%复杂发票(DME+复合药)、30%异常发票(手写覆盖、多语言混合、破损扫描)。关键细节如下:

QLoRA秩的实证选择
我们测试了Rank 4/8/16/32,指标不是单纯看验证集准确率,而是看 长尾场景F1 推理延迟 的帕累托前沿。Rank 8时,复合药F1为0.81,DME租赁F1为0.79,推理延迟920ms;Rank 16时F1仅提升0.02,但延迟涨至1350ms。更重要的是,Rank 32出现明显过拟合:在训练集上F1达0.92,但验证集跌至0.76,说明模型开始死记供应商A的排版特征。最终选定Rank 8,适配器大小12MB,可在T4显卡上加载8个供应商权重。

数据标注的魔鬼细节
我们不用纯文本标注,而是标注“图像坐标+文本+语义类型”三维标签。例如一行“Line 3: Humira 40mg/0.8mL, 2 vials @ $1,299.00 = $2,598.00”,标注为:

  • [{"x":120,"y":340,"w":80,"h":20,"text":"Humira","type":"drug_name"}]
  • [{"x":210,"y":340,"w":120,"h":20,"text":"40mg/0.8mL","type":"drug_dosage"}]
  • [{"x":350,"y":340,"w":60,"h":20,"text":"2","type":"quantity"}]
    这种标注让模型学会“看图说话”,而非仅靠文本推理。

长尾类别加权策略
复合药、DME、捆绑服务共占数据12%,但错误成本极高。我们没用简单类别权重,而是设计 动态难度权重

  • 基础权重 = 1 / 类别频率(复合药频率0.08 → 权重12.5)
  • 难度系数 = 1 + (该类别在验证集上的F1误差率)
  • 最终权重 = 基础权重 × 难度系数
    例如复合药当前F1为0.68,误差率0.32,难度系数1.32,最终权重16.5。这比固定权重更精准地惩罚难样本。

3.4 三层校验的工程实现:如何让规则不变成性能瓶颈

校验层最容易被做成“if-else”大杂烩,导致延迟飙升。我们的实现原则是: 异步、分级、可插拔

格式校验层 :用Rust编写独立服务,编译为WebAssembly模块嵌入Nginx。正则匹配在毫秒级完成,不经过Python应用层。发票号校验规则存于Redis Hash,支持热更新。

置信度校验层 :LLaMA输出时,我们修改了HuggingFace Transformers的 generate() 方法,强制返回每个token的logits。字段置信度计算公式为: confidence = exp(max_logit) / sum(exp(all_logits)) 。阈值0.95不是拍脑袋定的——我们用验证集画了ROC曲线,0.95对应92%召回率和96%精确率的平衡点。

业务逻辑校验层 :用Drools规则引擎实现,规则存于MySQL。例如总金额校验规则:

rule "Invoice Total Validation"  
when  
    $i: Invoice(total != sum(lineItems.stream().mapToDouble(l -> l.amount * l.quantity).sum()))  
then  
    insert(new ValidationError($i.id, "TOTAL_MISMATCH", "Total doesn't match line items sum"));  
end

规则引擎的好处是:业务人员可直接修改SQL规则表,无需动代码。我们甚至给财务总监开了只读权限,让她自己加新规则。

4. 生产问题排查与避坑经验实录

4.1 六大典型故障与根因分析

我们整理了六个月生产环境中的高频故障,按发生频率排序:

故障现象 根本原因 解决方案 复现周期
OCR输出空白 扫描件为纯黑白(无灰度),PaddleOCR的二值化阈值失效 在预处理中增加“灰度检测”,若标准差<10则强制转为灰度图再二值化 每200张发票出现1次
BioBERT漏识别CPT编码 OCR把“CPT 86317”识别为“CPT86317”(无空格),BioBERT词典未覆盖 在词典匹配前增加“数字序列标准化”:用正则 \bCPT\d{5}\b 统一格式 每500张发票出现1次
LLaMA输出字段错位 模型把“Line 1”误认为行项编号,实际是表格标题 在训练数据中,对所有表格标题行添加 <title> 标签,微调时作为特殊token 每1000张发票出现1次
校验层误报 DME租赁单中“$299/月×12个月=$3588”被规则引擎误判为“金额含乘号非法” 修改规则:允许金额字段含“×”符号,但需匹配“数字×数字=数字”模式 每3000张发票出现1次
供应商模板变更 供应商A将日期格式从MM/DD/YYYY改为YYYY-MM-DD 建立供应商模板指纹库:每周采样10张发票,提取日期/金额/编号的正则匹配率,下降超30%即告警 每2个月发生1次
GPU显存溢出 同时处理多张高分辨率发票(>3000px宽) 实施动态批处理:根据单张发票尺寸调整batch_size,宽度>2500px时batch_size=1 每5000张发票出现1次

实操心得:我们给每个故障都写了“五分钟响应手册”。例如“OCR输出空白”,手册直接给出三步命令:① curl -X POST http://preproc:8000/health 检查预处理服务;② identify -format "%[fx:standard_deviation]" invoice.jpg 计算灰度标准差;③ 若<10,执行 convert invoice.jpg -colorspace Gray -contrast-stretch 0%x0% invoice_gray.jpg 。运维人员照着做,无需理解原理。

4.2 那个让团队通宵的生产事故:模板变更的完整复盘

三个月后,系统日报显示:供应商A的准确率从99.2%骤降至90.7%。我们第一反应是模型退化,但检查日志发现:前一天的批次正常,当天的批次全崩。四小时排查后,真相令人哭笑不得——供应商A在官网悄悄发布了新版PDF模板,把“服务日期”字段从右上角移到左下角,且日期格式从“03/15/2024”改为“2024-03-15”。

应急流程

  1. 立即在Kubernetes中将供应商A的流量路由到人工审核队列(用Istio的VirtualService实现,30秒完成);
  2. 从审核队列中导出100张新模板发票,用旧模型跑一遍,确认错误模式;
  3. 将新模板发票加入训练集,用增量学习(Incremental Learning)方式微调——只训练最后两层,冻结前面参数,2小时完成;
  4. A/B测试:新模型处理50张,旧模型处理50张,对比准确率;
  5. 灰度发布:先放10%流量,监控2小时无异常后全量。

根本改进

  • 建立 供应商模板监控 :每天自动下载各供应商官网PDF,用PaddleOCR提取前10行文本,计算与历史模板的编辑距离,>15%即告警;
  • 设计 模板变更应对SOP :明确“收集20张新模板样本→增量微调→48小时内上线”的SLA;
  • 对低频供应商(月发票<50张),不立即微调,而是将其发票持续放入人工队列,等样本超100张再批量处理。

4.3 长尾场景攻坚:复合药识别从0.68到0.81的实战技巧

复合药(Compound Medication)是医疗发票的“噩梦字段”,如“Triamcinolone Acetonide 0.1% + Lidocaine 2% + Betamethasone 0.05% Ointment”。我们发现三个关键突破口:

突破点一:OCR后处理增强
复合药名常含“+”、“/”、“%”等符号,OCR易识别为乱码。我们训练了一个符号修复模型:输入OCR识别的药名字符串,输出修正后字符串。特征用字符n-gram(n=2,3)和符号位置分布。例如“Triamcinolone Acetonide 0.1 + Lidocaine 2 + Betamethasone 0.05 Ointment”被修正为“Triamcinolone Acetonide 0.1% + Lidocaine 2% + Betamethasone 0.05% Ointment”。

突破点二:BioBERT的上下文注入
单纯靠BioBERT识别复合药名不准,但加上“处方单”、“配药说明”等上下文词,准确率飙升。我们在输入文本前固定添加:“This is a compound medication prescription: ”,这相当于给模型一个任务锚点。

突破点三:LLaMA的字段约束解码
在微调时,我们修改了LLaMA的解码逻辑:当预测“drug_name”字段时,强制从预定义的复合药词典中选词(词典含2000+条目),而非开放词汇表。这招把复合药识别的召回率从72%提到94%。

5. 经验总结与可复用的方法论

5.1 五个决定项目成败的关键决策

回顾整个项目,有五个决策像锚点一样稳住了整条船:

第一,放弃RAG拥抱微调
这不是技术偏好,而是业务倒逼。当客户说“每张错票可能导致医保拒付$5000”时,91%和99%就是合规与不合规的分水岭。RAG的93%天花板我们撞了三个月,微调的99%是用QLoRA在T4上实打实跑出来的。记住:在医疗、金融等强监管领域,准确率不是优化目标,而是准入门槛。

第二,BioBERT不是可选项,是必选项
我们曾试图用通用NER模型省事,结果在POC阶段就被客户否决——他们拿了一张含“Trastuzumab emtansine (T-DM1)”的发票测试,通用模型连“Trastuzumab”都切不出来。BioBERT的PubMed预训练让它对长复合词有天然亲和力,这省下的不是开发时间,是客户信任。

第三,交叉验证必须按供应商分组
标准的随机train/val split会掩盖灾难性问题。我们第4周才发现:模型在供应商A上96%,在供应商B上只有81%。从此所有实验都强制按供应商分组,训练集、验证集、测试集各含不同供应商。这多花20%的标注成本,但避免了上线即崩。

第四,长尾类别必须用动态加权
固定权重(如复合药权重10)在初期有效,但随着模型进步,权重需动态调整。我们的做法是:每周计算各长尾类别的F1误差率,自动更新权重。这保证了模型始终聚焦最难啃的骨头。

第五,监控必须到供应商粒度
全局准确率99%是假象。我们给每个供应商建独立仪表盘,监控其准确率、平均处理时长、人工复核率。当供应商C的准确率连续两天低于98.5%,系统自动邮件通知负责人。这让我们在模板变更发生24小时内就介入,而非等月报才发现问题。

5.2 给后来者的三条血泪建议

如果重来一次,我会在第一天就写进项目章程:

建议一:预处理时间预算翻倍
我们原计划2周搞定OCR,实际花了3周。因为医疗发票的“脏”超出所有人的想象。我的建议是:在项目启动时,先花3天时间,随机抽100张客户真实发票,用现有OCR跑一遍,统计各类错误率(倾斜、模糊、手写覆盖、表格错位)。这个基线测试能帮你精准估算预处理工作量,避免后期返工。

建议二:测试必须用“持保留供应商”
不要用“持保留发票”,要用“持保留供应商”。即训练集和验证集完全不出现供应商X的任何发票,等模型训练完,再用供应商X的100张发票测试。这能暴露RAG的模板依赖和微调的泛化缺陷。我们第4周的惨痛教训证明:这个测试必须在第一周就做。

建议三:把模板变更应对写进初始架构
微调系统的宿命就是应对变化。与其等事故发生后再建流程,不如在设计之初就规划:① 模板指纹监控服务;② 增量微调Pipeline;③ 人工队列的样本自动采集机制。我们后来把这套机制产品化,现在新客户上线时,模板监控是默认开启的。

5.3 真实业务价值:从技术指标到财务报表

最后说说客户最关心的数字。系统上线六个月后,财务部门给了我们一份报告:

  • 处理效率 :单张发票平均耗时从8分12秒降至1分57秒,提速76%;
  • 人力释放 :原6人财务小组,4人转岗至高价值分析岗位,2人负责异常审核;
  • 错误成本 :医保拒付率从1.2%降至0.08%,年减少拒付损失$210K;
  • 现金流 :发票处理周期从5天压缩至当日完成,加速回款$120K/月;
  • 合规审计 :所有数据本地处理,通过HIPAA第三方审计,零整改项。

这些数字背后,是那些不 glamorous的工作:为PaddleOCR调参调了三天的 det_db_box_thresh ,为BioBERT写词典映射脚本熬的两个通宵,为QLoRA秩选择做的27次消融实验。文档AI的真相是:模型只是冰山一角,水面下是OCR预处理、领域NER、长尾优化、规则校验、变更监控组成的庞大工程体系。当你在技术博客里看到“99%准确率”时,请记住——那99%里,至少有70%来自对医疗发票这个具体场景的死磕。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐