Documentation
¶
Overview ¶
Package rag provides small interfaces and combinators for Retrieval-Augmented Generation.
Quick start:
q, _ := rag.NewQuery("what is GOAP?")
docs, err := retriever.Retrieve(ctx, q)
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 remain in this module and depend on these same domain contracts:
- github.com/Tangerg/scope/rag/chat owns model-backed query transforms, expansion, reranking, contextual prompts, and explicit chat request preparation.
- github.com/Tangerg/scope/rag/vectorstore adapts vector search to retrieval.
- github.com/Tangerg/scope/rag/rerank adapts a dedicated rerank model to refinement.
- github.com/Tangerg/scope/rag/tool exposes retrieval as a model-visible tool.
DocumentFormatter and TextFormatter keep evidence rendering consistent across adapters. Domain values own validation; adapters own external calls and check results before passing them across the next boundary.
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 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 public inputs so they can be used directly outside a composition.
IdentityAugmenter preserves the query when contextual augmentation is deliberately empty. Other optional stages are omitted from composition.
Parallel retriever fan-out ¶
ReciprocalRankFusion combines independent rankings without comparing their raw scores. WithExpander applies the same fusion to independent queries. Both configure retrieval concurrency independently from ReciprocalRankFusionConfig.
top, err := rag.TopK(topK)
combined, err := rag.ReciprocalRankFusion(rag.FusionRetrieverConfig{}, vectorR1, vectorR2)
r, err := rag.WithRefiners(combined, top)
TopK only sorts and caps a comparable result. Dedup independently keeps the best candidate for each known document identity. Apply Dedup before TopK when a source can return duplicate identities; RRF already fuses them.
Agentic retrieval ¶
github.com/Tangerg/scope/rag/tool.NewRetrieval adapts any composed Retriever to the ordinary core tool contract. Agent runtimes can advertise it immediately or keep it in their deferred tool set without introducing an agent-specific RAG API.
Per-query retriever routing ¶
Likewise, there is no "QueryRouter" stage. To route a query to a subset of retrievers (e.g. by topic, language, or metadata), wrap your retrievers in a custom Retriever that switches on the query internally:
type routingRetriever struct {
routeKey rag.ValueKey[string]
docsR, logsR rag.Retriever
}
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.logsR.Retrieve(ctx, q)
}
return r.docsR.Retrieve(ctx, q)
}
Create routeKey once with NewValueKey and retain it in the retriever. Callers stay oblivious; routing logic lives at the retriever boundary.
Index ¶
- Constants
- Variables
- type Augmentation
- type Augmenter
- type AugmenterFunc
- type Candidate
- type Candidates
- type Citation
- type Citations
- type DocumentFormatter
- type DocumentFormatterFunc
- type Expander
- type ExpanderFunc
- type ExpansionConfig
- type FusionRetrieverConfig
- type Query
- type ReciprocalRankFusionConfig
- type Refiner
- type RefinerFunc
- type Retriever
- func ReciprocalRankFusion(config FusionRetrieverConfig, retrievers ...Retriever) (Retriever, error)
- func WithExpander(config ExpansionConfig) (Retriever, error)
- func WithRefiners(next Retriever, refiners ...Refiner) (Retriever, error)
- func WithTransformers(next Retriever, transformers ...Transformer) (Retriever, error)
- type RetrieverFunc
- type Score
- type TextFormatter
- type Transformer
- type TransformerFunc
- type ValueKey
Examples ¶
Constants ¶
const DefaultMaxConcurrentRetrievals = 4
DefaultMaxConcurrentRetrievals bounds fan-out when no limit is specified.
const DefaultReciprocalRankConstant = 60
DefaultReciprocalRankConstant is the conventional RRF smoothing constant.
Variables ¶
var ( // ErrInvalidAugmentation identifies generation input or citation numbering // that cannot be represented portably. ErrInvalidAugmentation = errors.New("rag: invalid augmentation") // ErrNilAugmenter rejects composition without explicit prompt policy. ErrNilAugmenter = errors.New("rag: augmenter must not be nil") )
var ( // ErrInvalidQuery identifies blank text or invalid typed values. ErrInvalidQuery = errors.New("rag: invalid query") // ErrNilRetriever rejects retrieval without an explicit source capability. 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 rejects typed slots whose value is absent. ErrNilQueryValue = errors.New("rag: query value must not be nil") )
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 rejects a missing query transformation stage. ErrNilTransformer = errors.New("rag: transformer must not be nil") // ErrNilExpander rejects a missing query expansion stage. ErrNilExpander = errors.New("rag: expander must not be nil") // ErrNilRefiner rejects a missing candidate refinement stage. ErrNilRefiner = errors.New("rag: refiner must not be nil") // ErrEmptyExpansion prevents an expander from erasing a query. ErrEmptyExpansion = errors.New("rag: expander returned no queries") // ErrInvalidExpansion identifies invalid or duplicate expanded queries. ErrInvalidExpansion = errors.New("rag: invalid query expansion") )
var ErrInvalidRankConstant = errors.New("rag: reciprocal-rank constant must not be negative")
ErrInvalidRankConstant identifies a fusion policy that cannot preserve monotonic rank contribution.
var ErrInvalidRetrievalConcurrency = errors.New("rag: retrieval concurrency must not be negative")
ErrInvalidRetrievalConcurrency rejects a negative retrieval concurrency bound.
var ErrUnsupportedMedia = errors.New("rag: document formatter does not support media")
ErrUnsupportedMedia means a formatter cannot represent document media.
Functions ¶
This section is empty.
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 validates final generation text before citations are attached.
func (Augmentation) Citations ¶
func (a Augmentation) Citations() Citations
Citations returns an independent citation-order snapshot.
func (Augmentation) Text ¶
func (a Augmentation) Text() string
Text returns the final generation input.
func (Augmentation) Validate ¶
func (a Augmentation) Validate() error
func (Augmentation) WithCitations ¶
func (a Augmentation) WithCitations(citations Citations) (Augmentation, error)
WithCitations returns an independent augmentation with citations. Numbers must be consecutive and one-based so prompt markers have one interpretation.
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)
}
Augmenter turns a retrieval query and its candidates into final generation input.
func IdentityAugmenter ¶
func IdentityAugmenter() Augmenter
IdentityAugmenter preserves the query text when retrieval evidence is needed without prompt augmentation.
type AugmenterFunc ¶
type AugmenterFunc func(context.Context, Query, Candidates) (Augmentation, error)
AugmenterFunc adapts a function to Augmenter without another composition API.
func (AugmenterFunc) Augment ¶
func (a AugmenterFunc) Augment(ctx context.Context, query Query, candidates Candidates) (Augmentation, error)
type Candidate ¶
Candidate relates a document to the retrieval operation that produced it. Score is query-specific and therefore does not belong on document.Document.
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
Clone returns an independently owned candidate sequence.
func (Candidates) Validate ¶
func (c Candidates) Validate() error
type Citation ¶
Citation binds a one-based prompt marker to the candidate it identifies.
func NewCitation ¶
NewCitation snapshots a candidate under one positive prompt marker.
type Citations ¶
type Citations []Citation
Citations is an ordered, one-based mapping between prompt markers and retrieval candidates.
type DocumentFormatter ¶
type DocumentFormatter interface {
// Format renders one valid document without mutating or retaining it. The
// returned text is inserted into model context, so implementations must be
// deterministic for the same document and return an error for unsupported
// media rather than silently dropping evidence.
Format(doc *document.Document) (string, error)
}
DocumentFormatter renders one retrieved document for model input.
type DocumentFormatterFunc ¶
DocumentFormatterFunc adapts a pure document projection to DocumentFormatter.
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)
}
Expander turns one query into many — useful for poorly formed inputs (alternative phrasings) or complex problems (decompose into sub-queries).
type ExpanderFunc ¶
ExpanderFunc adapts a function to Expander.
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
}
ExpansionConfig selects the query expansion stage, retrieval source, and rank fusion policy used to combine the independent query results.
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
}
FusionRetrieverConfig selects ranking policy and retrieval scheduling.
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 (Query) Value ¶
Value returns the value stored under key. Missing values are distinct from invalid keys.
func (Query) WithValue ¶
WithValue returns an independent query containing value under key.
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 controls reciprocal-rank weighting. RankConstant is 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)
}
Refiner narrows candidate documents down to what the LLM should see.
func Dedup ¶
func Dedup() Refiner
Dedup returns a Refiner that keeps the highest-scoring candidate for each non-empty document.Document.ID. Document 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 TopK ¶
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
type RefinerFunc ¶
type RefinerFunc func(context.Context, Query, Candidates) (Candidates, error)
RefinerFunc adapts a function to Refiner.
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)
}
Retriever pulls candidate documents from a knowledge source.
func ReciprocalRankFusion ¶
func ReciprocalRankFusion(config FusionRetrieverConfig, retrievers ...Retriever) (Retriever, 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; failures are reported in declaration order without partial results.
func WithExpander ¶
func WithExpander(config ExpansionConfig) (Retriever, 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; raw scores never cross query boundaries.
func WithRefiners ¶
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) (Retriever, error)
WithTransformers returns a Retriever that rewrites the query through transformers before calling next.
type RetrieverFunc ¶
type RetrieverFunc func(context.Context, Query) (Candidates, error)
RetrieverFunc adapts a function to Retriever. Like the other stage function adapters, it forwards directly; the function must satisfy the stage contract. Combinators validate results received from external stages.
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.
type TextFormatter ¶ added in v0.18.0
type TextFormatter struct{}
TextFormatter renders document text and rejects media that text alone cannot represent. Its zero value is ready to use.
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)
}
Transformer rewrites a query to be more retrieval-friendly — translation, compression, ambiguity resolution, vocabulary normalization.
type TransformerFunc ¶
TransformerFunc adapts a function to Transformer.
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 ¶
NewValueKey creates one typed identity that callers retain across query producers and consumers.
Source Files
¶
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 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 vectorstore adapts core vector search to the rag Retriever contract.
|
Package vectorstore adapts core vector search to the rag Retriever contract. |