# Playwright 任务增广(合成题目生成) 本目录为 **playwright / playwright_webarena** 两个 MCP service 增广(augment)合成题目, 供 rollout 采集 SFT 轨迹。所有生成逻辑都在本目录内,**不修改** `src/mcp_services/` 与 评测主流程。 ## 0. 核心增广哲学(五条,所有生成器共用) 我们做的不是"造新题",而是**在真实评测站点上、按评测集已有题型,换参数换问法地放大题量**: 1. **不换站点 / 不换网页** —— 复用评测集用的同一批真实站点(Postmill 论坛、Magento 商城/后台、不可变 arXiv 页、eval-web.mcpmark.ai)。绝不新建/改写站点,保证 agent 看到的页面(观测分布)和评测集一致。 2. **不超纲、对齐评测集分布** —— 题型严格落在评测集 `tasks/playwright*/standard/` 已有 形态内;生成集要**覆盖**评测集原题的各种形态,不引入新能力。 3. **只换三样**:问**哪个事实/字段**、**参数**(SKU / 关键词 / 价格区间 / 顾客 / 税州 / arXiv id…)、**问法**(换措辞、换语气,保留全部确切实体)。 4. **GT 预先求真值(不靠 LLM 猜答案)** —— 建题时先用浏览器/`docker exec curl`/本地权威 CSV 把 ground-truth 真跑出来,定格到 `label.txt` / `content.txt`。arXiv 页、eval-web 表、docker 站快照都是稳定可复现的。 5. **verify 真实可核** —— agent 在对话里给 `` 块,verify 读 `MCP_MESSAGES` 逐字段 精确比对(数值按 int、文本 normalize,照搬评测集 `parse_answer_format`/`compare_answers`); **操作题**还要回站点核实改动是否真的发生。 > 历史教训(见 memory):早期"自包含玩具 HTML"那套对真实评测提分基本无用,已废弃; > 现在一律在**真站点**上按评测集原生 task 格式增广。 --- ## 1. 目录结构(一个任务类型一个文件夹) ``` playwright/ ├── base.py # 真网 Generator 基类 + verify 头 + 换问法 diversify_question ├── generate.py # 真网生成器的离线生成 + oracle 自检入口 ├── run_eval.py # 真网生成器的端到端 runner(生成→rollout→verify) ├── deepseek_keys.txt # LLM key 池(每行一个;dimcode deepseek-v4-pro) ├── runs/ # 真网生成器的结果落地 │ ├── reddit/ # A 类:webarena docker 生成器 │ ├── gen_reddit.py │ ├── _snapshot_reddit.json # 站点快照缓存(GT 来源) │ └── forum_data.json ├── shopping/ │ ├── gen_shopping.py │ └── _snapshot_shopping.json ├── shopping_admin/ │ ├── gen_shopping_admin.py │ └── _snapshot_shopping_admin.json │ ├── web_search_fact/ # B 类:真网 Generator(REGISTRY 注册,见 __init__.py) │ └── __init__.py └── web_table_extract/ └── __init__.py ``` 本目录有**两套**生成机制,对应两类站点: | 类 | 生成器 | 站点 | 产出 | 运行方式 | |---|---|---|---|---| | **A** | reddit / shopping / shopping_admin | 本地 docker(WebArena) | 直接写 mcpmark **原生 task 目录** 到 `tasks/playwright_webarena/standard/_gen/` | 独立 CLI;rollout 用 `pipeline.py --mcp playwright_webarena` | | **B** | web_search_fact / web_table_extract | **真实互联网**(走代理) | `base.Generator` 子类,进 `__init__.py` 的 `REGISTRY` | `generate.py` / `run_eval.py` | --- ## 2. A 类:WebArena docker 生成器(reddit / shopping / shopping_admin) 独立脚本,**爬一次真站点存快照 → 从快照采样按评测题型批量造题 → 写原生 task 目录**。 每题目录含 `params.json`(参数)、`label.txt`(GT)、`description.md`、`meta.json`、`verify.py`。 rollout 时 `playwright_webarena` 的 state manager 会自动起对应 docker 容器(按 category 映射 镜像/端口),agent 在真站点上操作,结束后跑 `verify.py`。 ### 2.1 reddit(Postmill 论坛,容器 `forum`/`forum_s{n}`,端口 9999+n) - **取数**:`docker exec forum curl` 抓各论坛 top 排序前 N 页(容器内访问,稳,不依赖端口映射)。 复用评测触及的论坛 + 同实例其它热门论坛(仅为多样性,不新建)。 - **题型**(严格对齐评测集):Top-N 高赞/高评论榜、关键词计数+极值、跨页"年份/图片帖" 计数+全局最高赞、给指定帖投赞(操作题)。 - **核对**:内容题预爬 GT 存 `label.txt`,agent **发帖**报答案,verify 登录→按标题找帖→ 解析 `Key|Value` 逐字段比(数值 int、用户名 strip 下划线、Top 榜票数递减校验,照搬 `buyitforlife_research`);操作题回站点读 `vote__net-score`(照搬 `routine_tracker_forum`)。 ### 2.2 shopping(Magento 商城 storefront,端口 7770+n) - **取数**:宿主→容器快照(须**干净环境**,去 LD_PRELOAD/proxychains,否则 localhost 被绕走)。 - **题型**:高级搜索(Product Name + 价格区间)→ 结果计数;按价升/降序 → 最便宜/最贵商品 的 SKU+价格(极值);加购指定数量 → 购物车 Subtotal(=单价×数量)。 - **核对**:GT 由浏览器预快照执行得到(total/价格/SKU/subtotal),agent 给 ``, verify 读 `MCP_MESSAGES` 逐字段精确比。**刻意避开**评论数/评分%/颜色/尺寸/产地(列表页 不显示、需逐个进详情且不稳,无法保证真 GT)。 ### 2.3 shopping_admin(Magento 后台,端口 7780+n) - **取数**:宿主→容器快照(干净环境,封装在 `_run_clean()` 自动重启)。 - **题型**:products 网格(名称含某词计数 / 按 SKU 查价·库存·状态 / 数量等于某值计数)、 dashboard Bestsellers、orders 网格(总数/按状态计数/最高 Grand Total 的顾客+金额)、 customers 网格、Search Terms、Cart Price Rules、Tax Rates;覆盖评测集的"多字段捆绑题"。 - **核对**:读取题 GT 存 `label.txt` + `` 比对;**操作题(~25%)**照搬 `customer_segmentation_setup` —— 记 baseline → 建客户组+建顾客 → 报 before/after,verify 既比 `` 又回站点核实(组/顾客存在 + records found 计数)。 ### 用法(干净环境) ```bash PY=/home/sunhc/miniconda3/envs/mcpmark/bin/python env -u LD_PRELOAD -u PROXYCHAINS_CONF_FILE -u PROXYCHAINS_QUIET_MODE \ $PY reddit/gen_reddit.py --n 300 # shopping / shopping_admin 同理 # 仅刷新快照:--refresh-crawl(reddit)/ --snapshot-only(shopping*) ``` 生成多了后按分片重切成 `_gen_s0..sN`、每片一个 docker 容器并行 rollout。 --- ## 3. B 类:真网 Generator(web_search_fact / web_table_extract) `base.Generator` 子类,定格在**不可变真网页面**上,沿用 oracle 契约: `build`(抓页/读权威数据→定格 GT 到 `content.txt`)→ `description` → `verify_src` (重算/比对)→ `solve`(oracle 浏览器再跑一遍证明 verify 接受预期答案、拒空答)。 - **web_search_fact**(对齐 `playwright/web_search`):锚定**不可变 arXiv `/abs/` 页** (永不变)。一个 arXiv id × 多个**问法模板**生成多变体,问页面上的确切细节(逼模型真开页 而非凭记忆)。一部分题走**搜索模式**:藏 URL,让模型按标题用搜索引擎找到论文(练 web_search 的搜索能力)。GT 来自建题时的页面快照。 - **web_table_extract**(对齐 `eval_web/extraction_table`):用**评测同一个页面** `https://eval-web.mcpmark.ai/extraction`,读它的表(Title/Rating/Likes/Views/Replies), **只换问法**。GT 来自仓库里已提交的权威 `data.csv`(97 行固定),建题时确定性算出答案定格, 不抓取、不让 LLM 猜。(早期用 Wikipedia 被否:偏离评测分布 + 图片多撑爆单代理 navigate 超时。) 两者 **rollout 时需经代理出网**(`$SYNTH_PROXY`,默认 US socks5 `socks5://127.0.0.1:7893`)。 ### 用法 ```bash # 离线生成 + oracle 自检(无需 API) conda run -n mcpmark python -m synth.generators.playwright.generate --no-llm --n 4 # 端到端:生成 → rollout(DeepSeek) → verify conda run -n mcpmark python -m synth.generators.playwright.run_eval \ --n 8 --k 4 --keys-file synth/generators/playwright/deepseek_keys.txt ``` --- ## 4. 答案格式与核对通道(两类共用) 每题报多字段 `` 块(对齐评测集,如 `customer_segmentation_setup`),verify 逐字段比 (数值 int、文本 normalize): ``` Key1|value1 Key2|value2 ``` 核对通道:对话 `MCP_MESSAGES`(真实评测的有效通道,browser agent 只能"说"答案); A 类操作题 / B 类 oracle 还会用站点状态 / `answer.txt` 二次确认。 --- ## 5. rollout 与轨迹压缩(与本目录配合) - **A 类**用 `pipeline.py --mcp playwright_webarena --tasks _gen_s{n} --models deepseek-v4-pro` 跑;**B 类**用 `run_eval.py`。LLM 走 dimcode `deepseek-v4-pro`(`DEEPSEEK_BASE_URL=https://dimcode.cn/v1`)。 - 为把轨迹压进 token 上限,rollout 可加 **`--summarize-tool-response`**:每个 **playwright 浏览器** 工具结果在进入对话历史**之前**被 LLM 总结(保结构、保确切数值),"模型看到的 == 轨迹记录的", 保真无损失;仅对 playwright 生效,数据型 service 不动。详见 `src/agents/mcpmark_agent.py`。 --- ## 6. 环境 ```bash conda create -n mcpmark python=3.11 -y conda run -n mcpmark pip install -e . conda run -n mcpmark python -m playwright install chromium # B 类 oracle / 快照需要 ``` `@playwright/mcp@latest` 由 `npx` 按需拉取(Node ≥ 18)。docker 站点镜像 (postmill / shopping / shopping_admin)需预先加载。