上线后第一次实战(企微销售发图出报价)暴露三个断点,本次升级全部修复。证据链:
.bin 无后缀 → 当时人肉判断是 JPEG 后手动 cp 成 .jpg 才跑usage.prompt_tokens_details.image_tokens 统计恒为 0(网关统计 bug)。今后禁止以 image_tokens==0 判断图片未送达;禁止换模型;GLM-5.3-flash 是唯一主力walls/柜高 → 页面重算口径 ≠ 服务端口径(已在 c45b0ef 修过一次,回归测试要锁死)/opt/data/floorplan-quotation/skill/(仓库 /opt/data/floorplan-quotation,remote main 可推)https://api.fmode.cn/v1/chat/completions,key 从 /opt/data/config.yaml 的 model.api_key 读glm-5.3-flash(思考型:正文可能空,兜底读 reasoning_content;max_tokens ≥ 8192;JSON 需截断修复,已有 repairJSON)/opt/data/tools/pwtest/send_wecom_doc.py(adapter 直发,已验证)。公告文字用 /opt/hermes/.venv/bin/hermes send --to "wecom:wrbAdKCAAAUkSbMbznGGG2wt4VoZtVNA" "..."/opt/data/tools/pwtest/verify_report.js,browsers 在 /opt/data/tools/pwtest/browsers(环境变量 PLAYWRIGHT_BROWSERS_PATH)/opt/data/floorplan-quotation-testdata/sample1_shidaichengzhi_q1.jpg(110㎡ 营销图,无尺寸标注)/opt/data/cache/images/img_83594a936f27.bin(63KB JPEG,.bin 后缀!两室两厅,含 6840/7230/2200/2950/2520/1400 尺寸线)export FMODE_API_KEY=$(python3 -c "import re;print(re.search(r'api_key:\s*(\S+)', open('/opt/data/config.yaml').read()).group(1))")sniffImageMime(buf):读文件头 magic bytes → jpeg(FFD8FF)/png(89504E47)/webp(RIFF..WEBP)/gif/gif87a/gif89a/bmp(BM)loadDocument() 与 imageToDataUrl():扩展名未知(.bin/.tmp/无后缀)或 mime 为 application/octet-stream 时,用 magic bytes 决定 MIME;识别不了再报错isPDF 已有 sniff,保持;补充:dataURL 一律带正确 mime.bin 与无后缀两个文件,loadDocument 均应得到 data:image/jpeg;base64,...z-ai/glm-5.3-flash、glm-5.3(同为 GLM 族,仍然禁止非 GLM 模型),成功后把生效模型名写入返回值 analysis._modelassessQuality(rec):返回 { ok, score, reasons[] }。计分:有尺寸线直读(+2/条, 上限4)、柜体 confidence≥0.7(+1/个,上限3)、识别到厨房(+1)、柜体数≥3(+1);总分≤2 或 柜体全部 confidence<0.5 → ok:falsequote 在 ok:false 时:stderr 打印「⚠️ 识别质量低(原因),建议销售补充:户型总尺寸/各房间宽深/柜体位置」且退出码 3;--force 可跳过fpc auto新增子命令:
fpc auto <企微附件路径或任意图片/PDF> \
--client "称呼" --note "销售原话" [--tier standard] [--material PET] [--float 15] \
[--out 报告路径] [--announce 报告路径] # --announce: 输出一段可直接群发的 Markdown 公告到指定文件
流程:sniff 识别 → quote 管线(内部已含质量门)→ 生成报告 → 自动触发 Playwright 触屏回归(调 /opt/data/tools/pwtest/verify_report.js,任何 STEP 失败则整体失败)→ 生成公告 Markdown(含:图纸概况、到手价、区间、明细行、文件路径、功能提示)→ 打印 JSON 摘要 {quote:{...}, report, announce, quality}
.bin 嗅探:loadDocument 对无后缀 JPEG 返回正确 dataURL 前缀c45b0ef 的修复):renderReport 产出的 HTML 里 window.__Q__ 的 cabinets JSON 必须含 厨房 walls 数组且各柜 height 与 dims 解析值一致(用正则从 HTML 提取 window.__Q__ = {...}; 解析断言)fpc auto 优先;写明企微 .bin 兼容已内置;写明质量门行为(退出码 3 时该问销售要什么);明确「模型固定 glm-5.3-flash(GLM 族回退),禁止换非 GLM 模型;image_tokens 网关恒 0 不是失败信号」cd /opt/data/floorplan-quotation/skill && node test/run.js 全过(≥16 项)export FMODE_API_KEY=... && node bin/fpc.js auto /opt/data/cache/images/img_83594a936f27.bin --client "测试客户" --note "实战回归" --out /tmp/regress.html 跑通且质量门 ok(该图有完整尺寸线,score 应≥6);报告里至少 4 组柜体、次卧衣柜 2.95m 尺寸线直读/opt/data/tools/pwtest/verify_report.js 验证 /tmp/regress.html:页面首屏价 == CLI 到手价(关键:厨房 L 型口径一致)路径:changelog/user/2026-09-01-企微实战复盘与v2升级.md
销售在企微发来户型图(63KB JPEG,缓存为 .bin 无后缀)+ "做下这个户型报价单"。
| # | 根因 | 影响 |
|---|---|---|
| 1 | parse.js 只认扩展名,不嗅探 magic bytes;企微缓存文件无后缀 | 一进来就靠人肉 cp 才能跑 |
| 2 | 网关 usage.prompt_tokens_details.image_tokens 恒为 0(统计 bug),被当成"图片未送达"的失败信号;代码与人肉判断都踩了同一个坑 | 误判 → 违规换模型 → 人肉重建,浪费 10+ 轮 |
| 3 | 无识别质量门:尺寸全默认值、confidence 全低的报价单照样出街 | 差点把垃圾报价发到客户群 |
| 4 | 无一键流水线:sniff→quote→验证→公告 全靠 agent 手工粘合 | 交互来回,速度慢、易错 |
| 5 | (已在 c45b0ef 修)报告内嵌状态丢 walls/柜高 |
页面口径与服务端不一致 |
fpc auto 一键流水线:附件→识别→报价→Playwright 触屏回归→群发公告 Markdown→JSON 摘要fpc auto,不许人肉拆步骤;群发走 send_wecom_doc.py