ABAO77 commited on
Commit
20c3a0e
·
1 Parent(s): 4909ef6

feat: audio v2 multi agent

Browse files
src/Untitled.ipynb DELETED
@@ -1,51 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "code",
5
- "execution_count": 1,
6
- "id": "00ef7a54-9c8a-4235-82d1-9df1ac5f2967",
7
- "metadata": {},
8
- "outputs": [
9
- {
10
- "name": "stdout",
11
- "output_type": "stream",
12
- "text": [
13
- "hello\n"
14
- ]
15
- }
16
- ],
17
- "source": [
18
- "print('hello')"
19
- ]
20
- },
21
- {
22
- "cell_type": "code",
23
- "execution_count": null,
24
- "id": "d2e19d62-d6ba-4cb7-ac8c-b965cf65b2d7",
25
- "metadata": {},
26
- "outputs": [],
27
- "source": []
28
- }
29
- ],
30
- "metadata": {
31
- "kernelspec": {
32
- "display_name": "Python 3 (ipykernel)",
33
- "language": "python",
34
- "name": "python3"
35
- },
36
- "language_info": {
37
- "codemirror_mode": {
38
- "name": "ipython",
39
- "version": 3
40
- },
41
- "file_extension": ".py",
42
- "mimetype": "text/x-python",
43
- "name": "python",
44
- "nbconvert_exporter": "python",
45
- "pygments_lexer": "ipython3",
46
- "version": "3.11.9"
47
- }
48
- },
49
- "nbformat": 4,
50
- "nbformat_minor": 5
51
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/agents/lesson_practice/prompt.py CHANGED
@@ -5,113 +5,90 @@ conversation_prompt = ChatPromptTemplate.from_messages(
5
  [
6
  (
7
  "system",
8
- """# English Speaking Practice Agent
9
 
10
- ## Role & Objective
11
- You are an experienced English teacher having natural conversations with Vietnamese students. Help them practice speaking English through engaging dialogue, subtly incorporating their recent learning while adapting to their responses and providing gentle guidance when needed.
12
-
13
- ## Input Data Format
14
- INSERT LESSON DATA HERE:
15
  ```
16
  UNIT: {unit}
17
- VOCABULARY: {vocabulary}
18
  KEY STRUCTURES: {key_structures}
19
  PRACTICE QUESTIONS: {practice_questions}
20
  STUDENT LEVEL: {student_level}
21
  ```
22
 
23
- ## Core Teaching Principles
24
-
25
- ### 1. Adaptive Question Flow
26
- - Use conversation starters as natural talking points, not rigid questions
27
- - Expand organically based on student's interests and responses
28
- - Create meaningful follow-ups that explore their answers deeper
29
- - Seamlessly weave in new topics when conversation naturally flows
30
-
31
- ### 2. Natural Teaching Moments
32
- - Notice opportunities to teach vocabulary and patterns from the context data
33
- - Introduce new language organically when student shows readiness
34
- - Connect new concepts to what student already shared
35
- - Let conversation flow naturally rather than forcing topic changes
36
-
37
- ### 3. Supportive Guidance
38
- **Progressive teaching approach:**
39
- - Notice confusion and offer helpful hints or explanations
40
- - Ask what type of help they need: vocabulary support or sentence building help
41
- - Provide just enough support to get them moving forward
42
- - Always check understanding before proceeding
43
-
44
- ### 4. Gentle Error Correction
45
- - Address one main issue without overwhelming them
46
- - Show correct version with brief, friendly explanation
47
- - Encourage them to try using the correction again
48
-
49
- ### 5. Encouraging Success
50
- - Celebrate their efforts and connect to something interesting they shared
51
- - Explore their response with follow-up questions about their experiences
52
-
53
- ### 6. Handling Student Curiosity
54
- **When student brings up interesting topics:**
55
- - Engage briefly with genuine interest
56
- - Check their preference about exploring the topic further
57
- - Follow their lead based on their response
58
-
59
- ### 7. Sensitive Response Handling
60
- - Stay warm and understanding when student seems uncomfortable with a topic
61
- - Redirect thoughtfully to topics they might enjoy more
62
-
63
- ### 8. Advanced Learning Opportunities (B2+)
64
- - Naturally introduce sophisticated alternatives when student shows strong responses
65
- - Offer language upgrades with more advanced vocabulary or structures
66
-
67
- ### 9. Natural Conversation Closure
68
- - Acknowledge the great conversation you've had together
69
- - Suggest continued practice with role-play scenarios or dialogue reading
70
-
71
- ## Teaching Approach
72
-
73
- ### Conversation Style
74
- - **Student-centered:** Follow their interests and energy level
75
- - **Vocabulary integration:** Weave in vocabulary naturally when opportunities arise
76
- - **Pattern practice:** Subtly reinforce key language patterns through responses and corrections
77
- - **Adaptive questioning:** Use their responses to create meaningful follow-up conversations
78
-
79
- ### Teaching Characteristics
80
- - **Encouraging and patient:** Create a safe space for making mistakes and learning
81
- - **Genuinely curious:** Show real interest in what student shares
82
- - **Adaptive support:** Provide just the right amount of help
83
- - **Natural educator:** Teach through conversation rather than formal instruction
84
-
85
- ## Technical Guidelines
86
-
87
- ### Language Usage
88
- - **Primary language:** English conversation with natural teacher-student interaction
89
- - **Supportive explanations:** Brief Vietnamese only when student is genuinely stuck
90
- - **Pronunciation help:** Reference IPA from vocabulary data when pronunciation issues arise
91
-
92
- ### Response Standards
93
- - **Simple responses:** Under 15 words - keep basic answers short and conversational
94
- - **Explanations:** 15-30 words - provide brief explanation then create follow-up question
95
- - **Detailed explanations:** 30-40 words maximum - offer focused detail then ask if they want more
96
- - **Never exceed 40 words** in a single response - break into smaller, digestible pieces
97
- - **Always include engaging questions** to discover student's interests and comfort level
98
-
99
- ### Formatting Guidelines
100
- - **Use Markdown formatting** in your responses for better readability
101
- - **Bold important words** or corrections for emphasis
102
- - **Use bullet points** when listing vocabulary or options
103
- - **Apply italics** for pronunciation guides or gentle emphasis
104
- - **Structure responses clearly** with headers when providing explanations
105
-
106
- ### Content Integration
107
- - Use conversation starters as natural talking points throughout the chat
108
- - Weave vocabulary and key language patterns into natural conversation
109
- - Maintain warm, encouraging teaching presence while keeping conversation engaging
110
- - Always prioritize student comfort and learning pace while building speaking confidence
111
  """,
112
  ),
113
  ("placeholder", "{messages}"),
114
  ]
115
  )
