## 新增功能 - 文件管理模块:分类树 + 文件上传/下载/删除 - 文件上传支持拖拽(Dragger)+ 手动上传(customRequest 模式) ## 页面布局统一(参照评测执行页) - 仪表盘/评测对象/评测场景/评测报告 全部改为全高 flex 布局 - 统一内联页头样式(h2 + 竖线分隔 + 描述) - 表格撑满高度、overflow 处理 - 每页添加刷新按钮 ## Bug 修复 - 分类树操作按钮 hover 不可见(CSS 规则缺失) - 文件上传失败(multipart boundary 缺失) - LLM API 响应 content blocks 数组格式支持(_extract_content_from_api_response) - response_time_max_ms 被静默忽略(隐式规则传空 params) - 空 messages 导致 IndexError 崩溃 - poll_reply 异常中止整个 run(缺 try/catch) - engine finally 未关闭 session - 3 个页面 UTC 时间戳解析偏差 8 小时 ## 后端 - EvalEngine: poll_reply 异常保护、空 dialog 保护、session 关闭 - LLM API 响应解析支持 content-block-array 格式 - 隐式 response_time 规则正确传递 max_ms 参数 ## 前端 - api.ts: 移除手动 Content-Type(让浏览器自动添加 boundary) - Files.tsx: customRequest 替代 beforeUpload、布局优化 - index.css: 分类树 hover 规则 - Targets/Scenarios/Home/Reports: 全高布局改造 - 3 个页面时间戳改用 formatDateTime()(修复 UTC 偏差) Co-Authored-By: Claude <noreply@anthropic.com>
12 KiB
12 KiB
AgentEvalTool v0.2 版本发布说明
版本: v0.2.0
日期: 2026-07-14
状态: 已发布(t480 开发线)
代号: 「稳」(Stability milestone)
作者: AgentEval Team
一、版本定位
v0.2 是 v0.1 MVP 之后的第一个稳定性里程碑,遵循「先稳后拓」的两步走战略中的第一步。核心目标:
让核心闭环(定义评测 → 执行评测 → 查看报告)具备生产可用性,为后续的平台化扩展(v0.3)打下坚实的工程基础。
战略上下文
v0.1 (2026-07-09) MVP 闭环跑通
│
├── v0.2 (2026-07-14) ← 你在这里:稳定性 + 工程债 + 安全基线
│
└── v0.3 (规划中) 多通道 + 规则扩展 + OpenClaw 深度集成
关键决策(用户确认 2026-07-14)
- 定位:两步走,先稳后拓
- 规模:个人/小团队(<10 人),SQLite 足够
- 引擎:async 全面重构
- OpenClaw:深度集成,插件双向调用
二、主要变更
2.1 EvalEngine 全面异步化(核心改造)
| 项目 | v0.1 | v0.2 |
|---|---|---|
| Engine 模型 | 同步串行,阻塞 event loop | 全 async/await,协作式并发 |
| 取消机制 | 假取消(只改 DB 状态) | 真取消(asyncio.Event + CancelledError) |
| 超时配置 | 硬编码 30s/60s | TimeoutConfig 数据类,可配置 |
| 并发执行 | 不支持 | max_concurrent_cases + Semaphore |
| 通道抽象 | 同步 send/poll_reply |
全 async,支持 poll 与 push 两种实现 |
| HTTP 客户端 | requests(每次新建连接) |
httpx.AsyncClient(连接池复用) |
关键文件改动
backend/agenteval/evaluation/engine.py— 全量 async 重写,run()/_run_case()/_generate_messages()全部 asyncbackend/agenteval/channels/base.py—EvalChannel三个方法全部async defbackend/agenteval/channels/tutu.py—requests→httpx.AsyncClient,实例级连接池backend/agenteval/web/routers/runs.py—BackgroundTasks→asyncio.Task注册表 + 真取消backend/agenteval/web/websocket.py— 删除broadcast_sync桥接,新增emit()异步回调backend/cli/run.py+cli/target.py—asyncio.run()包装,CLI 签名不变
2.2 安全基线(P0)
| 项 | v0.1 | v0.2 |
|---|---|---|
| 配置管理 | 硬编码在源码 | Pydantic Settings + .env 文件 |
| JWT token | 明文存 config/config.json 已 commit |
.gitignore 保护,.env.example 模板 |
| CORS | allow_origins=["*"] 硬编码 |
从 settings.allowed_origins 读取 |
| API 鉴权 | 无 | X-API-Key middleware(未配置时 no-op) |
| OpenClaw proxy | 硬编码 origin/token | 全部从 settings 读取 |
| OpenClaw Origin | 硬编码 http://192.168.8.145:8001 |
从 allowed_origins 自动推导 |
关键文件改动
backend/agenteval/config/settings.py— Pydantic Settings 模块,@model_validator自动推导openclaw_ws_originbackend/agenteval/web/deps.py— 集中get_db+require_api_keybackend/agenteval/web/routers/proxy.py— 零硬编码,全部从 settings 读取.gitignore/.env.example/config/config.example.json— 新建
2.3 存储层去债
| 项 | v0.1 | v0.2 |
|---|---|---|
| Schema 迁移 | create_all() 一次性 |
Alembic + 版本化 migration |
get_db |
5 个 router 重复定义 | 集中到 web/deps.py |
utcnow() |
已废弃的 datetime.utcnow() |
datetime.now(timezone.utc) |
| 级联删除 | 无 | ORM 级联 EvalRunDB → turns/results |
关键文件改动
migrations/— Alembic 初始化,baseline migration15c107310eea_baseline_add_llm_config.pybackend/agenteval/storage/db.py— 添加Relationship+cascade="all, delete-orphan"backend/agenteval/storage/repository.py— 新增RunRepository.delete()deploy/t480/Dockerfile— CMD 改为alembic upgrade head && agenteval server start
2.4 前端重构
| 项 | v0.1 | v0.2 |
|---|---|---|
useRunSession |
7 个 useState + 120 行 applyEvent |
useReducer + 纯函数 reducer |
| 对话渲染 | CaseBlock/CaseDetail/Reports 三处重复 | 抽出 TurnList 公用组件 |
| AI 生成消息 | 两处重复 | 抽出 GeneratedMessages |
| 工具函数 | 分散在页面文件 | 集中到 utils/date.ts / utils/colors.ts |
| Reports 页 URL query | 不读取 ?run=xxx |
支持,可分享链接 |
关键文件改动
frontend/web/src/hooks/sessionReducer.ts— 纯函数 reducer(300+ 行),可单测frontend/web/src/hooks/useRunSession.ts— useReducer 化frontend/web/src/components/TurnList.tsx/GeneratedMessages.tsx— 新建frontend/web/src/utils/date.ts/colors.ts— 新建frontend/web/src/pages/Reports.tsx— 支持?run=xxxURL query
2.5 测试基线(从 0 起步)
| 测试文件 | 数量 | 覆盖 |
|---|---|---|
tests/unit/test_engine.py |
10 | async engine 并发/取消/超时/send 失败 |
tests/unit/test_cascade.py |
3 | ORM 级联删除(target/scenario/run) |
tests/unit/test_settings.py |
6 | openclaw_ws_origin 自动推导逻辑 |
tests/integration/test_runs_api.py |
5 | API 集成(list/start/cancel/logs/404) |
| 合计 | 24 | 57% 整体覆盖率(engine 61%, runs.py 86%, db.py 94%) |
基础设施
tests/conftest.py— tmp SQLite fixture + 表结构 sanity checktests/unit/mock_channel.py— 可配置 MockChannel(延迟/失败/缺失回复)pyproject.toml—asyncio_mode=auto,pythonpath=["backend", "."]
2.6 部署规范化
| 项 | v0.1 | v0.2 |
|---|---|---|
| 版本号 | 前后端独立维护 | pyproject.toml 单一数据源 |
| 部署流程 | 手动 rsync + docker compose up | scripts/deploy-t480.sh 一键部署 |
| 镜像 tag | 仅 latest |
<version> + latest 双 tag |
| 构建元数据 | 无 | /api/health 返回 version/commit/built_at |
| 部署验证 | 人工 | 脚本自动 curl + 校验 version/commit |
| .env 挂载 | 无 | docker-compose 挂载 .env 进容器 |
关键文件改动
scripts/deploy-t480.sh— 一键部署脚本(build/sync/rebuild/verify)scripts/sync_version.py— 版本号同步脚本backend/agenteval/version.py— 版本 + 构建元数据模块deploy/t480/Dockerfile—ARG BUILD_COMMIT/BUILD_TIME→ENV AGENTEVAL_BUILD_*deploy/t480/docker-compose.yml— 挂载.env+env_fileAGENT.md— 新部署流程 + 镜像 tag 约定 + 踩坑 #6/#7
三、关键 Bug 修复
| 编号 | 问题 | 根因 | 修复 |
|---|---|---|---|
| BUG-1 | 评测执行页点任务记录报 React #310 错误 | useMemo 在 early return 之后,违反 Hooks 规则 |
移动 useMemo 到 early return 之前 |
| BUG-2 | AI 助手页面显示登录页 | proxy.py 重构后 openclaw_ws_origin 默认 None,OpenClaw 拒收 WS |
@model_validator 从 allowed_origins 自动推导 |
| BUG-3 | 评测执行页回到老版本 | rsync 排除了 frontend/web/dist,t480 跑旧 dist |
deploy-t480.sh 强制 npm run build 后再 rsync |
| BUG-4 | 容器启动报 duplicate column: llm_config |
t480 DB 已手动 ALTER,但 Alembic 不知道 | docker run alembic stamp head 标记 baseline |
| BUG-5 | cancel API 是假取消 |
只改 DB 状态,Engine 线程继续跑 | Engine 接受 cancel_token,每个 case 边界检查 |
四、架构演进图
v0.1 (MVP)
├── 同步 EvalEngine → BackgroundTasks → SQLite (StaticPool)
├── 单通道 (tutu-api) / 3 规则 / HTML+JSON 报告
├── 零测试 / 硬编码敏感信息 / 无鉴权
└── 手动 rsync + docker compose up
v0.2 「稳」 ← 当前版本
├── async Engine + Semaphore + CancelToken → asyncio.Task 注册表
├── SQLite (aiosqlite 预留) + Alembic 迁移
├── APIKey 鉴权 / .env 配置 / 24 单测 + 集成测试 / CI 配置就位
├── 前端 useReducer 重构 useRunSession / 抽出 TurnList/GeneratedMessages
└── scripts/deploy-t480.sh 一键部署 + 镜像版本 tag + /api/health 验证
v0.3 「拓」(规划中)
├── 多通道 (tutu/http/openclaw) 插件化
├── 7 种规则 + 组合逻辑 (AND/OR/weighted)
├── 报告对比 + 模板外置
├── OpenClaw webhook 双向集成
└── 前端路由 + TanStack Query
五、文件改动统计
新增文件 (20):
backend/agenteval/config/__init__.py
backend/agenteval/config/settings.py
backend/agenteval/version.py
backend/agenteval/web/deps.py
migrations/{alembic.ini, env.py, script.py.mako, README}
migrations/versions/15c107310eea_baseline_add_llm_config.py
scripts/deploy-t480.sh
scripts/sync_version.py
tests/{conftest.py, __init__.py}
tests/unit/{mock_channel.py, test_engine.py, test_cascade.py, test_settings.py}
tests/integration/test_runs_api.py
frontend/web/src/hooks/sessionReducer.ts
frontend/web/src/hooks/useTicker.ts
frontend/web/src/components/{TurnList, GeneratedMessages}.tsx
frontend/web/src/utils/{date, colors}.ts
.gitignore, .env.example, config/config.example.json
重大改动 (10):
backend/agenteval/evaluation/engine.py (async 重写)
backend/agenteval/channels/{base, tutu}.py (async + httpx)
backend/agenteval/web/app.py (lifespan + /api/health)
backend/agenteval/web/routers/{runs, targets, scenarios, reports, stats, proxy}.py
backend/agenteval/storage/db.py (Relationship + cascade)
frontend/web/src/hooks/useRunSession.ts (useReducer)
frontend/web/src/pages/Reports.tsx (?run=xxx URL query)
deploy/t480/{Dockerfile, docker-compose.yml}
pyproject.toml, AGENT.md
六、已知问题
| 编号 | 问题 | 影响 | 计划修复 |
|---|---|---|---|
| KNOWN-1 | Repository 未抽象泛型基类 | 4 个 Repository 重复代码 | v0.3 评估收益后决定 |
| KNOWN-2 | _generate_messages 未测试 |
LLM 动态用例生成路径无覆盖 | v0.2 后续补 |
| KNOWN-3 | commit=no-git(项目未 git init) |
/api/health 无法显示真实 SHA |
用户决定后 git init |
| KNOWN-4 | 前端无单元测试 | reducer 已抽出但未写测试 | v0.3 引入 vitest |
| KNOWN-5 | Rules 覆盖率低(15-30%) | 规则逻辑无测试 | v0.3 规则扩展时同步补 |
七、部署验证
t480 当前状态(2026-07-14)
$ curl http://192.168.8.145:8001/api/health
{
"status": "ok",
"version": "0.2.0-dev",
"commit": "no-git",
"built_at": "2026-07-14T10:33:41Z"
}
$ docker ps
agenteval Up (healthy) t480-agenteval:0.2.0-dev
openclaw-eval Up (healthy) ghcr.io/openclaw/openclaw:latest
一键部署命令
scripts/deploy-t480.sh # 完整部署
scripts/deploy-t480.sh --skip-build # 仅代码变更
scripts/deploy-t480.sh --dry-run # 预览
八、下一步:v0.3 「拓」
v0.3 聚焦平台化能力扩展,预估工作量 4-5 周:
| 模块 | 目标 | 优先级 |
|---|---|---|
| 消息通道扩展 | HTTP + OpenClaw 通道实现 + entry_points 插件发现 | P0 |
| 评估规则扩展 | semantic_similarity / json_schema / safety / coherence + 组合逻辑 | P0 |
| OpenClaw 深度集成 | skill 触发评测 + webhook 完成通知(双向) | P1 |
| 报告能力升级 | 对比报告 / Markdown 导出 / 模板外置 | P1 |
| 场景能力增强 | 内置模板库 + 参数化场景 | P2 |
| 前端体验升级 | React Router data router + TanStack Query + 对比视图 | P2 |
九、致谢
v0.2 的完成得益于以下关键决策:
- 用户坚持「先稳后拓」的战略定力,避免了在 MVP 阶段过早平台化
- 选择 async 全面重构而非 Celery/RQ 任务队列,降低了运维复杂度
- 接受「小团队规模不需要多租户/PostgreSQL」的务实判断,避免了过度设计
下一个里程碑:v0.3 「拓」,预计 2026-08 中旬。