Skip to content

feat(sight): add conversation grader#1349

Closed
haoowa wants to merge 9 commits into
alibaba:mainfrom
haoowa:feat/sight-grader-mvp
Closed

feat(sight): add conversation grader#1349
haoowa wants to merge 9 commits into
alibaba:mainfrom
haoowa:feat/sight-grader-mvp

Conversation

@haoowa

@haoowa haoowa commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Description

Adds a manual AgentSight conversation grader MVP for persisted agent-quality evaluation. The change introduces a rule-based grader over GenAI and interruption evidence, SQLite-backed idempotent evaluation runs, dashboard controls for running and viewing evaluations, and ATIF deeplinks for evidence navigation.

It also fixes capture and scoring issues found while validating the grader flow: manually interrupted streamed calls are persisted as pending evidence, successful assistant text is no longer misclassified as runtime interruption text, and Anthropic request-side tool_result blocks are preserved as structured tool-call responses for deterministic tool-failure grading.

Related Issue

Closes #1304

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional change)
  • Performance improvement
  • CI/CD or build changes

Scope

  • cosh (copilot-shell)
  • cosh-ng (cosh-ng)
  • sec-core (agent-sec-core)
  • skill (os-skills)
  • sight (agentsight)
  • tokenless (tokenless)
  • ckpt (ws-ckpt)
  • memory (agent-memory)
  • anolisa (anolisa-cli)
  • skillfs (SkillFS)
  • Multiple / Project-wide

Checklist

  • I have read the Contributing Guide
  • My code follows the project's code style
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the documentation accordingly
  • For cosh: Lint passes, type check passes, and tests pass
  • For cosh-ng: cargo clippy --all-targets -- -D warnings and cargo fmt --check pass
  • For sec-core (Rust): cargo clippy -- -D warnings and cargo fmt --check pass
  • For sec-core (Python): Ruff format and pytest pass
  • For skill: Skill directory structure is valid and shell scripts pass syntax check
  • For sight: cargo clippy -- -D warnings and cargo fmt --check pass
  • For tokenless: cargo clippy -- -D warnings and cargo fmt --check pass
  • For memory (Linux only): cargo clippy --all-targets -- -D warnings, cargo fmt --check, and cargo test pass
  • For anolisa: cargo clippy --all-targets --locked -- -D warnings, cargo fmt --all --check, and cargo test --locked pass
  • For skillfs: cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings, and cargo test --workspace pass
  • Lock files are up to date (package-lock.json / Cargo.lock)

Testing

Ran on the Linux AgentSight test host:

  • cargo fmt --all -- --check
  • cargo clippy -- -D warnings
  • cargo test
  • cargo test -p agentsight grader --locked
  • cargo test -p agentsight genai::call_builder --locked
  • cargo test -p agentsight aggregator::http::aggregator --locked
  • cargo test -p agentsight interruption::detector --locked
  • cd dashboard && npm run typecheck
  • cd dashboard && npm test -- src/test/apiClient.test.ts src/test/EvaluationBadge.test.tsx src/test/EvaluationPanel.test.tsx src/test/ConversationList.test.tsx src/test/AtifViewerPage.test.tsx
  • make install INSTALL_PROFILE=system SETCAP=1
  • systemctl restart agentsight
  • curl -sS -m 5 http://127.0.0.1:7396/health

Deployment smoke result:

  • Service state: active
  • Health response: {"status":"ok","version":"0.7.0"}

Additional Notes

The grader is intentionally manual for the MVP. It reuses completed runs for the same target, input hash, grader type, and grader version, while producing a new run when the captured input or grader version changes.

Historical rows whose normalized input_messages already dropped Anthropic tool_result blocks are not backfilled by this PR. New captures preserve those blocks as structured evidence so the grader can score tool failures without scanning raw event JSON and reintroducing prompt-context false positives.

haoowa added 6 commits July 6, 2026 15:22
Add a rule-based conversation evaluation pipeline with stable input hashing, SQLite persistence, and manual API endpoints.

This keeps the MVP deterministic over captured GenAI and interruption evidence so repeated evaluations can reuse completed runs. LLM and agent graders remain reserved extension points.

