Skip to content

feat: monitor repeated model output - #1346

Open
xinfei-shi wants to merge 1 commit into
mainfrom
feat/output-repetition-monitor
Open

feat: monitor repeated model output#1346
xinfei-shi wants to merge 1 commit into
mainfrom
feat/output-repetition-monitor

Conversation

@xinfei-shi

Copy link
Copy Markdown
Collaborator

Summary

  • add online detection for repeated model output, including same-token runs, contiguous n-gram/long-span loops, and non-contiguous repeated spans
  • integrate streaming token updates with frontend access logs, metrics, and configurable thresholds
  • preserve the existing tool-call loop detector and native-unavailable fallback behavior
  • add focused C++ and Python unit tests

Tests

  • //rtp_llm/cpp/repetition/test:online_repetition_tracker_test
  • //rtp_llm/dash_sc/test:repetition_monitor_test

Both targets pass with --config=cuda13.

@xinfei-shi
xinfei-shi force-pushed the feat/output-repetition-monitor branch from b952977 to 7e92fbc Compare August 28, 2026 08:55

@LLLLKKKK LLLLKKKK 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.

AI Code Review - PR #1346

Status: BLOCKING

Summary: P0/0 · P1/2 · P2/12 · P3/5

Reviewed: commit 7e92fbcb3131 · 2026-08-28 17:58 UTC+8

Blocking Issues

P1

  • grpc_metrics 无条件读取新属性使既有 access_log_test 打桩失效,CI 目标确定性失败 @ rtp_llm/dash_sc/grpc_metrics.py:162
    • 建议:在本 PR 内同步补齐该桩字段(output_repetition_check_ms=0.0output_repetition_result=None);更稳妥的做法是让桩直接使用真实 RequestRepetitionMonitor 实例(output 关闭态)按需赋值,避免后续再加字段时重复踩坑。不要在 grpc_metrics 侧改用 getattr 兜底——那会把生产边界的结构契约弱化为运行时探测。
  • 删除唯一加载真实 .so 的用例,同时把 native 必需 API 从 1 项扩到 3 项 @ rtp_llm/dash_sc/test/repetition_monitor_test.py:62
    • 建议:恢复一个加载真实 .so 的用例(可沿用 _fresh_native_status() 入口),至少断言:真实模块可导入、status.module_name 命中预期模块名、三个必需 API 均存在,并用真实 OnlineRepetitionTracker 跑一段明显重复的 token 序列断言 result.hit 为真。.so 目前仍经 //rtp_llm/dash_sc:repetition_monitordatadash_sc/BUILD:22)进入 runfiles,请确认 import path 可解析,否则把 data 加回 repetition_monitor_test。另建议把 test_module_without_required_api_is_unavailable(:87-100)的断言按 _NATIVE_TRACKER_REQUIRED_APIS 参数化逐项校验并锚定 "missing API" 前缀(当前只断 check_tool_call_loop,移除另两项仍会通过),使「必需 API 列表」本身成为被测契约。若该边界只能在 smoke 验证,请在 PR 描述中说明替代位置。

Non-blocking Suggestions

P2

  • kind 分类阶梯在指标层与访问日志层各写一份,含相同魔数 1/64 @ rtp_llm/dash_sc/grpc_metrics.py:170
    • 建议:在 repetition_monitor.py 抽出唯一实现(如模块级 output_repetition_kind(result: OutputRepetitionResult) -> str,或作为 OutputRepetitionResult 的只读属性),把 1 与 64 提为具名常量并注释取值依据;record_fields()_report_frontend_structured_metrics 均改为调用它,删除 grpc_metrics.py:170-178 的本地副本。这样日志与指标天然一致,repetition_monitor_test.py 现有的 kind 断言即可同时守住指标标签。
  • native 检测器降级在指标面完全不可见,check_ms > 0 哨兵在降级路径同样成立 @ rtp_llm/dash_sc/grpc_metrics.py:162
    • 建议:改用显式状态而非耗时累加值作判据:仅当 output_repetition_impl == "online_cpp_pybind"(或新增显式 output_checked: bool)时才上报 OUTPUT_REPETITION_CHECK_RT_METRIC;并补一个可告警信号,例如新增 py_rtp_output_repetition_unavailable_qps,或给现有指标加低基数 impl 标签(online_cpp_pybind / online_cpp_pybind_unavailable / disabled),据此配置「检测不可用比例 > 阈值」告警,作为特性静默失效的兜底。顺带统一两族哨兵约定:tool 侧是 Optional[float]is not None,output 侧是 float = 0.0> 0,同一对象上两种风格易在后续维护中误改。
  • 6 个新指标与 4 路 kind 分类零测试覆盖 @ rtp_llm/dash_sc/grpc_metrics.py:179
    • 建议:按既有 patch.object(grpc_metrics, "kmonitor") 范式补一组 test_done_output_repetition_family:以数据驱动方式覆盖 repeat_unit_size 取 1 / 64 / 65 与 non_contiguous=True 四条分支,断言 6 个指标各上报一次、kind/action 标签取值正确、SAME_TOKEN_RUN_QPS_METRIC 仅在 kind == "same_token_run" 时出现一次;再补 hit=Falseresult is None、native 不可用三种情形不产生命中类指标,并与 record_fields()["output_repetition_kind"] 交叉断言一致。
  • 7 个新阈值参数零校验,下界被两层静默 clamp、上界无限制且启动日志与生效值不一致 @ rtp_llm/server/server_args/repetition_detection_group_args.py:28
    • 建议:在 args 层改用带范围校验的 type=(参照同目录 util.pystr2boolargparse.ArgumentTypeError 的写法)——CLI 与 env 两条路径都能 fail-fast,因为 server_args.py:364-365ArgumentTypeError 会走 self.error();并为 max_period 设明确上界。clamp 真源建议只保留 C++ normalizeConfig() 作最终防线,删除 repetition_monitor.py 中的重复 max(...);若必须保留,请在 clamp 生效时打 WARNING 说明「请求值 X 已按下限 Y 生效」,或在装载后 normalize 并写回配置对象,使 to_string() 打印的就是生效值。
  • 7 个新参数全部缺少 help,且同一旋钮命名跨三层不统一 @ rtp_llm/server/server_args/repetition_detection_group_args.py:7
    • 建议:为 7 个参数补 help=,风格与同文件 tool_call_loop_* 一致,至少写明:作用、单位、下游实际生效下界、依赖 native .so、仅 dash-sc gRPC 路径生效、以及与 --output_repetition_monitor 总开关的关系。命名建议在合入前统一为 --output_repetition_noncontig_*(或全拼)与对应的 RTP_LLM_OUTPUT_REPETITION_NONCONTIG_*,使同一检测器配置项共享前缀并与下游字段名对应;env/flag 一旦随版本发布即成为难回收的外部契约。若认为当前命名更简洁,请在 PR 描述中记录该取舍。
  • 7 个新参数的绑定、默认值与跨模块改名映射均无测试,bind_to 拼错会静默失效 @ rtp_llm/server/server_args/repetition_detection_group_args.py:14
    • 建议:扩展 test_repetition_detection_config:对 7 个新字段各断言一次默认值与一次 CLI(或 env)覆盖后的生效值,尤其覆盖发生改名的 output_repetition_min_dup_tokens 与 3 个 noncontig_repeat_*,并包含一条通过 RTP_LLM_OUTPUT_REPETITION_MONITOR=0 关闭总开关的 str2bool 路径;可参考同文件 ServerArgsGrammarConfigTest 的逐字段写法。再为 _build_repetition_monitor_config 补一条 RepetitionDetectionConfig → OutputRepetitionConfig 的映射测试,把跨模块字段改名固化为测试契约。
  • 访问日志 repetition_detected / repetition_alert 语义扩宽且默认生效,下游告警口径变化 @ rtp_llm/dash_sc/repetition_monitor.py:425
    • 建议:在 PR 描述中明确列出这 5 个既有字段的语义扩宽,并通知访问日志下游消费方;repetition_reason 已带 output_repetition: 前缀可用于区分来源,建议同时说明 repetition_primary_source 的优先级(output 优先于 tool)。若下游告警不便同步调整,建议首个版本默认关闭该开关按集群灰度,或保持 repetition_alert 仅表达 tool-call loop、用新增的 output_repetition* 字段承载新语义,避免复用既有告警字段。
  • native 缺失时访问日志字段集整体退化,默认开启放大了该退化面 @ rtp_llm/dash_sc/repetition_monitor.py:412
    • 建议:确认所有部署形态都打包了 native .sodash_sc/BUILD:22 已列为 data,非 bazel 打包路径需另行确认),并在 PR 描述中说明该默认值翻转对访问日志 schema 的影响。若无法保证,建议调整降级策略:native 缺失时保留原有字段键(值为 None)并仅追加 repetition_monitor_available=False 与不可用原因,使日志 schema 不因开关默认值而收缩。另请注释说明唯一权威默认来源:目前 OutputRepetitionConfig.enabled 默认 True(:114)而 RequestRepetitionMonitorConfig.output_config 工厂默认 enabled=False(:158),同一开关存在两种默认语义。
  • 测试替身偏离真实 pybind 契约,配置字段改名回归会被掩盖 @ rtp_llm/dash_sc/test/repetition_monitor_test.py:41
    • 建议:让替身贴合真实契约:FakeConfig__slots__ 或 dataclass 限定为这 6 个字段(写未知字段即抛错)、update_many/finalize 返回 bool、补 token_count 属性;或改为对真实 OnlineRepetitionConfig 遍历 _ensure_output_tracker 写入的字段名逐个断言存在,把跨语言字段名漂移变成可失败的断言而非静默降级。同时把两个 test_streaming_* 用例改名为反映真实语义(字段投影),检测能力交由真实 .so 用例覆盖。
  • 生产读取未归一化 raw result,其偏差字段与 reset/token_count 零覆盖 @ rtp_llm/cpp/repetition/test/OnlineRepetitionTrackerTest.cc:34
    • 建议:新增直接驱动 OnlineRepetitionTracker 的用例:updateMany 分多段喂入(模拟 streaming delta)→ considerFinalTail() → 逐字段断言 result() 的原始值,并显式覆盖「最优候选来自流式、end_index < token_count」这一分支,把生产真正消费的 raw 语义固化下来,避免后续调整 normalizeResultForEnd 时误以为生产字段已被保护;再补一条 reset()tokenCount() 归零、旧命中不残留的用例。若 pybind 直返未归一化结果是有意设计,请在 result 的 pybind 处或头文件加一行说明 raw 与 normalized 的语义差异;若 detectOnlineRepetitionMax/HitOnly 确无生产用途,建议移入测试辅助文件,避免头文件长期暴露无消费者的公共 API。
  • 新增 C++ 用例自造 abort 断言宏与手写 main,偏离同目录与全仓 gtest 约定 @ rtp_llm/cpp/repetition/test/OnlineRepetitionTrackerTest.cc:8
    • 建议:改用 gtest:把 8 个 void testXxx() 拆为 TEST(OnlineRepetitionTrackerTest, Xxx)RTP_EXPECT 换成 EXPECT_EQ/EXPECT_TRUE,删除自造宏与手写 main(),并在 online_repetition_tracker_test 的 deps 中加入 @com_google_googletest//:gtestgtest_main,与同文件 sibling 保持一致。
  • C++ 用例缺失空/单元素与 max_period、配置 clamp 边界覆盖 @ rtp_llm/cpp/repetition/test/OnlineRepetitionTrackerTest.cc:19
    • 建议:补齐:空序列与单 token 输入断言不命中且不越界;max_period 边界上下各一例(周期大于 max_period 时应不命中);针对 normalizeConfig 传入非法值(min_repeats=0 时仍需 3 次重复才命中、max_period=0non_contiguous_max_span < min_span)断言 clamp 后的实际检测行为;并至少一例断言 first_detect_indextokenCount()

P3

  • 默认对全量流量开启的检测器命中后无早退、无预算上限,且缺开销数据 @ rtp_llm/dash_sc/repetition_monitor.py:301
    • 建议:补充长输出(如 8k tokens、含高重复退化样本)× 高并发下 py_rtp_output_repetition_check_rt 的 P99 与前端进程 RSS 对比数据;若暂无数据,建议首个版本默认 False 或按小比例集群通过 env 打开。实现上可加成本上界:命中后停止继续 update、或对单请求设 token/耗时预算超限即停并在日志标记 truncated;hash_power_ 可提为进程级共享表。若确定默认开启,请在 help 中标注这是全量生效开关及关闭方式。
  • py_rtp_same_token_run_qps 可由 kind 标签完全派生,属冗余指标名 @ rtp_llm/dash_sc/grpc_metrics.py:182
    • 建议:优先删除该条上报及 kmonitor_metric_reporter.py:78 的枚举定义,看板按 kind 下钻 py_rtp_output_repetition_qps;若确有历史告警链路依赖该名,请在枚举处注释说明它是 kind 维度的冗余投影及退役计划。
  • 新增指标枚举缺少口径注释,check_rt 累加语义与同族指标不一致 @ rtp_llm/metrics/kmonitor_metric_reporter.py:152
    • 建议:为 6 个新枚举补注释,明确单位、上报频次、output_repetition_check_rt 是跨流式 delta 的累计值、以及 period 在 non-contiguous 下需靠 kind 区分语义;若需与 tool-call 同图对比,可对累计量另行命名(如 _check_total_rt)。
  • 多处新增行超出仓库 black 88 列,且与相邻代码折行风格不一致 @ rtp_llm/dash_sc/grpc_metrics.py:183
    • 建议:提交前对本次改动的 Python 文件跑仓库既有 black + isort --profile=black,把 kmonitor_metric_reporter.py:155 按 :148-150 括号换行对齐、grpc_metrics.py:183-184 展开为与 :185-189 一致的多行调用;C++ 侧同时跑 clang-format(注意宏续行的行尾空格)。
  • testLongSameToken 名不符实,且随机用例含实现定义转换 @ rtp_llm/cpp/repetition/test/OnlineRepetitionTrackerTest.cc:104
    • 建议:长序列场景改用 detectOnlineRepetitionMax(或直接用 tracker 类喂完 1000 个 token)真正覆盖长输入,或把用例改名为 testSameTokenRunHitsEarly;随机用例改用 rng() % 1000000U + 1000000std::uniform_int_distribution<int>

Checklist Findings (16 fail / 48 total)

General Principles Checklist

  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue native 缺失时访问日志字段集整体退化,默认开启放大了该退化面
    monitor_available() 仅在 output_config.enabled 为真时才探测 native 模块(:392-395),tool 分支还额外要求配齐 markers(:398)。本 PR 之前不存在 output 开关,output 检测恒关闭,未配 markers 时 monitor_available() 直接返回 True、record_fields() 返回完整字段集。默认置 True 后,一旦 .so 不可用,该函数对所有请求返回 False,record_fields() 退化为 :413-419 的 5 字段集,原有 repetition_detected / repetition_alert / function_tool_repeated / tool_call_loop_* 等字段整体从访问日志消失,影响下游日志消费方与报表,且该退化在 kmonitor 上不可见。
  • [6.1] Architecture — 分层边界:新概念在正确层级,不泄漏内部 → issue kind 分类阶梯在指标层与访问日志层各写一份,含相同魔数 1/64
    grpc_metrics.py:170-178 用三元链把 OutputRepetitionResult 推导为指标标签 kindnon_contiguousrepeat_unit_size == 1<= 64 → else),与 repetition_monitor.py:438-447 推导访问日志字段 output_repetition_kind 的判定顺序、四个字符串字面量、阈值 1 与 64 逐字重复,两份独立维护、互不引用,且 64 无任何注释说明来源。而 access_record.py:551-558 的 docstring 明确声明 monitor 是检测结论、日志字段与 kmonitor 上报的 single source of truth,即分类本应由 monitor 归口、metrics 层只做投影。任一侧调整阈值或新增桶,同一请求在指标 kind 与日志 output_repetition_kind 上就会给出不同结论,而排障恰恰依赖两者交叉比对,且无任何测试会发现该偏差。
  • [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue 新增指标枚举缺少口径注释,check_rt 累加语义与同族指标不一致
    该文件同期新增的其他指标都有注释说明口径(如 DASH_SC_DSV4_PHASE2_QPS_METRIC 注明「一次/请求」,VIT_EMBEDDING_BATCH_SIZE_METRIC 说明取值含义),本次新增 6 项无任何注释。口径差异确实存在:output_repetition_check_msupdate_output_deltarepetition_monitor.py:313)每个流式 delta 与 finalize_output(:346)累加而成,是 per-request 累计耗时;同族 tool_call_loop_check_ms(:377)则是单次一次性测量。两者均以 _check_rt 结尾、标签集合相同,同图对比会被误当作同口径。py_rtp_output_repetition_period 承载 repeat_unit_size,non-contiguous 命中下语义是匹配跨度长度而非周期。
  • [6.1] Architecture — 回滚路径:风险行为存在运维回滚手段 → issue 默认对全量流量开启的检测器命中后无早退、无预算上限,且缺开销数据
    output_repetition_monitorpy_config_modules.py:406 与 argparse(:12)默认均为 True 且无附加门槛——与同组 tool_call_loop_monitor 不同,后者须配齐 marker 才真正运行(app.py:295-307),本参数是首个真正默认全量生效的按请求检测器。access_record.py:518-520 对每帧调用 update_output_delta,后者每帧重建 [int(t) for t in delta_ids] 并跨 pybind 调 update_manyupdateMany 即使 result_.hit 已为真也继续处理后续全部 token(.cc:215-221),无早退与耗时/长度预算。每请求持有 tokens_/prefix_hash_/hash_power_(各 O(n))与每 token 约 4 条 span_occurrences_ 记录、请求内零回收。PR 未给出长输出高并发下的 RT 与 RSS 数据。
  • [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue 默认对全量流量开启的检测器命中后无早退、无预算上限,且缺开销数据
    output_repetition_monitorpy_config_modules.py:406 与 argparse(:12)默认均为 True 且无附加门槛——与同组 tool_call_loop_monitor 不同,后者须配齐 marker 才真正运行(app.py:295-307),本参数是首个真正默认全量生效的按请求检测器。access_record.py:518-520 对每帧调用 update_output_delta,后者每帧重建 [int(t) for t in delta_ids] 并跨 pybind 调 update_manyupdateMany 即使 result_.hit 已为真也继续处理后续全部 token(.cc:215-221),无早退与耗时/长度预算。每请求持有 tokens_/prefix_hash_/hash_power_(各 O(n))与每 token 约 4 条 span_occurrences_ 记录、请求内零回收。PR 未给出长输出高并发下的 RT 与 RSS 数据。
  • [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue native 缺失时访问日志字段集整体退化,默认开启放大了该退化面
    monitor_available() 仅在 output_config.enabled 为真时才探测 native 模块(:392-395),tool 分支还额外要求配齐 markers(:398)。本 PR 之前不存在 output 开关,output 检测恒关闭,未配 markers 时 monitor_available() 直接返回 True、record_fields() 返回完整字段集。默认置 True 后,一旦 .so 不可用,该函数对所有请求返回 False,record_fields() 退化为 :413-419 的 5 字段集,原有 repetition_detected / repetition_alert / function_tool_repeated / tool_call_loop_* 等字段整体从访问日志消失,影响下游日志消费方与报表,且该退化在 kmonitor 上不可见。
  • [6.1] Quality — PR description 说明动机与设计 → issue 默认对全量流量开启的检测器命中后无早退、无预算上限,且缺开销数据
    output_repetition_monitorpy_config_modules.py:406 与 argparse(:12)默认均为 True 且无附加门槛——与同组 tool_call_loop_monitor 不同,后者须配齐 marker 才真正运行(app.py:295-307),本参数是首个真正默认全量生效的按请求检测器。access_record.py:518-520 对每帧调用 update_output_delta,后者每帧重建 [int(t) for t in delta_ids] 并跨 pybind 调 update_manyupdateMany 即使 result_.hit 已为真也继续处理后续全部 token(.cc:215-221),无早退与耗时/长度预算。每请求持有 tokens_/prefix_hash_/hash_power_(各 O(n))与每 token 约 4 条 span_occurrences_ 记录、请求内零回收。PR 未给出长输出高并发下的 RT 与 RSS 数据。
  • [6.1] Quality — 逻辑变更未混入无关格式化 → issue 多处新增行超出仓库 black 88 列,且与相邻代码折行风格不一致
    .pre-commit-config.yaml:12-16 启用 black 24.8.0 且未覆盖 line-length(默认 88),exclude^rtp_llm/ops|^3rdparty,本 PR 改动文件均在管辖范围。grpc_metrics.py:183(约 107 列)与 :184(约 109 列)写成单行,而同一新增块内 :185-189 与紧邻的 :163-167 同类调用都已逐参数展开,风格自相矛盾;kmonitor_metric_reporter.py:155 为 91 列,而同文件 :148-150 长度相当却已括号换行;repetition_monitor.py:289-296、:302、:386、:454、:456、:485-492 亦多行超 88。.flake8 的 120 列上限拦不住,问题会推迟到 pre-commit 暴露并产生无关的纯格式 diff。
  • [6.1] Software Engineering — DRY:重复非平凡逻辑被抽取或显式复用 → issue py_rtp_same_token_run_qps 可由 kind 标签完全派生,属冗余指标名
    grpc_metrics.py:179-182 先以已含 kindoutput_tags 上报 OUTPUT_REPETITION_QPS_METRIC,紧接着在 kind == "same_token_run" 时用完全同一份 output_tags 再上报 SAME_TOKEN_RUN_QPS_METRIC。两次上报的数值与标签集合完全相同,因此 py_rtp_same_token_run_qps 恒等于 py_rtp_output_repetition_qps{kind="same_token_run"},未携带任何新增维度,却多占一个全局注册的指标名,并留下「两者口径是否不同」的歧义。
  • [6.1] Software Engineering — KISS/YAGNI:无投机性抽象 → issue py_rtp_same_token_run_qps 可由 kind 标签完全派生,属冗余指标名
    grpc_metrics.py:179-182 先以已含 kindoutput_tags 上报 OUTPUT_REPETITION_QPS_METRIC,紧接着在 kind == "same_token_run" 时用完全同一份 output_tags 再上报 SAME_TOKEN_RUN_QPS_METRIC。两次上报的数值与标签集合完全相同,因此 py_rtp_same_token_run_qps 恒等于 py_rtp_output_repetition_qps{kind="same_token_run"},未携带任何新增维度,却多占一个全局注册的指标名,并留下「两者口径是否不同」的歧义。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue C++ 用例缺失空/单元素与 max_period、配置 clamp 边界覆盖
    main() 注册的 8 个用例均为「有内容的正常序列」。未覆盖:空 token 序列(considerFinalTailtoken_count_ <= 0 早返回,.cc:199)、单 token、token_count == max_period 边界与 update()period > max_period 的历史位置淘汰分支(.cc:168-181)。normalizeConfig.cc:10-18)的 5 条 clamp 全部无覆盖,而这些字段来自 server args、非法值会被静默改写,同一套 clamp 又在 repetition_monitor.py:288-296 逐条重复,两份都无测试锚定、漂移不会被发现。first_detect_index(经 pybind 落到访问日志)与 tokenCount() 在任何用例中均未断言;同目录 sibling 已有 EmptyOutputIdsDoesNotHit,本文件缺同类保护。
  • [6.1] Tests — 被删除测试有等价替代覆盖 → issue 删除唯一加载真实 .so 的用例,同时把 native 必需 API 从 1 项扩到 3 项
    本 PR 删除 test_packaged_native_module_imports_from_runfiles(原走真实 resolver,断言 status.available 并实调 check_tool_call_loop),并在 dash_sc/test/BUILD:67 摘掉 data = ["//rtp_llm/cpp/repetition:online_repetition_tracker"];同期 _NATIVE_TRACKER_REQUIRED_APISrepetition_monitor.py:26-30)由单项 check_tool_call_loop 扩为含 OnlineRepetitionConfig/OnlineRepetitionTracker 的 3 项。现存 _fresh_native_status() 的两处使用(:71、:88)都同时 patch 了 import_module,其「让真实 resolver 运行」的语义已无人使用,全仓无任何测试导入真实 .so.so 未打包或未导出新
  • [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue testLongSameToken 名不符实,且随机用例含实现定义转换
    testLongSameToken 构造 1000 个相同 token,但走 detectOnlineRepetitionHitOnly,该函数首次命中即 return(.cc:228-230)。按实现复算:min_duplicate_tokens=32 时 period 1 的 covered = token_index + 1duplicate = covered - 1,在 token_index == 32 即满足阈值,实际只消费约 33 个 token,「Long」从未被执行,长序列下 positions_by_token_ 增长与累积开销均未覆盖。另 testRandomNoHitstatic_cast<int>(rng() + 1000000U)(:122)在结果超过 INT_MAX 时为实现定义转换,跨平台可能得到不同 token 值。

RTP-LLM Checklist

  • [I] 代码质量 — 删除或重命名内部 file、registry entry、model name、metric enum、op binding、plugin symbol 时,必须全仓搜索消费者,并提供替代实现、迁移说明或 smoke 覆盖;只有暴露到 HTTP/RPC/config/persisted format 时才按外部兼容性处理 → issue 删除唯一加载真实 .so 的用例,同时把 native 必需 API 从 1 项扩到 3 项
    本 PR 删除 test_packaged_native_module_imports_from_runfiles(原走真实 resolver,断言 status.available 并实调 check_tool_call_loop),并在 dash_sc/test/BUILD:67 摘掉 data = ["//rtp_llm/cpp/repetition:online_repetition_tracker"];同期 _NATIVE_TRACKER_REQUIRED_APISrepetition_monitor.py:26-30)由单项 check_tool_call_loop 扩为含 OnlineRepetitionConfig/OnlineRepetitionTracker 的 3 项。现存 _fresh_native_status() 的两处使用(:71、:88)都同时 patch 了 import_module,其「让真实 resolver 运行」的语义已无人使用,全仓无任何测试导入真实 .so.so 未打包或未导出新
  • [I] 代码质量 — 同一功能用统一工具函数 → issue 新增 C++ 用例自造 abort 断言宏与手写 main,偏离同目录与全仓 gtest 约定
    新用例用宏 RTP_EXPECT + std::abort()(:8-14)加手写 main()(:159-170),cpp/repetition/test/BUILD:5-10 因此不依赖 gtest。同目录 sibling token_tool_call_loop_guard_test(同文件 :12-21)依赖 @com_google_googletest//:gtestgtest_main,用例均为 TEST(...) 形式,全仓约定亦是 Google Test + cc_test_wrapper。后果:首个断言失败即 abort,其余 7 个用例不再执行,一次回归会掩盖其他失败;无 gtest XML 与逐用例名,测试详情面板无结果、--test_filter 不可用;std::abort 以 SIGABRT 退出并产生 coredump,会被 CI 崩溃诊断链路误判为引擎崩溃。

