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
        }