Assisted-by: Codex
Signed-off-by: wanghao <1562495626@qq.com>
Add dashboard controls for fetching, running, and displaying persisted conversation evaluations with evidence deeplinks into ATIF.

The UI keeps evaluation manual so users decide when to grade a snapshot, while still surfacing saved verdicts in conversation rows. Pending snapshots require explicit force evaluation from the panel.

Assisted-by: Codex
Signed-off-by: wanghao <1562495626@qq.com>
Drain idle in-flight HTTP states and persist them as pending GenAI calls when a stream is abandoned while the agent process stays alive.

Manual output interruption does not necessarily kill the process, so dead-PID draining cannot recover these sessions. This preserves the captured request as pending evidence; unsupported states are skipped.

Assisted-by: Codex
Signed-off-by: wanghao <1562495626@qq.com>
Classify timeout keywords only from structured call errors and inspect response bodies for provider errors only on non-success status codes.

Successful assistant text can legitimately mention timeout, auth, rate limits, or context limits as troubleshooting content. This keeps interruption detection focused on runtime failures; provider-specific wording still depends on captured error fields.

Assisted-by: Codex
Signed-off-by: wanghao <1562495626@qq.com>
Convert Anthropic request content blocks into unified message parts, including tool_use, tool_result, and thinking blocks.

The grader relies on structured input evidence instead of raw event JSON to avoid prompt-context false positives. Historical rows are unchanged; new captures preserve tool failures for deterministic scoring.

Assisted-by: Codex
Signed-off-by: wanghao <1562495626@qq.com>
Document the manual conversation grader APIs, persistence model, current rule version, and dashboard-facing changelog entries.

Keeping the operational guide and semantic design note together makes the MVP discoverable without changing runtime behavior. The repository documentation-standard file was not present in this worktree, so this keeps the doc change narrowly scoped.

Assisted-by: Codex
Signed-off-by: wanghao <1562495626@qq.com>
@CLAassistant

