Skip to content

Scoring Function

Every retrieval result in contextdb is ranked by a composite score combining four dimensions.

The formula

score(candidate) =
    w_sim  * cosine_similarity(candidate.vector, query.vector)
  + w_conf * candidate.confidence
  + w_rec  * exp(-alpha * age_hours)
  + w_util * utility_feedback_score

All weights are normalised to sum to 1.0 at query time. You control alpha (decay rate) and the four weights.

Score dimensions

DimensionRangeWhat it measures
Similarity[0, 1]Vector cosine similarity to the query
Confidence[0, 1]How trustworthy the fact is (from source credibility)
Recency[0, 1]Exponential decay from valid_from to now
Utility[0, 1]Past usefulness feedback (agent memory mode)
Preset:
40Similarity
30Confidence
20Recency
10Utility
Go uses garbage collection
0.86
Go GC uses mark-and-sweep
0.79
Python uses ref counting
0.73
Rust has no GC
0.63
Java GC is generational
0.63
Go GC pauses under 1ms
0.55
Similarity Confidence Recency Utility

How the dimensions interact

Each dimension captures something the others miss. Here's how they play out in practice:

These trade-offs are why contextdb lets you tune per query. A chatbot answering "what language does the server use?" needs high similarity weight. A security audit checking "is this claim trustworthy?" needs high confidence weight. An agent deciding "what's still relevant?" needs recency and utility.

Recency decay

Recency uses exponential decay:

recency = exp(-alpha * age_in_hours)

Recency Decay Visualizer

How exponential decay affects facts of different ages. Formula: exp(-alpha * age_hours)

alpha = 0.08  |  half-life: 8.7 hours
User asked about auth module
1h ago
0.923
Sprint planning notes
1d ago
0.147
API redesign discussion
3d ago
0.003
Q1 roadmap priorities
1w ago
0.000
Architecture decision record
1mo ago
0.000
Memory typeAlphaHalf-life
Working999.0~seconds
Episodic0.08~8.7 hours
Semantic0.02~34.7 hours
Procedural0.001~29 days
General (default)0.05~13.9 hours

Preset strategies

Each namespace mode ships with tuned defaults:

ModeSimilarityConfidenceRecencyUtilityAlpha
belief_system0.300.450.200.050.03
agent_memory0.350.200.250.200.05
general0.400.300.200.100.05
procedural0.400.400.150.050.001

Overriding at query time

Pass ScoreParams to override any namespace defaults:

go
results, _ := ns.Retrieve(ctx, client.RetrieveRequest{
    Vector: queryVec,
    TopK:   10,
    ScoreParams: core.ScoreParams{
        SimilarityWeight: 0.60,
        ConfidenceWeight: 0.20,
        RecencyWeight:    0.15,
        UtilityWeight:    0.05,
        DecayAlpha:       0.01, // slower decay
    },
})

Score breakdown in results

Every Result exposes the individual component scores for debugging:

go
for _, r := range results {
    fmt.Printf("composite=%.3f sim=%.3f conf=%.3f rec=%.3f util=%.3f source=%s\n",
        r.Score,
        r.SimilarityScore,
        r.ConfidenceScore,
        r.RecencyScore,
        r.UtilityScore,
        r.RetrievalSource,
    )
}

Provenance attenuation

Claims derived through a chain of sources lose confidence at each hop. If "Alice told Bob who told the system," each hop attenuates by a configurable factor (default 0.9):

confidence_effective = confidence * 0.9^provenance_depth

A direct claim (depth 0) keeps full confidence. A claim derived through 3 hops retains ~73% of its original confidence.

Expiry-aware scoring

Nodes with a ValidUntil deadline get a confidence penalty as expiry approaches. This prevents soon-to-expire facts from ranking alongside evergreen knowledge:

penalty = 1 - exp(-0.02 * hours_until_expiry)

48 hours before expiry, confidence is reduced by ~60%. This is applied automatically — no configuration needed.

How this compares

Most vector databases rank purely by embedding similarity. contextdb's four-dimensional scoring means a highly relevant but low-credibility result ranks below a moderately relevant but well-established one. This is the difference between "closest match" and "best answer."

Released under the MIT License.