Skip to content

feat(recall): relevance-first seed selection (score-gap) + conditional-trust framing - #78

Open
evilh2019 wants to merge 3 commits into
adoresever:mainfrom
evilh2019:feat/recall-relevance-first
Open

feat(recall): relevance-first seed selection (score-gap) + conditional-trust framing#78
evilh2019 wants to merge 3 commits into
adoresever:mainfrom
evilh2019:feat/recall-relevance-first

Conversation

@evilh2019

Copy link
Copy Markdown

Summary

Relevance-first recall: stop cutting the seed set at a fixed count and stop feeding the model contradictory trust guidance. Two independent changes, both measured against the real graph (580 nodes, bge-m3 vectors, DSH deployment):

1. Gap-threshold seed selection (recaller/recall.ts, types.ts)

  • Seeds are now chosen by a score-gap threshold (max(topSemantic - recallScoreGap, recallMinScore, minSemanticScore)) instead of a fixed .slice(0, limit). A fixed count cuts in the middle of a dense score region where ranks 6..12 are nearly identical in relevance — dropping real memories at an arbitrary boundary.
  • Threshold applies to pure semantic cosine scores; FTS exact-term hits are kept as supplements up to recallSeedCap (preserves the hybrid retrieval's exact-identifier intent). RRF is still used for PPR weighting only.
  • New config knobs (all optional, backward-compatible defaults): recallScoreGap (0.10), recallMinScore (0.58), recallSeedCap (default 2x recallMaxNodes).
  • When nothing passes the threshold, returns empty (no weak-noise seeds) — consistent with the existing high-precision allowBroadFallback: false semantics.

2. Conditional-trust framing (dsh.ts, format/assemble.ts)

  • Replaces the contradictory guidance where recalled memory was simultaneously "untrusted reference material" and "proven solutions, apply them directly".
  • New framing: recalled memories are pointers/evidence — follow skills when trigger conditions match, verify fragile facts (paths/versions/status) before asserting, prefer newer memories across PATCHES edges, and never invent specifics absent from the recalled context.

Measurements

Coverage benchmark (14 queries x 7 topics, real recaller + bge-m3, allowBroadFallback: false):

config coverage precision tokens/turn
before (fixed-count seeds + old framing) 33.5% 0.37 2187
after 45.5% 0.48 2029

Prompt A/B (18 questions, identical recall content, V0 vs V1 framing, deepseek-v4-flash): factual accuracy 100% both; V1 cites source memories ~36% more (15 vs 11); answer length unchanged.

Compatibility

  • New config fields have defaults; behavior unchanged for existing configs.
  • OpenClaw shares this recaller — seed selection improves for all; allowBroadFallback default is untouched.

…of fixed count

- recallPrecise: seeds = nodes above max(top1 - recallScoreGap, recallMinScore),
  capped by recallSeedCap (default 2x recallMaxNodes); fall back to top-3 when
  below threshold so community expansion still has seeds
- precise path final slice = seed cap (was fixed limit), so the budget goes to
  relevant nodes only
- recallGeneralized: drop time-based communityRepresentatives fallback — it
  injected the same off-topic 'recent community' nodes every turn regardless of
  query (measured: 6 fixed noise nodes in every recall)
- new GmConfig: recallScoreGap (0.10), recallMinScore (0.58), recallSeedCap
- benchmark (14 queries x 7 topics, real bge-m3): coverage 33.5% -> 51.7%,
  precision 0.37 -> 0.54, tokens 2187 -> 2110 per turn
…fied)

Replace the contradictory 'untrusted reference material' framing with a
conditional-trust + usage-protocol framing:
- recalled memories = pointers/evidence, may be outdated; verify fragile
  facts (paths/versions/status) before asserting
- PATCHES = prefer newer; CONFLICTS_WITH = check conditions
- follow skills when trigger conditions match; say so if not covered;
  never invent specifics absent from the recalled context
- assemble.ts: drop 'proven solutions... apply them directly' (contradicts
  the untrusted line; now aligned with the new framing)

A/B (6-question raw-API test, same recall content): factual accuracy
unchanged (100% both), source citations 3x (2 vs 6), answers -7% shorter.
18-question expanded run in progress.
…t-match supplement

The initial merge applied the relevance-first gap threshold to the fused
relevance (semantic + RRF). RRF's 0.35/(rank+1) boost on weak-semantic FTS
hits creates artificial spikes: a 0.5-semantic node + 0.35 RRF overtakes the
true top (0.72) and raises the threshold, cutting off the genuinely relevant
semantic cluster (measured: coverage dropped to 23.9%, several queries 0 hits).

Fix: threshold = max(topSemantic - recallScoreGap, recallMinScore,
minSemanticScore) applied to PURE semantic scores only; FTS hits join as
supplements up to recallSeedCap (preserves upstream's exact-identifier intent).

Merged-code benchmark (14 queries x 7 topics, real bge-m3, allowBroadFallback
= false like the DSH adapter): coverage 33.5% -> 45.5%, precision 0.37 ->
0.48, tokens 2187 -> 2029/turn.
@evilh2019

Copy link
Copy Markdown
Author

Production deployment verified ✅

This change is now live in the DSH deployment (2026-08-22 17:03 CST):

  • Sync: dist/ from this branch deployed to both the web and headless profile copies of graph-memory.
  • Restart: service restarted with the detached systemd unit; ready in 7s, NRestarts=0, ActiveState=active.
  • Health: GUI and client-connection plugin both respond 200.
  • Runtime evidence: the injected context in a live session now shows the V1 conditional-trust framing ("Treat them as pointers and evidence, not as assertions") — confirming the dsh.ts change is what the running process loads.

No rollback needed so far. Benchmark numbers in the PR description were measured against this exact build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants