ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

用Qwen3.8-Max搭建商品资料包体检助手:多文档交叉校验实战

用Qwen3.8-Max搭建商品资料包体检助手:多文档交叉校验实战 做商品上架审核这活儿干过的人都知道有多磨人。尤其碰到那种资料包动不动就七八份的情况——产品说明书、质检报告、授权书、报关单、详情页文案甚至还有包装实拍图格式五花八门内容互相牵扯。人工一份份打开、对照、找错眼前全是 PDF 和 Excel 来回切漏掉一处细节后面就是客诉或者平台下架的风险。我这次直接用 Qwen3.8-Max 搭了个商品资料包体检助手把 6 份资料加 1 张商品主图一次性丢进去跑出来 27 个问题。整个过程从思路到落地也就两三天今天把关键步骤和踩过的坑完整分享出来给正在做商品合规、电商上架审核或者供应链数据治理的朋友做个参考。这次做的不是一个通用问答机器人而是偏“联审工具”的东西。核心逻辑很简单让模型像审稿人一样把多份资料交叉核对最后输出一张问题清单。谁适合参考这篇内容如果你手头经常要处理商品资料包、资质文件、检测报告这类多文档校验场景或者你正在尝试用多模态大模型做结构化信息抽取这篇应该能帮你省不少试错时间。1. 项目背景与整体设计思路1.1 人工审核的痛点在哪里先说说为什么非要搞这个助手。以前我做电商商品资料审核基本靠人工打开每个文件肉眼扫关键字段再手动比对。比如质检报告上的产品名称、型号和说明书、报关单、主图详情页上的是不是对得上授权书的有效期覆盖到什么时候检测标准是不是最新版本主图上的卖点文案和详情页有没有自相矛盾。这个过程有几个我很头疼的地方。第一是量大一个 SKU 动辄 5 到 8 份文件每天几十个 SKU 的话眼睛能看花。第二是维度多审核不只是看一眼“有没有”还得核对“一致不一致”。比如瓶身包装图上的“500ml”和说明书上的“500mL”看起来差不多但按严格标准这俩表示不一致得提出来。第三是效率低人工看 6 份文件至少要 20 分钟而且不同的人审核尺度不一样今天这个人觉得没问题的换个人又认为要整改。后来我想能不能让大模型来做这件事。将多份文件当成“材料清单”把商品名、品牌、型号、规格、材质、执行标准、证书编号、有效期、产地、制造商等字段当成“证据点”让模型把这些证据点从各份资料里提取出来再逐项做交叉比对。这就是整个体检助手的原型“抽取——比对——出报告”。1.2 方案选型为什么用 Qwen3.8-Max 做多模态联审选 Qwen3.8-Max 有我的理由。它一个模型同时具备文本理解和图像理解能力这对商品资料包来说太重要了——资料包里既有 PDF 文字又有扫描件图片还有实拍包装图、主图你总不能把每张图都单独外挂一个 OCR 服务再拼接文本吧。多模态模型一次搞定直接把图片和文字统一送进上下文里让模型自行做跨模态的对齐。另一个考虑是输出质量。商品审核这个场景非常忌讳模型“自由发挥”我要的是稳定的结构化输出最好是直接给我 JSON。Qwen3.8-Max 在指令遵循和 JSON 结构化输出上比较稳配合低温度参数结果的可控性比很多同类模型好。实际跑下来单次联审能输出的字段数量和一致性判断都比较符合预期。整体架构上我没有做得很复杂一共三层第一层是文件解析层把 PDF、Word、Excel、图片统一转成模型能读的文本或图像数据。第二层是智能核对层把解析结果按固定模板拼进 Prompt调用 Qwen3.8-Max 做交叉比对。第三层是规则叠加层用正则和规则脚本再扫一遍结构化字段补上模型容易漏掉的格式类问题。这套结构最大的好处是可插拔。今天用 Qwen3.8-Max明天换别的模型只需要改第二层的调用代码解析层和规则层都不用动。下面我按这个顺序把每层的关键实现讲清楚。2. 文件解析层6 份资料怎么统一喂给模型2.1 不同文件格式的解析方案资料包里的文件格式通常不统一常见的至少有 PDF、Word、Excel、图片四类。我这次测试的 6 份资料正好覆盖了这些格式产品说明书PDF质检报告PDF品牌授权书PDF 扫描件报关单Excel详情页文案Word包装实拍图JPEG外加一张需要做最终视觉校验的商品主图PNG。PDF 我用了 PyMuPDF也就是 fitz来提取文本。这里有个小经验如果 PDF 本身就是文字版fitz 直接page.get_text()很稳但质检报告这种经常是扫描件或者图片型 PDF文字提取出来是空的这种情况比较建议先用 fitz 把每页渲染成高清 PNG再交给后面的视觉模型去读。我这次遇到的情况就是品牌授权书是纯扫描件所以我在代码里做了一个自动检测提取出来的文本量少于某个阈值就转渲染。对于 Word 文档我用python-docx提取段落和表格。Excel 用的是openpyxl重点提取单元格值顺便保留表头对应的列名。图片处理相对简单我直接用Pillow把图片压缩到合适尺寸再转 base64 传给模型。这里要特别注意一点压缩的时候别把关键文字压模糊了下面踩坑部分会细讲。import fitz import base64 import io from PIL import Image from docx import Document from openpyxl import load_workbook def extract_pdf_text(pdf_path): doc fitz.open(pdf_path) text for page in doc: page_text page.get_text().strip() if page_text: text page_text \n else: pix page.get_pixmap(dpi200) img_bytes pix.tobytes(png) # 这里可以做图片压缩和缓存稍后统一传给视觉模型 return text def extract_word_text(docx_path): doc Document(docx_path) parts [] for p in doc.paragraphs: if p.text.strip(): parts.append(p.text.strip()) for table in doc.tables: for row in table.rows: cells [cell.text.strip() for cell in row.cells] parts.append( | .join(cells)) return \n.join(parts) def extract_excel_text(xlsx_path): wb load_workbook(xlsx_path, data_onlyTrue) lines [] for ws in wb.worksheets: for row in ws.iter_rows(values_onlyTrue): if any(v is not None for v in row): lines.append( | .join([str(v) if v is not None else for v in row])) return \n.join(lines) def image_to_base64(image_path, max_size1024): img Image.open(image_path) img.thumbnail((max_size, max_size), Image.LANCZOS) buf io.BytesIO() img.save(buf, formatJPEG, quality90) return base64.b64encode(buf.getvalue()).decode(utf-8)注意 openpyxl 加载时data_onlyTrue很关键。如果 Excel 里有公式不加这个参数拿到的可能是公式字符串而不是最终计算值。商品资料的报关单金额、数量这些字段非常依赖计算值拿公式字符串喂给模型会闹笑话。2.2 内容太长怎么办先分档抽取再统一联审把这 6 份文件全部塞进 Prompt 之前有个现实的问题——上下文长度有限。尤其是说明书和详情页文案动辄几千字如果全量拼接不仅 Token 消耗大模型还容易抓不住重点。我采用的策略是先做一轮“单文件字段抽取”再让模型基于抽取结果做“跨文件比对”。比如对说明书我先让模型单独提取商品名称、品牌、型号、容量、材质、执行标准、生产商、产地这些字段对质检报告单独抽取报告编号、样品名称、检测项目、检测结果、检测标准、签发日期、有效期。等每份文件的关键字段都抽出来了再把所有字段汇总成一张“字段清单表”让模型做一致性比对。这样做还有个额外好处我可以把规则脚本对齐到字段上比如检测标准必须匹配《XXX》规范日期格式必须统一成 YYYY-MM-DD。规则层面能扫出的问题就不必非得花 Token 让模型判断。我这次 27 个问题里至少有三分之一是靠规则层抓出来的比如“日期格式不统一”“金额币种缺失”“统一社会信用代码校验位不对”这类规则脚本比模型更稳、更省成本。3. 智能核对层让模型像审稿人一样交叉验证3.1 联审 Prompt 的设计技巧提示词的质量几乎决定了这个项目的成败。我这版 Prompt 总共迭代了四轮核心可以拆成这几个部分角色约束、任务步骤、输出格式、禁区。角色约束是防止模型乱答。我会明确告诉它“你是一个商品合规审核专家只做交叉校验不生成新内容。” 因为商品审核要的是“发现问题”而不是“解释问题”角色约束越强模型越不容易在结果里夹杂营销话术。任务步骤要清晰第一步列出所有文件第二步抽取每个文件的核心事实第三步建立字段映射表第四步逐项比对并判断差异第五步输出问题清单。每一步我给一个简短的提示比如“如果同一字段在不同文件中表述不一致以更具权威性的文件为准如质检报告优先于详情页”。输出格式我走的是 JSON因为后续要接规则层和表格。我给模型定义了 schema要求输出一个数组每项包含problem_id、issue_type、severity、related_files、description、suggestion。不要指望模型自动生成完美 JSON最好在 Prompt 里直接给一个示例。禁区设计也挺重要。我加了一句“如果资料中没有明确依据不要臆测标记为‘信息缺失’”。这句话能有效防止模型自己脑补一个品牌名或日期出来充数。3.2 Python 调用的完整示例调用代码本身不复杂我用 DashScope 兼容 OpenAI 格式的接口来做。这里演示的是多模态输入图片部分走image_url文本部分走text。import json from openai import OpenAI client OpenAI( api_key你的API-KEY, base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1 ) def run_audit(files_text, images_base64, rule_checksNone): prompt build_prompt(files_text, rule_checks) contents [] # 文本内容 for block in files_text: contents.append({type: text, text: block}) # 图片内容 for img in images_base64: contents.append({type: image_url, image_url: {url: fdata:image/jpeg;base64,{img}}}) response client.chat.completions.create( modelqwen3.8-max, messages[ {role: system, content: 你是严谨、保守的商品合规审核专家。}, {role: user, content: contents} ], temperature0.1, response_format{type: json_object} ) return json.loads(response.choices[0].message.content)我实测下来有两个细节值得强调。一是temperature0.1非常关键审核场景要的是稳定不是创意。第二次跑和第一次跑结果最好完全一致温度调高就会出现同一个问题这次报、下次不报的情况。二是response_format指定 JSON 输出配合 Prompt 里的示例模型基本不会给你返回多余的散文。3.3.3 提示词模板脱敏示例我可以把核心那版 Prompt 简化成下面这个样子你可以直接改成自己的字段现有以下商品资料 1. 产品说明书{doc_text} 2. 质检报告{report_text} 3. 品牌授权书扫描件{auth_image_base64} 4. 报关单{customs_text} 5. 详情页文案{copy_text} 6. 包装实拍图{packaging_image_base64} 附加资料商品主图 {main_image_base64} 请按以下步骤执行 1. 提取每份资料中的核心事实字段。 2. 将所有字段统一到同一 Fact Table 中列名分别为商品名称、品牌、型号、规格、材质、执行标准、认证编号、授权期限、生产商、产地、出厂日期、保质期、建议零售价。 3. 比对同一字段在不同文件中的取值记录所有冲突、缺失、格式不规范的条目。 4. 输出 JSON格式为 {problems: [ {field: 字段名, type: missing|conflict|format|expired, severity: high|medium|low, files: [说明书, 质检报告], description: 问题描述, suggestion: 整改建议} ]}这里我刻意没有把所有文件的全文贴进 Prompt而是在前一轮已经抽好了关键字段然后把字段表和少量原文片段拼进去。这样既保留了比对的“证据链”又不会让上下文爆炸。4. 规则叠加层把模型抓不牢的格式问题捞出来4.1 哪类问题适合交给规则脚本模型擅长的是语义理解比如“说明书写 500ml主图写 500mL这俩是不是一致”这种判断。但数据格式类的校验比如日期是不是合法、身份证/信用代码校验位对不对、邮箱格式、金额字段是不是纯数字模型做起来反而比正则慢而且容易出错。这类问题比较适合交给规则脚本。我这次把规则层分成两类。第一类是“必查格式”比如日期字段统一转成datetime再比较金融金额字段统一转成Decimal避免浮点误差。第二类是“字典匹配”比如执行标准编号必须在一定映射表里品牌名必须在授权品牌列表里。举个例子质检报告上的“签发日期2025.02.30”——这种日期肉眼都很难一眼看出有问题但datetime模块可以直接抛异常。这属于模型很自然就能放过的错误所以必须靠规则层兜底。import re from datetime import datetime def check_date_format(value): if not value: return 缺失 try: datetime.strptime(value, %Y-%m-%d) return 通过 except ValueError: return 格式错误或不合法日期 def check_uscc(uscc): 统一社会信用代码校验位检查简化版 if not uscc or len(uscc) ! 18: return 长度错误 # 实际还有加权因子校验此处省略 return 通过 def check_amount(value): if not value: return 缺失 if not re.fullmatch(r\d(\.\d{1,2})?, str(value)): return 金额格式错误 return 通过规则层的输出可以合并到模型输出里两份结果最终汇总成一个“问题池”再按problem_id去重。如果规则脚本查出某个问题模型在语义比对里也报了同一个字段就可以只保留规则层结果并把模型的描述词合并进去。这就是我说的“27 个问题”的最终来源不是光靠模型数出来的是模型加规则一起收敛出来的。4.2 规则层怎么跟模型结果合并合并的时候我踩过一个小坑模型报问题时用的字段名经常不那么统一比如这次叫“规格”下次叫“容量”。所以我做了一个字段名映射表把“规格”“容量”“净含量”“容积”统一归一到spec。这样可以避免同一条问题被重复计数也能让最终报表更干净。我建议把合并逻辑单独写一个函数输出标准化的问题对象包括严重级别。比如“质检报告已过期”这种直接关系到能不能上架的问题级别是high“详情页文案中的英文大小写与说明书不一致”级别是low。这样运营同学拿到清单后可以先处理高危项低危项批量修。FIELD_ALIAS { 规格: spec, 容量: spec, 净含量: spec, 容积: spec, 产品名称: product_name, 商品名称: product_name, 型号: model, 品牌: brand, 材质: material, 执行标准: standard, 生产商: manufacturer, 产地: origin } def normalize_field(name): return FIELD_ALIAS.get(name, name) def merge_problems(model_problems, rule_problems): result {} for p in model_problems rule_problems: key (normalize_field(p.get(field, )), p.get(type, )) if key not in result: result[key] p else: # 合并描述保留更高严重级别 if p[severity] high: result[key][severity] high result[key][description] p[description] return list(result.values())这里的排序逻辑建议按severity降序输出问题多的资料包一眼能看到哪些必须先处理。5. 一起来看实测6 份资料 1 张图怎么查出 27 个问题5.1 测试样本与前处理流程我用一个便携榨汁杯的商品资料包跑了一遍完整流程。6 份资料分别落在“说明书”“质检报告”“授权书”“报关单”“详情页文案”“包装图”上外加一张主图。整个前处理流程这样走PDF 里说明书和质检报告直接抽文本授权书是扫描件走图片渲染Excel 报关单走openpyxlWord 详情页走python-docx包装图和主图转 base64 后拼进 Prompt。调用模型时我把文本内容和图片内容都塞进同一个contents数组顺序依次是说明书、质检报告、授权书图片、报关单、详情页文案、包装图、商品主图。文件顺序尽量不要乱因为 Prompt 里的编号和顺序会影响模型抽取字段时的逻辑连贯性。模型跑完一轮之后会返回一个problems数组。我再独立跑一遍规则脚本把日期、金额、格式类问题追加进去。最后合并、去重、量化严重级别得到完整清单。整个过程从脚本启动到拿到结果大约 1 分 40 秒其中模型推理大概占 1 分 20 秒剩下的是文件解析和规则处理。5.2 27 个问题长什么样最终的问题清单按严重级别拆分high级别有 5 个medium有 13 个low有 9 个。举几个有代表性的编号字段类型级别涉及文件问题描述P01商品名称conflicthigh说明书 vs 详情页说明书写“便携式榨汁杯”详情页写“迷你榨汁机”同物异名P04认证编号conflicthigh质检报告 vs 报关单质检报告编号为 GZ2024-0886报关单写成 GZ2024-886P06执行标准expiredhigh质检报告引用的执行标准 GB/T 1234-2016 已被 GB/T 1234-2024 替代P10授权期限conflicthigh授权书 vs 详情页授权书有效期至 2025-06-30详情页标注长期有效P12规格conflictmedium包装图 vs 说明书包装图标注 500ml说明书标注 500mL大小写不一致P15品牌名formatmedium报关单报关单品牌栏写的是“无品牌”与授权书品牌不符P19出厂日期formatmedium说明书说明书标注 2025.03.21格式不统一应为 2025-03-21P22建议零售价formatlow报关单 vs 详情页报关单金额 9.99 USD详情页标价 89 CNY缺少汇率说明P24图片文字conflictlow主图 vs 包装图主图宣传“无线充电”包装图仅标注“Type-C 充电”信息不一致这 27 个问题里模型直接给出的有 20 个规则层补充了 7 个。你可能会问为什么模型报的问题不是全部因为有些格式类问题模型会主观地“忽略”掉而且模型容易把“看起来差不多”的误认为是一致的。所以规则层绝不只是一个保险丝而是体检报告的重要组成部分。5.3 输出报告怎么给运营用模型和规则合并后的问题我会生成一份 Markdown 格式的《商品资料包体检报告》按严重级别分组每组用表格展示。运营同学处理的时候high项是阻断项必须先整改才能过审medium项一般是要求补充说明或者统一表述low项可以批量修复。报告末尾我会自动附上一段“整改建议”比如“请以质检报告为准统一商品名称为便携式榨汁杯重新确认授权书有效期并补充品牌在报关单中的申报信息”。这些建议也是由模型生成的但它的生成前提是前面已经给出了明确的比对结果所以不会跑偏。这套方式相比人工审核最大的提升不是“发现问题的数量”而是“每个问题都有出处”。我是说模型会给每个问题关联到具体文件名的字段值这样运营就不用再翻一遍原始文件去核实。单这一点就省下了大量时间。6. 实操踩坑记录与排查技巧6.1 扫描件 OCR 识别错误和图片分辨率问题我测试的品牌授权书是扫描件一开始我直接把它当作 PDF 文本解析结果抽出来全是乱码模型什么都读不到。后来改成 PDF 渲染成图片再喂给视觉模型确实能读了但出现了新问题授权书上的“有限公司”被 OCR 识别成“有限公目”这种识别错误在海关、证书这类资料中屡见不鲜。排查思路是在把图片传给模型之前先做一轮基础的图片质量处理。我建议把渲染 DPI 从 72 提升到 150 到 200图片尺寸限制在 1024 像素以内但 DPI 不能太低。DPI 太低字会糊尺寸太大Token 占用又高。实测 200 DPI 渲染品牌授权书模型的识别准确率高了不少基本能正确读出公司名称、证件编号。另外一个细节是 base64 图片在传递时最好压缩成 JPEG而不要用 PNG。PNG 可能会让图片体积翻倍接口传输和模型处理都会变慢但画面中非文字的渐变区域对审核又没有实际帮助。JPEG 质量控制在 85 到 90 之间文字识别效果和性能平衡得很好。6.2 上下文越长模型越容易“抓小放大”一次送 6 份资料加 1 张图上下文长度大概有 3000 到 5000 Token。实测下来上下文越长模型越倾向于报“低价值问题”却忽略一些明显的大冲突。比如商品名称不一致这种跨文件大问题在全部文件一拥而上时反而不容易被揪出来小问题倒是报出一堆。我的处理办法是两阶段拆解。第一阶段让模型对每份文件单独做字段抽取同一时间只看一份文件上下文很短输出很精准。第二阶段再把所有抽取出来的字段汇总让模型基于精简的字段表做交叉比对。这样既保留了全局视角又降低了单次推理的复杂度。对比下来两阶段跑出来的结果比一次性全塞的准确率高不少而且 Token 消耗反而更少。6.3 模型把明显错误“纠正”掉的问题这里有个特别值得说的坑模型有时候会自作主张把已经不一致的字段“统一”成一个看似合理的值然后在报告里不报这个问题。比如说明书写的“500ml”详情页写的“500mL”模型可能直接统一成“500ml”然后告诉你没有问题。这种“纠正性幻觉”在审核场景里很危险。我的对策是在 Prompt 里反复强调不许修改原始字段值只做比对和报告。从工程角度看我还会在规则层做一次“原始值快照”把各文件里的关键字段原样抽取出来与模型给的比对结果做差异检查。如果模型输出里的“统一值”和某份原始文件不一致就自动标记为潜在漏报。6.4 输出格式不稳定怎么兜底即便用了response_format偶尔模型也会输出不标准的 JSON比如多了一对花括号或者字段名大小写漂移。我的兜底方案是写一个简单修复函数先尝试json.loads如果失败就用正则把problems数组切出来再逐段解析。实在解析不了就把这次调用标记为“审核失败”重新跑一次而不是让流程静默失败。def safe_json_parse(raw): try: return json.loads(raw) except json.JSONDecodeError: match re.search(r\{.*\}, raw, re.S) if match: try: return json.loads(match.group(0)) except json.JSONDecodeError: return {problems: []} return {problems: []}跑测试的时候这个safe_json_parse帮我拦住了至少 3 次因为 JSON 尾部多了一个逗号导致的解析失败。你如果想要更稳定可以在模型 Prompt 里加一句“不要在 JSON 末尾添加任何多余符号”实测也能降低出问题的概率。6.5 常见问题速查表为了方便你排查我整理一张速查表问题表现可能原因处理办法模型读不出 PDF 文字PDF 是扫描件或图片型 PDF改用 fitz 渲染图片再走视觉模型扫描件公司名识别错误图片 DPI 太低渲染 DPI 提升到 200 左右模型漏报大字段冲突上下文太长注意力被分散改用两阶段先抽取后比对模型把不一致悄悄改一致指令里缺少“禁止修改原值”约束Prompt 中明确禁止改写原始字段JSON 解析失败模型输出多符号增加 safe_json_parse 兜底同一问题重复计数字段名不统一维护字段别名映射表合并前归一化真正上手跑一遍之后我最深的体会是大模型在商品资料审核场景里不是替代规则引擎而是和规则引擎打配合。模型负责理解上下文、发现语义冲突规则层负责精确校验格式和计算。两者叠加之后27 个问题这种结果是人力很难一次性找齐的但对一个写好的脚本来说只是几分钟的事。如果你也想试建议不要一上来就追求“全自动无人审核”先让这个体检助手输出问题清单再由人工终审这样效率提升非常明显风险也可控。等跑顺了再把高危项的自动拦截和触发流程加上去一步步来。
返回列表