一、扩展评估标注集 二、在大标注集上寻参 三、(暂时不做,克制,业务发展初期不要做!做通用性强维护成本低的!)coarse rank使用LTR(各个因子做多个非线性映射+FM拟合 pairwise,参考ranknet)
0、得到all_keywords.txt.top1w.shuf.top1k.clothing_filtered(done)
方法1(目前这么做的): 用awk,读取not_clothing.txt作为set,对all_keywords.txt.top1w.shuf.top1k每一行,如果该行在set中,则过滤,得到过滤后的文件,生成文件:all_keywords.txt.top1w.shuf.top1k.clothing_filtered
方法2: scripts/evaluation/queries/all_keywords.txt.top1w.shuf.top1k 这个文件还混杂了一些非“服饰鞋帽”类搜索词,请先做一遍清理。 用llm做剔出,每次输入50条,提示词是: Please filter out the queries from the following list that do not belong to the clothing, shoes, and accessories category. Output the original list of queries, one query per line, without any additional content.
然后将返回的,从原始query剔出。 生成文件:all_keywords.txt.top1w.shuf.top1k.clothing_filtered
一、扩展评估标注集
参考当前的评估框架 @scripts/evaluation/README.md @scripts/evaluation/eval_framework/framework.py @start_eval.sh.sh 当前,是基于54个评测样本(queries.txt),建立了自动化评估的系统,便于发现策略在这个评估集上的效果。
我需要扩大评估样本,使用all_keywords.txt.top1w.shuf.top1k.clothing_filtered(771条)为query集合,走标注流程,从而新建一个标注集。 那么以后eval-web服务,现在的Batch Evaluation按钮,应该支持多个评估集合,左侧的History,也有对应多个评估集合的评估结果,请你考虑如何支持、如何设计。请进行统一的设计,不要补丁式的支持。
统一设计方案(2026-04-17)
先校正一下现状口径:
scripts/evaluation/queries/queries.txt当前仓库里是 53 条非空 query,不是 54 条。scripts/evaluation/queries/all_keywords.txt.top1w.shuf.top1k.clothing_filtered当前是 771 条。
当前实现的问题,不只是 UI 没有下拉框,而是“评估集”这个概念在系统里还不是一等公民:
- 配置层只有一个全局
search_evaluation.queries_file - Web UI 左侧 Queries/History 默认只服务这一份 query 文件
batch_runs/build_runs历史记录没有dataset_id- 产物目录是全局平铺的
batch_reports/、query_builds/ start_eval.sh/start_eval_web.sh/tune_fusion.py都是通过queries_file隐式指定评估集--reset-artifacts现在会清空整套 SQLite + query_builds,多评估集后这个语义会变得危险
所以这里要做的,不是“给 batch API 多传一个文件路径”,而是把“评估集”抽成贯穿配置、存储、API、UI、产物、调参脚本的一层统一模型。
设计目标
- 一个 eval-web 服务同时支持多个评估集。
- Batch Evaluation、History、调参任务都必须明确绑定某个评估集。
- 历史结果必须可追溯到“当时到底用了哪一批 query”,不能因为 query 文件后续变更而失真。
- 相同
(tenant_id, query, spu_id)的标签尽量复用,不因为 query 同时出现在两个评估集里就重复标注。 - 扩展到第三个、第四个评估集时,不需要再改表结构思路或前端交互模型。
核心抽象:区分“评估集”与“标签缓存”
- 评估集(Evaluation Dataset):一组有稳定
dataset_id的 query 集合,用来驱动 build、batch、history、调参。 - 标签缓存(Label Cache):对
(tenant_id, query_text, spu_id)的相关性判断结果。
这两者不要混为一谈。
建议保留现有 relevance_labels / rerank_scores 的“按 query 共享缓存”设计,不按 dataset 拆表,原因:
- 同一个 query 如果同时属于
core_queries和clothing_top771,其(query, spu_id)标签语义本质相同,应该复用。 - 这样新增大评估集时,只需要补齐新 query 的标签,不会对已有 query 重复做 LLM 标注。
- 真正需要 dataset 维度的是:运行历史、构建历史、覆盖率统计、产物归档、UI 选择上下文。
配置设计
把当前单一 queries_file 升级为“评估集注册表”。建议在 config.yaml 中变成:
search_evaluation:
artifact_root: artifacts/search_evaluation
default_dataset_id: core_queries
datasets:
- dataset_id: core_queries
display_name: Core Queries
description: Legacy baseline query set from queries.txt
query_file: scripts/evaluation/queries/queries.txt
tenant_id: "163"
language: en
enabled: true
- dataset_id: clothing_top771
display_name: Clothing Filtered 771
description: 771 filtered clothing/shoes/accessories queries
query_file: scripts/evaluation/queries/all_keywords.txt.top1w.shuf.top1k.clothing_filtered
tenant_id: "163"
language: en
enabled: true
# 保留这些作为全局默认值;dataset 没显式覆盖时继承
batch_top_k: 100
audit_top_k: 100
build_search_depth: 1000
build_rerank_depth: 10000
建议点:
dataset_id是稳定主键,前后端、SQLite、历史记录、调参脚本都只认它,不认文件路径。query_file只是这个 dataset 当前版本的来源,不是外部协议的一部分。- 继续保留全局默认参数;以后如果某个 dataset 需要特殊 top_k / language,再支持局部覆盖。
- 为兼容老脚本,可暂时保留
queries_file,但只作为 fallback,在 loader 里自动转换成一个隐式 dataset;新代码不再直接依赖它。
产物目录设计
当前所有 batch 报告都平铺在 artifacts/search_evaluation/batch_reports/ 下,后面 dataset 一多会很乱。建议改成“共享缓存 + dataset 独立产物目录”:
artifacts/search_evaluation/
search_eval.sqlite3 # 共享标签缓存/共享 rerank 缓存/运行索引
datasets/
core_queries/
batch_reports/
<batch_id>/
report.json
report.md
config_snapshot.json
dataset_snapshot.json
queries.txt
query_builds/
<run_id>.json
audits/
...
clothing_top771/
batch_reports/
<batch_id>/
...
query_builds/
<run_id>.json
audits/
...
重点是每次 batch/build 都要固化 dataset snapshot:
dataset_iddisplay_namequery_filequery_countquery_sha1- 当次实际 queries 副本
queries.txt
这样即使以后 all_keywords...clothing_filtered 文件被重新清洗、条数变化,历史 batch 仍然可复现“当时到底评了哪些 query”。
SQLite / 存储层设计
共享缓存表可以继续保留:
relevance_labels(tenant_id, query_text, spu_id, ...)rerank_scores(tenant_id, query_text, spu_id, ...)query_profiles(tenant_id, query_text, prompt_version, ...)
需要升级的是运行历史表:
build_runs增加dataset_iddataset_display_namedataset_query_filedataset_query_countdataset_query_sha1
batch_runs增加dataset_iddataset_display_namedataset_query_filedataset_query_countdataset_query_sha1
list_batch_runs()/get_batch_run()/insert_batch_run()全部变成 dataset-aware覆盖率统计接口按 dataset 聚合,而不是简单按全库 query 聚合
- 当前
list_query_label_stats(tenant_id)是“全量 query_text 分组” - 以后应该是“给定 dataset_id 后,只统计该 dataset queries 的覆盖情况”
这里建议不要额外把 query 全量写进 SQLite 做注册表主数据,query 主数据仍从 config + query_file 解析即可;SQLite 只负责记录 run 时的 snapshot 元数据。
API 设计
建议把 Web API 升级成以 dataset 为主轴,而不是默认只服务一个 query_file:
GET /api/datasets
返回所有可用评估集:
dataset_iddisplay_namedescriptionquery_countquery_filetenant_idlanguagecoverage_summary
GET /api/datasets/{dataset_id}/queries
返回该 dataset 的 query 列表,以及 dataset 元信息。
POST /api/search-eval
请求体增加可选 dataset_id。
- 单 query 评估本身仍然可以支持任意 query 文本
- 但当页面处于某个 dataset 上下文时,返回里也带上该 dataset 信息,便于 UI 一致展示
POST /api/batch-eval
请求体优先使用 dataset_id,不再默认依赖服务启动时绑定的唯一 query_file。
建议请求模型变成:
{
"dataset_id": "clothing_top771",
"top_k": 100,
"auto_annotate": false,
"language": "en",
"force_refresh_labels": false
}
queries 字段可保留为高级/调试能力,但 UI 主路径和调参脚本主路径都应该走 dataset_id。
GET /api/history?dataset_id=clothing_top771&limit=20
History 默认按当前 dataset 过滤;如有需要再支持 all=true 看全量。
GET /api/history/{batch_id}/report
返回报告时补充 dataset 元信息,前端 report modal 里能看到这是哪个 dataset 的报告。
前端 / eval-web 交互设计
现在左侧栏写死了:
- Queries 来自
queries.txt - History 没有 dataset 维度
建议改成三层结构:
- 左上增加 Dataset Selector
- 下拉框或 tabs,显示
Core Queries (53)、Clothing Filtered 771 (771) - 当前选中的 dataset 决定左侧 query 列表和默认 history 过滤
- Queries 区域绑定当前 dataset
- 标题显示 dataset 名称 + query 数
- 副标题显示 query 文件路径
- 点击 query 触发单 query 评估
- History 区域绑定当前 dataset
- 默认只显示当前 dataset 的 batch history
- 每个 item 显示
dataset badge + batch_id + created_at + query_count + primary metrics - 可选再加一个 “All Datasets” 开关,但默认视角一定要是“当前 dataset”
- 主区 Batch Evaluation 按钮绑定当前 dataset
- 点击时执行当前 dataset 的 batch,而不是对服务启动时唯一 query_file 执行
- 按钮文案建议带上 dataset 名,例如:
Batch Evaluate: Clothing Filtered 771
- 页面顶端增加当前 dataset 概览卡片
dataset_id- query 数
- 已有标签 query 数 / 覆盖率
- 最近一次 batch 时间
这样进入页面时,用户始终知道自己正在看哪个评估集,不会把 53 条基线集和 771 条大集合的结果混在一起。
CLI / 启动脚本设计
需要把 --dataset-id 提升为第一入口参数:
build_annotation_set.py build --dataset-id clothing_top771build_annotation_set.py batch --dataset-id clothing_top771build_annotation_set.py audit --dataset-id clothing_top771serve_eval_web.py serve --dataset-id core_queries
说明:
serve的--dataset-id只决定页面初始选中哪个 dataset,不应该再把整个服务绑定死到一个 query 文件。--queries-file可以保留一段时间做兼容,但内部先解析 registry;如果能映射到某个 dataset,就统一转成dataset_id处理。
start_eval.sh / start_eval_web.sh 也要同步升级:
- 读取
REPO_EVAL_DATASET_ID - 保留
REPO_EVAL_QUERIES兼容模式,但新用法优先REPO_EVAL_DATASET_ID
额外要修正的一点:
- 当前
--reset-artifacts会删整个 SQLite 和整个query_builds/ - 多 dataset 后这个行为太危险
- 应拆成更明确的选项,例如:
--reset-dataset-build-artifacts--purge-shared-label-cache(显式危险操作,默认不要碰)
调参框架联动设计
tune_fusion.py、start_coarse_fusion_tuning_long.sh、resume_coarse_fusion_tuning_long.sh 也必须带 dataset 维度,否则之后同一套 coarse rank 参数可能分别在 53 条集和 771 条集上跑出完全不同的结论,但 leaderboard 会混在一起。
建议:
tune_fusion.py增加--dataset-idsummary.json/leaderboard.csv/trials.jsonl记录dataset_id- 调参时调用 eval-web batch API,也传
dataset_id seed-report如果来自历史 batch 报告,也校验dataset_id一致
迁移方案
建议采用兼容迁移,而不是硬切:
- 先在配置中注册两个 dataset
core_queries->scripts/evaluation/queries/queries.txtclothing_top771->scripts/evaluation/queries/all_keywords.txt.top1w.shuf.top1k.clothing_filtered
- 旧历史记录回填 dataset 元信息
- 如果历史记录没有
dataset_id,且 query 列表 hash 与queries.txt一致,则回填为core_queries - 无法确认的旧记录,标记为
legacy_unknown
UI 默认只展示 registry 中
enabled=true的 dataset保留一段时间旧 CLI 参数,但 README、新脚本、新前端只文档化 dataset 模式
实施顺序
建议按下面顺序做,避免半途出现“后端支持了但前端看不出来”或者“前端能选但历史存不准”:
- 配置层:引入 dataset registry 与解析器
- 公共帮助层:统一的 dataset resolve / snapshot / artifact path helper
- SQLite:
batch_runs/build_runs增加 dataset 元字段 - Framework:
build/batch/audit全面改为 dataset-aware - Web API:新增
/api/datasets,History 支持 dataset filter - eval-web 前端:selector + dataset-scoped queries/history/batch
- 调参脚本:
--dataset-id全链路打通 - README / issue / 运维脚本更新
这套设计的关键点
- “评估集”是显式主键,不再靠文件路径暗示
- “标签缓存”继续按
(tenant_id, query, spu_id)共享复用 - “历史报告”按 dataset 严格隔离并带 snapshot
- “UI 交互”始终围绕当前 dataset 上下文展开
- “调参结果”必须标记 dataset,防止不同集合上的指标被误比
结论
这件事的统一做法,不是给现有单评估集逻辑加几个 if/else,而是把 eval framework 从“单 query 文件模式”升级为“多 dataset registry 模式”。
如果按这套方案落地,后面新增第三个评估集时,应该只需要:
- 在
config.yaml注册一个新 dataset - 跑对应 build
- 在 UI 中选择它做 batch / 看 history
- 在调参脚本里指定
--dataset-id
而不需要再次改数据模型和交互模型。
二、在大标注集上寻参
我以前经过过一轮调参,是基于54个评测样本(queries.txt),过程中发现的最优的参数是这一组: 0.641241 {'es_bias': '7.214', 'es_exponent': '0.2025', 'text_bias': '4.0', 'text_exponent': '1.584', 'text_translation_weight': '1.4441', 'knn_text_weight': '0.1', 'knn_image_weight': '5.6232', 'knn_tie_breaker': '0.021', 'knn_bias': '0.0019', 'knn_exponent': '11.8477', 'knn_text_bias': '2.3125', 'knn_text_exponent': '1.1547', 'knn_image_bias': '0.9641', 'knn_image_exponent': '5.8671'}
这一组参数分布比较极端,text_bias太大(文本项得分事0~1的,加上4被稀释的很大),图片的exponent太大,不过在这个数据集上面确实是最好的,我觉得有过拟合的可能,因此要扩大数据集,先扩展标注集,然后使用扩展的标注集,继续进行寻参。
我已经新建了一个标注集合,请启动寻参任务,把任务跑起来,以后等程序跑完了应该能拿到寻参结果,下次你可以结合程序执行的结果进行结论分析。
以前的一轮调参: 我当时的调参需求:
请对coarse_rank fusion公式进行调参: 目前的baseline是这一组,Primary_Metric_Score: 0.637642: coarse_rank: ... fusion: es_bias: 10.0 es_exponent: 0.05 text_bias: 0.1 text_exponent: 0.35 text_translation_weight: 1.0 knn_text_weight: 1.0 knn_image_weight: 2.0 knn_tie_breaker: 0.3 knn_bias: 0.2 knn_exponent: 5.6 knn_text_bias: 0.2 knn_text_exponent: 0.0 knn_image_bias: 0.2 knn_image_exponent: 0.0 评估指标在/data/saas-search/artifacts/search_evaluation/batch_reports/batch_20260415T150754Z_00b6a8aa3d.md 请以这个为基准,发散思维,进行宽一点的范围调参。因为每次重启、评测都需要几分钟,请写一个调参的框架,基于框架、设定好多组参数、写好脚本,每轮收集效果自动的调整参数分布(因为笛卡尔积、多种参数调参成本太高,因此考虑贝叶斯调参等方法通 过多轮迭代通过脚本自动收敛) 每次调整参数后需要重启backend (有时候重启backend后eval-web好像也挂了,如果有可以追查原因并修复) ./restart.sh backend 注意:请你调试脚本、进行一轮分析,最终要沉淀一套调参脚本,我下次可以重新跑(还是针对这组参数调参),能自动迭代(调整参数分布)、收集每组参数的指标、调优到最优的参数组合。
你给出的调参脚本:
长时间自动调参脚本已经配好,核心文件是:
- 调参主程序:scripts/evaluation/tune_fusion.py
- 宽范围搜索空间:scripts/evaluation/tuning/coarse_rank_fusion_space.yaml
- 后台长跑启动脚本:scripts/evaluation/start_coarse_fusion_tuning_long.sh
- 续跑脚本:scripts/evaluation/resume_coarse_fusion_tuning_long.sh
- 使用说明:scripts/evaluation/tuning/README.md
这套方案不是笛卡尔积穷举,而是“种子实验 + 随机探索 + 基于历史最优分布的自适应采样”反复迭代。搜索范围已经放宽,新增了多组偏离 baseline 很远的 seed,也保留了 baseline 附近抖动,适合长时间慢慢收敛。
直接启动一轮:
./scripts/evaluation/start_coarse_fusion_tuning_long.sh
如果想跑更久一点:
MAX_EVALS=48 BATCH_SIZE=3 CANDIDATE_POOL_SIZE=512 RUN_NAME=coarse_fusion_long_001 \ ./scripts/evaluation/start_coarse_fusion_tuning_long.sh
看日志:
tail -f artifacts/search_evaluation/tuning_launches/.log
看结果目录:
ls artifacts/search_evaluation/tuning_runs//
续跑:
./scripts/evaluation/resume_coarse_fusion_tuning_long.sh
每轮会自动做这些事:
- 生成一批候选 coarse_rank.fusion 参数
- 写入配置并重启 backend
- 检查 eval-web,必要时自愈拉起
- 跑评测并收集 Primary_Metric_Score
- 更新 trials.jsonl、leaderboard.csv、summary.md
- 基于历史结果调整下一轮采样分布
你先跑一轮长任务。跑完后把 run_name 或 scripts/evaluation/tuning/README.md 里对应实验目录发我,我再基于结果做下一步分析和收缩搜索空间。
› 我运行了:MAX_EVALS=400 BATCH_SIZE=3 CANDIDATE_POOL_SIZE=512 RUN_NAME=coarse_fusion_long_001 ./scripts/evaluation/start_coarse_fusion_tuning_long.sh
run_name=coarse_fusion_long_001 pid=2218620 log=artifacts/search_evaluation/tuning_launches/coarse_fusion_long_001.log pid_file=artifacts/search_evaluation/tuning_launches/coarse_fusion_long_001.pid cmd_file=artifacts/search_evaluation/tuning_launches/coarse_fusion_long_001.cmd run_dir=artifacts/search_evaluation/tuning_runs/coarse_fusion_long_001
tail -f artifacts/search_evaluation/tuning_launches/coarse_fusion_long_001.log cat artifacts/search_evaluation/tuning_runs/coarse_fusion_long_001/leaderboard.csv
• 我先看这次长跑的日志和当前排行榜,确认任务是否正常推进、是否有异常中断,以及目前最优参数落在哪个方向。
• Explored └ Read coarse_fusion_long_001.log, leaderboard.csv List coarse_fusion_long_001 Read summary.md
───
• 结果已经足够看出明显趋势了。我再补一层聚合分析,看看 top 区间里哪些参数方向反复出现,避免只盯着单个最优点。
• Ran ps -p 2218620 -o pid=,etimes=,cmd= └ (no output)
• Ran python -
… +61 lines (ctrl + t to view transcript)
knn_image_bias: mean=0.5631 median=0.2000 min=0.0010 max=4.0000
knn_image_exponent: mean=4.6316 median=5.8680 min=0.0000 max=6.0000
• Ran python -
… +30 lines (ctrl + t to view transcript)
10 bo_234 0.641241 {'es_bias': '7.214', 'es_exponent': '0.2025', 'text_bias': '4.0', 'text_exponent': '1.584', 'text_translation_weight': '1.4441', 'knn_text_weight': '0.1', 'knn_image_weight': '5.6232', 'knn_tie_breaker':
'0.021', 'knn_bias': '0.0019', 'knn_exponent': '11.8477', 'knn_text_bias': '2.3125', 'knn_text_exponent': '1.1547', 'knn_image_bias': '0.9641', 'knn_image_exponent': '5.8671'}
这一次因为外部原因(磁盘满)终止了,以上是最好的一组参数。