AgentEvalTool/.scratch/v0.7/spec.md
sinohqb e1e067bac4 feat(models): add analysis-default flag for campaign intelligence
Introduce ModelPurpose.ANALYSIS and a globally-unique is_analysis_default
marker on chat model configs so campaign analysis can resolve its model.
Service rejects disabled or non-chat configs; repo clears the previous
holder on set. Documented the analysis role in CONTEXT.md.
2026-08-03 01:46:51 +08:00

88 lines
9.5 KiB
Markdown
Raw Permalink 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.

# v0.7 — 活动智能分析(分析 Agent + 结构化分析报告)
## Problem Statement
评测工程师拿到活动报告时,看到的是一堆聚合数字(通过率、可用性、时延、趋势、分场景汇总),但「这个数字意味着什么、哪里出了问题、接下来该改什么」需要人自己钻进几十条子运行里翻失败对话,耗时且依赖经验。尤其是正式线(实时 ×1活动跑完后团队期望直接拿到一份可读的专业研判总体结论、问题清单、改进建议——目前平台给不出。
## Solution
为活动引入「分析Analysis岗位」CONTEXT.md 已有术语):一个两阶段分析 Agent对活动聚合结果做活动级、跨场景的叙述性研判产出**结构化分析报告**(总体结论 + 问题诊断 + 分场景叙述 + 改善建议),嵌在活动报告抽屉顶部展示,证据可点击下钻到具体子运行。正式线活动完成后自动生成;调试线(加速)活动按需手动生成,结果缓存可重新生成。分析模型在模型配置中心设「分析默认」,活动创建时可覆盖。
## User Stories
1. 作为评测工程师,我希望正式线活动一完成就自动得到分析报告,以便不用记得去点按钮。
2. 作为评测工程师,我希望调试线活动不自动消耗分析模型的 token以便控制成本。
3. 作为评测工程师,我希望在报告抽屉里对终态活动随时手动生成/重新生成分析,以便在调整数据视角后拿到新研判。
4. 作为评测工程师,我希望进行中的活动不能生成分析,以便报告永远基于稳定数据。
5. 作为评测工程师,我希望报告开头有一段总体结论,以便 30 秒内知道这个活动行不行。
6. 作为评测工程师,我希望看到按严重度排列的问题诊断列表,每条注明涉及场景和证据,以便优先处理大问题。
7. 作为评测工程师,我希望问题证据能直接跳到对应子运行报告,以便核实模型研判是否属实。
8. 作为评测工程师,我希望每个场景有一段叙述性表现分析,以便理解数字背后的行为模式。
9. 作为评测工程师,我希望改善建议按优先级排序且可执行,以便直接转成下一步工作。
10. 作为评测工程师,我希望模型引用的证据都真实存在(不虚构 run_id以便信任报告。
11. 作为管理员,我希望在模型配置中心把某个 chat 模型设为「分析默认」,以便全平台统一分析口径。
12. 作为管理员,我希望「分析默认」全局唯一、设置时自动互斥,以便不用手动清理旧标记。
13. 作为评测工程师,我希望创建活动时能为该活动单独指定分析模型,以便重要活动用更强的模型。
14. 作为评测工程师,我希望未配置分析模型时得到明确引导(去配置中心设置),以便知道为什么没有分析。
15. 作为评测工程师,我希望分析失败时看到失败原因并能重试,以便区分是模型故障还是数据问题。
16. 作为评测工程师,我希望导出的活动 Markdown 报告包含分析区块,以便离线分享完整报告。
17. 作为评测工程师,我希望分析所用的模型配置被快照记录,以便事后追溯报告出自哪个模型。
18. 作为评测工程师,我希望报告抽屉里能区分「生成中 / 已完成 / 失败」状态,以便知道后台任务进展。
## Implementation Decisions
- **分析岗位**`ModelPurpose` 枚举新增 `ANALYSIS`。分析模型不按场景绑定(区别于出题/判卷),而是全局默认 + 活动覆盖CONTEXT.md 术语定义)。
- **分析默认标记**`model_configs` 表新增 `is_analysis_default` 布尔列Alembic 迁移batch modeserver_default 回填 false。仓储层参照 `is_default``clear_default` 模式保证全局唯一;仅启用的 chat 能力配置可设为分析默认(校验与 `is_default and not enabled` 同款)。模型配置中心 UI 在 chat 配置上提供「分析默认」标记。
- **活动覆盖**`campaigns` 表新增可空 `analysis_model_config_id` 列(迁移);创建活动 API 接受该字段(可空=跟随全局默认);创建表单左列「时间与速度」区加「分析模型」下拉(选项=启用的 chat 配置,默认项「全局默认(<默认配置名>)」)。
- **分析模型解析**`活动.analysis_model_config_id ?? 全局分析默认`。两者都无 → 自动触发跳过;手动触发返回 409/400 并提示去配置中心。
- **分析存储**:新表 `campaign_analyses`每活动一行upsert 覆盖):`campaign_id` 唯一、`status`generating/completed/failed、`result`(结构化 JSON可空、`model_config_id`(快照)、`error`(可空)、`triggered_by`auto/manual、`created_at`/`updated_at`。后台任务与 Runs 同款 `asyncio.Task` + `try/finally` 关 Session。
- **API**`GET /api/campaigns/{id}/analysis` → `{status, result?, error?, model_config_id?, updated_at?}`(从未生成时 status 为 none/空态);`POST /api/campaigns/{id}/analysis` → 触发生成(已存在则覆盖重跑);活动为进行中/计划中返回 400无分析模型可解析返回 400 且 detail 引导配置。
- **自动触发**`campaign_runner` 写入 COMPLETED 的同一处campaign_runner.py:232 附近),若 `time_scale == 1` 且可解析到分析模型,则 enqueue 分析后台任务。失败/取消的活动不自动触发。
- **两阶段分析 Agent**(新模块 `evaluation/analysis.py`
- 输入数据:复用 `generate_campaign_report` 的聚合结果(不重算,遵循 ADR-0002/0004 口径)+ 每场景最多 3 条代表性失败对话(取自失败子运行的 turn用户消息/回复/判定理由,各截断到合理长度)。
- 阶段一:每个场景一次 LLM 调用(并行 `asyncio.gather`)→ 该场景叙述 + 问题点草稿。
- 阶段二:汇总各场景产出 + 全局统计 → 总体结论 + 跨场景问题 + 优先级建议。
- 输出用 JSON schema 约束prompt 内嵌 schema + 解析校验,解析失败按失败处理可重试)。
- 证据白名单:`run_id` 必须在提供的数据集内,模型虚构的引用在落库前剔除。
- **结构化报告 schema**
```
{
"overall": str, # 总体结论(一段话)
"problems": [{"severity": "high"|"medium"|"low",
"title": str, "description": str,
"scenario_ids": [str],
"evidence_run_ids": [str]}],
"scenario_narratives": [{"scenario_id": str, "narrative": str}],
"suggestions": [{"priority": int, "text": str}]
}
```
- **前端报告抽屉**:顶部新增「智能分析」区块——状态行(生成中 spinner / 失败 error+重试 / 未生成时的生成按钮与状态说明 + 分析模型名);完成后渲染:总体结论 callout → 问题诊断列表(严重度 Tag、场景名、证据 chip 点击跳 `/reports?run=`)→ 分场景叙述 → 改善建议(按 priority 排序)。生成/重新生成按钮仅终态活动可用,进行中禁用并提示「活动完成后可生成」。
- **Markdown 导出**`render_campaign_markdown` 追加分析区块(有 completed 分析时),按 总体结论/问题诊断/分场景叙述/改善建议 拼段。
- **语言**:分析输出一律中文。
## Testing Decisions
好测试只测外部行为,不测实现细节。
- **唯一新 seam分析服务**`evaluation/analysis.py`),用假 LLM 客户端注入(先例:`tests/unit/mock_channel.py` 的 MockChannel、llm_score 的假网关。覆盖两阶段编排阶段一并行、阶段二汇总、JSON 解析失败→ failed 状态、run_id 白名单剔除虚构引用、无失败样例的场景也能产出叙述、无分析模型可解析→明确错误。
- **API 集成测试**(先例 `tests/integration/test_campaigns_api.py`GET 空态POST 触发→后台完成→GET 拿到结果;进行中活动 POST 400无分析模型 POST 400覆盖重跑 upsert 不新增行。
- **自动触发**runner 完成正式线活动后分析任务被 enqueue用假分析服务断言调用加速活动不触发。
- **分析默认唯一性**:仓储/服务层测试(设第二个分析默认时第一个被清;停用配置不能设为分析默认)——先例 `is_default` 现有测试。
- **迁移**Alembic upgrade 后两表新列存在且回填正确。
- **前端**:无测试框架,`npx tsc --noEmit` + `npm run build` + 浏览器实操验证(生成流程、状态展示、证据跳转、终态禁用)。
## Out of Scope
- **工具调用循环 Agent**function calling 让模型自主拉数据)——本批固定两阶段编排。
- **HTML/PDF 专业报告页**——本批结构化 JSON + 抽屉原生渲染 + Markdown 导出。
- **分析报告的历史版本**——重新生成即覆盖upsert不保留旧版。
- **分析结果的通知推送**完成提醒、Webhook
- **跨活动对比分析**。
- **进行中活动的增量分析**。
## Further Notes
- 分析输入完全来自既有聚合口径ADR-0002失败按 0.0 计入ADR-0004取消不计入分母分析 Agent 不重算数字,只做叙述性研判。
- 阶段一按场景并行,场景数 = 该活动 capability_summary 中出现的场景数;阶段二单次调用。
- 分析模型的上下文窗口/最大输出元数据沿用模型配置中心的描述性元数据不改变网关请求参数AGENTS.md 模型配置中心约定)。