// Smoke test: verify sanitizeOne() rejects all known-bad inputs // Run with: node /tmp/sanitize_smoke.js const NOISE = /^(让我|用户|我需要|好的|现在|首先|分析|根据|对于|这条|这个|考虑|我们|这里|注意|提示|重要|关键|总结|综上|该|其|它|他们|这些|那些|由于|因为|所以|因此|需要|可能|应该|可以|建议|希望|要求|必须)/ const PROJECT_WORDS = /采购|项目|公司|工程|设备|材料|公告|招标|标段|标段|框架|年度/ function isValid(name) { if (!name) return false const s = name.trim() if (s.length === 0 || s.length > 6) return false if (/[*\->→]/.test(s)) return false if (/[,。:;!?、]/.test(s)) return false if (/[A-Za-z]{2,}/.test(s)) return false if (NOISE.test(s)) return false if (PROJECT_WORDS.test(s)) return false if (/^(中国|钢材|项目|采购|这些|这个|公司|工程|设备)$/.test(s)) return false if (/^[一-龥]+$/.test(s) === false) return false return true } function sanitize(raw) { if (!raw) return '' let s = String(raw).replace(/<\/?think>/g, '').replace(/\*\*/g, '').trim() const lines = s.split('\n').map((l) => l.trim()).filter((l) => l) for (const line of lines) { if (NOISE.test(line)) continue if (line.length > 20) continue if (/[,。:;!?、]/.test(line)) continue const cleaned = line.replace(/^[\d]+[\.、::]\s*/, '').trim() if (!cleaned) continue if (cleaned.includes(' - ') || cleaned.includes(' → ')) { const parts = cleaned.split(/\s*(?:-|→)\s*/).map((p) => p.trim()).filter((p) => p) for (const p of parts) if (isValid(p)) return p continue } if (isValid(cleaned)) return cleaned const m = cleaned.match(/([\u4e00-\u9fa5]{2,6})/) if (m && isValid(m[1])) return m[1] } return '' } const cases = [ ['**合金铝线采购** - 这是**电线电缆**的一种。', '', '老污染样本 — 长度>20 全段被丢'], ['**接地夹管束采购** - 是**管材**或电气配件', '', '同上 含"采购"项目词'], ['钢材', '钢材', '核心品类直接通过'], ['', '', '空'], ['**SVG/无功补偿装置** - 属于电气设备', '', '含英文字母拒绝'], ['钢管采购 — 设备配件', '', '含"采购"项目词'], ['\n\n钢材\n', '钢材', '前后空白被 trim'], ['让我分析一下,这条属于钢材', '钢材', '多行取尾部真品类'], ['钢材\n\n1. 钢材\n2. 管材\n3. 钢材', '钢材', '多行取首行'], ['电力金具', '电力金具', '4字新品类'], ['管材', '管材', '已有品类'], ['设备配件', '设备配件', '4字新品类'], ['标识标牌', '标识标牌', '4字'], ['工程服务', '工程服务', '4字'], ['杂品', '杂品', '2字'], ['中国电建', '', '黑名单单字"中国"包含时拒绝 — 但这是项目名前缀,要拆。修正'], ['配电箱', '配电箱', '3字'], ['阀门', '阀门', '2字'], ['一个非常长的品类名候选', '', '>6 字符拒绝'], ['防火门', '防火门', '3字'], ['建筑材料', '', '含项目词"材料"'], ['五金', '五金', '2字'], ] let pass = 0 let fail = 0 for (const [input, expected, desc] of cases) { const got = sanitize(input) const ok = got === expected if (ok) pass++; else fail++ const flag = ok ? '✓' : '✗' console.log(` ${flag} ${desc}`) if (!ok) { console.log(` input: ${JSON.stringify(input)}`) console.log(` expected: ${JSON.stringify(expected)}`) console.log(` got: ${JSON.stringify(got)}`) } } console.log(`\n${pass}/${pass + fail} passed`) process.exit(fail === 0 ? 0 : 1)