report

package
v0.9.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 21, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package report provides report generation functionality for evaluation results.

Overview

The report package processes NamespacedObserver trees containing ResultCollector data to produce markdown-formatted evaluation reports.

ByEval generates a report organized by evaluation type, then by model, then by test case. It requires observer paths following the /{model}/{test case}/{eval} structure.

Usage

import "chainguard.dev/driftlessaf/agents/evals/report"

// Create some evaluation data
obs := evals.NewNamespacedObserver(func(name string) *evals.ResultCollector {
	return evals.NewResultCollector(customObserver(name))
})

// Generate a report organized by evaluation type
reportStr, hasFailures := report.ByEval(obs, 0.8)
if hasFailures {
	fmt.Printf("Report:\n%s", reportStr)
}

Report Format

Reports are generated in markdown format with:

  • A summary table of pass rates and grades per evaluation and model
  • Hierarchical detail trees per evaluation
  • Failure message lists
  • Below-threshold grade details

Thread Safety

ByEval is safe for concurrent use as it is a pure function that does not modify its input parameters. Multiple goroutines can safely call it simultaneously with the same or different observers.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ByEval

func ByEval(obs *evals.NamespacedObserver[*evals.ResultCollector], threshold float64) (string, bool)

ByEval generates a report organized by evaluation, then by model, then by test case. Assumes paths follow the pattern /{model}/{test case}/{eval} for paths with results. Returns the report string and a boolean indicating if any evaluations fell below the threshold.

Example

ExampleByEval demonstrates basic usage of the ByEval report generator.

package main

import (
	"fmt"

	"chainguard.dev/driftlessaf/agents/evals"
	"chainguard.dev/driftlessaf/agents/evals/report"
)

// exampleObserver implements evals.Observer for examples
type exampleObserver struct {
	name  string
	count int64
}

func (e *exampleObserver) Fail(msg string) {

}

func (e *exampleObserver) Log(msg string) {

}

func (e *exampleObserver) Grade(score float64, reasoning string) {

}

func (e *exampleObserver) Increment() {
	e.count++
}

func (e *exampleObserver) Total() int64 {
	return e.count
}

func main() {
	// Create a factory for result collectors
	factory := func(name string) *evals.ResultCollector {
		return evals.NewResultCollector(&exampleObserver{name: name})
	}

	// Create root observer
	obs := evals.NewNamespacedObserver(factory)

	// Add evaluation data following /{model}/{test case}/{eval} pattern
	// Model: claude, Test case: security-check, Eval: no-vulnerabilities
	evalObs1 := obs.Child("claude").Child("security-check").Child("no-vulnerabilities")
	evalObs1.Fail("Buffer overflow detected")
	evalObs1.Increment()
	evalObs1.Increment()

	// Model: gemini, Test case: security-check, Eval: no-vulnerabilities
	evalObs2 := obs.Child("gemini").Child("security-check").Child("no-vulnerabilities")
	evalObs2.Increment()

	// Generate ByEval report with 80% threshold
	reportStr, hasFailures := report.ByEval(obs, 0.8)

	fmt.Printf("Has failures: %t\n", hasFailures)
	fmt.Printf("Report:\n%s", reportStr)

}
Output:
Has failures: true
Report:
## Summary Table

| Evaluation Metric    | claude        | gemini      | Average  |
|----------------------|---------------|-------------|----------|
| no-vulnerabilities   | ❌ 50.0%      | 100.0%      | ❌ 75.0% |
|    └─ security-check | ❌ 0.50 (50%) | 1.00 (100%) | ❌ 75.0% |

no-vulnerabilities [❌ 66.7%] (2/3)
└ claude [❌ 50.0%] (1/2)
  └ security-check [❌ 50.0%] (1/2)
    └ 1 [FAIL] Buffer overflow detected
Example (MultipleEvaluations)

ExampleByEval_multipleEvaluations demonstrates multiple evaluations organized by eval type.

package main

import (
	"fmt"

	"chainguard.dev/driftlessaf/agents/evals"
	"chainguard.dev/driftlessaf/agents/evals/report"
)

// exampleObserver implements evals.Observer for examples
type exampleObserver struct {
	name  string
	count int64
}

func (e *exampleObserver) Fail(msg string) {

}

