File size: 5,763 Bytes
f39ba75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# agents/viva_agent.py
"""
Viva Practice Agent - Handles mock interview sessions with state management.
"""
import re
import json

class VivaAgent:
    def __init__(self, gemini_model=None):
        """
        Initializes the agent with the Gemini model.

        Args:
            gemini_model: An instance of the Gemini model client.
        """
        self.model = gemini_model

    def _get_viva_question(self, topic: str, difficulty: str, asked_questions: list, file_context: str) -> str:
        """Calls the Gemini API to generate a single, unique viva question."""
        
        context_source = ""
        if file_context:
            context_source =f"---\nCONTEXT FROM KNOWLEDGE BASE:\n{file_context}\n---" if file_context else ""
        else:
            context_source = f"The question should be about the B.Pharmacy topic: **{topic}**."

        prompt = f"""
You are a "Viva Coach," a professional and encouraging AI examiner for B.Pharmacy students like Gurus from ancient India.
**CRITICAL INSTRUCTION FOR CITATIONS:** When you use information from the KNOWLEDGE BASE CONTEXT, you MUST cite the source at the end of the relevant sentence using the format `[Source: filename, Page: page_number]`.
**Your Task:**
Generate a SINGLE, insightful, open-ended viva question.

**Instructions:**
1.  **Context:** {context_source}
2.  **Difficulty:** The question's difficulty should be **{difficulty}**.
3.  **Avoid Repetition:** DO NOT ask any of these previously asked questions: {json.dumps(asked_questions)}.
4.  **Format:** Return ONLY the question itself. No conversational text, no "Here is your question:", just the question.

Example: "Can you explain the primary mechanism of action for beta-blockers?"
"""
        try:
            response = self.model.generate_content(prompt)
            # Basic cleanup of the response
            return response.text.strip().replace("\"", "")
        except Exception as e:
            print(f"Viva Agent AI Error: {e}")
            return "I'm having trouble thinking of a question right now. Please try again."

    def process_query(self, query: str, file_context: str = "", viva_state: dict = None):
        """
        Processes a query to manage a viva session.

        Args:
            query (str): The user's command (e.g., "start viva", "next question").
            file_context (str): Optional text from an uploaded file to base the viva on.
            viva_state (dict): The current state of the viva session from the user's session.
        
        Returns:
            dict: A dictionary containing the response and updated viva state.
        """
        if not self.model:
            return {
                'message': "πŸ—£οΈ **Viva Coach**\n\nThe examiner is unavailable! The Gemini API key is missing, so I can't conduct a viva. Please configure the API key.",
                'agent_type': 'viva_practice',
                'status': 'error_no_api_key',
                'viva_state': None # No state change
            }

        query = query.lower().strip()
        viva_state = viva_state or {'active': False, 'topic': '', 'asked_questions': [], 'difficulty': 'easy'}

        # --- Command Handling ---

        # Command: END VIVA
        if viva_state['active'] and any(cmd in query for cmd in ["end viva", "stop viva", "exit viva"]):
            message = "Great session! You did well. Keep practicing! πŸ‘\n\nThe viva session has now ended."
            return {'message': message, 'agent_used': 'viva_practice', 'status': 'session_ended', 'viva_state': {'active': False}}

        # Command: START VIVA
        if any(cmd in query for cmd in ["start viva", "begin viva"]):
            topic_match = re.search(r'viva on (.+)', query)
            topic = topic_match.group(1).title() if topic_match else "General Pharmacy"
            
            # Reset state for a new session
            new_state = {'active': True, 'topic': topic, 'asked_questions': [], 'difficulty': 'easy'}
            
            first_question = self._get_viva_question(topic, new_state['difficulty'], [], file_context)
            new_state['asked_questions'].append(first_question)
            
            message = f"Alright, let's begin your viva on **{topic}**! Here is your first question:\n\n**Q1:** {first_question}"
            return {'message': message, 'agent_used': 'viva_practice', 'status': 'session_started', 'viva_state': new_state}
            
        # Command: NEXT QUESTION (only if a session is active)
        if viva_state['active'] and any(cmd in query for cmd in ["next question", "next one", "ask another"]):
            question_number = len(viva_state['asked_questions']) + 1
            # Slightly increase difficulty over time
            if question_number > 5: viva_state['difficulty'] = 'hard'
            elif question_number > 2: viva_state['difficulty'] = 'medium'

            new_question = self._get_viva_question(viva_state['topic'], viva_state['difficulty'], viva_state['asked_questions'], file_context)
            viva_state['asked_questions'].append(new_question)
            
            message = f"Excellent. Here is your next question:\n\n**Q{question_number}:** {new_question}"
            return {'message': message, 'agent_used': 'viva_practice', 'status': 'next_question', 'viva_state': viva_state}

        # Default response if no command is recognized
        message = """πŸ—£οΈ **Viva Coach Ready!**

You can start a session by typing:
* `start viva on [your topic]` (e.g., `start viva on Pharmacokinetics`)
* Or just `start viva` for general questions.

Once started, you can say:
* `next question`
* `end viva`
"""
        return {'message': message, 'agent_type': 'viva_practice', 'status': 'idle', 'viva_state': viva_state}