Skip to content

[schemas] recency-boosted match_thoughts RPC#231

Open
txcfi-scott wants to merge 1 commit intoNateBJones-Projects:mainfrom
txcfi-scott:contrib/txcfi-scott/recency-boosted-match-thoughts
Open

[schemas] recency-boosted match_thoughts RPC#231
txcfi-scott wants to merge 1 commit intoNateBJones-Projects:mainfrom
txcfi-scott:contrib/txcfi-scott/recency-boosted-match-thoughts

Conversation

@txcfi-scott
Copy link
Copy Markdown

What it does

Adds a new RPC, match_thoughts_recency, alongside the core match_thoughts function from the getting-started guide. It accepts the same arguments plus two new optional parameters — recency_weight and half_life_days — and returns the same columns. Ranking is a blend of cosine similarity and an exponentially-decaying recency factor.

The original match_thoughts is not replaced. Callers opt into the new variant by name.

Why it matters

Pure cosine similarity returns ancient thoughts ranked high whenever they happen to be vector-nearest. For a long-lived evergreen personal brain that is fine — old high-quality notes should still surface. But for an active daily-context or task-tracking brain, a gentle recency preference produces visibly better results. Baking that preference into the core function would be disruptive; making it a separate RPC with an opt-in weight lets each caller tune it per query.

The formula

recency_factor = exp(-age_days / half_life_days)
final_score    = similarity * (1 - recency_weight)
               + recency_factor * recency_weight
  • recency_weight defaults to 0.0 → pure similarity, identical ranking to match_thoughts.
  • half_life_days defaults to 90.0 → a thought 90 days old contributes half of a brand-new thought's recency factor.
  • The match threshold is applied to the raw cosine similarity before the blend, so a high recency weight cannot let completely irrelevant recent thoughts surface.
  • Values outside [0, 1] on recency_weight are clamped; non-positive half_life_days falls back to 90.

How it stays safe

  • Additive only. No existing tables, columns, or functions are altered. The core match_thoughts RPC is untouched.
  • Idempotent. Uses CREATE OR REPLACE FUNCTION, so the file is safe to re-run.
  • Backward compatible. Default arguments reproduce match_thoughts behavior exactly; installing this schema has zero effect on existing callers.
  • Easy to roll back. A single DROP FUNCTION IF EXISTS match_thoughts_recency(vector(1536), float, int, jsonb, float, float); removes it cleanly.

Example usage

Pure similarity (identical to match_thoughts):

select *
from match_thoughts_recency(
  query_embedding := '[...]'::vector(1536),
  match_threshold := 0.7,
  match_count     := 10
);

Gentle recency nudge (20% weight, 90-day half-life):

select *
from match_thoughts_recency(
  query_embedding := '[...]'::vector(1536),
  match_threshold := 0.7,
  match_count     := 10,
  recency_weight  := 0.2,
  half_life_days  := 90.0
);

Strong recency preference ("what did I capture this week about X?"):

select *
from match_thoughts_recency(
  query_embedding := '[...]'::vector(1536),
  match_threshold := 0.6,
  match_count     := 10,
  recency_weight  := 0.7,
  half_life_days  := 14.0
);

What it requires

  • Working Open Brain setup (just the thoughts table + match_thoughts from the getting-started guide).

No additional services. No LLM calls. No embedding regeneration.

Tested

  • Ran schema.sql twice against a fresh and a populated Supabase Open Brain. Both runs complete idempotently with no errors.
  • Called match_thoughts_recency with default arguments and confirmed results match match_thoughts row-for-row (same rank order, same similarity values).
  • Swept recency_weight from 0.01.0 in 0.1 increments and confirmed the rank order shifts monotonically from pure-similarity toward pure-recency.
  • Confirmed the threshold gates on raw cosine similarity: with match_threshold := 0.7 and recency_weight := 1.0, brand-new thoughts whose raw similarity is below 0.7 are correctly excluded.
  • Verified recency_weight outside [0, 1] is clamped and non-positive half_life_days falls back to 90.

Files touched

Only schemas/recency-boosted-match-thoughts/ — stays within the contribution scope check.

Attribution

Adapted from a recency-weighted ranking variant used in a personal Open Brain deployment where the mix of evergreen notes and daily task captures made pure cosine ranking feel stale. Released here so any Open Brain user can opt in without modifying the core search function.

Installs match_thoughts_recency alongside the core match_thoughts RPC.
Blends cosine similarity with an exponential recency decay:

  recency_factor = exp(-age_days / half_life_days)
  final_score    = similarity * (1 - recency_weight)
                 + recency_factor * recency_weight

Defaults (recency_weight = 0) reproduce the behavior of match_thoughts
exactly, so installation is side-effect-free for existing callers.
Threshold is applied on raw cosine similarity before the blend.
@github-actions github-actions Bot added the schema Contribution: database extension label Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

schema Contribution: database extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant