ParulPandey commited on
Commit
2d79f41
·
verified ·
1 Parent(s): b3566fd

Update agent.py

Browse files
Files changed (1) hide show
  1. agent.py +39 -280
agent.py CHANGED
@@ -2,15 +2,13 @@ import os
2
  import requests
3
  from smolagents.tools import tool
4
  from difflib import SequenceMatcher
5
-
6
  try:
7
  from gradio_client import Client
8
  except ImportError:
9
  # Fallback import for older versions
10
  import gradio_client
11
  Client = gradio_client.Client
12
- from google import genai
13
- from google.genai import types
14
  import json
15
  import time
16
  import numpy as np
@@ -26,9 +24,9 @@ TTS_API = os.getenv("TTS_API")
26
  STT_API = os.getenv("STT_API")
27
  GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
28
 
29
- # Configure Google Gemini client
30
  if GOOGLE_API_KEY:
31
- gemini_client = genai.Client(api_key=GOOGLE_API_KEY)
32
 
33
  @tool
34
  def generate_story(name: str, grade: str, topic: str) -> str:
@@ -97,19 +95,20 @@ def generate_story(name: str, grade: str, topic: str) -> str:
97
  """
98
 
99
  # Use Google Gemini
 
 
100
  # Adjust generation parameters based on grade level
101
  max_tokens = 300 if grade_num <= 2 else 600 if grade_num <= 4 else 1000
102
 
103
- generation_config = types.GenerateContentConfig(
104
- temperature=0.8,
105
- max_output_tokens=max_tokens,
106
- top_p=0.9,
107
- )
108
 
109
- response = gemini_client.models.generate_content(
110
- model="gemini-2.0-flash",
111
- contents=[prompt],
112
- config=generation_config
113
  )
114
 
115
  return response.text.strip()
@@ -322,54 +321,23 @@ def compare_texts_for_feedback(original: str, spoken: str) -> str:
322
  Returns:
323
  str: Comprehensive, age-appropriate feedback with learning suggestions.
324
  """
325
- # Check if the spoken text is too short to be meaningful
326
- if not spoken or len(spoken.split()) < 3:
327
- return "⚠️ Your reading was too short. Please try reading the complete story."
328
-
329
  # Clean and process text
330
  orig_words = [w.strip(".,!?;:\"'").lower() for w in original.split() if w.strip()]
331
  spoken_words = [w.strip(".,!?;:\"'").lower() for w in spoken.split() if w.strip()]
332
 
333
- # Set minimum threshold for overall matching - if nothing matches at all,
334
- # it's likely the student read something completely different
335
- common_words = set(orig_words).intersection(set(spoken_words))
336
- if len(common_words) < max(2, len(orig_words) * 0.1): # At least 2 words or 10% must match
337
- return "⚠️ I couldn't recognize enough words from the story. Please try reading the story text shown on the screen.\n\nReading accuracy: 0.0%"
338
-
339
  # Calculate accuracy using sequence matching
340
  matcher = SequenceMatcher(None, orig_words, spoken_words, autojunk=False)
341
  accuracy = matcher.ratio() * 100
342
 
343
- # Identify different types of errors using context-aware approach
344
- # Use difflib to get a more accurate understanding of missed words in context
345
- import difflib
346
- d = difflib.Differ()
347
- diff = list(d.compare([w.lower() for w in original.split() if w.strip()],
348
- [w.lower() for w in spoken.split() if w.strip()]))
349
-
350
- missed_words = []
351
- for word in diff:
352
- if word.startswith('- '): # Words in original but not in spoken
353
- clean_word = word[2:].strip(".,!?;:\"'").lower()
354
- if clean_word and len(clean_word) > 1: # Avoid punctuation
355
- missed_words.append(clean_word)
356
-
357
- # Convert to set to remove duplicates but preserve order for important words
358
- missed_words_set = set(missed_words)
359
-
360
- # Extra words (might be mispronunciations or additions)
361
  extra_words = set(spoken_words) - set(orig_words)
362
 
363
  # Find mispronounced words (words that sound similar but are different)
364
  mispronounced = find_similar_words(orig_words, spoken_words)
365
 
366
- # Prioritize important words (like nouns, longer words) if available
367
- important_missed = [w for w in missed_words if len(w) > 4]
368
- if important_missed:
369
- missed_words_set = set(important_missed) | set([w for w in missed_words if w not in important_missed][:3])
370
-
371
  # Generate age-appropriate feedback
