From 285809d16f99db56b91fc2ff31dc171d784c038e Mon Sep 17 00:00:00 2001 From: Broque Thomas Date: Fri, 8 Aug 2025 13:19:49 -0700 Subject: [PATCH] better matching --- .../matching_engine.cpython-310.pyc | Bin 17148 -> 19134 bytes .../matching_engine.cpython-312.pyc | Bin 29486 -> 29435 bytes core/matching_engine.py | 74 +++++++++++++++--- .../music_database.cpython-312.pyc | Bin 70930 -> 71415 bytes database/music_database.py | 15 +++- 5 files changed, 78 insertions(+), 11 deletions(-) diff --git a/core/__pycache__/matching_engine.cpython-310.pyc b/core/__pycache__/matching_engine.cpython-310.pyc index 25e6e581350b697f422aaa55176a2b38887af304..7a24895d3ee466bab26d1019873d15462a5f7917 100644 GIT binary patch delta 4259 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 delta 2307 zcmZuzYitzP6`nJ@Ua!~t@*3M~jLia(?8OgZJGkH&*&!yiiEuC`E|7pb-Wi)o_vJHV zYOL8B>ZCzwo2tD;N=hx(w0WQ;ZP5N{lr||Uq@;DI+D270Nvfj$h+6eQepVv1=Uh9X ztvb?td(ZQpd(OFM_Km0E*5eS)g+c*^p6`sGJ^uXMrSRXvVGogBdhesx+8`<-jlMA@ z>6zaqMq`cQY9!X&@ezsSGm=!%Pb;?!HQUT3Jy=H+4lvv+PKVctd{s@*N2Fi%LR6i< zOZ+CVPP|ritJ?Ksw7H~r)nE@B+%K-hy5U=;Td^G~oEO_`4#JRlvIb#Ld{R>n`$~1S z4*;AirRvfUGsz-Zv1%P<>qo_n_!r?yX?Oj%J!JRph983^zS$V>-cM3j)v`&|^`wm~ zwz8#)4>B9RjBz%WP|vGTf~wMcjn6^lNv0oQ7!+qVHo=T|VdIG^x7<3OL)$>tm(FFU z4HV6Z=ivi!J@JF?YEmwzms4oH3yLzW6jTQuRjjC^7U7IiWXiJ)%K(a_jwxpp@!Y1* zfg(QK)Ij*pO??Zxe_AaBoWP)Rbg)oqR}=$IrQJ`htyh6wc z;RQSBgcd;$e5njC$W21aPzXC=(hWbMOo3jh2Osl0>Y%a+CxEyVjN>_{=w2s$PFeCu z?-Y{l*LQ~Q2z1|4*&?xLj!CCpavE{`__Cu~D^5fYlT$jyn$s0=d2_>PWX(E4&eyCd z2T?n;s1&ML_vpGp%!w7l%ZgJ)p?u^-DU_JZM^!PhDq(8ocTSYrE-HS0*X{LzV=WIK zYk#EWXlrubFW0m}q%4ch<|eB1{^p);CaJDF=?A|`aPiX`&tNU{{=3E#R2@sa*1Wf^ zg@iZHKlP);{sY4g9vD7&IMLOc7&9~Zw9%eQ8(P-T6Em|0p6pFDi{-8Ng`OpYB*;DR zyW-=m)n(i?Q=+1^Yaxn%Oyp@t1G5(H zV8yQyh^N{Ps#q&-wr%lk=R6z|_3h1_s#gW?ZGTx5yby*c1YkYHp%&Cr0goSIa_#l_ zzz;!^g+VPXwfi9U5_$ae;>(*@6r&Z@;#x->?9z>n0kwXFH~v30cue$m9$7y|(s}if zNgQG|3Wp9dmDW-?E`Hcq*YFTArl;id`~GAEx3QK?=^^pQ&Ul>D=K2gPrR5FW$HF5F z4~uA5L+lhSlc77Q!&k(vt|QTD)|h0F89Xjt=z0hWrBAxv1kXhn5tr|7RWF11``u?F zy!}PM82?a1iN9`*N4VTqDNsB>i}`*z(n8y}h<|La-1$1Oq&9w!R<6(DS)nKW{}IDa zSP-^SIW+VMG_2XQZBby|J!5c5JkhfkE|q@Ua~cA!KZoYDnbp#zLpv4#UKQ`{oLHby zYh=th*PAv^7_MJS+lLoVfvjFem>~O zt8DTXU)lgyu}3BHfVe$StbB&Zc~2sdKol46om{xVnsNuZm)w<0ioaku%^>e-g^{JC z)925S2Tun7r_y+hRXGK#-lU^HG5I#bF9}>QUEgXWeD*mKPwsAkc&W5|M%CrTuvoi> zVVL3b48LaJw2Yub=z32Y8e)>U$nYuw1=P=Ld1VH9B`1`JMv)v!D37;SoY}Ks(<#=E z$^*C|E1$E?sgo00dU7^{e_>1Q`&ah>43^%yzYjLtX63ae`Ix2uV#qLLMbl6(%!$K8 zBk)u4;?S-Ix$#Yw?PF+S2r}@01LTi6QYjRSFytAwFvvN{0|sAa2r<0Q@GAz{ZL&^( pW|IH3U>O64hWrsm`jYVE7y9tF%JQb*`eY(rdpOo#IzPM-{tbU}Q4RnA diff --git a/core/__pycache__/matching_engine.cpython-312.pyc b/core/__pycache__/matching_engine.cpython-312.pyc index c18910f785bb95aed1d57eeb9b2cbc19765fe9e3..d90c8cc655d22674487eae901240855b27ba58b1 100644 GIT binary patch delta 5645 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 delta 5813 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 m>_Kk14@DivcOxA(!9+wf@)`z1I4 diff --git a/core/matching_engine.py b/core/matching_engine.py index ac44bddf..31fd2c98 100644 --- a/core/matching_engine.py +++ b/core/matching_engine.py @@ -134,11 +134,40 @@ class MusicMatchingEngine: return self.normalize_string(cleaned) def similarity_score(self, str1: str, str2: str) -> float: - """Calculates similarity score between two strings.""" + """Calculates similarity score between two strings with enhanced version handling.""" if not str1 or not str2: return 0.0 - return SequenceMatcher(None, str1, str2).ratio() + # Standard similarity + standard_ratio = SequenceMatcher(None, str1, str2).ratio() + + # Enhanced logic: Check if one string is a version of the other + # This handles cases like "Back & forth" vs "Back & forth original mix" + shorter, longer = (str1, str2) if len(str1) <= len(str2) else (str2, str1) + + # If the shorter string is at the start of the longer string + if longer.startswith(shorter): + # Extract the extra content + extra_content = longer[len(shorter):].strip() + + # Check if the extra content looks like version info + version_keywords = [ + 'original mix', 'radio mix', 'club mix', 'extended mix', + 'slowed', 'reverb', 'sped up', 'acoustic', 'remix', 'remaster', + 'live', 'demo', 'instrumental', 'clean', 'explicit', + 'radio edit', 'extended', 'version' + ] + + # Normalize extra content for comparison + extra_normalized = extra_content.lower().strip(' -()[]') + + # If the extra content matches version keywords, boost the similarity + for keyword in version_keywords: + if keyword in extra_normalized: + # High similarity but not perfect (to distinguish from exact matches) + return max(standard_ratio, 0.85) + + return standard_ratio def duration_similarity(self, duration1: int, duration2: int) -> float: """Calculates similarity score based on track duration (in ms).""" @@ -339,16 +368,33 @@ class MusicMatchingEngine: # PRIORITY 2: Try simplified versions, but preserve important version info # Only remove content that's likely to be album names or noise, not version info - # Pattern 1: Remove content after " - " (likely album names) - dash_pattern = r'^([^-]+?)(?:\s*-\s*.+)?$' + # Pattern 1: Intelligently handle content after " - " + # Only remove if it looks like album names, preserve version info like "slowed", "remix", etc. + dash_pattern = r'^([^-]+?)\s*-\s*(.+)$' match = re.search(dash_pattern, original_title.strip()) if match: - dash_title = match.group(1).strip() - if dash_title and len(dash_title) >= 3 and dash_title != original_title: - dash_clean = self.clean_title(dash_title) + title_part = match.group(1).strip() + dash_content = match.group(2).strip().lower() + + # Define version keywords that should be preserved + preserve_keywords = [ + 'slowed', 'reverb', 'sped up', 'speed up', 'spedup', 'slowdown', + 'remix', 'mix', 'edit', 'version', 'remaster', 'acoustic', + 'live', 'demo', 'instrumental', 'radio', 'extended', 'club', + 'original', 'clean', 'explicit', 'mashup', 'bootleg' + ] + + # Check if the dash content contains version keywords + should_preserve = any(keyword in dash_content for keyword in preserve_keywords) + + if not should_preserve and title_part and len(title_part) >= 3: + # This looks like album content, safe to remove + dash_clean = self.clean_title(title_part) if dash_clean and dash_clean not in [self.clean_title(q.split(' ', 1)[1]) for q in queries if ' ' in q]: queries.append(f"{artist} {dash_clean}".strip()) - print(f"🎯 PRIORITY 2: Dash-cleaned query: '{artist} {dash_clean}'") + print(f"🎯 PRIORITY 2: Dash-cleaned query (removed album): '{artist} {dash_clean}'") + elif should_preserve: + print(f"🎯 PRESERVED: Keeping dash content '{dash_content}' as it appears to be version info") # Pattern 2: Only remove parentheses that contain noise (feat, explicit, etc), not version info # Check if parentheses contain version-related keywords before removing @@ -360,8 +406,14 @@ class MusicMatchingEngine: after_paren = paren_match.group(3).strip() # Define what we consider "noise" vs "important version info" - noise_keywords = ['feat', 'ft', 'featuring', 'explicit', 'clean', 'radio edit', 'radio version'] - version_keywords = ['extended', 'live', 'acoustic', 'remix', 'remaster', 'demo', 'instrumental', 'version', 'edit', 'mix'] + noise_keywords = ['feat', 'ft', 'featuring', 'explicit', 'clean'] + # Expanded version keywords to match the dash preserve keywords + version_keywords = [ + 'slowed', 'reverb', 'sped up', 'speed up', 'spedup', 'slowdown', + 'remix', 'mix', 'edit', 'version', 'remaster', 'acoustic', + 'live', 'demo', 'instrumental', 'radio', 'extended', 'club', + 'original', 'mashup', 'bootleg' + ] # Only remove parentheses if they contain noise, not version info is_noise = any(keyword in paren_content for keyword in noise_keywords) @@ -374,6 +426,8 @@ class MusicMatchingEngine: if simple_clean and simple_clean not in [self.clean_title(q.split(' ', 1)[1]) for q in queries if ' ' in q]: queries.append(f"{artist} {simple_clean}".strip()) print(f"🎯 PRIORITY 2: Noise-removed query: '{artist} {simple_clean}'") + elif is_version: + print(f"🎯 PRESERVED: Keeping parentheses content '({paren_content})' as it appears to be version info") # PRIORITY 3: Original query (ONLY if no album was detected or if it's different) original_track_clean = self.clean_title(original_title) diff --git a/database/__pycache__/music_database.cpython-312.pyc b/database/__pycache__/music_database.cpython-312.pyc index 834246cf6f75d5c6cefcdfb7d456584a68481532..755b64179e98f20207fd109a462869991fde43b3 100644 GIT binary patch delta 8826 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 diff --git a/database/music_database.py b/database/music_database.py index b991bd3a..6e4b1051 100644 --- a/database/music_database.py +++ b/database/music_database.py @@ -13,6 +13,14 @@ from pathlib import Path from utils.logging_config import get_logger logger = get_logger("music_database") + +# Import matching engine for enhanced similarity logic +try: + from core.matching_engine import MusicMatchingEngine + _matching_engine = MusicMatchingEngine() +except ImportError: + logger.warning("Could not import MusicMatchingEngine, falling back to basic similarity") + _matching_engine = None # Temporarily enable debug logging for edition matching logger.setLevel(logging.DEBUG) @@ -860,7 +868,8 @@ class MusicDatabase: def _string_similarity(self, s1: str, s2: str) -> float: """ - Calculate simple string similarity using Levenshtein distance. + Calculate string similarity using enhanced matching engine logic if available, + otherwise falls back to Levenshtein distance. Returns value between 0.0 (no similarity) and 1.0 (identical) """ if s1 == s2: @@ -869,6 +878,10 @@ class MusicDatabase: if not s1 or not s2: return 0.0 + # Use enhanced similarity from matching engine if available + if _matching_engine: + return _matching_engine.similarity_score(s1, s2) + # Simple Levenshtein distance implementation len1, len2 = len(s1), len(s2) if len1 < len2: