feat: sentence pattern matching per IMPLEMENT_GUIDE
- 68 regex patterns across 6 parameters (fear_state: 21, greed_state: 19, hype_velocity: 5, pub_velocity: 4, pump_score: 8, dump_score: 11) - Each pattern has weight (0.8-1.4) for importance scoring - Patterns cover direct terms, market vernacular, event triggers, technical indicators, on-chain signals, macro, social signals - Pre-compiled for efficiency with score_text_with_patterns() function - score_text_with_patterns(text, param) returns weighted match score - All 46 core NLP tests pass
This commit is contained in:
224
sentiment_engine/src/sentiment_engine/signal/patterns.py
Normal file
224
sentiment_engine/src/sentiment_engine/signal/patterns.py
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
"""
|
||||||
|
Sentence Pattern Matching per IMPLEMENT_GUIDE (spec Section 4.3)
|
||||||
|
|
||||||
|
Provides regex templates for each output parameter with weights.
|
||||||
|
These patterns capture linguistic constructions that strongly indicate
|
||||||
|
each sentiment parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import List, Dict, Tuple
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Pattern:
|
||||||
|
"""Regex pattern with weight and metadata"""
|
||||||
|
pattern: str
|
||||||
|
weight: float
|
||||||
|
param: str # Which parameter this pattern applies to
|
||||||
|
description: str
|
||||||
|
flags: int = re.IGNORECASE
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# FEAR_STATE PATTERNS
|
||||||
|
# ============================================================
|
||||||
|
FEAR_PATTERNS = [
|
||||||
|
# Direct fear declarations (weight 1.0)
|
||||||
|
Pattern(r"\b(?:fear|fearful|scared|terrified|panic|panicked|anxious|anxiety|dread|apprehension|trepidation)\b", 1.0, "fear_state", "Direct fear terms"),
|
||||||
|
Pattern(r"\b(?:afraid\s+(?:of|that)|scared\s+(?:of|that)|worried\s+about)\b", 1.0, "fear_state", "Fear constructions"),
|
||||||
|
|
||||||
|
# Market fear vernacular (weight 1.0)
|
||||||
|
Pattern(r"\b(?:crash|crashing|crashed|crash[-\s]?risk|flash\s+crash|market\s+crash)\b", 1.2, "fear_state", "Crash language"),
|
||||||
|
Pattern(r"\b(?:plunge|plunging|plummet|plummeting|nosedive|freefall|free\s+fall|implode|imploding|implosion)\b", 1.1, "fear_state", "Plunge language"),
|
||||||
|
Pattern(r"\b(?:dump|dumping|dumped|violent\s+dump|massive\s+dump|capitulation|capitulating)\b", 1.1, "fear_state", "Dump/capitulation language"),
|
||||||
|
Pattern(r"\b(?:selloff|sell[-\s]off|selling\s+pressure|heavy\s+selling|panic\s+sell)\b", 1.1, "fear_state", "Selloff language"),
|
||||||
|
Pattern(r"\b(?:bear(?:ish)?|bear\s+market|bearish\s+trend|downtrend|downtrending)\b", 1.0, "fear_state", "Bearish language"),
|
||||||
|
Pattern(r"\b(?:lower\s+(?:high|low)|downside|downside[-\s]?risk)\b", 1.0, "fear_state", "Technical downside"),
|
||||||
|
Pattern(r"\b(?:bleeding|bleeds|hemorrhage|hemorrhaging|carnage|bloodbath|wipeout|wiped\s+out)\b", 1.2, "fear_state", "Violent downside"),
|
||||||
|
Pattern(r"\b(?:liquidation|liquidating|liquidated|margin\s+call|forced\s+liquidation|cascade\s+liquidation)\b", 1.1, "fear_state", "Liquidation language"),
|
||||||
|
Pattern(r"\b(?:rekt|getting\s+rekt|blown\s+up|account\s+blown|margin\s+call)\b", 1.1, "fear_state", "Crypto fear slang"),
|
||||||
|
|
||||||
|
# Event-based fear triggers (weight 1.0)
|
||||||
|
Pattern(r"\b(?:hack|hacked|exploit|exploited|vulnerability|vulnerability|exploited|breach)\b", 1.3, "fear_state", "Security events"),
|
||||||
|
Pattern(r"\b(?:rug\s+pull|rugpull|exit\s+scam|abandoned|developer\s+fled)\b", 1.3, "fear_state", "Rug pull events"),
|
||||||
|
Pattern(r"\b(?:bank\s+run|run\s+on\s+(?:exchange|bank)|withdrawal\s+spike|mass\s+withdrawal|insolvent|insolvency)\b", 1.2, "fear_state", "Solvency events"),
|
||||||
|
Pattern(r"\b(?:regulatory|crackdown|ban|prohibited|sec\s+enforcement|cfdc\s+enforcement|lawsuit|lawsuit|litigation)\b", 1.1, "fear_state", "Regulatory events"),
|
||||||
|
Pattern(r"\b(?:delist|delisting|delisted|removed\s+from\s+exchange)\b", 1.1, "fear_state", "Delisting events"),
|
||||||
|
|
||||||
|
# Technical fear patterns (weight 0.8)
|
||||||
|
Pattern(r"\b(?:death\s+cross|bearish\s+divergence|hidden\s+bearish\s+divergence|resistance\s+(?:held|holds)|rejection\s+at\s+resistance)\b", 0.9, "fear_state", "Technical bearish"),
|
||||||
|
Pattern(r"\b(?:rsi\s+overbought|overbought\s+rsi|macd\s+bearish|macd\s+crossunder)\b", 0.8, "fear_state", "Indicator bearish"),
|
||||||
|
Pattern(r"\b(?:head\s+and\s+shoulders|double\s+top|triple\s+top|rising\s+wedge|bearish\s+pattern)\b", 0.8, "fear_state", "Chart patterns"),
|
||||||
|
|
||||||
|
# Sentiment/emotion indicators
|
||||||
|
Pattern(r"\b(?:fud|fear\s+uncertainty\s+doubt|despair|depression|anger|rage|panic\s+selling|blind\s+panic|herd\s+mentality|lemmings)\b", 1.0, "fear_state", "Fear emotions"),
|
||||||
|
Pattern(r"\b(?:social\s+dominance\s+(?:drop|falling)|mentions\s+falling|interest\s+fading|google\s+trends\s+down|search\s+interest\s+declining)\b", 0.8, "fear_state", "Social fear signals"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# GREED_STATE PATTERNS
|
||||||
|
# ============================================================
|
||||||
|
GREED_PATTERNS = [
|
||||||
|
# Direct greed declarations
|
||||||
|
Pattern(r"\b(?:greed|greedy|greedily|fomo|fear\s+of\s+missing\s+out|fear\s+of\s+missing\s+out)\b", 1.0, "greed_state", "Direct greed terms"),
|
||||||
|
Pattern(r"\b(?:euphoria|optimistic|optimism|bullish\s+sentiment|extreme\s+greed|greed\s+index)\b", 1.0, "greed_state", "Euphoria terms"),
|
||||||
|
|
||||||
|
# Market greed vernacular
|
||||||
|
Pattern(r"\b(?:surge|surging|surged|pump|pumping|pumped|moon|mooning|mooned|to\s+the\s+moon|rally|rallying|rallied)\b", 1.1, "greed_state", "Pump/moon language"),
|
||||||
|
Pattern(r"\b(?:breakout|breakouts|breaking\s+out|bull\s+run|bullish|bullish\s+trend|uptrend|uptrending)\b", 1.1, "greed_state", "Breakout language"),
|
||||||
|
Pattern(r"\b(?:ath|all[-\s]?time\s+high|record\s+high|new\s+high|higher\s+high|higher\s+low)\b", 1.0, "greed_state", "ATH language"),
|
||||||
|
Pattern(r"\b(?:green\s+candle|green\s+candles|ripping|rips|ripped|parabolic|explosive|violent\s+move\s+up)\b", 1.1, "greed_state", "Explosive upside"),
|
||||||
|
Pattern(r"\b(?:buy\s+the\s+dip|buying\s+the\s+dip|dip\s+bought|dca|dollar\s+cost\s+average)\b", 0.9, "greed_state", "Accumulation language"),
|
||||||
|
|
||||||
|
# Inflows/accumulation (in crypto: outflows = bullish)
|
||||||
|
Pattern(r"\b(?:outflow|outflows|net\s+outflow|exchange\s+outflow|capital\s+outflow|institutional\s+outflow)\b", 1.1, "greed_state", "Outflow language"),
|
||||||
|
Pattern(r"\b(?:whale\s+withdrawal|whale\s+withdrawals|large\s+withdrawal|exchange\s+withdrawal\s+to\s+cold)\b", 1.2, "greed_state", "Whale accumulation"),
|
||||||
|
Pattern(r"\b(?:balance\s+decreasing|off\s+exchange|cold\s+storage|whale\s+accumulation|smart\s+money\s+accumulation)\b", 1.1, "greed_state", "Accumulation signals"),
|
||||||
|
|
||||||
|
# Institutional/ETF
|
||||||
|
Pattern(r"\b(?:etf|spot\s+etf|bitcoin\s+etf|ethereum\s+etf|etf\s+approval|etf\s+approved|etf\s+inflow|etf\s+inflows)\b", 1.2, "greed_state", "ETF language"),
|
||||||
|
Pattern(r"\b(?:blackrock|fidelity|vanguard|grayscale|ark\s+invest|institutional|institutional\s+adoption|corporate\s+treasury|microstrategy|tesla)\b", 1.1, "greed_state", "Institutional signals"),
|
||||||
|
|
||||||
|
# Exchange/listing
|
||||||
|
Pattern(r"\b(?:listing|listed|new\s+listing|tier\s*1\s+listing|binance\s+listing|coinbase\s+listing)\b", 1.1, "greed_state", "Listing events"),
|
||||||
|
|
||||||
|
# Technical bullish
|
||||||
|
Pattern(r"\b(?:golden\s+cross|macd\s+crossover|rsi\s+oversold|support\s+(?:held|holds)|bounce|bouncing|reversal|reverses|bottomed|local\s+bottom|macro\s+bottom|capitulation\s+over)\b", 1.0, "greed_state", "Technical bullish"),
|
||||||
|
Pattern(r"\b(?:oversold|oversold\s+rsi|bullish\s+divergence|hidden\s+bullish\s+divergence)\b", 0.9, "greed_state", "Oversold signals"),
|
||||||
|
|
||||||
|
# On-chain bullish
|
||||||
|
Pattern(r"\b(?:staking|staked|staking\s+rewards|validator|delegation|hashrate\s+(?:up|rising)|difficulty\s+(?:up|rising|increasing)|network\s+growth|addresses\s+growing|new\s+addresses|transaction\s+count\s+rising)\b", 0.9, "greed_state", "On-chain bullish"),
|
||||||
|
|
||||||
|
# DeFi/yield
|
||||||
|
Pattern(r"\b(?:yield|apy|apr|high\s+yield|tvl\s+(?:growth|rising)|total\s+value\s+locked|protocol\s+revenue|fees\s+growing|revenue\s+growth|buyback|buybacks|token\s+burn|burns|burning|deflationary|supply\s+decreasing)\b", 0.8, "greed_state", "DeFi/yield signals"),
|
||||||
|
|
||||||
|
# Macro/narrative
|
||||||
|
Pattern(r"\b(?:halving|bitcoin\s+halving|supply\s+shock|supply\s+squeeze|scarcity|inflation\s+hedge|store\s+of\s+value|digital\s+gold|rate\s+cut|rate\s+cuts|fed\s+pivot|liquidity|m2\s+growth|global\s+liquidity|dollar\s+weakness|dxy\s+down|risk\s+on|risk\s+on\s+environment)\b", 0.8, "greed_state", "Macro bullish"),
|
||||||
|
|
||||||
|
# Sentiment/social
|
||||||
|
Pattern(r"\b(?:social\s+dominance|social\s+dominance\s+rising|dominance\s+rising|mentions\s+rising|trending\s+on\s+(?:twitter|reddit)|google\s+trends|search\s+interest|retail\s+fomo|new\s+entrants|onboarding\s+surge)\b", 0.8, "greed_state", "Social bullish signals"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# HYPE_VELOCITY PATTERNS
|
||||||
|
# ============================================================
|
||||||
|
HYPE_PATTERNS = [
|
||||||
|
# Acceleration declarations
|
||||||
|
Pattern(r"\b(?:accelerat(?:ing|ion)|surge|surging|surged|spike|spiking|spiked|explod(?:ing|ed)|rocket(?:ing)?)\b", 1.0, "hype_velocity", "Acceleration terms"),
|
||||||
|
Pattern(r"\b(?:going\s+viral|trending|dominating\s+(?:twitter|reddit|social)|flooding\s+(?:feeds|timelines))\b", 1.2, "hype_velocity", "Viral/hype detection"),
|
||||||
|
Pattern(r"\b(?:massive\s+(?:surge|spike|increase)|unprecedented\s+(?:volume|surge|coverage)|record\s+(?:volume|mentions|coverage))\b", 1.1, "hype_velocity", "Volume surge"),
|
||||||
|
Pattern(r"\b(?:velocity|momentum|acceleration)\s+(?:is\s+)?(?:building|increasing|accelerating|surging)\b", 1.0, "hype_velocity", "Velocity declarations"),
|
||||||
|
Pattern(r"\b(?:time\s+compression|overnight|in\s+hours|in\s+minutes|fast\s+money|quick\s+gains|rapid\s+accumulation)\b", 0.9, "hype_velocity", "Time compression"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# PUB_VELOCITY PATTERNS
|
||||||
|
# ============================================================
|
||||||
|
PUB_PATTERNS = [
|
||||||
|
Pattern(r"\b(?:breaking\s+news|live\s+updates?|developing\s+story|rolling\s+coverage|continuous\s+coverage|real[-\s]?time\s+updates?)\b", 1.1, "pub_velocity", "Breaking news"),
|
||||||
|
Pattern(r"\b(?:number\s+of\s+(?:articles|mentions|posts)\s+(?:has\s+)?(?:surged|spiked|doubled|tripled|increased\s+\d+%))\b", 1.2, "pub_velocity", "Quantified volume surge"),
|
||||||
|
Pattern(r"\b(?:dominating\s+(?:headlines|coverage|feeds)|avalanche\s+of\s+coverage|tidal\s+wave\s+of\s+articles|media\s+flood|press\s+storm)\b", 1.2, "pub_velocity", "Media flood"),
|
||||||
|
Pattern(r"\b(?:trending\s+topic|viral\s+thread|comment\s+storm|social\s+media\s+explosion|firehose|continuous\s+stream)\b", 1.1, "pub_velocity", "Social surge"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# PUMP_SCORE PATTERNS
|
||||||
|
# ============================================================
|
||||||
|
PUMP_PATTERNS = [
|
||||||
|
# Coordination detection
|
||||||
|
Pattern(r"\b(?:we\s+(?:are\s+)?pump|let'?s\s+pump|push\s+it|send\s+it|pump\s+it)\b", 1.4, "pump_score", "Direct coordination"),
|
||||||
|
Pattern(r"\b(?:pump\s+group|pump\s+channel|signal\s+group|signal\s+channel|alpha\s+group|alpha\s+call|call\s+group|discord\s+pump|telegram\s+pump)\b", 1.3, "pump_score", "Coordination channels"),
|
||||||
|
Pattern(r"\b(?:copy\s+pasta|copy[-\s]?paste|template\s+messages?|identical\s+posts?|mass\s+messaging|shill\s+army|paid\s+promotion|sponsored|incentivized|shill(?:ing)?)\b", 1.4, "pump_score", "Template/coordinated messaging"),
|
||||||
|
Pattern(r"\b(?:whale\s+(?:buying|accumulation|accumulating|loading|absorbing|absorption|bid\s+(?:absorption|wall|walls)))\b", 1.2, "pump_score", "Whale accumulation"),
|
||||||
|
|
||||||
|
# Hype-driven surge
|
||||||
|
Pattern(r"\b(?:100x|1000x|10x|moon|to\s+the\s+moon|moon\s+mission|lambo|diamond\s+hands|diamond\s+hodl|rocket|🚀)\b", 1.3, "pump_score", "Extreme multiplier/hype"),
|
||||||
|
Pattern(r"\b(?:influencer|promot(?:ion|ing)|promote|endorse(?:d|ment)?|paid\s+to\s+promote|sponsored|affiliate|incentivized|shill(?:ing)?)\b", 1.3, "pump_score", "Influencer promotion"),
|
||||||
|
|
||||||
|
# Artificial price action
|
||||||
|
Pattern(r"\b(?:parabolic|parabolic\s+move|rocket\s+fuel|mooning|mooning\s+hard|explod(?:ing|ed)\s+upward|surging\s+up|soaring|raging\s+bull|unstoppable\s+momentum|no\s+top\s+in\s+sight|all\s+new\s+highs|vertical|going\s+vertical|straight\s+up)\b", 1.2, "pump_score", "Artificial price action"),
|
||||||
|
Pattern(r"\b(?:wash\s+trading|wash\s+trade|spoofing|spoof|layering|quote\s+stuffing|artificial\s+(?:volume|rally|inflation|pump))\b", 1.3, "pump_score", "Manipulation tactics"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# DUMP_SCORE PATTERNS
|
||||||
|
# ============================================================
|
||||||
|
DUMP_PATTERNS = [
|
||||||
|
# Direct dump declarations
|
||||||
|
Pattern(r"\b(?:dump|dumping|dumped|violent\s+dump|massive\s+dump|capitulation|capitulating|panic\s+sell|panic\s+selling|panic\s+sold)\b", 1.2, "dump_score", "Dump language"),
|
||||||
|
Pattern(r"\b(?:crash|crashing|crashed|flash\s+crash|market\s+crash|free\s+fall|freefall|nose\s+dive|nosedive|plunge|plunging|plummet|implosion|implode|wipeout|wiped\s+out)\b", 1.2, "dump_score", "Crash language"),
|
||||||
|
|
||||||
|
# Bearish technical
|
||||||
|
Pattern(r"\b(?:death\s+cross|macd\s+bearish|macd\s+crossunder|rsi\s+overbought|overbought\s+rsi|rsi\s+rejection|resistance\s+(?:held|holds)|rejection|rejected|rejecting)\b", 1.0, "dump_score", "Technical bearish"),
|
||||||
|
Pattern(r"\b(?:head\s+and\s+shoulders|double\s+top|triple\s+top|rising\s+wedge|bearish\s+pattern|distribution\s+phase|wyckoff\s+distribution)\b", 0.9, "dump_score", "Chart patterns"),
|
||||||
|
|
||||||
|
# On-chain bearish
|
||||||
|
Pattern(r"\b(?:whale\s+selling|whale\s+sells|whale\s+dump|whale\s+dumps|large\s+holder\s+selling|exchange\s+inflow|exchange\s+inflows|balance\s+increasing|on\s+exchange|hot\s+wallet|exchange\s+deposit|deposit\s+spike|whale\s+deposit|large\s+deposit)\b", 1.1, "dump_score", "On-chain bearish"),
|
||||||
|
Pattern(r"\b(?:unstaking|unstaked|unstake|unstakes|withdrawal|withdrawals|mass\s+withdrawal|bank\s+run|run\s+on\s+exchange|solvency\s+concerns|proof\s+of\s+reserves)\b", 1.1, "dump_score", "Unstaking/withdrawal"),
|
||||||
|
|
||||||
|
# DeFi/Protocol issues
|
||||||
|
Pattern(r"\b(?:tvl\s+(?:drop|dropping|crash)|protocol\s+(?:exploit|hack)|smart\s+contract\s+exploit|oracle\s+failure|bad\s+debt|insolvent\s+protocol|undercollateralized\s+vault)\b", 1.2, "dump_score", "DeFi issues"),
|
||||||
|
Pattern(r"\b(?:unlock|unlocks|token\s+unlock|vesting\s+unlock|team\s+unlock|investor\s+unlock|cliff\s+unlock|linear\s+unlock|supply\s+shock|dilution|dilutive)\b", 1.0, "dump_score", "Token unlocks"),
|
||||||
|
|
||||||
|
# Macro risk-off
|
||||||
|
Pattern(r"\b(?:rate\s+hike|rate\s+hikes|fed\s+hawkish|hawkish\s+fed|tightening|qt|quantitative\s+tightening|liquidity\s+(?:drain|crunch)|credit\s+crunch|recession|recession\s+fears|economic\s+slowdown|gdp\s+slowing|inflation\s+high|cpi\s+high|sticky\s+inflation|core\s+inflation)\b", 0.8, "dump_score", "Macro risk-off"),
|
||||||
|
Pattern(r"\b(?:dollar\s+strength|dxy\s+up|dxy\s+rising|risk\s+off|risk\s+off\s+environment|flight\s+to\s+safety|safe\s+haven|treasury\s+yields|yields\s+rising|bond\s+yields|correlation|correlated\s+selloff|broad\s+selloff|market[-\s]wide\s+selloff|contagion|contagion\s+risk|systemic\s+risk|domino\s+effect|spillover)\b", 0.9, "dump_score", "Risk-off signals"),
|
||||||
|
|
||||||
|
# Sentiment
|
||||||
|
Pattern(r"\b(?:fud|fear\s+uncertainty\s+doubt|fear|extreme\s+fear|fear\s+and\s+greed|fear\s+index|capitulation|despair|depression|anger|rage|selling\s+panic|blind\s+panic|herd\s+mentality|herd\s+selling|lemmings|social\s+dominance\s+drop|mentions\s+falling|interest\s+fading|google\s+trends\s+down|search\s+interest\s+declining|retail\s+exodus|users\s+leaving|offboarding|narrative\s+broken|narrative\s+shift|thesis\s+broken|thesis\s+invalidated|disappointment|missed\s+expectations|guidance\s+lowered|warn|warning)\b", 1.0, "dump_score", "Fear/sentiment"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# ALL PATTERNS BY PARAMETER
|
||||||
|
# ============================================================
|
||||||
|
ALL_PATTERNS = {
|
||||||
|
"fear_state": FEAR_PATTERNS,
|
||||||
|
"greed_state": GREED_PATTERNS,
|
||||||
|
"hype_velocity": HYPE_PATTERNS,
|
||||||
|
"pub_velocity": PUB_PATTERNS,
|
||||||
|
"pump_score": PUMP_PATTERNS,
|
||||||
|
"dump_score": DUMP_PATTERNS,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_patterns_for_param(param: str) -> List[Pattern]:
|
||||||
|
"""Get all patterns for a given parameter"""
|
||||||
|
return ALL_PATTERNS.get(param, [])
|
||||||
|
|
||||||
|
|
||||||
|
def compile_all_patterns() -> Dict[str, List[Tuple[re.Pattern, float]]]:
|
||||||
|
"""Compile all patterns for efficient matching"""
|
||||||
|
compiled = {}
|
||||||
|
for param, patterns in ALL_PATTERNS.items():
|
||||||
|
compiled[param] = [(re.compile(p.pattern, p.flags), p.weight) for p in patterns]
|
||||||
|
return compiled
|
||||||
|
|
||||||
|
|
||||||
|
# Pre-compiled patterns for efficiency
|
||||||
|
COMPILED_PATTERNS = compile_all_patterns()
|
||||||
|
|
||||||
|
|
||||||
|
def score_text_with_patterns(text: str, param: str) -> float:
|
||||||
|
"""Score text against patterns for a given parameter"""
|
||||||
|
if param not in COMPILED_PATTERNS:
|
||||||
|
return 0.0
|
||||||
|
|
||||||
|
score = 0.0
|
||||||
|
for pattern, weight in COMPILED_PATTERNS[param]:
|
||||||
|
matches = pattern.findall(text)
|
||||||
|
if matches:
|
||||||
|
# Count unique matches, cap at reasonable number
|
||||||
|
unique_matches = len(set(matches))
|
||||||
|
score += min(unique_matches, 5) * weight
|
||||||
|
|
||||||
|
return score
|
||||||
|
|
||||||
|
|
||||||
|
# Pattern statistics
|
||||||
|
TOTAL_PATTERNS = sum(len(p) for p in ALL_PATTERNS.values())
|
||||||
|
print(f"Loaded {TOTAL_PATTERNS} sentence patterns across 6 parameters:")
|
||||||
|
for param, patterns in ALL_PATTERNS.items():
|
||||||
|
print(f" {param}: {len(patterns)} patterns")
|
||||||
Reference in New Issue
Block a user