在
search_eval/下新建的自包含模块。用写死的 4 组 query(不走动作×类型正交矩阵选词), 对每组 query 做「同义扩展 + 多渠道搜索 + 合并去重 + LLM 评分」,并提供一个去掉矩阵的查看界面。不改动任何原
search_eval/文件——搜索/评估引擎全部import复用,server/index 是复制后改造。
4 组写死的 query(产品名 + 意图词)
│ 产品名锁死,只对意图词扩同义(评测→测评/实测/体验;案例→作品/效果/实例)
▼
每组多措辞 × 3 渠道(xhs/x/gzh) 各搜 10 条
│ search_all 内建按 (platform, cid) 去重 + found_by_queries 记录命中措辞
▼
合并去重后的帖子池 → 视频转写 → LLM 多模态评分(同 search_eval 的 rubric)
▼
runs_full/q000N/form_A.json → server.py(:8770) 卡片界面浏览/筛选/排序/工序提取
与原 batch_3forms.py 的区别:不生成 query、不做 A/B/C 三形式对比,只用固定 4 组 query 直接搜,单一形式(沿用 form_A 字段名让前端零改动)。
fixed_query_eval/
├── run_search.py ★ 生产脚本:固定 query + 同义扩展 + 合并去重 + 评分 → runs_full/
├── tool_extract.py ★ 工具解构:帖子 → 结构化工具知识条目(gemini-3.1-flash-lite)
├── server.py 查看后端(复制自 ../server.py + 加 sys.path + 工具解构端点;矩阵自动降级)
├── index.html 查看前端(删正交矩阵 + 4-query 选择条 + 工具解构按钮/弹层/详情 tab)
├── runs_full/ 产出目录
│ └── q000N/
│ ├── form_A.json 搜索+评分结果
│ └── tools/{case_id}.json 工具解构结果(每帖一份)
└── README.md 本文件
全部集中在 run_search.py 顶部常量,改完直接重跑:
QUERIES = [
{"id": "q0000", "product": "GPT image2", "intent": "评测"},
{"id": "q0001", "product": "GPT image2", "intent": "案例"},
{"id": "q0002", "product": "nano banana pro", "intent": "评测"},
{"id": "q0003", "product": "nano banana pro", "intent": "案例"},
]
INTENT_SYNONYMS = {
"评测": ["评测", "测评", "实测", "体验"], # 产品名 + 这些词分别搜,再合并去重
"案例": ["案例", "作品", "效果", "实例"],
}
DEFAULT_PLATFORMS = "xhs,x,gzh"
DEFAULT_MAX_COUNT = 10 # 每条措辞每渠道取帖数(默认 10,控制成本)
加产品 / 加意图词:往
QUERIES加条目即可;新意图词记得在INTENT_SYNONYMS配同义(没配则原样单条搜)。
cd examples/process_pipeline/script/search_eval/fixed_query_eval
# ① 跑搜索 + 评分(已存在 form_A.json 的 query 默认跳过)
python run_search.py # 全部 4 组
python run_search.py --only-q q0,q2 # 只跑指定
python run_search.py --force # 覆盖重跑
python run_search.py --no-eval # 只搜不评分(省钱,验证召回用)
# ② 起查看界面(端口 8770,与原 search_eval server 同端口,别同时开)
python server.py # http://0.0.0.0:8770
run_search.py 主要参数:--platforms --max-count --eval-model(默认 gemini-flash-lite)
--max-concurrent --no-transcribe --no-images --only-q --force。
复用原 search_eval 界面的全部功能,只去掉正交矩阵:
接口(与原 server 一致):GET /api/data、POST /api/generate_procedure、POST /api/reeval、GET /api/procedure_status、GET /api/procedure_log。
把帖子(正文 + 配图)里提到的工具,用 gemini-3.1-flash-lite 提炼成结构化条目,每个工具一条。
两个入口:
解构结果字段(每个工具):工具名称 / 实质作用域 / 形式作用域 / 创作层级(制作层·创作层)/ 来源链接 / 输入 / 输出 / 用法 / 案例 / 缺点 / 最新更新时间。null 字段在 UI 自动省略。
实现要点:
tool_extract.py 单次多模态 LLM 调用(正文 + 配图),比工序解构(多轮 agent)轻得多;复用引擎的收图 / 帖子格式化 / JSON 重试封装。google/gemini-3.1-flash-lite(build_eval_llm_call("gemini-flash-lite"),OpenRouter 后端);评分筛选用的也是 OpenRouter,与之一致。runs_full/{q}/tools/{case_id}.json,已解构默认跳过(详情页「重新解构」可强制覆盖)。tool_extract.py(同工序解构模式),LLM 重依赖留子进程,server 本身保持轻量。相关接口:POST /api/extract_tools {q, case_ids[], force?}、GET /api/tools_status?q=&case_id=、GET /api/tools_data?q=&case_id=。
手动跑(一般由界面触发):
python tool_extract.py --q q0000 --case-ids xhs_abc,gzh_def [--force]
{
"form": "A",
"query": "GPT image2 评测", // 评估锚点(用户真实意图)
"original_q": "GPT image2 评测", // server 用作 query 标签
"phrasings": ["GPT image2 评测", "GPT image2 测评", "GPT image2 实测", "GPT image2 体验"],
"platforms": ["xhs", "x", "gzh"],
"total": 80,
"results": [ /* 去重池:帖子 + llm_evaluation + found_by_queries(哪些措辞命中)*/ ]
}
schema 与 batch_3forms.py 完全一致,所以本目录 server/index 与原版数据契约相同。
搜索/评分结果和工具解构结果在落本地 json 的同时写入 MySQL(.env 的 MYSQL_*,host rm-t4n…,库 agent-…)。
两张表(db.py 自动建,幂等):
fqe_posts —— 每行一个 (query, 帖子):q / query_text / case_id / platform / title / url / body / images / like_count / publish_time / found_by / knowledge_type / overall_score / llm_evaluation。唯一键 (q, case_id),重跑 upsert 不重复。fqe_tools —— 每行一个解构出的工具:q / case_id / 工具名称 / 实质作用域 / 形式作用域 / 创作层级 / 来源链接 / 输入 / 输出 / 用法 / 案例 / 缺点 / 最新更新时间 / model。重新解构按 (q, case_id) 先删旧再插新。特性:
server.py 的 scan_runs() 先读本地 runs_full/*/form_A.json,本地缺的 query 自动从 fqe_posts 补;详情页工具 tab(/api/tools_data)本地无结果时也回退读 fqe_tools。所以即使 runs_full 被清空,界面仍能从库展示数据(本地优先)。python db.py rebuild —— 把库里数据写回本地 runs_full/{q}/form_A.json 和 tools/{case_id}.json。界面回退只让「看」有数据,但提取脚本(tool_extract / 工序)仍读本地文件,故本地文件丢失后用此命令完整恢复。python db.py init(用 CREATE TABLE IF NOT EXISTS,可重复跑)。pymysql(仓库 MySQL 约定)。装:pip install pymysql。python db.py init # 建表(幂等)
python db.py rebuild # 本地文件丢失后,从库重建 runs_full
python run_search.py # 搜索结果自动双写 fqe_posts
python tool_extract.py --q q0000 --case-ids … # 工具结果自动双写 fqe_tools
默认每措辞每渠道搜 10 条(
run_search.py顶部DEFAULT_MAX_COUNT,原为 20,调小控成本)。
run_search.py 会触发 agent.tools.builtin 的完整注册链(同原 batch_3forms.py),需要:
Pillow(PIL,图像处理)fastapi 等 [server] 依赖若报 ModuleNotFoundError: No module named 'PIL' / 'fastapi',说明当前 venv 不全,装齐依赖即可:
pip install -e '.[all]' # 在仓库根
# 或最小补:pip install Pillow fastapi uvicorn websockets
server.py(查看界面)不依赖上述链,缺这些也能起、能看已有产出。
原 search_eval/ |
本 fixed_query_eval/ |
|
|---|---|---|
| query 来源 | 动作×类型正交矩阵生成 + 三形式(A/B/C) | 写死 4 组,单一形式 |
| 搜索引擎 | search_and_evaluate.py |
import 复用同一份(零改动) |
| 评分 rubric | eval_prompt_template.md |
同上(复用) |
| 查看界面 | 矩阵导航 + 卡片 | 去矩阵,4-query 选择条 + 卡片 |
| 产出 | runs_full/q*/form_A\|B\|C.json |
runs_full/q*/form_A.json |
实现说明:搜索/评估/转写/中译英全部复用 ../search_and_evaluate.py 的函数(只读 import);
server/index 复制自原版后做最小改造(server 加一行 sys.path 复用兄弟模块 + 矩阵自动降级;
index 用 CSS 隐藏矩阵 DOM 并新增 #navQ 选择条,矩阵元素保留在 DOM 以免 JS 取空崩溃)。