sonikan commited on
Commit
c4db906
·
1 Parent(s): ae9daf6

add ai improvement

Browse files
Files changed (47) hide show
  1. app/__pycache__/__init__.cpython-311.pyc +0 -0
  2. app/__pycache__/config.cpython-311.pyc +0 -0
  3. app/__pycache__/database.cpython-311.pyc +0 -0
  4. app/__pycache__/database.cpython-314.pyc +0 -0
  5. app/__pycache__/main.cpython-311.pyc +0 -0
  6. app/models/__pycache__/__init__.cpython-311.pyc +0 -0
  7. app/models/__pycache__/concept.cpython-311.pyc +0 -0
  8. app/models/__pycache__/content.cpython-311.pyc +0 -0
  9. app/models/__pycache__/help_request.cpython-311.pyc +0 -0
  10. app/models/__pycache__/notification.cpython-311.pyc +0 -0
  11. app/models/__pycache__/points.cpython-311.pyc +0 -0
  12. app/models/__pycache__/teacher.cpython-311.pyc +0 -0
  13. app/models/content.py +1 -0
  14. app/routes/__pycache__/__init__.cpython-311.pyc +0 -0
  15. app/routes/__pycache__/ai.cpython-311.pyc +0 -0
  16. app/routes/__pycache__/auth.cpython-311.pyc +0 -0
  17. app/routes/__pycache__/community.cpython-311.pyc +0 -0
  18. app/routes/__pycache__/concepts.cpython-311.pyc +0 -0
  19. app/routes/__pycache__/content.cpython-311.pyc +0 -0
  20. app/routes/__pycache__/help.cpython-311.pyc +0 -0
  21. app/routes/__pycache__/notifications.cpython-311.pyc +0 -0
  22. app/routes/__pycache__/points.cpython-311.pyc +0 -0
  23. app/routes/__pycache__/suggestions.cpython-311.pyc +0 -0
  24. app/routes/__pycache__/translate.cpython-311.pyc +0 -0
  25. app/routes/help.py +8 -6
  26. app/routes/suggestions.py +7 -5
  27. app/schemas/__pycache__/__init__.cpython-311.pyc +0 -0
  28. app/schemas/__pycache__/auth.cpython-311.pyc +0 -0
  29. app/schemas/__pycache__/concept.cpython-311.pyc +0 -0
  30. app/schemas/__pycache__/content.cpython-311.pyc +0 -0
  31. app/schemas/__pycache__/help_request.cpython-311.pyc +0 -0
  32. app/schemas/__pycache__/points.cpython-311.pyc +0 -0
  33. app/schemas/__pycache__/teacher.cpython-311.pyc +0 -0
  34. app/schemas/content.py +1 -0
  35. app/services/__pycache__/__init__.cpython-311.pyc +0 -0
  36. app/services/__pycache__/auth.cpython-311.pyc +0 -0
  37. app/services/__pycache__/cloudinary_service.cpython-311.pyc +0 -0
  38. app/services/__pycache__/concept_resolver.cpython-311.pyc +0 -0
  39. app/services/__pycache__/content_service.cpython-311.pyc +0 -0
  40. app/services/__pycache__/gemini_service.cpython-311.pyc +0 -0
  41. app/services/__pycache__/points_service.cpython-311.pyc +0 -0
  42. app/services/__pycache__/speech_service.cpython-311.pyc +0 -0
  43. app/services/__pycache__/translation_service.cpython-311.pyc +0 -0
  44. app/services/concept_resolver.py +10 -1
  45. app/services/content_service.py +38 -4
  46. app/services/gemini_service.py +51 -2
  47. app/services/speech_service.py +11 -2
app/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (129 Bytes). View file
 
app/__pycache__/config.cpython-311.pyc ADDED
Binary file (1.85 kB). View file
 
app/__pycache__/database.cpython-311.pyc ADDED
Binary file (1.46 kB). View file
 
app/__pycache__/database.cpython-314.pyc CHANGED
Binary files a/app/__pycache__/database.cpython-314.pyc and b/app/__pycache__/database.cpython-314.pyc differ
 
app/__pycache__/main.cpython-311.pyc ADDED
Binary file (2.73 kB). View file
 
app/models/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (921 Bytes). View file
 
app/models/__pycache__/concept.cpython-311.pyc ADDED
Binary file (2.55 kB). View file
 
app/models/__pycache__/content.cpython-311.pyc ADDED
Binary file (4.17 kB). View file
 
app/models/__pycache__/help_request.cpython-311.pyc ADDED
Binary file (3.05 kB). View file
 
app/models/__pycache__/notification.cpython-311.pyc ADDED
Binary file (1.91 kB). View file
 
app/models/__pycache__/points.cpython-311.pyc ADDED
Binary file (1.58 kB). View file
 
app/models/__pycache__/teacher.cpython-311.pyc ADDED
Binary file (1.53 kB). View file
 
app/models/content.py CHANGED
@@ -36,6 +36,7 @@ class UploadedContent(Base):
36
  title = Column(Text, nullable=False)
37
  content_url = Column(Text) # URL or file path
38
  description = Column(Text) # Brief summary
 
39
 
40
  # Source tracking
41
  source_type = Column(Text, default="internal") # internal, external
 
36
  title = Column(Text, nullable=False)
37
  content_url = Column(Text) # URL or file path
38
  description = Column(Text) # Brief summary
39
+ ai_summary = Column(Text) # AI-generated teacher-friendly summary
40
 
41
  # Source tracking
42
  source_type = Column(Text, default="internal") # internal, external
app/routes/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (975 Bytes). View file
 
app/routes/__pycache__/ai.cpython-311.pyc ADDED
Binary file (10.5 kB). View file
 
app/routes/__pycache__/auth.cpython-311.pyc ADDED
Binary file (5.41 kB). View file
 
app/routes/__pycache__/community.cpython-311.pyc ADDED
Binary file (4.04 kB). View file
 
app/routes/__pycache__/concepts.cpython-311.pyc ADDED
Binary file (3.57 kB). View file
 
app/routes/__pycache__/content.cpython-311.pyc ADDED
Binary file (18.9 kB). View file
 
app/routes/__pycache__/help.cpython-311.pyc ADDED
Binary file (11.3 kB). View file
 
app/routes/__pycache__/notifications.cpython-311.pyc ADDED
Binary file (6.53 kB). View file
 
app/routes/__pycache__/points.cpython-311.pyc ADDED
Binary file (1.9 kB). View file
 
app/routes/__pycache__/suggestions.cpython-311.pyc ADDED
Binary file (5.02 kB). View file
 
app/routes/__pycache__/translate.cpython-311.pyc ADDED
Binary file (4.18 kB). View file
 
app/routes/help.py CHANGED
@@ -80,7 +80,11 @@ def create_help_request(
80
  status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
81
  detail="Speech recognition not available"
82
  )
83
- query_text, detected_language = SpeechService.transcribe_audio(request.audio_base64)
 
 
 
 
84
 
85
  if not query_text:
86
  raise HTTPException(
@@ -90,11 +94,9 @@ def create_help_request(
90
 
91
  # CRITICAL: Resolve to concept_id
92
  # This is the core of the multilingual search system
93
- concept_id, language, normalized_text = ConceptResolver.resolve_concept(db, query_text)
94
-
95
- # Use detected language from speech if available
96
- if detected_language:
97
- language = detected_language
98
 
99
  # Store help request for analytics
100
  help_request = HelpRequest(
 
80
  status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
81
  detail="Speech recognition not available"
82
  )
83
+ language_hint = current_teacher.language_preference
84
+ query_text, detected_language = SpeechService.transcribe_audio(
85
+ request.audio_base64,
86
+ language_hint=language_hint
87
+ )
88
 
89
  if not query_text:
90
  raise HTTPException(
 
94
 
95
  # CRITICAL: Resolve to concept_id
96
  # This is the core of the multilingual search system
97
+ concept_id, language, normalized_text = ConceptResolver.resolve_concept(
98
+ db, query_text, speech_language=detected_language
99
+ )
 
 
100
 
101
  # Store help request for analytics
102
  help_request = HelpRequest(
app/routes/suggestions.py CHANGED
@@ -29,6 +29,7 @@ router = APIRouter(prefix="/suggestions", tags=["Suggestions"])
29
  def get_suggestions(
30
  concept_id: str = Query(..., description="The resolved concept ID"),
31
  language: Optional[str] = Query(None, description="Language override"),
 
32
  limit: int = Query(10, ge=1, le=50),
33
  db: Session = Depends(get_db),
34
  current_teacher: Teacher = Depends(get_current_teacher)
@@ -65,7 +66,8 @@ def get_suggestions(
65
  db,
66
  concept_id,
67
  target_lang,
68
- limit
 
69
  )
70
 
71
  # Build response
@@ -88,8 +90,8 @@ def get_suggestions(
88
  source_type=content.source_type,
89
  is_verified=content.is_verified,
90
  created_at=content.created_at,
91
- feedback_score=item["feedback_score"],
92
- uploader_name=item["uploader_name"]
93
  ))
94
  source = item["source"]
95
  else:
@@ -115,8 +117,8 @@ def get_suggestions(
115
  source_type=content.source_type,
116
  is_verified=content.is_verified,
117
  created_at=content.created_at,
118
- feedback_score=0,
119
- uploader_name="Google Search"
120
  ))
121
 
122
  # Add warning message for unverified content
 
29
  def get_suggestions(
30
  concept_id: str = Query(..., description="The resolved concept ID"),
31
  language: Optional[str] = Query(None, description="Language override"),
32
+ problem_description: Optional[str] = Query(None, description="Detailed problem context from teacher"),
33
  limit: int = Query(10, ge=1, le=50),
34
  db: Session = Depends(get_db),
35
  current_teacher: Teacher = Depends(get_current_teacher)
 
66
  db,
67
  concept_id,
68
  target_lang,
69
+ limit,
70
+ problem_description
71
  )
72
 
73
  # Build response
 
90
  source_type=content.source_type,
91
  is_verified=content.is_verified,
92
  created_at=content.created_at,
93
+ uploader_name=item["uploader_name"],
94
+ ai_summary=content.ai_summary
95
  ))
96
  source = item["source"]
97
  else:
 
117
  source_type=content.source_type,
118
  is_verified=content.is_verified,
119
  created_at=content.created_at,
120
+ uploader_name="Google Search",
121
+ ai_summary=content.ai_summary
122
  ))
123
 
124
  # Add warning message for unverified content
app/schemas/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (1.11 kB). View file
 
app/schemas/__pycache__/auth.cpython-311.pyc ADDED
Binary file (1.21 kB). View file
 
app/schemas/__pycache__/concept.cpython-311.pyc ADDED
Binary file (1.75 kB). View file
 
app/schemas/__pycache__/content.cpython-311.pyc ADDED
Binary file (3.25 kB). View file
 
app/schemas/__pycache__/help_request.cpython-311.pyc ADDED
Binary file (1.97 kB). View file
 
app/schemas/__pycache__/points.cpython-311.pyc ADDED
Binary file (1.39 kB). View file
 
app/schemas/__pycache__/teacher.cpython-311.pyc ADDED
Binary file (1.8 kB). View file
 
app/schemas/content.py CHANGED
@@ -35,6 +35,7 @@ class ContentResponse(BaseModel):
35
  # Computed fields for display
36
  feedback_score: Optional[float] = None
37
  uploader_name: Optional[str] = None
 
38
  likes_count: int = 0
39
  views_count: int = 0
40
  user_liked: bool = False
 
35
  # Computed fields for display
36
  feedback_score: Optional[float] = None
37
  uploader_name: Optional[str] = None
38
+ ai_summary: Optional[str] = None
39
  likes_count: int = 0
40
  views_count: int = 0
41
  user_liked: bool = False
app/services/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (647 Bytes). View file
 
app/services/__pycache__/auth.cpython-311.pyc ADDED
Binary file (4.96 kB). View file
 
app/services/__pycache__/cloudinary_service.cpython-311.pyc ADDED
Binary file (7.69 kB). View file
 
app/services/__pycache__/concept_resolver.cpython-311.pyc ADDED
Binary file (23 kB). View file
 
app/services/__pycache__/content_service.cpython-311.pyc ADDED
Binary file (14.8 kB). View file
 
app/services/__pycache__/gemini_service.cpython-311.pyc ADDED
Binary file (19.1 kB). View file
 
app/services/__pycache__/points_service.cpython-311.pyc ADDED
Binary file (4.66 kB). View file
 
app/services/__pycache__/speech_service.cpython-311.pyc ADDED
Binary file (4.36 kB). View file
 
app/services/__pycache__/translation_service.cpython-311.pyc ADDED
Binary file (11.8 kB). View file
 
app/services/concept_resolver.py CHANGED
@@ -165,13 +165,14 @@ class ConceptResolver:
165
  return text
