eval

package
v1.1.3 Latest Latest
Warning

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

Go to latest
Published: May 29, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package eval provides an evaluation harness for testing and validating NornicDB's search quality, ranking accuracy, and performance.

The eval harness allows you to:

  • Define test cases with queries and expected results
  • Run evaluations and compute standard IR metrics
  • Compare before/after changes to verify improvements
  • Track performance over time

Metrics computed:

  • Precision@K: What fraction of top-K results are relevant?
  • Recall@K: What fraction of all relevant docs appear in top-K?
  • MRR (Mean Reciprocal Rank): Where does the first relevant result appear?
  • NDCG (Normalized Discounted Cumulative Gain): Ranking quality
  • Diversity: How different are the results from each other?

Example usage:

harness := eval.NewHarness(searchService)
harness.AddTestCase(eval.TestCase{
    Name:     "ML concepts",
    Query:    "machine learning algorithms",
    Expected: []string{"node-1", "node-2", "node-3"},
})

results, err := harness.Run(ctx)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Precision@10: %.2f\n", results.Precision10)
fmt.Printf("MRR: %.2f\n", results.MRR)

ELI12 (Explain Like I'm 12):

Think of it like grading a test:

  • You have questions (search queries)
  • You have answer keys (expected results)
  • The harness checks how well the search did
  • It gives you a score so you know if changes help or hurt

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type EvalResult

type EvalResult struct {
	// Suite info
	SuiteName string        `json:"suite_name"`
	Timestamp time.Time     `json:"timestamp"`
	Duration  time.Duration `json:"duration"`

	// Aggregate metrics (averaged across all test cases)
	Aggregate Metrics `json:"aggregate"`

	// Per-test results
	Results []TestResult `json:"results"`

	// Summary statistics
	TotalTests  int `json:"total_tests"`
	PassedTests int `json:"passed_tests"`
	FailedTests int `json:"failed_tests"`

	// Thresholds used for pass/fail
	Thresholds Thresholds `json:"thresholds"`
}

EvalResult contains the complete evaluation results.

type Harness

type Harness struct {
	// contains filtered or unexported fields
}

Harness is the main evaluation harness.

func NewHarness

func NewHarness(searchService *search.Service) *Harness

NewHarness creates a new evaluation harness.

func (*Harness) AddTestCase

func (h *Harness) AddTestCase(tc TestCase)

AddTestCase adds a single test case.

func (*Harness) AddTestCases

func (h *Harness) AddTestCases(cases []TestCase)

AddTestCases adds multiple test cases.

func (*Harness) LoadSuite

func (h *Harness) LoadSuite(path string) error

LoadSuite loads a test suite from a JSON file.

func (*Harness) Run

func (h *Harness) Run(ctx context.Context) (*EvalResult, error)

Run executes the evaluation and returns results.

func (*Harness) SetThresholds

func (h *Harness) SetThresholds(t Thresholds)

SetThresholds sets the pass/fail thresholds.

type Metrics

type Metrics struct {
	// Precision at various K values
	Precision1  float64 `json:"precision@1"`
	Precision5  float64 `json:"precision@5"`
	Precision10 float64 `json:"precision@10"`

	// Recall at various K values
	Recall5  float64 `json:"recall@5"`
	Recall10 float64 `json:"recall@10"`
	Recall50 float64 `json:"recall@50"`

	// Mean Reciprocal Rank - where does first relevant result appear?
	MRR float64 `json:"mrr"`

	// Normalized Discounted Cumulative Gain
	NDCG5  float64 `json:"ndcg@5"`
	NDCG10 float64 `json:"ndcg@10"`

	// Mean Average Precision
	MAP float64 `json:"map"`

	// Diversity - how different are results from each other? (0-1)
	Diversity float64 `json:"diversity"`

	// Hit Rate - fraction of queries with at least one relevant result
	HitRate float64 `json:"hit_rate"`
}

Metrics contains all computed evaluation metrics.

type Reporter

type Reporter struct {
	// contains filtered or unexported fields
}

Reporter formats and outputs evaluation results.

func NewReporter

func NewReporter(w io.Writer) *Reporter

NewReporter creates a new reporter that writes to the given writer.

func (*Reporter) PrintCompact

func (r *Reporter) PrintCompact(result *EvalResult)

PrintCompact prints a one-line summary.

func (*Reporter) PrintDetails

func (r *Reporter) PrintDetails(result *EvalResult)

PrintDetails prints detailed per-test results.

func (*Reporter) PrintJSON

func (r *Reporter) PrintJSON(result *EvalResult) error

PrintJSON outputs results as JSON.

func (*Reporter) PrintSummary

func (r *Reporter) PrintSummary(result *EvalResult)

PrintSummary prints a human-readable summary of results.

func (*Reporter) SaveJSON

func (r *Reporter) SaveJSON(result *EvalResult, path string) error

SaveJSON saves results to a JSON file.

type TestCase

type TestCase struct {
	// Name is a human-readable identifier for this test
	Name string `json:"name"`

	// Query is the search query text
	Query string `json:"query"`

	// Embedding is optional pre-computed query embedding
	// If nil, the harness will use text-only search
	Embedding []float32 `json:"embedding,omitempty"`

	// Expected is the list of node IDs that should be returned
	// Order matters for ranking metrics (first = most relevant)
	Expected []string `json:"expected"`

	// RelevanceGrades allows graded relevance (0-3 scale)
	// If nil, binary relevance is assumed (in Expected = relevant)
	// Map of nodeID -> grade (0=not relevant, 1=marginal, 2=relevant, 3=highly relevant)
	RelevanceGrades map[string]int `json:"relevance_grades,omitempty"`

	// Tags for grouping and filtering test cases
	Tags []string `json:"tags,omitempty"`

	// Options overrides default search options for this test
	Options *search.SearchOptions `json:"options,omitempty"`
}

TestCase defines a single evaluation test case.

type TestResult

type TestResult struct {
	TestCase     TestCase      `json:"test_case"`
	Metrics      Metrics       `json:"metrics"`
	Returned     []string      `json:"returned"`
	Duration     time.Duration `json:"duration"`
	Error        string        `json:"error,omitempty"`
	SearchMethod string        `json:"search_method"`
}

TestResult contains results for a single test case.

type TestSuite

type TestSuite struct {
	Name        string     `json:"name"`
	Description string     `json:"description"`
	Version     string     `json:"version"`
	Created     time.Time  `json:"created"`
	TestCases   []TestCase `json:"test_cases"`
}

TestSuite is a collection of test cases.

type Thresholds

type Thresholds struct {
	Precision10 float64 `json:"precision@10"`
	Recall10    float64 `json:"recall@10"`
	MRR         float64 `json:"mrr"`
	NDCG10      float64 `json:"ndcg@10"`
	HitRate     float64 `json:"hit_rate"`
}

Thresholds define minimum acceptable metric values.

func DefaultThresholds

func DefaultThresholds() Thresholds

DefaultThresholds returns sensible default thresholds.

Jump to

Keyboard shortcuts

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