chore: establish local platform baseline
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"data-terminal-cloud/internal/agenteval"
|
||||
)
|
||||
|
||||
func main() {
|
||||
os.Exit(run(os.Args[1:], os.Stdout, os.Stderr))
|
||||
}
|
||||
|
||||
func run(args []string, stdout, stderr io.Writer) int {
|
||||
flags := flag.NewFlagSet("agent-eval-collect", flag.ContinueOnError)
|
||||
flags.SetOutput(stderr)
|
||||
suitePath := flags.String("suite", "", "评测集JSON路径")
|
||||
manifestPath := flags.String("manifest", "", "用例、通话和脱敏评分卡映射JSON路径")
|
||||
outputPath := flags.String("out", "", "观测结果输出路径;省略时输出到stdout")
|
||||
apiBaseURL := flags.String("api", "http://127.0.0.1:58080", "SaaS API基础地址")
|
||||
tokenFile := flags.String("access-token-file", "", "OIDC访问令牌文件;省略时读取AGENT_EVAL_ACCESS_TOKEN")
|
||||
if err := flags.Parse(args); err != nil {
|
||||
return 2
|
||||
}
|
||||
if *suitePath == "" || *manifestPath == "" || flags.NArg() != 0 {
|
||||
fmt.Fprintln(stderr, "usage: agent-eval-collect -suite <suite.json> -manifest <manifest.json> [-api <url>] [-access-token-file <path>] [-out <observations.json>]")
|
||||
return 2
|
||||
}
|
||||
var suite agenteval.Suite
|
||||
if err := decodeFile(*suitePath, &suite); err != nil {
|
||||
fmt.Fprintf(stderr, "读取评测集失败: %v\n", err)
|
||||
return 2
|
||||
}
|
||||
var manifest agenteval.CollectionManifest
|
||||
if err := decodeFile(*manifestPath, &manifest); err != nil {
|
||||
fmt.Fprintf(stderr, "读取采集清单失败: %v\n", err)
|
||||
return 2
|
||||
}
|
||||
token, err := readToken(*tokenFile)
|
||||
if err != nil {
|
||||
fmt.Fprintf(stderr, "读取访问令牌失败: %v\n", err)
|
||||
return 2
|
||||
}
|
||||
collector, err := agenteval.NewCollector(*apiBaseURL, token, &http.Client{Timeout: 15 * time.Second})
|
||||
if err != nil {
|
||||
fmt.Fprintf(stderr, "创建采集器失败: %v\n", err)
|
||||
return 2
|
||||
}
|
||||
runResult, err := collector.Collect(context.Background(), suite, manifest)
|
||||
if err != nil {
|
||||
fmt.Fprintf(stderr, "采集评测观测失败: %v\n", err)
|
||||
return 1
|
||||
}
|
||||
encoded, err := json.MarshalIndent(runResult, "", " ")
|
||||
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, "已采集%d个用例:%s\n", len(runResult.Observations), *outputPath)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func readToken(path string) (string, error) {
|
||||
if strings.TrimSpace(path) == "" {
|
||||
value := strings.TrimSpace(os.Getenv("AGENT_EVAL_ACCESS_TOKEN"))
|
||||
if value == "" {
|
||||
return "", errors.New("set AGENT_EVAL_ACCESS_TOKEN or -access-token-file")
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
value := strings.TrimSpace(string(content))
|
||||
if value == "" || strings.ContainsAny(value, "\r\n\x00") {
|
||||
return "", errors.New("token file must contain one non-empty line")
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user