Skip to content

fix: wire metrics service to existing methods#193

Open
Yurzi wants to merge 2 commits into
NickCharlie:mainfrom
Yurzi:fix/metrics-service-method-mismatch
Open

fix: wire metrics service to existing methods#193
Yurzi wants to merge 2 commits into
NickCharlie:mainfrom
Yurzi:fix/metrics-service-method-mismatch

Conversation

@Yurzi

@Yurzi Yurzi commented Jun 10, 2026

Copy link
Copy Markdown

背景

重构整个项目为新架构(e46b634)之后,webui/services/metrics_service.py 里残留了对已不存在方法的调用,导致三个 WebUI 指标接口实际上一直失效:

调用的方法 实际情况
intelligence_metrics_service.calculate_metrics() 不存在,真实方法是 calculate_learning_efficiency(...)
database_manager.get_diversity_metrics() 不存在,无对应数据源
database_manager.get_affection_metrics() 不存在,真实方法是 get_all_user_affections()

由于调用都包在 try/except 内,运行时不会崩溃,但每次请求都抛 AttributeError、刷错误日志,并返回全 0 的兜底数据。对应日志:

AttributeError: 'IntelligenceMetricsService' object has no attribute 'calculate_metrics'
AttributeError: 'SQLAlchemyDatabaseManager' object has no attribute 'get_diversity_metrics'
AttributeError: 'SQLAlchemyDatabaseManager' object has no attribute 'get_affection_metrics'

修改内容

webui/services/metrics_service.py

  • 智能指标:先经 get_detailed_metrics / get_all_user_affections 收集输入,再调用真实的 calculate_learning_efficiency(...),并将 LearningEfficiencyMetrics 映射为约定的 {overall_score, dimensions, trends}
  • 好感度指标:改用 get_all_user_affections(group_id),真实计算平均好感度、用户数、高/低好感度人数(≥70 / ≤30)及五档分布。
  • 多样性指标:当前架构无独立数据源,基于风格模式数做透明近似估算,保持返回结构、不再刷错误日志。

测试

  • 更新 tests/conftest.py 中仍指向旧方法名的 mock,改为真实 API。
  • 新增 tests/integration/test_metrics_service_endpoints.py,覆盖 /api/intelligence_metrics/api/affection_metrics/api/diversity_metrics,断言返回真实计算数据且不含 error 字段。

验证

pytest tests/integration/test_metrics_service_endpoints.py

本地(含 astrbot 运行环境)整套集成测试通过。

🤖 Generated with Claude Code

Summary by Sourcery

Wire the WebUI metrics service to the current metrics and database APIs so the three metrics endpoints return real computed data instead of zeroed fallbacks.

New Features:

  • Expose learning-efficiency based intelligence metrics with a structured score and dimension breakdown from existing services.
  • Provide affection metrics derived from per-user affection levels, including aggregates and bucketed distribution.
  • Estimate diversity metrics from learned style pattern counts while preserving the existing response shape.

Tests:

  • Add integration tests for the intelligence, affection, and diversity metrics HTTP endpoints to ensure they use the correct services and return non-error, non-fallback data.
  • Update shared test fixtures to mock the new detailed metrics and affection APIs and the learning-efficiency metrics service.

Yurzi and others added 2 commits June 10, 2026 21:18
The big architecture refactor (e46b634) left MetricsService calling
methods that no longer exist:

- intelligence_metrics_service.calculate_metrics()
- database_manager.get_diversity_metrics()
- database_manager.get_affection_metrics()

Each call raised AttributeError on every request, spamming error logs
and making the three WebUI metrics endpoints always return zeroed
fallback data.

Rewire the three methods to the real APIs:

- intelligence: gather inputs via get_detailed_metrics /
  get_all_user_affections, then call calculate_learning_efficiency and
  map LearningEfficiencyMetrics to {overall_score, dimensions, trends}
- affection: compute from get_all_user_affections (average, user count,
  high/low counts, distribution buckets)
- diversity: best-effort estimate from style patterns, no error spam

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Update the stale conftest mocks that mirrored the removed methods
(get_diversity_metrics / get_affection_metrics / calculate_metrics) to
the real API now used by MetricsService (get_detailed_metrics /
get_all_user_affections / calculate_learning_efficiency).

Add integration tests for /api/intelligence_metrics, /api/affection_metrics
and /api/diversity_metrics asserting they return real computed data with no
error key, guarding against the AttributeError regression.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Wires the WebUI metrics service to the new post-refactor metrics/data APIs, replacing calls to removed methods with the correct implementations and adding integration tests to ensure the three metrics endpoints return real computed data instead of zeroed fallbacks.

Sequence diagram for updated get_intelligence_metrics flow

sequenceDiagram
    actor WebUI
    participant MetricsService
    participant DatabaseManager
    participant IntelligenceMetricsService

    WebUI->>MetricsService: get_intelligence_metrics(group_id)
    activate MetricsService

    MetricsService->>DatabaseManager: get_detailed_metrics(group_id)
    DatabaseManager-->>MetricsService: detailed_metrics

    MetricsService->>DatabaseManager: get_all_user_affections(group_id)
    DatabaseManager-->>MetricsService: affections

    MetricsService->>IntelligenceMetricsService: calculate_learning_efficiency(total_messages, filtered_messages, style_patterns_learned, persona_updates_count, affection_users_count)
    IntelligenceMetricsService-->>MetricsService: LearningEfficiencyMetrics

    MetricsService-->>WebUI: {overall_score, dimensions, trends}
    deactivate MetricsService
Loading

File-Level Changes

Change Details Files
Reimplement intelligence metrics to use detailed DB metrics and the new learning efficiency service API, mapping its result into the existing WebUI response shape.
  • Collect message and learning stats from database_manager.get_detailed_metrics with defensive typing and logging on failure.
  • Fetch affection users count from database_manager.get_all_user_affections with warning logs on failure.
  • Call intelligence_metrics_service.calculate_learning_efficiency with the collected inputs instead of the removed calculate_metrics method.
  • Convert the LearningEfficiencyMetrics-like object into the expected dict with overall_score, dimensions (rounded values plus active_strategies_count), and an empty trends list.
webui/services/metrics_service.py
Replace the broken diversity metrics implementation with an estimated metric derived from style pattern counts while preserving the response contract.
  • Remove calls to the non-existent database_manager.get_diversity_metrics API.
  • Fetch style_patterns from database_manager.get_detailed_metrics and compute a bounded style_diversity score as min(style_patterns * 2, 100).
  • Set vocabulary_diversity and topic_diversity to zero and compute total_score as the rounded average of the three sub-scores.
webui/services/metrics_service.py
Compute affection metrics directly from per-user affection records instead of calling a non-existent aggregate API.
  • Replace database_manager.get_affection_metrics with get_all_user_affections to retrieve raw affection items.
  • Parse and sanitize affection_level values into integer scores, ignoring malformed entries.
  • Derive total_users, average_affection, high_affection_count, low_affection_count from the levels list.
  • Build a five-bucket distribution (0–20, 21–40, 41–60, 61–80, 81–100) and return the full affection metrics payload.
webui/services/metrics_service.py
Update test fixtures to mock the new metrics-related APIs used by MetricsService.
  • Remove mocks for get_diversity_metrics and get_affection_metrics on the database manager mock.
  • Add mocks for get_detailed_metrics and get_all_user_affections with representative sample payloads, plus get_total_affection.
  • Change the intelligence metrics service mock to provide calculate_learning_efficiency returning a SimpleNamespace that mimics LearningEfficiencyMetrics fields.
tests/conftest.py
Add integration tests that exercise the three metrics HTTP endpoints end-to-end against dummy services using the new APIs.
  • Create DummyDatabaseManager and DummyIntelligenceMetricsService test doubles that implement get_detailed_metrics, get_all_user_affections, and calculate_learning_efficiency.
  • Monkeypatch the metrics blueprint container (get_container) to return the dummy services in a Quart test app.
  • Add tests asserting that /api/intelligence_metrics returns the mapped learning efficiency metrics without an error field.
  • Add tests asserting that /api/affection_metrics correctly aggregates counts, averages, and bucket distribution from raw affections.
  • Add tests asserting that /api/diversity_metrics computes style_diversity from style_patterns and derives total_score as expected.
tests/integration/test_metrics_service_endpoints.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • In get_diversity_metrics, you call self.database_manager.get_detailed_metrics without checking if self.database_manager is None, unlike get_intelligence_metrics where you guard on db, which can lead to an AttributeError in cases where the DB manager is not wired.
  • The data collection logic in get_intelligence_metrics (pulling and normalizing metrics from get_detailed_metrics and get_all_user_affections) is getting fairly dense; consider extracting it into a small helper method to keep the endpoint method focused on orchestration.
  • The affection buckets (0–20, 21–40, etc.) and thresholds (≥70, ≤30) are currently hard-coded; if these ranges are expected to evolve or be reused, consider centralizing them as configuration or module-level constants to make future changes safer.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `get_diversity_metrics`, you call `self.database_manager.get_detailed_metrics` without checking if `self.database_manager` is `None`, unlike `get_intelligence_metrics` where you guard on `db`, which can lead to an AttributeError in cases where the DB manager is not wired.
- The data collection logic in `get_intelligence_metrics` (pulling and normalizing metrics from `get_detailed_metrics` and `get_all_user_affections`) is getting fairly dense; consider extracting it into a small helper method to keep the endpoint method focused on orchestration.
- The affection buckets (0–20, 21–40, etc.) and thresholds (≥70, ≤30) are currently hard-coded; if these ranges are expected to evolve or be reused, consider centralizing them as configuration or module-level constants to make future changes safer.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant