rag

package module
v0.59.0 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package rag provides small interfaces and combinators for Retrieval-Augmented Generation.

The root package owns queries, candidates, citations, generation input, stage contracts (Transformer, Expander, Retriever, Refiner, and Augmenter), and deterministic retrieval composition. It depends on document values rather than model, storage, or tool protocols. Adapters in this module build on the same contracts:

Composition is explicit. Wrap a retriever with the stages you need:

r, err := rag.WithTransformers(base, rewrite, translate)
r, err = rag.WithExpander(rag.ExpansionConfig{Retriever: r, Expander: multiQuery})
top, err := rag.TopK(8)
r, err = rag.WithRefiners(r, top)
docs, err := r.Retrieve(ctx, q)

Function adapters such as RetrieverFunc forward calls without adding policy. A composed retriever validates its query at entry and each external stage's output before the next stage consumes it; built-in stages also validate their own inputs so they can be used outside a composition.

Parallel retriever fan-out

ReciprocalRankFusion combines independent rankings without comparing their raw scores, and WithExpander applies the same fusion to expanded queries:

combined, err := rag.ReciprocalRankFusion(rag.FusionRetrieverConfig{}, vectorR1, vectorR2)

TopK only sorts and caps a comparable result. Dedup keeps the best candidate for each known document identity; apply it before TopK when a single source can return duplicate identities. Fusion already merges them.

Routing and agentic retrieval

There is no router stage. Route a query by implementing Retriever and switching on a value stored under a ValueKey:

func (r *routingRetriever) Retrieve(ctx context.Context, q rag.Query) (rag.Candidates, error) {
    route, _, err := q.Value(r.routeKey)
    if err != nil {
        return nil, err
    }
    if route == "logs" {
        return r.logs.Retrieve(ctx, q)
    }
    return r.docs.Retrieve(ctx, q)
}

github.com/Tangerg/scope/rag/tool.NewRetrieval adapts any composed Retriever to the ordinary core tool contract, so agents need no RAG-specific API.

Index

Examples

Constants

View Source
const DefaultMaxConcurrentRetrievals = 4
View Source
const DefaultReciprocalRankConstant = 60

DefaultReciprocalRankConstant is the conventional RRF smoothing constant.

Variables

View Source
var (
	// ErrInvalidAugmentation identifies generation input or citation numbering
	// that cannot be represented portably.
	ErrInvalidAugmentation = errors.New("rag: invalid augmentation")
	ErrNilAugmenter        = errors.New("rag: augmenter must not be nil")
)
View Source
var (
	// ErrInvalidQuery identifies invalid text or typed values.
	ErrInvalidQuery = errors.New("rag: invalid query")
	ErrNilRetriever = errors.New("rag: retriever must not be nil")
	// ErrInvalidQueryValueKey identifies a zero or malformed typed slot.
	ErrInvalidQueryValueKey = errors.New("rag: invalid query value key")
	ErrNilQueryValue        = errors.New("rag: query value must not be nil")
)
View Source
var (
	// ErrInvalidCandidate identifies an invalid document or non-finite score.
	ErrInvalidCandidate = errors.New("rag: invalid retrieval candidate")
	// ErrInvalidReranking identifies invalid model rankings or candidate projections.
	ErrInvalidReranking = errors.New("rag: invalid reranking")
	ErrNilTransformer   = errors.New("rag: transformer must not be nil")
	ErrNilExpander      = errors.New("rag: expander must not be nil")
	ErrNilRefiner       = errors.New("rag: refiner must not be nil")
	ErrEmptyExpansion   = errors.New("rag: expander returned no queries")
	// ErrInvalidExpansion identifies invalid or duplicate expanded queries.
	ErrInvalidExpansion = errors.New("rag: invalid query expansion")
)
View Source
var ErrInvalidRankConstant = errors.New("rag: reciprocal-rank constant must not be negative")
View Source
var ErrInvalidRetrievalConcurrency = errors.New("rag: retrieval concurrency must not be negative")
View Source
var ErrUnidentifiedCitation = errors.New("rag: citation requires a document ID")

ErrUnidentifiedCitation means the selected document has no stable document ID.

View Source
var ErrUnknownCitation = errors.New("rag: unknown citation marker")

ErrUnknownCitation means the marker is malformed or is outside this prompt's selection.

Functions

func CitationMarker added in v0.45.0

func CitationMarker(index int) string

CitationMarker is the one-based prompt marker of the citation at index.

Types

type Augmentation

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

Augmentation is immutable generation input that can be copied by assignment. It keeps final text and citations separate from Query's retrieval-scoped values.

func NewAugmentation

func NewAugmentation(text string) (Augmentation, error)

NewAugmentation preserves non-blank UTF-8 generation text exactly.

func (Augmentation) Citations

func (a Augmentation) Citations() Citations

Citations returns the immutable selection used for this prompt.

func (Augmentation) Text

func (a Augmentation) Text() string

func (Augmentation) Validate

func (a Augmentation) Validate() error

type Augmenter

type Augmenter interface {
	// Augment creates the complete generation input from one query and its
	// ordered candidates. It must not mutate either input, must preserve any
	// citation-to-candidate relationship it emits, and must honor ctx.
	Augment(ctx context.Context, query Query, candidates Candidates) (Augmentation, error)
}

type AugmenterFunc

type AugmenterFunc func(context.Context, Query, Candidates) (Augmentation, error)

func IdentityAugmenter

func IdentityAugmenter() AugmenterFunc

IdentityAugmenter preserves the query text when retrieval evidence is needed without prompt augmentation.

func (AugmenterFunc) Augment

func (a AugmenterFunc) Augment(ctx context.Context, query Query, candidates Candidates) (Augmentation, error)

type Candidate

type Candidate struct {
	Document *document.Document `json:"document"`
	Score    Score              `json:"score"`
}

Candidate relates a document to the retrieval operation that produced it. Score is query-specific and therefore does not belong on document.Document.

func (Candidate) Clone

func (c Candidate) Clone() Candidate

Clone returns an independently owned candidate and document.

func (Candidate) Validate

func (c Candidate) Validate() error

type Candidates

type Candidates []Candidate

Candidates is an ordered retrieval result. Its methods never mutate the receiver, preserving declaration and retrieval order where scores tie.

func (Candidates) Clone

func (c Candidates) Clone() Candidates

func (Candidates) Validate

func (c Candidates) Validate() error

type Citations

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

Citations is the immutable selection supplied to one prompt. The position owns its marker; neither model output nor changes to a returned document can create or renumber an entry. Its zero value is an empty selection.

func (Citations) Candidates added in v0.59.0

func (c Citations) Candidates() Candidates

Candidates returns an owned snapshot of admitted evidence in marker order. This also exposes temporary material without claiming that it is reproducible.

func (Citations) Len added in v0.59.0

func (c Citations) Len() int

Len reports how many prompt markers can resolve to admitted material.

func (Citations) MarshalJSON added in v0.59.0

func (c Citations) MarshalJSON() ([]byte, error)

MarshalJSON exposes the ordered admitted entries to host clients. Position, rather than a second stored field, determines each entry's marker.

func (Citations) Resolve added in v0.59.0

func (c Citations) Resolve(marker string) (*document.Document, error)

Resolve returns the original, detached document for an exact canonical prompt marker such as "[1]". Its Provenance owns the source, revision and known location. Anonymous material returns document.ErrUnversionedSource. Resolution neither fetches a source nor establishes that it supports a generated claim.

type Deduplicator added in v0.57.0

type Deduplicator struct{}

Deduplicator is a stateless refiner; its zero value is ready to use.

func Dedup

func Dedup() Deduplicator

Dedup returns a Refiner that keeps the highest-scoring candidate for each nonempty document ID within the same source revision and location. For unversioned local data, the caller owns the ID namespace. Identities retain first-seen order, and equal scores retain the first candidate. Documents without an ID remain distinct because the framework cannot prove they are duplicates.

func (Deduplicator) Refine added in v0.57.0

func (d Deduplicator) Refine(ctx context.Context, query Query, candidates Candidates) (Candidates, error)

type Evidence added in v0.59.0

type Evidence []Excerpt

Evidence is an ordered selection of complete excerpts. The same sequence renders the prompt block and binds its marker positions to original documents.

func (Evidence) Augment added in v0.59.0

func (e Evidence) Augment(prefix, suffix string) (Augmentation, error)

Augment inserts the selected evidence block between prefix and suffix and freezes exactly those citations. There is no separate marker-table input.

func (Evidence) Render added in v0.59.0

func (e Evidence) Render() (string, error)

Render returns the JSON block that Augment inserts verbatim. A host can pass it to its token counter when deciding whether the next whole excerpt fits.

type Excerpt added in v0.59.0

type Excerpt struct {
	Candidate Candidate
	Content   string
}

Excerpt pairs an original retrieval candidate with the exact text rendered from it. Content may be a host-formatted projection rather than a byte range in the original. The candidate's document remains the provenance owner.

type Expander

