18 KiB
Skill Agent 编译流水线
本项目将 SkillsBench 任务中的单个 Skill 依次经过静态编译、Fast 动态优化、Deep 动态迭代和 BenchFlow 评测,产出可恢复、可审计的最终 Skill。
安装与配置
配置系统环境
项目目前运行在 Windows WSL 2(Ubuntu 26.04 LTS) 系统中。
# 以管理员身份打开 ps 安装
wsl --install -d Ubuntu-26.04
设置账号密码,进入 wsl 后安装基础工具与 python,nodejs:
sudo apt update
sudo apt upgrade -y
sudo apt install -y ca-certificates curl git python3 python3-pip python3-venv python-is-python3
sudo apt install -y nodejs
项目依赖 docker, 直接运行在这个 WSL 发行版中的原生 Docker Engine(29.6.2)。
sudo apt remove -y docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
sudo usermod -aG docker "$USER"
newgrp docker
验证 docker:
docker version
docker run --rm hello-world
如果遇到permission denied相关提示,可能和docker权限问题/网络问题有关:
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock
网络问题可配置 WSL 网络镜像,在 Windows PowerShell 里创建/修改:
notepad $env:USERPROFILE\.wslconfig
写入:
[wsl2]
networkingMode=mirrored
dnsTunneling=true
autoProxy=true
firewall=true
保存后执行:
wsl --shutdown
wsl -d Ubuntu-26.04
然后再跑
docker run --rm hello-world
如果最后看到 Hello from Docker!,就说明问题已经完全解决。
项目建议放在 ~/projects/skill-agent-proj, 项目目录:
skill-agent-proj/
├── scripts/
├── requirements.txt
├── provider_routes.json
└── data/
└── skills-bench/
├── pyproject.toml
├── uv.lock
├── tasks/
└── skillsbench_agentbeats/
......
配置项目环境依赖
外部模型
在项目根目录配置 .env,并在 provider_routes.json 中维护模型路由。所有模型参数使用 provider/model-id 格式。
项目环境
可以用 conda 创建虚拟环境, python 版本选择3.12, 在虚拟环境中配置项目依赖:
python -m pip install -r requirements.txt
目前使用的是Python 3.12 自带的 venv,激活虚拟环境 Linux/macOS:
source .venv/bin/activate
用结束后退出环境
deactivate
skills-bench 环境
完整流水线要求 SkillsBench/BenchFlow CLI,测试脚本 run-raw-task.sh 会调用它们。
- SkillsBench:官方基准仓库,提供任务规范、Python 运行环境和 skillsbench_agentbeats worker。
- BenchFlow CLI:实际执行 bench eval run --sandbox docker 的命令行工具。
sudo snap remove astral-uv
hash -r
curl -LsSf https://astral.sh/uv/0.12.6/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
hash -r
uv --version
cd ~/Projects/skill-agent-proj/data/skills-bench
uv sync --locked
# 这里如果执行失败可能是 目录/权限问题.
# 验证
./.venv/bin/python --version
./.venv/bin/bench --version
- 注意uv sync --locked是在创建skills-bench下面的虚拟环境.venv
安装好验证测试脚本是否能运行:
cd ~/Projects/skill-agent-proj
source .venv/bin/activate
smoke_root=$(mktemp -d /tmp/skillc-eval-smoke.XXXXXX)
echo "临时输出目录:$smoke_root"
PYTHONDONTWRITEBYTECODE=1 \
bash scripts/evaluate/run-raw-task.sh \
--harness opencode \
--model siliconflow/Qwen/Qwen3.5-27B \
--task data/skills-bench/tasks/citation-check \
--skill-source data/skills-bench/tasks/citation-check/environment/skills \
--output "$smoke_root" \
--require-skill \
--repeat 1 \
--max-parallel 1
VSCODE推荐使用Containers插件,可以可视化docker镜像情况。
这里如果执行失败可能是因为: docker 需要配置代理或镜像加速,或检查 wsl 网络问题.
如果遇到以下问题:
test-001 (1/1) [#-------------------] 5% preparing elapsed=02:57
scripts/evaluate/run-raw-task.sh: line 534: rg: command not found
scripts/evaluate/run-raw-task.sh: line 536: rg: command not found
scripts/evaluate/run-raw-task.sh: line 538: rg: command not found
scripts/evaluate/run-raw-task.sh: line 540: rg: command not found
scripts/evaluate/run-raw-task.sh: line 542: rg: command not found
scripts/evaluate/run-raw-task.sh: line 544: rg: command not found
这是因为 WSL 系统里没有安装 rg(ripgrep),请新开一个wsl终端,安装ripgrep:
sudo apt update
sudo apt install -y ripgrep
验证:
rg --version
WSL mirrored 模式下配置 SkillsBench 容器代理 (补充章节)
SkillsBench/BenchFlow 会在 Docker 容器中运行 agent 和 verifier。仅配置 Docker daemon
的代理只能解决镜像拉取问题,不能保证运行中的容器可以访问 astral.sh、PyPI 等外部服务。
当前使用的代理链路如下:
SkillsBench 容器
-> HTTP_PROXY=http://172.17.0.1:18080
-> benchflow-proxy-bridge
-> 127.0.0.1:7897
-> Windows Clash Verge
-> Internet
端口说明:
7897:Windows Clash Verge 的实际代理端口。18080:Docker 容器访问的桥接入口。172.17.0.1:Docker 默认 bridge 网络的宿主机网关。- 桥接入口和实际代理出口应使用不同端口,避免监听冲突或转发回路。
1. 配置 WSL mirrored 网络
在 Windows PowerShell 中编辑 %USERPROFILE%\.wslconfig:
notepad $env:USERPROFILE\.wslconfig
确保 [wsl2] 中包含:
[wsl2]
networkingMode=mirrored
hostAddressLoopback=true
firewall=true
autoProxy=true
ignoredPorts=18080
ignoredPorts=18080 用于避免 mirrored 网络在 Windows 层保留该端口,导致 host 网络容器报错:
bind 0.0.0.0:18080: Address in use
如果已经配置其他忽略端口,使用逗号追加,例如:
ignoredPorts=53,18080
保存后,在 Windows PowerShell 中重启 WSL:
wsl --shutdown
2. 创建持久化代理桥接容器
确保 Windows Clash Verge 正在运行,并确认 mixed proxy 端口为 7897。然后在 WSL 中创建桥接容器:
docker run -d \
--name benchflow-proxy-bridge \
--network host \
--restart unless-stopped \
alpine/socat \
TCP-LISTEN:18080,fork,reuseaddr \
TCP:127.0.0.1:7897
检查容器状态和配置:
docker ps -a --filter name=benchflow-proxy-bridge
docker inspect benchflow-proxy-bridge \
--format 'RestartPolicy={{.HostConfig.RestartPolicy.Name}} NetworkMode={{.HostConfig.NetworkMode}}'
docker inspect benchflow-proxy-bridge \
--format '{{json .Config.Cmd}}'
预期结果包含:
RestartPolicy=unless-stopped NetworkMode=host
["TCP-LISTEN:18080,fork,reuseaddr","TCP:127.0.0.1:7897"]
unless-stopped 表示 Docker daemon 启动或容器异常退出后会自动恢复该容器。显式执行
docker stop benchflow-proxy-bridge 后,容器会保持停止,直到再次手动启动。
3. 给运行容器注入代理
编辑 Docker 客户端配置:
mkdir -p ~/.docker
nano ~/.docker/config.json
写入:
{
"proxies": {
"default": {
"httpProxy": "http://172.17.0.1:18080",
"httpsProxy": "http://172.17.0.1:18080",
"noProxy": "localhost,127.0.0.1,::1"
}
}
}
该配置会把大小写形式的 HTTP_PROXY、HTTPS_PROXY 和 NO_PROXY 注入新创建的
Docker 容器,包括 SkillsBench 的 agent/verifier 容器。JSON 中必须使用纯 URL,不能写成
Markdown 链接形式。
4. 验证完整代理链路
确认桥接容器正在运行并监听 18080:
docker ps --filter name=benchflow-proxy-bridge
sudo ss -lntp | grep ':18080'
确认新容器获得代理变量:
docker run --rm ubuntu:24.04 env | grep -i proxy
预期包含:
HTTP_PROXY=http://172.17.0.1:18080
HTTPS_PROXY=http://172.17.0.1:18080
测试 verifier 所需的 uv 下载链路:
docker run --rm ubuntu:24.04 \
bash -c 'apt-get update >/dev/null &&
apt-get install -y curl >/dev/null &&
curl --connect-timeout 10 --max-time 30 -fsSIL https://astral.sh/uv/0.9.7/install.sh'
最终返回 HTTP/2 200 表示链路正常,可以重新运行 SkillsBench 测试。
5. 常见问题
桥接容器反复显示 Restarting 时,先查看日志:
docker logs --tail 100 benchflow-proxy-bridge
如果日志包含:
bind 0.0.0.0:18080: Address in use
检查 Windows .wslconfig 是否包含 ignoredPorts=18080,修改后执行 wsl --shutdown。
如果普通容器访问 172.17.0.1:18080 时出现 Connection refused,依次检查:
docker ps --filter name=benchflow-proxy-bridge
sudo ss -lntp | grep ':18080'
docker logs --tail 100 benchflow-proxy-bridge
同时确认 Windows Clash Verge 正在运行,且 mixed proxy 端口仍为 7897。
Docker daemon 代理与运行容器代理的区别
Docker daemon 代理负责拉取镜像;~/.docker/config.json 中的代理负责运行中容器的网络请求,
两者用途不同。Docker daemon 可以继续使用宿主侧可直接访问的地址,例如:
HTTP_PROXY=http://127.0.0.1:7897
HTTPS_PROXY=http://127.0.0.1:7897
不要让 Docker daemon 依赖 benchflow-proxy-bridge,否则可能形成“Docker daemon 需要桥接
容器联网,而桥接容器又必须等待 Docker daemon 启动”的循环依赖。
两个环境说明
项目核心运行环境是 conda 创建的虚拟环境, data/skills-bench/.venv 是 SkillsBench/BenchFlow 的独立运行环境,负责执行评测。评测脚本会显式调用 data/skills-bench/.venv/bin/python 和其中的 bench;仅这些子进程使用该 uv 创建的虚拟环境,不会切换或改变当前 Conda 环境。
agentrm 启动
(可以使用codex协助启动, 目前无法自动化流程,因为autodl服务器没法一直占用,且成本较高)
动态优化中,还需要启动远程 AgentRM服务,假设模型部署在远端服务器 8000 端口运行,本地 28080端口接收:
服务器端:
复制SSH登录指令
PS C:\Users\xfd024> ssh -p 33706 root@connect.weste.seetacloud.com
随后输入密码
# 进入部署目录并激活 Conda 环境:
cd root/autodl-tmp/agentrm-deployment
source /root/miniconda3/etc/profile.d/conda.sh
conda activate agentrm
chmod +x run_agentrm_server.sh
# 启动服务:
RM_HOST=127.0.0.1 ./run_agentrm_server.sh
# 查看加载日志:
tail -f outputs/agentrm_server.log
# 看到以下内容表示模型加载完成:
# [ready] AgentRM loaded on cuda
# 远端健康检查:
curl -fsS http://127.0.0.1:8000/health
# 正常返回:
# {
# "status": "ok",
# "device": "cuda",
# "max_length": 8192
# }
本地建立 SSH 隧道:
Windows PowerShell 执行后保持窗口开启:
ssh -o ExitOnForwardFailure=yes
-o ServerAliveInterval=30
-o ServerAliveCountMax=3
-N
-L 127.0.0.1:28080:127.0.0.1:8000
-p <SSH端口> <用户>@<服务器地址>
推荐用法:完整流水线
python -m scripts.compile_pipeline \
--harness opencode \
--model provider/target-model \
--external-model provider/compiler-model \
--task <data/skills-bench/tasks 下的任务名>
使用原运行目录恢复中断任务:
python -m scripts.compile_pipeline \
--harness opencode \
--model provider/target-model \
--external-model provider/compiler-model \
--task <任务名> \
--run-dir results/compile-pipeline/<run-id>
任务必须位于 data/skills-bench/tasks,且 environment/skills 下仅有一个 SKILL.md。--run-dir 必须位于 results/compile-pipeline;同一目录不能并发运行。
执行顺序与产物
原始 Skill
→ 原始评测
→ 模型画像与静态编译
→ 静态产物评测
→ Fast 优化与评测
→ Deep 局部迭代
→ 最终评测
→ artifacts/deep/S_final
完整运行目录为 results/compile-pipeline/<run-id>/:
manifest.json:输入身份、阶段状态和错误;原子写入,可用于恢复。artifacts/static、artifacts/fast、artifacts/deep:各编译阶段产物与缓存。traces/<task>/:原始、静态、Fast、最终评测结果;Deep 最后一轮可复用 rollout 也会复制到此处的final_skill/。artifacts/deep/S_final:最终可交付 Skill。
评测仅复用完整的 test-* 产物(摘要、Skill 调用校验、结构化结果和 ACP 轨迹均有效)。不完整目录会移入同级 .incomplete/,不会被当作缓存。Deep 仅在最终 SKILL.md 哈希与最后一批有效 rollout 一致时复用其结果。
参考命令
以下示例使用现有的 111-offer-letter-generator 产物路径。静态编译使用 --model 指定待适配的目标模型,使用 --external-model 指定混合模式的语义规划模型。
静态编译
python -m scripts.static_compile \
--model siliconflow/Qwen/Qwen3.5-27B \
--external-model ali/deepseek-v4-pro-0813 \
--input data/skills-bench/tasks/111-offer-letter-generator/environment/skills \
--out-root results/static-opimization/ \
--mode hybrid
快速优化
python -m scripts.dynamic_compile.fast \
--traces results/dynamic-optimization/traces/raw_agent_trace/opencode/siliconflow-qwen-qwen3-5-27b/111-offer-letter-generator/model_skill \
--skill results/static-opimization/siliconflow-qwen-qwen3-5-27b/skills/docx \
--model ali/deepseek-v4-pro-0813 \
--max-parallel 3
深度迭代
python -m scripts.dynamic_compile.deep run \
--skill results/dynamic-optimization/compiled-skills/opencode/siliconflow-qwen-qwen3-5-27b/111-offer-letter-generator/model_compile/candidate-skill/docx \
--traces results/benchflow/opencode-siliconflow-qwen-qwen3-5-27b/111-offer-letter-generator/custom_skill \
--output results/dynamic-optimization-v1-5/deep-compiled-skills/opencode/siliconflow-qwen-qwen3-5-27b/111-offer-letter-generator \
--model ali/deepseek-v4-pro-0813
完整流水线
python -m scripts.compile_pipeline \
--harness opencode \
--model siliconflow/Qwen/Qwen3.5-27B \
--external-model ali/deepseek-v4-pro-0813 \
--task citation-check
独立模块
静态编译
根据模型画像对 Skill 做确定性或混合改写;保留 frontmatter、代码块和受保护字面量,语义保护失败时回滚原文。
python -m scripts.static_compile \
--model provider/model-id \
--input <Skill 目录或包目录> \
--out-root results/static-compiled-skills \
--mode deterministic
hybrid 模式允许一次受源文本约束的语义规划;--dry-run 不写产物也不调用规划模型。
实际执行 hybrid 模式时必须通过 --external-model provider/model-id 单独指定语义规划模型;--model 始终表示待适配的目标模型。
Fast 动态优化
基于至少 6 条同任务、同编译类型的 BenchFlow 轨迹,依次执行预评分、AgentRM 评分、Top/Bottom 分组、Map/Reduce 与局部补丁生成;候选包原子发布。
python -m scripts.dynamic_compile.fast \
--traces <BenchFlow 轨迹目录> \
--skill <Skill 包目录> \
--model provider/model-id
可选 --score-output、--output、--max-parallel、--rm-api-url 与 --force。缓存只有在输入内容、配置、版本、哈希和产物均匹配时才复用。
Deep 动态迭代
对 Fast 产物按章节、必要时按段落进行五维评分,生成并验证局部编辑,再用候选运行时轨迹比较;只有目标分数提升且没有运行时回归才提交。编辑始终校验章节边界、代码围栏、缓存和原子替换。
python -m scripts.dynamic_compile.deep run \
--skill <Skill 包目录> \
--traces <BenchFlow 轨迹目录> \
--output <Deep 输出目录> \
--model provider/model-id
python -m scripts.dynamic_compile.deep resume --run <Deep 输出目录>
BenchFlow 评测
bash scripts/evaluate/run-raw-task.sh \
--harness opencode \
--model provider/model-id \
--task <SkillsBench 任务目录> \
--skill-source <Skill 目录或 skills 根目录> \
--output <结果目录> \
--require-skill --repeat 3 --max-parallel 3
该脚本为官方 BenchFlow runner 的兼容包装:每次尝试在 <结果目录>/test-NNN/ 写入结果;--require-skill 会校验至少成功调用一次 Skill。可用 --image <本地镜像> 复用镜像;否则按任务创建或复用本地镜像。
失败处理
参数、任务范围、Skill 结构、模型路由、缓存、轨迹和产物均会校验。编译或评测阶段失败会记录到 manifest 并返回错误;可在修复配置后使用相同 --run-dir 恢复。执行实际编译或评测会调用外部模型、BenchFlow 和 Docker;--help 与模块导入不会。