一个商品要上架,得先备齐一套资料,包括产品说明书、检测报告、品牌授权书、平台发布规则、商品参数表,以及一份待发布的文案。这六份东西来自不同的人,说明书是研发给的,检测报告是第三方机构出的,授权书是品牌方签的,发布规则是平台下发的,文案是运营写的。
它们之间有一件事必须成立,就是关键字段得互相对得上,型号、净含量、品牌名、生产企业、授权渠道、授权有效期,任何一项对不上,轻则被平台驳回重提,重则算虚假宣传。
人工比一遍要多久,取决于资料有多少页。我手头这套六份文件加起来十一页,逐项核完大概二十分钟,而且是纯体力活,人一累就漏,这个工具要做的就是把那二十分钟压成一次点击,而它真正需要想清楚的地方是模型该怎么分工。
一、文本和图片是两种活,一个模型干不完
最开始我是拿一个模型全包的,文档丢进去让它读,图片转成 base64 也丢进去让它看,一次请求解决所有问题。跑是能跑,但结果很不稳,同一个模型在长文档上判断很细,到了图片上就含糊,包装上的品牌名和净含量它经常读错,或者干脆回一句「图片未显示相关信息」。
反过来,多模态能力强的模型,让它做文档级的合规判断又不够细,把「医美级修复」这种暗示医疗效果的措辞放了过去。
**这两个活的性质本来就不一样。**文本审查吃的是上下文长度和逻辑推理,要在一万多字的材料里找出字段之间的冲突,还要判断一句宣传语是否踩了广告法的线;图片识别吃的是视觉解析能力,要在包装图上把品牌、品名、型号、净含量读出来,一个字符都不能错。硬塞给一个模型,等于让它同时做两件不擅长的事。
所以方案改成拆开,文本的部分交给 qwen3.8-max,图片的部分交给 qwen3.5-omni-plus,两个模型各管一段,结果在本地合并。
页面顶上那行「一个 key 可以调用多个模型」是这套方案能成立的前提。左侧供应商列了一排,DeepSeek、智谱、MiniMax、Google、xAI、百度都在里面,想找哪家点哪家。
选这两个不是拍脑袋,qwen3.8-max 给到 1000k 上下文,文档级判断需要它,qwen3.5-omni-plus 是 256k 的全模态模型,图片解析归它。第五节会拿三个模型跑同一张图做对比。
二、在蓝耘控制台建一个 Key
蓝耘 MaaS 的入口在 maas.lanyun.net/ ,注册登录后到「API Key 管理」新建一个。
有两点顺手记一下,Key 只在创建那一刻完整显示,关掉页面就看不到了,得当场存好;另外账户得有余额,否则新建的 Key 调不通,会返回一个不太好理解的鉴权错误。这个项目里我从头到尾只用了这一个 Key,蓝耘是统一网关,文本模型和视觉模型共用同一个凭证,不用为每个模型单独申请。
三、改配置:一个 Key,两个模型名
工程原先的配置只有一组三元组,API_KEY、BASE_URL、MODEL,一个模型名走天下,要支持双模型,得把模型名拆成两项。我把模型相关的配置收拢进一块 PROVIDERS 结构,接入地址、凭证变量、文本模型、视觉模型排在一起,换模型只改这一个文件。
关键的几行长这样:
PROVIDERS = {
"lanyun": {
"label": "蓝耘元生代 MaaS",
"short": "蓝耘",
"base_url": "https://maas-api.lanyun.net/v1",
"base_url_env": "LANYUN_BASE_URL",
"key_env": "LANYUN_API_KEY",
"text_model": "qwen3.8-max",
"vision_model": "qwen3.5-omni-plus",
},
}
有个小设计要说明。Key 只从环境变量里读,代码里不出现明文。key_env 指向 LANYUN_API_KEY 这个变量名,真正的值放在 .env 里,仓库里只留一份 .env.example。这样配置结构可以随手改、随手贴,凭证不会跟着代码一起走漏。
另外旧的单模型字段我保留成了 property,指向上面的 text_model,上层代码里原来那些 settings.qwen_model 的调用一行都不用动,改动面收在一个文件里。
模型名是干净的 qwen3.8-max 这种写法,不带路径前缀,配置里写起来不容易出错。
四、跑一遍,看数据
资料准备齐了,六份文档加一张商品包装图,一起传进去。
页头那行「当前引擎:蓝耘元生代 MaaS · qwen3.8-max」是从后端配置里读出来渲染的,不是写死的文案,改配置会跟着变。
点开始之后,前端把整个执行过程流式推出来,每一步都带着耗时落在面板上。
六份文件依次读取,本地解析层先跑完,再把图片送去做多模态识别,最后一步才是大模型语义复核。
完整的一轮跑下来,工具调用明细和模型调用统计都记在过程面板里。
把这轮的数据整理成一张表:
| 项目 | 数值 |
|---|---|
| 模型调用次数 | 2 次 |
| Prompt Tokens | 1654 |
| Completion Tokens | 3747 |
| Total Tokens | 5401 |
| 总耗时 | 86.2 s |
两次调用的分布差异很明显:
| 调用 | 模型 | 耗时 | Total Tokens |
|---|---|---|---|
vision_llm | 蓝耘 · qwen3.5-omni-plus | 3.1 s | 1336 |
text_llm | 蓝耘 · qwen3.8-max | 83.0 s | 4065 |
视觉识别 3.1 秒就回来了,提取出四个可见字段,文本复核花了 83 秒,占总耗时的 96%。这 83 秒是这套流程里最需要提前知道的一件事,它不是在卡,是 qwen3.8-max 要把六份材料的关键字段全过一遍,再逐条判断合规风险,输出 token 有 3676 个,前端有进度事件推着,不会让人觉得程序死了,但第一次跑很容易以为它挂住了。
工具层面还有个对比很有说服力,这一轮总共触发了 12 次工具调用,其中只有 2 次真的消耗了 token:
pdf_parser 解析 01_产品说明书.pdf: 2 页、857 字符 16 ms
pdf_parser 解析 02_产品检测报告.pdf: 3 页、975 字符 17 ms
pdf_parser 解析 03_品牌授权书.pdf: 1 页、543 字符 7 ms
pdf_parser 解析 04_平台商品发布规则.pdf: 3 页、1041 字符 17 ms
markdown_parser 解析 06_商品信息表结构.md: 1 个表格、685 字符 0 ms
markdown_parser 解析 05_待发布商品草稿.md: 1 个表格、443 字符 0 ms
field_extractor 抽取品牌/型号/规格/功效/授权等关键字段 0 ms
vision_llm 蓝耘 · qwen3.5-omni-plus 3.1 s
consistency_checker 比对名称/品牌/型号/规格/生产企业,发现 4 处 0 ms
compliance_checker 扫描绝对化用语与功效证据,发现 11 处 0 ms
authorization_checker 核对授权渠道与有效期,发现 2 处 0 ms
text_llm 蓝耘 · qwen3.8-max 83.0 s
格式解析、字段抽取、一致性比对、合规扫描、授权核对,这些全部跑在本地,耗时都在 20 毫秒以内,一分钱 token 不花。真正必须交给大模型的只有两件事,看图,和判断语义。把能本地做的先做掉,模型只处理它独有的那部分,这是成本最低的分工方式。
模型调用失败时的处理也做了一层兜底。两个客户端在遇到网络异常、限流或者返回格式不对时都返回 None,编排层收到 None 不会抛异常,而是沿用本地规则引擎的结论继续往下走,报告里的引擎来源会如实标出来。
这样一次 API 抖动不至于让整个体检失败,代价是那一轮的语义判断精度会下降,所以结果里必须写清楚是谁给出的结论。
五、三个模型跑同一张图
第四节里视觉那一步选了 qwen3.5-omni-plus,理由是它快,这个判断是测出来的。我用同一张商品包装图,让蓝耘上的三个模型各做一遍同样的识别任务:
| 模型 | 耗时 | Total Tokens |
|---|---|---|
| qwen3.5-omni-plus | 3.4 s | 1336 |
| deepseek-v4.1-flash | 6.0 s | 1403 |
| qwen3.8-max | 17.8 s | 1561 |
同一份凭证下的三个模型,在控制台里是按行分开记的。调用总数、失败次数、最高 TPM、最近调用时间各占一列,qwen3.8-max 那行的调用总数里有 1 次失败,异常返回同样是按模型单独统计的,不用自己再翻日志。
这张图刚打开的时候,Token 消耗总量那栏显示的是 0,看着像调用没被记上。原因是查询周期落在了「最近三小时」,这一轮的调用在窗口之外,把周期拉回到覆盖当天,数字就出来了。对账之前先确认查询周期。
最快和最慢差了 5.2 倍,token 也省了 225 个。三个模型的识别结果倒是一致的,都读出了包装上的品牌、品名、型号和净含量,在这个任务上能力和速度并不同步,qwen3.5-omni-plus 用三分之一的 token 和五分之一的时间做到了同样的准确度。如果当时偷懒让 qwen3.8-max 一肩挑,光图片这一步就要多等 14 秒,而这 14 秒换不来任何额外的识别质量。
这三个模型是同一次对比里换着跑的,中间没有动过接入配置。蓝耘是一个网关,文本模型和视觉模型共用同一个接口地址和同一个 Key,模型名只是请求里的一个参数,脚本里真正切换模型的就一行:
for m in models:
settings.vision_model = m # 只换模型名,地址和 Key 全程没有变
res = analyze_images(payload) # 复用的是工程里生产用的那段调用逻辑
整个循环跑完三个模型,base_url 一直是 https://maas-api.lanyun.net/v1,凭证一直是 LANYUN_API_KEY 这一个变量。换模型不做任何凭证和地址上的动作,这是选型阶段最直接省下来的一笔成本。
第三节那个双模型方案能落得这么轻,也是同一个原因:文本和视觉各选一个模型,背后只有一个网关、一份凭证、一份账单。
速度上也有能拿出来的数字。这次对比里图片识别 3.4 秒返回,和第四节那轮体检记录的 3.1 秒基本一致,两次运行之间差 0.3 秒属于正常波动。这个延迟放进交互式流程是够用的,点一下按钮,图那部分几乎立刻完成。
文本侧那 83 秒看着长,换来的是 3676 个输出 token,折算下来每秒 44 个 token 左右,占时间的是输出量,不是响应本身。同一条链路里,短延迟的和长输出的各用各的模型,这个分工不是拍脑袋定的。
六、判出来的问题长什么样
体检的结论直接给在最前面,风险等级和问题总数一眼能看到,省得人从头翻。
这一轮是高风险,25 个问题,其中高风险 23 个、中风险 2 个、低风险 0 个。
问题按性质分成两类,一类是资料之间对不上。型号不一致,待发布文案写的是 CX-SR-50,说明书里的基准值是 CX-SR-30;净含量不一致,文案写 50 mL,基准值 30 mL。
另外两条来自图片识别,商品名称识别出的是「屏障修护精华」,基准值是「澄序屏障修护精华」,品牌识别出的是「星pure星纯」,基准值是「澄序 CALMORA」。
后两条是这个工具最核心的价值,品牌名和商品名肉眼看着差不多,只有把包装图里的字抠出来和文档逐字比对,才能发现它们根本不是同一个品牌。这两条是蓝耘的 qwen3.5-omni-plus 从包装图上读出来的,再交给本地做一致性比对。这一步纯靠人工看,很容易划过去。
每条问题下面都跟着一句处理建议,比如型号那一条会写明「请将待发布型号修改为基准材料中的 CX-SR-30,或确认基准材料已更新」,净含量那一条同理。给建议而不是只报错误,是因为这两类冲突有两种可能,要么是文案写错了,要么是基准材料该更新了,工具没法替人判断是哪种,只能把两条路都列出来。
另一类是合规风险,比如「3天彻底祛痘」属于绝对化疗效承诺,「医美级修复」涉嫌暗示医疗效果,「孕妇绝对安全」是高风险的安全承诺,「8小时长效保湿」和「敏感期也可放心使用」则缺少对应的证据材料。工具把所有需要人拍板的项单独列了一组。
这一组是 qwen3.8-max 判出来的,它得在六份材料里逐句找绝对化用语和缺证据的功效宣称,这也是整轮体检里最花时间的一步。
这张清单的设计意图是工具不替人下判断。授权渠道和目标渠道对不上、授权已过期这类问题,工具只能指出来,最终要不要发布得由人决定,把「机器判定的结论」和「需要人工确认的事项」分成两块呈现,比给一个笼统的风险分数有用。
七、回到蓝耘控制台对账
跑完一轮想确认调用记录和资源消耗,蓝耘控制台里有现成的,不用自己另外拼。
调用统计能看到每一次请求的时间和成功次数,Token 响应时间曲线里那两个波峰,对应的是几轮测试里耗时较长的文本复核,某次调用失败,可以直接对着时间点去查。这块记录不需要自己在代码里埋点,比自建一套调用日志省事。我换模型的时候主要看的就是它,配置改完之后有没有真的生效,看一眼调用记录就知道了。
结尾
回到开头那二十分钟。按上面这套流程走一遍,现在需要做的是传六个文件、点一次按钮、等一分半,然后看一份分好类的问题清单。
整套东西从头到尾只用了蓝耘的一个账户、一个 Key、一个接口地址。 文本模型和视觉模型都从这个网关里调,要换模型只是改配置里的一行字符串,不需要再申请一份凭证,也不需要改第二处接入地址。第五节那三个模型的对比能顺手做掉,就是因为切换的成本几乎为零。调用记录和用量也按同一个 Key 汇总,模型有没有真的切过去,看一眼记录就知道。
这轮体检花掉 5401 个 token,按 qwen3.8-max 的输入 0.012 元、输出 0.036 元每百万 token 算,成本在一分钱左右。六份材料加一张图,从解析到出结论 86.2 秒。
真正省下来的不是这点时间和这点钱,是它替人守住了那条最容易失守的线:包装图上印着「星pure星纯」,文档里写着「澄序 CALMORA」,这两个名字放在一起,人眼扫一遍是发现不了的。