perf: cache PreparedQuery per stream, skip double-normalize in dedupe (#282)

Scoring hot path (_normalize_score_dedupe) re-tokenized the same
ranking_query ~240x per stream: once per item for local_relevance,
plus ~5x per item across snippet windows. Query tokens are immutable
within a stream, so compute them once as relevance.PreparedQuery and
thread through signals.annotate_stream and snippet.extract_best_snippet.

dedupe._PreparedText called normalize_text twice: once in __init__ and
again via get_ngrams. Factor out _ngrams_of_normalized so the prepared
path skips the redundant pass while get_ngrams keeps its public contract.

Behavior unchanged.
This commit is contained in:
Ilia Alshanetsky
2026-04-25 17:16:57 -04:00
committed by GitHub
parent 2c2755b49c
commit e6b89f2644
5 changed files with 48 additions and 18 deletions
+7 -3
View File
@@ -26,7 +26,10 @@ def source_quality(source: str) -> float:
return SOURCE_QUALITY.get(source, 0.6)
def local_relevance(item: schema.SourceItem, ranking_query: str) -> float:
def local_relevance(
item: schema.SourceItem,
ranking_query: "str | relevance.PreparedQuery",
) -> float:
text = "\n".join(
part
for part in [item.title, item.body, item.snippet]
@@ -175,13 +178,14 @@ def normalize(values: list[float | None]) -> list[int | None]:
def annotate_stream(
items: list[schema.SourceItem],
ranking_query: str,
ranking_query: "str | relevance.PreparedQuery",
freshness_mode: str,
) -> list[schema.SourceItem]:
"""Attach local scoring metadata and return items sorted by local_rank_score."""
prepared_query = ranking_query if isinstance(ranking_query, relevance.PreparedQuery) else relevance.PreparedQuery(ranking_query)
engagement_scores = normalize([engagement_raw(item) for item in items])
for item, eng_score in zip(items, engagement_scores, strict=True):
item.local_relevance = local_relevance(item, ranking_query)
item.local_relevance = local_relevance(item, prepared_query)
item.freshness = freshness(item, freshness_mode)
item.engagement_score = eng_score
item.source_quality = source_quality(item.source)