@@ -2274,27 +2274,43 @@ def save_history(h):
22742274 if "quality_metrics" not in st .session_state or st .session_state .quality_metrics_hash != get_config_hash (current_config ):
22752275 with st .spinner ("Calculating coherence metrics..." ):
22762276 # prepare Data for Gensim (C_v)
2277- tokenized_docs = [d .split () for d in docs ]
2277+ # IMPORTANT: tokenise the docs the same way BERTopic's CountVectorizer
2278+ # does (lowercase + the default token pattern: word chars, 2+ length),
2279+ # otherwise the gensim dictionary keeps original case/punctuation
2280+ # (e.g. "Death,") and never matches the cleaned topic words
2281+ # (e.g. "death"), which makes CoherenceModel raise
2282+ # "unable to interpret topic as either a list of tokens or a list of ids".
2283+ _token_pattern = re .compile (r"(?u)\b\w\w+\b" )
2284+ tokenized_docs = [_token_pattern .findall (d .lower ()) for d in docs ]
22782285 dictionary = Dictionary (tokenized_docs )
2279-
2286+ _vocab = dictionary .token2id
2287+
22802288 # Get top 10 words for every active topic (excluding outliers)
22812289 unique_topics = [t for t in set (tm .topics_ ) if t != - 1 ]
22822290 topics_top_words = []
22832291 for t in unique_topics :
22842292 topic_words = tm .get_topic (t )
22852293 # tm.get_topic() can return False or empty for some topics
22862294 if topic_words and topic_words is not False :
2287- words = [word for word , _ in topic_words [:10 ]]
2288- if words : # Only add non-empty word lists
2295+ # split n-grams into their component tokens and keep only
2296+ # tokens that are actually present in the dictionary, so a
2297+ # single OOV / multi-word phrase can't crash the whole metric
2298+ words = []
2299+ for word , _ in topic_words [:10 ]:
2300+ for tok in str (word ).lower ().split ():
2301+ if tok in _vocab and tok not in words :
2302+ words .append (tok )
2303+ # C_v needs at least 2 words to compute co-occurrence
2304+ if len (words ) >= 2 :
22892305 topics_top_words .append (words )
22902306
22912307 # calculate C_v
22922308 if topics_top_words and len (topics_top_words ) > 0 :
22932309 cm = CoherenceModel (
2294- topics = topics_top_words ,
2295- texts = tokenized_docs ,
2296- dictionary = dictionary ,
2297- coherence = 'c_v' ,
2310+ topics = topics_top_words ,
2311+ texts = tokenized_docs ,
2312+ dictionary = dictionary ,
2313+ coherence = 'c_v' ,
22982314 processes = 1
22992315 )
23002316 c_v_score = cm .get_coherence ()
0 commit comments