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

97 lines
2.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}