feat: best-of-N采样 — 多温度生成选语法正确的候选

Generator不再遇到第一个非空结果就返回,而是:
1. temperature=0.0/0.3/0.6依次生成
2. 每个候选做ast.parse语法检查
3. 第一个语法正确的直接返回(优先确定性低温结果)
4. 全部语法错误时返回第一个候选(让verifier报具体错误)

直接解决"语法错误导致circuit break":temp=0错了,temp=0.4可能对。

513 tests passed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Val-sss
2026-05-07 18:37:35 +08:00
parent 3c5441d6c4
commit 5290dd117c

View File

@@ -457,17 +457,46 @@ class GeneratorExpert:
if think_cfg.get("think") and self.llm._is_reasoning:
base_tokens += think_cfg.get("budget", 0)
# ── Best-of-N采样生成多个候选选语法正确的最佳版本 ──
candidates = []
for temp in self.temperatures:
raw = self.llm.generate(prompt=prompt, system=system, max_tokens=base_tokens, temperature=temp)
# 审计记录LLM调用的输入输出
self._log_llm_call(ctx, "generator", prompt, system, raw)
modified = self._clean_code_output(raw)
if modified and modified != original:
return modified
if self._is_valid_syntax(modified):
# 语法正确,直接返回(优先低温度的确定性结果)
return modified
else:
# 语法错误但有内容,存为候选
candidates.append(modified)
# 所有温度都语法错误时返回第一个候选让verifier报具体错误
if candidates:
logger.debug("Generator: no syntax-valid candidate, returning best-effort")
return candidates[0]
logger.warning("Generator: all candidates identical to original or empty")
return None
@staticmethod
def _is_valid_syntax(code: str) -> bool:
"""检查Python代码语法是否正确。非Python代码直接返回True。"""
import ast
stripped = code.strip()
if not stripped:
return False
first_line = stripped.split("\n")[0].strip()
python_indicators = ("def ", "class ", "import ", "from ", "if ", "for ",
"while ", "try:", "with ", "async ", "@")
if not any(first_line.startswith(p) for p in python_indicators):
return True # 非Python代码跳过语法检查
try:
ast.parse(code)
return True
except SyntaxError:
return False
@staticmethod
def _extract_func_name_from_code(code: str) -> str:
"""从代码片段中提取函数/类名。"""