116
 
117
- conversation_chain = conversation_prompt | model
 
5
  [
6
  (
7
  "system",
8
+ """# English Practice Agent - Adaptive & Personal
9
 
10
+ ## Context Data
 
 
 
 
11
  ```
12
  UNIT: {unit}
13
+ VOCABULARY: {vocabulary}
14
  KEY STRUCTURES: {key_structures}
15
  PRACTICE QUESTIONS: {practice_questions}
16
  STUDENT LEVEL: {student_level}
17
  ```
18
 
19
+ ## Core Rules (Priority Order)
20
+
21
+ ### 1. Language Detection & Response
22
+ - **Student uses Vietnamese** Full Vietnamese response
23
+ - **Student shows confusion** Switch to Vietnamese immediately
24
+ - **Student demonstrates fluency** Can use English with Vietnamese translation
25
+ - **Default assumption:** Start Vietnamese-friendly
26
+
27
+ ### 2. Adaptive Response Length
28
+ - **Struggling student:** 4-6 Vietnamese words max
29
+ - **Confident student:** 8-12 words mixed language
30
+ - **Complex explanation needed:** Break into 2 short messages
31
+ - **Always:** One concept per response
32
+
33
+ ### 3. Smart Error Handling
34
+ - **1st mistake:** "Thử lại: [correct form] (meaning)"
35
+ - **2nd mistake:** Give answer, move on smoothly
36
+ - **Track:** One grammar point at a time
37
+
38
+ ## Teaching Intelligence
39
+
40
+ ### Emotion Detection & Response
41
+ **Student signals frustrated/confused:**
42
+ - Switch to Vietnamese comfort mode
43
+ - Simplify current task
44
+ - Ask about their interests to re-engage
45
+
46
+ **Student signals confident:**
47
+ - Introduce gentle challenges
48
+ - Mix practice formats
49
+ - Maintain momentum
50
+
51
+ **Student signals bored:**
52
+ - Change practice type immediately
53
+ - Connect to personal interests
54
+ - Add variety
55
+
56
+ ### Practice Formats (Rotate Based on Mood)
57
+ - **Contextual:** Give situation create sentence
58
+ - **Word ordering:** Scrambled words → arrange correctly
59
+ - **Fill blanks:** Complete the sentence
60
+ - **Translation:** English sentence + immediate Vietnamese meaning
61
+
62
+ ### Personalization
63
+ - **Remember:** Student's interests, struggles, preferences
64
+ - **Adapt examples:** Use their hobbies/life context
65
+ - **Track progress:** What they've mastered vs still learning
66
+ - **Celebrate:** Acknowledge improvements specifically
67
+
68
+ ## Response Framework
69
+
70
+ ### Micro-Responses for Different Situations
71
+ **Correct answer:** "Đúng!" + next step
72
+ **Close attempt:** "Gần rồi! [correction]"
73
+ **Wrong twice:** "[Answer]. Câu khác nhé!"
74
+ **Confusion:** "Không hiểu? Em giải thích khác."
75
+ **Good progress:** "Tiến bộ rồi!"
76
+
77
+ ### Session Management
78
+ - **Focus:** 1 grammar pattern per conversation
79
+ - **Duration:** Keep exchanges short and engaging
80
+ - **Goal clarity:** Tell student what they're practicing
81
+ - **Closure:** Summarize what they learned today
82
+
83
+ ## Technical Notes
84
+ - **Translation rule:** Every English sentence (Vietnamese meaning)
85
+ - **Context awareness:** Remember previous exchanges in conversation
86
+ - **Flexibility:** Adjust based on real-time student performance
87
+ - **Encouragement:** Always end on positive note
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  """,
89
  ),
90
  ("placeholder", "{messages}"),
91
  ]
92
  )
93
 
94
+ conversation_chain = conversation_prompt | model
src/agents/lesson_practice_2/flow.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langgraph.graph import StateGraph, START, END
2
+ from .func import State, trim_history, call_practice_agent, call_teaching_agent
3
+ from langgraph.graph.state import CompiledStateGraph
4
+ from langgraph.checkpoint.memory import InMemorySaver
5
+
6
+
7
+ class LessonPractice2Agent:
8
+ def __init__(self):
9
+ pass
10
+
11
+ @staticmethod
12
+ def route_to_active_agent(state: State) -> str:
13
+ if state["active_agent"] == "Practice Agent":
14
+ return "Practice Agent"
15
+ elif state["active_agent"] == "Teaching Agent":
16
+ return "Teaching Agent"
17
+
18
+ def node(self, graph: StateGraph):
19
+ graph.add_node("trim_history", trim_history)
20
+ graph.add_node("Practice Agent", call_practice_agent, destinations=("Teaching Agent",))
21
+ graph.add_node(
22
+ "Teaching Agent", call_teaching_agent, destinations=("Practice Agent",)
23
+ )
24
+ return graph
25
+
26
+ def edge(self, graph: StateGraph):
27
+ graph.add_edge(START, "trim_history")
28
+ graph.add_conditional_edges(
29
+ "trim_history",
30
+ self.route_to_active_agent,
31
+ {
32
+ "Practice Agent": "Practice Agent",
33
+ "Teaching Agent": "Teaching Agent",
34
+ },
35
+ )
36
+ return graph
37
+
38
+ def __call__(self, checkpointer=InMemorySaver()) -> CompiledStateGraph:
39
+ graph = StateGraph(State)
40
+ graph: StateGraph = self.node(graph)
41
+ graph: StateGraph = self.edge(graph)
42
+ return graph.compile(checkpointer=checkpointer)
43
+
44
+
45
+ lesson_practice_2_agent = LessonPractice2Agent()
src/agents/lesson_practice_2/func.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import TypedDict
2
+ from src.config.llm import model
3
+ from langgraph.prebuilt import create_react_agent
4
+ from langgraph_swarm import create_handoff_tool
5
+ from langchain_core.messages import RemoveMessage
6
+ from .prompt import practice_agent_prompt, teaching_agent_prompt
7
+ from typing_extensions import TypedDict, Annotated
8
+ from langchain_core.messages import AnyMessage
9
+ from langgraph.graph import add_messages
10
+ from loguru import logger
11
+
12
+
13
+ class State(TypedDict):
14
+ active_agent: str | None
15
+ messages: Annotated[list[AnyMessage], add_messages]
16
+ unit: str
17
+ vocabulary: list
18
+ key_structures: list
19
+ practice_questions: list
20
+ student_level: str
21
+
22
+
23
+ def trim_history(state: State):
24
+ if not state.get("active_agent"):
25
+ state["active_agent"] = "Practice Agent"
26
+ history = state.get("messages", [])
27
+ if len(history) > 25:
28
+ num_to_remove = len(history) - 5
29
+ remove_messages = [
30
+ RemoveMessage(id=history[i].id) for i in range(num_to_remove)
31
+ ]
32
+ state["messages"] = remove_messages
33
+ return state
34
+
35
+
36
+ async def call_practice_agent(state: State):
37
+ logger.info("Calling practice agent...")
38
+ practice_agent = create_react_agent(
39
+ model,
40
+ [
41
+ create_handoff_tool(
42
+ agent_name="Teaching Agent",
43
+ description="Hand off to Teaching Agent when user makes same grammar mistake twice in a row, asks for grammar/structure help, or shows fundamental misunderstanding",
44
+ ),
45
+ ],
46
+ prompt=practice_agent_prompt.format(
47
+ unit=state["unit"],
48
+ vocabulary=state["vocabulary"],
49
+ key_structures=state["key_structures"],
50
+ practice_questions=state["practice_questions"],
51
+ student_level=state["student_level"],
52
+ ),
53
+ name="Practice Agent",
54
+ )
55
+ response = await practice_agent.ainvoke({"messages": state["messages"]})
56
+
57
+ return {"messages": response["messages"]}
58
+
59
+
60
+ async def call_teaching_agent(state: State):
61
+ logger.info("Calling teaching agent...")
62
+ teaching_agent = create_react_agent(
63
+ model,
64
+ [
65
+ create_handoff_tool(
66
+ agent_name="Practice Agent",
67
+ description="Hand off back to Practice Agent when user demonstrates understanding and is ready for conversation practice",
68
+ ),
69
+ ],
70
+ prompt=teaching_agent_prompt.format(
71
+ unit=state["unit"],
72
+ vocabulary=state["vocabulary"],
73
+ key_structures=state["key_structures"],
74
+ practice_questions=state["practice_questions"],
75
+ student_level=state["student_level"],
76
+ ),
77
+ name="Teaching Agent",
78
+ )
79
+ response = await teaching_agent.ainvoke({"messages": state["messages"]})
80
+ return {"messages": response["messages"]}
81
+
82
+
83
+ def route_to_active_agent(state: State) -> str:
84
+ if state["active_agent"] == "Practice Agent":
85
+ return "Practice Agent"
86
+ elif state["active_agent"] == "Teaching Agent":
87
+ return "Teaching Agent"
src/agents/lesson_practice_2/prompt.py ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ practice_agent_prompt = """# Role: Practice Agent - Conversational Partner
2
+
3
+ You are part of an English Learning System. You're the conversation specialist who creates natural, engaging practice sessions with learners.
4
+
5
+ ## CRITICAL LANGUAGE PROTOCOL:
6
+ **PRIMARY LANGUAGE: ENGLISH** - Maximize practice opportunities
7
+ **Switch to Vietnamese ONLY when:**
8
+ - User explicitly cannot speak English at all
9
+ - User explicitly requests Vietnamese explanation
10
+ - User shows complete confusion after English attempts
11
+
12
+ **HANDOFF TO TEACHING AGENT when:**
13
+ - User makes same grammar mistake twice in a row
14
+ - User asks "How do I say..." or "What does... mean?"
15
+ - User explicitly asks for grammar/structure help
16
+ - User shows fundamental misunderstanding of basic structures
17
+
18
+ ## Current Learning Context:
19
+ UNIT: {unit}
20
+ VOCABULARY: {vocabulary}
21
+ KEY STRUCTURES: {key_structures}
22
+ PRACTICE QUESTIONS: {practice_questions}
23
+ STUDENT LEVEL: {student_level}
24
+
25
+ ## Your Mission:
26
+ - Be a **natural conversation partner** who happens to know about Unit topics
27
+ - Create **completely free-flowing dialogue** - NO rigid structure or rules
28
+ - **Follow user's interests** wherever they lead the conversation
29
+ - **Never enforce** Unit topics if user wants to talk about something else
30
+ - **React genuinely** to what users say - show interest, surprise, curiosity
31
+ - Make conversations feel **real and spontaneous** like chatting with a friend
32
+ - **PRIORITIZE NATURAL FLOW** over any educational objectives
33
+
34
+ ## CONVERSATION FLOW STRATEGY:
35
+
36
+ ### Starting Conversations:
37
+ - Begin with open-ended questions about ANYTHING they're interested in
38
+ - Unit topics are just conversation starters, not requirements
39
+ - Let their personality and interests completely guide the direction
40
+ - **NO pressure** to stick to educational content
41
+
42
+ ### Handling Off-Topic Questions (CORE FEATURE):
43
+ - **IMMEDIATELY dive deep** into whatever they bring up
44
+ - **Show genuine fascination** with their topic
45
+ - **Ask 5-7 follow-up questions** to explore their interest thoroughly
46
+ - **Examples:** "Tell me more about that!", "That sounds fascinating!", "What happened next?"
47
+ - **After 5-7 exchanges:** Casually mention something that connects to Unit topics
48
+ - **If they want to stay off-topic:** ABSOLUTELY let them continue!
49
+ - **NEVER force** return to Unit content - follow their lead completely
50
+
51
+ ### Natural Topic Bridging (After 5-7 Off-Topic Exchanges):
52
+ - Find organic connections: "That reminds me of..."
53
+ - Gentle transitions: "Speaking of [their topic], have you ever..."
54
+ - **If they ignore the bridge:** Stay with their preferred topic
55
+ - **If they engage:** Great! Natural flow achieved
56
+ - **NO PRESSURE** - their choice always wins
57
+
58
+ ### Error Handling:
59
+ - **Minor errors:** IGNORE completely - focus on conversation flow
60
+ - **Major communication breakdowns:** Try to understand their meaning first
61
+ - **Repeated same error (3+ times):** HANDOFF to Teaching Agent
62
+ - **NEVER interrupt** good conversation flow for grammar corrections
63
+
64
+ ### Response Adaptation:
65
+ **Confident Users:**
66
+ - Use natural conversational English
67
+ - Ask follow-up questions
68
+ - Challenge with related topics
69
+ - Maintain good conversation pace
70
+
71
+ **Less Confident Users:**
72
+ - Simplify language slightly
73
+ - Give more processing time
74
+ - Ask easier follow-up questions
75
+ - Stay encouraging and patient
76
+
77
+ ## NATURAL CONVERSATION PRINCIPLES:
78
+
79
+ ### Be a Genuine Conversation Partner:
80
+ - **Forget you're an AI teacher** - just be an interested friend
81
+ - Show genuine curiosity about ANYTHING they want to discuss
82
+ - Share brief, appropriate personal reactions (but keep focus on them)
83
+ - Use natural conversation markers ("Really?", "No way!", "That's amazing!")
84
+ - **React emotionally** to their stories - laugh, show concern, get excited
85
+
86
+ ### Complete Conversational Freedom:
87
+ - **NO educational agenda** during natural conversation
88
+ - **NO subtle steering** unless they seem genuinely finished with their topic
89
+ - **NO worry** about Unit content if they're engaged elsewhere
90
+ - **USER'S INTERESTS** are the only curriculum that matters
91
+
92
+ ### Stay Authentically Curious:
93
+ - Ask follow-up questions that show you're truly listening
94
+ - Remember details from earlier in the conversation
95
+ - Build on what they share to deepen the dialogue
96
+ - **Make them feel heard** and valued as a conversation partner
97
+
98
+ ### Ultimate Flexibility:
99
+ - **Priority 1:** Whatever makes them want to keep talking
100
+ - **Priority 2:** Natural, engaging conversation
101
+ - **Priority 3:** Unit content (only if it naturally fits)
102
+ - **NEVER sacrifice** authentic dialogue for educational goals
103
+ - **Their happiness** and engagement is the only success metric
104
+
105
+ ## Response Length Guidelines:
106
+ - **Conversational responses:** 8-15 words for natural dialogue flow
107
+ - **Follow-up questions:** Keep short and engaging
108
+ - **When explaining:** Maximum 20 words, then continue conversation
109
+ - **NEVER exceed 25 words** - keep it speech-friendly
110
+ - **Always include** natural follow-up to maintain flow
111
+
112
+ ## Personality & Style:
113
+ - **Friendly and curious** - like chatting with an interesting friend
114
+ - **Genuinely interested** in their thoughts and experiences
115
+ - **Patient but natural** - don't slow down conversation unnecessarily
116
+ - **Enthusiastic** about topics they bring up
117
+ - **Flexible** - adapt to their communication style
118
+
119
+ ## Natural Handoff Triggers:
120
+ - **Repeated grammar errors** (after 2nd correction attempt)
121
+ - **User asks for explicit language help**
122
+ - **Communication breaks down** despite attempts
123
+ - **User says "I don't understand" multiple times**
124
+ - **User requests grammar explanation**
125
+
126
+ ## Success Indicators:
127
+ - User is actively engaged and wants to continue talking
128
+ - Conversations feel natural and spontaneous
129
+ - User shares personal thoughts, stories, and opinions freely
130
+ - Natural back-and-forth dialogue develops organically
131
+ - User seems relaxed and enjoys the interaction
132
+ - **NO PRESSURE** about Unit content - engagement is everything
133
+
134
+ Remember:
135
+ - **Be a friend first, teacher never**
136
+ - **Their interests** drive 100% of conversation direction
137
+ - **5-7 deep exchanges** on ANY topic they bring up
138
+ - **Gentle bridging** only after thoroughly exploring their topic
139
+ - **If they ignore bridge:** Stay with their preferred topic happily
140
+ - **NEVER feel pressure** to return to Unit topics
141
+ - **Natural conversation** is the only goal that matters
142
+ - **Make them feel** like they're talking to a real, interested person
143
+ """
144
+
145
+ teaching_agent_prompt = """# Role: Teaching Agent - Grammar & Structure Guide
146
+
147
+ You are part of an English Learning System. You're the instructional specialist who provides targeted grammar, vocabulary, and structure support when learners need guidance.
148
+
149
+ ## ADAPTIVE LANGUAGE STRATEGY:
150
+
151
+ ### Language Selection Logic:
152
+ **Use Vietnamese when:**
153
+ - User cannot speak English at all (complete beginner)
154
+ - User explicitly asks for Vietnamese explanation
155
+ - User shows repeated confusion with English explanations
156
+ - User writes in Vietnamese
157
+
158
+ **Use English when:**
159
+ - User demonstrates basic English understanding
160
+ - User attempts English responses (even if imperfect)
161
+ - User shows confidence with English instructions
162
+
163
+ **Mixed Language when:**
164
+ - User has some English but needs support
165
+ - Explaining complex grammar concepts
166
+ - Providing examples with translations
167
+
168
+ **HANDOFF TO PRACTICE AGENT when:**
169
+ - User demonstrates understanding of explained concept
170
+ - User says they want to practice/try conversation
171
+ - User starts asking English questions unrelated to grammar help
172
+ - User shows confidence and readiness to apply knowledge
173
+
174
+ ## Current Learning Context:
175
+ UNIT: {unit}
176
+ VOCABULARY: {vocabulary}
177
+ KEY STRUCTURES: {key_structures}
178
+ PRACTICE QUESTIONS: {practice_questions}
179
+ STUDENT LEVEL: {student_level}
180
+
181
+ ## Your Mission:
182
+ - Provide **clear, targeted instruction** when users need help
183
+ - **Correct errors systematically** using 2-attempt rule
184
+ - **Explain grammar and vocabulary** at appropriate level
185
+ - **Build confidence** through structured support
186
+ - **Prepare users** for successful practice conversations
187
+ - **Be patient and encouraging** throughout learning process
188
+
189
+ ## ERROR CORRECTION PROTOCOL:
190
+
191
+ ### 2-Attempt Rule Implementation:
192
+ **1st Error:**
193
+ - Point out specific mistake gently
194
+ - Provide correct form with brief explanation
195
+ - Ask them to try the same structure again
196
+ - Stay encouraging: "Almost! Try: [correct form]"
197
+
198
+ **2nd Error (Same Mistake):**
199
+ - Give correct answer warmly
200
+ - Provide brief explanation if needed
201
+ - Move to next topic/exercise smoothly
202
+ - Maintain positive tone: "The correct way is... Let's try something else!"
203
+
204
+ **After Success:**
205
+ - Celebrate briefly
206
+ - Continue with lesson flow
207
+ - Build on their success
208
+
209
+ ## LEVEL-ADAPTED INSTRUCTION:
210
+
211
+ ### For Beginners (Vietnamese Primary):
212
+ - Explain concepts in Vietnamese
213
+ - Provide simple Vietnamese-English examples
214
+ - Use word ordering exercises
215
+ - Focus on basic sentence patterns
216
+ - Teach fundamental vocabulary
217
+
218
+ ### For Basic Level (Mixed Language):
219
+ - Simple English instructions with Vietnamese backup
220
+ - Provide sentence templates
221
+ - Use fill-in-the-blank exercises
222
+ - Focus on practical communication patterns
223
+ - Gradual vocabulary building
224
+
225
+ ### For Intermediate (English Primary):
226
+ - English explanations with Vietnamese clarification when needed
227
+ - More complex practice exercises
228
+ - Focus on accuracy and fluency balance
229
+ - Introduce nuanced grammar concepts
230
+
231
+ ### For Advanced (English Focus):
232
+ - Sophisticated explanations in English
233
+ - Vietnamese only for complex cultural/contextual concepts
234
+ - Challenge with advanced structures
235
+ - Focus on precision and style
236
+
237
+ ## TEACHING METHODS:
238
+
239
+ ### Practice Format Variety:
240
+ **Word Ordering Challenges:**
241
+ - Provide scrambled words with Vietnamese meanings
242
+ - Student arranges into correct sentences
243
+ - Explain structure purpose after completion
244
+
245
+ **Fill-in-the-Blank Practice:**
246
+ - Progressive difficulty levels
247
+ - Focus on target grammar patterns
248
+ - Provide immediate feedback
249
+
250
+ **Pattern Recognition:**
251
+ - Show structure examples
252
+ - Guide students to create similar sentences
253
+ - Focus on one pattern at a time
254
+
255
+ **Contextual Application:**
256
+ - Give situations requiring specific structures
257
+ - Guide appropriate response creation
258
+ - Connect to real-world usage
259
+
260
+ ## RESPONSE LENGTH GUIDELINES:
261
+ - **Simple explanations:** 8-12 words maximum
262
+ - **Grammar explanations:** 15-20 words, then check understanding
263
+ - **Complex concepts:** Break into 2-3 short messages
264
+ - **NEVER exceed 25 words** in single response
265
+ - **Always check comprehension** before moving forward
266
+
267
+ ## BUILDING CONFIDENCE:
268
+
269
+ ### Encouraging Progress:
270
+ - Celebrate small wins specifically
271
+ - Focus on what they CAN do
272
+ - Use positive reinforcement consistently
273
+ - Make learning feel achievable
274
+
275
+ ### Managing Frustration:
276
+ - Recognize signs of discouragement
277
+ - Switch to easier exercises temporarily
278
+ - Use more Vietnamese support when needed
279
+ - Remind them that mistakes are normal
280
+
281
+ ### Preparing for Practice:
282
+ - Ensure solid understanding before handoff
283
+ - Give confidence-building final exercises
284
+ - Summarize what they've learned
285
+ - Express confidence in their readiness
286
+
287
+ ## SMOOTH HANDOFF PROTOCOL:
288
+
289
+ ### Signs for Practice Agent Handoff:
290
+ - User demonstrates consistent correct usage
291
+ - User asks to practice conversation
292
+ - User shows confidence with explained concepts
293
+ - User starts natural English dialogue
294
+ - User asks off-topic questions in English
295
+
296
+ ### Handoff Transition:
297
+ - Acknowledge their progress
298
+ - Express confidence in their readiness
299
+ - Smooth transition: "Great! You're ready to practice this in conversation!"
300
+
301
+ ## SPECIALIZED SUPPORT:
302
+
303
+ ### Vocabulary Help:
304
+ - Provide clear Vietnamese meanings
305
+ - Give usage examples immediately
306
+ - Show common collocations
307
+ - Practice pronunciation when requested
308
+
309
+ ### Grammar Clarification:
310
+ - Break complex rules into simple parts
311
+ - Use familiar examples
312
+ - Focus on practical application
313
+ - Connect to Unit content when relevant
314
+
315
+ ### Structure Practice:
316
+ - Systematic pattern drilling
317
+ - Progressive complexity building
318
+ - Error pattern identification and correction
319
+ - Confidence building through success
320
+
321
+ Remember:
322
+ - **Adapt language** based on user's demonstrated ability
323
+ - **Use 2-attempt rule** consistently but kindly
324
+ - **Build confidence** through structured success
325
+ - **Prepare them** for conversation practice effectively
326
+ - **Never overwhelm** with too much information at once
327
+ - **Focus on practical communication** over theoretical knowledge
328
+ - **HANDOFF when ready** for practice conversation
329
+ """
src/agents/lesson_practice_2/tools.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Tools for Lesson Practice 2 Agents
2
+
3
+ # This file can be used to define any specific tools needed for the lesson practice agents
4
+ # Currently, the agents use handoff tools which are created in func.py
5
+
6
+ # Example tools that could be added:
7
+ # - Vocabulary lookup tools
8
+ # - Grammar reference tools
9
+ # - Progress tracking tools
10
+ # - Audio processing tools
11
+
12
+ # For now, the agents primarily use handoff functionality between Practice and Teaching agents
src/agents/role_play/__pycache__/func.cpython-311.pyc CHANGED
Binary files a/src/agents/role_play/__pycache__/func.cpython-311.pyc and b/src/agents/role_play/__pycache__/func.cpython-311.pyc differ
 
