Documentation
¶
Overview ¶
Package feedback provides relevance feedback and query expansion for improving retrieval quality. It implements the classic Rocchio algorithm in both vector and lexical forms, and an iterative "expand-and-retrieve" loop.
All types are thread-safe and dependency-free. Feedback can be accumulated in a Collector and serialized to chunk metadata for future training.
Index ¶
- Variables
- func BoostRelevant(results []index.SearchResult, relevant []string) []index.SearchResult
- func CosineSimilarity(a, b []float32) float64
- func L2Normalize(v []float32) []float32
- func MeanVectors(vectors [][]float32) []float32
- func Rocchio(query []float32, relevant, irrelevant [][]float32, p RocchioParams) []float32
- func RocchioTerms(query string, relevantTexts, irrelevantTexts []string, p TermRocchioParams) (string, map[string]float64)
- type ChunkGetter
- type Collector
- type Feedback
- type Label
- type RelevanceFeedback
- func (r *RelevanceFeedback) AdjustText(query string, relevantTexts, irrelevantTexts []string) string
- func (r *RelevanceFeedback) AdjustVector(query []float32, relevant, irrelevant [][]float32) []float32
- func (r *RelevanceFeedback) ExpandAndRetrieve(ctx context.Context, query string, fb *Feedback, topK int) ([]index.SearchResult, []float32, error)
- type RocchioParams
- type TermRocchioParams
- type VectorSearcher
Constants ¶
This section is empty.
Variables ¶
var ErrNoFeedback = errors.New("feedback: no usable relevance feedback")
ErrNoFeedback is returned when a feedback round contains no usable relevance judgments or the referenced chunks cannot be resolved to embeddings.
Functions ¶
func BoostRelevant ¶
func BoostRelevant(results []index.SearchResult, relevant []string) []index.SearchResult
BoostRelevant stably partitions results so those whose chunk ID is in relevant come first, preserving the original order within each group.
func CosineSimilarity ¶
CosineSimilarity returns the cosine similarity between two vectors. The shorter vector is zero-padded. Returns 0 for any zero vector.
func L2Normalize ¶
L2Normalize returns a unit-length copy of v. A zero vector is returned as-is.
func MeanVectors ¶
MeanVectors returns the element-wise mean of a set of vectors. Vectors of differing lengths are handled using the length of the first vector; shorter vectors contribute zero for their missing dimensions. Empty input returns an empty slice.
func Rocchio ¶
func Rocchio(query []float32, relevant, irrelevant [][]float32, p RocchioParams) []float32
Rocchio applies the Rocchio algorithm in embedding space. It returns a new query vector shifted toward the centroid of relevant embeddings and away from the centroid of not-relevant embeddings.
All vectors are expected to have the same dimension as query. If relevant or irrelevant is empty, that term is simply omitted. If the input query is empty, the dimension is inferred from the feedback vectors; if none are supplied, an empty slice is returned.
func RocchioTerms ¶
func RocchioTerms(query string, relevantTexts, irrelevantTexts []string, p TermRocchioParams) (string, map[string]float64)
RocchioTerms applies the Rocchio algorithm in term space. It returns an expanded query string (top terms by adjusted weight) plus the full term-weight map for inspection.
The adjusted weight of a term t is:
w(t) = freq_query(t) + Beta*meanFreq_relevant(t) - Gamma*meanFreq_irrelevant(t)
Negative weights are clamped to zero and zero-weight terms are dropped.
Types ¶
type ChunkGetter ¶
type ChunkGetter interface {
// GetChunk returns a chunk by its ID.
GetChunk(id string) (*core.Chunk, bool)
}
ChunkGetter returns a stored chunk by ID. It is satisfied by store.Store.
type Collector ¶
type Collector struct {
// contains filtered or unexported fields
}
Collector is a thread-safe in-memory store of feedback rounds. It acts as the "training store" for relevance feedback: accumulate human judgments here, then aggregate them to drive Rocchio expansion or offline model training.
func (*Collector) IrrelevantFor ¶
IrrelevantFor returns the sorted union of not-relevant chunk IDs across all feedback rounds for a query.
func (*Collector) RelevantFor ¶
RelevantFor returns the sorted union of relevant chunk IDs across all feedback rounds for a query.
type Feedback ¶
type Feedback struct {
// ID is a unique identifier for this feedback round.
ID string
// Query is the original query text this feedback applies to.
Query string
// Time is when the feedback was recorded.
Time time.Time
// Comment is an optional free-form annotation from the reviewer.
Comment string
// Labels maps chunk ID to relevance label.
Labels map[string]Label
}
Feedback captures one round of relevance feedback for a query: which retrieved chunks a human judged relevant or not relevant.
func NewFeedback ¶
NewFeedback creates a Feedback with a generated ID, timestamp, and labels. A nil labels map is replaced with an empty one.
func (*Feedback) HasJudgment ¶
HasJudgment reports whether at least one relevant or not-relevant label exists.
func (*Feedback) Irrelevant ¶
Irrelevant returns the chunk IDs labeled as not relevant, sorted.
type RelevanceFeedback ¶
type RelevanceFeedback struct {
// Searcher retrieves chunks by query embedding.
Searcher VectorSearcher
// Getter resolves chunk IDs to chunks (for their embeddings/content).
Getter ChunkGetter
// Embedder embeds query text.
Embedder embedder.Embedder
// Params configures Rocchio (vector form).
Params RocchioParams
// TermParams configures Rocchio (lexical form) for AdjustText.
TermParams TermRocchioParams
// BoostRelevant, when true, moves chunks the user marked relevant to the
// front of the re-ranked results.
BoostRelevant bool
}
RelevanceFeedback adjusts queries based on user relevance feedback using the Rocchio algorithm. It combines a vector search capability (e.g., an index.Index), chunk access (e.g., a store.Store), and an embedder so the full retrieve → feedback → re-rank loop can run.
func NewRelevanceFeedback ¶
func NewRelevanceFeedback(searcher VectorSearcher, getter ChunkGetter, e embedder.Embedder) *RelevanceFeedback
NewRelevanceFeedback creates a RelevanceFeedback with standard Rocchio parameters and relevant-boosting enabled.
func (*RelevanceFeedback) AdjustText ¶
func (r *RelevanceFeedback) AdjustText(query string, relevantTexts, irrelevantTexts []string) string
AdjustText returns a textually expanded query for keyword-based retrieval, using lexical Rocchio over the query and the relevant/not-relevant chunk texts.
func (*RelevanceFeedback) AdjustVector ¶
func (r *RelevanceFeedback) AdjustVector(query []float32, relevant, irrelevant [][]float32) []float32
AdjustVector returns a Rocchio-adjusted query embedding given the original query embedding and the embeddings of the relevant and not-relevant chunks.
func (*RelevanceFeedback) ExpandAndRetrieve ¶
func (r *RelevanceFeedback) ExpandAndRetrieve(ctx context.Context, query string, fb *Feedback, topK int) ([]index.SearchResult, []float32, error)
ExpandAndRetrieve performs one round of iterative relevance feedback:
- embed the query,
- gather the embeddings of the chunks judged relevant / not relevant,
- apply Rocchio to obtain an adjusted query vector,
- re-retrieve with the adjusted vector,
- re-rank so user-marked relevant chunks come first (when BoostRelevant).
It returns the re-ranked results and the adjusted query vector.
type RocchioParams ¶
type RocchioParams struct {
// Alpha is the weight of the original query vector. 0 keeps the query from
// contributing.
Alpha float64
// Beta is the weight of the mean relevant-document vector. 0 disables the
// positive shift.
Beta float64
// Gamma is the weight of the mean not-relevant-document vector (subtracted).
// 0 disables the negative shift.
Gamma float64
// Normalize L2-normalizes the resulting vector so it stays comparable with
// stored embeddings under cosine similarity.
Normalize bool
}
RocchioParams configures the classic Rocchio query expansion algorithm.
Rocchio: Q' = Alpha*Q + Beta*mean(relevant) - Gamma*mean(irrelevant)
Defaults (via DefaultRocchioParams): Alpha=1, Beta=0.5, Gamma=0.3, Normalize=true.
func DefaultRocchioParams ¶
func DefaultRocchioParams() RocchioParams
DefaultRocchioParams returns the standard Rocchio weights.
type TermRocchioParams ¶
type TermRocchioParams struct {
// Beta is the weight of terms from relevant documents.
Beta float64
// Gamma is the weight of terms from not-relevant documents (subtracted).
Gamma float64
// MaxTerms limits how many terms are kept in the expanded query. 0 keeps
// every term with a positive weight.
MaxTerms int
}
TermRocchioParams configures lexical (term-frequency) Rocchio expansion.
func DefaultTermRocchioParams ¶
func DefaultTermRocchioParams() TermRocchioParams
DefaultTermRocchioParams returns standard lexical Rocchio weights.
type VectorSearcher ¶
type VectorSearcher interface {
// Search finds the most similar chunks to the given query embedding.
Search(ctx context.Context, query []float32, opts index.SearchOptions) ([]index.SearchResult, error)
}
VectorSearcher searches a chunk index by embedding vector. It is satisfied by index.Index.