The documented `log_base` range accepts 1.0, but the resolver silently replaces it with 2.6

オープン
#11,060 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@lhjl-j がすでに取り組んでいます。

2026年11月9日 から。

  • #11064 @lhjl-j による — オープン

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
76/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
python
領域
backend

調査の方向性

Read astrbot/core/config/default.py at the log_base hint and _resolve_log_base in astrbot/core/pipeline/respond/stage.py to compare the advertised range with the accepted values. Check for existing tests of _resolve_log_base and its use by _calc_comp_interval. Done means the documented range and resolver behavior agree, with a test covering the boundary value.

索引モデルが issue の本文から書いたものです。

説明

The documented log_base range accepts 1.0, but the resolver silently replaces it with 2.6

  • Repository: AstrBotDevs/AstrBot
  • Target commit: 14835b5011bbc3ffb0a76829df3e272ddeacfafa
  • File: astrbot/core/config/default.py:4551-4557, astrbot/core/pipeline/respond/stage.py:17-36

Summary

The UI metadata for platform_settings.segmented_reply.log_base documents the range as
1.0-10.0, so 1.0 is presented to users as a legal value. The pipeline resolver rejects
any base <= 1 and silently substitutes DEFAULT_LOG_BASE = 2.6, so a configured 1.0
never reaches the computation and the reply interval is calculated with a different base
than the user set.

Actual behavior

With interval_method = "log" and log_base = 1.0 (the lowest value the hint allows), the
real resolver logs Unusable segmented-reply log base: 1.0, using the default 2.6 instead.
and RespondStage._calc_comp_interval calls math.log(wc + 1, 2.6); the configured value
is discarded without any indication in the UI.

Observed on the target commit:

documented_hint="对数间隔的底数,默认为 2.6。取值范围为 1.0-10.0。"
configured_log_base=1.0
resolved_log_base=2.6
math_log_base=2.6

1.0 is inside the advertised range but outside the range the code accepts, so the
documented contract and the implementation disagree. A base of exactly 1 cannot be used
by math.log (it raises ZeroDivisionError), but the metadata should not advertise it as
valid, and the resolver currently substitutes a different value rather than rejecting the
input.

Expected: a value the UI documents as legal is either honoured or rejected with a
visible error; the documented range matches the resolver's accepted range.

Reproduction
  1. Set platform_settings.segmented_reply.interval_method to log and
    platform_settings.segmented_reply.log_base to 1.0 (a value the configuration hint
    explicitly lists as in range).
  2. Run the responder with segmented replies enabled and send a message that triggers
    segmentation.
  3. The error log shows Unusable segmented-reply log base: 1.0, using the default 2.6 instead., and the computed interval is derived from math.log(n, 2.6).

A unit test can call the shipped _resolve_log_base(1.0) directly and assert whether the
result should be 1.0 (honoured), an error (rejected), or 2.6 (documented substitution) —
today it returns 2.6 while the hint says 1.0 is valid.

Relevant code
# astrbot/core/config/default.py:4551-4557
"platform_settings.segmented_reply.log_base": {
    "description": "对数底数",
    "type": "float",
    "hint": "对数间隔的底数,默认为 2.6。取值范围为 1.0-10.0。",
    "condition": {
        "platform_settings.segmented_reply.interval_method": "log",
    },
},
# astrbot/core/pipeline/respond/stage.py:17-36
DEFAULT_LOG_BASE = 2.6


def _resolve_log_base(value: float | str | None) -> float:
    """Return a log base that math.log accepts, or the documented default."""
    try:
        log_base = float(value)
    except (TypeError, ValueError) as e:
        logger.error(f"Failed to parse the segmented-reply log base: {e}")
        return DEFAULT_LOG_BASE
    if not math.isfinite(log_base) or log_base <= 1:
        # math.log(words, 1) raises ZeroDivisionError and a non-positive base
        # raises ValueError; both escape from _calc_comp_interval before the
        # first send, so the whole reply is dropped.
        logger.error(
            f"Unusable segmented-reply log base: {log_base}, "
            f"using the default {DEFAULT_LOG_BASE} instead.",
        )
        return DEFAULT_LOG_BASE
    return log_base
# astrbot/core/pipeline/respond/stage.py:96-97,124
self.log_base = _resolve_log_base(
    ctx.astrbot_config["platform_settings"]["segmented_reply"]["log_base"],
)
...
i = math.log(wc + 1, self.log_base)

Root cause

The metadata hint in default.py was written as an inclusive 1.0-10.0 range, while the
resolver in stage.py treats log_base <= 1 as unusable and replaces it with 2.6
(adding only an error log). The two ranges are maintained in different files with no shared
constant or test, so the UI advertises a boundary value the consumer refuses; a user who
sets the documented minimum gets a different base than requested, and the substitution is
only visible in the log.

Suggested fix

  1. Make the documented range match the implementation: state (1.0, 10.0] (or
    1.0 < log_base <= 10.0) in the hint, or accept 1.0 by defining the effective base
    as 1.0 + epsilon and documenting that behaviour.
  2. Derive the hint from a single shared constant (e.g. MIN_LOG_BASE/MAX_LOG_BASE) used
    by both default.py and _resolve_log_base.
  3. Add a test asserting that every value inside the advertised range is either honoured or
    produces a user-visible validation error, and that out-of-range values are rejected.
主要言語
Python
スター
46.4k
フォーク
3.4k
平均マージ
1日 11時間
マージ済み PR(30日)
120

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

AstrBotDevs/AstrBot のほかの issue

AstrBotDevs/AstrBot の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。