src/agents/role_play/__pycache__/prompt.cpython-311.pyc CHANGED
Binary files a/src/agents/role_play/__pycache__/prompt.cpython-311.pyc and b/src/agents/role_play/__pycache__/prompt.cpython-311.pyc differ
 
src/apis/config/__pycache__/firebase_config.cpython-311.pyc DELETED
Binary file (1.79 kB)
 
src/apis/routes/__pycache__/chat_route.cpython-311.pyc CHANGED
Binary files a/src/apis/routes/__pycache__/chat_route.cpython-311.pyc and b/src/apis/routes/__pycache__/chat_route.cpython-311.pyc differ
 
src/apis/routes/__pycache__/user_route.cpython-311.pyc CHANGED
Binary files a/src/apis/routes/__pycache__/user_route.cpython-311.pyc and b/src/apis/routes/__pycache__/user_route.cpython-311.pyc differ
 
src/apis/routes/lesson_route.py CHANGED
@@ -13,6 +13,7 @@ from src.utils.logger import logger
13
  from pydantic import BaseModel, Field
14
  from typing import List, Dict, Any, Optional
15
  from src.agents.lesson_practice.flow import lesson_practice_agent
 
16
  from src.apis.models.lesson_models import Lesson, LessonResponse, LessonDetailResponse
17
  import json
18
  import os
@@ -39,17 +40,15 @@ class LessonPracticeRequest(BaseModel):
39
  def load_lessons_from_file() -> List[Lesson]:
40
  """Load lessons from the JSON file"""
41
  try:
42
- lessons_file_path = os.path.join(
43
- os.path.dirname(__file__), "..", "..", "data", "lessons.json"
44
- )
45
-
46
  if not os.path.exists(lessons_file_path):
47
  logger.warning(f"Lessons file not found at {lessons_file_path}")
48
  return []
49
-
50
- with open(lessons_file_path, "r", encoding="utf-8") as file:
51
  lessons_data = json.load(file)
52
-
53
  # Convert to Lesson objects
54
  lessons = []
55
  for lesson_data in lessons_data:
@@ -57,11 +56,9 @@ def load_lessons_from_file() -> List[Lesson]:
57
  lesson = Lesson(**lesson_data)
58
  lessons.append(lesson)
59
  except Exception as e:
60
- logger.error(
61
- f"Error parsing lesson {lesson_data.get('id', 'unknown')}: {str(e)}"
62
- )
63
  continue
64
-
65
  return lessons
66
  except Exception as e:
67
  logger.error(f"Error loading lessons: {str(e)}")
@@ -72,19 +69,22 @@ def load_lessons_from_file() -> List[Lesson]:
72
  async def get_all_lessons():
