# comkey **Repository Path**: millionnn/comkey ## Basic Information - **Project Name**: comkey - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-10 - **Last Updated**: 2026-05-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Comkey(Python 版) 将原 Java CompKey 流水线迁移为 Python,按**阶段脚本**组织:从查询日志/分词结果出发,完成中介词提取、共现与权重、竞争候选与竞争度、融合打分与排序,并可选做**时间效率**基准测试。核心算法在 `src/comkey/` 下,阶段入口在 `scripts/`。 --- ## 1. 目录与配置 | 路径 | 说明 | |------|------| | `config/settings.yaml` | `interim_dir`、`processed_dir`、停用词、阶段四黑名单/白名单、`compkey.midkey_num` 等 | | `data/interim/` | 阶段二输入与中间文件(分词 CSV、编码 parquet、词表) | | `data/processed/` | 阶段三、四产出(按种子命名的 CSV、画像 JSON) | | `data/external/` | 停用词、阶段四额外屏蔽词、竞品白名单 YAML 等 | | `src/comkey/` | 编码、CompKey 模型、打分融合、API 等库代码 | | `scripts/` | 阶段一至五入口脚本 | | `src/efficiency/` | 效率基准脚本(阶段二/三/四及端到端) | | `efficiency/results/` | 默认效率结果目录(`timing_*.csv` / `timing_*.png`) | --- ## 2. 环境安装 **要求**:Python 3.10+(与 `requirements.txt` 一致即可)。 ```powershell cd D:\Comkey python -m venv .venv .\.venv\Scripts\Activate.ps1 pip install -r requirements.txt ``` 后续命令均在**项目根目录** `D:\Comkey` 下执行,并设置: ```powershell $env:PYTHONPATH = "D:\Comkey\src" ``` (Linux/macOS:`export PYTHONPATH=项目根/src`) --- ## 3. 运行命令(均在项目根 `D:\Comkey` 执行) ### 3.1 环境与路径 ```powershell Set-Location D:\Comkey $env:PYTHONPATH = "D:\Comkey\src" ``` ### 3.2 阶段一至二(各运行一次) ```powershell python scripts/stage1_prepare_data.py python scripts/stage2_preprocess.py ``` ### 3.3 阶段三至四(20 个种子) 与 `data/external/stage4_competitor_whitelist.yaml` 中主 `seeds` 列表一致,并补充 **建设银行**、**小米**(二者走 `categories` 品类白名单)。**须在阶段二完成后**执行: ```powershell $seeds = @( "美的","海尔","华为","苹果","三星","宝马","电信","京东","淘宝","美团", "茅台","伊利","顺丰","抖音","携程","万科","中国平安","工商银行", "建设银行","小米" ) foreach ($s in $seeds) { python scripts/stage3_compkey_calc.py --seed $s python scripts/stage4_score_hotword.py --seed $s } ``` ### 3.4 效率基准(可选) 效率脚本在 **`src/efficiency/`**。请使用下文路径中的 **`src/efficiency/`**(若写成顶层 `efficiency/` 而仓库中无该目录会找不到文件)。建议将 `src/efficiency` 一并加入 `PYTHONPATH`,以便导入同目录下的 `_bench_common`: ```powershell Set-Location D:\Comkey $env:PYTHONPATH = "D:\Comkey\src;D:\Comkey\src\efficiency" ``` **阶段二效率** ```powershell python src/efficiency/benchmark_stage2.py python src/efficiency/benchmark_stage2.py --sizes 5000,20000,100000 --out-dir D:\Comkey\efficiency\results ``` **阶段三效率** ```powershell python src/efficiency/benchmark_stage3.py --seed 美的 python src/efficiency/benchmark_stage3.py --seed 华为 --sizes 10000,50000,200000 ``` **阶段四效率**(需先有 `data\processed\compkeys_seed_{种子}.csv`) ```powershell python src/efficiency/benchmark_stage4.py --seed 美的 python src/efficiency/benchmark_stage4.py --seed 华为 --sizes 500,2000,10000,50000 ``` **端到端(阶段二 → 四)** ```powershell python src/efficiency/benchmark_pipeline_end_to_end.py --seed 美的 python src/efficiency/benchmark_pipeline_end_to_end.py --seed 伊利 --sizes 5000,20000 ``` 未安装 `matplotlib` 时仍会生成 CSV,仅跳过 PNG。`--sizes` 会在 parquet/compkeys 行长上限内做有效规模去重,见 `src/efficiency/_bench_common.py`。 --- ## 4. 数据前提(必读) ### 4.1 阶段二固定输入 `scripts/stage2_preprocess.py` **固定读取**: `{interim_dir}/cleaned_queries_keywords.csv` - 须含 **`tokens`** 列(空格分隔的分词序列,一行一条「查询」)。 - 该文件通常来自上游实验:从训练/搜索日志抽查询文本后,经 `scripts/run_hybrid_tokenize.py` 或 `scripts/run_glm_tokenize.py` 等分词流水线生成;也可由你方实验一产出后**拷贝/命名**到上述路径。 ### 4.2 阶段一(可选) `scripts/stage1_prepare_data.py` 不读查询正文,仅根据 `settings.yaml` 中路径生成**数据清单与画像**(检查训练集等文件是否存在),用于实验登记。 --- ## 5. 如何运行(推荐顺序) **一键可复制命令(含 20 种子与效率基准)已集中在 §3。** ### 5.1 分阶段执行 ```powershell cd D:\Comkey $env:PYTHONPATH = "D:\Comkey\src" python scripts/stage1_prepare_data.py python scripts/stage2_preprocess.py python scripts/stage3_compkey_calc.py --seed 美的 python scripts/stage4_score_hotword.py --seed 美的 ``` - **`--seed`**:与分词、词表中出现的字符串一致(例如 `美的`、`建设银行`)。阶段三、四均依赖该种子在 `vocab_encode.csv` 中已有 id。 - 更换种子时:**只需重跑阶段三、四**(阶段二为全局编码与词表,一般不必重复)。 ### 5.2 一键执行(默认种子「图片」) ```powershell cd D:\Comkey $env:PYTHONPATH = "D:\Comkey\src" python scripts/run_all.py ``` 默认顺序:阶段一 → 二 → 三 → 四。修改默认种子请编辑 `scripts/run_all.py` 中 `seed = "..."`。 ### 5.3 阶段五(HTTP 服务) ```powershell cd D:\Comkey $env:PYTHONPATH = "D:\Comkey\src" uvicorn comkey.api:app --host 0.0.0.0 --port 10086 ``` - `POST /find`:在线跑中介 + 竞争候选 + 融合打分(读 interim 下 parquet 与词表)。 - `POST /score`、`GET /hotwords`:见 `src/comkey/api.py`。 --- ## 6. 各阶段产出物一览 路径中的 `{interim}`、`{processed}` 以 `config/settings.yaml` 为准(默认 `data/interim`、`data/processed`)。 ### 阶段一 `stage1_prepare_data.py` | 产出 | 说明 | |------|------| | `{processed}/stage1_data_inventory.csv` | 配置中若干数据文件的存在性与大小 | | `{processed}/stage1_profile.json` | 条数、编码假设等元信息 | ### 阶段二 `stage2_preprocess.py` | 产出 | 说明 | |------|------| | `{interim}/cleaned_queries.csv` | 与本次编码输入一致的 `tokens` 文本落盘(便于核对) | | `{interim}/vocab_encode.csv`、`vocab_decode.csv` | 词 ↔ id | | `{interim}/encoded_sequences.parquet` | 每条查询一行,`encoded` 为空格分隔的 id 序列 | | `{processed}/stage2_profile.json` | 阶段二简要画像 | **说明**:编码的**直接输入**是内存中从 `cleaned_queries_keywords.csv` 解析出的分词列表;`cleaned_queries.csv` 为同批数据的导出副本。 ### 阶段三 `stage3_compkey_calc.py --seed <种子>` | 产出 | 说明 | |------|------| | `{processed}/midkeys_seed_{种子}.csv` | 中介词及在「含种子查询」内的词频式统计 `freq` | | `{processed}/midkey_coquery_volume_seed_{种子}.csv` | 每条查询为 1 次:与种子**同条共现**的中介计数 `coquery_volume` | | `{processed}/midkey_weights_seed_{种子}.csv` | 由共现向量归一化得到的**中介权重** `weight` | | `{processed}/compkeys_seed_{种子}.csv` | 竞争候选 id 解码后的 `comp_key` 与 **`competition_score`(竞争度)** | 若词表中无该种子,会写出空表或占位空文件(见脚本内分支)。 ### 阶段四 `stage4_score_hotword.py --seed <种子>` | 产出 | 说明 | |------|------| | `{processed}/score_table.csv` | 人工/业务可调分表(`seed_key, comp_key, score`);缺省时阶段四会创建示例 | | `{processed}/ranked_seed_{种子}.csv` | 过滤停用词等后,按 **`final_score = competition_score × score`** 排序;受 `ranked_top_n` 截断 | | `{processed}/hotwords_top.csv` | 热词相关更新(与 `hotword_num` 等配置相关) | 阶段四可选:`data/external/stage4_competitor_whitelist.yaml` 中 **`seeds`** 精确白名单,或 **`categories`** 按品类共享竞品表(详见该文件头部注释)。 --- ## 7. 实验步骤与实现对照(结论与代码位置) 以下对应你方实验说明中的步骤(原稿步骤编号保留;**无原稿「步骤 7」**,热词/API 可作为扩展)。 ### 7.1 中介关键字提取 **实验要求**:读取实验一数据;通过词频类统计,提取与种子相关的中介关键字;落盘。 **本仓库实现**: - **数据读取**:阶段二将 `cleaned_queries_keywords.csv` 转为整数序列的全表 `data`(内存);阶段三读 `encoded_sequences.parquet` + 全局词表,重建与阶段二一致的 `data`。 - **关联与词频**:对每条查询(分词序列),若含种子 id,则将该行中出现的其它 token 计入中介计数 → `get_midkeys`。 - **输出**:`midkeys_seed_{种子}.csv`(并过滤纯拉丁型号等不宜作展示中介的词,见 `stage3_compkey_calc.py` 与 `compkey_model.normalize_mid_key_label` / `mid_key_is_latin_alphanumeric_only`)。 **核心代码**:`src/comkey/compkey_model.py` 中 `get_midkeys`。 **结论**:中介词 =「与种子出现在同一条分词序列中的共现 token 及其频次」;不是单独再读一份「实验一原始日志」,而是读**已由实验一链路或等价流程得到的、与阶段二一致的分词编码结果**。 --- ### 7.2 搜索量统计(种子 + 中介共现条数) **实验要求**:统计包含种子与中介的查询搜索量。 **本仓库实现**:将**每条编码序列视为 1 次查询**。若某序列中同时出现种子与某中介(各 id 在该序列内去重各计一次),则该中介的 `coquery_volume` 加 1。 **产出**:`midkey_coquery_volume_seed_{种子}.csv`。 **核心代码**:`src/comkey/compkey_model.py` 中 `midkey_seed_coquery_volumes`。 **结论**:此处的「搜索量」= **查询条数**(每条最多贡献 1),不是引擎曝光量;与 CompKey 论文/ Java 版「会话或查询条」统计口径一致。 --- ### 7.3 权重计算 **实验要求**:设计公式并编程,按统计量计算每个中介关键字权重。 **本仓库实现**:在参与统计的中介集合上, \[ w(m)=\frac{\text{coquery\_volume}(m)}{\sum_{m'}\text{coquery\_volume}(m')} \] 与 `get_midkeys` 中的词频 `freq` **解耦**(`freq` 为种子行内 token 出现次数之和;权重仅由共现条数归一化)。 **产出**:`midkey_weights_seed_{种子}.csv`(含 `coquery_volume`、`token_freq_in_seed_rows`、`weight`)。 **核心代码**:`src/comkey/compkey_model.py` 中 `midkey_weights_from_coquery_volumes`。 --- ### 7.4 竞争关键字提取(候选集合) **实验要求**:根据数据提取种子的竞争关键字候选。 **本仓库实现**:取词频最高的 Top `midkey_num` 个中介作「hub」(可过滤动词、纯拉丁型号 hub,见 `get_compkeys`);对每个 hub,在**所有包含该 hub 的查询**中统计其它 token 的共现,再按与 hub、种子相关的式子累加为每个候选 token 的得分并聚合。 **产出**:`compkeys_seed_{种子}.csv`(`comp_key` 为解码后的词,`competition_score` 为聚合后的竞争度,尚未乘业务分)。 **核心代码**:`src/comkey/compkey_model.py` 中 `get_compkeys`(含可选 `semantic_seed_alignment` 对得分做语义贴近度调节,环境变量 `COMPKEY_SIM_LAMBDA` 等)。 **结论**:候选集合是 **统计共现意义**上的「竞争相关词」,不保证全是「品牌竞品名」;阶段四黑名单/白名单用于业务裁剪。 --- ### 7.5 竞争度计算 **实验要求**:设计竞争度公式,以先前步骤结果为输入,存储各候选竞争度。 **本仓库实现**:竞争度在 `get_compkeys` 内对每个 hub-候选对计算并聚合到 `competition_score`(见源码中 `score = (sa / s) * (ak / denom)` 及跨 hub 累加);写入 `compkeys_seed_{种子}.csv`。 **核心代码**:同上 `get_compkeys`。 --- ### 7.6 排序输出 **实验要求**:读取步骤 5 结果,排序输出。 **本仓库实现**:`src/comkey/score_fusion.py` 中 `apply_score`:合并停用词/黑名单/动词过滤等 → 与 `score_table.csv` 左连接得到 `score` → `final_score` → 降序排序;若配置了竞品白名单且过滤后非空,则只保留白名单内词再排序。`ranked_top_n` 控制写出行数。 **产出**:`ranked_seed_{种子}.csv`(列含 `comp_key, competition_score, score, final_score` 等)。 **脚本**:`scripts/stage4_score_hotword.py`。 --- ### 7.7 算法时间效率分析 **实验要求**:在不同长度查询日志下测耗时并绘图。 **本仓库实现**:`src/efficiency/` 下独立脚本(默认结果目录 **`efficiency/results/`**,可用 `--out-dir` 指定,见 **§3.4**)。 | 脚本 | 测量内容 | |------|----------| | `benchmark_stage2.py` | `cleaned_queries_keywords.csv` 前 N 行:读 CSV + `encode_rows` | | `benchmark_stage3.py` | parquet 前 N 条序列 + 全局词表:阶段三 core(`get_midkeys`、共现权重、`get_compkeys`) | | `benchmark_stage4.py` | 已有 `compkeys_seed_{种子}.csv` 前 N 行:`apply_score` | | `benchmark_pipeline_end_to_end.py` | 前缀 N 行:阶段二 → 阶段三 → 阶段四(种子须出现在该前缀词表中,否则该 N 会跳过) | **可直接复制的命令**:见上文 **§3.4 效率基准(可选)**。 - `--sizes`:逗号分隔规模列表;脚本会对**重复 N** 与 **超过 parquet/compkeys 行长后相同的有效 N** 去重,避免图中横坐标重复(见 `src/efficiency/_bench_common.py`)。 - `--out-dir`:可改结果输出目录。 - 若未安装 `matplotlib`,仍会写 CSV,仅跳过 PNG。 **结果如何解读(结论)**: 1. **阶段二**:`read_csv`、`encode_rows`、合计时间应随 `n_token_rows` 大致单调上升;大 N 下编码有时重于读入属正常。 2. **阶段三 / 端到端里的 `get_compkeys`**:第一次触发 **jieba 词性**等路径时会有**冷启动**,首档耗时可能明显高于下一档,**不代表**算法复杂度在 N 增大时反而下降;正式报告建议 warm-up 或丢弃首点。 3. **阶段四**:`apply_score` 随候选行数近似增长;若 `sizes` 中多个值被 `head` 截断到同一行数,去重后只保留一档。 4. **端到端**:词表仅由前缀 N 行构建;若种子在前缀分词中从未出现,该 N 不写结果行,CSV 行数可能少于 `--sizes` 档位数。 **产出**:`timing_*.csv` 与各阶段耗时列;可选 `timing_*.png` 折线图。 --- ## 8. 与 Java 原版的对应关系(简要) | Java | Python | |------|--------| | 预处理与编码相关 | `comkey/preprocess.py`、`comkey/encode.py` | | 竞争词与打分 | `comkey/compkey_model.py`、`comkey/score_fusion.py` | | 服务入口 | `comkey/api.py` | 分词由 HanLP 换为 **jieba**(及可选 GLM 混合分词脚本),统计与排序会有细微差异。 --- ## 9. 常见问题 1. **`gbk` 与路径**:阶段一检查的 `train_file` 等默认按实验环境配置;若本机路径不同,请改 `config/settings.yaml`。 2. **阶段二找不到 CSV**:确认 `cleaned_queries_keywords.csv` 已在 `interim_dir`,且含 `tokens` 列。 3. **阶段三提示种子不在词表**:该词未出现在阶段二所用关键词语料中,需换种子或扩大/调整分词语料。 4. **`ranked` 里出现泛词(如「个人」)**:共现统计使然;配置 `stage4_competitor_whitelist.yaml` 的 `seeds` / `categories` 或扩充 `compkey_stage4_extra.txt` 可收紧结果。 5. **效率脚本 import 失败**:确保 `PYTHONPATH` 含 `src`,且从项目根执行;`_bench_common.py` 内 `PROJECT_ROOT` 指向仓库根以便读取 `config/settings.yaml`。 --- ## 10. API 调用示例 ```bash curl -X POST "http://127.0.0.1:10086/find" -H "Content-Type: application/json" -d "{\"seed\":\"美的\"}" curl "http://127.0.0.1:10086/hotwords" ``` --- ## 11. 测试 ```powershell cd D:\Comkey $env:PYTHONPATH = "D:\Comkey\src" pytest tests ``` (以仓库内实际测试文件为准。)