Files
story/cmd/agent-eval/main.go
T

97 lines
2.7 KiB
Go
Raw Normal View History

2026-08-26 06:41:07 +08:00
package main
import (
"encoding/json"
"errors"
"flag"
"fmt"
"io"
"os"
"time"
"data-terminal-cloud/internal/agenteval"
)
func main() {
os.Exit(run(os.Args[1:], os.Stdout, os.Stderr, time.Now))
}
func run(args []string, stdout, stderr io.Writer, now func() time.Time) int {
flags := flag.NewFlagSet("agent-eval", flag.ContinueOnError)
flags.SetOutput(stderr)
suitePath := flags.String("suite", "", "评测集JSON路径")
observationsPath := flags.String("observations", "", "脱敏观测结果JSON路径")
outputPath := flags.String("out", "", "报告输出路径;省略时输出到stdout")
reportRef := flags.String("report-ref", "", "登记到运营配置评测证据中的报告引用")
if err := flags.Parse(args); err != nil {
return 2
}
if *suitePath == "" || *observationsPath == "" || *reportRef == "" || flags.NArg() != 0 {
fmt.Fprintln(stderr, "usage: agent-eval -suite <suite.json> -observations <observations.json> -report-ref <reference> [-out <report.json>]")
return 2
}
var suite agenteval.Suite
if err := decodeFile(*suitePath, &suite); err != nil {
fmt.Fprintf(stderr, "读取评测集失败: %v\n", err)
return 2
}
var observations agenteval.ObservationRun
if err := decodeFile(*observationsPath, &observations); err != nil {
fmt.Fprintf(stderr, "读取观测结果失败: %v\n", err)
return 2
}
report, err := agenteval.Evaluate(suite, observations, now())
if err != nil {
fmt.Fprintf(stderr, "评测输入无效: %v\n", err)
return 2
}
artifact, err := agenteval.NewArtifact(report, *reportRef)
if err != nil {
fmt.Fprintf(stderr, "报告引用无效: %v\n", err)
return 2
}
encoded, err := json.MarshalIndent(artifact, "", " ")
if err != nil {
fmt.Fprintf(stderr, "生成评测报告失败: %v\n", err)
return 2
}
encoded = append(encoded, '\n')
if *outputPath == "" {
if _, err = stdout.Write(encoded); err != nil {
fmt.Fprintf(stderr, "输出评测报告失败: %v\n", err)
return 2
}
} else if err = os.WriteFile(*outputPath, encoded, 0o600); err != nil {
fmt.Fprintf(stderr, "写入评测报告失败: %v\n", err)
return 2
} else {
fmt.Fprintf(stdout, "%s:%s(%d/%d)\n", report.Result, *outputPath, report.Metrics.CasesPassed, report.Metrics.CasesTotal)
}
if report.Result != "PASSED" {
return 1
}
return 0
}
func decodeFile(path string, target any) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
decoder := json.NewDecoder(file)
decoder.DisallowUnknownFields()
if err = decoder.Decode(target); err != nil {
return err
}
var trailing any
if err = decoder.Decode(&trailing); !errors.Is(err, io.EOF) {
if err == nil {
return errors.New("JSON文件包含多个顶层值")
}
return err
}
return nil
}