Documentation
¶
Overview ¶
Package eval 是 ainovel-cli 的离线评测 harness。
设计立足点:评测器(确定性诊断 diag、全书文体 stylestat、七维 rubric)项目里已经 存在,eval 只做薄薄一层——批量驱动 case、采集产出、把 diag Finding 与 case 契约映射 成门禁、聚合报告。一份事实定义,不在评测层重写一遍判断。详见 docs/evaluation-system.md。
当前已覆盖确定性主线:单路门禁、baseline/variant A/B delta、repeat 聚合与 stylestat 回归。 LLM Judge 仍是可选后续层,不能污染确定性门禁。
Index ¶
- Constants
- func Command(argv []string) int
- func RunCase(cfg bootstrap.Config, bundle assets.Bundle, c Case, opts RunOptions) error
- func Summary(s Suite) string
- func WriteReport(s Suite, outDir string) error
- type Case
- type CaseResult
- type Collected
- type Delta
- type DeltaMetrics
- type Expect
- type Gate
- type Issue
- type Metrics
- type Outcome
- type RangeSummary
- type RepeatSummary
- type Result
- type RunOptions
- type RunResult
- type StyleCollection
- type StyleDelta
- type Suite
- type UsageMetrics
Constants ¶
const ( ArmSingle = "single" ArmBaseline = "baseline" ArmVariant = "variant" )
Variables ¶
This section is empty.
Functions ¶
func Command ¶
Command 是 `ainovel-cli eval` 子命令入口,返回进程退出码: 0=PASS/WARN,1=有 case FAIL,2=用法/配置错误。
清晰流程:加载配置 → 加载 case → 按 single/A-B 编排运行 → 采集 → 评分 → 聚合 → 报告。
func RunCase ¶
RunCase 驱动一次 case:装配 host → 启动 → 按章数上限推进 → 到点 Abort。 bundle 由调用方做过 variant 覆盖(如有)。返回的 error 即"运行时错误"(hard fail 依据); 正常写完或正常截停都返回 nil。
RunCase 独占并重置 OutputDir:StartPrepared 只重置 progress/checkpoints,不清 chapters/ foundation 等工件,复用旧目录会让残留产物污染 diag 与 novel_context。故运行前清空,保证隔离。
func WriteReport ¶
WriteReport 在 outDir 下写 report.json(机读)与 report.md(人读)。
Types ¶
type Case ¶
type Case struct {
ID string `json:"id"`
Category string `json:"category"` // 评测层:smoke/workflow/quality/longform/recovery/steering
Role string `json:"role,omitempty"` // 被测角色:writer/architect/editor(与 Category 正交)
Description string `json:"description,omitempty"`
Prompt string `json:"prompt"` // 用户创作需求
Style string `json:"style,omitempty"` // 覆盖配置风格
MaxChapters int `json:"max_chapters"` // 章数上限;0 表示只跑到规划完成(进入 writing)
TargetPrompts []string `json:"target_prompts,omitempty"` // 本 case 主要验证的 prompt 文件(信息性)
Rubric string `json:"rubric,omitempty"` // LLM Judge 评分表(Phase 3 启用)
Expect Expect `json:"expect"`
Gate Gate `json:"gate"`
}
Case 是一个评测样本:一段创作需求 + 一组事实层断言。
type CaseResult ¶
type CaseResult struct {
CaseID string `json:"case_id"`
Category string `json:"category"`
Role string `json:"role,omitempty"`
Outcome Outcome `json:"outcome"`
Runs []RunResult `json:"runs"`
Deltas []Delta `json:"deltas,omitempty"`
Summary RepeatSummary `json:"summary"`
}
func NewABCaseResult ¶
func NewABCaseResult(c Case, runs []RunResult, deltas []Delta) CaseResult
func NewSingleCaseResult ¶
func NewSingleCaseResult(c Case, r Result) CaseResult
func NewSingleRunsCaseResult ¶
func NewSingleRunsCaseResult(c Case, runs []RunResult) CaseResult
type Collected ¶
type Collected struct {
Dir string
Report diag.Report // diag.Diagnose:工件 + 运行时 Findings + Stats
Progress *domain.Progress
Checkpoints []domain.Checkpoint
Pending map[string]bool // 残留信号:pending_commit/pending_steer/last_commit/last_review
LoadErrors []string // 契约依赖工件的真实读取失败(非"不存在");Grade 据此 hard fail
RuntimeErr string // runner 捕获的运行时错误(hard fail),空=无
Style StyleCollection
Usage UsageMetrics
ToolCalls int
}
Collected 是一次运行产出的只读采集结果。全部来自已有评测器与事实层,eval 不自己重算。
type Delta ¶
type Delta struct {
Outcome Outcome `json:"outcome"`
HardFails []Issue `json:"hard_fails,omitempty"`
Warnings []Issue `json:"warnings,omitempty"`
Notes []Issue `json:"notes,omitempty"`
Metrics DeltaMetrics `json:"metrics"`
}
Delta 描述 variant 相对 baseline 的确定性差异。
func GradeDelta ¶
GradeDelta 只比较确定性事实:variant 比 baseline 是否更差。
type DeltaMetrics ¶
type DeltaMetrics struct {
CompletedChapters int `json:"completed_chapters"`
CriticalFindings int `json:"critical_findings"`
WarningFindings int `json:"warning_findings"`
TotalWordsRatio float64 `json:"total_words_ratio,omitempty"`
ToolCallDeltaRatio float64 `json:"tool_call_delta_ratio,omitempty"`
CostDeltaRatio float64 `json:"cost_delta_ratio,omitempty"`
InputTokenDeltaRatio float64 `json:"input_token_delta_ratio,omitempty"`
OutputTokenDeltaRatio float64 `json:"output_token_delta_ratio,omitempty"`
Stylestat *StyleDelta `json:"stylestat,omitempty"`
}
type Expect ¶
type Expect struct {
Phase string `json:"phase,omitempty"` // 期望最终 phase
MinCompletedChapters int `json:"min_completed_chapters,omitempty"` // 至少完成的章数
RequiredCheckpoints []string `json:"required_checkpoints,omitempty"` // 形如 "chapter:1:commit" / "arc:1:1:arc_summary" / "global:layered_outline"
NoPending []string `json:"no_pending,omitempty"` // 结束时应清空的信号:pending_commit/pending_steer/last_commit/last_review
}
Expect 是 case 级契约断言——只声明 diag 通用规则覆盖不到、与本 case 强相关的预期。
type Gate ¶
type Gate struct {
MaxSeverity string `json:"max_severity,omitempty"` // diag Finding 允许的最高严重度(默认 warning):超过即 hard fail
MaxCostDeltaRatio *float64 `json:"max_cost_delta_ratio,omitempty"`
MaxToolCallDeltaRatio *float64 `json:"max_tool_call_delta_ratio,omitempty"`
StylestatRegression string `json:"stylestat_regression,omitempty"`
}
Gate 是本 case 的门禁阈值。本期只用 MaxSeverity;其余字段为 A/B(regression)阶段预留, 解析但不参与门禁——保留是为了 case 文件能按 docs/evaluation-system.md 的完整 schema 书写。
type Issue ¶
type Issue struct {
Kind string `json:"kind"` // hard_fail / warning / passed
Source string `json:"source"` // runtime / finding:<rule> / contract:<name>
Severity string `json:"severity,omitempty"` // critical / warning / info
Detail string `json:"detail"`
}
Issue 是门禁判定中的一条记录。
type Metrics ¶
type Metrics struct {
CompletedChapters int `json:"completed_chapters"`
TotalChapters int `json:"total_chapters"`
TotalWords int `json:"total_words"`
AvgWordsPerChap int `json:"avg_words_per_chapter"`
Phase string `json:"phase"`
Flow string `json:"flow"`
ReviewCount int `json:"review_count"`
RewriteCount int `json:"rewrite_count"`
AvgReviewScore float64 `json:"avg_review_score"`
CriticalFindings int `json:"critical_findings"`
WarningFindings int `json:"warning_findings"`
ToolCalls int `json:"tool_calls"`
Usage UsageMetrics `json:"usage"`
StylestatStatus string `json:"stylestat_status,omitempty"`
Stylestat *stylestat.Stats `json:"stylestat,omitempty"`
}
Metrics 是从 diag.Stats 直接借来的概览指标——eval 不重算。
type RangeSummary ¶
type RepeatSummary ¶
type RepeatSummary struct {
PassRate float64 `json:"pass_rate"`
HardFailRuns int `json:"hard_fail_runs"`
WarningRuns int `json:"warning_runs"`
CostUSD *RangeSummary `json:"cost_usd,omitempty"`
ToolCalls *RangeSummary `json:"tool_calls,omitempty"`
VariantPassRate float64 `json:"variant_pass_rate,omitempty"`
DeltaPassRate float64 `json:"delta_pass_rate,omitempty"`
}
type Result ¶
type Result struct {
CaseID string `json:"case_id"`
Category string `json:"category"`
Role string `json:"role,omitempty"`
Arm string `json:"arm,omitempty"`
Repeat int `json:"repeat,omitempty"`
Outcome Outcome `json:"outcome"`
HardFails []Issue `json:"hard_fails"`
Warnings []Issue `json:"warnings"`
Notes []Issue `json:"notes,omitempty"`
Passed []Issue `json:"passed"`
Metrics Metrics `json:"metrics"`
Dir string `json:"dir"`
}
Result 是单个 case 的完整评测结果。对齐设计稿三层模型: HardFails(阻塞)/ Warnings(回归,WARN)/ Notes(信息性,不影响门禁)。
type RunOptions ¶
type RunOptions struct {
OutputDir string // 隔离输出目录(必填)
Timeout time.Duration // 单 case 墙钟上限;0 表示不限
Progress io.Writer // 进度行输出(可选,nil 则不打印)
}
RunOptions 控制单次 case 运行。
type StyleCollection ¶
type StyleCollection struct {
Status string `json:"status"` // ok / insufficient_sample
Stats *stylestat.Stats `json:"stats,omitempty"`
}
StyleCollection 是从章节终稿中采集的全书文体事实。
type StyleDelta ¶
type StyleDelta struct {
Status string `json:"status"` // ok / insufficient_sample
PatternTopPerChapter float64 `json:"pattern_top_per_chapter_delta,omitempty"`
EndingShortRatio float64 `json:"ending_short_ratio_delta,omitempty"`
RepeatedSentences int `json:"repeated_sentences_delta,omitempty"`
TitleMixedDelta int `json:"title_mixed_delta,omitempty"`
}
type Suite ¶
type Suite struct {
RunID string `json:"run_id"`
Mode string `json:"mode"` // single / ab
Variant string `json:"variant,omitempty"`
Repeat int `json:"repeat"`
Gate Outcome `json:"gate"`
Cases []CaseResult `json:"cases"`
}
Suite 是一次评测运行的聚合结果。
type UsageMetrics ¶
type UsageMetrics struct {
Input int `json:"input,omitempty"`
Output int `json:"output,omitempty"`
CacheRead int `json:"cache_read,omitempty"`
CacheWrite int `json:"cache_write,omitempty"`
CostUSD float64 `json:"cost_usd,omitempty"`
MissingUsage int `json:"missing_usage,omitempty"`
UsageRecorded bool `json:"usage_recorded"`
}
UsageMetrics 是 meta/usage.json 中已有的可靠成本/token 事实。