Python Static-First Checklist

  • [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue 测试替身偏离真实 pybind 契约,配置字段改名回归会被掩盖
    _fake_output_nativeFakeConfig 是空的普通类(:42-43 class FakeConfig: pass),任意属性赋值都成立;真实 pybind OnlineRepetitionConfigOnlineRepetitionPybind.cc:12-19)只有 6 个 def_readwrite 且未开 py::dynamic_attr(),写未定义字段会抛 AttributeError_ensure_output_tracker()repetition_monitor.py:287-296)连续设置这 6 个字段,一旦 C++ 侧字段改名,替身测试仍通过,而生产被宽 except Exception 吞掉、只留 online_cpp_pybind_unavailable。此外 FakeTracker.update_many/finalize 返回 result 对象(真实 API 返回 bool)、也未提供 token_countFakeTracker 对任意输入返回同一份写死

Strengths

  • 跨语言配置契约干净:7 个字段在 argparse、RepetitionDetectionConfigOutputRepetitionConfig、pybind OnlineRepetitionConfig、C++ OnlineRepetitionTracker.h:10-17 五处名称与默认值完全一致。考虑到 ConfigBinding.applyserver_args.py:122-126)走无校验 setattr、拼错只会静默失效,且链路含 7 字段 × 2 跳改名,作者在这条最易出错的路径上没有留下任何错位。
  • 指标注册与标签设计正确:新增枚举经 MetricReporter.init() 遍历 enum 自动注册,避免「上报了但未注册、被 report() 静默丢弃」;kind 仅 4 个取值、action 为常量、刻意不含 request_id,标签基数有界。
  • 热路径 tag 处理安全:命中分支统一用 {**tags, ...} 派生新字典,未原地修改 _metric_tagslru_cache 共享实例,严格遵守该函数 docstring(grpc_metrics.py:36-44)声明的只读约定,per-token 的 report_chunk 仍零额外分配。
  • 分层边界清晰:新增上报只落在 _report_frontend_structured_metricsreport_forwarder_rpc_done 保持「无 token 载荷指标」契约;update_output_delta/finalize_output 均对 raw_mode 早返回,forwarder 的无原始载荷契约未被破坏。
  • C++ 算法边界处理经核对无越界:spanHashprefix_hash_[start+length]hash_power_[length]std::equal 三段迭代器范围在所有调用点均落在有效区间;非连续 span 用滚动哈希后仍以 std::equal 精确复核,碰撞只导致漏报不会误报,对监控类特性是正确取舍;normalizeConfignon_contiguous_min_span >= 8 同时兜住了 length *= 2 的死循环风险。
  • BUILD 依赖收窄方向正确:online_repetition_tracker_core 让算法脱离 pybind/torch 即可被单测链接;//rtp_llm/dash_sc:repetition_monitor 让纯 CPU monitor 不再拖入整个 gRPC server 依赖闭包。
  • 8 个新增 C++ 用例给的是精确数值断言而非只断 hit,我按 OnlineRepetitionTracker.cc 逐条复算 repeat_unit_size/repeat_count/partial_tail/covered/duplicate/start/end 均一致,并含固定种子负例防误报。
  • pybind 侧 update_manycheck_tool_call_loop 均用 py::gil_scoped_release 释放 GIL,跨界调用不阻塞其他协程;降级路径整体 fail-open,record_fields() 明确注明「Emitting all-clear detection results would be a lie」,设计意图清晰。
  • 变更主体为纯追加:既有 tool_call_loop_* 字段、flag 名、env 名与默认值均未改动,且 --output_repetition_monitor 提供了可用的运维关闭开关。

kmonitor.report(GaugeMetrics.INPUT_TOKEN_SIZE_METRIC, record.input_len, tags)
kmonitor.report(GaugeMetrics.OUTPUT_TOKEN_SIZE_METRIC, record.output_len, tags)
monitor = record.repetition_monitor
if monitor.output_repetition_check_ms > 0:

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.

[P1] grpc_metrics 无条件读取新属性使既有 access_log_test 打桩失效,CI 目标确定性失败