166
 
167
  @staticmethod
168
- def resolve_concept(db: Session, text: str) -> Tuple[Optional[str], str, str]:
169
  """
170
  Main resolution function.
171
 
172
  Args:
173
  db: Database session
174
  text: User input in any language
 
175
 
176
  Returns:
177
  Tuple of (concept_id, detected_language, normalized_text)
@@ -179,6 +180,14 @@ class ConceptResolver:
179
  """
180
  # Step 1: Detect language
181
  language = ConceptResolver.detect_language(text)
 
 
 
 
 
 
 
 
182
  print(f"[ConceptResolver] Input: '{text}' | Language: {language}")
183
 
184
  # Step 2: Normalize text
 
165
  return text
166
 
167
  @staticmethod
168
+ def resolve_concept(db: Session, text: str, speech_language: Optional[str] = None) -> Tuple[Optional[str], str, str]:
169
  """
170
  Main resolution function.
171
 
172
  Args:
173
  db: Database session
174
  text: User input in any language
175
+ speech_language: Optional language detected by speech engine
176
 
177
  Returns:
178
  Tuple of (concept_id, detected_language, normalized_text)
 
180
  """
181
  # Step 1: Detect language
182
  language = ConceptResolver.detect_language(text)
183
+
184
+ # If script detection says "en" but speech engine detected "kn" or "hi",
185
+ # it's likely transliterated text (Hinglish/Kanglish).
186
+ # In this case, trust the speech engine.
187
+ if language == "en" and speech_language in ["kn", "hi"]:
188
+ language = speech_language
189
+ print(f"[ConceptResolver] Overriding script language 'en' with speech language '{language}' (Transliteration detected)")
190
+
191
  print(f"[ConceptResolver] Input: '{text}' | Language: {language}")
192
 
193
  # Step 2: Normalize text
app/services/content_service.py CHANGED
@@ -15,6 +15,7 @@ import uuid
15
 
16
  from app.models.content import UploadedContent, ContentFeedback, ContentInteraction
17
  from app.models.teacher import Teacher
 
18
  from app.services.gemini_service import GeminiService
19
 
20
 
@@ -30,7 +31,8 @@ class ContentService:
30
  db: Session,
31
  concept_id: str,
32
  teacher_language: str = "en",
33
- limit: int = 10
 
34
  ) -> Tuple[List[UploadedContent], str]:
35
  """
36
  Get content suggestions for a concept.
@@ -114,7 +116,11 @@ class ContentService:
114
 
115
  # Step 4: Use Google Web Search via Gemini to find external content
116
  print(f"[ContentService] No content found for '{concept_id}', trying Google Web Search...")
117
- search_results = GeminiService.google_web_search(concept_id.replace("_", " "), num_results=5)
 
 
 
 
118
 
119
  if search_results:
120
  # Create/Get content entries from search results
@@ -130,6 +136,17 @@ class ContentService:
130
  ).first()
131
 
132
  if existing_content:
 
 
 
 
 
 
 
 
 
 
 
133
  web_content.append(existing_content)
134
  continue
135
 
@@ -140,14 +157,30 @@ class ContentService:
140
  elif url.endswith(".pdf"):
141
  content_type = "document"
142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  # Persist new content (without specific uploader)
144
  new_content = UploadedContent(
145
  id=uuid.uuid4(), # Explicitly setting UUID or letting DB handle it
146
  title=result.get("title", "External Resource"),
147
  description=result.get("snippet", "Found via Google Search"),
 
148
  content_type=content_type,
149
  content_url=url,
150
  concept_id=concept_id,
 
 
151
  language="en", # Default to English for external content
152
  source_type="external",
153
  is_verified=False,
@@ -174,14 +207,15 @@ class ContentService:
174
  db: Session,
175
  concept_id: str,
176
  teacher_language: str = "en",
177
- limit: int = 10
 
178
  ) -> List[dict]:
179
  """
180
  Get content with computed feedback scores.
181
  Returns dictionaries with content and score.
