跳到主要内容
IM智引科技

研究 / 外贸与 B2B 增长

AI Skill:关键词聚类与商业/工程/知识意图分类

把第 02 篇手工做的意图分类和聚类固化成可复用 Skill:脚本负责词形规则的确定性判定和聚类的机械合并,模型负责规则覆盖不到的模糊词和 SERP 意图判断,输出可直接导入注册表的 CSV。

BLKTECH 编辑部2026年8月4日12 分钟难度 实战免费Node.jsAI Agent

意图分类分两层:脚本用词形规则表处理 70–80% 的明确词(含 manufacturer 判 commercial、含 specs 判 engineering、含 what is 判 informational),剩余模糊词交给模型看 SERP 结果类型判断。聚类按"意图 + 主题词根"两个维度机械合并,超过 6 个词的组自动标记待拆分。

AI Skill:关键词聚类与商业/工程/知识意图分类

为什么要把这件事做成 Skill

第 02 篇讲了如何用 AI 做意图分类和聚类,但那是一次性的提示词。每次新增一批词,都要重新组织提示词、重新解释判定标准,输出格式也不稳定。

做成 Skill 之后:

  • 判定标准写死在说明书里,每次结果一致
  • 明确的词形规则交给脚本,成本降到零且 100% 可靠
  • 输出格式固定,可以直接导入注册表

关键的分工原则和审计篇一致:

词形规则明确的词交给脚本,规则覆盖不到的模糊词交给模型看 SERP 判断。


一、词形规则能覆盖多少

实测下来,B2B 工业品关键词有 70–80% 可以用词形规则直接判定。剩下的 20–30% 才需要模型判断。

规则表(按优先级从高到低匹配)

