> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cognee.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Tune How Strongly Ratings Steer an Answer

> Rate one answer up and another down, bake both into graph feedback weights, then sweep feedback_influence from 0.0 to 1.0 over one ambiguous question and watch the ranking move

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`](https://github.com/topoteretes/cognee/blob/main/examples/demos/feedback/feedback_score_shifting_example.py) —
this page walks through its key moments rather than reproducing it.

## Features in Play

* [Remember](/core-concepts/main-operations/remember) — loads both text files into one memory in a single call, so the two topics compete for the same retrieval slots
* [Sessions](/guides/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 System](/guides/feedback-system) — `add_feedback()` puts the `5` and the `1` on those two QA entries
* [Improve](/core-concepts/main-operations/improve#with-session-ids) — the feedback-weights pipeline the demo calls directly is the stage `improve()` runs for you outside a demo
* [Feedback-Weighted Ranking](/guides/truth-subspace-reranking#relationship-to-the-feedback-loop) — `feedback_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`.

```text theme={null}
Step 1: Ask cars-specific question and give positive feedback (5).
...
  Added feedback score=5 for cars context.

Step 2: Ask companies-specific question and give negative feedback (1).
...
  Added feedback score=1 for companies context.

Step 3: Apply feedback into graph feedback_weight values (memify).
...
  Feedback weights applied.
```

**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.

```text theme={null}
Step 4: Ask one neutral query while sweeping beta.
  As beta increases, ranking should shift toward positively-rated context (companies focused on car manufacturers). 1 means only feedback score is taken into account nothing else.

--- beta = 0.0 (0% feedback influence) ---
- Apple
- Google
- Microsoft
- Amazon
- Meta (formerly Facebook)
- Audi
- BMW
- Mercedes‑Benz
- Porsche
- Volkswagen

--- beta = 0.2 (20% feedback influence) ---
Apple
Google
Microsoft
Amazon
Meta (formerly Facebook)
Audi
BMW
Mercedes-Benz
Porsche
Volkswagen
```

**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.

```text theme={null}
--- beta = 0.4 (40% feedback influence) ---
Audi
BMW
Mercedes-Benz
Porsche
Volkswagen

...

--- beta = 1.0 (100% feedback influence) ---
Audi
BMW
Mercedes-Benz
Porsche
Volkswagen
```

## Before You Start

* Complete [Quickstart](/getting-started/quickstart) to understand basic operations
* Ensure you have [LLM Providers](/setup-configuration/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](/core-concepts/sessions-and-caching#cache-adapters) — 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

```python theme={null}
cache_config = get_cache_config()
if not cache_config.caching or cache_config.cache_backend != "fs":
    raise CogneeConfigurationError(
        "feedback_score_shifting_example requires caching=True and CACHE_BACKEND=fs."
    )
```

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

```python theme={null}
async def main():
    await cognee.forget(everything=True)

    await cognee.remember([TEXT_1, TEXT_2], self_improvement=False)
```

`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

```python theme={null}
    await cognee.recall(
        query_text="Which German car manufacturers are described and what are they known for?",
        query_type=SearchType.GRAPH_COMPLETION,
        user=user,
        session_id=session_id,
    )
    qa_cars = (await cognee.session.get_session(session_id=session_id, user=user, last_n=1))[0]
    await cognee.session.add_feedback(
        session_id=session_id,
        qa_id=qa_cars.qa_id,
        feedback_score=5,
        feedback_text="Cars-focused context is exactly what I want.",
        user=user,
    )
```

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

```python theme={null}
    qa_companies = (await cognee.session.get_session(session_id=session_id, user=user, last_n=1))[0]
    await cognee.session.add_feedback(
        session_id=session_id,
        qa_id=qa_companies.qa_id,
        feedback_score=1,
        feedback_text="Companies-focused context is less useful for this goal.",
        user=user,
    )
```

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

```python theme={null}
    await apply_feedback_weights_pipeline(user=user, session_ids=[session_id], alpha=0.9)
```

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()`](/core-concepts/main-operations/improve#with-session-ids) does for you.

### Stage 6: Sweep the Dial Over One Ambiguous Query

```python theme={null}
    final_query = "List the companies in the context"
    for beta in [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]:
        answer = await cognee.recall(
            query_text=final_query,
            query_type=SearchType.GRAPH_COMPLETION,
            user=user,
            feedback_influence=beta,
        )
        print(f"\n--- beta = {beta:.1f} ({beta * 100:.0f}% feedback influence) ---")
        print(str(answer))
```

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

```bash theme={null}
uv run python examples/demos/feedback/feedback_score_shifting_example.py
```

<Columns cols={2}>
  <Card title="Feedback System" icon="brain-circuit" href="/guides/feedback-system">
    Rating a session answer and pushing that rating into graph weights.
  </Card>

  <Card title="Truth-Subspace Reranking" icon="compass" href="/guides/truth-subspace-reranking">
    Where `feedback_weight` meets retrieval scoring, alongside truth weighting.
  </Card>

  <Card title="Improve" icon="sparkles" href="/core-concepts/main-operations/improve">
    The operation that applies feedback weights for you outside a demo.
  </Card>

  <Card title="Resolve Conflicting Facts in Memory" icon="scale" href="/examples/contradiction-handling">
    The sibling demo, where a rating steers attention but cannot decide what is true.
  </Card>
</Columns>
