File size: 5,323 Bytes
fec9168 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
"""
LLM-based question generation utilities.
Supports multiple LLM providers for generating natural, lexically consistent questions.
"""
import os
import random
from typing import Dict, List, Optional, Tuple
import json
from .logger import setup_logger
logger = setup_logger(__name__)
class LLMQuestionGenerator:
"""Generate questions using local Llama 3.1 8B Instruct LLM."""
def __init__(
self,
enabled: bool = False,
template_questions: Optional[Dict] = None
):
"""
Initialize LLM question generator.
Args:
enabled: Whether LLM generation is enabled
template_questions: Template questions for fallback
"""
self.enabled = enabled
self.template_questions = template_questions or {}
if not self.enabled:
logger.info("LLM generation disabled, using templates")
return
# TODO: Initialize local Llama 3.1 8B model connection
# This will be implemented based on your local LLM setup
logger.info("LLM generation enabled (local Llama 3.1 8B)")
logger.warning("Local LLM integration not yet implemented, falling back to templates")
def generate_count_questions(
self,
correct_count: int,
categories_present: List[str],
generate_both: bool = True
) -> Dict:
"""
Generate count task questions.
Args:
correct_count: Correct number of unique sounds
categories_present: List of sound categories in the audio
generate_both: Whether to generate both MCQ and open-text
Returns:
Dictionary with mcq_question and/or open_text_question
"""
# TODO: Implement LLM generation when enabled
# For now, always use templates
return self._generate_count_template(correct_count)
def generate_category_questions(
self,
task_type: str,
correct_category: str,
categories_present: List[str],
context: Optional[Dict] = None
) -> Dict:
"""
Generate questions where the answer is a sound category.
Args:
task_type: Type of task (duration, order, volume)
correct_category: Correct answer category
categories_present: All categories in the audio
context: Additional context (e.g., question_type, reference_sound)
Returns:
Dictionary with mcq_question and open_text_question
"""
# TODO: Implement LLM generation when enabled
# For now, always use templates
return self._generate_category_template(task_type, correct_category, context)
def _generate_count_template(self, correct_count: int) -> Dict:
"""Generate count questions from templates."""
mcq_templates = self.template_questions.get("count", {}).get("mcq", [
"What is the number of distinct sound sources in the audio file?",
"How many different types of sounds can be identified in this recording?"
])
open_templates = self.template_questions.get("count", {}).get("open_text", [
"How many distinct sound sources are present in the audio?",
"Count the number of unique sounds in this recording."
])
return {
"mcq_question": random.choice(mcq_templates),
"open_text_question": random.choice(open_templates)
}
def _generate_category_template(
self,
task_type: str,
correct_category: str,
context: Optional[Dict]
) -> Dict:
"""Generate category questions from templates."""
context = context or {}
if task_type == "duration":
q_type = context.get("question_type", "shortest")
mcq_q = f"Which of the following sounds is heard for the {q_type} duration?"
open_q = f"Which sound is heard for the {q_type} duration in the audio?"
elif task_type == "order":
q_subtype = context.get("question_subtype", "first")
if q_subtype == "first":
mcq_q = "Which sound appears first in the audio clip?"
open_q = "What is the first sound you hear in the audio?"
elif q_subtype == "last":
mcq_q = "Which sound appears last in the audio clip?"
open_q = "What is the last sound you hear in the audio?"
elif q_subtype == "after":
ref = context.get("reference_sound", "")
mcq_q = f"Which sound comes after {ref}?"
open_q = f"What sound comes after {ref}?"
else:
ref = context.get("reference_sound", "")
mcq_q = f"Which sound comes before {ref}?"
open_q = f"What sound comes before {ref}?"
else: # volume
q_type = context.get("question_type", "loudest")
mcq_q = f"Which sound is the {q_type} in the audio?"
open_q = f"Identify the {q_type} sound in the audio clip."
return {
"mcq_question": mcq_q,
"open_text_question": open_q
}
|