Skip to main content
Your users rate the answers your assistant gives, and now you have to decide how much those ratings should count when memory is searched again. Too little and the feedback is decorative; too much and a single thumbs-up decides everything — and there is no way to pick the number without watching it move.

What You’ll Build

Two bundled text files — five German car manufacturers and five US tech companies — are remembered into one memory, so the graph holds two distinct bodies of context. One session then asks a cars question and rates the answer 5, asks a companies question and rates that answer 1, and a feedback-weights pipeline bakes both ratings into the feedback_weight of the graph elements each answer used. What comes out is a sweep: the deliberately ambiguous question “List the companies in the context” is asked six times at feedback_influence 0.0, 0.2, 0.4, 0.6, 0.8, and 1.0, with every answer printed under its beta, so you can read the dial’s effect off one screen instead of guessing at a default. The complete runnable script is examples/demos/feedback/feedback_score_shifting_example.py — this page walks through its key moments rather than reproducing it.

Features in Play

  • Remember — loads both text files into one memory in a single call, so the two topics compete for the same retrieval slots
  • Sessions — one shared session_id records each answered question as a QA entry, including which graph elements the answer used, giving the ratings something to attach to
  • Feedback Systemadd_feedback() puts the 5 and the 1 on those two QA entries
  • Improve — the feedback-weights pipeline the demo calls directly is the stage improve() runs for you outside a demo
  • Feedback-Weighted Rankingfeedback_influence is the per-call dial that decides how much the stored weights count during triplet scoring

What to Expect

The excerpts below come from a real run, trimmed: cognee’s progress logs are elided. The step lines are what the script prints; the answers are shown as the text they returned, because print(str(answer)) wraps each one in the ResponseGraphEntry(...) object your terminal will actually show — same content, more scaffolding around it. Ingestion and all eight answers are live LLM calls, so the wording of every answer — and the exact beta where the ranking shifts — varies from run to run. Steps 1 to 3 set the experiment up. Two ratings are stored against the session, then the pipeline writes them into the graph. Nothing has been swept yet — Feedback weights applied. is the line that says the graph now carries the 5 and the 1.
At low beta the ratings barely register. The ambiguous question pulls from both documents: all ten names, technology companies first, exactly as semantic similarity ranks them.
From 0.4 on the up-rated context owns the answer. The five technology companies drop out entirely and only the German car manufacturers — the context the 5 was attached to — come back. The answer at 0.6 and 0.8 is identical to both blocks below, elided here: past the tipping point, turning the dial further changes nothing, which is exactly what the sweep is for.

Before You Start

  • Complete Quickstart to understand basic operations
  • Ensure you have LLM Providers configured — ingestion and all eight answers are live calls, so the wording of every answer in the sweep varies from run to run
  • Set CACHING=true and CACHE_BACKEND=fs; the script checks both at import time and raises CogneeConfigurationError if either is wrong. Sessions and feedback work on any cache adapter — the script pins the filesystem one so the run needs no external service and leaves its session files where you can inspect them
  • Run it from a checkout of the cognee repo: it reads its two documents from the feedback_score_shifting_example_data/ folder next to the script, so a copy-pasted copy has nothing to ingest
  • The run opens with cognee.forget(everything=True) and the script does not redirect cognee’s storage roots, so it clears whatever memory the current configuration points at — run it against a scratch instance rather than storage you want to keep

How It Works

Stage 1: Require a Filesystem Session Cache

The check runs at import time, before anything is ingested, because the whole demo hangs off session storage: with CACHING=false there are no QA entries to rate, and therefore no ratings for the weights pipeline to read. Any cache backend would store those entries; requiring fs is the demo keeping its run self-contained. Either way the check fails loudly on a misconfigured instance instead of quietly sweeping a graph whose weights never moved.

Stage 2: Put Two Rival Topics in One Memory

TEXT_1 and TEXT_2 are the two bundled documents — Audi, BMW, Mercedes-Benz and their peers in one, Apple, Google and theirs in the other — and they go in as a single list, into a single memory. That shared memory is what makes the closing question ambiguous: both files describe companies, so nothing but the ratings can tell retrieval which set to favor. self_improvement=False skips the improve() pass that remember() would otherwise run after cognify, so the graph the sweep queries is exactly what was ingested — and the demo’s own pipeline call in Stage 5 is the only thing that ever writes a feedback_weight.

Stage 3: Rate the Cars Context Up

Everything from here on runs as the default user (get_default_user()) under one named session the script opens just above. Asking with that session_id is what records the exchange, and get_session(..., last_n=1) reads that one entry straight back so its qa_id can be rated. The question is narrow on purpose: it pulls the car manufacturers into the answer, so the 5/5 lands on exactly the graph elements that describe them.

Stage 4: Rate the Companies Context Down

The mirror image, in the same session: a question about technology companies and their products, then a 1 on the answer it produced. Two ratings pulling in opposite directions is what makes the sweep readable — a symmetric signal would raise both topics equally and leave their relative order untouched.

Stage 5: Bake the Ratings Into the Graph

Until this call the two ratings live only in the session; the graph has not moved. The pipeline walks the elements each rated answer used and updates their feedback_weight toward the normalized rating, with alpha setting how far one rating pulls — the default is 0.1, and the demo turns it up to 0.9 so a single rating per topic is enough to separate them. In an ordinary application this is what improve() does for you.

Stage 6: Sweep the Dial Over One Ambiguous Query

The same question, six times, with only feedback_influence changing. It is asked without a session_id, so no conversation history carries the earlier ratings’ text forward and the graph plus its new weights are the only thing in play. At 0.0 the weights are ignored and ranking is pure semantic similarity; as beta rises, the script’s own note says ranking should shift toward the positively-rated context, and at 1.0 — as it puts it, “only feedback score is taken into account nothing else” — similarity drops out of the triplet score entirely.

Run It

Feedback System

Rating a session answer and pushing that rating into graph weights.

Truth-Subspace Reranking

Where feedback_weight meets retrieval scoring, alongside truth weighting.

Improve

The operation that applies feedback weights for you outside a demo.

Resolve Conflicting Facts in Memory

The sibling demo, where a rating steers attention but cannot decide what is true.