Skip to content

7.3 ai.relevant — the per-row relevance filter

MATCH (me:AssistantUser)-[:TRACKS]->(n:NewsItem)
WHERE ai.relevant(n, 'about my company\'s Series A funding round')
AND n.published > date() - duration('P7D')
RETURN n.title, n.url

Means: “of the news fetched for me this week, keep only the items actually about my funding round” — a discriminator no keyword and no embedding reliably draws (a piece can name “funding” yet not be about mine; can be about mine yet never say “Series A”).

How it executes:

  • Fetch the NewsItem rows as any virtual join would (§2) — the source can’t apply the criterion, so it returns the broad set.
  • Judge — one batched LLM call per criterion. The fetched rows’ text is scored 0..1 for fit to the criterion; rows below a threshold are dropped, keeping the nodes (unlike the relevant(text, criterion) fan-in aggregation of §5.3-adjacent LLM reducers, which returns text — this keeps the rows so the query can traverse and return them).
  • Stamp & run. The criterion is written onto each surviving row under the internal ai_relevant stamp, and the executor rewrites ai.relevant(n, '…') in the executed query to a match against that stamp, so it filters as ordinary data. It composes with real predicates via AND (the date filter above) and with the other ai.* primitives.

Use it only for a subjective about / relevant-to that maps to no shown property; for a concrete field, an ordinary WHERE is cheaper and exact.