type Expander interface {
	// Expand returns a non-empty, ordered set of valid alternative or decomposed
	// queries with distinct Text values. Per-query values do not create another
	// expansion identity. It must not mutate query or expose reusable backing storage;
	// ordering is semantic because downstream fusion uses it for stable ties.
	Expand(ctx context.Context, query Query) ([]Query, error)
}

type ExpanderFunc

type ExpanderFunc func(context.Context, Query) ([]Query, error)

func (ExpanderFunc) Expand

func (e ExpanderFunc) Expand(ctx context.Context, query Query) ([]Query, error)

type ExpansionConfig added in v0.18.0

type ExpansionConfig struct {
	Retriever Retriever
	Expander  Expander
	Fusion    ReciprocalRankFusionConfig
	// MaxConcurrentRetrievals bounds expanded-query retrievals per invocation.
	// Zero uses DefaultMaxConcurrentRetrievals; one is sequential.
	MaxConcurrentRetrievals int
}

type FusionRetriever added in v0.57.0

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

FusionRetriever owns an admitted, detached set of rank-fusion inputs. Construct it with ReciprocalRankFusion; its zero value is invalid.

func ReciprocalRankFusion

func ReciprocalRankFusion(config FusionRetrieverConfig, retrievers ...Retriever) (*FusionRetriever, error)

ReciprocalRankFusion returns a retriever that concurrently executes each input retriever and fuses their ordered results using reciprocal-rank fusion. Raw candidate scores are deliberately ignored because independent retrievers commonly use incomparable score scales. Every retriever must succeed; the first failure cancels the remaining retrievals and is returned without partial results.

func (*FusionRetriever) Retrieve added in v0.57.0

func (f *FusionRetriever) Retrieve(ctx context.Context, query Query) (Candidates, error)

type FusionRetrieverConfig added in v0.19.0

type FusionRetrieverConfig struct {
	Fusion ReciprocalRankFusionConfig
	// MaxConcurrentRetrievals bounds active child calls independently per
	// invocation. Zero uses DefaultMaxConcurrentRetrievals; one is sequential.
	MaxConcurrentRetrievals int
}

type PipelineRetriever added in v0.57.0

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

PipelineRetriever owns the public entry boundary. Its pipeline checks each external stage result before passing it onward, so returning that same result does not require another candidate traversal. Construct it with WithTransformers, WithExpander, or WithRefiners; its zero value is invalid.

func WithExpander

func WithExpander(config ExpansionConfig) (*PipelineRetriever, error)

WithExpander returns a Retriever that retrieves each expanded query under the configured concurrency bound and combines rankings with reciprocal-rank fusion. Every query must succeed; the first failure cancels the remaining retrievals and is returned. Raw scores never cross query boundaries.

func WithRefiners

func WithRefiners(next Retriever, refiners ...Refiner) (*PipelineRetriever, error)

WithRefiners returns a Retriever that calls next and then applies refiners to the returned documents in order.

func WithTransformers

func WithTransformers(next Retriever, transformers ...Transformer) (*PipelineRetriever, error)

WithTransformers returns a Retriever that rewrites the query through transformers before calling next.

func (*PipelineRetriever) Retrieve added in v0.57.0

func (p *PipelineRetriever) Retrieve(ctx context.Context, query Query) (Candidates, error)

type Query

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

Query is a persistent retrieval query: Text is required, and WithText or WithValue returns a new envelope without changing existing queries' slots. Referenced values remain caller-owned and must be treated as read-only when the same query is used by parallel retrieval stages.

func NewQuery

func NewQuery(text string) (Query, error)

NewQuery trims surrounding whitespace and requires valid UTF-8 text.

func (Query) Text

func (q Query) Text() string

func (Query) Validate

func (q Query) Validate() error

func (Query) Value

func (q Query) Value[T any](key ValueKey[T]) (T, bool, error)

Value returns the value stored under key. Missing values are distinct from invalid keys.

func (Query) WithText

func (q Query) WithText(text string) (Query, error)

func (Query) WithValue

func (q Query) WithValue[T any](key ValueKey[T], value T) (Query, error)
Example
package main

import (
	"fmt"

	"github.com/Tangerg/scope/rag"
)

func main() {
	query, err := rag.NewQuery("how does retrieval work?")
	if err != nil {
		panic(err)
	}
	tenant, err := rag.NewValueKey[string]("tenant")
	if err != nil {
		panic(err)
	}
	query, err = query.WithValue(tenant, "docs")
	if err != nil {
		panic(err)
	}
	value, found, err := query.Value(tenant)
	if err != nil {
		panic(err)
	}

	fmt.Println(query.Text(), value, found)
}
Output:
how does retrieval work? docs true

type ReciprocalRankFusionConfig

type ReciprocalRankFusionConfig struct {
	RankConstant int
}

ReciprocalRankFusionConfig sets the constant added to each one-based rank before reciprocal weighting; zero uses DefaultReciprocalRankConstant.

type Refiner

type Refiner interface {
	// Refine returns a valid, independently owned subset or reordering of
	// candidates for query. It must not mutate either input; a successful empty
	// result explicitly means no evidence survived refinement.
	Refine(ctx context.Context, query Query, candidates Candidates) (Candidates, error)
}

type RefinerFunc

type RefinerFunc func(context.Context, Query, Candidates) (Candidates, error)

func (RefinerFunc) Refine

func (r RefinerFunc) Refine(ctx context.Context, query Query, candidates Candidates) (Candidates, error)

type Retriever

type Retriever interface {
	// Retrieve returns independently owned, valid candidates in the source's
	// relevance order. Scores remain query-relative; the implementation must
	// honor ctx and must not mutate query.
	Retrieve(ctx context.Context, query Query) (Candidates, error)
}

type RetrieverFunc

type RetrieverFunc func(context.Context, Query) (Candidates, error)

func (RetrieverFunc) Retrieve

func (r RetrieverFunc) Retrieve(ctx context.Context, query Query) (Candidates, error)

type Score added in v0.13.0

type Score float64

Score is a finite, query-relative ordering value. Scores are comparable only within the retrieval or fusion result that produced them.

func (Score) Float64 added in v0.13.0

func (s Score) Float64() float64

func (Score) Validate added in v0.13.0

func (s Score) Validate() error

type TopKRefiner added in v0.57.0

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

TopKRefiner retains the bound admitted by TopK. Its zero value is invalid.

func TopK

func TopK(topK int) (*TopKRefiner, error)

TopK returns a Refiner that stably sorts candidates by descending score and returns at most topK candidates. topK must be positive. Use Dedup before TopK when unique document identities are required.

Example
package main

import (
	"context"
	"fmt"

	"github.com/Tangerg/scope/core/document"
	"github.com/Tangerg/scope/rag"
)

func main() {
	first, err := document.NewDocument("first", nil)
	if err != nil {
		panic(err)
	}
	second, err := document.NewDocument("second", nil)
	if err != nil {
		panic(err)
	}
	query, err := rag.NewQuery("rank the evidence")
	if err != nil {
		panic(err)
	}
	refiner, err := rag.TopK(1)
	if err != nil {
		panic(err)
	}
	result, err := refiner.Refine(context.Background(), query, rag.Candidates{
		{Document: first, Score: 0.25},
		{Document: second, Score: 0.75},
	})
	if err != nil {
		panic(err)
	}

	fmt.Println(result[0].Document.Text)
}
Output:
second

func (*TopKRefiner) Refine added in v0.57.0

func (t *TopKRefiner) Refine(ctx context.Context, query Query, candidates Candidates) (Candidates, error)

type Transformer

type Transformer interface {
	// Transform returns one valid query that preserves the caller's retrieval
	// intent while changing its representation. It must not mutate query, must
	// honor ctx, and transfers ownership of the returned value to the caller.
	Transform(ctx context.Context, query Query) (Query, error)
}

type TransformerFunc

type TransformerFunc func(context.Context, Query) (Query, error)

func (TransformerFunc) Transform

func (t TransformerFunc) Transform(ctx context.Context, query Query) (Query, error)

type ValueKey

type ValueKey[T any] struct {
	// contains filtered or unexported fields
}

ValueKey is a typed slot in a Query. Define a key once and share that key with the code that writes and reads the slot. Each key instance has its own identity; the name is diagnostic only and never acts as a global namespace.

The zero value and ValueKey[any] are invalid. Create keys with NewValueKey and retain the returned value because equal names do not share identity.

func NewValueKey

func NewValueKey[T any](name string) (ValueKey[T], error)

func (ValueKey[T]) Name

func (v ValueKey[T]) Name() string

Directories

Path Synopsis
Package chat composes retrieval with chat models through the rag domain contracts.
Package chat composes retrieval with chat models through the rag domain contracts.
Package index prepares and embeds source-bound documents before sending precomputed records to a native index.
Package index prepares and embeds source-bound documents before sending precomputed records to a native index.
Package rerank adapts dedicated rerank models to the rag Refiner contract.
Package rerank adapts dedicated rerank models to the rag Refiner contract.
Package tool exposes rag retrieval through the ordinary core Tool contract.
Package tool exposes rag retrieval through the ordinary core Tool contract.
Package vector adapts core vector search to the rag Retriever contract.
Package vector adapts core vector search to the rag Retriever contract.

Jump to

Keyboard shortcuts

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