Some checks failed
CI / test (push) Failing after 38s
- 新增 release-notes-v0.4.md(事故排查 + 功能总结 + v0.5 候选方向) - AGENT.md 里程碑表更新至 v0.4 + 鉴权配置说明 - README / plan-v0.4 状态同步
230 lines
9.8 KiB
Markdown
230 lines
9.8 KiB
Markdown
# AgentEvalTool — AI Agent 项目知识
|
||
|
||
> 本文件为 AI 助手提供项目上下文,帮助快速理解项目并参与开发。
|
||
|
||
## 项目概述
|
||
|
||
**AgentEvalTool** 是智能体质量评估工具集平台,评估 AI 数字员工(大模型 + RAG)和 AI 助手(OpenClaw)的服务质量。核心闭环:定义评估 → 执行评估 → 分析结果 → 改进优化。
|
||
|
||
- **当前版本**: v0.4.0-dev(2026-07-28 发布至 t480,里程碑「联」)
|
||
- **运行环境**: 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-07-17 | 多通道 + 规则扩展 + 模型配置中心 | ✅ 已发布(t480) |
|
||
| **v0.4** | **「联」** | **2026-07-28** | **AI 助手标准化(triggered_by) + 登录 + 仪表盘重构** | **✅ 已发布(t480)** |
|
||
| v0.5 | — | 规划中 | 前端测试 / 报告聚合看板 / OpenClaw 二期 / 多模态 | 📋 待规划 |
|
||
|
||
详细内容见 [docs/release-notes-v0.4.md](docs/release-notes-v0.4.md)。
|
||
|
||
## 技术栈
|
||
|
||
### 后端
|
||
- **框架**: FastAPI + Uvicorn
|
||
- **ORM**: SQLModel(基于 SQLAlchemy)
|
||
- **CLI**: Typer + Rich
|
||
- **数据库**: SQLite(StaticPool 模式)
|
||
- **模板引擎**: Jinja2(HTML 报告)
|
||
- **关键依赖**: Pydantic v2、requests、PyYAML
|
||
|
||
### 前端
|
||
- **框架**: React 18 + TypeScript + Vite 5
|
||
- **UI 库**: Ant Design 5.x + ProComponents
|
||
- **代码编辑**: Monaco Editor(JSON 场景编辑)
|
||
- **图表**: @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-t480(192.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`)
|
||
|
||
### 鉴权(v0.4 起)
|
||
- `AGENTEVAL_ADMIN_PASSWORD`:设置后 Web UI 需登录(会话 token, 关浏览器失效);不设则无登录门
|
||
- `AGENTEVAL_API_KEY`:机器调用凭据(X-API-Key);deploy 脚本会把它写入 openclaw 工作区
|
||
`data/openclaw/agenteval-api-key`, agenteval-run skill 自动读取
|
||
- 两个凭据任一匹配即放行(`web/deps.py: require_auth`);`/api/health` 与 `/api/auth/*` 始终开放
|
||
|
||
### 镜像 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 端点先创建 run(pending),返回 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` 做 lint(line-length 120, target py310)
|
||
- 前端 TypeScript 使用 `tsc --noEmit` 类型检查
|
||
- 文档文件名带版本号(如 `architecture-v1.0.md`)
|
||
- 用户偏好简体中文交互
|
||
|
||
## CI 检查
|
||
|
||
- `scripts/ci-check.sh` 一键跑:版本号一致性 + ruff + pytest + tsc(`--fast` 跳过 tsc)
|
||
- 本地 `git push` 会自动触发 pre-push hook 执行 `ci-check.sh --fast`(`.git/hooks/pre-push`,新 clone 需手动重装)
|
||
- Gitea Actions 工作流:`.gitea/workflows/ci.yml`(需 Gitea 实例启用 Actions + 注册 runner 才生效)
|
||
- 紧急绕过:`git push --no-verify`(仅限救急,事后必须补跑)
|
||
|