grpc_metrics.py:161-168monitor = record.repetition_monitor 后,在既有 tool 分支(:190)之前无条件读取 monitor.output_repetition_check_ms.output_repetition_result,均为非 Optional 硬属性访问;access_record.py:551-560 的 property 原样返回 _repetition_monitor,无惰性兜底。既有测试 access_log_test.py:934 把它替换为只含 tool_call_loop_check_ms / tool_call_loop_resultSimpleNamespace,:940 随即调用 report_frontend_rpc_done 且调用处无 try/except,SimpleNamespace 缺属性必抛 AttributeError。该文件不在 diff_paths 中,而 `dash_sc/test/BUILD:5...

建议: 在本 PR 内同步补齐该桩字段(output_repetition_check_ms=0.0output_repetition_result=None);更稳妥的做法是让桩直接使用真实 RequestRepetitionMonitor 实例(output 关闭态)按需赋值,避免后续再加字段时重复踩坑。不要在 grpc_metrics 侧改用 getattr 兜底——那会把生产边界的结构契约弱化为运行时探测。

)


def _fresh_native_status():

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.

[P1] 删除唯一加载真实 .so 的用例,同时把 native 必需 API 从 1 项扩到 3 项

本 PR 删除 test_packaged_native_module_imports_from_runfiles(原走真实 resolver,断言 status.available 并实调 check_tool_call_loop),并在 dash_sc/test/BUILD:67 摘掉 data = ["//rtp_llm/cpp/repetition:online_repetition_tracker"];同期 _NATIVE_TRACKER_REQUIRED_APISrepetition_monitor.py:26-30)由单项 check_tool_call_loop 扩为含 OnlineRepetitionConfig/OnlineRepetitionTracker 的 3 项。现存 _fresh_native_status() 的两处使用(:71、:88)都同时 patch 了 import_module,其「让真实 resolver 运行」的语义已无人使用,全仓无任何测试导入真实 .so.so 未打包或未...

建议: 恢复一个加载真实 .so 的用例(可沿用 _fresh_native_status() 入口),至少断言:真实模块可导入、status.module_name 命中预期模块名、三个必需 API 均存在,并用真实 OnlineRepetitionTracker 跑一段明显重复的 token 序列断言 result.hit 为真。.so 目前仍经 //rtp_llm/dash_sc:repetition_monitordatadash_sc/BUILD:22)进入 runfiles,请确认 import path 可解析,否则把 data 加回 repetition_monitor_test。另建议把 test_module_without_required_api_is_unavailable(:87-100)的断言按 _NATIVE_TRACKER_REQUIRED_APIS 参数化逐项校验并锚定 "missing API" 前缀(当前只断 check_tool_call_loop,移除另两项仍会通过),使「必需 API 列表」本身成为被测契约。若该边界只能在 smoke 验证,请在 PR 描述中说明替代位置。

Checklist: [6.1] 被删除测试有等价替代覆盖;[I] 删除或重命名内部 file、registry entry、model name、metric enum、op binding、plugin symbol 时,必须全仓搜索消费者,并提供替代实现、迁移说明或 smoke 覆盖;只有暴露到 HTTP/RPC/config/persisted format 时才按外部兼容性处理

@LLLLKKKK LLLLKKKK 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.

AI Code Review - PR #1346 (non-blocking suggestions)

17 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

)
output = monitor.output_repetition_result
if output is not None and output.hit:
kind = (

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.

[P2] kind 分类阶梯在指标层与访问日志层各写一份,含相同魔数 1/64

grpc_metrics.py:170-178 用三元链把 OutputRepetitionResult 推导为指标标签 kindnon_contiguousrepeat_unit_size == 1<= 64 → else),与 repetition_monitor.py:438-447 推导访问日志字段 output_repetition_kind 的判定顺序、四个字符串字面量、阈值 1 与 64 逐字重复,两份独立维护、互不引用,且 64 无任何注释说明来源。而 access_record.py:551-558 的 docstring 明确声明 monitor 是检测结论、日志字段与 kmonitor 上报的 single source of truth,即分类本应由 monitor 归口、metrics 层只做投影。任一侧调整阈值或新增桶,同一请求在指标 kind 与日志 output_repetition_kind 上就会给出不同结论,而排障恰恰依赖两者交叉比对,且无任何测试会发现该偏差。

建议:repetition_monitor.py 抽出唯一实现(如模块级 output_repetition_kind(result: OutputRepetitionResult) -> str,或作为 OutputRepetitionResult 的只读属性),把 1 与 64 提为具名常量并注释取值依据;record_fields()_report_frontend_structured_metrics 均改为调用它,删除 grpc_metrics.py:170-178 的本地副本。这样日志与指标天然一致,repetition_monitor_test.py 现有的 kind 断言即可同时守住指标标签。

Checklist: [6.1] 分层边界:新概念在正确层级,不泄漏内部

kmonitor.report(GaugeMetrics.INPUT_TOKEN_SIZE_METRIC, record.input_len, tags)
kmonitor.report(GaugeMetrics.OUTPUT_TOKEN_SIZE_METRIC, record.output_len, tags)
monitor = record.repetition_monitor
if monitor.output_repetition_check_ms > 0:

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.

[P2] native 检测器降级在指标面完全不可见,check_ms > 0 哨兵在降级路径同样成立

native .so 缺失时 _ensure_output_tracker() 返回 None、impl 置 online_cpp_pybind_unavailable 且不抛异常(repetition_monitor.py:284-286),但 update_output_delta(:312-313)与 finalize_output(:345-346)的 finally 仍无条件累加耗时,异常路径(:309-311 / :342-344)亦然。因此 grpc_metrics.py:162check_ms > 0 在检测彻底降级为 no-op 时仍成立,py_rtp_output_repetition_check_rt 照常上报纯空跑耗时,而命中类指标恒不增长——看板上「检测健康且零命中」与「检测根本没跑」完全同形。不可用状态只落访问日志 repetition_monitor_available,kmonitor 侧无任何可告警维度,基于该指标的告警会假阴性。

建议: 改用显式状态而非耗时累加值作判据:仅当 output_repetition_impl == "online_cpp_pybind"(或新增显式 output_checked: bool)时才上报 OUTPUT_REPETITION_CHECK_RT_METRIC;并补一个可告警信号,例如新增 py_rtp_output_repetition_unavailable_qps,或给现有指标加低基数 impl 标签(online_cpp_pybind / online_cpp_pybind_unavailable / disabled),据此配置「检测不可用比例 > 阈值」告警,作为特性静默失效的兜底。顺带统一两族哨兵约定:tool 侧是 Optional[float]is not None,output 侧是 float = 0.0> 0,同一对象上两种风格易在后续维护中误改。

if output.repeat_unit_size <= 64
else "long_span_repeat"
)
output_tags = {**tags, "kind": kind, "action": "metric"}

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.

[P2] 6 个新指标与 4 路 kind 分类零测试覆盖

全仓搜索 OUTPUT_REPETITION / SAME_TOKEN_RUN 仅命中 kmonitor_metric_reporter.py:77-78,152-155 的枚举定义、grpc_metrics.py 的上报处与参数文件的 env 名,无任何测试引用。repetition_monitor_test.py:123,153 只断言 record 层 output_repetition_kind(仅 same_token_runnon_contiguous_span_repeat 两桶),指标层这份副本零用例,exact_ngram_looplong_span_repeat 两桶两侧均无覆盖。仓库已有完全对位的范式(access_log_test.py:930-947test_done_tool_call_loop_family 断言 QPS 计数与 action=metric 标签),本次未按该范式扩展。

建议: 按既有 patch.object(grpc_metrics, "kmonitor") 范式补一组 test_done_output_repetition_family:以数据驱动方式覆盖 repeat_unit_size 取 1 / 64 / 65 与 non_contiguous=True 四条分支,断言 6 个指标各上报一次、kind/action 标签取值正确、SAME_TOKEN_RUN_QPS_METRIC 仅在 kind == "same_token_run" 时出现一次;再补 hit=Falseresult is None、native 不可用三种情形不产生命中类指标,并与 record_fields()["output_repetition_kind"] 交叉断言一致。

type=int,
default=32,
)
group.add_argument(

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.

[P2] 7 个新阈值参数零校验,下界被两层静默 clamp、上界无限制且启动日志与生效值不一致

6 个新 int 参数只声明裸 type=int,不拒绝 0/负数,也不校验 noncontig_repeat_min_span_tokens <= max_span_tokens。同一套 clamp 被写了两遍且都无日志:repetition_monitor.py:288-296max(3,·)/max(0,·)/max(1,·)/max(8,·)/max(2,·),与 C++ normalizeConfig()OnlineRepetitionTracker.cc:10-18)逐条重复。后果三点:--output_repetition_min_repeats 2 实际按 3 生效,而 py_config_modules.py:419-433to_string() 打印的是声明值,排障被启动日志误导;min_repeats 默认 3 恰等于下界,暴露区间下半段不可达;max_period 完全不设上界却直接决定两个 max_period+1 长度 vector(.cc:59-60)与每 token O(max_pe...

建议: 在 args 层改用带范围校验的 type=(参照同目录 util.pystr2boolargparse.ArgumentTypeError 的写法)——CLI 与 env 两条路径都能 fail-fast,因为 server_args.py:364-365ArgumentTypeError 会走 self.error();并为 max_period 设明确上界。clamp 真源建议只保留 C++ normalizeConfig() 作最终防线,删除 repetition_monitor.py 中的重复 max(...);若必须保留,请在 clamp 生效时打 WARNING 说明「请求值 X 已按下限 Y 生效」,或在装载后 normalize 并写回配置对象,使 to_string() 打印的就是生效值。

def init_repetition_detection_group_args(parser, repetition_detection_config):
group = parser.add_argument_group("Repetition Detection")

group.add_argument(

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.

[P2] 7 个新参数全部缺少 help,且同一旋钮命名跨三层不统一

同文件既有 5 个 tool_call_loop_* 参数全部带 help=(:63、:71、:79、:87、:96),而新增 7 个(:7-55)全部没有,--help 只显示裸参数名与类型。这些是面向运维的外部配置面,语义无法从名字推断(min_dup_tokens 指重复覆盖 token 数还是去重后 token 数?单位是 token 还是次数?),也无从得知生效前提依赖 native .so、下界会被静默抬升、以及仅 app.py:_build_repetition_monitor_config 消费(在标准 OpenAI/HTTP 前端设置后既不生效也无告警)。命名上同一旋钮跨三层有三套写法:CLI/配置字段用缩写 noncontig_repeat_*min_dup_tokens,运行期 dataclass 与 C++ 结构体用全拼 non_contiguous_*min_duplicate_tokens,env 前缀也分裂为 RTP_LLM_NONCONTIG_REPEAT_* 与 `RTP_LLM_OUTPU...

