fix: goal 宣告检测容忍行尾句号,修提示与检测自矛盾致空转
_llm_declared_done 此前要求回合文本里单独一行恰好等于 目标已达成,但 run_goal_loop 三处提示都让模型输出 目标已达成。(带句号);模型照做后检测永不触发,实弹 goal 任务空转 292 轮才被手动取消。改成比对前去行尾空白 与句末标点(。!?;,、. 等),提示不动、单独一行要求 不动,行内带其它文字仍不算。 回归测试 test_goal_marker_trailing_punctuation_counts:裸标记、 句号、感叹号、句号前空格、行尾空格算达成;前缀文字、逗号 后续、反问、空串不算。
This commit is contained in:
1 parent
2a7cdd582f
commit
49dfb7c458
2 files changed
+29
-4
No files matched your search
@@ -1706,14 +1706,24 @@ GOAL_DONE_MARKER = "目标已达成"
|
|||||||
|
|
||||||
|
|
||||||
def _llm_declared_done(text):
|
def _llm_declared_done(text):
|
||||||
"""模型是否宣告目标达成:回合文本里单独一行恰好是标记行。
|
"""模型是否宣告目标达成:回合文本里单独一行是标记行。
|
||||||
|
|
||||||
只有完整跑完的回合才查标记(调用方保证):超时/中断回合的
|
只有完整跑完的回合才查标记(调用方保证):超时/中断回合的
|
||||||
部分文本即使含标记也不算,否则没做完也会提前结束。"""
|
部分文本即使含标记也不算,否则没做完也会提前结束。
|
||||||
|
|
||||||
|
行尾句号要容忍:提示本身让模型输出“目标已达成。”(带句
|
||||||
|
号),若检测要求整行恰好等于无句号的标记,模型照做也永
|
||||||
|
远不算达成、循环空转(2026-10-27 实弹 292 轮教训)。所以
|
||||||
|
比对前先去行尾空白与句末标点,但行内其它文字一律不算
|
||||||
|
(“xx目标已达成”“目标已达成,继续”仍不算,单独一行要
|
||||||
|
求不动)。"""
|
||||||
if not text:
|
if not text:
|
||||||
return False
|
return False
|
||||||
return any(line.strip() == GOAL_DONE_MARKER
|
punct = "。!!??;;,,、.."
|
||||||
for line in text.splitlines())
|
for line in text.splitlines():
|
||||||
|
if line.strip().rstrip(punct).strip() == GOAL_DONE_MARKER:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def run_goal_loop(server, state, state_path, task, goal_text, verify,
|
def run_goal_loop(server, state, state_path, task, goal_text, verify,
|
||||||
|
|||||||
@@ -922,6 +922,21 @@ class GoalLoopLongTaskTest(unittest.TestCase):
|
|||||||
self.assertIn("目标已达成", srv.prompts[0])
|
self.assertIn("目标已达成", srv.prompts[0])
|
||||||
self.assertIn("目标已达成", srv.prompts[1])
|
self.assertIn("目标已达成", srv.prompts[1])
|
||||||
|
|
||||||
|
def test_goal_marker_trailing_punctuation_counts(self):
|
||||||
|
# 2026-10-27 实弹教训:提示让模型输出“目标已达成。”(带
|
||||||
|
# 句号),检测若要求整行恰好等于无句号标记,循环空转
|
||||||
|
# 292 轮。行尾句末标点必须容忍,但单独一行要求不动。
|
||||||
|
self.assertTrue(host._llm_declared_done("done\n目标已达成"))
|
||||||
|
self.assertTrue(host._llm_declared_done("done\n目标已达成。"))
|
||||||
|
self.assertTrue(host._llm_declared_done("done\n目标已达成!"))
|
||||||
|
self.assertTrue(host._llm_declared_done("done\n目标已达成 。"))
|
||||||
|
self.assertTrue(host._llm_declared_done("done\n目标已达成。 "))
|
||||||
|
self.assertFalse(host._llm_declared_done("done\nxx目标已达成"))
|
||||||
|
self.assertFalse(host._llm_declared_done("done\n目标已达成,继续"))
|
||||||
|
self.assertFalse(host._llm_declared_done("done\n目标已达成吗?"))
|
||||||
|
self.assertFalse(host._llm_declared_done(""))
|
||||||
|
self.assertFalse(host._llm_declared_done(None))
|
||||||
|
|
||||||
def test_goal_llm_decided_marker_ignored_on_timeout_turn(self):
|
def test_goal_llm_decided_marker_ignored_on_timeout_turn(self):
|
||||||
# 超时回合的部分文本即使含标记行也不算达标,必须继续跑。
|
# 超时回合的部分文本即使含标记行也不算达标,必须继续跑。
|
||||||
class FakeServer:
|
class FakeServer:
|
||||||
|
|||||||
Reference in new issue
Block a user