mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-10-26 13:16:24 +00:00
fix(config): reject boolean loop detection thresholds (#6017)
* fix(config): reject boolean loop detection thresholds * refactor(config): 复用循环阈值布尔校验 * Revise CHANGELOG for configuration and upload updates Updated CHANGELOG to reflect changes in configuration loading and document ownership. * Update the document of ChangeLog 修复了配置加载阶段的整数阈值字段报错行为,并更新了文档转换的归属记录处理。 --------- Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
parent
f840e843d3
commit
63e399f2bd
@ -460,6 +460,14 @@ This release closes that milestone with **301 merged pull requests**.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **agents:** Loop-detection integer thresholds now reject YAML booleans instead
|
||||
of coercing `true` to `1`. A configuration such as `warn_threshold: true`
|
||||
and `hard_limit: true` previously made the first tool-call set meet the hard
|
||||
limit and forced the agent to stop; booleans on the tracking-window,
|
||||
per-tool-frequency, and per-tool override fields similarly collapsed their
|
||||
limits to one. All integer threshold fields now fail configuration loading
|
||||
with a field-specific error while valid integers and numeric strings retain
|
||||
their existing behavior.([#6017])
|
||||
- **uploads:** Converted Markdown ownership is now recorded when a document is
|
||||
converted. `list_uploaded_files` hides only verified conversion outputs, and
|
||||
document outlines use only the recorded companion; a user-uploaded Markdown
|
||||
|
||||
@ -419,6 +419,12 @@
|
||||
|
||||
### 修复
|
||||
|
||||
- **智能体:** 循环检测的整数阈值现在会拒绝 YAML 布尔值,而不是把
|
||||
`true` 静默转换为 `1`。此前若配置 `warn_threshold: true` 和
|
||||
`hard_limit: true`,第一组工具调用就会达到硬上限并强制终止智能体;
|
||||
跟踪窗口、工具频率和按工具覆盖项中的布尔值也会把对应限制缩小为
|
||||
1。现在所有整数阈值字段都会在配置加载阶段按字段名报错,同时保持
|
||||
有效整数和数字字符串的既有行为。([#6017])
|
||||
- **上传:** 文档转换时现在会记录原文件与 Markdown 的归属关系。
|
||||
`list_uploaded_files` 只隐藏归属已验证的转换文件,文档大纲也只读取
|
||||
记录中指定的 Markdown;用户自行上传的同名文件会正常显示,不会被
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
"""Configuration for loop detection middleware."""
|
||||
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
from pydantic import BaseModel, Field, ValidationInfo, field_validator, model_validator
|
||||
|
||||
|
||||
def _reject_boolean_threshold(value: object, info: ValidationInfo) -> object:
|
||||
if isinstance(value, bool):
|
||||
raise ValueError(f"{info.field_name} must be an integer, not a boolean")
|
||||
return value
|
||||
|
||||
|
||||
class ToolFreqOverride(BaseModel):
|
||||
@ -14,6 +20,11 @@ class ToolFreqOverride(BaseModel):
|
||||
warn: int = Field(ge=1)
|
||||
hard_limit: int = Field(ge=1)
|
||||
|
||||
@field_validator("warn", "hard_limit", mode="before")
|
||||
@classmethod
|
||||
def reject_boolean_thresholds(cls, value: object, info: ValidationInfo) -> object:
|
||||
return _reject_boolean_threshold(value, info)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _validate(self) -> "ToolFreqOverride":
|
||||
if self.hard_limit < self.warn:
|
||||
@ -63,6 +74,19 @@ class LoopDetectionConfig(BaseModel):
|
||||
description=("Per-tool overrides for tool_freq_warn / tool_freq_hard_limit, keyed by tool name. Values can be higher or lower than the global defaults. Commonly used to raise thresholds for high-frequency tools like bash."),
|
||||
)
|
||||
|
||||
@field_validator(
|
||||
"warn_threshold",
|
||||
"hard_limit",
|
||||
"window_size",
|
||||
"max_tracked_threads",
|
||||
"tool_freq_warn",
|
||||
"tool_freq_hard_limit",
|
||||
mode="before",
|
||||
)
|
||||
@classmethod
|
||||
def reject_boolean_thresholds(cls, value: object, info: ValidationInfo) -> object:
|
||||
return _reject_boolean_threshold(value, info)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_thresholds(self) -> "LoopDetectionConfig":
|
||||
"""Ensure hard stop cannot happen before the warning threshold."""
|
||||
|
||||
@ -36,6 +36,28 @@ class TestLoopDetectionConfig:
|
||||
assert config.tool_freq_warn == 60
|
||||
assert config.tool_freq_hard_limit == 80
|
||||
|
||||
def test_accepts_numeric_string_thresholds(self):
|
||||
config = LoopDetectionConfig.model_validate(
|
||||
{
|
||||
"warn_threshold": "10",
|
||||
"hard_limit": "20",
|
||||
"window_size": "50",
|
||||
"max_tracked_threads": "200",
|
||||
"tool_freq_warn": "60",
|
||||
"tool_freq_hard_limit": "80",
|
||||
"tool_freq_overrides": {"bash": {"warn": "150", "hard_limit": "300"}},
|
||||
},
|
||||
)
|
||||
|
||||
assert config.warn_threshold == 10
|
||||
assert config.hard_limit == 20
|
||||
assert config.window_size == 50
|
||||
assert config.max_tracked_threads == 200
|
||||
assert config.tool_freq_warn == 60
|
||||
assert config.tool_freq_hard_limit == 80
|
||||
assert config.tool_freq_overrides["bash"].warn == 150
|
||||
assert config.tool_freq_overrides["bash"].hard_limit == 300
|
||||
|
||||
def test_rejects_zero_thresholds(self):
|
||||
with pytest.raises(ValueError):
|
||||
LoopDetectionConfig(warn_threshold=0)
|
||||
@ -49,6 +71,23 @@ class TestLoopDetectionConfig:
|
||||
with pytest.raises(ValueError):
|
||||
LoopDetectionConfig(tool_freq_hard_limit=0)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("payload", "field"),
|
||||
[
|
||||
({"warn_threshold": True}, "warn_threshold"),
|
||||
({"warn_threshold": 1, "hard_limit": True}, "hard_limit"),
|
||||
({"window_size": True}, "window_size"),
|
||||
({"max_tracked_threads": True}, "max_tracked_threads"),
|
||||
({"tool_freq_warn": True}, "tool_freq_warn"),
|
||||
({"tool_freq_warn": 1, "tool_freq_hard_limit": True}, "tool_freq_hard_limit"),
|
||||
({"tool_freq_overrides": {"bash": {"warn": True, "hard_limit": 2}}}, "warn"),
|
||||
({"tool_freq_overrides": {"bash": {"warn": 1, "hard_limit": True}}}, "hard_limit"),
|
||||
],
|
||||
)
|
||||
def test_rejects_boolean_integer_thresholds(self, payload, field):
|
||||
with pytest.raises(ValueError, match=field):
|
||||
LoopDetectionConfig(**payload)
|
||||
|
||||
def test_rejects_hard_limit_below_warn_threshold(self):
|
||||
with pytest.raises(ValueError, match="hard_limit"):
|
||||
LoopDetectionConfig(warn_threshold=5, hard_limit=4)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user