Tighten relevance scoring and Polymarket ranking
Score against original user intent on Reddit, remove the artificial low-end relevance floor, and make Polymarket semantics dominate generic market quality signals. Also apply the relevance filter to Polymarket and update the affected cross-source tests. Validation: uv run python -m unittest
This commit is contained in:
@@ -57,9 +57,9 @@ class TestComputeRelevance(unittest.TestCase):
|
||||
boosted = instagram._compute_relevance("claude code", "random video about stuff", ["claudecode", "ai"])
|
||||
self.assertGreater(boosted, base)
|
||||
|
||||
def test_floor_at_01(self):
|
||||
def test_no_match_returns_zero(self):
|
||||
rel = instagram._compute_relevance("quantum physics", "cat dancing video")
|
||||
self.assertGreaterEqual(rel, 0.1)
|
||||
self.assertEqual(rel, 0.0)
|
||||
|
||||
def test_empty_query_returns_default(self):
|
||||
rel = instagram._compute_relevance("", "Some video title")
|
||||
|
||||
@@ -569,8 +569,9 @@ class TestTextSimilarity(unittest.TestCase):
|
||||
|
||||
def test_partial_token_overlap(self):
|
||||
score = polymarket._compute_text_similarity("Arizona Basketball", "Will Arizona win?")
|
||||
# "Arizona" matches, "Basketball" doesn't -> 0.5
|
||||
self.assertAlmostEqual(score, 0.5)
|
||||
# Partial informative match should stay below exact match.
|
||||
self.assertGreater(score, 0.3)
|
||||
self.assertLess(score, 0.6)
|
||||
|
||||
def test_no_overlap(self):
|
||||
score = polymarket._compute_text_similarity("Arizona Basketball", "Will AI regulation pass?")
|
||||
@@ -595,7 +596,7 @@ class TestTextSimilarity(unittest.TestCase):
|
||||
"Who will be the #1 overall seed?",
|
||||
outcomes=["Duke", "Arizona", "Houston"],
|
||||
)
|
||||
self.assertEqual(score, 0.85)
|
||||
self.assertEqual(score, 1.0)
|
||||
|
||||
def test_outcome_bidirectional_match(self):
|
||||
"""Topic 'Arizona Basketball' should match outcome 'Arizona' (outcome in core)."""
|
||||
@@ -604,16 +605,17 @@ class TestTextSimilarity(unittest.TestCase):
|
||||
"Who will be the #1 overall seed?",
|
||||
outcomes=["Duke", "Arizona", "Houston"],
|
||||
)
|
||||
self.assertEqual(score, 0.85)
|
||||
self.assertEqual(score, 0.88)
|
||||
|
||||
def test_outcome_token_overlap(self):
|
||||
"""Partial token overlap with outcome gets 0.7 when no substring match."""
|
||||
"""Partial token overlap with outcome gets a moderate score."""
|
||||
score = polymarket._compute_text_similarity(
|
||||
"Iran War",
|
||||
"Unrelated geopolitics title",
|
||||
outcomes=["War continues", "Peace deal"],
|
||||
)
|
||||
self.assertEqual(score, 0.7)
|
||||
self.assertGreater(score, 0.3)
|
||||
self.assertLess(score, 0.6)
|
||||
|
||||
def test_outcome_no_match(self):
|
||||
"""No outcome match falls through to title token overlap."""
|
||||
@@ -632,7 +634,15 @@ class TestTextSimilarity(unittest.TestCase):
|
||||
"Unrelated title",
|
||||
outcomes=["Arizona"],
|
||||
)
|
||||
self.assertEqual(score, 0.85)
|
||||
self.assertEqual(score, 1.0)
|
||||
|
||||
def test_generic_only_odds_match_stays_below_threshold(self):
|
||||
score = polymarket._compute_text_similarity(
|
||||
"Anthropic odds",
|
||||
"Republican 2026 House odds",
|
||||
outcomes=["Yes", "No"],
|
||||
)
|
||||
self.assertLess(score, 0.3)
|
||||
|
||||
def test_title_match_still_beats_outcome(self):
|
||||
"""Title substring match (1.0) takes priority over outcome match (0.85)."""
|
||||
|
||||
+16
-4
@@ -47,16 +47,28 @@ class TestExpandRedditQueries(unittest.TestCase):
|
||||
self.assertGreaterEqual(len(queries), 1)
|
||||
|
||||
def test_default_includes_review_variant(self):
|
||||
queries = reddit.expand_reddit_queries("cursor IDE", "default")
|
||||
queries = reddit.expand_reddit_queries("cursor IDE pricing", "default")
|
||||
self.assertTrue(any("worth it" in q or "review" in q for q in queries))
|
||||
|
||||
def test_default_skips_review_variant_for_prediction(self):
|
||||
queries = reddit.expand_reddit_queries("anthropic odds", "default")
|
||||
self.assertFalse(any("worth it" in q or "review" in q for q in queries))
|
||||
|
||||
def test_default_skips_review_variant_for_breaking_news(self):
|
||||
queries = reddit.expand_reddit_queries("kanye west", "default")
|
||||
self.assertFalse(any("worth it" in q or "review" in q for q in queries))
|
||||
|
||||
def test_deep_includes_issues_variant(self):
|
||||
queries = reddit.expand_reddit_queries("cursor IDE", "deep")
|
||||
queries = reddit.expand_reddit_queries("cursor IDE pricing", "deep")
|
||||
self.assertTrue(any("issues" in q or "problems" in q for q in queries))
|
||||
|
||||
def test_deep_skips_issues_variant_for_prediction(self):
|
||||
queries = reddit.expand_reddit_queries("anthropic odds", "deep")
|
||||
self.assertFalse(any("issues" in q or "problems" in q for q in queries))
|
||||
|
||||
def test_deep_has_more_queries_than_quick(self):
|
||||
quick = reddit.expand_reddit_queries("cursor IDE", "quick")
|
||||
deep = reddit.expand_reddit_queries("cursor IDE", "deep")
|
||||
quick = reddit.expand_reddit_queries("cursor IDE pricing", "quick")
|
||||
deep = reddit.expand_reddit_queries("cursor IDE pricing", "deep")
|
||||
self.assertGreater(len(deep), len(quick))
|
||||
|
||||
|
||||
|
||||
+10
-1
@@ -75,7 +75,7 @@ class TestTokenOverlapRelevance(unittest.TestCase):
|
||||
|
||||
def test_floor_at_0_1(self):
|
||||
rel = token_overlap_relevance("quantum physics", "cat dancing video")
|
||||
self.assertGreaterEqual(rel, 0.1)
|
||||
self.assertEqual(rel, 0.0)
|
||||
|
||||
def test_full_match_returns_1(self):
|
||||
rel = token_overlap_relevance("python tutorial", "Python Tutorial for Beginners")
|
||||
@@ -96,6 +96,15 @@ class TestTokenOverlapRelevance(unittest.TestCase):
|
||||
rel = token_overlap_relevance("the a is", "some content here")
|
||||
self.assertEqual(rel, 0.5)
|
||||
|
||||
def test_generic_only_overlap_stays_below_filter_threshold(self):
|
||||
rel = token_overlap_relevance("anthropic odds", "Republican house odds update")
|
||||
self.assertLess(rel, 0.3)
|
||||
|
||||
def test_informative_partial_match_stays_above_generic_only(self):
|
||||
generic_only = token_overlap_relevance("anthropic odds", "Republican house odds update")
|
||||
informative = token_overlap_relevance("anthropic odds", "Anthropic valuation market")
|
||||
self.assertGreater(informative, generic_only)
|
||||
|
||||
|
||||
class TestHashtagRelevance(unittest.TestCase):
|
||||
"""Tests for hashtag-aware relevance (TikTok/Instagram pattern)."""
|
||||
|
||||
@@ -44,9 +44,9 @@ class TestComputeRelevance(unittest.TestCase):
|
||||
score = scrapecreators_x._compute_relevance("", "some text")
|
||||
self.assertEqual(score, 0.5)
|
||||
|
||||
def test_floor_at_01(self):
|
||||
def test_no_match_returns_zero(self):
|
||||
score = scrapecreators_x._compute_relevance("abcdef ghijkl", "xyz")
|
||||
self.assertGreaterEqual(score, 0.1)
|
||||
self.assertEqual(score, 0.0)
|
||||
|
||||
|
||||
class TestExtractCoreSubject(unittest.TestCase):
|
||||
|
||||
@@ -33,9 +33,9 @@ class TestTikTokRelevance(unittest.TestCase):
|
||||
rel = tiktok._compute_relevance("", "Some video title")
|
||||
self.assertEqual(rel, 0.5)
|
||||
|
||||
def test_floor(self):
|
||||
def test_no_match_returns_zero(self):
|
||||
rel = tiktok._compute_relevance("quantum physics", "cat dancing video")
|
||||
self.assertGreaterEqual(rel, 0.1)
|
||||
self.assertEqual(rel, 0.0)
|
||||
|
||||
|
||||
class TestExtractCoreSubject(unittest.TestCase):
|
||||
|
||||
@@ -62,7 +62,7 @@ class TestComputeRelevance(unittest.TestCase):
|
||||
|
||||
def test_no_match(self):
|
||||
result = _compute_relevance("Claude Code", "Python Web Scraping")
|
||||
self.assertEqual(result, 0.1) # Floor
|
||||
self.assertEqual(result, 0.0)
|
||||
|
||||
def test_empty_query_returns_neutral(self):
|
||||
result = _compute_relevance("", "Some Video Title")
|
||||
@@ -74,7 +74,7 @@ class TestComputeRelevance(unittest.TestCase):
|
||||
|
||||
def test_empty_title(self):
|
||||
result = _compute_relevance("Claude Code", "")
|
||||
self.assertEqual(result, 0.1) # Floor
|
||||
self.assertEqual(result, 0.0)
|
||||
|
||||
def test_case_insensitive(self):
|
||||
result = _compute_relevance("claude code", "CLAUDE CODE Tutorial")
|
||||
@@ -89,9 +89,9 @@ class TestComputeRelevance(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(result, 1.0)
|
||||
|
||||
def test_floor_at_0_1(self):
|
||||
def test_no_match_returns_zero(self):
|
||||
result = _compute_relevance("quantum computing", "cat videos compilation")
|
||||
self.assertEqual(result, 0.1)
|
||||
self.assertEqual(result, 0.0)
|
||||
|
||||
def test_cap_at_1_0(self):
|
||||
result = _compute_relevance("AI", "AI AI AI AI AI")
|
||||
@@ -103,7 +103,7 @@ class TestComputeRelevance(unittest.TestCase):
|
||||
|
||||
def test_single_word_no_match(self):
|
||||
result = _compute_relevance("Seedance", "Random cooking video")
|
||||
self.assertEqual(result, 0.1)
|
||||
self.assertEqual(result, 0.0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user