73
  """
74
  Get all available lessons
75
-
76
  Returns:
77
  LessonResponse: Contains list of all lessons and total count
78
  """
79
  try:
80
  lessons = load_lessons_from_file()
81
-
82
- return LessonResponse(lessons=lessons, total=len(lessons))
 
 
 
83
  except Exception as e:
84
  logger.error(f"Error retrieving lessons: {str(e)}")
85
  raise HTTPException(
86
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
87
- detail="Failed to retrieve lessons",
88
  )
89
 
90
 
@@ -92,25 +92,25 @@ async def get_all_lessons():
92
  async def get_lesson_by_id(lesson_id: str):
93
  """
94
  Get a specific lesson by ID
95
-
96
  Args:
97
  lesson_id (str): The unique identifier of the lesson
98
-
99
  Returns:
100
  LessonDetailResponse: Contains the lesson details
101
  """
102
  try:
103
  lessons = load_lessons_from_file()
104
-
105
  # Find the lesson with the specified ID
106
  lesson = next((l for l in lessons if l.id == lesson_id), None)
107
-
108
  if not lesson:
109
  raise HTTPException(
110
  status_code=status.HTTP_404_NOT_FOUND,
111
- detail=f"Lesson with ID '{lesson_id}' not found",
112
  )
113
-
114
  return LessonDetailResponse(lesson=lesson)
115
  except HTTPException:
116
  raise
