Harbor Framework

Harbor Framework

一、简介和原理

1.1 项目简介

Harbor Framework 是开源智能体(Agent)与大语言模型(LLM)评估、调优框架,主要面向代码智能体、容器化仿真场景,支持批量并行实验、基准测试、强化学习轨迹数据生成。

1.2 核心能力

支持主流代码智能体的评测;

支持自定义评测数据集与沙箱运行环境;

支持本地 Docker、云端容器大规模并发执行任务;

自动输出 Agent 交互轨迹,可用于强化学习训练;

兼容 Terminal-Bench、SWE-Bench 等主流代码评测基准。

1.3 核心运行原理

容器沙箱隔离:所有任务运行在 Docker 或云端容器环境,任务之间环境隔离,互不污染。

三层解耦架构:数据集(Dataset)、智能体(Agent)、大模型(Model)完全解耦,通过命令行参数自由组合,不需要修改源代码。

并发调度:本地模式限制容器数量;云端模式支持弹性高并发。

日志与观测:内置可视化查看面板,完整记录交互步骤、耗时、任务结果。

版本化数据集管理:数据集采用名称@版本格式管理,多版本共存,一键切换版本。

执行流程图:
#mermaid-svg-vo7XOEOTmA7bTJ02{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vo7XOEOTmA7bTJ02 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vo7XOEOTmA7bTJ02 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vo7XOEOTmA7bTJ02 .error-icon{fill:#552222;}#mermaid-svg-vo7XOEOTmA7bTJ02 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vo7XOEOTmA7bTJ02 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vo7XOEOTmA7bTJ02 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vo7XOEOTmA7bTJ02 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vo7XOEOTmA7bTJ02 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vo7XOEOTmA7bTJ02 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vo7XOEOTmA7bTJ02 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vo7XOEOTmA7bTJ02 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vo7XOEOTmA7bTJ02 .marker.cross{stroke:#333333;}#mermaid-svg-vo7XOEOTmA7bTJ02 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vo7XOEOTmA7bTJ02 p{margin:0;}#mermaid-svg-vo7XOEOTmA7bTJ02 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-vo7XOEOTmA7bTJ02 .cluster-label text{fill:#333;}#mermaid-svg-vo7XOEOTmA7bTJ02 .cluster-label span{color:#333;}#mermaid-svg-vo7XOEOTmA7bTJ02 .cluster-label span p{background-color:transparent;}#mermaid-svg-vo7XOEOTmA7bTJ02 .label text,#mermaid-svg-vo7XOEOTmA7bTJ02 span{fill:#333;color:#333;}#mermaid-svg-vo7XOEOTmA7bTJ02 .node rect,#mermaid-svg-vo7XOEOTmA7bTJ02 .node circle,#mermaid-svg-vo7XOEOTmA7bTJ02 .node ellipse,#mermaid-svg-vo7XOEOTmA7bTJ02 .node polygon,#mermaid-svg-vo7XOEOTmA7bTJ02 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vo7XOEOTmA7bTJ02 .rough-node .label text,#mermaid-svg-vo7XOEOTmA7bTJ02 .node .label text,#mermaid-svg-vo7XOEOTmA7bTJ02 .image-shape .label,#mermaid-svg-vo7XOEOTmA7bTJ02 .icon-shape .label{text-anchor:middle;}#mermaid-svg-vo7XOEOTmA7bTJ02 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vo7XOEOTmA7bTJ02 .rough-node .label,#mermaid-svg-vo7XOEOTmA7bTJ02 .node .label,#mermaid-svg-vo7XOEOTmA7bTJ02 .image-shape .label,#mermaid-svg-vo7XOEOTmA7bTJ02 .icon-shape .label{text-align:center;}#mermaid-svg-vo7XOEOTmA7bTJ02 .node.clickable{cursor:pointer;}#mermaid-svg-vo7XOEOTmA7bTJ02 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vo7XOEOTmA7bTJ02 .arrowheadPath{fill:#333333;}#mermaid-svg-vo7XOEOTmA7bTJ02 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vo7XOEOTmA7bTJ02 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vo7XOEOTmA7bTJ02 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vo7XOEOTmA7bTJ02 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vo7XOEOTmA7bTJ02 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vo7XOEOTmA7bTJ02 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vo7XOEOTmA7bTJ02 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vo7XOEOTmA7bTJ02 .cluster text{fill:#333;}#mermaid-svg-vo7XOEOTmA7bTJ02 .cluster span{color:#333;}#mermaid-svg-vo7XOEOTmA7bTJ02 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vo7XOEOTmA7bTJ02 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vo7XOEOTmA7bTJ02 rect.text{fill:none;stroke-width:0;}#mermaid-svg-vo7XOEOTmA7bTJ02 .icon-shape,#mermaid-svg-vo7XOEOTmA7bTJ02 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vo7XOEOTmA7bTJ02 .icon-shape p,#mermaid-svg-vo7XOEOTmA7bTJ02 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vo7XOEOTmA7bTJ02 .icon-shape .label rect,#mermaid-svg-vo7XOEOTmA7bTJ02 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vo7XOEOTmA7bTJ02 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vo7XOEOTmA7bTJ02 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vo7XOEOTmA7bTJ02 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} harbor run
加载数据集,分配并发任务
拉起隔离容器
Agent执行任务
验证器校验打分
保存结果,销毁容器
输出汇总报告

二、资料地址

GitHub 仓库: https://github.com/harbor-framework/harbor

配套资源:

官方文档:https://www.harborframework.com/docs

Harbor Hub:https://hub.harborframework.com

三、安装

3.1 前置依赖

本地运行模式:Docker 服务必须正常启动;

Linux 注意:当前用户需要加入 docker 用户组,否则需要 sudo 执行 harbor 命令;Windows 建议使用 WSL2 后端。

云端运行模式:需要对应云服务商 API Key;

大模型调用:需要对应 LLM 厂商 API Key。

⚠️注意:PyPI 上存在旧包名harbor,请勿直接使用pip install harbor,会安装到错误的第三方包。

3.2 安装方式

shell 复制代码
# 推荐
uv tool install harbor
# or
pip install harbor

安装完成后,终端可直接调用全局 harbor 命令。

四、Demo

说明:本次使用oracle的agent演示,后续评分,大家可以自己去配置需要跑模型

文件目录:

SHELL 复制代码
demo/
├── environment/          # 容器沙箱构建环境,构建任务Docker镜像所用素材
│   └── Dockerfile        # 沙箱镜像构建脚本
├── instruction.md        # 给Agent的任务提示词/任务描述,智能体要完成的目标、需求说明
├── jobs/                 # harbor run执行之后输出的运行结果目录,执行后会自动创建
├── solution/
│   └── solve.sh          # 参考标准答案脚本;可选,作为baseline正确实现
├── task.toml             # 任务元配置文件,Harbor Framework核心配置
└── tests/
    ├── test_outputs.py   # Python校验逻辑:断言、结果解析、打分逻辑
    └── test.sh           # 验证器入口shell脚本,执行测试、生成reward、stdout输出

日志目录:

shell 复制代码
jobs/
└── 2026-08-12__11-24-24/                # 一次完整harbor run全局实验总目录    ├── config.json                      # 本次全局实验配置
    ├── exam_task__fWfoVLm/            # 单个任务实例目录,每个评测任务生成1个
    │   ├── agent/                       # Agent智能体工作目录
    │   ├── artifacts/                   # 任务产出工件、沙箱输出文件
    │   ├── config.json                  # 当前这一条任务的独立配置
    │   ├── lock.json                    # 任务运行锁文件
    │   ├── result.json                  # 单条任务最终结果(打分、成功失败)
    │   ├── trial.log                    # Agent完整交互轨迹日志(最重要!)
    │   └── verifier/                    # 验证器/评测校验模块工作目录
    │       ├── reward.txt               # 验证器原始奖励分数
    │       └── test-stdout.txt          # 校验脚本执行stdout,断言、报错信息
    ├── job.log                          # 整个实验总运行日志
    ├── lock.json                        # 全局实验锁
    └── result.json                      # 整个实验汇总结果

4.1 创建项目

shell 复制代码
[root@localhost home]# tree test_demo
test_demo
├── environment
│   ├── app
│   │   └── extract_log.sh
│   ├── data
│   │   └── app.log
│   └── Dockerfile
├── instruction.md
├── solution
│   └── solve.sh
├── task.toml
└── tests
    ├── test_outputs.py
    └── test.sh

5 directories, 8 files
[root@localhost home]# cat test_demo/environment/app/extract_log.sh 
#!/bin/bash
# 提取日志脚本,bug:当前过滤WARN,需要改为ERROR
LOG_FILE="/var/log/app.log"
OUT_FILE="/tmp/error_only.log"

# 错误:grep WARN,应该为 grep ERROR
grep "WARN" "${LOG_FILE}" > "${OUT_FILE}"
[root@localhost home]# cat test_demo/environment/data/app.log 
2026-08-12 08:10:01 INFO service start ok
2026-08-12 08:10:05 WARN disk usage 75%
2026-08-12 08:10:10 ERROR database connect failed
2026-08-12 08:10:15 WARN memory high
2026-08-12 08:10:20 ERROR timeout request
2026-08-12 08:10:25 INFO receive request
2026-08-12 08:10:30 ERROR parse json failed
2026-08-12 08:10:35 WARN slow query
2026-08-12 08:10:40 ERROR rpc call exception
2026-08-12 08:10:45 INFO task complete
[root@localhost home]# cat test_demo/environment/Dockerfile 
FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/tiangolo/uvicorn-gunicorn:python3.11-slim

# 创建目录
RUN mkdir -p /app /var/log /tmp

# 拷贝业务脚本与日志
COPY app/extract_log.sh /app/extract_log.sh
COPY data/app.log /var/log/app.log

RUN chmod +x /app/extract_log.sh

WORKDIR /

#CMD ["/bin/bash"]
[root@localhost home]# cat test_demo/instruction.md 
你是Linux运维工程师。
容器中业务日志路径:/var/log/app.log
/app/extract_log.sh 为日志提取脚本。

当前脚本存在问题:脚本提取的是WARN警告日志。
业务需求:提取日志文件中所有包含 ERROR 的行,输出写入文件 /tmp/error_only.log。

请完成:
1. 查看 /var/log/app.log 日志内容理解日志格式
2. 修改 /app/extract_log.sh,修改过滤关键字
3. 执行脚本 /app/extract_log.sh
4. 确认 /tmp/error_only.log 生成并且内容为全部ERROR行
任务完成即可结束。
[root@localhost home]# cat test_demo/solution/solve.sh 
#!/bin/bash
# 参考正确解法,人工baseline
sed -i 's/grep "WARN"/grep "ERROR"/' /app/extract_log.sh
chmod +x /app/extract_log.sh
/app/extract_log.sh
cat /tmp/error_only.log
[root@localhost home]# cat test_demo/task.toml 
version = "1.0"

id = "demo-extract-error-log@v1"
name = "提取日志ERROR错误行"
description = "运维demo:修改shell脚本提取日志中ERROR行输出到文件"
timeout = 300

[environment]
build_timeout_sec = 600.0
cpus = 1
memory_mb = 1024
storage_mb = 4096
gpus = 0
dockerfile = "./environment/Dockerfile"

[verifier]
timeout_sec = 120.0
entrypoint = "./tests/test.sh"

[verifier.env]

[solution.env]

[root@localhost home]# cat test_demo/tests/test_outputs.py 
#!/usr/bin/env python3
import sys
import os

output_file = "/tmp/error_only.log"

# 判断输出文件是否存在
if not os.path.exists(output_file):
    print("FAIL:输出文件 /tmp/error_only.log 不存在")
    sys.exit(1)

with open(output_file, "r", encoding="utf-8") as f:
    lines = f.readlines()

# 统计包含ERROR的行数
error_lines = [line for line in lines if "ERROR" in line]
count = len(error_lines)

print(f"实际ERROR行数:{count},期望:4")

if count == 4:
    print("PASS:提取ERROR日志正确")
    sys.exit(0)
else:
    print(f"FAIL:ERROR行数不对,得到 {count},预期4")
    sys.exit(1)
[root@localhost home]# cat test_demo/tests/test.sh 
#!/bin/bash
set -e

python3 ./tests/test_outputs.py #> ./verifier/test-stdout.txt
exit_code=$?

if [ ${exit_code} -eq 0 ]; then
    echo 1 > /logs/verifier/reward.txt
else
    echo 0 > /logs/verifier/reward.txt
fi
[root@localhost home]# 

执行demo

shell 复制代码
[root@localhost test_demo]# harbor run -p . -a oracle
  1/1 Mean: 1.000 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0:00:13 0:00:00

