真把 GPT-5 / Claude / 通义 / DeepSeek / Doubao / Kimi / Yi-Lightning / Step / GLM / Llama 等 15 个大模型 + 5 个企业场景全部接到一个画布 DAG 里,同时跑、实时打分、月度账单可视化
从 0 到 1 搭一套 AI Agent 评测沙箱 的完整路线,包含 Docker 部署 / 后端 Nest + Redis Streams / 前端 Nuxt + Antd / 关键源码 / 6 个工程坑。## 一、为什么要做 Agent 评测沙箱上一篇横评写完(见我前一篇文章),后台留言最多的不是"哪家模型最好",是:- “你的横评数据怎么跑的?能不能给个工具?”- “我自己想跑同一组 prompt 在 N 个模型,但每次手工切配置 + 算账单 + 比时延,太累”- “有没有一个画布,能直接拖个节点上去跑"于是这就是这个项目的起点——Agent 评测沙箱:你定义场景 + prompt + 评分标准,系统自动在 N 个模型上跑、实时打分、月度账单可视化。适用人群:- 企业 CTO / 中台架构师:选型时一次拍板,不再"换个模型重新评一次”- AI Agent 开发者:跑 prompt 工程的时候直接看哪家最稳- AI 创业者 / SaaS 老板:每月可视化大模型账单,知道钱花在哪里## 二、整体架构(一张图看清)[前端 Nuxt 3 + Antd] ↓ REST/SSE[后端 Nest + Redis Streams + BullMQ] ↓ ┌────────────────────┬───────────────────┐ │ │ │[评测引擎] [路由器 / DAG] [账单核算] │ │ │ └─→ [Model Adapter Layer:15+ providers] ←─┘ ↓ ┌──────────┬──────────┬──────────┬──────────┐ GPT-5 Claude 通义 DeepSeek Doubao Kimi Yi Step GLM Llama5 个核心模块:1. 画布 DAG:拖节点定义"场景 + prompt + 评分逻辑 + 路由策略"2. Model Adapter Layer:15+ 主流大模型的统一接口,新增模型 < 30 行代码3. 评测引擎:同一个 prompt 投喂到 N 个模型,异步并行跑 + 评分 + 落库4. 账单核算:按"次 / token / 模型 / 场景 / 日期"五维度聚合5. 可视化看板:实时跑分对比 + 月度账单趋势 + 漂移告警## 三、Docker 一键启动整套系统 6 个容器,docker-compose 一键起:yaml# docker-compose.yml(片段)version: '3.8'services: postgres: image: postgres:16 environment: POSTGRES_DB: sandbox POSTGRES_PASSWORD: ${PG_PASSWORD} volumes: ['./data/pg:/var/lib/postgresql/data'] redis: image: redis:7-alpine backend: build: ./backend environment: DATABASE_URL: postgres://postgres:${PG_PASSWORD}@postgres:5432/sandbox REDIS_URL: redis://redis:6379 OPENAI_API_KEY: ${OPENAI_API_KEY} ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY} DASHSCOPE_API_KEY: ${DASHSCOPE_API_KEY} # ... 15+ providers depends_on: [postgres, redis] ports: ['3001:3001'] worker: build: ./backend command: node dist/worker.js depends_on: [redis] deploy: replicas: 4 frontend: build: ./frontend environment: NUXT_PUBLIC_API_BASE: /api ports: ['3000:3000'] nginx: image: nginx:alpine volumes: ['./nginx.conf:/etc/nginx/nginx.conf:ro'] ports: ['80:80'] depends_on: [backend, frontend]启动:bashcp .env.example .env# 编辑 .env 填各家 API Key(15 个)docker compose up -ddocker compose logs -f backend# 浏览器打开 http://localhost5 分钟搞定。## 四、Model Adapter:15+ 模型一个接口适配层是这套沙箱的灵魂。所有模型对外都长一个样:typescript// shared/types.tsexport interface ChatRequest { prompt: string; system?: string; temperature?: number; responseFormat?: 'text' | 'json'; maxTokens?: number;}export interface ChatResponse { text: string; usage: { promptTokens: number; completionTokens: number }; costCny: number; // 单位:人民币 latencyMs: number; model: string; rawResponse?: any;}export interface ModelProvider { name: string; chat(req: ChatRequest): Promise<ChatResponse>; priceTable: { input: number; output: number }; // 每 1M token 价格(¥)}加一个新模型只要实现一个 Provider:typescript// providers/doubao.tsexport class DoubaoProvider implements ModelProvider { name = 'doubao-1.6-pro'; priceTable = { input: 4, output: 12 }; async chat(req: ChatRequest): Promise<ChatResponse> { const start = Date.now(); const resp = await fetch('https://ark.cn-beijing.volces.com/api/v3/chat/completions', { method: 'POST', headers: { Authorization: `Bearer ${process.env.DOUBAO_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'doubao-1.6-pro-32k', messages: [ ...(req.system ? [{ role: 'system', content: req.system }] : []), { role: 'user', content: req.prompt }, ], temperature: req.temperature ?? 0.7, response_format: req.responseFormat === 'json' ? { type: 'json_object' } : undefined, max_tokens: req.maxTokens ?? 2048, }), }); const data = await resp.json(); const usage = { promptTokens: data.usage.prompt_tokens, completionTokens: data.usage.completion_tokens }; return { text: data.choices[0].message.content, usage, costCny: (usage.promptTokens * 4 + usage.completionTokens * 12) / 1_000_000, latencyMs: Date.now() - start, model: this.name, }; }}GPT / Claude / 通义 / Kimi / Yi / Step / GLM / DeepSeek / Llama 也都是 30 行内。## 五、评测引擎:同 prompt 并行跑 N 个模型评测引擎拿到一个评测任务,会:1. 把任务拆成 N 个子任务(每个模型 1 个)2. 子任务进 BullMQ 队列,Worker 异步并行跑3. 全部完成后跑评分(LLM 评 + 规则评)4. 结果写入 PG + 推 SSE 到前端核心代码:typescript// services/evaluator.service.ts @Injectable()export class EvaluatorService { constructor( @InjectQueue('eval') private queue: Queue, private bus: EventBus, ) {} async runEvaluation(scenario: Scenario, modelIds: string[]): Promise<string> { const traceId = nanoid(); const subTasks = modelIds.map((m) => ({ traceId, modelId: m, scenario, })); await Promise.all(subTasks.map((t) => this.queue.add('chat', t))); return traceId; }}// workers/eval.worker.tsprocessor('chat', async (job) => { const { traceId, modelId, scenario } = job.data; const provider = providerRegistry.get(modelId); const resp = await provider.chat(scenario.prompt); const score = await scorer.score(scenario, resp); await prisma.evalResult.create({ data: { traceId, modelId, ...resp, score }, }); bus.emit(`eval.${traceId}.update`, { modelId, resp, score });});前端订阅 SSE,每个模型跑完就闪一个卡片出来。## 六、画布 DAG:拖节点定义评测流画布是基于 reactflow + 自定义节点的。节点类型:- Input 节点:场景 + prompt 模板 + 输入示例- Model 节点:选模型 + 选参数(temperature / max_tokens / response_format)- Scorer 节点:LLM 评 / 正则评 / JSON Schema 评 / 业务自定义- Aggregator 节点:聚合维度(模型 / 时延 / 成本 / 准确率)DAG 配置直接存 JSON:json{ "nodes": [ { "id": "in", "type": "input", "data": { "prompt": "把这段评论分类...", "examples": [...] } }, { "id": "m1", "type": "model", "data": { "modelId": "gpt-5" } }, { "id": "m2", "type": "model", "data": { "modelId": "claude-sonnet-4-6" } }, { "id": "m3", "type": "model", "data": { "modelId": "doubao-1.6-pro" } }, { "id": "score", "type": "scorer", "data": { "type": "json-schema", "schema": {...} } }, { "id": "agg", "type": "aggregator", "data": { "by": ["model"] } } ], "edges": [ { "from": "in", "to": "m1" }, { "from": "in", "to": "m2" }, { "from": "in", "to": "m3" }, { "from": "m1", "to": "score" }, { "from": "m2", "to": "score" }, { "from": "m3", "to": "score" }, { "from": "score", "to": "agg" } ]}执行时拓扑排序 + 异步推进,跟 LangGraph / Dify 思路一样,但是更轻、零依赖。## 七、账单核算:5 维度聚合 + 月度趋势每次 chat 调用都按下面这张表写入 model_call_log😐 字段 | 类型 | 说明 || ----------- | --------- | ------------------- || trace_id | uuid | 关联评测任务 || model_id | varchar | 模型 ID || scenario_id | varchar | 场景 ID || input_tokens | int | 提示 token || output_tokens | int | 输出 token |
| latency_ms | int | 时延(毫秒) || cost_cny | numeric | 单次成本(¥) || created_at | timestamp | 创建时间 |可视化看板按 5 个维度聚合:- 按 模型:各家这个月跑了多少次、花了多少钱- 按 场景:工单分类 / 合同抽取 / RAG / 代码 各占多少- 按 日期:日活调用量 + 成本走势- 按 时延分布:p50 / p90 / p99- 按 业务正确率漂移:本周 vs 上周实测看板效果:CTO 一眼能看出哪家模型本月暴涨、哪个场景过度依赖某家。## 八、6 个工程坑(直接抄)1. Provider 接口必须强约束——cost / latency / usage 都进 ChatResponse,不要业务方自己算2. chat 任务一定走队列异步——15 家模型同时调,同步等会 5-12 秒,前端卡死3. 失败要落库 + 告警——某家 502 / 鉴权过期 / 限流,得能看见,不能默默丢4. token 价格表跟着 .env 走——各家定期降价,价格写代码里就完蛋,改 env 重启就好5. 评分用 LLM 评要避免"裁判选手是同一家"——千万别用 GPT-5 评 GPT-5 的结果6. trace_id 串到日志 + DB + SSE——出问题能从前端 toast 一路追到 provider 报错## 九、上线 30 天真实使用数据我们把这套沙箱内部用 + 给 12 家客户试用,30 天数据:| 指标 | 数据 | 备注 || ---------------- | ---------- | -------------------------- || 接入模型数 | 15 | 主流海外 + 国产全覆盖 || 创建评测任务数 | 8,400 | 平均每天 280 个 || 总 chat 调用数 | 126,000 | 平均每任务 15 次模型并发 || 总评测成本 | ¥3,920 | 平均单次 ¥0.031 || 客户选型时间 | 3 天 → 4 小时 | 不需要"重新评一次" || 客户月度账单可视化 | 12/12 | 100% 接入 || 模型漂移告警次数 | 47 | 平均每模型 3 次/月 |客户反馈最多的是:“之前选模型要花一周,现在 4 小时,而且选完之后还能持续监控,这才叫工程化。”## 十、给不同人的建议如果你是:- 企业 CTO:照着搭一套,选型 + 持续监控全包了- AI 中台架构师:把这套沙箱接入你的中台,模型路由有数据支撑- AI 创业者:这套沙箱本身就是一个超贵 SaaS 的雏形,值得单独做产品- 个人开发者:fork 下来跑,15+ 家模型一键比对,prompt 工程效率翻倍模型今年换 GPT-5 明年换下一代,画布 DAG + Model Adapter + 评测引擎 + 账单核算这套基础设施 18 个月不被替代。—v2 路线图(已立项):- 自动 prompt 优化(根据评分结果自动改 prompt 直到分数过线)- 多轮对话评测(Agent 多轮 Tool Call,不仅单次 chat)- 离线评测集自动扩充(从生产流量回流到评测集)留个钩子:评论区扣个 “评测沙箱源码”,我把完整 docker-compose + 后端 Nest + 前端 Nuxt + 15 家 provider 实现 + 画布 DAG 节点定义整理一份单独发。> 写在最后:做 AI 中台 6 个月能搭一套评测沙箱就赚,CTO 真不在意你用谁家模型,在意的是"我能不能持续看到账单 / 时延 / 正确率漂移"。能看见的中台,才是企业愿意续费的中台。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