372
- return generate_adaptive_feedback(accuracy, missed_words_set, extra_words, mispronounced, len(orig_words))
373
 
374
  def find_similar_words(original_words: list, spoken_words: list) -> list:
375
  """
@@ -467,8 +435,6 @@ def get_pronunciation_tip(word: str) -> str:
467
  return f"Sound it out: {'-'.join(word)}"
468
  elif word.endswith('tion'):
469
  return "Ends with 'shun' sound"
470
- elif word.endswith('sion'):
471
- return "Ends with 'zhun' or 'shun' sound"
472
  elif word.endswith('ed'):
473
  if word[-3] in 'td':
474
  return "Past tense - ends with 'ed' sound"
@@ -476,24 +442,8 @@ def get_pronunciation_tip(word: str) -> str:
476
  return "Past tense - ends with 'd' sound"
477
  elif 'th' in word:
478
  return "Put your tongue between your teeth for 'th'"
479
- elif 'ch' in word:
480
- return "Make the 'ch' sound like in 'cheese'"
481
- elif 'sh' in word:
482
- return "Make the 'sh' sound like in 'ship'"
483
- elif word.startswith('kn'):
484
- return "The 'k' is silent, start with the 'n' sound"
485
- elif word.startswith('ph'):
486
- return "The 'ph' makes an 'f' sound"
487
  elif word.startswith('wh'):
488
  return "Starts with 'w' sound (like 'when')"
489
- elif word.endswith('igh'):
490
- return "The 'igh' makes a long 'i' sound like in 'night'"
491
- elif 'ou' in word:
492
- return "The 'ou' often sounds like 'ow' in 'cow'"
493
- elif 'ai' in word:
494
- return "The 'ai' makes the long 'a' sound"
495
- elif 'ea' in word:
496
- return "The 'ea' usually makes the long 'e' sound"
497
  elif len(word) >= 6:
498
  # Break longer words into syllables
499
  return f"Break it down: {break_into_syllables(word)}"
@@ -523,32 +473,12 @@ def get_pronunciation_correction(original: str, spoken: str) -> str:
523
  return f"Starts with '{orig[0]}' sound, not '{spok[0]}'"
524
  elif orig[-1] != spok[-1]:
525
  return f"Ends with '{orig[-1]}' sound"
526
-
527
- # Check for vowel confusion
528
- orig_vowels = [c for c in orig if c in 'aeiou']
529
- spok_vowels = [c for c in spok if c in 'aeiou']
530
-
531
- if orig_vowels != spok_vowels:
532
- # Find the first different vowel
533
- for i in range(min(len(orig_vowels), len(spok_vowels))):
534
- if orig_vowels[i] != spok_vowels[i]:
535
- vowel_map = {
536
- 'a': "ah (like in 'cat')",
537
- 'e': "eh (like in 'bed')",
538
- 'i': "ih (like in 'sit')",
539
- 'o': "oh (like in 'hot')",
540
- 'u': "uh (like in 'cup')"
541
- }
542
- correct_sound = vowel_map.get(orig_vowels[i], f"'{orig_vowels[i]}'")
543
- wrong_sound = vowel_map.get(spok_vowels[i], f"'{spok_vowels[i]}'")
544
- return f"Say the vowel sound as {correct_sound}, not {wrong_sound}"
545
-
546
- # Default case
547
- return f"Listen carefully: '{orig}' - try saying it slower"
548
 
549
  def break_into_syllables(word: str) -> str:
550
  """
551
- Improved syllable breaking for pronunciation help.
552
 
553
  Args:
554
  word (str): Word to break into syllables
@@ -556,97 +486,22 @@ def break_into_syllables(word: str) -> str:
556
  Returns:
557
  str: Word broken into syllables
