Skip to content

[Bug]: TEMPORAL search ignores vector similarity — filter_top_k_events keys score lookup by UUID but looks it up by str #3909

Description

@Goodnight77

Bug Description

TemporalRetriever.filter_top_k_events (cognee/modules/retrieval/temporal_retriever.py:109-120) builds its relevance-score lookup with UUID keys but queries it with str keys, so every lookup misses. Each event falls back to float("inf"), the subsequent sort becomes a no-op, and TEMPORAL search returns events in graph traversal order instead of by semantic relevance — the top_k slice is effectively arbitrary.

score_lookup = {res.id: res.score for res in scored_results}   # L111 — res.id is a UUID
...
score = score_lookup.get(event["id"], float("inf"))            # L115 — event["id"] is a str → always misses
events_with_scores.sort(key=itemgetter("score"))               # L118 — every score == inf → order is meaningless
  • ScoredResult.id is typed id: UUID (cognee/infrastructure/databases/vector/models/ScoredResult.py:19); scored_results come from vector_engine.search(collection_name="Event_name", ...).
  • event["id"] is assigned from the graph node id as a string in collect_events (cognee/infrastructure/databases/graph/ladybug/adapter.py:2824-2825; same in the Neo4j adapter).
  • {UUID(...): score}.get("<str>") never matches (different hash; UUID.__eq__(str) is False).

Steps to Reproduce

  1. Ingest data that builds a temporal graph with several dated Event nodes (cognify content containing timestamps).
  2. await search(query_text="<time-bounded question matching several events>", query_type=SearchType.TEMPORAL).
  3. Inspect the ordering of the returned events / context.

Expected Behavior

Events ranked ascending by vector distance (most semantically relevant first), then truncated to top_k.

Actual Behavior

score_lookup.get(event["id"], inf) always misses (UUID key vs str query) → every event scores inf → the stable sort leaves the events in collect_events traversal order → the top_k selection is arbitrary and unrelated to relevance.

Environment

  • OS: any (platform-independent)
  • Python version: 3.10–3.13
  • Cognee version: dev (also affects released 1.x)
  • LLM Provider: any
  • Database: default Ladybug or Neo4j (both return string node ids); Vector: LanceDB / PGVector (ScoredResult.id is UUID)

Logs/Error Messages

None — this is a silent correctness bug: no exception is raised, the ordering is simply wrong.

Additional Context

The existing unit tests (cognee/tests/unit/modules/retrieval/temporal_retriever_test.py) pass despite this bug because they mock scored_results with string ids (SimpleNamespace(id="e2", ...)) and mock collect_events with matching string ids — so both sides are strings in tests and the real UUID-vs-str production path is never exercised.

Suggested fix: normalize both sides to str (str(res.id) / str(event["id"])) — backward-compatible with the string-id tests — plus a regression test using a real UUID-typed ScoredResult that fails before the fix and passes after. Happy to open a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions