@@ -636,6 +636,23 @@ def predict_aroma(smiles, top_k=8):
636636 return {"available" : False , "note" : "aroma model load ok but prediction failed" , "detail" : str (e )}
637637
638638
639+ def _taste_profile (out ):
640+ """Trained taste heads ranked by probability (descending) — the 'order of
641+ dominance' view. Sour is a small-data indicative head; the deterministic
642+ sour/salty rules remain separate flags (out['sour'], out['salty'])."""
643+ ranked = []
644+ for t in ("sweet" , "bitter" , "umami" ):
645+ v = out .get (t )
646+ if isinstance (v , (int , float )):
647+ ranked .append ({"taste" : t , "probability" : round (float (v ), 3 ), "basis" : "trained" })
648+ sp = out .get ("sour_predicted" )
649+ if isinstance (sp , (int , float )):
650+ ranked .append ({"taste" : "sour" , "probability" : round (float (sp ), 3 ),
651+ "basis" : "trained (indicative)" })
652+ ranked .sort (key = lambda e : e ["probability" ], reverse = True )
653+ return ranked
654+
655+
639656def predict (smiles : str , include_aroma : bool = False ) -> dict :
640657 mol = Chem .MolFromSmiles (smiles )
641658 if mol is None :
@@ -644,6 +661,10 @@ def predict(smiles: str, include_aroma: bool = False) -> dict:
644661 out = {"smiles" : Chem .MolToSmiles (mol )}
645662 for name , clf in sorted (_CLASSIFIERS .items ()):
646663 out [name ] = round (float (clf .predict_proba (x )[0 , 1 ]), 3 )
664+ # Sour trains as a small-data INDICATIVE head, but its boolean stays the rule's
665+ # call below — keep the model probability separately as sour_predicted.
666+ if "sour" in out :
667+ out ["sour_predicted" ] = out .pop ("sour" )
647668 if _INTENSITY is not None :
648669 out ["sweet_intensity" ] = round (float (_INTENSITY .predict (x )[0 ]), 2 )
649670 out .update (_sour (mol ))
@@ -661,6 +682,7 @@ def predict(smiles: str, include_aroma: bool = False) -> dict:
661682 strong = [t for t in ("sweet" , "bitter" , "umami" )
662683 if isinstance (out .get (t ), float ) and out [t ] >= 0.5 ]
663684 out ["multitaste" ] = len (strong ) >= 2
685+ out ["taste_profile" ] = _taste_profile (out )
664686 out ["physchem" ] = physchem (mol )
665687 out ["stability" ] = stability (mol )
666688 out ["chemesthesis" ] = chemesthesis (mol )
0 commit comments