558
  """
559
- vowels = 'aeiouy'
560
- word = word.lower()
561
  syllables = []
562
  current_syllable = ''
563
- consonant_cluster = ''
564
-
565
- # Handle common prefixes
566
- common_prefixes = ['re', 'pre', 'un', 'in', 'im', 'dis', 'mis', 'non', 'sub', 'inter', 'ex']
567
- for prefix in common_prefixes:
568
- if word.startswith(prefix) and len(word) > len(prefix) + 1:
569
- syllables.append(prefix)
570
- word = word[len(prefix):]
571
- break
572
-
573
- # Handle common suffixes
574
- common_suffixes = ['ing', 'ed', 'er', 'est', 'ly', 'ful', 'ness', 'less', 'ment', 'able', 'ible']
575
- for suffix in common_suffixes:
576
- if word.endswith(suffix) and len(word) > len(suffix) + 1:
577
- suffix_syllable = suffix
578
- word = word[:-len(suffix)]
579
- syllables.append(word)
580
- syllables.append(suffix_syllable)
581
- return '-'.join(syllables)
582
-
583
- # Process the word character by character
584
- i = 0
585
- while i < len(word):
586
- char = word[i]
587
-
588
- # If we encounter a vowel
589
- if char in vowels:
590
- # Start or add to a syllable
591
- if consonant_cluster:
592
- # For consonant clusters, we generally add one consonant to the current syllable
593
- # and move the rest to the next syllable
594
- if len(consonant_cluster) > 1:
595
- if current_syllable: # If we already have a syllable started
596
- current_syllable += consonant_cluster[0]
597
- syllables.append(current_syllable)
598
- current_syllable = consonant_cluster[1:] + char
599
- else: # For starting consonant clusters
600
- current_syllable = consonant_cluster + char
601
- else: # Single consonant
602
- current_syllable += consonant_cluster + char
603
- consonant_cluster = ''
604
- else:
605
- current_syllable += char
606
-
607
- # Check for vowel pairs that should stay together
608
- if i < len(word) - 1 and word[i+1] in vowels:
609
- vowel_pairs = ['ea', 'ee', 'oo', 'ou', 'ie', 'ai', 'oa']
610
- if word[i:i+2] in vowel_pairs:
611
- current_syllable += word[i+1]
612
- i += 1 # Skip the next vowel since we've added it
613
- else: # Consonant
614
- if current_syllable: # If we have an open syllable
615
- if i < len(word) - 1 and word[i+1] not in vowels: # Consonant cluster
616
- consonant_cluster += char
617
- else: # Single consonant followed by vowel
618
- current_syllable += char
619
- else: # Starting with consonant or building consonant cluster
620
- consonant_cluster += char
621
-
622
- # Handle end of word or ready to break syllable
623
- if i == len(word) - 1 or (char in vowels and i < len(word) - 1 and word[i+1] not in vowels):
624
- if current_syllable:
625
  syllables.append(current_syllable)
626
  current_syllable = ''
627
-
628
- i += 1
629
-
630
- # Add any remaining parts
631
- if consonant_cluster:
632
- if syllables:
633
- syllables[-1] += consonant_cluster
634
- else:
635
- syllables.append(consonant_cluster)
636
 
637
  if current_syllable:
638
  syllables.append(current_syllable)
639
 
640
- # Special case handling
641
- result = '-'.join(syllables) if syllables else word
642
-
643
- # If we ended up with no breaks, provide a simpler approach
644
- if result == word and len(word) > 3:
645
- # Simple fallback: break after every other letter
646
- syllables = [word[i:i+2] for i in range(0, len(word), 2)]
647
- result = '-'.join(syllables)
648
-
649
- return result
650
 
651
  @tool
652
  def generate_targeted_story(previous_feedback: str, name: str, grade: str, missed_words: list = None) -> str:
@@ -666,38 +521,15 @@ def generate_targeted_story(previous_feedback: str, name: str, grade: str, misse
666
  grade_num = int(''.join(filter(str.isdigit, grade)) or "3")
667
  age = grade_num + 5
668
 
669
- # Dynamically determine story parameters based on grade - match the same criteria as main story generation
670
- if grade_num <= 2:
671
- # Grades 1-2: Very simple stories
672
- story_length = "2-3 short sentences"
673
- vocabulary_level = "very simple words (mostly 1-2 syllables)"
674
- sentence_structure = "short, simple sentences"
675
- complexity = "basic concepts"
676
- reading_level = "beginner"
677
- elif grade_num <= 4:
678
- # Grades 3-4: Intermediate stories
679
- story_length = "1-2 short paragraphs"
680
- vocabulary_level = "age-appropriate words with some longer words"
681
- sentence_structure = "mix of simple and compound sentences"
682
- complexity = "intermediate concepts with some detail"
683
- reading_level = "intermediate"
684
- else:
685
- # Grades 5-6: More advanced stories
686
- story_length = "2-3 paragraphs"
687
- vocabulary_level = "varied vocabulary including descriptive words"
688
- sentence_structure = "complex sentences with descriptive language"
689
- complexity = "detailed concepts and explanations"
690
- reading_level = "advanced elementary"
691
-
692
  # Extract difficulty level from previous feedback
693
  if "AMAZING" in previous_feedback or "accuracy: 9" in previous_feedback:
694
- difficulty_adjustment = "slightly more challenging but still within grade level"
695
  focus_area = "new vocabulary and longer sentences"
696
  elif "GOOD" in previous_feedback or "accuracy: 8" in previous_feedback:
697
  difficulty_adjustment = "similar level with some new words"
698
  focus_area = "reinforcing current skills"
699
  else:
700
- difficulty_adjustment = "slightly simpler but still grade-appropriate"
701
  focus_area = "basic vocabulary and simple sentences"
702
 
703
  # Create targeted practice words
@@ -711,16 +543,8 @@ def generate_targeted_story(previous_feedback: str, name: str, grade: str, misse
711
  prompt = f"""
