keyword-filter-framework
Skill0 starsChanged 7 months agoMITView on GitHub
High-performance keyword-based content filtering with compiled regex, bot/spam exclusion, configurable thresholds, and quality scoring. Use when building any text classification or filtering pipeline — content moderation, comment filtering, relevance scoring, spam detection, domain-specific text selection.
In this repository37 other files it gives its agents.
- ablation-study-frameworkSkill
- async-http-websocket-patternsSkill
- brain-dumpSkill
- chaos-controlled-behavior-systemSkill
- daily-digestSkill
- database-reset-and-seedSkill
- duckdb-analytics-layerSkill
- event-driven-backtest-engineSkill
- event-study-full-pipelineSkill
- event-study-stats-suiteSkill
- failure-learning-systemSkill
- fastapi-sse-live-dashboardSkill
- goal-task-decompositionSkill
- high-information-gain-interviewerSkill
- idea-extraction-batch-pipelineSkill
- idea-grouping-taxonomySkill
- interview-belief-extractorSkill
- journal-captureSkill
- journal-reviewSkill
- langgraph-agentic-pipelineSkill
- llm-as-judge-eval-frameworkSkill
- multi-tab-dashboard-rendererSkill
- multi-tier-memory-systemSkill
- parquet-storage-with-walSkill
- project-insightsSkill
- pydantic-typed-config-loaderSkill
- quality-trend-detectionSkill
- research-gap-finderSkill
- safe-commitSkill
- simtom-knowledge-isolationSkill
- statistical-signal-detectionSkill
- streaming-dataset-pipelineSkill
- structured-data-extraction-pipelineSkill
- structured-logging-setupSkill
- system-health-monitoringSkill
- textual-tui-reactiveSkill
- vector-db-ingestionSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 3 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 25
Every filter follows the same structure: exclude bad sources, reject low-quality items, require domain signal.
- Very specific: line 73
Use pattern.match() (anchored to start) for patterns that describe the entire message.
- Very specific: line 74
Use pattern.search() for patterns that can appear anywhere.
- Very specific: line 164
Set MIN_LENGTH: Look at 20 good items and 20 bad items — find the length threshold that separates them.
- Distinctive: line 165
Tune scoring weights: Run on 100 items, sort by score, check if the top 10 are actually the best.
- Distinctive: line 186
Always include a self-test at the bottom of your filter module.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Keyword Filter Framework
A pattern for building fast, maintainable keyword-based content filters. Combines compiled regex for speed, layered rejection rules, and a scoring function for ranking passing items.
When to Use
Any time you need to filter a stream of text items (comments, articles, messages, reviews, documents) based on domain relevance, quality, and source trustworthiness. This is the right pattern when:
- You have a known vocabulary for your domain
- You need to exclude known-bad sources (bots, spam accounts)
- You want both a binary pass/fail AND a quality ranking
- Performance matters (thousands+ items)
Architecture: Three-Layer Filter
Every filter follows the same structure: exclude bad sources, reject low-quality items, require domain signal.
Layer 1: Source Exclusion
Maintain a set of known-bad sources to skip entirely. These never change per-item — check them first for early exit.
EXCLUDED_SOURCES = {
"AutoModerator",
"SpamBot",
"[deleted]",
"[removed]",
# Add domain-specific exclusions
}
def _is_excluded_source(item):
author = item.get("author", "")
return author in EXCLUDED_SOURCES or author == ""Using a set gives O(1) lookup. Always check this first — it is the cheapest rejection.
Layer 2: Low-Effort Rejection
Reject items that are too short, match known low-effort patterns, or are obviously off-topic. Use pre-compiled regex patterns for speed.
import re
MIN_LENGTH = 50 # Tune per domain
LOW_EFFORT_PATTERNS = [
re.compile(r"^(nice|cool|awesome|love it|wow|lol|same|thanks)[\.\!\?\s]*$", re.IGNORECASE),
re.compile(r"^(where did you (get|buy|find)|what is that|source|link)\b", re.IGNORECASE),
re.compile(r"^https?://", re.IGNORECASE), # bare links
]
def _is_low_effort(text):
if len(text) < MIN_LENGTH:
return True
for pattern in LOW_EFFORT_PATTERNS:
if pattern.match(text):
return True
return FalseKey decisions:
MIN_LENGTH: Start at 50, adjust based on your domain. Shorter for tweets, longer for articles.- Use
pattern.match()(anchored to start) for patterns that describe the entire message. - Use
pattern.search()for patterns that can appear anywhere.
Layer 3: Domain Keyword Requirement
The item must contain at least one domain-relevant keyword. Compile all keywords into a single regex for performance.
DOMAIN_KEYWORDS = [
# Group by sub-category for maintainability
# Category A
"keyword1", "keyword2", "multi-word phrase",
# Category B
"keyword3", "keyword4",
]
# Compile once at module load — not per call
_KEYWORD_PATTERN = re.compile(
"|".join(re.escape(kw) for kw in DOMAIN_KEYWORDS),
re.IGNORECASE,
)
def _has_domain_signal(text):
return bool(_KEYWORD_PATTERN.search(text))Why one compiled regex instead of looping:
- Single pass through the text instead of N passes
re.compilewith alternation is optimized by Python's regex enginere.escapehandles special characters in keywords safely
Putting It Together
def passes_filter(item):
"""Returns True if item passes all filter layers."""
if _is_excluded_source(item):
return False
text = item.get("body", "") or item.get("text", "") or item.get("content", "")
if text in ("[deleted]", "[removed]", ""):
return False
if _is_low_effort(text):
return False
if not _has_domain_signal(text):
return False
return TrueThe order matters: cheapest checks first, most expensive last.
Quality Scoring
Items that pass the filter can be ranked. A good scoring function combines:
- Keyword density — More domain keywords = more relevant
- Length bonus — Longer items carry more signal (with diminishing returns)
- External signal — Upvotes, likes, citations, or any platform-provided quality metric
def score_item(item):
"""Score a passing item for ranking. Higher = better."""
text = item.get("body", "")
external_score = max(item.get("score", 1), 1) # Floor at 1
# Count keyword matches
keyword_hits = len(_KEYWORD_PATTERN.findall(text))
# Length bonus with diminishing returns (cap at 2x)
length_score = min(len(text) / 300, 2.0)
# Weighted combination
return keyword_hits * 2 + length_score + (external_score ** 0.3)Tuning notes:
- The
** 0.3on external score compresses outliers (a 1000-upvote comment is not 1000x better than a 1-upvote comment) - Adjust the
300divisor based on typical item length in your domain - Keyword hits get the highest weight because domain relevance is the primary signal
Customization Guide
Adapting to a New Domain
- Define your keyword list. Group keywords by sub-category for readability. Aim for 30-100 keywords. Too few = low recall, too many = low precision.
- Define your excluded sources. Known bots, spam accounts, system accounts.
- Define your low-effort patterns. What does a useless item look like in your domain?
- Set MIN_LENGTH. Look at 20 good items and 20 bad items — find the length threshold that separates them.
- Tune scoring weights. Run on 100 items, sort by score, check if the top 10 are actually the best. Adjust weights.
Example Domains
Code review comments:
- Keywords: "refactor", "bug", "performance", "readable", "test", "edge case", "null check"
- Exclude: CI bots, auto-generated comments
- Low effort: "LGTM", "+1", "nit"
Product reviews:
- Keywords: "battery", "screen", "camera", "build quality", "price", "worth", "compared to"
- Exclude: incentivized reviewers, duplicate accounts
- Low effort: "Great product!", "5 stars", single emoji
Research paper relevance:
- Keywords: domain-specific terms from your research area
- Exclude: retracted papers, predatory publishers
- Low effort: abstracts under 100 words
Self-Test Pattern
Always include a self-test at the bottom of your filter module. Define items that should pass and items that should fail, then assert.
if __name__ == "__main__":
test_items = [
{"body": "Nice!", "author": "user1", "score": 5}, # too short
{"body": "Bot output.", "author": "SpamBot", "score": 0}, # excluded source
{"body": "A substantive comment with keyword1 and detailed reasoning about the topic at hand.", "author": "real_user", "score": 15}, # PASS
]
for item in test_items:
result = passes_filter(item)
score = score_item(item) if result else 0
preview = item["body"][:60]
print(f" [{'PASS' if result else 'SKIP'}] (score={score:.1f}) {preview}")
# Assert expected results
assert passes_filter(test_items[2]), "Good item should pass"
assert not passes_filter(test_items[0]), "Short item should fail"
assert not passes_filter(test_items[1]), "Bot should fail"This catches regressions when you add or modify keywords. Run it every time you change the filter.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

