Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Profiles and constants

A profile is a named set of ranking constants. The server and the UI use MEMO_PROFILE, default default. The CLI takes search --profile <name>. MCP clients cannot pick a profile per request in 1.x.

memo-mcp profiles show            # every profile, every constant, with its derivation
memo-mcp profiles show precise

Shipped profiles

ProfileWeights: sem / kw / exact / fact / entity / graphOther differencesUse for
default0.5 / 0.5 / 0.3 / 0.4 / 0.4 / 0.5—General use
precisesame as defaultfetch_depth 200, cutoff_gap 0.6, rerank on when a reranker is attachedRarely worded answers; shorter, surer lists
recencysame as defaultEvery kind ages; half-life 30 days; floor 0.6“What did I write lately”
code0.4 / 0.4 / 0.6 / 0.4 / 0.5 / 0.5No recencyIdentifier-heavy questions
minmaxsame as defaultMin-max score fusion instead of RRFExperiment
text-onlysame as defaultNo entity or graph arm (the 1.0 arms)Ablation
no-graphsame as defaultEntity arm without the graph walkAblation
keyword-onlykeyword 1.0 only—Ablation; the baseline to beat
semantic-onlysemantic 1.0 only—Ablation

The constants

ConstantDefaultRaise it to…Lower it to…
weights.<arm>see aboveLet that arm’s ranking count for moreMute an arm (0 disables it)
rrf_k60Flatten the difference between rank 1 and rank 10Reward top ranks more
fetch_depth100Keep rarely worded hits in the fused list, at some latency costSpeed up large KBs
half_life_days90Age more slowlyFavour recent items more strongly
recency_floor0.8Make age matter lessMake age matter more (floor is the minimum kept)
recency_kindsnote, conversationAge more kinds[] turns recency off
cutoff_gap0.5Cut later, giving longer listsCut sooner at a score cliff
min_results3Always show more before a gap cutAllow single-answer lists
semantic_floor0.30Abstain more readily on vague matchesKeep weaker meaning-only matches
bands0.60 / 0.45 / 0.30Generic relevance bands; per-model bands override them—

Worked example: fusion

A passage at keyword rank 1 and semantic rank 2 under default:

keyword   0.5 / (60 + 1) = 0.008197
semantic  0.5 / (60 + 2) = 0.008065
fused                    = 0.016262

A keyword-only hit at rank 1 scores 0.008197, the same as a semantic-only hit at rank 1. Equal weights therefore let either arm put a result on the first page. That is the main reason the default is balanced.

Graph routing

The entity and graph arms run only when the query names two or more known entities, or one entity with relational phrasing (“depends on”, “related to”, …). The trace’s routing_reason says why they ran. Ablations show that routing them on every query hurts single-entity lookups. That is why routing is not a tunable constant.

Customising

Overrides go in profiles.json. The derivations behind each default are in architecture §5–§6 and the eval reports.