712
  You are an expert reading coach creating a personalized story for {name}, a {age}-year-old in {grade}.
713
 
714
- GRADE LEVEL: {grade} ({reading_level} level)
715
-
716
- STORY SPECIFICATIONS:
717
- - Length: {story_length}
718
- - Vocabulary: {vocabulary_level}
719
- - Sentence structure: {sentence_structure}
720
- - Complexity: {complexity}
721
-
722
  LEARNING ADAPTATION:
723
- - Make this story {difficulty_adjustment}
724
  - Focus on: {focus_area}
725
  - {word_focus}
726
 
@@ -737,17 +561,17 @@ def generate_targeted_story(previous_feedback: str, name: str, grade: str, misse
737
  """
738
 
739
  # Generate targeted story
 
740
  max_tokens = 300 if grade_num <= 2 else 600 if grade_num <= 4 else 1000
741
 
742
- generation_config = genai.GenerationConfig(
743
- temperature=0.7,
744
- max_output_tokens=max_tokens,
745
- top_p=0.9,
746
- )
747
 
748
- response = gemini_client.models.generate_content(
749
- model="gemini-2.5-flash",
750
- contents=[prompt],
751
  generation_config=generation_config
752
  )
753
 
@@ -826,18 +650,6 @@ class ReadingCoachAgent:
826
  # Transcribe the audio
827
  transcribed_text = transcribe_audio(audio_path)
828
 
829
- # Check if the transcribed text is an error message or empty
830
- if transcribed_text.startswith("Error:") or transcribed_text.startswith("I couldn't hear") or len(transcribed_text.strip()) < 3:
831
- # Return a helpful message instead of giving feedback with accuracy points
832
- error_feedback = "⚠️ I couldn't hear your reading clearly. Please try again and make sure to:\n"
833
- error_feedback += "• Speak clearly and at a normal pace\n"
834
- error_feedback += "• Make sure your microphone is working properly\n"
835
- error_feedback += "• Try reading in a quieter environment\n"
836
- error_feedback += "• Read the complete story from beginning to end\n\n"
837
- error_feedback += "Reading accuracy: 0.0%"
838
-
839
- return transcribed_text, error_feedback, 0.0
840
-
841
  # Compare with original story and get feedback
842
  feedback = compare_texts_for_feedback(self.current_story, transcribed_text)
843
 
@@ -871,25 +683,8 @@ class ReadingCoachAgent:
871
  name = self.student_info["name"]
872
  grade = self.student_info["grade"]
873
 
874
- # Get the last feedback to personalize the practice story
875
- last_feedback = ""
876
- missed_words_list = []
877
-
878
- # Extract missed words from feedback if available
879
- if self.current_session:
880
- session_data = self.session_manager.get_session(self.current_session)
881
- if session_data and "feedback_history" in session_data and session_data["feedback_history"]:
882
- last_feedback = session_data["feedback_history"][-1]["feedback"]
883
-
884
- # Extract missed words from the feedback
885
- import re
886
- if "PRACTICE THESE WORDS:" in last_feedback:
887
- # Find all words that appear after bullet points
888
- matches = re.findall(r'• ([A-Z]+)', last_feedback)
889
- missed_words_list = [word.lower() for word in matches]
890
-
891
  # Generate a new practice story using the targeted story function
892
- practice_story = generate_targeted_story(last_feedback, name, grade, missed_words_list)
893
  self.current_story = practice_story
894
 
895
  return practice_story
@@ -912,39 +707,3 @@ class ReadingCoachAgent:
912
  if match:
913
  return float(match.group(1))
914
  return 0.0
915
-
916
- def _extract_missed_words_from_feedback(feedback: str) -> list:
917
- """
918
- Extract missed words from feedback text.
919
-
920
- Args:
921
- feedback (str): Feedback text containing missed words
922
-
923
- Returns:
924
- list: List of missed words
925
- """
926
- import re
927
- missed_words = []
928
-
929
- # Check if feedback contains practice words section
930
- if "PRACTICE THESE WORDS:" in feedback:
931
- # Extract the section with practice words
932
- practice_section = feedback.split("PRACTICE THESE WORDS:")[1].split("\n")[1:]
933
- # Extract words that appear after bullet points
934
- for line in practice_section:
935
- if "•" in line and "-" in line:
936
- # Extract word before the dash
937
- match = re.search(r'• ([A-Z]+) -', line)
938
- if match:
939
- missed_words.append(match.group(1).lower())
940
-
941
- # If we also have mispronounced words, add them too
942
- if "PRONUNCIATION PRACTICE:" in feedback:
943
- pronun_section = feedback.split("PRONUNCIATION PRACTICE:")[1].split("\n")[1:]
944
- for line in pronun_section:
945
- if "•" in line and "(you said" in line:
946
- match = re.search(r'• ([A-Z]+) \(you said', line)
947
- if match:
948
- missed_words.append(match.group(1).lower())
949
-
950
- return missed_words
 
2
  import requests
3
  from smolagents.tools import tool
4
  from difflib import SequenceMatcher
 
5
  try:
6
  from gradio_client import Client
7
  except ImportError:
8
  # Fallback import for older versions
9
  import gradio_client
10
  Client = gradio_client.Client
11
+ import google.generativeai as genai
 
12
  import json
13
  import time
14
  import numpy as np
 
24
  STT_API = os.getenv("STT_API")
25
  GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
26
 
27
+ # Configure Google Gemini
28
  if GOOGLE_API_KEY:
29
+ genai.configure(api_key=GOOGLE_API_KEY)
30
 
31
  @tool
32
  def generate_story(name: str, grade: str, topic: str) -> str:
 
95
  """
96
 
97
  # Use Google Gemini
98
+ model = genai.GenerativeModel('gemini-1.5-flash')
99
+
100
  # Adjust generation parameters based on grade level
101
  max_tokens = 300 if grade_num <= 2 else 600 if grade_num <= 4 else 1000
102
 
103
+ generation_config = {
104
+ "temperature": 0.8,
105
+ "max_output_tokens": max_tokens,
106
+ "top_p": 0.9,
107
+ }
108
 
109
+ response = model.generate_content(
110
+ contents=prompt,
111
+ generation_config=generation_config
 
112
  )
113
 
114
  return response.text.strip()
 
321
  Returns:
322
  str: Comprehensive, age-appropriate feedback with learning suggestions.
323
  """
 
 
 
 
324
  # Clean and process text
325
  orig_words = [w.strip(".,!?;:\"'").lower() for w in original.split() if w.strip()]
326
  spoken_words = [w.strip(".,!?;:\"'").lower() for w in spoken.split() if w.strip()]
327
 
 
 
 
 
 
 
328
  # Calculate accuracy using sequence matching
329
  matcher = SequenceMatcher(None, orig_words, spoken_words, autojunk=False)
330
  accuracy = matcher.ratio() * 100
331
 
332
+ # Identify different types of errors
333
+ missed_words = set(orig_words) - set(spoken_words)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
  extra_words = set(spoken_words) - set(orig_words)
335
 
336
  # Find mispronounced words (words that sound similar but are different)
337
  mispronounced = find_similar_words(orig_words, spoken_words)
338
 
 
 
 
 
 
339
  # Generate age-appropriate feedback
340
+ return generate_adaptive_feedback(accuracy, missed_words, extra_words, mispronounced, len(orig_words))
341
 
342
  def find_similar_words(original_words: list, spoken_words: list) -> list:
343
  """
 
435
  return f"Sound it out: {'-'.join(word)}"
436
  elif word.endswith('tion'):
437
  return "Ends with 'shun' sound"
 
 
438
  elif word.endswith('ed'):
439
  if word[-3] in 'td':
440
  return "Past tense - ends with 'ed' sound"
 
442
  return "Past tense - ends with 'd' sound"
443
  elif 'th' in word:
444
  return "Put your tongue between your teeth for 'th'"
 
 
 
 
 
 
 
 
445
  elif word.startswith('wh'):
446
  return "Starts with 'w' sound (like 'when')"
 
 
 
 
 
 
 
 
447
  elif len(word) >= 6:
448
  # Break longer words into syllables
449
  return f"Break it down: {break_into_syllables(word)}"
 
473
  return f"Starts with '{orig[0]}' sound, not '{spok[0]}'"
474
  elif orig[-1] != spok[-1]:
475
  return f"Ends with '{orig[-1]}' sound"
476
+ else:
477
+ return f"Listen carefully: '{orig}' - try saying it slower"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
 
479
  def break_into_syllables(word: str) -> str:
480
  """
481
+ Simple syllable breaking for pronunciation help.
482
 
483
  Args:
484
  word (str): Word to break into syllables
 
486
  Returns:
487
  str: Word broken into syllables
488
  """
489
+ vowels = 'aeiou'
 
490
  syllables = []
491
  current_syllable = ''
492
+
493
+ for i, char in enumerate(word):
494
+ current_syllable += char
495
+ # Simple rule: break after vowel if next char is consonant
496
+ if char.lower() in vowels and i < len(word) - 1:
497
+ if word[i + 1].lower() not in vowels:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
498
  syllables.append(current_syllable)
499
  current_syllable = ''
 
 
 
 
 
 
 
 
 
500
 
501
  if current_syllable:
502
  syllables.append(current_syllable)
503
 
504
+ return '-'.join(syllables) if len(syllables) > 1 else word
 
 
 
 
 
 
 
 
 
505
 
506
  @tool
507
  def generate_targeted_story(previous_feedback: str, name: str, grade: str, missed_words: list = None) -> str:
 
521
  grade_num = int(''.join(filter(str.isdigit, grade)) or "3")
522
  age = grade_num + 5
523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
524
  # Extract difficulty level from previous feedback
525
  if "AMAZING" in previous_feedback or "accuracy: 9" in previous_feedback:
526
+ difficulty_adjustment = "slightly more challenging"
527
  focus_area = "new vocabulary and longer sentences"
528
  elif "GOOD" in previous_feedback or "accuracy: 8" in previous_feedback:
529
  difficulty_adjustment = "similar level with some new words"
530
  focus_area = "reinforcing current skills"
531
  else:
532
+ difficulty_adjustment = "simpler and shorter"
533
  focus_area = "basic vocabulary and simple sentences"
534
 
535
  # Create targeted practice words
 
543
  prompt = f"""
544
  You are an expert reading coach creating a personalized story for {name}, a {age}-year-old in {grade}.
545
 
 
 
 
 
 
 
 
 
546
  LEARNING ADAPTATION:
547
+ - Make this story {difficulty_adjustment} than the previous one
548
  - Focus on: {focus_area}
549
  - {word_focus}
550
 
 
561
  """
562
 
563
  # Generate targeted story
564
+ model = genai.GenerativeModel('gemini-1.5-flash')
565
  max_tokens = 300 if grade_num <= 2 else 600 if grade_num <= 4 else 1000
566
 
567
+ generation_config = {
568
+ "temperature": 0.7,
569
+ "max_output_tokens": max_tokens,
570
+ "top_p": 0.9,
571
+ }
572
 
573
+ response = model.generate_content(
574
+ contents=prompt,
 
575
  generation_config=generation_config
576
  )
577
 
 
650
  # Transcribe the audio
651
  transcribed_text = transcribe_audio(audio_path)
652
 
 
 
 
 
 
 
 
 
 
 
 
 
653
  # Compare with original story and get feedback
654
  feedback = compare_texts_for_feedback(self.current_story, transcribed_text)
655
 
 
683
  name = self.student_info["name"]
684
  grade = self.student_info["grade"]
685
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
686
  # Generate a new practice story using the targeted story function
687
+ practice_story = generate_targeted_story("", name, grade)
688
  self.current_story = practice_story
689
 
690
  return practice_story
 
707
  if match:
708
  return float(match.group(1))
709
  return 0.0