feat(harness): 评测闭环 —— 评测结果落库 + 分级 + 告警 + 可查(测温计→恒温器)

此前 eval 只打日志、不闭环。现在:
- 分级:evalLevel 据综合分+忠实度 → ok(≥0.75) / warn(≥0.5 或忠实<0.6) / poor(<0.5);poor 出 slog.Warn 告警。
- 落库:dispatcher 评完经 NATS(SubjectEval) 广播 EvalEvent → 网关订阅写 PG(新表 sundynix_eval,
  按 task_id upsert)。沿用任务状态回写那套(dispatcher 无 DB,经 bus→gateway 落库)。
- 可查:GET /api/v1/tasks/:id/eval 返回 overall/rule/llm/faithful/level/flags/reason/sources。
- 契约 EvalEvent + EvalOK/Warn/Poor;bus PublishEval/SubscribeEval;dispatcher EvalSink(NewOrchestrator 第9参)。

验证:三模块 build+vet+test 全绿;live RAG 任务评测落库,端点返回 overall~1.0 / level=ok / faithful=1 / sources=1。
剩:桌面端质量面板、低分自动重试(P3)。project_analysis 勾掉该项。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-06-25 15:26:19 +08:00
parent 446b784fc6
commit 10f08ffb14
12 changed files with 173 additions and 10 deletions
+25
View File
@@ -338,6 +338,31 @@ func (b *Bus) SubscribeTaskStatus(onEvent func(*contract.TaskStatusEvent)) (unsu
return sub.Unsubscribe, nil
}
// ---- 自动化评测结果回写(core NATS pub-sub----
// PublishEval 广播一次评测结果(dispatcher 调用)。
func (b *Bus) PublishEval(ev *contract.EvalEvent) error {
data, err := json.Marshal(ev)
if err != nil {
return err
}
return b.nc.Publish(contract.SubjectEval, data)
}
// SubscribeEval 订阅评测结果(网关调用,落 PG)。
func (b *Bus) SubscribeEval(onEvent func(*contract.EvalEvent)) (unsub func() error, err error) {
sub, err := b.nc.Subscribe(contract.SubjectEval, func(m *nats.Msg) {
var ev contract.EvalEvent
if json.Unmarshal(m.Data, &ev) == nil {
onEvent(&ev)
}
})
if err != nil {
return nil, fmt.Errorf("subscribe eval: %w", err)
}
return sub.Unsubscribe, nil
}
// ---- 人工审批(HITLcore NATS pub-sub----
// PublishApproval 广播一次人工审批决定(网关在收到 UI 的批准/拒绝后调用)。
+24
View File
@@ -37,8 +37,32 @@ const (
// 人工审批(HITL)决定回传前缀:实际 sundynix.approval.<task_id>。
// core NATS pub-subUI 点批准/拒绝 → 网关发到此 → dispatcher 解除审批节点的阻塞。
SubjectApproval = "sundynix.approval"
// 自动化评测结果回写:dispatcher 评完经此广播,网关订阅落 PG 并供 UI 查询。core NATS pub-sub。
SubjectEval = "sundynix.eval.task"
)
// 评测质量分级(据综合分 + 忠实度阈值,闭环门控/告警用)。
const (
EvalOK = "ok" // 综合 ≥ 0.75 且无忠实度风险
EvalWarn = "warn" // 0.5 ≤ 综合 < 0.75,或忠实度偏低
EvalPoor = "poor" // 综合 < 0.5
)
// EvalEvent 是一次自动化评测的结果(经 SubjectEval 回流给网关落库)。
type EvalEvent struct {
TaskID string `json:"task_id"`
Overall float64 `json:"overall"` // 综合分 [0,1]
Rule float64 `json:"rule"` // 规则分
LLM float64 `json:"llm"` // LLM 质量分
Faithful float64 `json:"faithful"` // RAG 忠实度分(0=无来源未评)
Level string `json:"level"` // ok / warn / poor
Flags []string `json:"flags,omitempty"` // 命中问题(规则 + 未被来源支持)
Reason string `json:"reason,omitempty"` // 评语
Sources int `json:"sources,omitempty"` // 检索来源数
TS int64 `json:"ts"` // unix 毫秒
}
// 任务生命周期状态机:submitted(网关建任务)→ runningdispatcher 开跑)
// → done / failed / timeoutdispatcher 收尾)。
// HITL:执行到审批节点 → waiting(等人工决定)→ 批准回 running / 拒绝→rejected。