优先级 匹配词素 判定 说明
1 manufacturer, supplier, factory, OEM, ODM, wholesale, distributor commercial 明确的供应商寻找意图
2 buy, price, quote, cost, for sale, purchase commercial 明确的采购意图
3 specs, specification, datasheet, dimensions, drawing, technical data engineering 参数查询
4 flow rate, pressure, capacity, voltage, power rating, efficiency engineering 具体参数词
5 for + [场景词], used in, application, suitable for engineering 场景选型
6 vs, versus, compared to, difference between, or informational 对比意图(但见下方例外)
7 what is, how does, how to, why, types of, explained, guide, principle informational 知识学习
8 匹配型号正则(如 [A-Z]{2,4}-?\d{2,4} engineering 型号词

优先级为什么重要:一个词可能匹配多条规则。centrifugal pump manufacturer specifications 同时含 manufacturer(规则1)和 specifications(规则3),按优先级判为 commercial——因为采购意图信号更强。

规则的两个已知例外

例外一:对比词的意图分歧

"centrifugal pump vs gear pump"        → informational(技术对比)
"CP-100 vs CP-200"                     → engineering(同品牌型号选型)
"aquaflow vs [竞品品牌]"                → commercial(供应商对比)

同样是 vs,意图完全不同。脚本无法判断,必须交给模型。

例外二:单纯品类词

"centrifugal pump"          → 意图不明(可能是任何一种)
"industrial pump"           → 意图不明

这类“裸品类词”需要看 SERP 才能判断当前主流意图。


二、Skill 说明书

# Skill:关键词聚类与意图分类

## 何时使用
- 新一批关键词需要分类和聚类
- 竞品词导出后的批处理
- GSC 发现新词需要纳入注册表

## 输入
- 关键词列表(每行一个,纯文本或 CSV)
- 可选:月搜索量数据(用于聚类时判断主词)
- 可选:产品型号列表(提升型号词识别准确率)

## 执行步骤

### Step 1:运行确定性脚本
执行 `scripts/keyword-classify.mjs --input keywords.txt`

脚本输出三部分:
- `classified`:规则明确判定的词(含判定依据)
- `ambiguous`:规则无法判定或匹配多条规则冲突的词
- `clusters`:初步聚类结果(按意图 + 主题词根)

### Step 2:处理 ambiguous 词(你来判断)

对每个模糊词,按以下顺序判断:

**方法一:看词的结构**
- 含品牌名对比 → commercial
- 含自家型号对比 → engineering
- 含品类对比 → informational

**方法二:看 SERP 结果类型(最可靠)**
如果你有搜索结果数据或能访问搜索,检查该词的前 5 个结果:
- 多为公司产品页/报价页 → commercial
- 多为技术规格页/参数表/选型指南 → engineering
- 多为 Wikipedia/博客/教育网站 → informational

**方法三:无法判断时的默认规则**
裸品类词(如 "centrifugal pump")默认判为 commercial,
归属 Pillar 页——因为 Pillar 页承接品类大词是架构设计的既定安排。

### Step 3:审核聚类结果(你来判断)

脚本的聚类是机械的(按词根匹配),需要人工审核:

**拆分判断**
- 组内词数 > 6 → 检查是否应拆成两个页面
- 判定标准:组内是否存在两个明显不同的子主题
  例:"centrifugal pump chemical" 组里同时有
  "for acid transfer" 和 "for solvent transfer" →
  可以合并(都是化工输送),不拆
  例:"centrifugal pump material" 组里同时有
  "SS316 selection" 和 "casting process" →
  应拆(一个是选型,一个是制造工艺)

**合并判断**
- 组内只有 1 个词 → 检查是否应并入邻近组
- 判定标准:该词是否值得单独一个页面
  月搜索量 < 50 且非高价值商业词 → 建议并入邻近组

### Step 4:为每组分配 page_type 和建议 slug

按意图映射:
- commercial + 品类词 → pillar
- commercial + 型号词 → cluster-sku
- engineering + 型号词 → cluster-sku
- engineering + 场景词 → cluster-app
- informational → cluster-resource

slug 命名规范(第 04 篇):全小写、连字符、含主词、不含停用词。

### Step 5:输出可导入注册表的 CSV

## 输出格式

第一部分:分类统计

关键词分类报告

输入词数:[N] 脚本判定:[N]([N]%) 模型判定:[N]([N]%)

意图分布:

  • commercial:[N] 词
  • engineering:[N] 词
  • informational:[N] 词

聚类结果:[N] 组 → [N] 个建议页面 待拆分组:[N] 待合并组:[N]


第二部分:聚类明细

聚类结果

组 1:/products/centrifugal-pumps/(pillar)

意图:commercial 主词(PKW):centrifugal pump manufacturer(月搜索量 880) 次级词(SKW):

  • centrifugal pump supplier(320)
  • industrial centrifugal pump OEM(140)
  • centrifugal pump factory(90) 判定依据:脚本规则 1(含 manufacturer/supplier/OEM/factory)

组 2:/applications/centrifugal-pump-chemical-transfer/(cluster-app)

意图:engineering 主词:centrifugal pump for chemical transfer(210) 次级词:

  • chemical transfer pump selection(85)
  • corrosion resistant centrifugal pump(60) 判定依据:脚本规则 5(for + 场景词)

第三部分:CSV 导出
```csv
keyword,intent_type,page_slug,page_type,pkw,skw,priority,decided_by
centrifugal pump manufacturer,commercial,/products/centrifugal-pumps/,pillar,centrifugal pump manufacturer,"centrifugal pump supplier;industrial centrifugal pump OEM",5,script
centrifugal pump vs gear pump,informational,/blog/centrifugal-vs-gear-pump/,cluster-resource,centrifugal pump vs gear pump,,2,model

decided_by 字段记录是脚本还是模型判定的——便于后续追溯和 校准规则表。

第四部分:需人工确认项

## 需人工确认([N] 项)

### 1. "centrifugal pump" (裸品类词,月搜索量 2400)
- 已按默认规则判为 commercial → /products/centrifugal-pumps/
- 建议:搜索该词确认 SERP 主流意图,如多为知识类结果,
  考虑改判 informational 并新建 /blog/centrifugal-pump-explained/

### 2. "pump repair service" (月搜索量 170)
- 判定:commercial,但与现有业务范围不符
- 建议:确认是否提供维修服务。不提供则从词库剔除,
  并加入所有 Commercial 页面的 NKW

禁止行为

  • 不要跳过脚本直接用模型分类全部词(成本高且不一致)
  • 不要为月搜索量 < 20 的词单独建组(除非是高价值商业词)
  • 输出的 CSV 必须包含 decided_by 字段
  • 不要自动写入注册表(输出 CSV 供人工审核后导入)

---

## 三、确定性脚本

```javascript
// scripts/keyword-classify.mjs
import fs from 'fs/promises';

// ── 词形规则表(按优先级排序,先匹配的优先) ──
const RULES = [
  {
    priority: 1,
    intent: 'commercial',
    terms: ['manufacturer', 'supplier', 'factory', 'oem', 'odm',
            'wholesale', 'distributor', 'exporter'],
    note: '供应商寻找意图',
  },
  {
    priority: 2,
    intent: 'commercial',
    terms: ['buy', 'price', 'quote', 'cost', 'for sale', 'purchase'],
    note: '采购意图',
  },
  {
    priority: 3,
    intent: 'engineering',
    terms: ['specs', 'specification', 'datasheet', 'data sheet',
            'dimensions', 'drawing', 'technical data', 'catalogue', 'catalog'],
    note: '参数查询',
  },
  {
    priority: 4,
    intent: 'engineering',
    terms: ['flow rate', 'pressure', 'capacity', 'voltage', 'power rating',
            'efficiency', 'head', 'rpm', 'npsh', 'viscosity'],
    note: '具体参数词',
  },
  {
    priority: 5,
    intent: 'engineering',
    patterns: [/\bfor\s+\w+/i, /\bused in\b/i, /\bapplication\b/i,
               /\bsuitable for\b/i],
    note: '场景选型',
  },
  {
    priority: 6,
    intent: 'AMBIGUOUS',   // 对比词意图分歧,交给模型
    terms: ['vs', 'versus', 'compared to', 'comparison',
            'difference between', 'better than'],
    note: '对比词,需模型判断对比对象类型',
  },
  {
    priority: 7,
    intent: 'informational',
    terms: ['what is', 'how does', 'how to', 'why', 'types of',
            'explained', 'guide', 'principle', 'working', 'meaning',
            'introduction', 'basics'],
    note: '知识学习',
  },
];

// 型号词正则(可根据实际型号命名规则调整)
const MODEL_PATTERN = /\b[A-Z]{1,4}[-\s]?\d{2,4}[A-Z]{0,3}\b/;

// 停用词(聚类时忽略)
const STOPWORDS = new Set([
  'the', 'a', 'an', 'for', 'of', 'in', 'on', 'to', 'and', 'or',
  'with', 'best', 'top', 'good', 'china', 'chinese',
]);

function classify(keyword) {
  const kw = keyword.toLowerCase().trim();

  // 型号词优先判 engineering(除非同时含 commercial 词素)
  const hasModel = MODEL_PATTERN.test(keyword);

  for (const rule of RULES) {
    let matched = false;
    let matchedTerm = null;

    if (rule.terms) {
      matchedTerm = rule.terms.find(t => kw.includes(t));
      matched = Boolean(matchedTerm);
    }
    if (!matched && rule.patterns) {
      matched = rule.patterns.some(p => p.test(kw));
      matchedTerm = 'pattern match';
    }

    if (matched) {
      return {
        intent: rule.intent,
        rule: rule.priority,
        matchedTerm,
        note: rule.note,
        hasModel,
      };
    }
  }

  // 无规则匹配:型号词判 engineering,其余标为模糊
  if (hasModel) {
    return {
      intent: 'engineering',
      rule: 8,
      matchedTerm: 'model number',
      note: '型号词',
      hasModel: true,
    };
  }

  return {
    intent: 'AMBIGUOUS',
    rule: null,
    matchedTerm: null,
    note: '无规则匹配,需模型判断(可能是裸品类词)',
    hasModel: false,
  };
}

// ── 聚类:按 意图 + 主题词根 ──
function extractRoot(keyword) {
  // 去停用词,取剩余词的排序组合作为词根
  const tokens = keyword.toLowerCase()
    .replace(/[^a-z0-9\s-]/g, '')
    .split(/[\s-]+/)
    .filter(t => t && !STOPWORDS.has(t));

  // 去掉意图标识词(这些词不构成主题差异)
  const INTENT_TERMS = new Set([
    'manufacturer', 'supplier', 'factory', 'oem', 'wholesale',
    'specs', 'specification', 'datasheet', 'dimensions',
    'what', 'is', 'how', 'does', 'guide', 'explained',
    'buy', 'price', 'quote', 'vs', 'versus',
  ]);

  return tokens.filter(t => !INTENT_TERMS.has(t)).sort().join('-');
}

// ── 主流程 ──
const inputPath = process.argv.includes('--input')
  ? process.argv[process.argv.indexOf('--input') + 1]
  : 'keywords.txt';

const raw = await fs.readFile(inputPath, 'utf8');
const keywords = raw.split('\n')
  .map(l => l.trim())
  .filter(Boolean)
  // 支持 "keyword,volume" 格式
  .map(l => {
    const [kw, vol] = l.split(',');
    return { keyword: kw.trim(), volume: vol ? Number(vol) : null };
  });

const classified = [];
const ambiguous = [];

for (const { keyword, volume } of keywords) {
  const result = classify(keyword);
  const entry = { keyword, volume, ...result, root: extractRoot(keyword) };
  if (result.intent === 'AMBIGUOUS') ambiguous.push(entry);
  else classified.push(entry);
}

// 聚类:按 intent + root 分组
const clusterMap = new Map();
for (const entry of classified) {
  const key = `${entry.intent}|||${entry.root}`;
  if (!clusterMap.has(key)) clusterMap.set(key, []);
  clusterMap.get(key).push(entry);
}

const clusters = [...clusterMap.entries()].map(([key, members]) => {
  const [intent, root] = key.split('|||');
  // 主词:搜索量最高的,无量则取最短的(通常最核心)
  const sorted = [...members].sort((a, b) => {
    if (a.volume != null && b.volume != null) return b.volume - a.volume;
    return a.keyword.length - b.keyword.length;
  });
  return {
    intent,
    root,
    memberCount: members.length,
    pkw: sorted[0].keyword,
    skw: sorted.slice(1).map(m => m.keyword),
    totalVolume: members.reduce((s, m) => s + (m.volume ?? 0), 0),
    needsSplit: members.length > 6,
    needsMerge: members.length === 1,
  };
});

clusters.sort((a, b) => b.totalVolume - a.totalVolume);

console.log(JSON.stringify({
  summary: {
    inputCount: keywords.length,
    scriptDecided: classified.length,
    modelNeeded: ambiguous.length,
    scriptCoverage: ((classified.length / keywords.length) * 100).toFixed(1) + '%',
    intentDistribution: {
      commercial: classified.filter(c => c.intent === 'commercial').length,
      engineering: classified.filter(c => c.intent === 'engineering').length,
      informational: classified.filter(c => c.intent === 'informational').length,
    },
    clusterCount: clusters.length,
    needsSplit: clusters.filter(c => c.needsSplit).length,
    needsMerge: clusters.filter(c => c.needsMerge).length,
  },
  classified,
  ambiguous,   // 交给模型处理
  clusters,
}, null, 2));

四、校准规则表

decided_by 字段的用途在这里体现:跑几轮之后,回看模型判定的词,如果发现某类词反复被模型判为同一意图,就把它加进脚本规则表。

校准流程

1. 累积 3–5 批词的分类结果
2. 筛选 decided_by=model 的词,按模型判定的 intent 分组
3. 找出组内的共同词素(如反复出现的 "certified"、"approved")
4. 如果某词素在同一意图下出现 ≥ 5 次 → 加入规则表
5. 重跑历史词库验证新规则不会造成误判

规则表覆盖率从 70% 提升到 85% 以上后,模型调用成本会显著下降。


五、与第 02 篇的关系

第 02 篇 本篇
形式 一次性提示词 可复用 Skill
分类方式 全部交给模型 脚本 70–80% + 模型 20–30%
输出稳定性 每次可能不同 格式固定
成本 每次全量调用模型 只对模糊词调用
适用场景 首次建注册表 持续运营中的批量增词

第 02 篇解决“从零开始”,本篇解决“持续运营”。首次建注册表用第 02 篇的流程更快,之后的日常增词用这个 Skill。


→ AI Skill:Meta 标签批量生成(基于注册表字段)

NEXT ACTION / 下一步

继续系列:AI 外贸站建设全系列

把读到的方法变成一个小行动,完成后再回来迭代。

继续

RELATED / 相关推荐

接着读这些

按同一分类、系列与标签为你挑选。