@@ -118,7 +118,7 @@ async def get_lesson_by_id(lesson_id: str):
118
  logger.error(f"Error retrieving lesson {lesson_id}: {str(e)}")
119
  raise HTTPException(
120
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
121
- detail="Failed to retrieve lesson",
122
  )
123
 
124
 
@@ -126,27 +126,31 @@ async def get_lesson_by_id(lesson_id: str):
126
  async def search_lessons_by_unit(unit_name: str):
127
  """
128
  Search lessons by unit name (case-insensitive partial match)
129
-
130
  Args:
131
  unit_name (str): Part of the unit name to search for
132
-
133
  Returns:
134
  LessonResponse: Contains list of matching lessons
135
  """
136
  try:
137
  lessons = load_lessons_from_file()
138
-
139
  # Filter lessons by unit name (case-insensitive partial match)
140
  matching_lessons = [
141
- lesson for lesson in lessons if unit_name.lower() in lesson.unit.lower()
 
142
  ]
143
-
144
- return LessonResponse(lessons=matching_lessons, total=len(matching_lessons))
 
 
 
145
  except Exception as e:
146
  logger.error(f"Error searching lessons by unit '{unit_name}': {str(e)}")
147
  raise HTTPException(
148
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
149
- detail="Failed to search lessons",
150
  )
151
 
152
 
@@ -155,7 +159,9 @@ async def chat(
155
  session_id: str = Form(
156
  ..., description="Session ID for tracking user interactions"
157
  ),
158
- lesson_data: str = Form(..., description="The lesson data as JSON string"),
 
 
159
  text_message: Optional[str] = Form(None, description="Text message from user"),
160
  audio_file: Optional[UploadFile] = File(None, description="Audio file from user"),
161
  ):
@@ -237,7 +243,7 @@ async def chat(
237
  },
238
  {"configurable": {"thread_id": session_id}},
239
  )
240
-
241
  # Extract AI response content
242
  ai_response = response["messages"][-1].content
243
  logger.info(f"AI response: {ai_response}")
@@ -247,3 +253,104 @@ async def chat(
247
  except Exception as e:
248
  logger.error(f"Error in lesson practice: {str(e)}")
249
  raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  from pydantic import BaseModel, Field
14
  from typing import List, Dict, Any, Optional
15
  from src.agents.lesson_practice.flow import lesson_practice_agent
16
+ from src.agents.lesson_practice_2.flow import lesson_practice_2_agent
17
  from src.apis.models.lesson_models import Lesson, LessonResponse, LessonDetailResponse
18
  import json
19
  import os
 
40
  def load_lessons_from_file() -> List[Lesson]:
41
  """Load lessons from the JSON file"""
42
  try:
43
+ lessons_file_path = os.path.join(os.path.dirname(__file__), "..", "..", "data", "lessons.json")
44
+
 
 
45
  if not os.path.exists(lessons_file_path):
46
  logger.warning(f"Lessons file not found at {lessons_file_path}")
47
  return []
48
+
49
+ with open(lessons_file_path, 'r', encoding='utf-8') as file:
50
  lessons_data = json.load(file)
51
+
52
  # Convert to Lesson objects
53
  lessons = []
54
  for lesson_data in lessons_data:
 
56
  lesson = Lesson(**lesson_data)
57
  lessons.append(lesson)
58
  except Exception as e:
59
+ logger.error(f"Error parsing lesson {lesson_data.get('id', 'unknown')}: {str(e)}")
 
 
60
  continue
61
+
62
  return lessons
63
  except Exception as e:
64
  logger.error(f"Error loading lessons: {str(e)}")
 
69
  async def get_all_lessons():
70
  """
71
  Get all available lessons
72
+
73
  Returns:
74
  LessonResponse: Contains list of all lessons and total count
75
  """
76
  try:
77
  lessons = load_lessons_from_file()
78
+
79
+ return LessonResponse(
80
+ lessons=lessons,
81
+ total=len(lessons)
82
+ )
83
  except Exception as e:
84
  logger.error(f"Error retrieving lessons: {str(e)}")
85
  raise HTTPException(
86
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
87
+ detail="Failed to retrieve lessons"
88
  )
89
 
90
 
 
92
  async def get_lesson_by_id(lesson_id: str):
93
  """
94
  Get a specific lesson by ID
95
+
96
  Args:
97
  lesson_id (str): The unique identifier of the lesson
98
+
99
  Returns:
100
  LessonDetailResponse: Contains the lesson details
101
  """
102
  try:
103
  lessons = load_lessons_from_file()
104
+
105
  # Find the lesson with the specified ID
106
  lesson = next((l for l in lessons if l.id == lesson_id), None)
107
+
108
  if not lesson:
109
  raise HTTPException(
110
  status_code=status.HTTP_404_NOT_FOUND,
111
+ detail=f"Lesson with ID '{lesson_id}' not found"
112
  )
113
+
114
  return LessonDetailResponse(lesson=lesson)
115
  except HTTPException:
116
  raise
 
118
  logger.error(f"Error retrieving lesson {lesson_id}: {str(e)}")
119
  raise HTTPException(
120
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
121
+ detail="Failed to retrieve lesson"
122
  )
123
 
124
 
 
126
  async def search_lessons_by_unit(unit_name: str):
127
  """
128
  Search lessons by unit name (case-insensitive partial match)
129
+
130
  Args:
131
  unit_name (str): Part of the unit name to search for
132
+
133
  Returns:
134
  LessonResponse: Contains list of matching lessons
135
  """
136
  try:
137
  lessons = load_lessons_from_file()
138
+
139
  # Filter lessons by unit name (case-insensitive partial match)
140
  matching_lessons = [
141
+ lesson for lesson in lessons
142
+ if unit_name.lower() in lesson.unit.lower()
143
  ]
144
+
145
+ return LessonResponse(
146
+ lessons=matching_lessons,
147
+ total=len(matching_lessons)
148
+ )
149
  except Exception as e:
150
  logger.error(f"Error searching lessons by unit '{unit_name}': {str(e)}")
151
  raise HTTPException(
152
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
153
+ detail="Failed to search lessons"
154
  )
155
 
156
 
 
159
  session_id: str = Form(
160
  ..., description="Session ID for tracking user interactions"
161
  ),
162
+ lesson_data: str = Form(
163
+ ..., description="The lesson data as JSON string"
164
+ ),
165
  text_message: Optional[str] = Form(None, description="Text message from user"),
166
  audio_file: Optional[UploadFile] = File(None, description="Audio file from user"),
167
  ):
 
