PERSONALIZATION_INFLUENCE, PREFERENCE_ALPHA, PREFERENCE_BETA — are
documented in Setup Configuration. For a runnable walkthrough of
the rate → improve → recall loop, see the
Feedback System guide. This page explains
the mechanism.
Where the ratings come from
A rating can reach personalization two ways:- Explicitly, via
cognee.session.add_feedback(..., feedback_score=1..5). - Inferred, when
AUTO_FEEDBACKis on. The per-turn analysis can read a 1–5 rating of the previous answer out of what you say next (“that was exactly right”, “no, that’s wrong again”). The rating question is only added to the analysis whenPERSONALIZATION_ENABLEDis on, and a value outside 1–5 degrades to “no signal” instead of raising. With the flag off, a turn that carries only a rating writes nothing.
feedback_score wins over an inferred rating for the same Q&A entry. A rating of
3 is neutral and is treated as a no-op.
The same ratings also feed the global feedback weights, which move
ranking for every user. That mechanism is independent of personalization — you can run either,
both, or neither.
How preferences are stored
Personalization keeps one internal preference node per (user, dataset) pair, grouped under theuser_preferences node set. From it, weighted prefers edges point at the graph nodes that
were actually used to build the answers that user rated (only nodes — edges are never prefers
targets).
- A weight of
0.5is neutral, meaning “no signal”. - Each rating moves a weight toward its target by
PREFERENCE_ALPHA(default0.3). - Untouched weights decay back toward neutral by
PREFERENCE_BETA(default0.02) per conversation turn. Decay is computed on read from a turn counter, so nothing is rewritten in the background and there are no timestamps involved. A weight that has decayed to within0.01of neutral is pruned. - Stated preferences (“always answer in bullet points”) are also folded into the preference node’s text, newest first, capped at 2000 characters — the oldest lines fall off first, never mid-line. That text is injected as guidance into graph, hybrid, and RAG completion prompts.
How preferences are updated
The preference update runs as a stage ofimprove()
when you pass session_ids — the same call that applies global feedback weights. It runs once
for all the sessions you pass, because preferences aggregate across a user’s sessions. It is
safe to re-run: each turn is counted once and each rating spent once. Like its neighbouring
stages it is best-effort — a failure is logged and never blocks the rest of improve() — and it
is a no-op that writes nothing at all when PERSONALIZATION_ENABLED is off.
What changes at retrieval time
When weights exist for the current user and dataset, they act as a multiplicative nudge on ranking, capped byPERSONALIZATION_INFLUENCE (default 0.3, i.e. at most 30%):
- Graph completion — the personal weight multiplies into triplet scoring.
- Hybrid — it multiplies alongside the existing importance and truth factors.
- RAG completion (
RAG_COMPLETION) — when the loaded weights actually match rows in the chunk collection, the candidate fetch widens to the retriever’s existingwide_search_top_k(default100), the results are re-sorted by personalized distance, and the list is trimmed back totop_k. So personalization can change which chunks make the cut, not only their order. Weights that match nothing leave the fetch attop_k.
PERSONALIZATION_INFLUENCE=0, the ranking factor is exactly 1.0,
so an empty or non-matching weight map leaves every path arithmetically identical to an
un-personalized run.
Two conditions are needed for personalization to apply at all: a user must be in context, and
exactly one dataset must resolve. A search that spans several datasets never personalizes.
Reads are fail-open everywhere — a missing, empty, or broken preference node costs you the
personalization, never the search.
Preference nodes are internal and are never surfaced in retrieval output. They are filtered at
the graph read chokepoints: graph projection for search, triplet embedding, contradiction
detection, natural-language search, and the provenance and schema-inventory views (which also
drop every edge touching an internal node). The one exception is
SearchType.CYPHER, which runs
your Cypher verbatim and applies no filter.Feedback System
Rate answers and fold ratings into ranking
Improve
Enrich the graph and bridge session memory
Setup Configuration
Personalization environment variables