fix(harness): 评测不再误判长答案「截断」—— 评审截断从 1500 抬到 6000 + 明确标注

T0.1 校准后 judge 变严,但被评测自己的截断坑了:judge 评分前把模型回答截到 1500 字
(evalTruncate(output,1500)),而报告/多智能体综合等长答案普遍 2000+ 字 → judge 只看到
前半截、误判「回答不完整/截断」,给出假阴性 warn。多智能体一跑就暴露(2278 字答案被
误判 0.55 warn「截断」)。

- evalReviewOutput: 评审长度上限 6000(覆盖绝大多数长答案);确被截断时明确标注
  「已被评审系统截断,勿因结尾不完整扣分」,杜绝 judge 因自身截断而扣分。
- llmJudge / llmJudgeGrounded 改用 evalReviewOutput 喂模型回答。

live 验证:同款 2 专家协调任务,修复前 0.55 warn「截断」→ 修复后 0.85 ok,且 judge
挑出真实缺陷(推荐逻辑前后矛盾)而非假截断。既公平又严格。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-06-29 17:35:13 +08:00
parent cb6eec5614
commit 835a6d7432
+16 -2
View File
@@ -134,7 +134,7 @@ func normJudge(v float64) float64 {
func (e *Evaluator) llmJudge(ctx context.Context, input, output string) (float64, string, bool) {
user := fmt.Sprintf("【用户输入】%s\n\n【模型输出】%s\n\n%s\n\n"+
"只输出 JSON{\"score\":1到5整数,\"reason\":\"先点最主要的缺陷(没有就说无明显缺陷)再给结论,一句话\"},不要多余文字。",
evalTruncate(input, 500), evalTruncate(output, 1500), evalQualityRubric)
evalTruncate(input, 500), evalReviewOutput(output), evalQualityRubric)
txt, err := e.chat(ctx, evalQualitySys, user)
if err != nil {
return 0, "", false
@@ -161,7 +161,7 @@ func (e *Evaluator) llmJudgeGrounded(ctx context.Context, input, output string,
"faithfulness(忠实度):5=每个关键说法都有资料依据;分数随无依据/编造的说法增多而降;只要有一处明显编造,faithfulness 不得高于 2。\n"+
"unsupported:列出回答中未被检索资料支持的具体说法(无则空数组)。\n"+
"只输出 JSON{\"quality\":1到5整数,\"faithfulness\":1到5整数,\"unsupported\":[\"...\"],\"reason\":\"一句话\"},不要多余文字。",
evalTruncate(input, 400), src, evalTruncate(output, 1500))
evalTruncate(input, 400), src, evalReviewOutput(output))
txt, err := e.chat(ctx, sys, user)
if err != nil {
return 0, 0, nil, "", false
@@ -186,6 +186,20 @@ func evalTruncate(s string, n int) string {
return string(r[:n]) + "…"
}
// evalReviewLimit 是喂给 judge 的「模型回答」最长字数。不能太短:报告/多智能体综合等长答案
// 普遍 2000+ 字,截太短会让 judge 误判「回答不完整/截断」(而那是评审自己截的)。
const evalReviewLimit = 6000
// evalReviewOutput 把待评审的模型回答按 evalReviewLimit 截断;若确被截断,明确标注是评审所为,
// 让 judge 不要因结尾不完整而扣分(杜绝长答案被误判 warn/poor 的假阴性)。
func evalReviewOutput(s string) string {
r := []rune(s)
if len(r) <= evalReviewLimit {
return s
}
return string(r[:evalReviewLimit]) + "\n…(注:回答过长,已被评审系统截断,请勿因结尾不完整而扣分)"
}
// evalStripFence 去掉模型可能包裹的 ```json … ``` 围栏。
func evalStripFence(s string) string {
s = strings.TrimSpace(s)