func (e *exampleObserver) Log(msg string) {

}

func (e *exampleObserver) Grade(score float64, reasoning string) {

}

func (e *exampleObserver) Increment() {
	e.count++
}

func (e *exampleObserver) Total() int64 {
	return e.count
}

func main() {
	// Create a factory for result collectors
	factory := func(name string) *evals.ResultCollector {
		return evals.NewResultCollector(&exampleObserver{name: name})
	}

	// Create root observer
	obs := evals.NewNamespacedObserver(factory)

	// Add data for multiple evaluations
	// Security evaluation - passing
	securityObs := obs.Child("claude").Child("auth-test").Child("security-check")
	securityObs.Increment()

	// Performance evaluation - passing
	perfObs := obs.Child("claude").Child("load-test").Child("performance-check")
	perfObs.Grade(0.85, "Good performance")
	perfObs.Increment()

	// Performance evaluation - failing (below 80% threshold)
	perfFailObs := obs.Child("claude").Child("stress-test").Child("performance-check")
	perfFailObs.Grade(0.65, "Performance issues under load")
	perfFailObs.Increment()

	// Generate report
	reportStr, hasFailures := report.ByEval(obs, 0.8)

	fmt.Printf("Has failures: %t\n", hasFailures)
	fmt.Printf("Report:\n%s", reportStr)

}
Output:
Has failures: true
Report:
## Summary Table

| Evaluation Metric | claude         | Average  |
|-------------------|----------------|----------|
| performance-check | ❌ 2/2 (75.0%) | ❌ 75.0% |
|    └─ stress-test | ❌ 0.65 (65%)  | ❌ 65.0% |
| security-check    | 100.0%         | 100.0%   |

performance-check [❌ 0.75 avg] (2 results)
└ claude [❌ 0.75 avg] (2 results)
  └ stress-test [❌ 0.65 avg] (1 result)
    └ 1 [0.65] Performance issues under load
security-check [100.0%] (1/1)
Example (WithGrades)

ExampleByEval_withGrades demonstrates ByEval with graded evaluations.

package main

import (
	"fmt"

	"chainguard.dev/driftlessaf/agents/evals"
	"chainguard.dev/driftlessaf/agents/evals/report"
)

// exampleObserver implements evals.Observer for examples
type exampleObserver struct {
	name  string
	count int64
}

func (e *exampleObserver) Fail(msg string) {

}

func (e *exampleObserver) Log(msg string) {

}

func (e *exampleObserver) Grade(score float64, reasoning string) {

}

func (e *exampleObserver) Increment() {
	e.count++
}

func (e *exampleObserver) Total() int64 {
	return e.count
}

func main() {
	// Create a factory for result collectors
	factory := func(name string) *evals.ResultCollector {
		return evals.NewResultCollector(&exampleObserver{name: name})
	}

	// Create root observer
	obs := evals.NewNamespacedObserver(factory)

	// Add evaluation data with grades
	// Model: claude, Test case: code-quality, Eval: readability-score
	evalObs1 := obs.Child("claude").Child("code-quality").Child("readability-score")
	evalObs1.Grade(0.75, "Some improvements needed")
	evalObs1.Increment()

	// Model: gemini, Test case: code-quality, Eval: readability-score
	evalObs2 := obs.Child("gemini").Child("code-quality").Child("readability-score")
	evalObs2.Grade(0.90, "Very readable code")
	evalObs2.Increment()

	// Generate report with 80% threshold
	reportStr, hasFailures := report.ByEval(obs, 0.8)

	fmt.Printf("Has failures: %t\n", hasFailures)
	fmt.Printf("Report:\n%s", reportStr)

}
Output:
Has failures: true
Report:
## Summary Table

| Evaluation Metric  | claude        | gemini     | Average |
|--------------------|---------------|------------|---------|
| readability-score  | ❌ 75.0%      | 90.0%      | 82.5%   |
|    └─ code-quality | ❌ 0.75 (75%) | 0.90 (90%) | 82.5%   |

readability-score [0.82 avg] (2 results)
└ claude [❌ 0.75 avg] (1 result)
  └ code-quality [❌ 0.75 avg] (1 result)
    └ 1 [0.75] Some improvements needed

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL