Skip to content

Commit a22a56a

Browse files
committed
Fix CoherenceModel crash from tokenization mismatch in app2
1 parent ae99e4e commit a22a56a

1 file changed

Lines changed: 24 additions & 8 deletions

File tree

app2.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)