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.urlMeans: “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
NewsItemrows 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_relevantstamp, and the executor rewritesai.relevant(n, '…')in the executed query to a match against that stamp, so it filters as ordinary data. It composes with real predicates viaAND(the date filter above) and with the otherai.*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.

