mcq / question_generation /option_generator.py
4deffo's picture
Upload folder using huggingface_hub
b96156b verified
Raw
History Blame Contribute Delete
2.48 kB
"""
option_generator.py
Generates the 4-option list for an MCQ.
Changes from original:
- Accepts pos_tag and forwards it to generate_distractors so the
auto_register / cluster routing uses POS for better sub-cluster matching.
- All options (including the answer) are root forms β€” lemmatization has
already happened upstream in process_pipeline.py.
"""
import random
import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from question_generation.cluster_store import generate_distractors
def generate_options(answer_word: str,
sentence_words: list[str],
pos_tags: list[tuple] | None = None,
n: int = 3,
domain: str | None = None,
question: str = "",
context: str = "") -> list[str]:
"""
Return a shuffled list of 4 options (3 distractors + 1 correct answer).
All items are root forms.
Parameters
----------
answer_word : root form of the correct answer
sentence_words : tokenised words from the sentence (used to avoid
accidentally selecting a word already in the question)
pos_tags : list of (word, upos) pairs from Stanza β€” used to look
up the POS of answer_word for better cluster routing
n : number of distractors to generate (default 3)
question : MCQ question string (for keyword-based cluster detection)
context : original sentence (for domain detection)
"""
# Derive POS tag for the answer word from pos_tags list
pos_tag = "NOUN" # safe default
if pos_tags:
pos_lookup = {word: tag for word, tag in pos_tags}
# pos_tags uses surface (inflected) forms; answer_word is root form.
# Try direct match first, then check if any surface form shares the root.
if answer_word in pos_lookup:
pos_tag = pos_lookup[answer_word]
else:
# answer_word is the root; surface form may differ β€” use first NOUN/PROPN
for word, tag in pos_tags:
if tag in ("NOUN", "PROPN"):
pos_tag = tag
break
distractors = generate_distractors(
answer=answer_word,
question=question,
context=context,
k=n,
)
options = distractors[:n] + [answer_word]
random.shuffle(options)
return options