Nodes/ComfyUI-QING/向量匹配丨分类
ComfyUI Node

向量匹配丨分类

Free text into a fixed category list, via embeddings — and the setup it quietly demands

By sheengoa·Created about a year ago·Updated 19 days ago· 16
向量匹配丨分类
    • 类目
    • 分数
    • 状态
    • 匹配层级
    • 匹配ID
    • 总类目
    • 调试信息
    user_text
    model_name_or_pathbge-base-zh-v1.5
    vectors_path
    meta_path
    top1_threshold0.38
    gap_threshold0.03
    level3_gap_threshold0.010
    level2_gap_threshold0.008
    level1_gap_threshold0.005
    return_topk3
    enable_query_fusiontrue
    raw_query_weight0.20
    keyword_query_weight0.50
    industry_query_weight0.30
    rules_path
    rules_profile

    Here's the problem VectorMatcher solves: you have a fixed list of categories - say a storefront taxonomy with levels like 餐饮行业 → 中式正餐 → 高端酒楼 - and users keep typing free-form text that doesn't match any of them exactly. "我晚上想吃个高端点的粤菜馆" is not equal to any category name. VectorMatcher embeds both sides, measures semantic similarity, and maps the loose text onto your whitelist with a confidence score.

    It's the most ambitious node in this pack's data tools, and the one that demands the most setup. Be warned up front: unlike the rest of QING, this node will not just work out of the box.

    How it works

    At runtime, three things have to exist:

    1. A sentence-transformers model (default bge-base-zh-v1.5) to embed the query. The node looks for it in ComfyUI's models/embeddings directory, or hands the name to sentence-transformers, which downloads it from HuggingFace on first use.
    2. A precomputed index: vectors.npy (embedding vectors, one per category) plus meta.json (the category rows). By default these are read from the pack's data/vectors.npy and data/meta.json.
    3. The rules config (optional) that powers query fusion.

    The query gets a Chinese retrieval-instruction prefix (the standard BGE usage pattern: "为这个句子生成表示以用于检索相关文章:"), gets embedded, and the node computes cosine similarity against every category vector. Then it makes a hierarchical decision - it checks the best category, then aggregates up to level 3, level 2, level 1 - and each level must clear two bars to be accepted: a top-1 score at or above top1_threshold (default 0.38) and a gap between the best and second-best candidate at or above a gap threshold (default 0.03, with tighter per-level values). Output status reflects the outcome: 命中 (ok), 未命中 (no_match), 模糊 (ambiguous), or 错误 (error).

    Query fusion (on by default) builds three weighted query variants - raw, keyword, and industry - from the rules profile and blends their scores, so a storefront-style query matches on category and on its industry/keyword aliases. If no rules file exists, it silently falls back to a single raw query (and warns in the console).

    The honest setup cost

    This is where people get burned. The pack ships only data/storefront_categories.json.example - an example taxonomy, not a built index. There is no vectors.npy and no meta.json in the repo. So for VectorMatcher to return anything but an error, you need to:

    • Install sentence-transformers yourself - it is not in the pack's requirements.txt (that lists Pillow, opencv, scipy, scikit-image, cairosvg, openai).
    • Build your index from your own category list using the companion ConvertDataToVectors node (which turns a category JSON like the example into vectors + meta).
    • Have the embedding model reachable - either in models/embeddings or via a working HuggingFace download.

    The error output is actually decent about this: a failure returns empty 类目, score 0, status 错误 (error), and the 调试信息 output with the traceback and the resolved file paths. Read that output before anything else.

    Inputs and outputs

    • user_text (required) - the free text to classify.
    • model_name_or_path - the embedding model (dynamically lists models found in your embeddings dirs).
    • vectors_path / meta_path - where your built index lives; defaults to the pack's data/ paths.
    • top1_threshold, gap_threshold, level1/2/3_gap_threshold - the acceptance bars. Lower top1_threshold if matches keep coming back "no match".
    • return_topk - how many candidates feed the decision (default 3).
    • enable_query_fusion, raw_query_weight, keyword_query_weight, industry_query_weight - blending weights for the three query variants.
    • rules_path, rules_profile - optional rules config and profile for query fusion.
    • Outputs: 类目 (category name), 分数 (score), 状态 (status text), 匹配层级 (category/level3/level2/level1), 匹配ID (category id), 总类目 (full joined level path), 调试信息 (JSON debug).

    Installing it

    VectorMatcher ships in ComfyUI-QING:

    cd ComfyUI/custom_nodes
    git clone https://github.com/GAO-SHIQING/ComfyUI-QING
    cd ComfyUI-QING
    python install_dependencies.py
    

    Then, separately, the node's real dependency:

    cd ComfyUI-QING
    pip install sentence-transformers
    

    Restart ComfyUI. ComfyUI Manager users: install "ComfyUI-QING" from the GUI, then add sentence-transformers manually.

    Troubleshooting

    • Status 错误 (error) and 调试信息 mentions "sentence-transformers 导入失败". That's the missing package above.
    • Debug shows missing vectors.npy. You haven't built an index. Run your category list through ConvertDataToVectors first; the example file shows the expected schema.
    • Everything returns 未命中. Your top1_threshold (0.38 default) is probably too high for your category set - cosine scores for weak categories sit lower. Drop it to ~0.25–0.3 and re-test.
    • 模糊 (ambiguous). Best score cleared the bar but the gap to the runner-up didn't. Tighten your taxonomy so categories are more distinct, or lower gap_threshold.

    This is genuinely the right tool for "classify loose text into a fixed list" - the kind of job an LLM does sloppily and expensively per call. Just budget the setup time, because the node assumes you read its companion ConvertDataToVectors and built an index first.

    CategoryQING/数据工具

    Inputs (16)

    NameTypeDefaultDescription
    user_textSTRING
    model_name_or_pathoptCOMBObge-base-zh-v1.51 options: bge-base-zh-v1.5
    vectors_pathoptSTRING
    meta_pathoptSTRING
    top1_thresholdoptFLOAT0.380–1
    gap_thresholdoptFLOAT0.030–1
    level3_gap_thresholdoptFLOAT0.0100–1
    level2_gap_thresholdoptFLOAT0.0080–1
    level1_gap_thresholdoptFLOAT0.0050–1
    return_topkoptINT31–20
    enable_query_fusionoptBOOLEANtrue
    raw_query_weightoptFLOAT0.200–1
    keyword_query_weightoptFLOAT0.500–1
    industry_query_weightoptFLOAT0.300–1
    rules_pathoptSTRING
    rules_profileoptSTRING

    Outputs (7)

    NameTypeDescription
    类目STRING
    分数FLOAT
    状态STRING
    匹配层级STRING
    匹配IDSTRING
    总类目STRING
    调试信息STRING