182
  """
183
  content_list, source = ContentService.get_suggestions(
184
- db, concept_id, teacher_language, limit
185
  )
186
 
187
  # For Google Search results, return directly without DB queries
 
15
 
16
  from app.models.content import UploadedContent, ContentFeedback, ContentInteraction
17
  from app.models.teacher import Teacher
18
+ from app.models.concept import Concept
19
  from app.services.gemini_service import GeminiService
20
 
21
 
 
31
  db: Session,
32
  concept_id: str,
33
  teacher_language: str = "en",
34
+ limit: int = 10,
35
+ problem_description: Optional[str] = None
36
  ) -> Tuple[List[UploadedContent], str]:
37
  """
38
  Get content suggestions for a concept.
 
116
 
117
  # Step 4: Use Google Web Search via Gemini to find external content
118
  print(f"[ContentService] No content found for '{concept_id}', trying Google Web Search...")
119
+ search_results = GeminiService.google_web_search(
120
+ concept_id.replace("_", " "),
121
+ num_results=5,
122
+ problem_description=problem_description
123
+ )
124
 
125
  if search_results:
126
  # Create/Get content entries from search results
 
136
  ).first()
137
 
138
  if existing_content:
139
+ # If we have a specific problem description, re-generate summary even for existing content
140
+ # to ensure it's tailored to the current session.
141
+ if problem_description:
142
+ # Re-generate summary dynamically (won't persist to DB unless explicit save)
143
+ # This gives a "session-aware" summary
144
+ existing_content.ai_summary = GeminiService.generate_summary(
145
+ title=existing_content.title,
146
+ snippet=existing_content.description,
147
+ topic=concept_id.replace("_", " ").title(),
148
+ problem_description=problem_description
149
+ )
150
  web_content.append(existing_content)
151
  continue
152
 
 
157
  elif url.endswith(".pdf"):
158
  content_type = "document"
159
 
160
+ # Get concept details for subject and grade
161
+ concept = db.query(Concept).filter(Concept.concept_id == concept_id).first()
162
+ subject = concept.subject if concept else "General"
163
+ grade = concept.grade if concept else "All"
164
+
165
+ # Generate AI summary for better teacher experience
166
+ ai_summary = GeminiService.generate_summary(
167
+ title=result.get("title", "External Resource"),
168
+ snippet=result.get("snippet", ""),
169
+ topic=concept_id.replace("_", " ").title(),
170
+ problem_description=problem_description
171
+ )
172
+
173
  # Persist new content (without specific uploader)
174
  new_content = UploadedContent(
175
  id=uuid.uuid4(), # Explicitly setting UUID or letting DB handle it
176
  title=result.get("title", "External Resource"),
177
  description=result.get("snippet", "Found via Google Search"),
178
+ ai_summary=ai_summary,
179
  content_type=content_type,
180
  content_url=url,
181
  concept_id=concept_id,
182
+ subject=subject,
183
+ grade=grade,
184
  language="en", # Default to English for external content
185
  source_type="external",
186
  is_verified=False,
 
207
  db: Session,
208
  concept_id: str,
209
  teacher_language: str = "en",
210
+ limit: int = 10,
211
+ problem_description: Optional[str] = None
212
  ) -> List[dict]:
213
  """
214
  Get content with computed feedback scores.
215
  Returns dictionaries with content and score.
216
  """
217
  content_list, source = ContentService.get_suggestions(
218
+ db, concept_id, teacher_language, limit, problem_description
219
  )
220
 
221
  # For Google Search results, return directly without DB queries
app/services/gemini_service.py CHANGED
@@ -96,7 +96,7 @@ class GeminiService:
96
  raise e
97
 
98
  @staticmethod
99
- def google_web_search(query: str, num_results: int = 5) -> List[dict]:
100
  """
101
  Use Google Search via Gemini API to find educational content.
102
 
@@ -107,10 +107,14 @@ class GeminiService:
107
  return []
108
 
109
  try:
 
 
 
 
110
  # Use google_search tool with Gemini
111
  data = {
112
  "contents": [{
113
- "parts": [{"text": f"Find {num_results} educational resources (videos, articles, websites) about: {query}. For each result, provide the title, URL, and a brief description. Focus on educational content suitable for teachers and students."}]
114
  }],
115
  "tools": [{
116
  "google_search": {}
@@ -396,3 +400,48 @@ Rules:
396
  "search_keywords": [query],
397
  "error": str(e)
398
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  raise e
97
 
98
  @staticmethod
99
+ def google_web_search(query: str, num_results: int = 5, problem_description: str = None) -> List[dict]:
100
  """
101
  Use Google Search via Gemini API to find educational content.
102
 
 
107
  return []
108
 
109
  try:
110
+ search_query = f"educational resources about {query}"
111
+ if problem_description:
112
+ search_query += f" specifically help for: {problem_description}"
113
+
114
  # Use google_search tool with Gemini
115
  data = {
116
  "contents": [{
117
+ "parts": [{"text": f"Find {num_results} {search_query}. For each result, provide the title, URL, and a brief description. Focus on educational content suitable for teachers and students."}]
118
  }],
119
  "tools": [{
120
  "google_search": {}
 
400
  "search_keywords": [query],
401
  "error": str(e)
402
  }
403
+
404
+ @staticmethod
405
+ def generate_summary(
406
+ title: str,
407
+ snippet: str,
408
+ topic: str = None,
409
+ problem_description: str = None
410
+ ) -> str:
411
+ """
412
+ Generate a teacher-friendly summary for a suggested resource.
413
+
414
+ Args:
415
+ title: Title of the resource
416
+ snippet: Search snippet or context
417
+ topic: The concept/topic name
418
+ problem_description: Specific problem context provided by teacher
419
+
420
+ Returns:
421
+ A concise, high-quality summary
422
+ """
423
+ if not GeminiService.is_available():
424
+ return snippet or "No summary available."
425
+
426
+ try:
427
+ prompt = f"""You are an expert educational consultant helping teachers in India.
428
+ Write a concise, teacher-friendly summary (2-3 sentences) explaining how an educational resource directly solves a teacher's specific classroom problem.
429
+
430
+ Resource Title: {title}
431
+ Resource Context: {snippet}
432
+ {f'Core Topic: {topic}' if topic else ''}
433
+ {f"Teacher's Specific Problem: {problem_description}" if problem_description else ""}
434
+
435
+ Rules:
436
+ 1. FOCUS: If a specific problem is provided, the summary MUST explain how this resource solves THAT specific problem.
437
+ 2. AVOID: Do not waste words describing the platform (e.g., "Khan Academy offers videos"). Instead, say "This resource helps you explain [Topic] using [Method] to address [Problem]".
438
+ 3. DEPTH: Mention specific features or content (from the snippet) that are relevant to the problem.
439
+ 4. TONE: Professional, practical, and highly encouraging.
440
+ 5. CONCISENESS: Under 60 words. No intro/outro.
441
+
442
+ Summary:"""
443
+
444
+ return GeminiService._call_gemini(prompt).strip()
445
+ except Exception as e:
446
+ print(f"[GeminiService] Summary generation failed: {e}")
447
+ return snippet or "No summary available."
app/services/speech_service.py CHANGED
@@ -50,12 +50,13 @@ class SpeechService:
50
  """
51
 
52
  @staticmethod
53
- def transcribe_audio(audio_base64: str) -> Tuple[str, str]:
54
  """
55
  Transcribe base64-encoded audio to text.
56
 
57
  Args:
58
  audio_base64: Base64 encoded audio data
 
59
 
60
  Returns:
61
  Tuple of (transcribed_text, detected_language)
@@ -76,10 +77,18 @@ class SpeechService:
76
  try:
77
  model = get_whisper_model()
78
 
79
- # Transcribe with language detection
 
 
 
 
 
 
 
80
  result = model.transcribe(
81
  tmp_path,
82
  task="transcribe",
 
83
  )
84
 
85
  text = result["text"].strip()
 
50
  """
51
 
52
  @staticmethod
53
+ def transcribe_audio(audio_base64: str, language_hint: str = None) -> Tuple[str, str]:
54
  """
55
  Transcribe base64-encoded audio to text.
56
 
57
  Args:
58
  audio_base64: Base64 encoded audio data
59
+ language_hint: Optional language code hint (en, kn, hi)
60
 
61
  Returns:
62
  Tuple of (transcribed_text, detected_language)
 
77
  try:
78
  model = get_whisper_model()
79
 
80
+ # Map our hint to Whisper language codes
81
+ whisper_lang = None
82
+ if language_hint == "kn":
83
+ whisper_lang = "kn"
84
+ elif language_hint == "hi":
85
+ whisper_lang = "hi"
86
+
87
+ # Transcribe with language detection/hint
88
  result = model.transcribe(
89
  tmp_path,
90
  task="transcribe",
91
+ language=whisper_lang
92
  )
93
 
94
  text = result["text"].strip()