feat(harness): RAG 忠实度评测 —— judge 拿检索原文评幻觉
补 Harness 已知洞:此前 LLM-judge 只看 input+output,看不到检索来源,幻觉其实没评。 - Evaluator.Score 增 sources 参数;有来源时走 llmJudgeGrounded:一次调用同时评 quality 质量 + faithfulness 忠实度,并列出 unsupported(未被来源支持的说法)→ 进 Flags。 综合分(有来源)=0.3规则+0.35质量+0.35忠实;无来源时维持原 0.4规则+0.6质量。Result 增 Faithful 字段。 - 透传检索来源:runGraph 返回 (answer, refs, err),executeGraph 同步;Handle→evaluate(input,output,refs); refsOf(board)=检索资料+工具产出。compose 路径暂返回 nil refs(不评忠实度)。 - eval 日志增「忠实 X.XX,来源 N」。 测试:单测覆盖 grounded(quality/faithfulness/unsupported 解析 + 加权 + flags)与无来源跳过; 3 处测试 runGraph 三返回值更新。live 实测 RAG 任务忠实 1.00/来源 1,judge 正确判定无编造。 project_analysis Harness 清单勾掉该项。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -42,7 +42,7 @@ type board struct {
|
||||
// branch 按条件只激活选中的下游(剪枝)→ agent 节点流式回流 token。
|
||||
//
|
||||
// 逐节点点亮"运行·观测"。返回终端 agent 的完整产出(供写回历史)。
|
||||
func (o *Orchestrator) runGraph(ctx context.Context, t *contract.Task, tr *execTracer) (string, error) {
|
||||
func (o *Orchestrator) runGraph(ctx context.Context, t *contract.Task, tr *execTracer) (string, []string, error) {
|
||||
flow, ferr := dsl.Parse(t.Graph)
|
||||
plan := dsl.Compile(t.Graph)
|
||||
b := &board{
|
||||
@@ -57,7 +57,7 @@ func (o *Orchestrator) runGraph(ctx context.Context, t *contract.Task, tr *execT
|
||||
b.profile = o.fetchMemory(ctx, b.uid, b.query)
|
||||
b.history = o.fetchHistory(ctx, b.sid)
|
||||
o.runConversation(ctx, t.ID, b, plan.System, tr, "agent")
|
||||
return b.answer, b.fatalErr // 模型失败 → 上抛判 failed
|
||||
return b.answer, refsOf(b), b.fatalErr // 模型失败 → 上抛判 failed
|
||||
}
|
||||
|
||||
// 建邻接与入度(只认两端都存在的边)。保留整条边以便 branch 按 true/false 标签选路。
|
||||
@@ -165,10 +165,10 @@ func (o *Orchestrator) runGraph(ctx context.Context, t *contract.Task, tr *execT
|
||||
}
|
||||
|
||||
if b.rejected {
|
||||
return b.answer, errRejected // 合法终态,Handle 据此判 rejected 并优雅收尾
|
||||
return b.answer, nil, errRejected // 合法终态,Handle 据此判 rejected 并优雅收尾
|
||||
}
|
||||
if b.fatalErr != nil {
|
||||
return b.answer, b.fatalErr // 上抛 → Handle 判 failed(带原因)
|
||||
return b.answer, nil, b.fatalErr // 上抛 → Handle 判 failed(带原因)
|
||||
}
|
||||
|
||||
// 图里无 agent 节点(纯工具/检索图)也要出一段模型答复,否则没有输出。
|
||||
@@ -176,9 +176,15 @@ func (o *Orchestrator) runGraph(ctx context.Context, t *contract.Task, tr *execT
|
||||
o.runConversation(ctx, t.ID, b, plan.System, tr, "agent")
|
||||
}
|
||||
if b.fatalErr != nil {
|
||||
return b.answer, b.fatalErr
|
||||
return b.answer, nil, b.fatalErr
|
||||
}
|
||||
return b.answer, nil
|
||||
return b.answer, refsOf(b), nil // 成功:带回检索来源供忠实度评测
|
||||
}
|
||||
|
||||
// refsOf 汇总本次执行的检索来源(检索资料 + 工具产出),供忠实度评测。
|
||||
func refsOf(b *board) []string {
|
||||
out := append([]string{}, b.refs...)
|
||||
return append(out, b.toolOut...)
|
||||
}
|
||||
|
||||
// retrieverNode 执行检索节点:kb 按 owner 作用域 → kb_search → 累计参考资料。
|
||||
|
||||
Reference in New Issue
Block a user