retrieval

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Aug 2, 2026 License: MIT, MIT Imports: 20 Imported by: 0

README

retrieval

Go Reference Go Version

Hybrid scoring and reranking for local retrieval pipelines — embedding similarity, keyword and filename overlap, MMR diversification, and IR evaluation, all over vectors you supply.

package main

import (
	"fmt"

	"github.com/dotcommander/reliquary/retrieval"
)

func main() {
	scorer := retrieval.NewScorer(retrieval.DefaultWeights())
	docVec1 := []float64{1, 0}
	docVec2 := []float64{0, 1}
	queryEmbedding := []float64{1, 0}

	results := []*retrieval.Result{
		{ID: "doc1", Content: "machine learning fundamentals", Filename: "ml-guide.md", Embedding: docVec1},
		{ID: "doc2", Content: "cooking recipes", Filename: "recipes.md", Embedding: docVec2},
	}

	ranked := scorer.Rerank(queryEmbedding, "machine learning", results)
	fmt.Println(ranked[0].ID, ranked[0].CombinedScore)
}

Install

go get github.com/dotcommander/reliquary/retrieval

Requires Go 1.26+.

How it fits

vectors   ─── cosine similarity primitives (Cosine64)
chunking  ─── text splitting strategies (NewChunker, Chunk)
               │
               ▼
          retrieval  ─── scoring · reranking · MMR · filtering · eval

retrieval sits at the top of the local-retrieval stack. It imports vector for similarity math, chunking for text splitting, and the provider-neutral embedding contract for vector adapters. You still produce embeddings externally — with any model or provider — and pass them in. The package imposes no constraints on how embeddings are generated.

What's inside

Construct Purpose
Scorer / Rerank Corpus-aware batch scoring with min-max calibration
CalibratedScore / Band Fixed-weight single-document scoring and tiering
MMR Maximal Marginal Relevance — relevance vs. diversity
TextChunks / BestChunk Split text and pick the best-matching chunk
Filter Path inclusion/exclusion for retrieval scans
ExtractMetadata / MetadataScore Title and heading signal from path + content
Evaluate Recall@K, Precision@K, MRR, NDCG@K, unique-topic count
Fixture / EvaluateRun Golden query judgments plus aggregate, per-query, segment, and layer reports
Plan / PlanRun Provider-neutral source budgets, fusion labels, stage outputs, and per-source metrics

Evaluate a captured run against golden judgments:

fixture := retrieval.Fixture{
	ID: "golden",
	Queries: []retrieval.FixtureQuery{{
		ID:        "q1",
		Text:      "machine learning",
		Judgments: []retrieval.Judgment{{DocID: "doc1", Relevance: 2, Topic: "ml"}},
	}},
}
run := retrieval.Run{
	ID: "candidate",
	Queries: []retrieval.RunQuery{{
		ID:      "q1",
		Results: []retrieval.RankedResult{{ID: "doc1", Score: 0.91}},
	}},
}

report, err := retrieval.EvaluateRun(fixture, run, 3)
if err != nil {
	panic(err)
}
fmt.Println(report.Metrics.RecallAtK)

EvaluateRun requires the run to cover every query in the fixture and rejects unknown query IDs. Run validation rejects blank or duplicate result IDs in the final list and every captured stage. Lower-level metric and tuning helpers canonicalize repeated result IDs by retaining the first occurrence.

Capture staged hybrid retrieval without encoding provider query syntax:

plan := retrieval.Plan{
	ID:     "hybrid",
	Fusion: retrieval.FusionModeRRF,
	Sources: []retrieval.CandidateSource{
		{ID: "lexical", ScoreSpace: "local_bm25", Limit: 50},
		{ID: "vector", ScoreSpace: "cosine", Limit: 100},
	},
}
run := retrieval.EvaluatePlan(query, plan, layers, sourceReports, 10)
fmt.Println(run.Report.CandidateRecall)

Documentation

License

MIT © DotCommander contributors

Documentation

Overview

Package retrieval is a hybrid scoring and reranking layer for local retrieval pipelines.

It sits above github.com/dotcommander/reliquary/vector (cosine primitives), github.com/dotcommander/reliquary/chunking (text splitting), and the provider-neutral embeddings contract. Callers still own model/provider execution; retrieval only adapts embedding vectors into its scoring space.

Pipeline shape

chunk (chunking) → embed (caller) → Rerank → MMR → Evaluate

Optional diagnostics and calibration layers can be added around that path: ScoreReference for cohort-relative score percentiles, EvaluateSegments for slice-level metrics, EvaluateLayers for candidate/rerank/diversification attribution, EvaluateRun for fixture-backed golden reports, and TuneWeights for deterministic weight/lambda grid search.

Scoring pipelines

Two paths are available depending on whether corpus context is present:

  • Scorer / Rerank: corpus-aware batch scoring. Rerank runs min-max calibration across the whole result set so ranking is relative to the corpus. Build with NewScorer(DefaultWeights()) and call Rerank with the query embedding, query text, and all candidate Results. RerankWithTrace follows the same scoring path and returns rank-aligned diagnostics for raw scores, calibrated scores, weights, and signal contributions. RerankWithReference applies an explicit ScoreReference after reranking when callers need stable cohort-relative percentiles.

  • CalibratedScore: single-document scoring with fixed weights (0.62 cosine / 0.18 keyword / 0.10 filename / 0.10 metadata). Independent of corpus distribution; useful when scoring one result in isolation.

AdaptiveWeights adjusts the weight mix by query token count when a more query-length-aware Scorer is preferred over DefaultWeights.

Diversification

MMR (Maximal Marginal Relevance) re-orders a ranked list to balance relevance against redundancy. The lambda parameter slides between pure relevance (lambda=1) and pure diversity (lambda=0).

Evaluation and tuning

Evaluate computes RecallAtK, PrecisionAtK, MRR, NDCGAtK, and UniqueTopicAtK from a ranked result list against expected relevant document IDs. EvaluateSegments reports the same metrics by caller-owned segment keys with sample and hit counts. EvaluateLayers separates candidate generation, reranking, diversification, and final top-k metrics so regressions can be localized. EvaluateRun evaluates captured run outputs against golden fixture judgments and reports aggregate, per-query, segment, and layer metrics. TuneWeights runs a deterministic grid over precomputed ScoreSignals and optional MMR lambdas, rejects configs that miss floor constraints, and returns the best remaining configuration.

Supporting building blocks

  • Filter: path inclusion/exclusion by extension or prefix
  • ExtractMetadata / MetadataScore: title and heading signal from file path and content
  • ScoreReference: sorted reference cohorts for stable percentile scoring

Index

Examples

Constants

View Source
const (
	// ScoreReferenceVersion is the current ScoreReference schema version.
	ScoreReferenceVersion = 1
	// MinScoreReferenceSamples is the minimum number of finite samples
	// FitScoreReference accepts for a reference cohort.
	MinScoreReferenceSamples = 20
)
View Source
const ContextEndLineKey = "reliquary.context.end_line"

ContextEndLineKey is the retrieval-owned metadata key for a result's inclusive, one-based ending source line.

View Source
const ContextStartLineKey = "reliquary.context.start_line"

ContextStartLineKey is the retrieval-owned metadata key for a result's inclusive, one-based starting source line.

Variables

View Source
var ErrDuplicateDocumentID = errors.New("retrieval: duplicate document ID")

ErrDuplicateDocumentID reports duplicate identifiers in one document batch.

View Source
var ErrEmbeddingCountMismatch = errors.New("retrieval: embedding count mismatch")

ErrEmbeddingCountMismatch reports that result and embedding batches no longer describe the same candidate set.

View Source
var ErrInvalidDocumentID = errors.New("retrieval: document ID must not be blank")

ErrInvalidDocumentID reports a blank document identifier.

View Source
var ErrInvalidRerankResult = errors.New("retrieval: invalid rerank result")

ErrInvalidRerankResult reports that a reranker returned scores that do not correspond one-to-one with its candidates or are not finite values in [0,1].

View Source
var ErrNilResult = errors.New("retrieval: nil result")

ErrNilResult reports a nil result in a batch passed to EmbedResults. Unlike AttachEmbeddings, EmbedResults needs every result in order to build the input batch and therefore rejects sparse result slices before calling the embedder.

Functions

func AttachEmbeddings

func AttachEmbeddings(results []*Result, vectors []embedding.Vector) error

AttachEmbeddings copies embedding vectors onto matching retrieval results by index. It returns an error rather than silently dropping vectors because a count mismatch means the caller's scoring identity is ambiguous. Unlike EmbedResults, it preserves its existing sparse-destination behavior: a nil result consumes the matching vector without mutation.

func CalibratedScore

func CalibratedScore(c ScoreComponents) float64

CalibratedScore compresses hybrid signals into a stable 0..1 score.

func DiversifyWithTrace added in v0.11.0

func DiversifyWithTrace(results []*Result, k int, lambda float64) ([]*Result, []MMRExplanation)

DiversifyWithTrace applies the same MMR selection as Diversify and returns one rank-aligned explanation for each selected result.

func EmbedResults

func EmbedResults(ctx context.Context, e embedding.Embedder, results []*Result) error

EmbedResults embeds each result's Content with the embedder and attaches the resulting vectors in place. It is the glue between ResultsFromDocuments and scoring, so callers no longer hand-roll the texts -> Embed -> AttachEmbeddings loop.

func EmbeddingVector

func EmbeddingVector(v embedding.Vector) []float64

EmbeddingVector converts a provider-neutral embedding.Vector into the float64 vector space used by retrieval scoring.

func EmbeddingVectors

func EmbeddingVectors(vectors []embedding.Vector) [][]float64

EmbeddingVectors converts a batch of provider-neutral embedding vectors into retrieval vectors.

func FilenameOverlap

func FilenameOverlap(filename, categoryName string) float64

func FormatContext added in v0.11.0

func FormatContext(results []*Result, opts ...ContextOption) (string, error)

FormatContext renders non-empty retrieval results in order. It adds no prompt instructions, escaping, or filtering; by default blocks are joined by one blank line.

Example
package main

import (
	"fmt"
	"strings"

	"github.com/dotcommander/reliquary/retrieval"
)

type wordCounter struct{}

func (wordCounter) Count(text string) (int, error) {
	return len(strings.Fields(text)), nil
}

func main() {
	results := []*retrieval.Result{
		{
			Filename: "gc.md",
			Content:  "Go uses a concurrent garbage collector.",
			Metadata: map[string]any{
				retrieval.ContextStartLineKey: 12,
				retrieval.ContextEndLineKey:   12,
			},
		},
		{
			DocumentID: "scheduler",
			Content:    "Goroutines are multiplexed onto threads.",
			Metadata: map[string]any{
				retrieval.ContextStartLineKey: 4,
				retrieval.ContextEndLineKey:   5,
			},
		},
	}

	promptBlock, err := retrieval.FormatContext(results,
		retrieval.WithHeader("[Source: %s, Lines: %d-%d]"),
		retrieval.WithMaxTokens(2048, wordCounter{}),
	)
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println(promptBlock)
}
Output:
[Source: gc.md, Lines: 12-12]
Go uses a concurrent garbage collector.

[Source: scheduler, Lines: 4-5]
Goroutines are multiplexed onto threads.

func MetadataScore

func MetadataScore(query string, meta Metadata) float64

func ParseCSV

func ParseCSV(value string) []string

func RecencyFromAge

func RecencyFromAge(age, halfLife float64) float64

RecencyFromAge maps an age to a 0..1 freshness score via exponential decay: 2^(-age/halfLife). An item exactly halfLife old scores 0.5; brand-new scores ~1.0; very old asymptotes toward 0. Both arguments are in the same time unit (e.g. seconds).

Guards: NaN input returns 0.0; age <= 0 returns 1.0 (treat future/now as fully fresh); halfLife <= 0 returns 1.0 (no decay configured -> no penalty). Indeterminate exponential results such as +Inf/+Inf also return 0.0. Use the result as Result.ImportanceScore's sibling: assign to RecencyScore.

func TextChunks

func TextChunks(content string, size int, overlap int) []string

TextChunks splits text into chunks and filters empties.

func ValidateFixture

func ValidateFixture(f Fixture) error

ValidateFixture checks the structural invariants required for fixture evaluation.

func ValidateRerankScores added in v0.11.0

func ValidateRerankScores(candidateCount int, scores []float64) error

ValidateRerankScores verifies that scores contains exactly one finite value in [0,1] for each candidate.

func ValidateRun

func ValidateRun(r Run) error

ValidateRun checks the structural invariants required for run evaluation.

Types

type CandidateSource

type CandidateSource struct {
	ID         string
	ScoreSpace string
	Limit      int
	Weight     float64
}

CandidateSource describes one provider-neutral candidate source in a retrieval plan.

type ChunkResult

type ChunkResult struct {
	Text       string
	Embedding  []float64
	Similarity float64
}

func BestChunk

func BestChunk(queryEmbedding []float64, chunks []ChunkResult) ChunkResult

BestChunk returns the chunk with highest cosine similarity.

type ContextOption added in v0.11.0

type ContextOption func(*contextConfig)

ContextOption configures FormatContext.

func WithHeader added in v0.11.0

func WithHeader(template string) ContextOption

WithHeader adds a header before each result's content. The supported placeholders are %s for the source, the first two %d placeholders for the inclusive source line range, and %% for a literal percent sign.

func WithMaxTokens added in v0.11.0

func WithMaxTokens(maxTokens int, counter ContextTokenCounter) ContextOption

WithMaxTokens limits formatted context to a contiguous prefix of complete result blocks. A positive limit requires a non-nil counter. A nonpositive limit produces empty output without invoking the counter.

func WithSeparator added in v0.11.0

func WithSeparator(separator string) ContextOption

WithSeparator replaces the default blank-line separator between results.

type ContextTokenCounter added in v0.11.0

type ContextTokenCounter interface {
	Count(text string) (int, error)
}

ContextTokenCounter counts tokens using the caller's provider and model policy.

type EvalQuery

type EvalQuery struct {
	ID         string
	Relevant   map[string]float64
	TopicByDoc map[string]string
}

EvalQuery describes expected relevant documents for one retrieval query.

func EvalQueryFromFixture

func EvalQueryFromFixture(fq FixtureQuery) EvalQuery

EvalQueryFromFixture converts positive judgments into Relevant and all judgment topics into TopicByDoc.

type Filter

type Filter struct {
	IncludeExts []string
	IgnoreDirs  []string
	IgnoreExts  []string
}

func DefaultFilter

func DefaultFilter() Filter

func (Filter) Include

func (f Filter) Include(path string) bool

type Fixture

type Fixture struct {
	ID          string
	Description string
	Queries     []FixtureQuery
}

Fixture is a caller-owned golden query set for deterministic retrieval quality reports.

type FixtureQuery

type FixtureQuery struct {
	ID        string
	Text      string
	Judgments []Judgment
}

FixtureQuery is one golden query and its judged documents.

func (FixtureQuery) EvalQuery

func (fq FixtureQuery) EvalQuery() EvalQuery

EvalQuery converts a fixture query into the existing evaluation shape.

type FusionMode

type FusionMode string

FusionMode labels how source candidate lists are combined. It is a caller contract only; this package does not execute provider queries or rerankers.

const (
	FusionModeNone     FusionMode = ""
	FusionModeRRF      FusionMode = "rrf"
	FusionModeWeighted FusionMode = "weighted"
)

type Judgment

type Judgment struct {
	DocID     string
	Relevance float64
	Topic     string
	Segment   string
}

Judgment labels one document for a fixture query. Relevance values greater than zero are relevant; zero relevance can still provide topic or segment metadata for evaluated results.

type LayerReport

type LayerReport struct {
	RelevantCount       int
	CandidateCount      int
	CandidateHitCount   int
	CandidateRecall     float64
	CandidateMetrics    Metrics
	RerankMetrics       Metrics
	DiversifiedMetrics  Metrics
	FinalMetrics        Metrics
	DiversityLiftAtK    int
	FinalDeltaRecallAtK float64
}

LayerReport separates candidate generation, reranking, diversification, and final top-k quality so retrieval regressions can be localized to one stage.

func EvaluateLayers

func EvaluateLayers(query EvalQuery, layers LayeredResults, k int) LayerReport

EvaluateLayers evaluates retrieval outputs captured at each stage. CandidateRecall is computed across the full candidate set, independent of k; the layer Metrics fields use Evaluate with the provided k. DiversityLiftAtK is Diversified.UniqueTopicAtK minus Rerank.UniqueTopicAtK, and FinalDeltaRecallAtK is Final.RecallAtK minus CandidateMetrics.RecallAtK.

type LayeredResults

type LayeredResults struct {
	Candidates  []RankedResult
	Reranked    []RankedResult
	Diversified []RankedResult
	Final       []RankedResult
}

LayeredResults carries ranked result lists captured at each retrieval stage. Empty slices are valid and report zero metrics for that layer.

type MMRExplanation added in v0.11.0

type MMRExplanation struct {
	Lambda                float64
	Relevance             float64
	MaxSimilarity         float64
	RelevanceContribution float64
	Penalty               float64
	SelectionScore        float64
}

MMRExplanation describes one maximal-marginal-relevance selection. MaxSimilarity is the maximum positive cosine similarity to a previously selected item; missing, orthogonal, and negatively correlated embeddings contribute zero. Penalty is signed and is therefore zero or negative.

type MMRItem

type MMRItem struct {
	ID        string
	Score     float64
	Embedding []float64
	Topic     string
}

MMRItem represents an item participating in MMR diversification.

func MMR

func MMR(items []MMRItem, k int, lambda float64) []MMRItem
Example
package main

import (
	"fmt"

	"github.com/dotcommander/reliquary/retrieval"
)

func main() {
	// Diversify items to avoid returning multiple identical documents
	items := []retrieval.MMRItem{
		{
			ID:        "doc1",
			Score:     0.95,
			Embedding: []float64{0.1, 0.2, 0.3},
		},
		{
			ID:        "doc2", // Highly redundant with doc1 (identical embedding)
			Score:     0.92,
			Embedding: []float64{0.1, 0.2, 0.3},
		},
		{
			ID:        "doc3", // Lower score but different topic
			Score:     0.75,
			Embedding: []float64{0.9, 0.1, 0.0},
		},
	}

	// k = 2, lambda = 0.5 (equal balance of relevance and diversity)
	diversified := retrieval.MMR(items, 2, 0.5)

	for _, item := range diversified {
		fmt.Printf("- %s (Score: %.2f)\n", item.ID, item.Score)
	}
}
Output:
- doc1 (Score: 0.95)
- doc3 (Score: 0.75)

func MMRItems

func MMRItems(results []*Result) []MMRItem

MMRItems adapts scored retrieval results into MMR input items.

type Metadata

type Metadata struct {
	Title    string
	Headings []string
	Path     string
}

func ExtractMetadata

func ExtractMetadata(path string, content string) Metadata

type Metrics

type Metrics struct {
	RecallAtK      float64
	PrecisionAtK   float64
	MRR            float64
	NDCGAtK        float64
	UniqueTopicAtK int
}

Metrics summarizes retrieval quality for a ranked result list.

func Evaluate

func Evaluate(query EvalQuery, results []RankedResult, k int) Metrics

type Plan

type Plan struct {
	ID             string
	Sources        []CandidateSource
	Fusion         FusionMode
	RerankLabel    string
	DiversifyLabel string
	Budgets        []StageBudget
	Identity       hash.Digest
}

Plan describes source budgets and stage labels for a retrieval run.

type PlanRun

type PlanRun struct {
	Plan    Plan
	QueryID string
	Sources []SourceReport
	Layers  LayeredResults
	Report  LayerReport
}

PlanRun captures the observed outputs for a retrieval plan.

func EvaluatePlan

func EvaluatePlan(query EvalQuery, plan Plan, layers LayeredResults, sources []SourceReport, k int) PlanRun

EvaluatePlan builds a PlanRun with per-source and layered metrics.

Example
package main

import (
	"fmt"

	"github.com/dotcommander/reliquary/retrieval"
)

func main() {
	query := retrieval.EvalQuery{
		ID:       "q1",
		Relevant: map[string]float64{"doc1": 1, "doc3": 1},
	}
	plan := retrieval.Plan{
		ID:     "hybrid",
		Fusion: retrieval.FusionModeRRF,
		Sources: []retrieval.CandidateSource{
			{ID: "lexical", ScoreSpace: "local_bm25", Limit: 2},
			{ID: "vector", ScoreSpace: "cosine", Limit: 2},
		},
	}
	sources := []retrieval.SourceReport{
		{Source: plan.Sources[0], Results: []retrieval.RankedResult{{ID: "doc1"}, {ID: "doc2"}}},
		{Source: plan.Sources[1], Results: []retrieval.RankedResult{{ID: "doc3"}, {ID: "doc4"}}},
	}
	layers := retrieval.LayeredResults{
		Candidates: []retrieval.RankedResult{{ID: "doc1"}, {ID: "doc2"}, {ID: "doc3"}, {ID: "doc4"}},
		Final:      []retrieval.RankedResult{{ID: "doc1"}, {ID: "doc3"}},
	}

	run := retrieval.EvaluatePlan(query, plan, layers, sources, 2)
	fmt.Println(run.Report.CandidateRecall, run.Sources[0].CandidateRecall)
}
Output:
1 0.5

type RRFExplanation added in v0.11.0

type RRFExplanation struct {
	K                   float64
	VectorRank          int
	LexicalRank         int
	VectorContribution  float64
	LexicalContribution float64
	FusedScore          float64
	FusedRank           int
}

RRFExplanation describes reciprocal-rank fusion for one result. A zero lane rank and contribution mean that the result was absent from that lane.

type RankedResult

type RankedResult struct {
	ID    string
	Score float64
	Topic string
}

RankedResult is a scored retrieval result for metric evaluation.

type Report

type Report struct {
	FixtureID  string
	RunID      string
	K          int
	QueryCount int
	Metrics    Metrics
	Queries    []ReportQuery
}

Report is the aggregate and per-query fixture evaluation output.

func EvaluateRun

func EvaluateRun(f Fixture, r Run, k int) (Report, error)

EvaluateRun evaluates captured retrieval results against a validated fixture. The run must contain every fixture query and no unknown query IDs. Query reports are sorted lexically by query ID, independent of fixture or run input order.

type ReportQuery

type ReportQuery struct {
	ID       string
	Metrics  Metrics
	Segments []SegmentMetrics
	Layers   LayerReport
}

ReportQuery is the per-query portion of a fixture evaluation report.

type ReportThresholds

type ReportThresholds struct {
	MinRecallAtK       float64
	MinPrecisionAtK    float64
	MinMRR             float64
	MinNDCGAtK         float64
	MinUniqueTopicsAtK int
}

ReportThresholds declares aggregate metric floors for CheckThresholds.

type Reranker added in v0.11.0

type Reranker interface {
	Rerank(ctx context.Context, query string, candidates []*Result) ([]float64, error)
}

Reranker assigns an external relevance score to each candidate for a query. Returned scores correspond positionally to candidates.

Separate Search calls may invoke the same Reranker concurrently. Implementations that are not concurrency-safe must provide their own synchronization.

type RerankerExplanation added in v0.11.0

type RerankerExplanation struct {
	InputRank int
	Score     float64
	Rank      int
}

RerankerExplanation describes the observable input and output of an external reranker. The Reranker interface does not expose model-internal reasoning.

type Result

type Result struct {
	ID              string
	IndexIdentity   string
	DocumentID      string
	Content         string
	Filename        string
	Metadata        map[string]any
	Embedding       []float64
	EmbeddingScore  float64
	KeywordScore    float64
	FilenameScore   float64
	RecencyScore    float64
	ImportanceScore float64
	CombinedScore   float64
	Explain         *SearchExplanation
}

Result represents a scored item.

RecencyScore and ImportanceScore are caller-supplied, already-normalized 0..1 values. Unlike EmbeddingScore/KeywordScore/FilenameScore they are NOT corpus min-max calibrated by Rerank: importance is an absolute salience tier and recency is an absolute time-decay, so corpus-relative rescaling would distort their meaning. Map your own importance tier (e.g. 1..5) or timestamp age (see RecencyFromAge) into 0..1 before assigning. Explain is ephemeral facade output and is nil unless reliquary.WithExplain was requested.

func Diversify

func Diversify(results []*Result, k int, lambda float64) []*Result

Diversify applies MMR to ranked retrieval results and returns the matching result pointers in diversified order.

func ResultsFromDocuments

func ResultsFromDocuments(docs []document.Document, strategy chunking.Strategy, size, overlap int) ([]*Result, error)

ResultsFromDocuments chunks documents into retrieval results using stable documentID#chunkID identifiers. It is the small adapter most callers otherwise hand-write before embedding and reranking.

type Run

type Run struct {
	ID      string
	Queries []RunQuery
}

Run is a captured retrieval run to evaluate against a Fixture.

type RunQuery

type RunQuery struct {
	ID      string
	Results []RankedResult
	Stages  StageResults
}

RunQuery contains the primary ranked results and optional stage outputs for one fixture query.

type ScoreBand

type ScoreBand string
const (
	BandWeak   ScoreBand = "weak"
	BandMedium ScoreBand = "medium"
	BandStrong ScoreBand = "strong"
)

func Band

func Band(score float64) ScoreBand

type ScoreComponents

type ScoreComponents struct {
	Semantic float64
	Keyword  float64
	Filename float64
	Metadata float64
}

type ScoreReference

type ScoreReference struct {
	Version   int
	CreatedAt time.Time
	Identity  ScoreReferenceIdentity
	Values    []float64
}

ScoreReference stores a sorted production/reference score cohort. Callers can persist this data in their own format and map future raw scores to stable cohort-relative percentiles with Percentile.

func FitScoreReference

func FitScoreReference(values []float64, identity ScoreReferenceIdentity) (ScoreReference, error)

FitScoreReference cleans and sorts raw reference scores. It rejects cohorts smaller than MinScoreReferenceSamples after dropping NaN and infinite values.

func (ScoreReference) Percentile

func (reference ScoreReference) Percentile(score float64) float64

Percentile maps a raw score to a stable 0..1 cohort-relative percentile. The minimum reference score maps to 0 and the maximum maps to 1.

func (ScoreReference) Validate

func (reference ScoreReference) Validate(expected ScoreReferenceIdentity) error

Validate returns an actionable error when the reference identity does not match the expected scoring/model/config identity.

type ScoreReferenceIdentity

type ScoreReferenceIdentity struct {
	ScoreVersion string
	ModelID      string
	SchemaHash   string
	ConfigHash   string
}

ScoreReferenceIdentity describes scoring inputs that invalidate a reference distribution when they change. Zero fields are ignored by Validate.

type ScoreSignals

type ScoreSignals struct {
	Embedding  float64
	Keyword    float64
	Filename   float64
	Recency    float64
	Importance float64
}

ScoreSignals groups retrieval signal values.

type ScoreTrace

type ScoreTrace struct {
	ID              string
	QueryTokenCount int
	AdaptiveWeights bool
	Present         SignalPresence
	Weights         Weights
	Raw             ScoreSignals
	Calibrated      ScoreSignals
	Contributions   ScoreSignals
	CombinedScore   float64
}

ScoreTrace explains how a result's CombinedScore was produced.

Raw contains pre-calibration text/vector scores plus caller-supplied salience scores. Calibrated contains the values actually multiplied by Weights. Contributions is Calibrated multiplied by Weights per signal.

type Scorer

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

Scorer computes hybrid relevance scores.

func NewScorer

func NewScorer(weights Weights) *Scorer

NewScorer constructs a Scorer. When weights use the default text-signal mix, Rerank adapts Embedding/Keyword/Filename weights by query token length; explicit custom text weights are honored as-is.

func NewScorerOpts

func NewScorerOpts(opts ...WeightOption) *Scorer

NewScorerOpts builds a Scorer from DefaultWeights plus the given overrides. It is the fluent alternative to constructing a Weights struct and calling NewScorer.

func NewScorerWithOptions

func NewScorerWithOptions(weights Weights, adaptiveWeights bool) *Scorer

NewScorerWithOptions constructs a Scorer and lets callers disable adaptive weighting even when using DefaultWeights.

func (*Scorer) Rerank

func (s *Scorer) Rerank(queryEmbedding []float64, queryText string, results []*Result) []*Result

Rerank scores and sorts results by combined score (descending).

Example
package main

import (
	"fmt"

	"github.com/dotcommander/reliquary/retrieval"
)

func main() {
	scorer := retrieval.NewScorer(retrieval.DefaultWeights())

	// Example data (embeddings must match dimensional lengths)
	queryEmb := []float64{0.1, 0.2, 0.3}
	results := []*retrieval.Result{
		{
			ID:        "doc1",
			Content:   "machine learning algorithms and modeling",
			Filename:  "machine-learning.md",
			Embedding: []float64{0.12, 0.18, 0.31},
		},
		{
			ID:        "doc2",
			Content:   "italian pizza baking recipe",
			Filename:  "cooking.md",
			Embedding: []float64{0.85, 0.05, 0.10},
		},
	}

	ranked := scorer.Rerank(queryEmb, "machine learning", results)

	for _, r := range ranked {
		fmt.Printf("- %s: Score %.4f (Embedding: %.4f, Keyword: %.4f)\n", r.ID, r.CombinedScore, r.EmbeddingScore, r.KeywordScore)
	}
}
Output:
- doc1: Score 1.0000 (Embedding: 1.0000, Keyword: 1.0000)
- doc2: Score 0.0000 (Embedding: 0.0000, Keyword: 0.0000)

func (*Scorer) RerankEmbedding

func (s *Scorer) RerankEmbedding(queryEmbedding embedding.Vector, queryText string, results []*Result) []*Result

RerankEmbedding scores results with an embedding.Vector query.

func (*Scorer) RerankWithReference

func (s *Scorer) RerankWithReference(queryEmbedding []float64, queryText string, results []*Result, reference ScoreReference) []*Result

RerankWithReference scores and sorts results, then maps each CombinedScore to its score-reference percentile. The caller should Validate the reference identity before applying it.

func (*Scorer) RerankWithTrace

func (s *Scorer) RerankWithTrace(queryEmbedding []float64, queryText string, results []*Result) ([]*Result, []ScoreTrace)

RerankWithTrace scores and sorts results, returning one trace per ranked result in the same order as the returned result slice.

func (*Scorer) Score

func (s *Scorer) Score(queryEmbedding []float64, queryText string, result *Result) float64

Score computes the combined score from raw (uncalibrated) component scores. The returned CombinedScore must NOT be compared against scores produced by Rerank, which applies corpus-relative min-max calibration before scoring.

type SearchExplanation added in v0.11.0

type SearchExplanation struct {
	Hybrid          ScoreTrace
	HybridRank      int
	HybridScoreUsed bool
	RRF             *RRFExplanation
	Reranker        *RerankerExplanation
	MMR             *MMRExplanation
	FinalRank       int
}

SearchExplanation describes how a retained search candidate moved through Reliquary's ranking stages. It is populated only for searches using reliquary.WithExplain and is not persistent index data.

type SegmentMetrics

type SegmentMetrics struct {
	Segment       string
	Metrics       Metrics
	RelevantCount int
	ResultCount   int
	HitCount      int
}

SegmentMetrics summarizes retrieval quality for one segment. RelevantCount counts relevant documents assigned to the segment, ResultCount counts top-k results assigned to the segment, and HitCount counts top-k results that are relevant within the segment.

func EvaluateSegments

func EvaluateSegments(query EvalQuery, results []RankedResult, k int, segmenter Segmenter) []SegmentMetrics

EvaluateSegments evaluates one query by caller-provided document segments. It returns segments in deterministic lexical order. Segment metrics are computed by filtering the query relevance set and top-k result list to each segment, then applying Evaluate with the same k.

type Segmenter

type Segmenter func(docID string) string

Segmenter maps a document ID to a caller-owned evaluation segment. Returning an empty string excludes the document from segment summaries.

type SignalPresence

type SignalPresence struct {
	Embedding  bool
	Keyword    bool
	Filename   bool
	Recency    bool
	Importance bool
}

SignalPresence reports which signals had usable inputs for a scored result.

type SourceReport

type SourceReport struct {
	Source          CandidateSource
	Results         []RankedResult
	CandidateCount  int
	HitCount        int
	CandidateRecall float64
	Metrics         Metrics
}

SourceReport captures ranked output and metrics for one candidate source.

func EvaluateSource

func EvaluateSource(query EvalQuery, report SourceReport, k int) SourceReport

EvaluateSource fills metrics for one candidate source report.

type StageBudget

type StageBudget struct {
	Stage string
	Limit int
}

StageBudget describes a limit for a named retrieval stage.

type StageResults

type StageResults = LayeredResults

StageResults aliases the existing layered retrieval stage shape.

type ThresholdFailure

type ThresholdFailure struct {
	Metric string
	Got    float64
	Want   float64
}

ThresholdFailure reports one aggregate metric below its configured floor.

func CheckThresholds

func CheckThresholds(report Report, thresholds ReportThresholds) []ThresholdFailure

CheckThresholds compares aggregate report metrics to configured floors. The returned failures are ordered by stable metric name order.

type TuneCandidate

type TuneCandidate struct {
	ID        string
	Signals   ScoreSignals
	Embedding []float64
	Topic     string
}

TuneCandidate is a precomputed candidate row for retrieval tuning. Signals are already normalized into caller-owned comparable spaces.

type TuneCase

type TuneCase struct {
	Query      EvalQuery
	Candidates []TuneCandidate
}

TuneCase is one labeled retrieval query and its candidate set.

type TuneConfig

type TuneConfig struct {
	K           int
	Weights     []Weights
	MMRLambdas  []float64
	Constraints TuneConstraints
}

TuneConfig configures deterministic grid search over weights and optional MMR lambdas. Empty MMRLambdas evaluates plain weighted ranking only.

type TuneConstraints

type TuneConstraints struct {
	MinRecallAtK       float64
	MinNDCGAtK         float64
	MinUniqueTopicsAtK int
}

TuneConstraints reject grid configurations that fail required floor metrics.

type TuneReport

type TuneReport struct {
	Results []TuneResult
	Best    TuneResult
	HasBest bool
}

TuneReport contains all grid results plus the best non-rejected result.

func TuneWeights

func TuneWeights(cases []TuneCase, config TuneConfig) TuneReport

TuneWeights evaluates each weight/lambda configuration, rejects configs below constraints, and selects the best remaining result by deterministic tie-breaks.

type TuneResult

type TuneResult struct {
	Weights      Weights
	MMRLambda    float64
	UsedMMR      bool
	Metrics      Metrics
	QueryCount   int
	Rejected     bool
	RejectReason string
}

TuneResult reports one grid configuration's aggregate metrics and rejection state.

type WeightOption

type WeightOption func(*Weights)

WeightOption adjusts a Weights value for NewScorerOpts.

func Embedding

func Embedding(v float64) WeightOption

Embedding sets the embedding-similarity weight.

func Filename

func Filename(v float64) WeightOption

Filename sets the filename-overlap weight.

func Importance

func Importance(v float64) WeightOption

Importance sets the importance-salience weight.

func Keyword

func Keyword(v float64) WeightOption

Keyword sets the keyword-overlap weight.

func Recency

func Recency(v float64) WeightOption

Recency sets the recency-salience weight.

type Weights

type Weights struct {
	Embedding  float64
	Keyword    float64
	Filename   float64
	Recency    float64
	Importance float64
}

Weights configures relative importance of scoring signals.

Recency and Importance are optional salience axes orthogonal to textual similarity. They default to 0 (DefaultWeights/AdaptiveWeights leave them unset), so callers that supply only Embedding/Keyword/Filename signals produce exactly the same CombinedScore as before these fields existed.

func AdaptiveWeights

func AdaptiveWeights(queryTokenCount int) Weights

AdaptiveWeights computes weights by query token count.

func DefaultWeights

func DefaultWeights() Weights

DefaultWeights provides sensible defaults for file organization.

Jump to

Keyboard shortcuts

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