ChanceNa commited on
Commit
934f3c5
·
verified ·
1 Parent(s): 04debed

Upload train_bge_v5.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. train_bge_v5.py +1219 -0
train_bge_v5.py ADDED
@@ -0,0 +1,1219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # /// script
2
+ # requires-python = ">=3.10"
3
+ # dependencies = [
4
+ # "sentence-transformers>=3.0.0",
5
+ # "torch",
6
+ # "transformers>=4.40.0",
7
+ # "numpy",
8
+ # "datasets",
9
+ # "accelerate>=1.1.0",
10
+ # ]
11
+ #
12
+ # [tool.uv.sources]
13
+ # torch = [
14
+ # { index = "pytorch-cu124", marker = "sys_platform == 'linux'" },
15
+ # ]
16
+ #
17
+ # [[tool.uv.index]]
18
+ # name = "pytorch-cu124"
19
+ # url = "https://download.pytorch.org/whl/cu124"
20
+ # explicit = true
21
+ # ///
22
+ """
23
+ BGE-large comparison: automotive embedding fine-tuning + evaluation.
24
+
25
+ Fine-tunes BAAI/bge-large-en-v1.5 (335M params) to compare against
26
+ nomic-embed-text-v1.5 (137M) on the same PCAdb subcategory retrieval task.
27
+
28
+ Run on HF: hf jobs uv run --flavor a100-large --timeout 30m --namespace <ns> train_bge.py
29
+ """
30
+
31
+ import json
32
+ import os
33
+ import random
34
+ import sys
35
+ import tempfile
36
+ from pathlib import Path
37
+
38
+ import numpy as np
39
+ from sentence_transformers import InputExample, SentenceTransformer, losses
40
+ from torch.utils.data import DataLoader
41
+
42
+ random.seed(42)
43
+ np.random.seed(42)
44
+
45
+ # ============================================================================
46
+ # BENCHMARK — DO NOT MODIFY
47
+ # 55 concerns (49 real + 1 garbage). This is the fixed evaluation set.
48
+ # ============================================================================
49
+
50
+ BENCHMARK = [
51
+ {"concern": "Replace front brake pads and rotors", "expected_subcategories": ["Brake > Disc Pads and Brake Shoes", "Brake > Drums and Rotors"]},
52
+ {"concern": "Brake pads worn to backing", "expected_subcategories": ["Brake > Disc Pads and Brake Shoes"]},
53
+ {"concern": "Replace front shocks and struts", "expected_subcategories": ["Suspension > Shocks and Struts"]},
54
+ {"concern": "Control arm bushing worn", "expected_subcategories": ["Suspension > Suspension, Springs and Related Components"]},
55
+ {"concern": "Timing chain replacement needed", "expected_subcategories": ["Engine > Valve Train Components"]},
56
+ {"concern": "Serpentine belt cracking", "expected_subcategories": ["Belts and Cooling > Accessory Drive Belt System Components"]},
57
+ {"concern": "Battery dead needs replacement", "expected_subcategories": ["Electrical, Charging and Starting > Battery and Related Components"]},
58
+ {"concern": "Alternator failing low voltage", "expected_subcategories": ["Electrical, Charging and Starting > Alternator / Generator and Related Components"]},
59
+ {"concern": "Fuel pump making noise", "expected_subcategories": ["Air and Fuel Delivery > Fuel Pumps and Related Components"]},
60
+ {"concern": "A/C compressor not engaging", "expected_subcategories": ["HVAC > A/C Clutch and Compressor"]},
61
+ {"concern": "Power steering pump leak", "expected_subcategories": ["Steering > Power Steering Hoses, Pumps, and Related Components"]},
62
+ {"concern": "Spark plugs replacement due", "expected_subcategories": ["Ignition > Secondary Ignition"]},
63
+ {"concern": "Wiper blades streaking", "expected_subcategories": ["Wiper and Washer > Wiper Arm, Blade, and Related Components"]},
64
+ {"concern": "Wheel bearing noise from front", "expected_subcategories": ["Driveline and Axles > Wheel Bearings, Seals, and Related Components"]},
65
+ {"concern": "Synthetic Oil Service due", "expected_subcategories": ["Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
66
+ {"concern": "Power steering flush needed", "expected_subcategories": ["Steering > Power Steering Hoses, Pumps, and Related Components", "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
67
+ {"concern": "Differential service recommended", "expected_subcategories": ["Driveline and Axles > Differential", "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
68
+ {"concern": "Transfer case fluid change", "expected_subcategories": ["Transfer Case > Transfer Case Components", "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
69
+ {"concern": "BRAKE PAD WORN", "expected_subcategories": ["Brake > Disc Pads and Brake Shoes"]},
70
+ {"concern": "AC recharge needed blowing warm", "expected_subcategories": ["HVAC > A/C Clutch and Compressor"]},
71
+ {"concern": "r&r radiator", "expected_subcategories": ["Belts and Cooling > Radiators, Coolers and Related Components"]},
72
+ {"concern": "Vehicle pulls right", "expected_subcategories": ["Suspension > Alignment"]},
73
+ {"concern": "CEL on rough running", "expected_subcategories": ["Ignition > Secondary Ignition"]},
74
+ {"concern": "Mailer oil change", "expected_subcategories": ["Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
75
+ {"concern": "ATF flush", "expected_subcategories": ["Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
76
+ {"concern": "Brak pads worn", "expected_subcategories": ["Brake > Disc Pads and Brake Shoes"]},
77
+ {"concern": "upper mount plate", "expected_subcategories": ["Suspension > Shocks and Struts"]},
78
+ {"concern": "mirror assembly", "expected_subcategories": ["Body > Mirrors"]},
79
+ {"concern": "grinding noise when braking", "expected_subcategories": ["Brake > Disc Pads and Brake Shoes"]},
80
+ {"concern": "car won't start clicking", "expected_subcategories": ["Electrical, Charging and Starting > Starter and Related Components"]},
81
+ {"concern": "clunking over bumps", "expected_subcategories": ["Suspension > Shocks and Struts"]},
82
+ {"concern": "overheating", "expected_subcategories": ["Belts and Cooling > Radiators, Coolers and Related Components"]},
83
+ {"concern": "a/c blowing warm", "expected_subcategories": ["HVAC > A/C Clutch and Compressor"]},
84
+ {"concern": "rotten egg smell", "expected_subcategories": ["Exhaust > Catalytic Converter"]},
85
+ {"concern": "clicking when turning", "expected_subcategories": ["Driveline and Axles > CV Components"]},
86
+ {"concern": "whining when turning", "expected_subcategories": ["Steering > Power Steering Hoses, Pumps, and Related Components"]},
87
+ {"concern": "humming from wheel area", "expected_subcategories": ["Driveline and Axles > Wheel Bearings, Seals, and Related Components"]},
88
+ {"concern": "squealing belt noise", "expected_subcategories": ["Belts and Cooling > Accessory Drive Belt System Components"]},
89
+ {"concern": "oil leak from top of engine", "expected_subcategories": ["Engine > Gaskets and Sealing Systems"]},
90
+ {"concern": "loud exhaust", "expected_subcategories": ["Exhaust > Mufflers"]},
91
+ {"concern": "Replace catalytic converter", "expected_subcategories": ["Exhaust > Catalytic Converter"]},
92
+ {"concern": "CV axle boot torn", "expected_subcategories": ["Driveline and Axles > CV Components", "Driveline and Axles > CV Boots and Related Components"]},
93
+ {"concern": "Cabin air filter replacement", "expected_subcategories": ["HVAC > Filters"]},
94
+ {"concern": "Blower motor not working", "expected_subcategories": ["HVAC > Motors, Core, Case and Related Components"]},
95
+ {"concern": "EGR valve stuck", "expected_subcategories": ["Emission Control > EGR and Related Components"]},
96
+ {"concern": "TPMS light on", "expected_subcategories": ["Tire and Wheel > Sensors"]},
97
+ {"concern": "New tires needed", "expected_subcategories": ["Tire and Wheel > Tire"]},
98
+ {"concern": "Turbo boost leak", "expected_subcategories": ["Air and Fuel Delivery > Turbocharger, Supercharger and Ram Air"]},
99
+ {"concern": "customer wants alignment check", "expected_subcategories": ["Suspension > Alignment"]},
100
+ {"concern": "Complete garbage text 12345 xyz", "expected_subcategories": []},
101
+ ]
102
+
103
+ # ============================================================================
104
+ # === EXPERIMENT ZONE === (modify freely below this line)
105
+ # ============================================================================
106
+
107
+ # -- Hyperparameters --
108
+ BASE_MODEL = "BAAI/bge-large-en-v1.5"
109
+ EPOCHS = 10
110
+ BATCH_SIZE = 64
111
+ LEARNING_RATE = 3e-5
112
+ WARMUP_RATIO = 0.1
113
+ MATRYOSHKA_DIMS = [] # Disabled — dilutes gradient across dims
114
+ GARBAGE_THRESHOLD = 0.3
115
+
116
+ # -- Training Data --
117
+
118
+ KEYWORD_TO_SUBCATEGORIES = [
119
+ # Suspension
120
+ {"keywords": ["shock", "strut", "loaded strut", "quick strut"], "subcategories": ["Suspension > Shocks and Struts"]},
121
+ {"keywords": ["control arm", "ball joint", "sway bar", "stabilizer bar", "stabilizer link", "tie rod", "track bar"], "subcategories": ["Suspension > Suspension, Springs and Related Components"]},
122
+ {"keywords": ["coil spring", "leaf spring", "spring assembly"], "subcategories": ["Suspension > Suspension, Springs and Related Components"]},
123
+ {"keywords": ["alignment", "camber", "caster", "toe"], "subcategories": ["Suspension > Alignment"]},
124
+ # Brake
125
+ {"keywords": ["brake pad", "brake shoe"], "subcategories": ["Brake > Disc Pads and Brake Shoes"]},
126
+ {"keywords": ["brake rotor", "brake drum", "rotor"], "subcategories": ["Brake > Drums and Rotors"]},
127
+ {"keywords": ["brake caliper", "caliper bracket", "brake hose"], "subcategories": ["Brake > Brake Hydraulics"]},
128
+ {"keywords": ["brake fluid", "brake bleed", "brake flush"], "subcategories": ["Brake > Brake System Service", "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
129
+ {"keywords": ["abs system", "abs sensor", "abs module", "abs pump", "abs light", "anti-lock"], "subcategories": ["Brake > ABS Components"]},
130
+ # Engine
131
+ {"keywords": ["valve cover", "head gasket", "intake manifold gasket", "exhaust manifold gasket", "oil pan gasket"], "subcategories": ["Engine > Gaskets and Sealing Systems"]},
132
+ {"keywords": ["timing chain", "timing belt", "camshaft", "crankshaft", "rocker arm", "lifter", "engine valve", "intake valve", "exhaust valve"], "subcategories": ["Engine > Valve Train Components"]},
133
+ {"keywords": ["piston", "engine block", "connecting rod", "main bearing", "cylinder sleeve", "cylinder liner"], "subcategories": ["Engine > Cylinder Block Components"]},
134
+ # Belts and Cooling
135
+ {"keywords": ["serpentine", "drive belt", "belt tensioner", "idler pulley"], "subcategories": ["Belts and Cooling > Accessory Drive Belt System Components"]},
136
+ {"keywords": ["radiator", "radiator hose"], "subcategories": ["Belts and Cooling > Radiators, Coolers and Related Components"]},
137
+ {"keywords": ["coolant", "antifreeze"], "subcategories": ["Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
138
+ {"keywords": ["water pump"], "subcategories": ["Belts and Cooling > Water Pump and Related Components"]},
139
+ {"keywords": ["thermostat"], "subcategories": ["Belts and Cooling > Thermostat and Housing"]},
140
+ {"keywords": ["cooling fan", "fan clutch", "fan motor", "radiator fan"], "subcategories": ["Belts and Cooling > Cooling Fan, Clutch and Motor"]},
141
+ {"keywords": ["coolant hose", "heater hose"], "subcategories": ["Belts and Cooling > Hoses and Pipes"]},
142
+ # Air and Fuel Delivery
143
+ {"keywords": ["fuel pump", "fuel pump assembly", "fuel sender"], "subcategories": ["Air and Fuel Delivery > Fuel Pumps and Related Components"]},
144
+ {"keywords": ["fuel injector", "fuel rail", "throttle body", "throttle"], "subcategories": ["Air and Fuel Delivery > Fuel Injection System and Related Components"]},
145
+ {"keywords": ["air filter", "intake filter"], "subcategories": ["Air and Fuel Delivery > Filters"]},
146
+ {"keywords": ["fuel tank", "fuel filler"], "subcategories": ["Air and Fuel Delivery > Fuel Storage"]},
147
+ {"keywords": ["turbo", "turbocharger", "supercharger", "intercooler", "wastegate", "boost"], "subcategories": ["Air and Fuel Delivery > Turbocharger, Supercharger and Ram Air"]},
148
+ # Electrical
149
+ {"keywords": ["battery", "battery cable", "battery terminal"], "subcategories": ["Electrical, Charging and Starting > Battery and Related Components"]},
150
+ {"keywords": ["alternator", "generator"], "subcategories": ["Electrical, Charging and Starting > Alternator / Generator and Related Components"]},
151
+ {"keywords": ["starter", "starter motor"], "subcategories": ["Electrical, Charging and Starting > Starter and Related Components"]},
152
+ # Emission Control
153
+ {"keywords": ["catalytic converter", "cat converter"], "subcategories": ["Exhaust > Catalytic Converter"]},
154
+ {"keywords": ["oxygen sensor", "o2 sensor"], "subcategories": ["Emission Control > Sensors"]},
155
+ {"keywords": ["egr", "egr valve"], "subcategories": ["Emission Control > EGR and Related Components"]},
156
+ {"keywords": ["evap", "purge valve", "charcoal canister", "vapor canister"], "subcategories": ["Emission Control > Evaporative System"]},
157
+ {"keywords": ["pcv", "pcv valve"], "subcategories": ["Emission Control > Crankcase Ventilation System"]},
158
+ # Exhaust
159
+ {"keywords": ["muffler"], "subcategories": ["Exhaust > Mufflers"]},
160
+ {"keywords": ["exhaust pipe", "exhaust manifold", "flex pipe", "resonator"], "subcategories": ["Exhaust > Exhaust and Tail Pipes", "Exhaust > Exhaust Manifolds"]},
161
+ # Ignition
162
+ {"keywords": ["spark plug"], "subcategories": ["Ignition > Secondary Ignition"]},
163
+ {"keywords": ["ignition coil", "coil pack", "coil on plug"], "subcategories": ["Ignition > Ignition Coil"]},
164
+ {"keywords": ["plug wire", "ignition wire"], "subcategories": ["Ignition > Ignition Wire and Related Components"]},
165
+ {"keywords": ["distributor"], "subcategories": ["Ignition > Distributor and Magneto"]},
166
+ # Steering
167
+ {"keywords": ["power steering pump", "power steering hose", "power steering fluid", "power steering flush", "power steering"], "subcategories": ["Steering > Power Steering Hoses, Pumps, and Related Components", "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
168
+ {"keywords": ["rack and pinion", "steering gear", "steering rack", "inner tie rod", "outer tie rod"], "subcategories": ["Steering > Steering, Gear and Related Components"]},
169
+ {"keywords": ["steering column"], "subcategories": ["Steering > Steering Column"]},
170
+ # Transmission
171
+ {"keywords": ["transmission fluid", "trans fluid", "atf", "transmission flush"], "subcategories": ["Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
172
+ {"keywords": ["clutch", "flywheel", "clutch disc", "pressure plate", "throwout bearing"], "subcategories": ["Transmission > Clutch Plates", "Transmission > Flywheel"]},
173
+ {"keywords": ["torque converter"], "subcategories": ["Transmission > Automatic Transmission Components"]},
174
+ # Driveline
175
+ {"keywords": ["cv axle", "cv joint", "cv boot"], "subcategories": ["Driveline and Axles > CV Components", "Driveline and Axles > CV Boots and Related Components"]},
176
+ {"keywords": ["drive shaft", "u-joint", "universal joint"], "subcategories": ["Driveline and Axles > Drive Shaft"]},
177
+ {"keywords": ["differential", "diff fluid", "diff service"], "subcategories": ["Driveline and Axles > Differential", "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
178
+ {"keywords": ["wheel bearing", "hub bearing", "hub assembly"], "subcategories": ["Driveline and Axles > Wheel Bearings, Seals, and Related Components", "Driveline and Axles > Hubs and Related Components"]},
179
+ # Transfer Case
180
+ {"keywords": ["transfer case"], "subcategories": ["Transfer Case > Transfer Case Components", "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
181
+ # HVAC
182
+ {"keywords": ["a/c compressor", "ac compressor"], "subcategories": ["HVAC > A/C Clutch and Compressor", "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
183
+ {"keywords": ["a/c condenser", "ac condenser", "evaporator"], "subcategories": ["HVAC > A/C Condenser and Evaporator", "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
184
+ {"keywords": ["refrigerant", "freon", "a/c recharge", "ac recharge", "a/c service", "ac service"], "subcategories": ["HVAC > A/C Clutch and Compressor", "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
185
+ {"keywords": ["blower motor", "blower resistor"], "subcategories": ["HVAC > Motors, Core, Case and Related Components"]},
186
+ {"keywords": ["cabin filter", "cabin air filter"], "subcategories": ["HVAC > Filters"]},
187
+ {"keywords": ["heater core"], "subcategories": ["HVAC > Air Heater Components"]},
188
+ # Tire and Wheel
189
+ {"keywords": ["tire", "tyre"], "subcategories": ["Tire and Wheel > Tire"]},
190
+ {"keywords": ["wheel", "rim", "lug nut"], "subcategories": ["Tire and Wheel > Wheel"]},
191
+ {"keywords": ["tpms", "tire pressure sensor"], "subcategories": ["Tire and Wheel > Sensors"]},
192
+ # Wiper and Washer
193
+ {"keywords": ["wiper", "wiper blade"], "subcategories": ["Wiper and Washer > Wiper Arm, Blade, and Related Components"]},
194
+ {"keywords": ["washer fluid", "washer pump", "windshield washer"], "subcategories": ["Wiper and Washer > Windshield Washer and Related Components"]},
195
+ # Oil and Chemicals
196
+ {"keywords": ["oil change", "oil service", "motor oil", "engine oil", "synthetic oil", "oil filter"], "subcategories": ["Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)", "Engine > Filters"]},
197
+ {"keywords": ["brake cleaner", "dielectric grease", "anti-seize", "thread locker", "penetrating oil"], "subcategories": ["Oil, Fluids and Chemicals > Cleaners and Removers", "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
198
+ ]
199
+
200
+ VARIANT_TEMPLATES = [
201
+ "Replace {kw}",
202
+ "R&R {kw}",
203
+ "{kw} replacement",
204
+ "{kw} replacement needed",
205
+ "Install new {kw}",
206
+ "{kw} is bad",
207
+ "{kw} failing",
208
+ "{kw} worn out",
209
+ "{kw} leaking",
210
+ "{kw} noise",
211
+ "needs {kw}",
212
+ "new {kw}",
213
+ "{kw} - replace",
214
+ "Customer states {kw} issue",
215
+ "Check and replace {kw}",
216
+ "Recommend {kw} replacement",
217
+ ]
218
+
219
+ SYMPTOM_VARIANTS = [
220
+ # Brakes — pads/shoes
221
+ {"symptoms": [
222
+ "grinding noise when braking", "squealing when stopping", "brake pedal goes to floor",
223
+ "pulsating brake pedal", "car pulls when braking", "scraping sound when stopping",
224
+ "metal on metal when braking", "grinding from front when stopping",
225
+ "high pitched squeal stopping", "brakes feel spongy",
226
+ ], "subcategories": ["Brake > Disc Pads and Brake Shoes"]},
227
+ # Brakes — rotors/drums
228
+ {"symptoms": [
229
+ "steering wheel shakes when braking", "vibration when stopping",
230
+ "pulsation in pedal at highway speed", "shimmy when braking",
231
+ "warped rotors vibration", "shudder when applying brakes",
232
+ ], "subcategories": ["Brake > Drums and Rotors"]},
233
+ {"symptoms": ["abs light on", "anti-lock brake warning", "abs fault code", "traction control light and abs light"], "subcategories": ["Brake > ABS Components"]},
234
+ # Suspension — shocks/struts (expert-expanded)
235
+ {"symptoms": [
236
+ "clunking over bumps", "vehicle bounces excessively", "nose dives when stopping",
237
+ "rough ride", "bouncy ride", "car keeps bouncing after bumps",
238
+ "thump over speed bumps", "leaking strut", "front end bottoming out",
239
+ "rear sags under load", "knocking over potholes", "harsh ride quality",
240
+ "suspension feels loose", "banging noise hitting bumps",
241
+ "front end clunk", "noise over railroad tracks",
242
+ "bang over bumps", "thud from front end", "knock over rough road",
243
+ "chassis slap over bumps", "double thump speed bumps",
244
+ "front end bangs dips", "rear clunk over bumps", "trunk area thump bumps",
245
+ "rattle over small bumps", "suspension noise over potholes",
246
+ "clunk from front suspension", "rear suspension thump",
247
+ "noise over expansion joints", "knocks on washboard road",
248
+ "clunk over driveway apron", "noise from strut area over bumps",
249
+ ], "subcategories": ["Suspension > Shocks and Struts"]},
250
+ # Suspension — strut mounts (expert-expanded)
251
+ {"symptoms": [
252
+ "upper mount plate", "strut mount noise", "top mount bearing worn",
253
+ "upper strut mount", "mount plate clunking", "popping when turning steering wheel stationary",
254
+ "creaking from top of strut tower", "strut plate bearing",
255
+ "upper strut plate", "mount plate bearing", "strut tower mount",
256
+ "top mount worn", "upper spring seat", "strut top hat",
257
+ "mount plate popping", "bearing plate noise turning",
258
+ "strut mount bearing noisy", "upper mount clunk", "top hat binding",
259
+ "spring seat cracked", "mount bearing seized",
260
+ "pop while steering from strut mount", "front mount plate noise",
261
+ "upper mount separated",
262
+ ], "subcategories": ["Suspension > Shocks and Struts"]},
263
+ # Suspension — alignment (expert-expanded)
264
+ {"symptoms": [
265
+ "vehicle pulls to one side", "uneven tire wear", "steering wheel off center",
266
+ "vehicle pulls right", "vehicle pulls left", "car drifts right",
267
+ "car drifts left", "steering wheel crooked", "feathering on tires",
268
+ "cupping on tires", "car doesn't track straight", "pulls to the right on highway",
269
+ "pulls to right", "drifts right on flat road", "steering pulls",
270
+ "needs alignment pulls", "alignment off pulls right", "tracks right",
271
+ "wanders on highway", "won't hold straight line",
272
+ "off center steering wheel", "lane drift", "darting on highway",
273
+ ], "subcategories": ["Suspension > Alignment"]},
274
+ # Suspension — control arms/bushings (expert-expanded)
275
+ {"symptoms": [
276
+ "clunk when turning", "loose steering feel",
277
+ "control arm bushing worn", "worn control arm bushings",
278
+ "sway bar link rattle", "stabilizer bar noise",
279
+ "ball joint play", "loose front end", "front end clunk turning",
280
+ "bushing cracked", "bushing deteriorated", "lower control arm play",
281
+ "LCA bushing torn", "compliance bushing shot",
282
+ "control arm rear bushing split", "bushing separated",
283
+ "arm bushing excessive movement", "thrust arm bushing cracked",
284
+ "front end looseness low speed", "clunk turning and braking",
285
+ "hydro bushing leaking", "rear compliance bushing torn",
286
+ "FCA bushing worn", "RCA bushing worn",
287
+ ], "subcategories": ["Suspension > Suspension, Springs and Related Components"]},
288
+ # Engine — gaskets
289
+ {"symptoms": ["oil leak from top of engine", "burning oil smell", "oil seeping from valve cover", "wet around intake"], "subcategories": ["Engine > Gaskets and Sealing Systems"]},
290
+ # Engine — timing/valve train (expert-expanded)
291
+ {"symptoms": [
292
+ "rattling on cold start", "timing noise", "engine ticking",
293
+ "timing chain replacement needed", "timing chain stretched",
294
+ "timing chain rattle", "chain slap on startup", "variable valve timing code",
295
+ "cam phaser noise", "vvt solenoid", "engine timing off",
296
+ "chain stretched", "timing chain code", "P0016 cam crank correlation",
297
+ "P0017 cam position", "timing set replacement", "chain guides worn",
298
+ "cold start chain rattle", "chain noise on startup", "chain slack",
299
+ "cam crank out of sync", "correlation fault", "chain tensioner weak",
300
+ "guides broken", "phaser correlation fault",
301
+ "cam timing over retarded", "cam timing over advanced",
302
+ "engine rattles first start", "chain kit recommended",
303
+ "front cover timing repair", "timing chain needed",
304
+ ], "subcategories": ["Engine > Valve Train Components"]},
305
+ # Cooling
306
+ {"symptoms": ["overheating", "temperature gauge high", "coolant on ground", "coolant leak", "steam from hood"], "subcategories": ["Belts and Cooling > Radiators, Coolers and Related Components"]},
307
+ {"symptoms": [
308
+ "squealing belt noise", "belt chirping on startup",
309
+ "serpentine belt cracking", "belt squeal", "chirping from front of engine",
310
+ "belt slipping when wet", "cracked belt", "belt glazed",
311
+ ], "subcategories": ["Belts and Cooling > Accessory Drive Belt System Components"]},
312
+ # Electrical
313
+ {"symptoms": ["car won't start", "clicking when turning key", "no crank", "slow crank", "starter grinds"], "subcategories": ["Electrical, Charging and Starting > Starter and Related Components"]},
314
+ {"symptoms": ["battery light on", "dim headlights", "electrical issues", "charging system warning"], "subcategories": ["Electrical, Charging and Starting > Alternator / Generator and Related Components"]},
315
+ {"symptoms": ["dead battery", "battery keeps dying", "battery won't hold charge", "needs jump every morning"], "subcategories": ["Electrical, Charging and Starting > Battery and Related Components"]},
316
+ # Ignition — CEL/misfire (expert-expanded)
317
+ {"symptoms": [
318
+ "CEL on", "check engine light", "misfire", "rough idle", "rough running",
319
+ "CEL on rough running", "engine misfiring", "stumbles at idle",
320
+ "rough running check engine light", "cylinder misfire code",
321
+ "P0300 random misfire", "P0301 misfire cylinder 1", "hesitation under acceleration",
322
+ "tune up needed", "tune-up", "engine tune up",
323
+ "CEL rough running", "CEL with misfire", "check engine rough idle",
324
+ "MIL on running rough", "SES light rough idle", "CEL P0300",
325
+ "CEL multiple misfire", "engine light on stumbling",
326
+ "CEL on with shaking", "service engine soon rough",
327
+ "misfiring under load", "flashing CEL misfire",
328
+ "sputtering with check engine light", "shaking at idle CEL",
329
+ "rough idle with codes", "stumble and check engine light",
330
+ "P0301", "P0302", "P0303", "P0304",
331
+ "random misfire", "multiple cylinder misfire",
332
+ "bucks and jerks with CEL",
333
+ ], "subcategories": ["Ignition > Secondary Ignition"]},
334
+ # Ignition — spark plugs maintenance (expert-expanded)
335
+ {"symptoms": [
336
+ "spark plugs replacement due", "plugs due for service", "100k spark plug service",
337
+ "plugs due", "spark plug service", "60k plug change",
338
+ "100k plug service", "iridium plugs due", "platinum plugs worn",
339
+ "plug gap too wide", "mileage-based plug replacement", "maintenance plugs",
340
+ "tune up due", "due for plugs per mileage", "recommend spark plugs",
341
+ "plugs worn", "electrodes worn", "plugs original",
342
+ "overdue for spark plugs", "plug service due by maintenance schedule",
343
+ "replace plugs as maintenance",
344
+ ], "subcategories": ["Ignition > Secondary Ignition"]},
345
+ # HVAC — A/C (expert-expanded)
346
+ {"symptoms": [
347
+ "a/c blowing warm", "no cold air", "a/c not working",
348
+ "AC recharge needed blowing warm", "ac not cold enough",
349
+ "ac recharge needed", "a/c weak", "a/c warm on one side",
350
+ "refrigerant low", "ac blows hot", "air conditioning not cooling",
351
+ "AC recharge", "A/C recharge needed", "freon low",
352
+ "134a recharge", "1234yf recharge", "ac charge and check",
353
+ "air not blowing cold", "AC performance check",
354
+ "AC system evacuation and recharge", "AC evac and recharge",
355
+ "low refrigerant", "static pressure low", "recharge and leak test",
356
+ "recover evacuate recharge", "recharge with dye",
357
+ "not cooling at idle", "vent temp high", "AC weak",
358
+ "warm air from vents",
359
+ ], "subcategories": ["HVAC > A/C Clutch and Compressor"]},
360
+ {"symptoms": ["no heat", "heater not working", "heat blows cold", "lukewarm heat", "heater weak"], "subcategories": ["HVAC > Air Heater Components"]},
361
+ # HVAC — blower motor (expert-expanded)
362
+ {"symptoms": [
363
+ "blower motor not working", "no air from vents", "fan not blowing",
364
+ "blower only works on high", "hvac fan stopped", "no air flow from dash",
365
+ "blower resistor", "fan speed not changing", "only high speed works on fan",
366
+ "HVAC fan dead", "cabin fan stopped", "no air movement dash",
367
+ "blower quit working", "heat fan not blowing", "fan motor seized",
368
+ "blower motor intermittent", "no fan from vents", "blower inop",
369
+ "interior fan not working", "no blower on any speed",
370
+ "blower resistor concern", "fan cuts in and out",
371
+ "no airflow from vents", "HVAC blower intermittent",
372
+ ], "subcategories": ["HVAC > Motors, Core, Case and Related Components"]},
373
+ # Exhaust — muffler
374
+ {"symptoms": ["loud exhaust", "exhaust leak", "rumbling underneath", "exhaust drone", "holes in muffler"], "subcategories": ["Exhaust > Mufflers"]},
375
+ # Exhaust — catalytic converter (expert-expanded)
376
+ {"symptoms": [
377
+ "rotten egg smell", "catalytic converter code", "sulfur smell from exhaust",
378
+ "P0420 catalyst efficiency", "P0430 catalyst", "cat efficiency below threshold",
379
+ "rotten egg odor", "exhaust smells like eggs", "failing catalytic converter",
380
+ "egg smell from exhaust", "sulfur odor driving", "rotten smell tailpipe",
381
+ "hydrogen sulfide smell", "cat going bad smell", "stinky exhaust",
382
+ "exhaust smells terrible", "rotten smell after hard acceleration",
383
+ "bad catalyst smell", "converter smell", "strong sulfur exhaust odor",
384
+ "rotten egg smell under load", "sulfur smell after highway drive",
385
+ ], "subcategories": ["Exhaust > Catalytic Converter"]},
386
+ # Steering — power steering (expert-expanded)
387
+ {"symptoms": [
388
+ "whining when turning", "hard to steer", "power steering whine",
389
+ "whining noise turning wheel", "groan when turning steering wheel",
390
+ "steering stiff", "fluid leaking from steering rack",
391
+ "whine at low speed turns", "moaning sound turning",
392
+ "power steering fluid low", "ps pump noise",
393
+ "whine at full lock", "pump noise turning", "moan turning wheel",
394
+ "steering whine low speed", "PS pump whine", "groan turning at idle",
395
+ "howling when steering", "fluid cavitation noise turning",
396
+ "power steering noisy", "steering pump moans",
397
+ "whine when parking", "groan backing out while turning",
398
+ "steering noise cold", "aerated PS fluid", "low PS fluid noise",
399
+ ], "subcategories": ["Steering > Power Steering Hoses, Pumps, and Related Components"]},
400
+ # Driveline — CV
401
+ {"symptoms": ["clicking when turning", "cv clicking", "clicking noise in turns", "cv axle popping"], "subcategories": ["Driveline and Axles > CV Components"]},
402
+ # Driveline — wheel bearings (expert-expanded)
403
+ {"symptoms": [
404
+ "humming from wheel area", "wheel noise at speed", "growling noise from front",
405
+ "humming gets louder with speed", "bearing noise",
406
+ "roaring sound from wheel", "drone changes with steering input",
407
+ "wheel hum goes away turning one direction", "rumble from rear axle area",
408
+ "hub bearing noise", "grinding from front wheel",
409
+ "hum from front wheel", "droning noise road speed", "wheel rumble highway",
410
+ "noise changes turning left right", "growl from hub area",
411
+ "bearing drone 40mph plus", "hum louder faster you go",
412
+ "helicopter noise road speed", "wheel bearing growl",
413
+ "drone from left front", "drone from right front",
414
+ "noise unloads on turns", "hub noise",
415
+ "rumble from corner of vehicle",
416
+ ], "subcategories": ["Driveline and Axles > Wheel Bearings, Seals, and Related Components"]},
417
+ # Body — mirrors
418
+ {"symptoms": [
419
+ "mirror assembly", "mirror replacement", "side mirror broken",
420
+ "mirror glass cracked", "power mirror not working", "mirror folding mechanism",
421
+ "driver side mirror", "passenger mirror", "rear view mirror fell off",
422
+ "mirror turn signal", "blind spot mirror",
423
+ ], "subcategories": ["Body > Mirrors"]},
424
+ # Tire — TPMS (expert-expanded)
425
+ {"symptoms": [
426
+ "TPMS light on", "tire pressure light", "tire pressure warning",
427
+ "tpms sensor", "tire monitor light", "low tire pressure warning",
428
+ "tpms fault", "tire pressure monitoring light",
429
+ "tire light on dash", "TPMS warning", "tire monitor fault",
430
+ "low tire light stays on after fill", "TPMS sensor battery dead",
431
+ "tire pressure indicator", "TPMS relearn needed",
432
+ "tire pressure light flashing", "sensor not detected",
433
+ "tire pressure monitor inop", "tpms service",
434
+ "no sensor signal", "relearn tire sensors", "sensor battery low",
435
+ ], "subcategories": ["Tire and Wheel > Sensors"]},
436
+ # Fluids — ATF (expert-expanded)
437
+ {"symptoms": [
438
+ "ATF flush", "ATF change", "transmission fluid service",
439
+ "trans fluid flush", "automatic transmission fluid",
440
+ "transmission fluid dark", "burnt trans fluid",
441
+ "ATF exchange", "ATF drain and fill", "automatic transmission fluid service",
442
+ "transmission service ATF", "ATF dark needs flush",
443
+ "ATF maintenance", "trans fluid exchange",
444
+ "transmission fluid service due", "CVT fluid service",
445
+ "DSG service", "pan drop and filter", "trans service by mileage",
446
+ "burnt ATF", "fluid discolored", "fluid exchange recommended",
447
+ "service transmission fluid", "trans fluid change",
448
+ ], "subcategories": ["Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
449
+ # Fluids — oil change with marketing prefix
450
+ {"symptoms": [
451
+ "Mailer oil change", "oil change special", "coupon oil change",
452
+ "promo oil change", "mail-in oil change", "oil change deal",
453
+ "customer came in for oil change", "just here for an oil change",
454
+ "routine oil change", "express oil change", "quick lube oil change",
455
+ ], "subcategories": ["Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
456
+ # ====================== EXPANDED TRAINING DATA (v3+) ======================
457
+ # Category 1: Catalytic Converter / Exhaust (expanded)
458
+ {"symptoms": [
459
+ "rotten egg smell from exhaust", "smells like sulfur", "eggs smell when I drive it",
460
+ "bad exhaust smell", "stinks out the tailpipe", "nasty smell coming from exhaust",
461
+ "exhaust smells rich", "exhaust smells burnt", "fumes smell weird",
462
+ "sulfer smell", "sulphur smell", "egg smell from car",
463
+ "cat smell bad", "converter smell", "clogged cat", "plugged cat",
464
+ "stopped up cat", "bad catalytic converter", "cat code stored",
465
+ "P0420 in memory", "P0430 stored", "catalyst efficiency code",
466
+ "bank 1 cat low efficiency", "bank 2 cat low efficiency",
467
+ "failed emissions for cat", "won't get out of its own way",
468
+ "no power uphill and smells", "runs hot and smells funny",
469
+ "glowing cat underneath", "rattle in catalytic converter",
470
+ "something loose in exhaust", "honeycomb busted in cat",
471
+ "cat material broke apart", "exhaust restriction", "restricted exhaust",
472
+ "backpressure high", "muffled exhaust flow", "sounds choked up",
473
+ "tailpipe barely blowing", "smells like burning chemicals",
474
+ "fume smell in cabin", "cat is toast", "cat's smoked",
475
+ "converter stopped up", "catylitic converter bad", "cadillac converter bad",
476
+ "cad converter issue", "cat con bad", "replace front pipe/cat",
477
+ "after cat damaged", "downstream cat code", "upstream cat failure",
478
+ "MIL on for catalyst", "check engine light for cat",
479
+ "exhaust smells like ass", "smells like something died in exhaust",
480
+ "smells like cat pee", "smells like ammonia from exhaust",
481
+ "sounds like marbles in a can",
482
+ ], "subcategories": ["Exhaust > Catalytic Converter"]},
483
+ # Category 2: Starter / No-Start (expanded)
484
+ {"symptoms": [
485
+ "car won't start, just clicks", "single click no start",
486
+ "rapid clicking when turning key", "click click click won't start",
487
+ "no crank no start", "won't crank", "won't turn over",
488
+ "doesn't even try to start", "dead on the lot", "dead in driveway",
489
+ "won't fire up", "starter just spins", "starter freewheels",
490
+ "grinding when starting", "hard start then nothing",
491
+ "intermittent no start", "starts sometimes",
492
+ "have to turn key a few times", "push button does nothing",
493
+ "key on and nothing happens", "dash lights on but no crank",
494
+ "all lights come on but won't start", "battery seems fine but won't start",
495
+ "slow crank", "cranks real slow", "lazy starter", "drags when cranking",
496
+ "long crank then starts", "cranks but won't start",
497
+ "turns over but won't fire", "starter sticking", "solenoid clicking",
498
+ "starter relay maybe", "tap starter and it starts",
499
+ "starts after hitting starter", "hot soak no start",
500
+ "won't start when hot", "starts cold not hot", "starter heat soak",
501
+ "dead spot in starter", "starter hangs up", "locked up starter",
502
+ "starter seized", "starter out", "bad starter motor",
503
+ "needs starter/sol", "starter engagement noise",
504
+ "starter stays engaged", "starter keeps spinning after start",
505
+ "no start concern", "vehicle will not crank",
506
+ "cust states no start", "c/s heard one click",
507
+ "c/s intermittent crank/no crank", "c/s engine won't rotate by key",
508
+ "RO: no crank verified", "RO: starter inop",
509
+ "RO: starter drawing high amps", "starter bad", "strtr bad",
510
+ "n/s condition", "nc/ns",
511
+ ], "subcategories": ["Electrical, Charging and Starting > Starter and Related Components"]},
512
+ # Category 3: Ignition / Check Engine Light (expanded)
513
+ {"symptoms": [
514
+ "check engine light on, running rough", "CEL on", "MIL on",
515
+ "SES light on", "service engine soon light", "engine light came on",
516
+ "check eng lite on", "check motor light", "running rough",
517
+ "rough idle", "idles rough", "shaking at idle", "engine shaking",
518
+ "car is sputtering", "hesitates on takeoff", "stumble on acceleration",
519
+ "bucks when accelerating", "jerks under load", "missing", "has a miss",
520
+ "misfire", "multiple misfire", "cyl 3 misfire",
521
+ "P0300", "P0301", "P0302", "P0303", "P0304",
522
+ "coil code", "bad coil maybe", "spark plugs due",
523
+ "needs tune up", "needs plugs and coils",
524
+ "cuts out going uphill", "breaks up under load",
525
+ "feels like it's dropping a cylinder", "sounds like a Subaru now",
526
+ "flashing check engine light", "CEL blinking", "MIL flashing",
527
+ "loss of power with engine light", "hard start and rough run",
528
+ "runs like crap", "runs like dog shit", "engine chugging",
529
+ "surging at idle", "vibration from engine", "hesitation from stop",
530
+ "popping through intake", "backfiring", "afterfire out exhaust",
531
+ "fuel smell and misfire", "wet plug", "fouled plug",
532
+ "burnt coil boot", "arc mark on coil", "secondary ignition fault",
533
+ "ignition breakdown", "coil pack bad", "coil rail issue",
534
+ "bad plug wire", "spark leak", "engine skips", "skip in engine",
535
+ "rough on cold start", "misfire when wet/raining",
536
+ "starts and stumbles", "won't rev clean",
537
+ "poor acceleration, no codes yet", "customer says needs tune-up",
538
+ "RO: ck eng lt on, misfire felt", "RO: rough run/poor accel",
539
+ "RO: scanned codes p030x", "c/s vehicle shudders at stops",
540
+ "c/s engine hiccups", "it only does it when it rains",
541
+ "sounds like popcorn under the hood",
542
+ ], "subcategories": ["Ignition > Secondary Ignition"]},
543
+ # Category 4: Cooling System / Overheating (expanded)
544
+ {"symptoms": [
545
+ "car is overheating", "running hot", "temp gauge high",
546
+ "temperature climbing", "needle almost in the red", "temp pegged hot",
547
+ "engine got hot", "overheated on freeway", "overheats in traffic",
548
+ "overheats at idle", "overheats with AC on", "steam from hood",
549
+ "smoke from hood but not smoke", "coolant leaking", "antifreeze leak",
550
+ "losing coolant", "have to keep adding coolant", "low coolant light on",
551
+ "coolant smell", "sweet smell from engine bay", "puking coolant",
552
+ "blowing coolant out", "spits coolant out reservoir",
553
+ "overflow bottle boiling", "coolant reservoir empty",
554
+ "reservoir keeps overflowing", "radiator cracked", "radiator leaking",
555
+ "hose blew off", "upper hose rock hard", "coolant all over engine bay",
556
+ "green fluid under car", "orange fluid under car", "pink fluid leaking",
557
+ "cust states engine hot", "c/s overheating concern", "c/s temp light on",
558
+ "check gauges message", "hot coolant warning", "engine over temp message",
559
+ "over temp shut down", "limp mode from overheating",
560
+ "coolant disappearing no visible leak", "pressure test failed",
561
+ "cooling system won't hold pressure", "rad cap bad",
562
+ "bad cap causing boil over", "needs radiator",
563
+ "air pocket in system", "air locked cooling system",
564
+ "boiling over", "hot but then goes back down", "temp fluctuates",
565
+ ], "subcategories": ["Belts and Cooling > Radiators, Coolers and Related Components"]},
566
+ # Category 4b: Cooling — thermostat specific
567
+ {"symptoms": [
568
+ "thermostat stuck", "thermostat not opening",
569
+ "needs thermostat housing", "temp gauge drops on the freeway",
570
+ ], "subcategories": ["Belts and Cooling > Thermostat and Housing"]},
571
+ # Category 4c: Cooling — water pump specific
572
+ {"symptoms": [
573
+ "water pump leaking", "water pump making noise",
574
+ ], "subcategories": ["Belts and Cooling > Water Pump and Related Components"]},
575
+ # Category 4d: Cooling — fan specific
576
+ {"symptoms": [
577
+ "fans not coming on", "cooling fan inop", "fan only works with AC",
578
+ "fan roaring all the time", "fan runs after I shut car off",
579
+ ], "subcategories": ["Belts and Cooling > Cooling Fan, Clutch and Motor"]},
580
+ # Category 4e: Cooling — heater / coolant crossover symptoms
581
+ {"symptoms": [
582
+ "heater blows cold then hot", "no heat and overheating",
583
+ "bubbles in coolant bottle", "gurgling in dash",
584
+ "gurgling in cooling system", "heater quits when gauge goes high",
585
+ "heater only gets hot when I'm driving",
586
+ "smells like syrup in the car",
587
+ ], "subcategories": ["HVAC > Air Heater Components"]},
588
+ # Category 5: Strut Mounts / Upper Mounts (expanded)
589
+ {"symptoms": [
590
+ "upper mount plate worn", "strut mount bad", "top hat bad",
591
+ "top mount bad", "upper strut mount loose", "mount plate noisy",
592
+ "bearing plate bad", "strut bearing noisy",
593
+ "popping from front end", "front end clunk",
594
+ "thunk over speed bumps", "knock from left front",
595
+ "knock from right front", "noise when turning steering wheel",
596
+ "spring bind when turning", "creaks when turning",
597
+ "boing noise from front", "rubber twisting noise",
598
+ "pops backing out of driveway", "clunk when entering driveway",
599
+ "noise at top of strut", "play in upper mount",
600
+ "mount separated", "strut tower noise", "bearing seized in mount",
601
+ "steering notchy at low speed", "spring snaps when steering",
602
+ "front suspension popping", "suspension clunk over rough roads",
603
+ "rattle from strut area", "metal on metal from upper mount",
604
+ "top of strut moving", "mount collapsed", "mount blown out",
605
+ "mount mushroomed", "worn strut hats", "upper isolator bad",
606
+ "strut mount bearing plate", "front coilover mount noise",
607
+ "noise from cowl area over bumps", "sounds like loose shock",
608
+ "sounds like loose suspension bolt",
609
+ "customer says something up top is loose",
610
+ "RO: clunk from upper mounts", "RO: inspect strut mount brg",
611
+ "RO: top plate play noted", "RO: mount brg binding",
612
+ "c/s popping LF over bumps", "c/s front end creak when turning",
613
+ "strt mnt noisy", "upper plate worn", "bearing plate seized",
614
+ "steering snaps back weird after turn",
615
+ ], "subcategories": ["Suspension > Shocks and Struts"]},
616
+ # Category 6: Turbocharger / Boost (new)
617
+ {"symptoms": [
618
+ "turbo boost leak", "no boost", "not making boost",
619
+ "turbo not kicking in", "feels naturally aspirated now",
620
+ "no power till forever", "turbo lag bad", "laggy as hell",
621
+ "boost leak noise", "whooshing under acceleration",
622
+ "air noise when boosting", "hiss under boost", "whistle changed",
623
+ "turbo whining", "siren noise from turbo", "dentist drill noise",
624
+ "wastegate rattle", "rattle on decel from turbo",
625
+ "underboost code", "overboost code", "P0299", "P0234",
626
+ "boost pressure low", "boost too high", "limp mode turbo",
627
+ "goes into limp when I get on it", "reduced power with turbo",
628
+ "charge pipe blew off", "intercooler leak", "split boost hose",
629
+ "CAC leak", "turbo seals leaking", "smokes after boost",
630
+ "burning oil from turbo", "oil in intercooler pipes",
631
+ "shaft play in turbo", "turbo seized", "turbo blown",
632
+ "turbo toast", "bad turbocharger", "waste gate stuck",
633
+ "wastegate actuator bad", "boost solenoid bad",
634
+ "diverter valve issue", "BOV leaking", "surging under boost",
635
+ "cuts out in boost", "won't build boost past 5 psi",
636
+ "overboosting and fuel cuts", "flutter noise", "compressor surge",
637
+ "spools then falls flat", "boost comes and goes",
638
+ "slow spool", "late spool", "whistle then no power",
639
+ "check engine light with turbo code", "epc light with no boost",
640
+ "customer says turbo sounds louder", "customer says turbo quit",
641
+ "RO: verify underboost", "RO: boost leak suspected",
642
+ "RO: turbocharger noisy", "RO: wg rattle noted",
643
+ "turbski bad", "turbski no chooch", "no chooch from turbo",
644
+ "not spooling", "not spoolin", "boost dump noise", "charge air leak",
645
+ "whistles when I accelerate",
646
+ ], "subcategories": ["Air and Fuel Delivery > Turbocharger, Supercharger and Ram Air"]},
647
+ # Category 7: Wheel Alignment (expanded)
648
+ {"symptoms": [
649
+ "customer requests alignment check", "needs alignment",
650
+ "alignment feels off", "pulls left", "pulls right",
651
+ "drifts left", "drifts right", "won't track straight",
652
+ "have to hold steering wheel crooked", "steering wheel off center",
653
+ "wheel is crooked going straight", "steering not centered",
654
+ "dog tracking", "crab walking", "wanders on highway",
655
+ "all over the road", "feels loose on freeway",
656
+ "uneven tire wear", "inside tire wear", "outside tire wear",
657
+ "feathered tires", "cupping on tires",
658
+ "new tires need alignment", "after hitting pothole",
659
+ "after curb hit", "after accident alignment check",
660
+ "after suspension work needs alignment",
661
+ "after tie rod replacement", "after struts needs alignment",
662
+ "after control arm replacement", "shimmy and pull",
663
+ "tracks weird", "veers when braking", "pulls on crowned roads",
664
+ "rear feels like it steers itself",
665
+ "steering wheel not straight after repair",
666
+ "toe looks off", "camber off", "caster issue", "alignment out",
667
+ "front end alignment", "4 wheel alignment", "thrust angle issue",
668
+ "set the toe", "straighten wheel",
669
+ "pulling since I bought tires", "eating tires",
670
+ "chewing up front tires", "wearing out rear tires funny",
671
+ "customer says it don't drive straight",
672
+ "RO: ck/aln", "RO: align after front end work",
673
+ "RO: steer wheel off ctr", "RO: pulls R verify",
674
+ "RO: abnormal tire wear, chk alignment",
675
+ "c/s vehicle drifts", "c/s wheel crooked",
676
+ "needs front end lined up",
677
+ ], "subcategories": ["Suspension > Alignment"]},
678
+ # Category 8: Oil Change / Coupon / Mailer (expanded)
679
+ {"symptoms": [
680
+ "came in with mailer for oil change", "coupon oil change",
681
+ "mailer special oil change", "LOF", "lube oil filter",
682
+ "lube, oil, filter", "oil service", "synthetic service",
683
+ "full syn oil service", "conventional oil service",
684
+ "blend oil change", "express oil change", "quick lube service",
685
+ "basic service special", "maintenance special",
686
+ "5k service", "5000 mile service", "3k service", "7,500 mile service",
687
+ "routine maintenance", "due for service", "service due light on",
688
+ "maintenance light on for oil", "oil life says 15%",
689
+ "oil life monitor on", "change oil soon message",
690
+ "change engine oil message", "oil reset needed",
691
+ "annual oil service", "came in for advertised oil special",
692
+ "internet coupon for oil change", "mail flyer oil special",
693
+ "postcard oil change deal", "seasonal service special",
694
+ "winter service oil change", "first free oil change",
695
+ "complimentary oil change", "prepaid maintenance oil service",
696
+ "works package / oil service", "tire rotation and oil change special",
697
+ "LOF/tire rotate", "oil/filter change", "engine oil and filter",
698
+ "minor service", "A service", "B service with oil",
699
+ "factory maintenance due", "scheduled maintenance",
700
+ "PM service", "preventive maintenance", "pit stop service",
701
+ "customer says just needs fluids and oil",
702
+ "cust here for sticker oil change", "the little light says oil",
703
+ "my oil percentage is low", "needs oil and reset",
704
+ "came in with $29.95 oil coupon", "came in with ValPak oil coupon",
705
+ "came in from postcard offer", "RO: customer requests LOF",
706
+ "RO: perform LOF", "RO: oil svc per coupon",
707
+ "RO: maint light on / oil change",
708
+ "RO: customer here for advertised special",
709
+ ], "subcategories": ["Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)"]},
710
+ # ====================== BONUS: Symptom → Repair Patterns ======================
711
+ # Brake — rotors/pulsation
712
+ {"symptoms": [
713
+ "car shakes when I brake", "vibration when stopping at highway speed",
714
+ "steering wheel shakes when braking at 65",
715
+ ], "subcategories": ["Brake > Drums and Rotors"]},
716
+ # Brake — hydraulics
717
+ {"symptoms": [
718
+ "brake pedal goes to floor", "pedal is hard as a rock",
719
+ "brake pedal spongy",
720
+ ], "subcategories": ["Brake > Brake Hydraulics"]},
721
+ # Brake — stuck caliper
722
+ {"symptoms": [
723
+ "smells hot after driving", "smells like brakes after short drive",
724
+ ], "subcategories": ["Brake > Brake Hydraulics"]},
725
+ # Battery — parasitic draw
726
+ {"symptoms": [
727
+ "battery keeps dying overnight", "radio and dash reboot when I start it",
728
+ ], "subcategories": ["Electrical, Charging and Starting > Battery and Related Components"]},
729
+ # Belt — serpentine off
730
+ {"symptoms": [
731
+ "all the lights came on and steering got hard",
732
+ "chirp chirp chirp from engine", "it sounds supercharged now",
733
+ ], "subcategories": ["Belts and Cooling > Accessory Drive Belt System Components"]},
734
+ # Engine — valve train / detonation
735
+ {"symptoms": [
736
+ "ticking after oil change", "sounds like marbles in a can",
737
+ ], "subcategories": ["Engine > Valve Train Components"]},
738
+ # Engine — mounts
739
+ {"symptoms": [
740
+ "thumps when I stop", "clunk when shifting into drive",
741
+ "shudders taking off",
742
+ ], "subcategories": ["Engine > Engine and Transmission Mounts"]},
743
+ # Exhaust — leak / flex pipe
744
+ {"symptoms": [
745
+ "car sounds louder but only when accelerating",
746
+ "exhaust leak at flex pipe", "loud exhaust and smell",
747
+ "needs exhaust manifold/cat",
748
+ ], "subcategories": ["Exhaust > Exhaust and Tail Pipes"]},
749
+ # Exhaust — heat shield
750
+ {"symptoms": [
751
+ "rattles underneath at idle",
752
+ ], "subcategories": ["Exhaust > Exhaust and Tail Pipes"]},
753
+ # Emission Control — EVAP
754
+ {"symptoms": [
755
+ "gas smell after I fill up", "takes forever to fill gas tank",
756
+ "gas pump keeps clicking off",
757
+ ], "subcategories": ["Emission Control > Evaporative System"]},
758
+ # Driveline — u-joint / lash
759
+ {"symptoms": [
760
+ "thunk when I let off the gas",
761
+ ], "subcategories": ["Driveline and Axles > Drive Shaft"]},
762
+ # Tire — slow leak
763
+ {"symptoms": [
764
+ "one tire keeps going low", "flaps or slaps at highway speed",
765
+ ], "subcategories": ["Tire and Wheel > Tire"]},
766
+ # Tire — balance / vibration
767
+ {"symptoms": [
768
+ "steering wheel shakes at 65", "vibration at highway speed",
769
+ "sounds like an airplane on the highway",
770
+ ], "subcategories": ["Tire and Wheel > Tire"]},
771
+ # Suspension — springs / lean
772
+ {"symptoms": [
773
+ "car leans on one side", "my truck squats in the back",
774
+ "rear end wiggles over bumps",
775
+ ], "subcategories": ["Suspension > Suspension, Springs and Related Components"]},
776
+ # HVAC — blend door actuator
777
+ {"symptoms": [
778
+ "clicking in dash", "no heat on passenger side",
779
+ ], "subcategories": ["HVAC > Motors, Core, Case and Related Components"]},
780
+ # HVAC — water on floor
781
+ {"symptoms": [
782
+ "water on passenger floor", "smoke from the vents",
783
+ ], "subcategories": ["HVAC > A/C Condenser and Evaporator"]},
784
+ # Transfer case
785
+ {"symptoms": [
786
+ "4x4 light flashing",
787
+ ], "subcategories": ["Transfer Case > Transfer Case Components"]},
788
+ # ABS / traction
789
+ {"symptoms": [
790
+ "traction light and ABS light on together",
791
+ ], "subcategories": ["Brake > ABS Components"]},
792
+ # Engine — gaskets / oil smell
793
+ {"symptoms": [
794
+ "can smell oil but no drips", "white smoke only in the morning",
795
+ ], "subcategories": ["Engine > Gaskets and Sealing Systems"]},
796
+ # Air and Fuel — throttle / limp
797
+ {"symptoms": [
798
+ "won't go over 20 mph", "gas pedal does nothing sometimes",
799
+ "engine races at stoplights", "car falls on its face",
800
+ "black smoke when I punch it",
801
+ ], "subcategories": ["Air and Fuel Delivery > Fuel Injection System and Related Components"]},
802
+ ]
803
+
804
+ SYMPTOM_TEMPLATES = [
805
+ "{symptom}",
806
+ "Customer states {symptom}",
807
+ "C/S {symptom}",
808
+ "Complaint: {symptom}",
809
+ "Concern: {symptom}",
810
+ "Vehicle has {symptom}",
811
+ "Car {symptom}",
812
+ "Inspect for {symptom}",
813
+ "Diag for {symptom}",
814
+ "Check {symptom}",
815
+ # Expert-added: DMS/shop shorthand prefixes
816
+ "Cust states {symptom}",
817
+ "States {symptom}",
818
+ "Complains of {symptom}",
819
+ "Chk and advise {symptom}",
820
+ "Check and advise {symptom}",
821
+ "Inspect and advise {symptom}",
822
+ "Found {symptom}",
823
+ "Verified {symptom}",
824
+ "Confirmed {symptom}",
825
+ "Recommend {symptom}",
826
+ "Rec {symptom}",
827
+ "LF {symptom}",
828
+ "RF {symptom}",
829
+ "LR {symptom}",
830
+ "RR {symptom}",
831
+ "Front {symptom}",
832
+ "Rear {symptom}",
833
+ ]
834
+
835
+ COMMON_TYPOS = {
836
+ "brake": ["brak", "brke", "barke"],
837
+ "rotor": ["roter", "rotot"],
838
+ "strut": ["strutt", "strrt"],
839
+ "alternator": ["alternater", "alterntor"],
840
+ "thermostat": ["thermistat", "thermstat", "thermastat"],
841
+ "serpentine": ["serpantine", "serpentene"],
842
+ "catalytic": ["catalitic", "catylitic", "catalyic"],
843
+ "differential": ["differntial", "diferential"],
844
+ "compressor": ["compresser", "compresser"],
845
+ "radiator": ["raditor", "raidator"],
846
+ "transmission": ["transmision", "trnasmission"],
847
+ "steering": ["steerin", "stearing"],
848
+ "exhaust": ["exaust", "exhuast"],
849
+ "alignment": ["alignemnt", "aligment"],
850
+ "battery": ["baterry", "batter"],
851
+ "coolant": ["coolent", "coollant"],
852
+ "muffler": ["mufler", "mufflar"],
853
+ }
854
+
855
+ HARD_NEGATIVES = [
856
+ # --- Original hard negatives ---
857
+ {"query": "replace radiator", "positive": "Belts and Cooling > Radiators, Coolers and Related Components", "negative": "Transmission > Radiators, Coolers and Related Components"},
858
+ {"query": "r&r radiator", "positive": "Belts and Cooling > Radiators, Coolers and Related Components", "negative": "Transmission > Radiators, Coolers and Related Components"},
859
+ {"query": "radiator leaking", "positive": "Belts and Cooling > Radiators, Coolers and Related Components", "negative": "Transmission > Radiators, Coolers and Related Components"},
860
+ {"query": "radiator hose replacement", "positive": "Belts and Cooling > Radiators, Coolers and Related Components", "negative": "Transmission > Radiators, Coolers and Related Components"},
861
+ {"query": "transmission cooler", "positive": "Transmission > Radiators, Coolers and Related Components", "negative": "Belts and Cooling > Radiators, Coolers and Related Components"},
862
+ {"query": "trans cooler line leaking", "positive": "Transmission > Radiators, Coolers and Related Components", "negative": "Belts and Cooling > Radiators, Coolers and Related Components"},
863
+ {"query": "timing chain replacement", "positive": "Engine > Valve Train Components", "negative": "Driveline and Axles > Drive Shaft"},
864
+ {"query": "timing belt worn", "positive": "Engine > Valve Train Components", "negative": "Belts and Cooling > Accessory Drive Belt System Components"},
865
+ {"query": "spark plug replacement", "positive": "Ignition > Secondary Ignition", "negative": "Ignition > Ignition Coil"},
866
+ {"query": "new spark plugs", "positive": "Ignition > Secondary Ignition", "negative": "Ignition > Ignition Coil"},
867
+ {"query": "CEL on rough running", "positive": "Ignition > Secondary Ignition", "negative": "Electrical, Charging and Starting > Battery and Related Components"},
868
+ {"query": "check engine light misfire", "positive": "Ignition > Secondary Ignition", "negative": "Emission Control > Sensors"},
869
+ {"query": "ATF flush", "positive": "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)", "negative": "Transmission > Automatic Transmission Components"},
870
+ {"query": "transmission fluid change", "positive": "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)", "negative": "Transmission > Automatic Transmission Components"},
871
+ {"query": "Mailer oil change", "positive": "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)", "negative": "Engine > Gaskets and Sealing Systems"},
872
+ {"query": "oil change special", "positive": "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)", "negative": "Engine > Gaskets and Sealing Systems"},
873
+ {"query": "clunking over bumps", "positive": "Suspension > Shocks and Struts", "negative": "Brake > Drums and Rotors"},
874
+ {"query": "clunking over bumps", "positive": "Suspension > Shocks and Struts", "negative": "Driveline and Axles > CV Boots and Related Components"},
875
+ {"query": "noise over speed bumps", "positive": "Suspension > Shocks and Struts", "negative": "Transmission > Clutch Plates"},
876
+ {"query": "rotten egg smell", "positive": "Exhaust > Catalytic Converter", "negative": "Engine > Valve Train Components"},
877
+ {"query": "rotten egg smell", "positive": "Exhaust > Catalytic Converter", "negative": "Emission Control > Evaporative System"},
878
+ {"query": "sulfur smell exhaust", "positive": "Exhaust > Catalytic Converter", "negative": "Engine > Gaskets and Sealing Systems"},
879
+ {"query": "whining when turning", "positive": "Steering > Power Steering Hoses, Pumps, and Related Components", "negative": "Emission Control > Crankcase Ventilation System"},
880
+ {"query": "whining when turning", "positive": "Steering > Power Steering Hoses, Pumps, and Related Components", "negative": "Transmission > Flywheel"},
881
+ {"query": "whine turning wheel", "positive": "Steering > Power Steering Hoses, Pumps, and Related Components", "negative": "Emission Control > Sensors"},
882
+ {"query": "humming from wheel area", "positive": "Driveline and Axles > Wheel Bearings, Seals, and Related Components", "negative": "Tire and Wheel > Wheel"},
883
+ {"query": "humming from wheel area", "positive": "Driveline and Axles > Wheel Bearings, Seals, and Related Components", "negative": "Transmission > Flywheel"},
884
+ {"query": "humming gets louder with speed", "positive": "Driveline and Axles > Wheel Bearings, Seals, and Related Components", "negative": "Tire and Wheel > Sensors"},
885
+ {"query": "vehicle pulls right", "positive": "Suspension > Alignment", "negative": "Transmission > Flywheel"},
886
+ {"query": "vehicle pulls right", "positive": "Suspension > Alignment", "negative": "Driveline and Axles > Drive Shaft"},
887
+ {"query": "car drifts right", "positive": "Suspension > Alignment", "negative": "Steering > Steering Column"},
888
+ {"query": "mirror assembly", "positive": "Body > Mirrors", "negative": "Wiper and Washer > Windshield Washer and Related Components"},
889
+ {"query": "mirror assembly", "positive": "Body > Mirrors", "negative": "Wiper and Washer > Wiper Arm, Blade, and Related Components"},
890
+ {"query": "side mirror replacement", "positive": "Body > Mirrors", "negative": "Suspension > Alignment"},
891
+ {"query": "blower motor not working", "positive": "HVAC > Motors, Core, Case and Related Components", "negative": "Exhaust > Catalytic Converter"},
892
+ {"query": "blower motor not working", "positive": "HVAC > Motors, Core, Case and Related Components", "negative": "Emission Control > Crankcase Ventilation System"},
893
+ {"query": "no air from vents", "positive": "HVAC > Motors, Core, Case and Related Components", "negative": "Air and Fuel Delivery > Turbocharger, Supercharger and Ram Air"},
894
+ {"query": "upper mount plate", "positive": "Suspension > Shocks and Struts", "negative": "Transmission > Clutch Plates"},
895
+ {"query": "upper mount plate", "positive": "Suspension > Shocks and Struts", "negative": "Exhaust > Exhaust Manifolds"},
896
+ {"query": "strut mount plate", "positive": "Suspension > Shocks and Struts", "negative": "Suspension > Alignment"},
897
+ {"query": "control arm bushing worn", "positive": "Suspension > Suspension, Springs and Related Components", "negative": "Wiper and Washer > Wiper Arm, Blade, and Related Components"},
898
+ {"query": "control arm bushing worn", "positive": "Suspension > Suspension, Springs and Related Components", "negative": "Emission Control > Crankcase Ventilation System"},
899
+ {"query": "AC recharge needed blowing warm", "positive": "HVAC > A/C Clutch and Compressor", "negative": "Emission Control > Crankcase Ventilation System"},
900
+ {"query": "ac not blowing cold", "positive": "HVAC > A/C Clutch and Compressor", "negative": "Transmission > Radiators, Coolers and Related Components"},
901
+ {"query": "TPMS light on", "positive": "Tire and Wheel > Sensors", "negative": "Ignition > Distributor and Magneto"},
902
+ {"query": "TPMS light on", "positive": "Tire and Wheel > Sensors", "negative": "Driveline and Axles > CV Boots and Related Components"},
903
+ {"query": "tire pressure light on", "positive": "Tire and Wheel > Sensors", "negative": "Driveline and Axles > Wheel Bearings, Seals, and Related Components"},
904
+ # --- Expert-added hard negatives (with corrected PCAdb names) ---
905
+ {"query": "CEL rough running", "positive": "Ignition > Secondary Ignition", "negative": "Emission Control > Sensors"},
906
+ {"query": "CEL rough running", "positive": "Ignition > Secondary Ignition", "negative": "Engine > Valve Train Components"},
907
+ {"query": "CEL rough running", "positive": "Ignition > Secondary Ignition", "negative": "Air and Fuel Delivery > Fuel Pumps and Related Components"},
908
+ {"query": "CEL rough running", "positive": "Ignition > Secondary Ignition", "negative": "Air and Fuel Delivery > Filters"},
909
+ {"query": "Spark plugs replacement due", "positive": "Ignition > Secondary Ignition", "negative": "Ignition > Ignition Coil"},
910
+ {"query": "Spark plugs replacement due", "positive": "Ignition > Secondary Ignition", "negative": "Engine > Valve Train Components"},
911
+ {"query": "Spark plugs replacement due", "positive": "Ignition > Secondary Ignition", "negative": "Air and Fuel Delivery > Fuel Injection System and Related Components"},
912
+ {"query": "AC recharge needed", "positive": "HVAC > A/C Clutch and Compressor", "negative": "HVAC > A/C Condenser and Evaporator"},
913
+ {"query": "AC recharge needed", "positive": "HVAC > A/C Clutch and Compressor", "negative": "HVAC > Motors, Core, Case and Related Components"},
914
+ {"query": "blower not working", "positive": "HVAC > Motors, Core, Case and Related Components", "negative": "HVAC > A/C Clutch and Compressor"},
915
+ {"query": "blower not working", "positive": "HVAC > Motors, Core, Case and Related Components", "negative": "Belts and Cooling > Cooling Fan, Clutch and Motor"},
916
+ {"query": "TPMS light", "positive": "Tire and Wheel > Sensors", "negative": "Tire and Wheel > Tire"},
917
+ {"query": "timing chain needed", "positive": "Engine > Valve Train Components", "negative": "Belts and Cooling > Accessory Drive Belt System Components"},
918
+ {"query": "control arm bushing", "positive": "Suspension > Suspension, Springs and Related Components", "negative": "Suspension > Shocks and Struts"},
919
+ {"query": "control arm bushing", "positive": "Suspension > Suspension, Springs and Related Components", "negative": "Steering > Steering, Gear and Related Components"},
920
+ {"query": "clunking over bumps", "positive": "Suspension > Shocks and Struts", "negative": "Suspension > Suspension, Springs and Related Components"},
921
+ {"query": "clunking over bumps", "positive": "Suspension > Shocks and Struts", "negative": "Steering > Steering, Gear and Related Components"},
922
+ {"query": "clunking over bumps", "positive": "Suspension > Shocks and Struts", "negative": "Brake > Brake Hydraulics"},
923
+ {"query": "vehicle pulls right", "positive": "Suspension > Alignment", "negative": "Tire and Wheel > Tire"},
924
+ {"query": "vehicle pulls right", "positive": "Suspension > Alignment", "negative": "Brake > Brake Hydraulics"},
925
+ {"query": "vehicle pulls right", "positive": "Suspension > Alignment", "negative": "Suspension > Suspension, Springs and Related Components"},
926
+ {"query": "whining when turning", "positive": "Steering > Power Steering Hoses, Pumps, and Related Components", "negative": "Belts and Cooling > Accessory Drive Belt System Components"},
927
+ {"query": "whining when turning", "positive": "Steering > Power Steering Hoses, Pumps, and Related Components", "negative": "Driveline and Axles > CV Components"},
928
+ {"query": "humming from wheel area", "positive": "Driveline and Axles > Wheel Bearings, Seals, and Related Components", "negative": "Tire and Wheel > Tire"},
929
+ {"query": "humming from wheel area", "positive": "Driveline and Axles > Wheel Bearings, Seals, and Related Components", "negative": "Brake > Brake Hydraulics"},
930
+ {"query": "humming from wheel area", "positive": "Driveline and Axles > Wheel Bearings, Seals, and Related Components", "negative": "Driveline and Axles > Differential"},
931
+ # ====================== EXPANDED HARD NEGATIVES (v3+) ======================
932
+ # Catalytic converter — not engine, not evap, not fuel, not muffler
933
+ {"query": "rotten egg smell from exhaust", "positive": "Exhaust > Catalytic Converter", "negative": "Engine > Gaskets and Sealing Systems"},
934
+ {"query": "rotten egg smell from exhaust", "positive": "Exhaust > Catalytic Converter", "negative": "Air and Fuel Delivery > Fuel Pumps and Related Components"},
935
+ {"query": "sulfur smell", "positive": "Exhaust > Catalytic Converter", "negative": "Exhaust > Mufflers"},
936
+ {"query": "P0420 in memory", "positive": "Exhaust > Catalytic Converter", "negative": "Emission Control > Sensors"},
937
+ {"query": "cat code stored", "positive": "Exhaust > Catalytic Converter", "negative": "Emission Control > Evaporative System"},
938
+ {"query": "sounds like marbles in a can", "positive": "Exhaust > Catalytic Converter", "negative": "Engine > Valve Train Components"},
939
+ {"query": "honeycomb busted in cat", "positive": "Exhaust > Catalytic Converter", "negative": "Exhaust > Mufflers"},
940
+ {"query": "restricted exhaust", "positive": "Exhaust > Catalytic Converter", "negative": "Exhaust > Exhaust and Tail Pipes"},
941
+ # Starter — not battery, not alternator, not ignition
942
+ {"query": "car won't start, just clicks", "positive": "Electrical, Charging and Starting > Starter and Related Components", "negative": "Electrical, Charging and Starting > Battery and Related Components"},
943
+ {"query": "rapid clicking when turning key", "positive": "Electrical, Charging and Starting > Starter and Related Components", "negative": "Electrical, Charging and Starting > Alternator / Generator and Related Components"},
944
+ {"query": "tap starter and it starts", "positive": "Electrical, Charging and Starting > Starter and Related Components", "negative": "Ignition > Secondary Ignition"},
945
+ {"query": "hot soak no start", "positive": "Electrical, Charging and Starting > Starter and Related Components", "negative": "Air and Fuel Delivery > Fuel Pumps and Related Components"},
946
+ {"query": "nc/ns", "positive": "Electrical, Charging and Starting > Starter and Related Components", "negative": "Electrical, Charging and Starting > Battery and Related Components"},
947
+ # Ignition / CEL — not sensors, not fuel, not engine mechanical
948
+ {"query": "CEL on", "positive": "Ignition > Secondary Ignition", "negative": "Emission Control > Sensors"},
949
+ {"query": "runs like crap", "positive": "Ignition > Secondary Ignition", "negative": "Air and Fuel Delivery > Fuel Injection System and Related Components"},
950
+ {"query": "engine chugging", "positive": "Ignition > Secondary Ignition", "negative": "Engine > Valve Train Components"},
951
+ {"query": "coil pack bad", "positive": "Ignition > Secondary Ignition", "negative": "Electrical, Charging and Starting > Alternator / Generator and Related Components"},
952
+ {"query": "fouled plug", "positive": "Ignition > Secondary Ignition", "negative": "Air and Fuel Delivery > Filters"},
953
+ {"query": "it only does it when it rains", "positive": "Ignition > Secondary Ignition", "negative": "Belts and Cooling > Accessory Drive Belt System Components"},
954
+ # Overheating — not thermostat, not water pump (primary = radiator category)
955
+ {"query": "overheating", "positive": "Belts and Cooling > Radiators, Coolers and Related Components", "negative": "Belts and Cooling > Thermostat and Housing"},
956
+ {"query": "overheating", "positive": "Belts and Cooling > Radiators, Coolers and Related Components", "negative": "Belts and Cooling > Water Pump and Related Components"},
957
+ {"query": "temp pegged hot", "positive": "Belts and Cooling > Radiators, Coolers and Related Components", "negative": "Engine > Gaskets and Sealing Systems"},
958
+ {"query": "coolant leaking", "positive": "Belts and Cooling > Radiators, Coolers and Related Components", "negative": "Belts and Cooling > Hoses and Pipes"},
959
+ # Strut mounts — not control arms, not steering, not wheel bearings
960
+ {"query": "upper mount plate worn", "positive": "Suspension > Shocks and Struts", "negative": "Suspension > Suspension, Springs and Related Components"},
961
+ {"query": "strut mount bad", "positive": "Suspension > Shocks and Struts", "negative": "Steering > Steering, Gear and Related Components"},
962
+ {"query": "bearing plate bad", "positive": "Suspension > Shocks and Struts", "negative": "Driveline and Axles > Wheel Bearings, Seals, and Related Components"},
963
+ {"query": "mount collapsed", "positive": "Suspension > Shocks and Struts", "negative": "Engine > Engine and Transmission Mounts"},
964
+ {"query": "steering snaps back weird after turn", "positive": "Suspension > Shocks and Struts", "negative": "Steering > Power Steering Hoses, Pumps, and Related Components"},
965
+ # Turbo — not intake filters, not exhaust, not engine
966
+ {"query": "turbo boost leak", "positive": "Air and Fuel Delivery > Turbocharger, Supercharger and Ram Air", "negative": "Air and Fuel Delivery > Filters"},
967
+ {"query": "no boost", "positive": "Air and Fuel Delivery > Turbocharger, Supercharger and Ram Air", "negative": "Air and Fuel Delivery > Fuel Injection System and Related Components"},
968
+ {"query": "P0299", "positive": "Air and Fuel Delivery > Turbocharger, Supercharger and Ram Air", "negative": "Emission Control > Sensors"},
969
+ {"query": "turbo blown", "positive": "Air and Fuel Delivery > Turbocharger, Supercharger and Ram Air", "negative": "Engine > Valve Train Components"},
970
+ {"query": "whistles when I accelerate", "positive": "Air and Fuel Delivery > Turbocharger, Supercharger and Ram Air", "negative": "Belts and Cooling > Accessory Drive Belt System Components"},
971
+ {"query": "charge pipe blew off", "positive": "Air and Fuel Delivery > Turbocharger, Supercharger and Ram Air", "negative": "Belts and Cooling > Hoses and Pipes"},
972
+ # Alignment — not tire, not suspension components, not steering
973
+ {"query": "customer requests alignment check", "positive": "Suspension > Alignment", "negative": "Tire and Wheel > Tire"},
974
+ {"query": "customer requests alignment check", "positive": "Suspension > Alignment", "negative": "Steering > Steering, Gear and Related Components"},
975
+ {"query": "eating tires", "positive": "Suspension > Alignment", "negative": "Tire and Wheel > Tire"},
976
+ {"query": "dog tracking", "positive": "Suspension > Alignment", "negative": "Driveline and Axles > Drive Shaft"},
977
+ {"query": "needs front end lined up", "positive": "Suspension > Alignment", "negative": "Suspension > Suspension, Springs and Related Components"},
978
+ # Oil change / mailer — not engine, not filters
979
+ {"query": "came in with mailer for oil change", "positive": "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)", "negative": "Engine > Gaskets and Sealing Systems"},
980
+ {"query": "LOF", "positive": "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)", "negative": "Engine > Filters"},
981
+ {"query": "maintenance light on for oil", "positive": "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)", "negative": "Electrical, Charging and Starting > Battery and Related Components"},
982
+ {"query": "oil life says 15%", "positive": "Oil, Fluids and Chemicals > Functional Fluid, Lubricant, Grease (including Additives)", "negative": "Engine > Cylinder Block Components"},
983
+ # Bonus cross-category disambiguation
984
+ {"query": "smells like syrup in the car", "positive": "HVAC > Air Heater Components", "negative": "Exhaust > Catalytic Converter"},
985
+ {"query": "all the lights came on and steering got hard", "positive": "Belts and Cooling > Accessory Drive Belt System Components", "negative": "Steering > Power Steering Hoses, Pumps, and Related Components"},
986
+ {"query": "battery keeps dying overnight", "positive": "Electrical, Charging and Starting > Battery and Related Components", "negative": "Electrical, Charging and Starting > Alternator / Generator and Related Components"},
987
+ {"query": "brake pedal goes to floor", "positive": "Brake > Brake Hydraulics", "negative": "Brake > Disc Pads and Brake Shoes"},
988
+ {"query": "gas smell after I fill up", "positive": "Emission Control > Evaporative System", "negative": "Air and Fuel Delivery > Fuel Pumps and Related Components"},
989
+ {"query": "clicking in dash", "positive": "HVAC > Motors, Core, Case and Related Components", "negative": "Electrical, Charging and Starting > Starter and Related Components"},
990
+ {"query": "thumps when I stop", "positive": "Engine > Engine and Transmission Mounts", "negative": "Suspension > Shocks and Struts"},
991
+ {"query": "car leans on one side", "positive": "Suspension > Suspension, Springs and Related Components", "negative": "Suspension > Alignment"},
992
+ {"query": "sounds like an airplane on the highway", "positive": "Driveline and Axles > Wheel Bearings, Seals, and Related Components", "negative": "Tire and Wheel > Tire"},
993
+ {"query": "won't go over 20 mph", "positive": "Air and Fuel Delivery > Fuel Injection System and Related Components", "negative": "Transmission > Automatic Transmission Components"},
994
+ ]
995
+
996
+
997
+ # ============================================================================
998
+ # DATA GENERATION
999
+ # ============================================================================
1000
+
1001
+ def apply_typo(text: str) -> str | None:
1002
+ lower = text.lower()
1003
+ for correct, typos in COMMON_TYPOS.items():
1004
+ if correct in lower:
1005
+ typo = random.choice(typos)
1006
+ return text.replace(correct, typo).replace(correct.capitalize(), typo.capitalize())
1007
+ return None
1008
+
1009
+
1010
+ def generate_training_data() -> tuple[list[dict], list[dict]]:
1011
+ """Generate training pairs and triplets. Returns (positive_pairs, triplets)."""
1012
+ qp = "Represent this sentence for searching relevant passages: "
1013
+ dp = ""
1014
+ positive_pairs = []
1015
+ triplets = []
1016
+
1017
+ # Source 1: keyword → subcategory with variant templates
1018
+ for entry in KEYWORD_TO_SUBCATEGORIES:
1019
+ for kw in entry["keywords"]:
1020
+ for subcat in entry["subcategories"]:
1021
+ for tmpl in VARIANT_TEMPLATES:
1022
+ query = tmpl.format(kw=kw)
1023
+ positive_pairs.append({"query": f"{qp}{query}", "positive": f"{dp}{subcat}"})
1024
+ typo_text = apply_typo(f"Replace {kw}")
1025
+ if typo_text:
1026
+ positive_pairs.append({"query": f"{qp}{typo_text}", "positive": f"{dp}{subcat}"})
1027
+
1028
+ # Source 2: symptom-based with template expansion
1029
+ for entry in SYMPTOM_VARIANTS:
1030
+ for symptom in entry["symptoms"]:
1031
+ for subcat in entry["subcategories"]:
1032
+ for tmpl in SYMPTOM_TEMPLATES:
1033
+ query = tmpl.format(symptom=symptom)
1034
+ positive_pairs.append({"query": f"{qp}{query}", "positive": f"{dp}{subcat}"})
1035
+
1036
+ # Source 3: hard negatives (triplets)
1037
+ for hn in HARD_NEGATIVES:
1038
+ triplets.append({
1039
+ "query": f"{qp}{hn['query']}",
1040
+ "positive": f"{dp}{hn['positive']}",
1041
+ "negative": f"{dp}{hn['negative']}",
1042
+ })
1043
+
1044
+ random.shuffle(positive_pairs)
1045
+ random.shuffle(triplets)
1046
+ return positive_pairs, triplets
1047
+
1048
+
1049
+ # ============================================================================
1050
+ # EVALUATION — DO NOT MODIFY
1051
+ # ============================================================================
1052
+
1053
+ def strip_prefix(text: str) -> str:
1054
+ for prefix in ("Represent this sentence for searching relevant passages: ", "search_query: ", "search_document: "):
1055
+ if text.startswith(prefix):
1056
+ return text[len(prefix):]
1057
+ return text
1058
+
1059
+
1060
+ def evaluate_model(model: SentenceTransformer, corpus_names: list[str]) -> dict:
1061
+ """Run benchmark evaluation. Returns metrics dict."""
1062
+ k_values = [1, 3, 5, 10]
1063
+
1064
+ # BGE: no prefix for documents
1065
+ corpus_texts = [name for name in corpus_names]
1066
+ corpus_embeddings = model.encode(corpus_texts, normalize_embeddings=True, show_progress_bar=False)
1067
+
1068
+ # BGE: instruction prefix for queries
1069
+ query_texts = [f"Represent this sentence for searching relevant passages: {b['concern']}" for b in BENCHMARK]
1070
+ query_embeddings = model.encode(query_texts, normalize_embeddings=True, show_progress_bar=False)
1071
+
1072
+ sim_matrix = np.array(query_embeddings) @ np.array(corpus_embeddings).T
1073
+
1074
+ hits_at_k = {k: 0 for k in k_values}
1075
+ failures = []
1076
+ garbage_correct = 0
1077
+ garbage_total = 0
1078
+
1079
+ for i, case in enumerate(BENCHMARK):
1080
+ expected = set(case["expected_subcategories"])
1081
+ scores = sim_matrix[i]
1082
+ ranked_indices = np.argsort(scores)[::-1]
1083
+
1084
+ if len(expected) == 0:
1085
+ garbage_total += 1
1086
+ top_score = scores[ranked_indices[0]]
1087
+ if top_score < GARBAGE_THRESHOLD:
1088
+ garbage_correct += 1
1089
+ continue
1090
+
1091
+ for k in k_values:
1092
+ top_k_names = {corpus_names[idx] for idx in ranked_indices[:k]}
1093
+ if expected & top_k_names:
1094
+ hits_at_k[k] += 1
1095
+
1096
+ top_5_names = [corpus_names[idx] for idx in ranked_indices[:5]]
1097
+ if not (expected & set(top_5_names)):
1098
+ failures.append(case["concern"])
1099
+
1100
+ n_real = sum(1 for c in BENCHMARK if len(c["expected_subcategories"]) > 0)
1101
+ accuracy = {k: hits_at_k[k] / n_real * 100 for k in k_values}
1102
+
1103
+ return {
1104
+ "hit_at_1": accuracy[1],
1105
+ "hit_at_5": accuracy[5],
1106
+ "hit_at_10": accuracy[10],
1107
+ "garbage_correct": garbage_correct,
1108
+ "garbage_total": garbage_total,
1109
+ "failures": failures,
1110
+ "n_real": n_real,
1111
+ }
1112
+
1113
+
1114
+ # ============================================================================
1115
+ # TRAINING
1116
+ # ============================================================================
1117
+
1118
+ def train():
1119
+ import torch
1120
+ print(f"=== Automotive Embedding Fine-Tuning ===")
1121
+ print(f"CUDA available: {torch.cuda.is_available()}")
1122
+ if torch.cuda.is_available():
1123
+ print(f"GPU: {torch.cuda.get_device_name(0)}")
1124
+ print(f"Base model: {BASE_MODEL}")
1125
+ print(f"Epochs: {EPOCHS}, Batch size: {BATCH_SIZE}, LR: {LEARNING_RATE}")
1126
+ print(f"Matryoshka dims: {MATRYOSHKA_DIMS}")
1127
+ print()
1128
+
1129
+ # Generate data
1130
+ print("Generating training data...")
1131
+ positive_pairs, triplets = generate_training_data()
1132
+ print(f" Positive pairs: {len(positive_pairs)}")
1133
+ print(f" Hard negative triplets: {len(triplets)}")
1134
+
1135
+ # Build corpus for evaluation
1136
+ all_subcats = set()
1137
+ for p in positive_pairs:
1138
+ all_subcats.add(strip_prefix(p["positive"]))
1139
+ for t in triplets:
1140
+ all_subcats.add(strip_prefix(t["positive"]))
1141
+ all_subcats.add(strip_prefix(t["negative"]))
1142
+ corpus_names = sorted(all_subcats)
1143
+ print(f" Corpus size: {len(corpus_names)} subcategories")
1144
+
1145
+ # Load model
1146
+ print(f"\nLoading {BASE_MODEL}...")
1147
+ model = SentenceTransformer(BASE_MODEL)
1148
+
1149
+ # Baseline evaluation
1150
+ print("\n--- Baseline (before training) ---")
1151
+ baseline = evaluate_model(model, corpus_names)
1152
+ print(f" Hit@1={baseline['hit_at_1']:.1f}% Hit@5={baseline['hit_at_5']:.1f}% Hit@10={baseline['hit_at_10']:.1f}%")
1153
+ print(f" Garbage: {baseline['garbage_correct']}/{baseline['garbage_total']}")
1154
+ if baseline["failures"]:
1155
+ print(f" Failures ({len(baseline['failures'])}): {baseline['failures']}")
1156
+
1157
+ # Build training objectives — MNRL (no Matryoshka) + hard negative TripletLoss
1158
+ pos_examples = [InputExample(texts=[p["query"], p["positive"]]) for p in positive_pairs]
1159
+ trip_examples = [InputExample(texts=[t["query"], t["positive"], t["negative"]]) for t in triplets]
1160
+
1161
+ train_objectives = []
1162
+
1163
+ if pos_examples:
1164
+ pos_loader = DataLoader(pos_examples, shuffle=True, batch_size=BATCH_SIZE)
1165
+ mnrl_loss = losses.MultipleNegativesRankingLoss(model)
1166
+ if MATRYOSHKA_DIMS:
1167
+ mnrl_loss = losses.MatryoshkaLoss(model, mnrl_loss, matryoshka_dims=MATRYOSHKA_DIMS)
1168
+ train_objectives.append((pos_loader, mnrl_loss))
1169
+
1170
+ if trip_examples:
1171
+ trip_loader = DataLoader(trip_examples, shuffle=True, batch_size=BATCH_SIZE)
1172
+ triplet_loss = losses.TripletLoss(model)
1173
+ if MATRYOSHKA_DIMS:
1174
+ triplet_loss = losses.MatryoshkaLoss(model, triplet_loss, matryoshka_dims=MATRYOSHKA_DIMS)
1175
+ train_objectives.append((trip_loader, triplet_loss))
1176
+
1177
+ total_steps = sum(len(loader) for loader, _ in train_objectives) * EPOCHS
1178
+ warmup_steps = int(total_steps * WARMUP_RATIO)
1179
+
1180
+ # Train to a temp directory
1181
+ output_dir = tempfile.mkdtemp(prefix="automotive-embed-")
1182
+ print(f"\nTraining ({total_steps} steps, {warmup_steps} warmup)...")
1183
+
1184
+ model.fit(
1185
+ train_objectives=train_objectives,
1186
+ epochs=EPOCHS,
1187
+ warmup_steps=warmup_steps,
1188
+ optimizer_params={"lr": LEARNING_RATE},
1189
+ output_path=output_dir,
1190
+ show_progress_bar=True,
1191
+ )
1192
+
1193
+ # Evaluate the in-memory trained model directly
1194
+ # (Reloading from disk causes _IncompatibleKeys with nomic's custom architecture)
1195
+ print("\n--- Fine-tuned (after training) ---")
1196
+ result = evaluate_model(model, corpus_names)
1197
+ print(f" Hit@1={result['hit_at_1']:.1f}% Hit@5={result['hit_at_5']:.1f}% Hit@10={result['hit_at_10']:.1f}%")
1198
+ print(f" Garbage: {result['garbage_correct']}/{result['garbage_total']}")
1199
+ if result["failures"]:
1200
+ print(f" Failures ({len(result['failures'])}): {result['failures']}")
1201
+
1202
+ # Delta
1203
+ d1 = result["hit_at_1"] - baseline["hit_at_1"]
1204
+ d5 = result["hit_at_5"] - baseline["hit_at_5"]
1205
+ d10 = result["hit_at_10"] - baseline["hit_at_10"]
1206
+ print(f"\n--- Delta ---")
1207
+ print(f" Hit@1: {'+' if d1 >= 0 else ''}{d1:.1f}% Hit@5: {'+' if d5 >= 0 else ''}{d5:.1f}% Hit@10: {'+' if d10 >= 0 else ''}{d10:.1f}%")
1208
+
1209
+ # Parseable result line
1210
+ print(f"\nRESULT: hit@1={result['hit_at_1']:.1f} hit@5={result['hit_at_5']:.1f} hit@10={result['hit_at_10']:.1f} garbage={result['garbage_correct']}/{result['garbage_total']}")
1211
+
1212
+ # Save model path
1213
+ print(f"\nModel saved to: {output_dir}")
1214
+
1215
+ return result
1216
+
1217
+
1218
+ if __name__ == "__main__":
1219
+ train()