建议: 为 7 个参数补 help=,风格与同文件 tool_call_loop_* 一致,至少写明:作用、单位、下游实际生效下界、依赖 native .so、仅 dash-sc gRPC 路径生效、以及与 --output_repetition_monitor 总开关的关系。命名建议在合入前统一为 --output_repetition_noncontig_*(或全拼)与对应的 RTP_LLM_OUTPUT_REPETITION_NONCONTIG_*,使同一检测器配置项共享前缀并与下游字段名对应;env/flag 一旦随版本发布即成为难回收的外部契约。若认为当前命名更简洁,请在 PR 描述中记录该取舍。

self.output_repetition_impl = "online_cpp_pybind"
return self._output_tracker

def update_output_delta(self, delta_ids: Sequence[int]) -> None:

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.

[P3] 默认对全量流量开启的检测器命中后无早退、无预算上限,且缺开销数据

output_repetition_monitorpy_config_modules.py:406 与 argparse(:12)默认均为 True 且无附加门槛——与同组 tool_call_loop_monitor 不同,后者须配齐 marker 才真正运行(app.py:295-307),本参数是首个真正默认全量生效的按请求检测器。access_record.py:518-520 对每帧调用 update_output_delta,后者每帧重建 [int(t) for t in delta_ids] 并跨 pybind 调 update_manyupdateMany 即使 result_.hit 已为真也继续处理后续全部 token(.cc:215-221),无早退与耗时/长度预算。每请求持有 tokens_/prefix_hash_/hash_power_(各 O(n))与每 token 约 4 条 span_occurrences_ 记录、请求内零回收。PR 未给出长输出高并发下的 RT 与 RSS 数据。

建议: 补充长输出(如 8k tokens、含高重复退化样本)× 高并发下 py_rtp_output_repetition_check_rt 的 P99 与前端进程 RSS 对比数据;若暂无数据,建议首个版本默认 False 或按小比例集群通过 env 打开。实现上可加成本上界:命中后停止继续 update、或对单请求设 token/耗时预算超限即停并在日志标记 truncated;hash_power_ 可提为进程级共享表。若确定默认开启,请在 help 中标注这是全量生效开关及关闭方式。

Checklist: [6.1] 回滚路径:风险行为存在运维回滚手段;[6.1] 状态不变量:创建/更新/失败/重试/回滚路径有效;[6.1] PR description 说明动机与设计

output_tags = {**tags, "kind": kind, "action": "metric"}
kmonitor.report(AccMetrics.OUTPUT_REPETITION_QPS_METRIC, 1, output_tags)
if kind == "same_token_run":
kmonitor.report(AccMetrics.SAME_TOKEN_RUN_QPS_METRIC, 1, output_tags)

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.

[P3] py_rtp_same_token_run_qps 可由 kind 标签完全派生,属冗余指标名

grpc_metrics.py:179-182 先以已含 kindoutput_tags 上报 OUTPUT_REPETITION_QPS_METRIC,紧接着在 kind == "same_token_run" 时用完全同一份 output_tags 再上报 SAME_TOKEN_RUN_QPS_METRIC。两次上报的数值与标签集合完全相同,因此 py_rtp_same_token_run_qps 恒等于 py_rtp_output_repetition_qps{kind="same_token_run"},未携带任何新增维度,却多占一个全局注册的指标名,并留下「两者口径是否不同」的歧义。

建议: 优先删除该条上报及 kmonitor_metric_reporter.py:78 的枚举定义,看板按 kind 下钻 py_rtp_output_repetition_qps;若确有历史告警链路依赖该名,请在枚举处注释说明它是 kind 维度的冗余投影及退役计划。

Checklist: [6.1] DRY:重复非平凡逻辑被抽取或显式复用;[6.1] KISS/YAGNI:无投机性抽象

"py_rtp_tool_call_loop_current_span_tokens"
)
TOOL_CALL_LOOP_CHECK_RT_METRIC = "py_rtp_tool_call_loop_check_rt"
OUTPUT_REPETITION_CHECK_RT_METRIC = "py_rtp_output_repetition_check_rt"

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.

[P3] 新增指标枚举缺少口径注释,check_rt 累加语义与同族指标不一致

该文件同期新增的其他指标都有注释说明口径(如 DASH_SC_DSV4_PHASE2_QPS_METRIC 注明「一次/请求」,VIT_EMBEDDING_BATCH_SIZE_METRIC 说明取值含义),本次新增 6 项无任何注释。口径差异确实存在:output_repetition_check_msupdate_output_deltarepetition_monitor.py:313)每个流式 delta 与 finalize_output(:346)累加而成,是 per-request 累计耗时;同族 tool_call_loop_check_ms(:377)则是单次一次性测量。两者均以 _check_rt 结尾、标签集合相同,同图对比会被误当作同口径。py_rtp_output_repetition_period 承载 repeat_unit_size,non-contiguous 命中下语义是匹配跨度长度而非周期。

建议: 为 6 个新枚举补注释,明确单位、上报频次、output_repetition_check_rt 是跨流式 delta 的累计值、以及 period 在 non-contiguous 下需靠 kind 区分语义;若需与 tool-call 同图对比,可对累计量另行命名(如 _check_total_rt)。

Checklist: [6.1] 可观测性:日志/指标/超时可操作、非噪声

kmonitor.report(AccMetrics.OUTPUT_REPETITION_QPS_METRIC, 1, output_tags)
if kind == "same_token_run":
kmonitor.report(AccMetrics.SAME_TOKEN_RUN_QPS_METRIC, 1, output_tags)
kmonitor.report(GaugeMetrics.OUTPUT_REPETITION_PERIOD_METRIC, output.repeat_unit_size, output_tags)

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.

[P3] 多处新增行超出仓库 black 88 列,且与相邻代码折行风格不一致

.pre-commit-config.yaml:12-16 启用 black 24.8.0 且未覆盖 line-length(默认 88),exclude^rtp_llm/ops|^3rdparty,本 PR 改动文件均在管辖范围。grpc_metrics.py:183(约 107 列)与 :184(约 109 列)写成单行,而同一新增块内 :185-189 与紧邻的 :163-167 同类调用都已逐参数展开,风格自相矛盾;kmonitor_metric_reporter.py:155 为 91 列,而同文件 :148-150 长度相当却已括号换行;repetition_monitor.py:289-296、:302、:386、:454、:456、:485-492 亦多行超 88。.flake8 的 120 列上限拦不住,问题会推迟到 pre-commit 暴露并产生无关的纯格式 diff。

建议: 提交前对本次改动的 Python 文件跑仓库既有 black + isort --profile=black,把 kmonitor_metric_reporter.py:155 按 :148-150 括号换行对齐、grpc_metrics.py:183-184 展开为与 :185-189 一致的多行调用;C++ 侧同时跑 clang-format(注意宏续行的行尾空格)。

Checklist: [6.1] 逻辑变更未混入无关格式化

RTP_EXPECT(result.end_index == static_cast<int>(tokens.size()));
}

void testLongSameToken() {

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.

[P3] testLongSameToken 名不符实,且随机用例含实现定义转换

testLongSameToken 构造 1000 个相同 token,但走 detectOnlineRepetitionHitOnly,该函数首次命中即 return(.cc:228-230)。按实现复算:min_duplicate_tokens=32 时 period 1 的 covered = token_index + 1duplicate = covered - 1,在 token_index == 32 即满足阈值,实际只消费约 33 个 token,「Long」从未被执行,长序列下 positions_by_token_ 增长与累积开销均未覆盖。另 testRandomNoHitstatic_cast<int>(rng() + 1000000U)(:122)在结果超过 INT_MAX 时为实现定义转换,跨平台可能得到不同 token 值。

建议: 长序列场景改用 detectOnlineRepetitionMax(或直接用 tracker 类喂完 1000 个 token)真正覆盖长输入,或把用例改名为 testSameTokenRunHitsEarly;随机用例改用 rng() % 1000000U + 1000000std::uniform_int_distribution<int>

Checklist: [6.1] 边界 case 覆盖(空、单元素、最大值)

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.

2 participants