AgentEvalTool/AGENT.md
sinohqb a77cd83e6a v0.2.0-dev: 文件管理 + 页面布局统一 + 6 个 bug 修复
## 新增功能
- 文件管理模块:分类树 + 文件上传/下载/删除
- 文件上传支持拖拽(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>
2026-07-16 15:25:22 +08:00

215 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AgentEvalTool — AI Agent 项目知识
> 本文件为 AI 助手提供项目上下文,帮助快速理解项目并参与开发。
## 项目概述
**AgentEvalTool** 是智能体质量评估工具集平台,评估 AI 数字员工(大模型 + RAG和 AI 助手OpenClaw的服务质量。核心闭环定义评估 → 执行评估 → 分析结果 → 改进优化。
- **当前版本**: v0.2.02026-07-14里程碑「稳」
- **运行环境**: t480 测试服务器192.168.8.145:8001
- **语言**: Python 3.11(后端) + TypeScript/React 18前端
## 里程碑路线图
| 版本 | 代号 | 日期 | 主题 | 状态 |
|---|---|---|---|---|
| v0.1 | MVP | 2026-07-09 | 核心闭环跑通 | ✅ 已发布 |
| **v0.2** | **「稳」** | **2026-07-14** | **async 引擎 + 安全基线 + 测试 + 部署规范化** | **✅ 已发布(t480)** |
| v0.3 | 「拓」 | 规划中(2026-08) | 多通道 + 规则扩展 + OpenClaw 深度集成 | 📋 规划中 |
| v0.4 | 「展」 | 远景 | 多租户 / SSO / 监控告警 / 对外服务 | 💭 远景 |
详细路线图见 [docs/release-notes-v0.2.md](docs/release-notes-v0.2.md) 第八节。
## 技术栈
### 后端
- **框架**: FastAPI + Uvicorn
- **ORM**: SQLModel基于 SQLAlchemy
- **CLI**: Typer + Rich
- **数据库**: SQLiteStaticPool 模式)
- **模板引擎**: Jinja2HTML 报告)
- **关键依赖**: Pydantic v2、requests、PyYAML
### 前端
- **框架**: React 18 + TypeScript + Vite 5
- **UI 库**: Ant Design 5.x + ProComponents
- **代码编辑**: Monaco EditorJSON 场景编辑)
- **图表**: @ant-design/charts
- **路由**: react-router-dom v6
- **HTTP**: axios带请求拦截器和统一错误提示
## 项目结构
```
AgentEvalTool/
├── backend/
│ ├── agenteval/ # 核心 Python 库
│ │ ├── agents/ # EvalAgent 抽象SimpleAgent
│ │ ├── channels/ # 消息通道TutuApiChannel
│ │ ├── evaluation/ # 评测引擎 + 规则
│ │ │ └── rules/ # keyword_match, response_time, llm_score
│ │ ├── scenarios/ # 场景加载/校验
│ │ ├── storage/ # SQLite + Repository 模式
│ │ └── web/ # FastAPI 后端
│ │ ├── routers/ # targets, scenarios, runs, reports, stats
│ │ └── websocket.py # WebSocket 实时进度推送
│ ├── cli/ # CLI 入口Typer
│ └── plugins/openclaw/ # OpenClaw 插件示例
├── frontend/web/ # React 前端Vite + Ant Design
├── config/config.json # tutu-api 配置(敏感信息)
├── data/ # SQLite DB + 场景 YAML + 报告输出
├── deploy/t480/ # Docker 部署配置
├── docs/ # 版本化文档集
├── scripts/mock_call.py # 历史参考脚本
└── pyproject.toml # hatchling 构建 + 依赖定义
```
## 核心架构
### 消息通道EvalChannel
- 抽象接口:`send()` / `poll_reply()` / `health_check()`
- V1 实现:`TutuApiChannel`HTTP + Bearer Token + questionMsgId 配对)
- 工厂模式:`ChannelFactory` 按 channel_type 创建实例
### 评测引擎EvalEngine
- 遍历 Scenario.cases → 每个 case 遍历 messages多轮对话
- 发送消息 → 轮询回复 → 记录 Turn → 执行规则 → 保存 EvalResult
- 支持 `progress_callback` 实时推送事件WebSocket 集成)
- 支持 `existing_run` 参数复用已有 run 记录
### 评估规则EvalRule
- `keyword_match`:关键词包含/排除匹配
- `response_time`:响应时间阈值检查
- `llm_score`LLM-as-judge 评分OpenAI 兼容 API
### 数据模型
- `EvalTarget``EvalRun``Scenario`
- `EvalRun``Turn`(对话轮次)
- `EvalRun``EvalResult`(规则结果)
## 部署知识
### t480 测试服务器
- **地址**: sola-t480192.168.8.145
- **端口**: 8001映射容器内 8000
- **部署方式**: Docker Compose 双容器agenteval + openclaw-eval
- **Python 镜像**: python:3.11.15-slim-bookworm
- **APT/Pip 镜像**: 阿里云(绕过 GFW
### 版本号(单一数据源)
- **pyproject.toml** 是版本号的唯一来源
- **package.json** 的版本号由 `scripts/sync_version.py` 自动同步
- 每次部署前必须运行 `python3 scripts/sync_version.py`deploy 脚本会自动做)
- 镜像 tag 同时打 `t480-agenteval:<version>``t480-agenteval:latest`
### 部署流程(标准)
```bash
# 推荐: 一键部署build/sync/rebuild/verify 全包)
scripts/deploy-t480.sh
# 仅代码变更(跳过镜像重建, backend 通过 volume 热加载)
scripts/deploy-t480.sh --skip-build
# 预览命令, 不实际执行
scripts/deploy-t480.sh --dry-run
```
脚本会自动:
1. 同步版本号 `pyproject.toml → package.json`
2. `npm run build` 构建前端
3. rsync 代码 + dist 到 t480
4. `docker compose build --build-arg BUILD_COMMIT=... --build-arg BUILD_TIME=...`
5. `docker tag t480-agenteval:<version>`
6. `docker compose up -d`(容器启动时自动跑 `alembic upgrade head`
7. curl `/api/health` 验证版本号和 commit 一致
### 部署验证
```bash
curl http://192.168.8.145:8001/api/health
# 返回: {"status":"ok","version":"0.2.0-dev","commit":"abc1234","built_at":"2026-07-14T10:33:41Z"}
# 如果 version 不匹配本地 pyproject.toml → 部署失败, 脚本会报错退出
```
### 关键 Volume 挂载
- `data/``/app/data`SQLite DB + 报告 + openclaw 状态, 可写)
- `config/config.json``/app/config/config.json:ro`
- `frontend/web/dist/``/app/frontend/web/dist:ro`**必须 build 后再部署**
- `backend/``/app/backend:ro`(代码热更新)
- `.env``/app/.env:ro`Pydantic Settings 配置, 见 `.env.example`
### 镜像 tag 约定
- `t480-agenteval:<version>` — 不可变, 对应某次具体构建
- `t480-agenteval:latest` — 可变, 总是指向最新部署
- 回滚: `docker tag t480-agenteval:<old-version> t480-agenteval:latest && docker compose up -d`
## 重要踩坑记录
### 1. SQLite + FastAPI 必须用 StaticPool
- 默认 QueuePool 在多线程环境下快速耗尽
- `check_same_thread=False` + `StaticPool` 是 SQLite 的正确配置
### 2. Docker COPY vs Volume 挂载
- Dockerfile 中 `COPY backend ./backend` 烘焙的代码不会随 rsync 更新
- 必须通过 volume 挂载 `backend/` 才能实现代码热更新
- 只有 Dockerfile 或 Python 依赖变更时才需要 `--build`
### 3. Session 生命周期管理
- 所有 Router 必须使用 `Depends(get_db)` 管理 Session
- `get_db()` 是 generator`finally` 中 `session.close()` 确保连接释放
- 后台任务也需要 `try/finally` 关闭 Session
### 4. EvalEngine.run() 与 API 端点的 run 创建
- API 端点先创建 runpending返回 run_id 给前端
- 后台任务通过 `existing_run` 参数复用该记录,避免重复创建
### 5. 中国网络环境
- Docker Hub 和 npm 在国内访问极慢或被墙
- 使用阿里云 APT/Pip 镜像
- Clash 代理不可靠时,优先使用镜像策略
### 6. 前端 dist 必须显式构建再部署
- `frontend/web/dist/` 是构建产物, 不是源码
- rsync 时如果 `--exclude='frontend/web/dist'`, t480 会一直跑旧 dist, 看起来像"页面回到老版本"
- 必须 `npm run build` 之后再 rsync, 或者直接用 `scripts/deploy-t480.sh`(自动做这两步)
- 部署后用 `curl /api/health` 验证 version/commit 和本地一致, 脚本会自动做
### 7. OpenClaw 免登录依赖 Origin 注入
- OpenClaw 的 `gateway.controlUi.allowedOrigins` 检查 WebSocket 的 Origin header
- `proxy.py` 必须注入 `origin=http://192.168.8.145:8001`(或 settings.allowed_origins 的第一项)
- 如果 Origin 缺失, OpenClaw 拒收 WS 连接, SPA 会显示登录页
- v0.2 起 `openclaw_ws_origin``allowed_origins` 自动推导, 不再硬编码
## CLI 命令速查
```bash
agenteval target add --name "名称" --config config/config.json
agenteval target list
agenteval target test <id>
agenteval scenario import data/scenarios/xxx.yaml
agenteval scenario list
agenteval run start --target-id <id> --scenario-id <id>
agenteval run list
agenteval report show <run-id> --format json
agenteval report generate <run-id> --format html
agenteval server start --host 0.0.0.0 --port 8000
```
## 当前数据t480
- **评测对象**: 1社区医院AI客服tutu-api 通道)
- **评测场景**: 2社区医院基础服务评测 + 科室导航与挂号咨询)
- **API 端点**: `http://192.168.8.145:8001/`
- **WebSocket**: `ws://192.168.8.145:8001/ws/runs/{run_id}`
## 开发约定
- Python 代码使用 `ruff` 做 lintline-length 120, target py310
- 前端 TypeScript 使用 `tsc --noEmit` 类型检查
- 文档文件名带版本号(如 `architecture-v1.0.md`
- 用户偏好简体中文交互