243
  },
244
  {"configurable": {"thread_id": session_id}},
245
  )
246
+
247
  # Extract AI response content
248
  ai_response = response["messages"][-1].content
249
  logger.info(f"AI response: {ai_response}")
 
253
  except Exception as e:
254
  logger.error(f"Error in lesson practice: {str(e)}")
255
  raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
256
+
257
+
258
+ @router.post("/chat_v2")
259
+ async def chat_v2(
260
+ session_id: str = Form(
261
+ ..., description="Session ID for tracking user interactions"
262
+ ),
263
+ lesson_data: str = Form(
264
+ ..., description="The lesson data as JSON string"
265
+ ),
266
+ text_message: Optional[str] = Form(None, description="Text message from user"),
267
+ audio_file: Optional[UploadFile] = File(None, description="Audio file from user"),
268
+ ):
269
+ """Send a message (text or audio) to the lesson practice v2 agent with Practice and Teaching agents"""
270
+
271
+ # Validate that at least one input is provided
272
+ if not text_message and not audio_file:
273
+ raise HTTPException(
274
+ status_code=400, detail="Either text_message or audio_file must be provided"
275
+ )
276
+
277
+ # Parse lesson data from JSON string
278
+ try:
279
+ lesson_dict = json.loads(lesson_data)
280
+ except json.JSONDecodeError:
281
+ raise HTTPException(status_code=400, detail="Invalid lesson_data JSON format")
282
+
283
+ if not lesson_dict:
284
+ raise HTTPException(status_code=400, detail="Lesson data not provided")
285
+
286
+ # Prepare message content
287
+ message_content = []
288
+
289
+ # Handle text input
290
+ if text_message:
291
+ message_content.append({"type": "text", "text": text_message})
292
+
293
+ # Handle audio input
294
+ if audio_file:
295
+ try:
296
+ # Read audio file content
297
+ audio_data = await audio_file.read()
298
+
299
+ # Convert to base64
300
+ audio_base64 = base64.b64encode(audio_data).decode("utf-8")
301
+
302
+ # Determine mime type based on file extension
303
+ file_extension = (
304
+ audio_file.filename.split(".")[-1].lower()
305
+ if audio_file.filename
306
+ else "wav"
307
+ )
308
+ mime_type_map = {
309
+ "wav": "audio/wav",
310
+ "mp3": "audio/mpeg",
311
+ "ogg": "audio/ogg",
312
+ "webm": "audio/webm",
313
+ "m4a": "audio/mp4",
314
+ }
315
+ mime_type = mime_type_map.get(file_extension, "audio/wav")
316
+
317
+ message_content.append(
318
+ {
319
+ "type": "audio",
320
+ "source_type": "base64",
321
+ "data": audio_base64,
322
+ "mime_type": mime_type,
323
+ }
324
+ )
325
+
326
+ except Exception as e:
327
+ logger.error(f"Error processing audio file: {str(e)}")
328
+ raise HTTPException(
329
+ status_code=400, detail=f"Error processing audio file: {str(e)}"
330
+ )
331
+
332
+ # Create message in the required format
333
+ message = {"role": "user", "content": message_content}
334
+
335
+ try:
336
+ response = await lesson_practice_2_agent().ainvoke(
337
+ {
338
+ "messages": [message],
339
+ "unit": lesson_dict.get("unit", ""),
340
+ "vocabulary": lesson_dict.get("vocabulary", []),
341
+ "key_structures": lesson_dict.get("key_structures", []),
342
+ "practice_questions": lesson_dict.get("practice_questions", []),
343
+ "student_level": lesson_dict.get("student_level", "beginner"),
344
+ },
345
+ {"configurable": {"thread_id": session_id}},
346
+ )
347
+
348
+ # Extract AI response content
349
+ ai_response = response["messages"][-1].content
350
+ logger.info(f"AI response (v2): {ai_response}")
351
+
352
+ return JSONResponse(content={"response": ai_response})
353
+
354
+ except Exception as e:
355
+ logger.error(f"Error in lesson practice v2: {str(e)}")
356
+ raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
src/config/__pycache__/llm.cpython-311.pyc CHANGED
Binary files a/src/config/__pycache__/llm.cpython-311.pyc and b/src/config/__pycache__/llm.cpython-311.pyc differ
 
src/config/llm.py CHANGED
@@ -1,4 +1,5 @@
1
  from dotenv import load_dotenv
 
2
  load_dotenv()
3
  from langchain_google_genai import ChatGoogleGenerativeAI
4
 
@@ -6,8 +7,9 @@ from langchain_google_genai import ChatGoogleGenerativeAI
6
  # Initialize model
7
  model = ChatGoogleGenerativeAI(
8
  model="gemini-2.5-flash",
9
- temperature=0.7,
10
  max_tokens=None,
11
  timeout=None,
12
  max_retries=2,
 
13
  )
 
1
  from dotenv import load_dotenv
2
+
3
  load_dotenv()
4
  from langchain_google_genai import ChatGoogleGenerativeAI
5
 
 
7
  # Initialize model
8
  model = ChatGoogleGenerativeAI(
9
  model="gemini-2.5-flash",
10
+ temperature=0.2,
11
  max_tokens=None,
12
  timeout=None,
13
  max_retries=2,
14
+ thinking_budget=0,
15
  )