CLAassistant commented Jul 6, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions Bot added component:sight src/agentsight/ scope:documentation ./docs/|./*.md|./NOTICE labels Jul 6, 2026
@haoowa haoowa force-pushed the feat/sight-grader-mvp branch from 33a7efe to ba8c19f Compare July 6, 2026 08:06
Apply current Clippy mechanical suggestions in AgentSight code touched by the PR and adjacent existing paths.

This keeps the community preflight check `cargo clippy -- -D warnings` passing on the Linux test host without changing runtime behavior.

Assisted-by: Codex
Signed-off-by: wanghao <1562495626@qq.com>

@chengshuyi chengshuyi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review 意见

总体评价

功能完整且设计合理的 MVP 对话评估模块。核心架构清晰:rule-based grader 五维评分、SQLite 幂等持久化、手动触发模式。同时修复了中断检测误报、Anthropic tool result 丢失和空闲流丢弃等问题。代码质量整体较高,无 unwrap/expect/dbg 违规,SQL 使用参数化查询,错误处理链路完整。

主要建议:拆分为多个 PR

当前 PR 共 3244 行 / 31 文件,远超 AGENTS.md 中 800 行的硬性限制。建议按职责拆分为 3-4 个独立 PR,便于 review 和回溯:

  1. fix(sight): avoid false interruption signals — 中断检测误报修复(~85 行)。这个改动独立且逻辑严谨,区分了 structured_error(仅 error 字段)和 response_error_body(status >= 400),附带 5 个精确的回归测试,建议单独合入。

  2. fix(sight): persist idle streamed calls + preserve Anthropic tool results — 聚合器 idle 流排空 + Anthropic tool_result 保留修复(~250 行)。两者都是数据采集层面的 bug fix,关联性强。

  3. feat(sight): add conversation grader API — grader 后端模块(~1800 行)。作为 Level 3 新功能可接受,但仍偏大,可考虑将 rule.rs 的测试拆到独立文件。

  4. feat(sight): add grader dashboard controls — 前端 UI(~700 行)。与后端解耦,可独立 review。

其他需要关注的 finding

Major:

  • evict_idle_and_oversized 不再驱逐 oversized 非 Idle 连接 — 当连接 body 超过 max_body_bytes 但状态不是 Idle 时,被加入 to_evict 列表但在内部 if matches!(..., ConnectionState::Idle) 检查时被跳过,导致不被移除。下次调用仍会重复此过程,连接永远留在内存中直到状态转为 Idle。建议 oversized 的非 Idle 连接至少有一个最终保护机制,防止异常大请求导致内存耗尽。

  • 每个 grader API 请求都新建 SQLite 连接evaluate_graderlatest_grader handler 中每次都调用 EvaluationStore::new_with_path(),执行 CREATE TABLE IF NOT EXISTS + schema 初始化。建议将 EvaluationStore 加入 AppState 作为 Arc<EvaluationStore>,与 InterruptionStore 保持一致的使用模式。

Minor:

  • load_conversation_interruptions 硬编码了 interruption DB 路径推导(假设与 storage_path 同目录),如果上游修改了命名或位置会静默返回空结果。建议从 config 或 AppState 中获取路径。

  • evaluate_grader handler 在 SQLite 锁内执行 CPU 评估(load_conversation_inputRuleGrader::evaluatestore.insert_completed 全程持有 Mutex),建议分离加载/评估/持久化步骤,仅在 SQL 操作时持有锁。

亮点

  • 中断检测误报修复逻辑严谨,区分了哪些关键字应扫描 response body(如 context_length_exceeded),哪些只应匹配 error 字段(如 timeout
  • 幂等评估设计 — (target_type, target_id, input_hash, grader_type, grader_version) 唯一约束 + INSERT OR IGNORE + 重试查找
  • Anthropic tool result 保留完整覆盖了 Text/ToolUse/ToolResult/Thinking 四种 content block 类型
  • 评估规则版本化 — RULE_GRADER_VERSION 参与幂等键和 input hash 计算,版本升级自动触发重新评估

haoowa added 2 commits July 8, 2026 15:00
Keep only SQLite reads and writes under the EvaluationStore mutex.

JSON serialization and record conversion now run outside the lock, which addresses the review concern without changing the rule grader execution path.

Assisted-by: Codex
Signed-off-by: wanghao <1562495626@qq.com>
Reuse the grader evaluation store from server state instead of reopening SQLite on each API request.

Load interruption evidence from the existing interruption store rather than deriving a sibling database path, and add regression coverage for oversized request-body eviction.

Assisted-by: Codex

Signed-off-by: wanghao <1562495626@qq.com>
@haoowa

haoowa commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

已处理本轮 review 里可直接落地的 finding,并准备按职责拆分 PR。

当前大 PR head 已追加两类 review 修复:

  1. SQLite 锁范围:复核后 RuleGrader::evaluate 并不在 EvaluationStore 的 mutex 内执行;同时已进一步收窄 store 内部锁范围,把 JSON serialization / record conversion 移到锁外,只保留 SQLite read/write 在锁内。
  2. Grader store 复用:EvaluationStore 已加入 AppStateevaluate_grader / latest_grader 不再每个请求重新打开 SQLite 并初始化 schema。
  3. Interruption DB 路径:load_conversation_input 改为使用 server 注入的 InterruptionStore,不再硬编码推导 sibling interruption_events.db 路径。
  4. Oversized eviction:当前实现会驱逐 oversized RequestBodyPending 连接;已新增回归测试锁住非 Idle oversized 连接和 side cache 一起清理的行为。

已在 Linux AgentSight 测试机验证:

  • cargo fmt --all -- --check
  • git diff --check
  • cargo test -p agentsight grader --locked --quiet
  • cargo test -p agentsight aggregator --locked --quiet
  • cargo clippy -p agentsight --all-targets --locked -- -D warnings

接下来按 review 建议拆成独立 PR,避免继续在这个大 PR 上叠加:

  • fix(sight): avoid false interruption signals
  • fix(sight): persist idle streams and Anthropic tool results
  • feat(sight): add conversation grader API
  • feat(sight): add grader dashboard controls

拆分完成后,这个大 PR 会被替换为上述 smaller PRs。

@haoowa

haoowa commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

已按 review 建议拆分为 smaller PRs:

这个聚合 PR 不再继续 review,后续请看上述拆分 PR。

@haoowa haoowa closed this Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component:sight src/agentsight/ scope:documentation ./docs/|./*.md|./NOTICE

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[sight] feat(sight): add trajectory grader for agent quality evaluation

3 participants