adhoc • oracle
┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━┓
┃ Trials ┃ Exceptions ┃  Mean ┃
┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━┩
│      1 │          0 │ 1.000 │
└────────┴────────────┴───────┘

┏━━━━━━━━┳━━━━━━━┓
┃ Reward ┃ Count ┃
┡━━━━━━━━╇━━━━━━━┩
│ 1.0    │     1 │
└────────┴───────┘

Job Info
Total runtime: 13s
Results written to jobs/2026-08-12__11-49-49/result.json
Inspect results by running `harbor view jobs`
Share results by running `harbor upload jobs/2026-08-12__11-49-49`

11:50:09 - LiteLLM:WARNING: get_model_cost_map.py:290 - LiteLLM: Failed to fetch remote model cost map from https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json: The read operation timed out. Falling back to local backup.
[root@localhost test_demo]# 

Reward为1,说明demo已经跑通了,可以看一下具体结果行数是不是4

shell 复制代码
[root@localhost test_demo]# cat jobs/2026-08-12__11-49-49/exam_task_test__hNpKdip/verifier/test-stdout.txt 
实际ERROR行数:4,期望:4
PASS:提取ERROR日志正确

五、备注

1、目录格式名称需要严格限制:数据集模板目录结构、文件名不能随意改动;task.toml、instruction.md、environment/、tests/、solution/ 为框架识别固定目录名,不能改名。

2、Dockerfile 尽量使用 slim 基础镜像,减小构建耗时;脚本拷贝完成后,shell 脚本考虑是否加加 chmod +x 赋予可执行权限。

3、instruction.md 任务中不要写依赖外部网络的操作,沙箱容器默认隔离外网;明确写清楚输出文件绝对路径,Agent 容易混淆相对 / 绝对路径;不要在指令中暗示答案,只描述业务需求。

4、test.sh最后是需要写入到/logs/verifier/reward.txt中的,harbor会自动挂载这个目录,不需要提前新建。

5、数据集模板中禁止携带 jobs 目录,该目录是 harbor run 运行时输出目录,原始数据集模板中必须删除;如果残留 jobs 目录,加载数据集会产生干扰。

六、常用命令

shell 复制代码
# 1、本地开发调试:oracle参考解执行器,加载当前目录任务(不走大模型,校验数据集逻辑)
harbor run -p . -a oracle

# 2、仅构建/初始化环境,不执行agent任务(替代dry‑run,做预校验)
harbor run -p . -a oracle --install-only --n-tasks 1

# 3、oracle模式,跑完**不删除容器**,方便排查现场(--no-delete)
harbor run -p . -a oracle --no-delete --n-tasks 1

# 4、真实大模型agent评测,限制只跑1个样本,并发1
harbor run -p . -a code-agent -m gpt-4o-mini -n 1 --n-tasks 1

# 5、使用历史job配置文件复现实验
harbor run -c ./jobs/xxx/config.json

# ========== 数据集管理 ==========
# 查看registry仓库内数据集(本地手写task不会出现在列表)
harbor dataset list

# 初始化顶层dataset集合(用于打包发布;单task开发建议手动建目录)
harbor init ./test_demo

# ========== 结果查看 & 清理 ==========
# 打开web页面浏览任务轨迹trajectory
harbor view ./jobs/2026-08-05__11-24-24

# 清理缓存、环境残留
harbor cache clean
相关推荐
康娜喵1 小时前
在Ubuntu26上使用Docker部署Gitea
docker·容器·gitea
东宇科技2 小时前
我用docker创建了一个springboot4项目
阿里云·docker·容器
梦梦代码精11 小时前
连锁品牌数字化:从门店扩张到用户资产运营的技术底座
大数据·人工智能·低代码·docker·开源·代码规范
InfinitePlus14 小时前
Docker MySQL搭建一主一从
mysql·docker
坐吃山猪17 小时前
Docker07-MySQL
mysql·docker·容器
Wzx19801217 小时前
python沙箱和docker沙箱你选对了吗?
开发语言·python·docker
CodeDevMaster17 小时前
关于PaddleOCR-VL部署与使用说明
docker·llm
Ghost Face...19 小时前
龙芯Docker全流程:安装到离线迁移实战
java·docker·eureka
JavaPub-rodert1 天前
我又把自己的 Go 后台管理系统升级了一遍:文件管理、2GB 上传、私有文件预览、Docker 镜像全安排上了
开发语言·docker·golang·shiyuadmin