ashokpoudel's picture
Update app.py
48ec3d4 verified
import os
import gradio as gr
import pandas as pd
import numpy as np
import random
import datetime
import uuid
import json
import io # For BytesIO
from huggingface_hub import HfApi, create_repo, HfFileSystem
from datasets import Dataset # Still useful for potential future aggregation
import soundfile as sf
import shutil
import traceback # For detailed error logging
# --- Configuration ---
SAMPLE_PROMPTS = [
# --- Greetings and Introductions ---
"नमस्ते, मेरो नाम __ हो। म नेपाली बोल्छु।",
"शुभ प्रभात! तपाईंलाई कस्तो छ?",
"शुभ रात्री, राम्रोसँग सुत्नुहोस्।",
"मेरो परिवारमा चार जना छन्: बुबा, आमा, दाइ र म।",
"तपाईं कहाँबाट हुनुहुन्छ? म काठमाडौंबाट हुँ।",
"म बिरामी छु, कृपया मलाई सहयोग गर्नुहोस्।",
"तपाईंसँग भेटेर खुसी लाग्यो।",
"मेरो घर पोखरामा छ।",
"के म तपाईंको नाम जान्न सक्छु?",
"उहाँ मेरो मिल्ने साथी हुनुहुन्छ।",
# --- Weather and Nature ---
"आज मौसम धेरै राम्रो र घमाइलो छ।",
"आज बिहानदेखि भारी वर्षा भइरहेको छ।",
"उफ! यो हावाले कति चिसो बनाएको!",
"हिजो राति तराईमा बाक्लो हुस्सु लागेको थियो।",
"सुन्दर मौसममा हरियो डाँडाकाँडा घुम्न जान मन लाग्छ।",
"आकाशमा इन्द्रेणी देखिएको छ।",
"भोलिको मौसम पूर्वानुमान कस्तो छ?",
"रुखहरूमा नयाँ पालुवा पलाएको छ।",
"पहाडबाट झरना बगिरहेको हेर्न कति रमाइलो!",
"समुद्र किनारमा हिँड्न मलाई मन पर्छ।", # (Though Nepal is landlocked, for general ASR)
# --- Places and Travel ---
"नेपाल हिमाल, पहाड र तराईले बनेको एक सुन्दर देश हो।",
"काठमाडौं नेपालको ऐतिहासिक र सांस्कृतिक राजधानी हो।",
"पोखरा फेवातालको मनमोहक किनारमा अवस्थित छ।",
"चितवन राष्ट्रिय निकुञ्जमा दुर्लभ एक सिंगे गैंडा र पाटे बाघ हेर्न पाइन्छ।",
"लुम्बिनी भगवान गौतम बुद्धको पवित्र जन्मस्थल हो।",
"सगरमाथा आरोहण गर्न कति खर्च लाग्छ होला?",
"म अर्को महिना मुक्तिनाथ दर्शन गर्न जाँदैछु।",
"नेपालमा धेरै आकर्षक पर्यटकीय गन्तव्यहरू छन्।",
"यहाँबाट सबैभन्दा नजिकको होटल कुन हो?",
"बसको टिकट कहाँ किन्न पाइन्छ?",
# --- Daily Activities ---
"म आज बिहान छिट्टै उठेँ र स्कूल जाँदैछु।",
"म प्रायः साँझपख पार्कमा दौडिन वा व्यायाम गर्न जान्छु।",
"तपाईंले बिहानको खाजा खानु भयो? मैले त खाइसकेँ।",
"मेरो आज धेरै काम बाँकी छ, रातिसम्ममा सक्नुपर्छ।",
"म आज अफिसमा मिटिङहरूले गर्दा धेरै व्यस्त थिएँ।",
"म अहिले खाना बनाउँदै छु।",
"के तपाईं आज मसँग बजार जानुहुन्छ?",
"मैले गृहकार्य सकेर साथीहरूसँग खेल्न जान्छु।",
"राति सुत्नुअघि म किताब पढ्छु।",
"आजकल म चाँडै सुत्ने र चाँडै उठ्ने प्रयास गर्दैछु।",
# --- Food and Culture ---
"मलाई नेपाली परम्परागत खाना, विशेष गरी दाल, भात, तरकारी धेरै मन पर्छ।",
"मःमः, सेल रोटी र ढिँडो मेरो सबैभन्दा मनपर्ने नेपाली परिकार हुन्।",
"तपाईंले आज दिउँसोको खानामा दाल भात खाउनु भयो?",
"नेपालमा तिहारको बेला समूहमा देउसी-भैलो खेल्ने पुरानो चलन छ।",
"दशैं नेपालीहरूको सबैभन्दा ठूलो र महत्वपूर्ण चाड हो।",
"यो गुन्द्रुकको अचार साह्रै मीठो रहेछ।",
"के तपाईंलाई नेवारी खाजा मन पर्छ?",
"विभिन्न जातजातिका आ-आफ्नै सांस्कृतिक विशेषताहरू छन्।",
"नेपाली लोक संगीत सुन्दा मन आनन्दित हुन्छ।",
"हाम्रो संस्कृतिमा अतिथि देवो भवः भन्ने मान्यता छ।",
# --- History and Religion ---
"भगवान गौतम बुद्ध नेपालको लुम्बिनीमा जन्मिएका थिए।",
"विश्वको सर्वोच्च शिखर सगरमाथा नेपालमा पर्दछ।",
"पोखराको तालबाराही मन्दिर तालको बीचमा रहेको छ।", # Modified slightly for accuracy
"नेपालमा लिच्छविकालीन, मल्लकालीन मठ मन्दिरहरु र वास्तुकला प्रसिद्ध छन्।",
"काठमाडौंमा रहेको पशुपतिनाथ मन्दिर बागमती नदीको किनारमा अवस्थित छ।",
"पृथ्वीनारायण शाहले आधुनिक नेपालको एकीकरण गरेका थिए।",
"स्वयम्भूनाथ स्तूपामा धेरै बाँदरहरू छन्।",
"जानकी मन्दिर सीताको जन्मस्थल जनकपुरमा रहेको छ।",
"नेपालमा हिन्दु र बौद्ध धर्मावलम्बीहरूको बाहुल्यता छ।",
"मनकामना मन्दिर दर्शन गर्न केबलकार चढेर जानुपर्छ।",
# --- Emotions ---
"यो सफलता पाएर म आज निकै खुशी छु।",
"परीक्षामा असफल हुँदा ऊ धेरै दुखी देखिन्छ।",
"किन यस्तो व्यवहार गरेको? तिमी रिसाएको जस्तो देखिन्छौ।",
"यो अनौठो समाचारले मलाई साँच्चै अचम्मित बनाएको छ।",
"आज म सामान्य र शान्त महसुस गर्दैछु, कुनै विशेष कुरा छैन।",
"मलाई अलिकति डर लागिरहेको छ।",
"उनी आफ्नो प्रस्तुतिलाई लिएर उत्साहित छिन्।",
"मैले गरेको गल्तीमा मलाई पछुतो छ।",
"यो कस्तो अचम्मको कुरा हो!",
"मलाई एकदमै दिक्क लाग्यो।",
# --- Hobbies and Interests ---
"म फुर्सदको समयमा विभिन्न प्रकारका पुस्तक पढ्न मन पराउँछु।",
"मैले आजकल गितार बजाउन र गीत गाउन सिक्दैछु।",
"के तपाईंलाई क्रिकेट हेर्न वा फुटबल खेल्न रुचाउनु हुन्छ?",
"मलाई प्रकृति र मानिसहरूको चित्रकला गर्न औधी मन पर्छ।",
"हामी अर्को हप्ता पदयात्रामा जान उत्साहित छौं।",
"बागवानी गर्नु मेरो सोख हो।",
"मलाई विभिन्न देशका मुद्राहरू संकलन गर्न मनपर्छ।",
"के तपाईंलाई खाना पकाउन आउँछ?",
"मलाई नयाँ ठाउँहरू घुम्न र नयाँ संस्कृतिहरू सिक्न मन पर्छ।",
"फोटोग्राफी मेरो रुचिको विषय हो।",
# --- Education and Work ---
"म त्रिभुवन विश्वविद्यालयमा बीए द्वितीय वर्षमा मानविकी संकायमा अध्ययन गर्दैछु।",
"उहाँ एक अनुभवी र सफल वकील हुनुहुन्छ।",
"मैले भर्खरै एउटा नयाँ सामाजिक उद्यम परियोजना सुरु गरेको छु।",
"अन्ततः, मैले लोकसेवाको परीक्षा प्रथम श्रेणीमा उत्तीर्ण गरेँ।",
"आजकल तपाईंको व्यवसाय र कामकाज कस्तो चल्दैछ?",
"म एक सफ्टवेयर इन्जिनियरको रूपमा काम गर्छु।",
"शिक्षण एउटा सम्मानित पेशा हो।",
"के तपाईंले आफ्नो स्नातकोत्तर पूरा गर्नुभयो?",
"म जागिरको खोजीमा छु।",
"कार्यशालामा धेरै उपयोगी जानकारी पाइयो।",
# --- Technology and Media ---
"म अहिले नयाँ मोडलको स्मार्टफोन प्रयोग गर्दैछु।",
"म हरेक दिन जुम मार्फत अनलाइन कक्षा लिन्छु।",
"आजकलका युवाहरू सोशल मिडियामा धेरै समय बिताउँछन्।",
"मैले भर्खरै एउटा उपयोगी मोबाइल एप्लिकेसन विकास गरेको छु।",
"आफ्ना विचारहरू व्यक्त गर्न ब्लग लेख्न मलाई रमाइलो लाग्छ।",
"इन्टरनेटले संसारलाई एउटा सानो गाउँ बनाएको छ।",
"के तपाईंले त्यो भाइरल भिडियो हेर्नुभयो?",
"कृत्रिम बौद्धिकता (AI) भविष्यको प्रविधि हो।",
"म अनलाइन समाचार पोर्टलहरू नियमित रूपमा पढ्छु।",
"डिजिटल भुक्तानीले कारोबारलाई सजिलो बनाएको छ।",
# --- Health and Fitness ---
"म आफ्नो शारीरिक र मानसिक स्वास्थ्यका लागि दैनिक योग अभ्यास गर्छु।",
"लामो र स्वस्थ जीवनका लागि सन्तुलित खानपान आवश्यक छ।",
"हामी सबै रोगमुक्त र सुखी जीवन चाहन्छौं।",
"यदि तपाईंलाई अस्वस्थ महसुस भइरहेको छ भने तुरुन्त डाक्टरको सल्लाह लिनुहोस्।",
"नियमित व्यायामले हाम्रो शरीरलाई बलियो र स्फूर्त बनाउँछ।",
"पर्याप्त निद्रा स्वास्थ्यका लागि महत्त्वपूर्ण छ।",
"तनाव व्यवस्थापन गर्न ध्यान गर्नु राम्रो हुन्छ।",
"धुम्रपान स्वास्थ्यका लागि हानिकारक छ।",
"म हरेक बिहान जगिङ गर्न जान्छु।",
"फलफूल र हरियो सागसब्जी प्रशस्त खानुपर्छ।",
# --- Shopping and Services ---
"म अहिले तरकारी किन्न बजार जान्छु, तपाईंलाई केही चाहिन्छ कि?",
"माफ गर्नुहोस्, यो निलो सर्टको कति पर्छ होला?",
"यो सुन्दर पश्मिना सल कतातिर बनेको होला? यो निकै राम्रो छ।",
"मलाई यो सामानको पेमेन्ट मेरो मोबाइल वालेटबाट गर्न मन छ, के यो सम्भव छ?",
"तपाईंको पसल ठ्याक्कै कहाँनिर छ, मलाई ठेगाना दिनुहुन्छ कि?",
"के यहाँ अनलाइन अर्डर गर्ने सुविधा छ?",
"मलाई यो जुत्ताको साइज अलि मिलेन, साट्न मिल्छ?",
"बैंक कति बजे खुल्छ?",
"मलाई बिजुलीको बिल तिर्नु छ।",
"यो औषधि पसलमा सबै किसिमका औषधि पाइन्छ।",
# --- Family and Relationships ---
"मेरो जेठो दाई गाउँको सरकारी विद्यालयमा पढाउनुहुन्छ।",
"हामी सबै परिवारका सदस्यहरू एक आपसमा धेरै माया र सम्मान गर्छौं।",
"चित्रमा देखिनुहुने व्यक्तिहरू मेरा आदरणीय पुर्खाहरु हुन्।",
"हाम्रो संयुक्त परिवार निकै ठूलो र रमाइलो छ।",
"मेरा बाल्यकालका केही मिल्ने साथीहरु आज मलाई भेट्न आउँदैछन्।",
"आमाबुबाको आज्ञा पालन गर्नु हाम्रो कर्तव्य हो।",
"छिमेकीहरूसँग राम्रो सम्बन्ध राख्नुपर्छ।",
"के तपाईं विवाहित हुनुहुन्छ?",
"मेरा भाइबहिनीहरू धेरै चकचके छन्।",
"सम्बन्धमा विश्वास सबैभन्दा महत्त्वपूर्ण कुरा हो।",
# --- Greetings and Introductions (with Code-Switching) ---
"नमस्ते, मेरो नाम __ हो। म नेपाली बोल्छु and I also speak English.",
"हाई! तपाईंलाई कस्तो छ? Are you feeling okay today?",
"शुभ रात्री, good night, राम्रोसँग सुत्नुहोस्।",
"मेरो family मा चार जना छन्: बुबा, आमा, दाइ र म।",
"तपाईं कहाँबाट हुनुहुन्छ? I am from Kathmandu.",
"म अलि sick छु, please मलाई सहयोग गर्नुहोस्।",
"तपाईंसँग भेटेर खुसी लाग्यो, it was nice meeting you.",
"मेरो घर पोखरामा छ, it's a beautiful city.",
"के म तपाईंको name जान्न सक्छु? What should I call you?",
"उहाँ मेरो best friend हुनुहुन्छ, हामी सँगै हुर्कियौं।",
# --- Weather and Nature (with Code-Switching) ---
"आज मौसम धेरै राम्रो छ, it's very sunny and pleasant.",
"Oh no! आज बिहानदेखि heavy rain भइरहेको छ।",
"यो wind ले कति चिसो बनाएको! It's freezing!",
"हिजो राति तराईमा thick fog लागेको थियो।",
"सुन्दर weather मा हरियो डाँडाकाँडा घुम्न जान मन लाग्छ, especially during spring.",
"आकाशमा beautiful rainbow देखिएको छ।",
"भोलिको weather forecast कस्तो छ? Is it going to rain?",
"रुखहरूमा new leaves पलाएको छ।",
"यो waterfall हेर्न कति amazing!",
"I love walking on the beach, तर नेपालमा beach छैन।",
# --- Places and Travel (with Code-Switching) ---
"नेपाल एक beautiful देश हो, full of mountains, hills, and plains.",
"काठमाडौं नेपालको capital city हो, with a rich history.",
"पोखरा फेवातालको side मा अवस्थित छ, it's very picturesque.",
"चितवन National Park मा tigers and rhinos हेर्न पाइन्छ।",
"लुम्बिनी भगवान बुद्धको birthplace हो, a very sacred place.",
"सगरमाथा climb गर्न कति cost लाग्छ होला? It must be expensive.",
"म अर्को month मुक्तिनाथ दर्शन गर्न जाँदैछु, it's a famous pilgrimage site.",
"नेपालमा धेरै attractive tourist destinations छन्।",
"Excuse me, यहाँबाट सबैभन्दा नजिकको hotel कुन हो?",
"बसको ticket कहाँ किन्न पाइन्छ? Can I book online?",
# --- Daily Activities (with Code-Switching) ---
"म आज बिहान छिट्टै उठेँ and I am going to school now.",
"म प्रायः evening मा पार्कमा jogging गर्न जान्छु for some exercise.",
"तपाईंले breakfast खानु भयो? I just had mine.",
"मेरो आज धेरै work बाँकी छ, I need to finish it by tonight.",
"म आज office मा meetings ले गर्दा धेरै busy थिएँ।",
"म अहिले dinner बनाउँदै छु।",
"Are you free today? मसँग बजार जानुहुन्छ?",
"मैले homework सकेर I'll go play with friends.",
"राति सुत्नुअघि म usually a book पढ्छु।",
"Nowadays, I am trying to sleep early and wake up early.",
# --- Food and Culture (with Code-Switching) ---
"मलाई नेपाली traditional खाना, especially दाल, भात, तरकारी, I love it!",
"मःमः, सेल रोटी and ढिँडो are my favorite Nepali dishes.",
"तपाईंले lunch मा दाल भात खाउनु भयो? What did you have?",
"नेपालमा Tihar को बेला देउसी-भैलो खेल्ने old tradition छ।",
"दशैं is the biggest festival for Nepalis.",
"यो गुन्द्रुकको pickle साह्रै delicious रहेछ।",
"Do you like Newari food? It's quite unique.",
"विभिन्न ethnic groups का आ-आफ्नै cultural traditions छन्।",
"नेपाली folk music सुन्दा I feel so relaxed.",
"हाम्रो culture मा 'अतिथि देवो भवः' meaning guest is god भन्ने मान्यता छ।",
# --- Technology and Media (with Code-Switching) ---
"म अहिले new model को smartphone प्रयोग गर्दैछु।",
"म हरेक दिन Zoom मार्फत online class लिन्छु।",
"आजकलका youngsters Social Media मा धेरै time बिताउँछन्।",
"मैले भर्खरै एउटा useful mobile application develop गरेको छु।",
"आफ्ना thoughts express गर्न blog लेख्न मलाई रमाइलो लाग्छ, it's a good hobby.",
"Internet ले संसारलाई एउटा global village बनाएको छ।",
"Did you see that viral video? It's everywhere.",
"Artificial Intelligence, or AI, भविष्यको technology हो।",
"म online news portals regularly पढ्छु to stay updated.",
"Digital payment ले transactions लाई धेरै easy बनाएको छ।",
# --- Shopping and Services (with Code-Switching) ---
"म अहिले market जान्छु, do you need anything?",
"Excuse me, कति पर्छ यो किताब? What's the price?",
"यो beautiful पश्मिना shawl कता made in होला?",
"मलाई यो item को payment मेरो mobile wallet बाट गर्न मन छ, is that possible?",
"तपाईंको shop ठ्याक्कै कहाँ छ? Can you give me the location?",
"Do you have online ordering facility?",
"मलाई यो shoes को size अलि मिलेन, can I exchange it?",
"बैंक कति बजे open हुन्छ?",
"मलाई electricity bill pay गर्नु छ।",
"यो pharmacy मा सबै A-Z medicine पाइन्छ।",
# --- Work and Office Talk (with Code-Switching) ---
"यो project को deadline कहिले हो?",
"Can we schedule a meeting for tomorrow morning?",
"मैले presentation prepare गरिसकेँ।",
"Please send me the report by end of day.",
"हाम्रो team ले target achieve गर्‍यो।",
"I have a conference call at 3 PM.",
"यो task लाई prioritize गर्नुपर्छ।",
"Could you please follow up on that email?",
"Let's brainstorm some new ideas for the campaign.",
"The client is very happy with our work.",
# --- Casual Conversation Snippets (with Code-Switching) ---
"Actually, मलाई त्यस्तो लाग्दैन।",
"Seriously? त्यो त great news हो!",
"By the way, तपाईंले त्यो movie हेर्नुभयो?",
"Okay, no problem, म manage गर्छु।",
"I think, हामीले plan B मा जानुपर्छ।",
"To be honest, मलाई यो idea मन परेन।",
"Wow, that's amazing! Congratulations!",
"Sorry, I am a bit late today.",
"What's up? सब ठीक छ?",
"Let's catch up soon, है त?",
# --- Asking for Help or Information (with Code-Switching) ---
"Excuse me, can you help me with this address?",
"मलाई यो form fill up गर्न अलि confusion भयो।",
"Do you know where the nearest ATM is?",
"यो ठाउँको बारेमा more information दिन सक्नुहुन्छ?",
"What time does the next bus to Pokhara leave?",
"I am looking for a good restaurant, any recommendations?",
"Could you please repeat that? मैले बुझिनँ।",
"How much does this cost? Is there any discount?",
"Is Wi-Fi available here?",
"Sorry to bother you, तर मलाई direction चाहिएको थियो।",
# --- Greetings and Introductions (with Code-Switching) ---
"नमस्ते, मेरो नाम __ हो। म नेपाली बोल्छु। and I also speak English.",
"हाई! तपाईंलाई कस्तो छ? Are you feeling okay today?",
"शुभ रात्री, good night, राम्रोसँग सुत्नुहोस्।",
"मेरो family मा चार जना छन्: बुबा, आमा, दाइ र म।",
"तपाईं कहाँबाट हुनुहुन्छ? I am from Kathmandu.",
"म अलि sick छु, please मलाई सहयोग गर्नुहोस्।",
"तपाईंसँग भेटेर खुसी लाग्यो, it was nice meeting you.",
"मेरो घर पोखरामा छ, it's a beautiful city.",
"के म तपाईंको name जान्न सक्छु? What should I call you?",
"उहाँ मेरो best friend हुनुहुन्छ, हामी सँगै हुर्कियौं।",
"मेरो परिवारमा पाँच जना सदस्य हुनुहुन्छ।",
"I have been living here for the past 10 years.",
# --- Weather and Nature (with Code-Switching) ---
"आज मौसम धेरै राम्रो छ, it's very sunny and pleasant.",
"Oh no! आज बिहानदेखि heavy rain भइरहेको छ।",
"यो wind ले कति चिसो बनाएको! It's freezing!",
"हिजो राति तराईमा thick fog लागेको थियो।",
"सुन्दर weather मा हरियो डाँडाकाँडा घुम्न जान मन लाग्छ, especially during spring.",
"आकाशमा beautiful rainbow देखिएको छ।",
"भोलिको weather forecast कस्तो छ? Is it going to rain?",
"रुखहरूमा new leaves पलाएको छ।",
"यो waterfall हेर्न कति amazing!",
"I love walking on the beach, तर नेपालमा beach छैन।",
# --- Places and Travel (with Code-Switching) ---
"नेपाल एक beautiful देश हो, full of mountains, hills, and plains.",
"काठमाडौं नेपालको capital city हो, with a rich history.",
"पोखरा फेवातालको side मा अवस्थित छ, it's very picturesque.",
"चितवन National Park मा tigers and rhinos हेर्न पाइन्छ।",
"लुम्बिनी भगवान बुद्धको birthplace हो, a very sacred place.",
"सगरमाथा climb गर्न कति cost लाग्छ होला? It must be expensive.",
"म अर्को month मुक्तिनाथ दर्शन गर्न जाँदैछु, it's a famous pilgrimage site.",
"नेपालमा धेरै attractive tourist destinations छन्।",
"Excuse me, यहाँबाट सबैभन्दा नजिकको hotel कुन हो?",
"बसको ticket कहाँ किन्न पाइन्छ? Can I book online?",
"सगरमाथाको उचाई ८८४८.८६ मिटर छ।",
"यो यात्रामा करिब ३ दिन लाग्नेछ।",
"Our flight departs at 6:45 AM.",
# --- Daily Activities (with Code-Switching) ---
"म आज बिहान छिट्टै उठेँ and I am going to school now.",
"म प्रायः evening मा पार्कमा jogging गर्न जान्छु for some exercise.",
"तपाईंले breakfast खानु भयो? I just had mine.",
"मेरो आज धेरै work बाँकी छ, I need to finish it by tonight.",
"म आज office मा meetings ले गर्दा धेरै busy थिएँ।",
"म अहिले dinner बनाउँदै छु।",
"Are you free today? मसँग बजार जानुहुन्छ?",
"मैले homework सकेर I'll go play with friends.",
"राति सुत्नुअघि म usually a book पढ्छु।",
"Nowadays, I am trying to sleep early and wake up early.",
"म हरेक दिन बिहान ६ बजे उठ्छु।",
"I usually work for 8 hours a day.",
# --- Food and Culture (with Code-Switching) ---
"मलाई नेपाली traditional खाना, especially दाल, भात, तरकारी, I love it!",
"मःमः, सेल रोटी and ढिँडो are my favorite Nepali dishes.",
"तपाईंले lunch मा दाल भात खाउनु भयो? What did you have?",
"नेपालमा Tihar को बेला देउसी-भैलो खेल्ने old tradition छ।",
"दशैं is the biggest festival for Nepalis.",
"यो गुन्द्रुकको pickle साह्रै delicious रहेछ।",
"Do you like Newari food? It's quite unique.",
"विभिन्न ethnic groups का आ-आफ्नै cultural traditions छन्।",
"नेपाली folk music सुन्दा I feel so relaxed.",
"हाम्रो culture मा 'अतिथि देवो भवः' meaning guest is god भन्ने मान्यता छ।",
"एउटा मःमः प्लेटमा सामान्यतया १० वटा हुन्छ।",
"This recipe requires 2 cups of flour.",
# --- History and Religion ---
"भगवान गौतम बुद्ध नेपालको लुम्बिनीमा जन्मिएका थिए।",
"विश्वको सर्वोच्च शिखर सगरमाथा नेपालमा पर्दछ।",
"पोखराको तालबाराही मन्दिर तालको बीचमा रहेको छ।",
"नेपालमा लिच्छविकालीन, मल्लकालीन मठ मन्दिरहरु र वास्तुकला प्रसिद्ध छन्।",
"काठमाडौंमा रहेको पशुपतिनाथ मन्दिर बागमती नदीको किनारमा अवस्थित छ।",
"पृथ्वीनारायण शाहले आधुनिक नेपालको एकीकरण गरेका थिए।",
"स्वयम्भूनाथ स्तूपामा धेरै बाँदरहरू छन्।",
"जानकी मन्दिर सीताको जन्मस्थल जनकपुरमा रहेको छ।",
"नेपालमा हिन्दु र बौद्ध धर्मावलम्बीहरूको बाहुल्यता छ।",
"मनकामना मन्दिर दर्शन गर्न केबलकार चढेर जानुपर्छ।",
# --- Emotions ---
"यो सफलता पाएर म आज निकै खुशी छु।",
"परीक्षामा असफल हुँदा ऊ धेरै दुखी देखिन्छ।",
"किन यस्तो व्यवहार गरेको? तिमी रिसाएको जस्तो देखिन्छौ।",
"यो अनौठो समाचारले मलाई साँच्चै अचम्मित बनाएको छ।",
"आज म सामान्य र शान्त महसुस गर्दैछु, कुनै विशेष कुरा छैन।",
"मलाई अलिकति डर लागिरहेको छ।",
"उनी आफ्नो प्रस्तुतिलाई लिएर उत्साहित छिन्।",
"मैले गरेको गल्तीमा मलाई पछुतो छ।",
"यो कस्तो अचम्मको कुरा हो!",
"मलाई एकदमै दिक्क लाग्यो।",
# --- Hobbies and Interests ---
"म फुर्सदको समयमा विभिन्न प्रकारका पुस्तक पढ्न मन पराउँछु।",
"मैले आजकल गितार बजाउन र गीत गाउन सिक्दैछु।",
"के तपाईंलाई क्रिकेट हेर्न वा फुटबल खेल्न रुचाउनु हुन्छ?",
"मलाई प्रकृति र मानिसहरूको चित्रकला गर्न औधी मन पर्छ।",
"हामी अर्को हप्ता पदयात्रामा जान उत्साहित छौं।",
"बागवानी गर्नु मेरो सोख हो।",
"मलाई विभिन्न देशका मुद्राहरू संकलन गर्न मनपर्छ।",
"के तपाईंलाई खाना पकाउन आउँछ?",
"मलाई नयाँ ठाउँहरू घुम्न र नयाँ संस्कृतिहरू सिक्न मन पर्छ।",
"फोटोग्राफी मेरो रुचिको विषय हो।",
# --- Education and Work (with Code-Switching) ---
"म त्रिभुवन विश्वविद्यालयमा बीए द्वितीय वर्षमा मानविकी संकायमा अध्ययन गर्दैछु।",
"उहाँ एक अनुभवी र सफल वकील हुनुहुन्छ।",
"मैले भर्खरै एउटा नयाँ सामाजिक उद्यम project सुरु गरेको छु।",
"अन्ततः, मैले लोकसेवाको examination प्रथम श्रेणीमा उत्तीर्ण गरेँ।",
"आजकल तपाईंको business र कामकाज कस्तो चल्दैछ?",
"म एक software engineer को रूपमा काम गर्छु।",
"Teaching एउटा सम्मानित पेशा हो।",
"के तपाईंले आफ्नो master's degree पूरा गर्नुभयो?",
"म job को खोजीमा छु।",
"Workshop मा धेरै useful जानकारी पाइयो।",
"म कलेजमा बीए प्रथम वर्षमा अध्ययन गर्दैछु।",
"My presentation is scheduled for 11:00 AM on Friday.",
"यो कम्पनी सन् २००५ मा स्थापना भएको हो।",
# --- Technology and Media (with Code-Switching) ---
"म अहिले new model को smartphone प्रयोग गर्दैछु।",
"म हरेक दिन Zoom मार्फत online class लिन्छु।",
"आजकलका youngsters Social Media मा धेरै time बिताउँछन्।",
"मैले भर्खरै एउटा useful mobile application develop गरेको छु।",
"आफ्ना thoughts express गर्न blog लेख्न मलाई रमाइलो लाग्छ, it's a good hobby.",
"Internet ले संसारलाई एउटा global village बनाएको छ।",
"Did you see that viral video? It's everywhere.",
"Artificial Intelligence, or AI, भविष्यको technology हो।",
"म online news portals regularly पढ्छु to stay updated.",
"Digital payment ले transactions लाई धेरै easy बनाएको छ।",
# --- Health and Fitness ---
"म आफ्नो शारीरिक र मानसिक स्वास्थ्यका लागि दैनिक योग अभ्यास गर्छु।",
"लामो र स्वस्थ जीवनका लागि सन्तुलित खानपान आवश्यक छ।",
"हामी सबै रोगमुक्त र सुखी जीवन चाहन्छौं।",
"यदि तपाईंलाई अस्वस्थ महसुस भइरहेको छ भने तुरुन्त डाक्टरको सल्लाह लिनुहोस्।",
"नियमित व्यायामले हाम्रो शरीरलाई बलियो र स्फूर्त बनाउँछ।",
"पर्याप्त निद्रा स्वास्थ्यका लागि महत्त्वपूर्ण छ।",
"तनाव व्यवस्थापन गर्न ध्यान गर्नु राम्रो हुन्छ।",
"धुम्रपान स्वास्थ्यका लागि हानिकारक छ।",
"म हरेक बिहान जगिङ गर्न जान्छु।",
"फलफूल र हरियो सागसब्जी प्रशस्त खानुपर्छ।",
# --- Shopping and Services (with Code-Switching) ---
"म अहिले market जान्छु, do you need anything?",
"Excuse me, कति पर्छ यो किताब? What's the price?",
"यो beautiful पश्मिना shawl कता made in होला?",
"मलाई यो item को payment मेरो mobile wallet बाट गर्न मन छ, is that possible?",
"तपाईंको shop ठ्याक्कै कहाँ छ? Can you give me the location?",
"Do you have online ordering facility?",
"मलाई यो shoes को size अलि मिलेन, can I exchange it?",
"बैंक कति बजे open हुन्छ?",
"मलाई electricity bill pay गर्नु छ।",
"यो pharmacy मा सबै A-Z medicine पाइन्छ।",
"मलाई २ किलो आलु र १ दर्जन केरा दिनुहोस्।",
"यो मोबाइलको वारेन्टी १ वर्षको छ।",
"The total bill is 1,270 rupees.",
# --- Family and Relationships ---
"मेरो जेठो दाई गाउँको सरकारी विद्यालयमा पढाउनुहुन्छ।",
"हामी सबै परिवारका सदस्यहरू एक आपसमा धेरै माया र सम्मान गर्छौं।",
"चित्रमा देखिनुहुने व्यक्तिहरू मेरा आदरणीय पुर्खाहरु हुन्।",
"हाम्रो संयुक्त परिवार निकै ठूलो र रमाइलो छ।",
"मेरा बाल्यकालका केही मिल्ने साथीहरु आज मलाई भेट्न आउँदैछन्।",
"आमाबुबाको आज्ञा पालन गर्नु हाम्रो कर्तव्य हो।",
"छिमेकीहरूसँग राम्रो सम्बन्ध राख्नुपर्छ।",
"के तपाईं विवाहित हुनुहुन्छ?",
"मेरा भाइबहिनीहरू धेरै चकचके छन्।",
"सम्बन्धमा विश्वास सबैभन्दा महत्त्वपूर्ण कुरा हो।",
# --- Work and Office Talk (with Code-Switching) ---
"यो project को deadline कहिले हो?",
"Can we schedule a meeting for tomorrow morning?",
"मैले presentation prepare गरिसकेँ।",
"Please send me the report by end of day.",
"हाम्रो team ले target achieve गर्‍यो।",
"I have a conference call at 3 PM.",
"यो task लाई prioritize गर्नुपर्छ।",
"Could you please follow up on that email?",
"Let's brainstorm some new ideas for the campaign.",
"The client is very happy with our work.",
# --- Casual Conversation Snippets (with Code-Switching) ---
"Actually, मलाई त्यस्तो लाग्दैन।",
"Seriously? त्यो त great news हो!",
"By the way, तपाईंले त्यो movie हेर्नुभयो?",
"Okay, no problem, म manage गर्छु।",
"I think, हामीले plan B मा जानुपर्छ।",
"To be honest, मलाई यो idea मन परेन।",
"Wow, that's amazing! Congratulations!",
"Sorry, I am a bit late today.",
"What's up? सब ठीक छ?",
"Let's catch up soon, है त?",
# --- Asking for Help or Information (with Code-Switching) ---
"Excuse me, can you help me with this address?",
"मलाई यो form fill up गर्न अलि confusion भयो।",
"Do you know where the nearest ATM is?",
"यो ठाउँको बारेमा more information दिन सक्नुहुन्छ?",
"What time does the next bus to Pokhara leave?",
"I am looking for a good restaurant, any recommendations?",
"Could you please repeat that? मैले बुझिनँ।",
"How much does this cost? Is there any discount?",
"Is Wi-Fi available here?",
"Sorry to bother you, तर मलाई direction चाहिएको थियो。",
# --- Prompts Involving Numbers (Nepali and Code-Switched) ---
"मसँग पाँच सय रुपैयाँ मात्र छ।",
"यो सामानको मूल्य दुई हजार तीन सय पचास हो।",
"आज मिति २०८० साल, फाल्गुण महिनाको १५ गते हो।",
"बिहानको साढे सात बज्यो, उठ्ने बेला भयो।",
"मेरो फोन नम्बर ९८४१-१२३४५६ हो। (कृपया यो नम्बर रेकर्ड नगर्नुहोस्)",
"यो कक्षामा पच्चीस जना विद्यार्थी छन्।",
"मैले तीनवटा किताब किनेँ।",
"उहाँ पहिलो पटक काठमाडौं आउनुभएको हो।",
"हाम्रो घर नम्बर १०२/४ हो।",
"यो गाडीको गति प्रति घण्टा साठी किलोमिटर छ।",
"मैले दौडमा दोस्रो स्थान हासिल गरेँ।",
"यो कोठाको लम्बाई १२ फिट र चौडाई १० फिट छ।",
"बैंक खातामा लगभग पचास हजार रुपैयाँ बाँकी छ।",
"कार्यक्रम दिउँसोको ठीक ३ बजे सुरु हुनेछ।",
"यो वर्षको बजेट अनुमानित १७ खर्बको छ।",
"There are 7 days in a week.",
"My appointment is on October 21st at 2:30 PM.",
"The score was 3-2 in favor of our team.",
"Please dial extension 101.",
"This laptop costs around 75,000 rupees.",
"I need to buy 2 kilograms of sugar and 1 liter of milk.",
"The building has 15 floors.",
"Her flight number is RA 205.",
"The temperature today is 28 degrees Celsius.",
"Can you give me a 10% discount?",
"मेरो जन्म सन् १९९५ मा भएको थियो।",
"यो फिल्मको अवधि २ घण्टा ३० मिनेट छ।",
"उनले १०० मा ९० अंक प्राप्त गरिन्।",
"यो बाटो लगभग ५ किलोमिटर लामो छ।",
"We need to submit the assignment by the 5th of next month."
]
EMOTIONS = ["सामान्य (Neutral)", "खुसी (Happy)", "दुःखी (Sad)", "रिसाएको (Angry)", "अचम्मित (Surprised)"]
GENDERS = ["पुरुष (Male)", "महिला (Female)", "अन्य (Other)", "भन्न चाहन्न (Prefer not to say)"]
AGE_GROUPS = ["18 भन्दा कम", "18-24", "25-34", "35-44", "45-54", "55-64", "65+"]
REGIONS = [
"प्रदेश १ (Province 1)", "मधेश प्रदेश (Madhesh Province)", "बागमती प्रदेश (Bagmati Province)",
"गण्डकी प्रदेश (Gandaki Province)", "लुम्बिनी प्रदेश (Lumbini Province)",
"कर्णाली प्रदेश (Karnali Province)", "सुदूरपश्चिम प्रदेश (Sudurpashchim Province)"
]
COMMON_LAST_NAMES = {
"पहाडी (Pahadi)": ["शर्मा (Sharma)", "पौडेल (Poudel)", "खनाल (Khanal)", "अधिकारी (Adhikari)", "भट्टराई (Bhattarai)", "अन्य पहाडी (Other Pahadi)"],
"नेवार (Newar)": ["श्रेष्ठ (Shrestha)", "प्रधान (Pradhan)", "महर्जन (Maharjan)", "बज्राचार्य (Bajracharya)", "अन्य नेवार (Other Newar)"],
"मधेसी (Madhesi)": ["यादव (Yadav)", "साह (Shah)", "सिंह (Singh)", "गुप्ता (Gupta)", "अन्य मधेसी (Other Madhesi)"],
"थारु (Tharu)": ["चौधरी (Chaudhary)", "थारु (Tharu)", "अन्य थारु (Other Tharu)"],
"मगर (Magar)": ["मगर (Magar)", "थापा (Thapa)", "राना (Rana)", "अन्य मगर (Other Magar)"],
"तामाङ (Tamang)": ["तामाङ (Tamang)", "लामा (Lama)", "अन्य तामाङ (Other Tamang)"],
"राई (Rai)": ["राई (Rai)", "अन्य राई (Other Rai)"],
"गुरुङ (Gurung)": ["गुरुङ (Gurung)", "अन्य गुरुङ (Other Gurung)"],
"लिम्बु (Limbu)": ["लिम्बु (Limbu)", "अन्य लिम्बु (Other Limbu)"],
"शेर्पा (Sherpa)": ["शेर्पा (Sherpa)", "अन्य शेर्पा (Other Sherpa)"],
"अन्य (Other)": ["अन्य (Other)"]
}
# --- Directory and File Paths (Local to the Space) ---
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # Ensures paths are relative to app.py
RECORDINGS_DIR = os.path.join(BASE_DIR, "recordings")
METADATA_DIR = os.path.join(BASE_DIR, "metadata")
RATINGS_DIR = os.path.join(BASE_DIR, "ratings")
LOCAL_METADATA_FILE = os.path.join(METADATA_DIR, "local_metadata.csv")
LOCAL_RATINGS_FILE = os.path.join(RATINGS_DIR, "local_ratings.json")
HF_UPLOAD_LOG_FILE = os.path.join(METADATA_DIR, "hf_upload_log.csv") # To track HF uploads
# --- Hugging Face Configuration (from Space Secrets) ---
# These will be fetched from environment variables set by Space Secrets
# HF_TOKEN: Your HF Write Token
# ADMIN_UPLOAD_PASSWORD: Password for admin functions
# TARGET_HF_DATASET_REPO_ID: e.g., "yourusername/your-dataset-repo"
# --- Initialization ---
def initialize_data_storage():
os.makedirs(RECORDINGS_DIR, exist_ok=True)
os.makedirs(METADATA_DIR, exist_ok=True)
os.makedirs(RATINGS_DIR, exist_ok=True)
if not os.path.exists(LOCAL_METADATA_FILE):
pd.DataFrame(columns=[
"id", "text", "local_audio_path", "gender", "age_group", "ethnicity",
"last_name", "region", "emotion", "timestamp", "recording_type",
"hf_audio_uploaded", "hf_metadata_uploaded" # Track HF upload status
]).to_csv(LOCAL_METADATA_FILE, index=False)
if not os.path.exists(LOCAL_RATINGS_FILE):
with open(LOCAL_RATINGS_FILE, 'w') as f:
json.dump({}, f)
if not os.path.exists(HF_UPLOAD_LOG_FILE):
pd.DataFrame(columns=["id", "timestamp", "hf_repo_id", "type", "status", "message"]).to_csv(HF_UPLOAD_LOG_FILE, index=False)
initialize_data_storage()
# --- Helper: Log HF Upload Attempts ---
def log_hf_upload_attempt(recording_id, hf_repo_id, upload_type, status, message=""):
log_df = pd.read_csv(HF_UPLOAD_LOG_FILE)
new_log_entry = pd.DataFrame([{
"id": recording_id,
"timestamp": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"hf_repo_id": hf_repo_id,
"type": upload_type, # "audio", "metadata_entry", "ratings_sync"
"status": status, # "success", "failure"
"message": message
}])
updated_log_df = pd.concat([log_df, new_log_entry], ignore_index=True)
updated_log_df.to_csv(HF_UPLOAD_LOG_FILE, index=False)
# --- Core Functions ---
def save_and_direct_upload_recording(audio_input, text, gender, age_group, ethnicity, last_name, region, emotion, recording_type):
"""Saves recording locally and attempts immediate upload to Hugging Face."""
if audio_input is None:
return "कृपया पहिले रेकर्डिङ गर्नुहोस्। (Please record audio first)", None
# --- Get HF Config from Secrets ---
hf_token = os.environ.get("HF_TOKEN")
target_hf_repo_id = os.environ.get("TARGET_HF_DATASET_REPO_ID")
if not hf_token or not target_hf_repo_id:
# Critical config missing, only save locally
status_msg, _ = save_recording_locally(
audio_input, text, gender, age_group, ethnicity, last_name, region, emotion, recording_type,
hf_audio_uploaded=False, hf_metadata_uploaded=False # Mark as not uploaded
)
return f"{status_msg} (HF config missing in secrets, saved locally only)", None
# --- Save Locally First (always) ---
status_msg_local, recording_id, local_audio_path = save_recording_locally(
audio_input, text, gender, age_group, ethnicity, last_name, region, emotion, recording_type,
hf_audio_uploaded=False, hf_metadata_uploaded=False # Initial state
)
if not recording_id: # Failed to save locally
return status_msg_local, None
# --- Attempt Direct HF Upload ---
hf_upload_success = True
final_status_message = status_msg_local # Start with local save message
try:
api = HfApi(token=hf_token)
# Ensure base repo and standard subfolders exist
create_repo(repo_id=target_hf_repo_id, token=hf_token, repo_type="dataset", exist_ok=True, private=False)
for folder in ["audio", "metadata_entries", "ratings_entries"]:
try:
api.create_folder(repo_id=target_hf_repo_id, folder_path=folder, repo_type="dataset", exist_ok=True)
except Exception: pass # Ignore if folder exists
# 1. Upload Audio File to HF
hf_audio_path = f"audio/{os.path.basename(local_audio_path)}"
api.upload_file(
path_or_fileobj=local_audio_path,
path_in_repo=hf_audio_path,
repo_id=target_hf_repo_id,
repo_type="dataset",
commit_message=f"feat: Add audio for recording {recording_id}"
)
log_hf_upload_attempt(recording_id, target_hf_repo_id, "audio", "success")
update_local_metadata_hf_status(recording_id, hf_audio_uploaded=True)
final_status_message += f"\nअडियो सफलतापूर्वक HF मा अपलोड गरियो। (Audio uploaded to HF successfully.)"
# 2. Prepare and Upload Metadata Entry to HF
single_metadata_dict_for_hf = {
"id": recording_id, "text": text, "hf_audio_path": hf_audio_path,
"gender": gender, "age_group": age_group, "ethnicity": ethnicity,
"last_name": last_name, "region": region, "emotion": emotion,
"timestamp": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), # Use current time for HF metadata
"recording_type": recording_type
# Initial ratings are not part of this base metadata; they'll be separate
}
hf_metadata_entry_path = f"metadata_entries/{recording_id}.json"
api.upload_file(
path_or_fileobj=io.BytesIO(json.dumps(single_metadata_dict_for_hf, ensure_ascii=False, indent=2).encode('utf-8')),
path_in_repo=hf_metadata_entry_path,
repo_id=target_hf_repo_id,
repo_type="dataset",
commit_message=f"feat: Add metadata for recording {recording_id}"
)
log_hf_upload_attempt(recording_id, target_hf_repo_id, "metadata_entry", "success")
update_local_metadata_hf_status(recording_id, hf_metadata_uploaded=True)
final_status_message += f"\nमेटाडाटा सफलतापूर्वक HF मा अपलोड गरियो। (Metadata uploaded to HF successfully.)"
except Exception as e:
tb_str = traceback.format_exc()
error_message = f"HF अपलोडको क्रममा त्रुटि: {str(e)}. (Error during HF upload.)\nविवरण (Details): {tb_str}"
log_hf_upload_attempt(recording_id, target_hf_repo_id, "audio_or_metadata_entry_direct", "failure", error_message)
final_status_message += f"\n{error_message}\nडाटा स्थानीय रूपमा सुरक्षित गरिएको छ। (Data saved locally.)"
hf_upload_success = False # Mark that direct upload had issues
return final_status_message, None # Clear audio input
def save_recording_locally(audio_input, text, gender, age_group, ethnicity, last_name, region, emotion, recording_type, hf_audio_uploaded=False, hf_metadata_uploaded=False):
"""Saves recording and metadata locally in the Space."""
recording_id = str(uuid.uuid4())
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
audio_filename_relative = f"{recording_id}.wav"
local_audio_path = os.path.join(RECORDINGS_DIR, audio_filename_relative)
try:
if isinstance(audio_input, tuple):
sr, data = audio_input
sf.write(local_audio_path, data, sr)
elif isinstance(audio_input, str) and os.path.exists(audio_input):
shutil.copy(audio_input, local_audio_path)
else:
return "अडियो फाइल बचत गर्न सकिएन। (Could not save audio file. Invalid audio input.)", None, None
except Exception as e:
return f"स्थानीय रूपमा अडियो बचत गर्दा त्रुटि भयो: {e} (Error saving audio locally: {e})", None, None
# Save to local metadata CSV
try:
metadata_df = pd.read_csv(LOCAL_METADATA_FILE)
new_row = pd.DataFrame([{
"id": recording_id, "text": text, "local_audio_path": local_audio_path,
"gender": gender, "age_group": age_group, "ethnicity": ethnicity,
"last_name": last_name, "region": region, "emotion": emotion,
"timestamp": timestamp, "recording_type": recording_type,
"hf_audio_uploaded": hf_audio_uploaded, "hf_metadata_uploaded": hf_metadata_uploaded
}])
updated_metadata = pd.concat([metadata_df, new_row], ignore_index=True)
updated_metadata.to_csv(LOCAL_METADATA_FILE, index=False)
except Exception as e:
# If metadata save fails, try to clean up audio to avoid orphans
if os.path.exists(local_audio_path): os.remove(local_audio_path)
return f"स्थानीय मेटाडाटा बचत गर्दा त्रुटि: {e} (Error saving local metadata: {e})", None, None
# Initialize local ratings
try:
with open(LOCAL_RATINGS_FILE, 'r+') as f:
ratings = json.load(f)
ratings[recording_id] = {"upvotes": 0, "downvotes": 0, "quality_score": 0, "quality_votes": 0, "correctness_score": 0, "correctness_votes": 0}
f.seek(0)
json.dump(ratings, f, indent=2, ensure_ascii=False)
f.truncate()
except Exception as e:
# Non-critical for recording saving, but log it
print(f"Warning: Could not initialize local ratings for {recording_id}: {e}")
return f"रेकर्डिङ सफलतापूर्वक स्थानीय रूपमा सुरक्षित गरियो! ID: {recording_id} (Recording saved locally successfully!)", recording_id, local_audio_path
def update_local_metadata_hf_status(recording_id, hf_audio_uploaded=None, hf_metadata_uploaded=None):
"""Updates the HF upload status flags in the local metadata CSV."""
try:
metadata_df = pd.read_csv(LOCAL_METADATA_FILE)
idx = metadata_df[metadata_df['id'] == recording_id].index
if not idx.empty:
if hf_audio_uploaded is not None:
metadata_df.loc[idx, 'hf_audio_uploaded'] = hf_audio_uploaded
if hf_metadata_uploaded is not None:
metadata_df.loc[idx, 'hf_metadata_uploaded'] = hf_metadata_uploaded
metadata_df.to_csv(LOCAL_METADATA_FILE, index=False)
except Exception as e:
print(f"Error updating local metadata HF status for {recording_id}: {e}")
def get_random_prompt(): return random.choice(SAMPLE_PROMPTS)
def get_ethnicity_based_last_names(ethnicity): return gr.Dropdown.update(choices=COMMON_LAST_NAMES.get(ethnicity, COMMON_LAST_NAMES["अन्य (Other)"]))
def vote_recording(recording_id, vote_type, vote_value_str):
if not recording_id: return "कृपया पहिले समीक्षा गर्न रेकर्डिङ चयन गर्नुहोस्।"
if not os.path.exists(LOCAL_RATINGS_FILE): return "स्थानीय रेटिङ फाइल भेटिएन।"
try: vote_value = int(vote_value_str)
except ValueError: vote_value = 0
try:
with open(LOCAL_RATINGS_FILE, 'r+') as f:
ratings = json.load(f)
if recording_id not in ratings: return "यस रेकर्डिङको लागि स्थानीय मूल्याङ्कन भेटिएन।"
rec_ratings = ratings[recording_id]
if vote_type == "upvote": rec_ratings["upvotes"] += 1
elif vote_type == "downvote": rec_ratings["downvotes"] += 1
elif vote_type == "quality":
new_votes = rec_ratings.get("quality_votes", 0) + 1
rec_ratings["quality_score"] = ((rec_ratings.get("quality_score", 0) * rec_ratings.get("quality_votes", 0)) + vote_value) / new_votes
rec_ratings["quality_votes"] = new_votes
elif vote_type == "correctness":
new_votes = rec_ratings.get("correctness_votes", 0) + 1
rec_ratings["correctness_score"] = ((rec_ratings.get("correctness_score", 0) * rec_ratings.get("correctness_votes", 0)) + vote_value) / new_votes
rec_ratings["correctness_votes"] = new_votes
else: return "अमान्य मतदान प्रकार।"
f.seek(0); json.dump(ratings, f, indent=2, ensure_ascii=False); f.truncate()
return "स्थानीय मतदान सफलतापूर्वक दर्ता गरियो!"
except Exception as e: return f"स्थानीय मतदान दर्ता गर्दा त्रुटि: {str(e)}"
def get_local_recording_audio(recording_id):
if not recording_id: return None, "कुनै रेकर्डिङ आईडी प्रदान गरिएको छैन।"
if not os.path.exists(LOCAL_METADATA_FILE): return None, "स्थानीय मेटाडाटा फाइल भेटिएन।"
try: metadata = pd.read_csv(LOCAL_METADATA_FILE)
except pd.errors.EmptyDataError: return None, "स्थानीय मेटाडाटा खाली छ।"
recording = metadata[metadata['id'] == recording_id]
if len(recording) == 0: return None, "रेकर्डिङ भेटिएन।"
audio_path = recording['local_audio_path'].iloc[0]
text = recording['text'].iloc[0]
if not os.path.exists(audio_path): return None, f"स्थानीय अडियो फाइल भेटिएन: {audio_path}"
return audio_path, text
def get_local_recording_ratings(recording_id):
if not recording_id: return "रेकर्डिङ आईडी चयन गर्नुहोस्।"
if not os.path.exists(LOCAL_RATINGS_FILE): return "स्थानीय मूल्याङ्कन डाटा भेटिएन।"
with open(LOCAL_RATINGS_FILE, 'r') as f: ratings_data = json.load(f)
if recording_id not in ratings_data: return "यस रेकर्डिङको लागि कुनै स्थानीय मूल्याङ्कन भेटिएन।"
r = ratings_data[recording_id]
return (f"👍 Upvotes: {r.get('upvotes',0)} | 👎 Downvotes: {r.get('downvotes',0)}\n"
f"गुणस्तर (Quality): {r.get('quality_score',0):.1f}/5 ({r.get('quality_votes',0)} मत)\n"
f"शुद्धता (Correctness): {r.get('correctness_score',0):.1f}/5 ({r.get('correctness_votes',0)} मत)")
def update_local_count():
if os.path.exists(LOCAL_METADATA_FILE):
try:
metadata = pd.read_csv(LOCAL_METADATA_FILE)
uploaded_audio_count = metadata['hf_audio_uploaded'].sum()
uploaded_metadata_count = metadata['hf_metadata_uploaded'].sum()
return (f"कुल स्थानीय रेकर्डिङ: {len(metadata)}\n"
f"HF मा अडियो अपलोड गरिएको: {uploaded_audio_count}\n"
f"HF मा मेटाडाटा अपलोड गरिएको: {uploaded_metadata_count}")
except pd.errors.EmptyDataError: return "स्थानीय रेकर्डिङ: 0"
return "कुनै स्थानीय रेकर्डिङ भेटिएन।"
def list_local_recordings(num_items=10):
if not os.path.exists(LOCAL_METADATA_FILE): return pd.DataFrame()
try: metadata = pd.read_csv(LOCAL_METADATA_FILE)
except pd.errors.EmptyDataError: return pd.DataFrame()
if len(metadata) == 0: return pd.DataFrame()
metadata['timestamp'] = pd.to_datetime(metadata['timestamp'], errors='coerce')
sorted_metadata = metadata.sort_values('timestamp', ascending=False).head(int(num_items))
display_df = sorted_metadata[['id', 'text', 'ethnicity', 'region', 'timestamp', 'hf_audio_uploaded', 'hf_metadata_uploaded']].copy()
display_df['timestamp'] = display_df['timestamp'].dt.strftime('%Y-%m-%d %H:%M').fillna('N/A')
return display_df.reset_index(drop=True)
# --- Admin Functions for HF Syncing ---
def admin_retry_failed_uploads(admin_password_attempt):
hf_token = os.environ.get("HF_TOKEN")
target_hf_repo_id = os.environ.get("TARGET_HF_DATASET_REPO_ID")
expected_admin_password = os.environ.get("ADMIN_UPLOAD_PASSWORD")
if admin_password_attempt != expected_admin_password: return "अमान्य प्रशासक पासवर्ड।"
if not hf_token or not target_hf_repo_id: return "HF कन्फिगरेसन गोप्यमा हराइरहेको छ।"
if not os.path.exists(LOCAL_METADATA_FILE): return "कुनै स्थानीय मेटाडाटा फाइल भेटिएन।"
local_meta_df = pd.read_csv(LOCAL_METADATA_FILE)
# Find recordings where audio or metadata upload is marked as False
to_retry_df = local_meta_df[~(local_meta_df['hf_audio_uploaded'] & local_meta_df['hf_metadata_uploaded'])]
if to_retry_df.empty: return "पुनः प्रयास गर्न कुनै असफल अपलोडहरू भेटिएन।"
api = HfApi(token=hf_token)
success_count = 0
failure_count = 0
messages = []
for _, row in to_retry_df.iterrows():
rec_id = row['id']
local_audio_p = row['local_audio_path']
hf_audio_path = f"audio/{os.path.basename(local_audio_p)}"
current_status_msg = f"Retrying {rec_id}: "
try:
# Retry audio if not uploaded
if not row['hf_audio_uploaded'] and os.path.exists(local_audio_p):
api.upload_file(path_or_fileobj=local_audio_p, path_in_repo=hf_audio_path, repo_id=target_hf_repo_id, repo_type="dataset", commit_message=f"fix: Retry audio upload for {rec_id}")
update_local_metadata_hf_status(rec_id, hf_audio_uploaded=True)
log_hf_upload_attempt(rec_id, target_hf_repo_id, "audio_retry", "success")
current_status_msg += "Audio OK. "
elif row['hf_audio_uploaded']:
current_status_msg += "Audio already uploaded. "
# Retry metadata if not uploaded
if not row['hf_metadata_uploaded']:
# Reconstruct metadata dict for HF
hf_meta_dict = {
"id": rec_id, "text": row["text"], "hf_audio_path": hf_audio_path,
"gender": row["gender"], "age_group": row["age_group"], "ethnicity": row["ethnicity"],
"last_name": row["last_name"], "region": row["region"], "emotion": row["emotion"],
"timestamp": row["timestamp"], "recording_type": row["recording_type"]
}
hf_meta_entry_path = f"metadata_entries/{rec_id}.json"
api.upload_file(
path_or_fileobj=io.BytesIO(json.dumps(hf_meta_dict, ensure_ascii=False, indent=2).encode('utf-8')),
path_in_repo=hf_meta_entry_path, repo_id=target_hf_repo_id, repo_type="dataset",
commit_message=f"fix: Retry metadata entry upload for {rec_id}"
)
update_local_metadata_hf_status(rec_id, hf_metadata_uploaded=True)
log_hf_upload_attempt(rec_id, target_hf_repo_id, "metadata_entry_retry", "success")
current_status_msg += "Metadata OK."
elif row['hf_metadata_uploaded']:
current_status_msg += "Metadata already uploaded."
success_count += 1
messages.append(f"SUCCESS: {current_status_msg}")
except Exception as e:
failure_count += 1
err_msg = f"FAILURE for {rec_id}: {str(e)}"
messages.append(err_msg)
log_hf_upload_attempt(rec_id, target_hf_repo_id, "audio_or_metadata_retry", "failure", str(e))
return f"पुनः प्रयास सम्पन्न। सफलता: {success_count}, असफलता: {failure_count}\n" + "\n".join(messages)
def admin_sync_ratings_to_hf(admin_password_attempt):
hf_token = os.environ.get("HF_TOKEN")
target_hf_repo_id = os.environ.get("TARGET_HF_DATASET_REPO_ID")
expected_admin_password = os.environ.get("ADMIN_UPLOAD_PASSWORD")
if admin_password_attempt != expected_admin_password: return "अमान्य प्रशासक पासवर्ड।"
if not hf_token or not target_hf_repo_id: return "HF कन्फिगरेसन गोप्यमा हराइरहेको छ।"
if not os.path.exists(LOCAL_RATINGS_FILE): return "कुनै स्थानीय मूल्याङ्कन फाइल भेटिएन।"
with open(LOCAL_RATINGS_FILE, 'r') as f:
local_ratings = json.load(f)
if not local_ratings: return "सिंक गर्न कुनै स्थानीय मूल्याङ्कन छैन।"
api = HfApi(token=hf_token)
fs = HfFileSystem(token=hf_token) # For checking file existence
success_count = 0
failure_count = 0
messages = []
for rec_id, ratings_data in local_ratings.items():
# Only sync if there are any votes/scores
if not any(ratings_data.values()):
continue
hf_ratings_path = f"ratings_entries/{rec_id}.json"
try:
# Optional: Check if ratings on HF are older or different before uploading.
# For simplicity, we'll just overwrite/create.
api.upload_file(
path_or_fileobj=io.BytesIO(json.dumps(ratings_data, ensure_ascii=False, indent=2).encode('utf-8')),
path_in_repo=hf_ratings_path,
repo_id=target_hf_repo_id,
repo_type="dataset",
commit_message=f"chore: Sync ratings for recording {rec_id}"
)
success_count += 1
log_hf_upload_attempt(rec_id, target_hf_repo_id, "ratings_sync", "success")
messages.append(f"SUCCESS: Synced ratings for {rec_id}")
except Exception as e:
failure_count += 1
err_msg = f"FAILURE syncing ratings for {rec_id}: {str(e)}"
messages.append(err_msg)
log_hf_upload_attempt(rec_id, target_hf_repo_id, "ratings_sync", "failure", str(e))
return f"मूल्याङ्कन सिंक सम्पन्न। सफलता: {success_count}, असफलता: {failure_count}\n" + "\n".join(messages)
# --- Gradio UI Build ---
def build_ui():
with gr.Blocks(title="नेपाली ASR डाटा संकलन") as app:
gr.Markdown("# नेपाली ASR डाटा संकलन (Nepali ASR Data Collection)")
gr.Markdown(
"यस प्लेटफर्मले नेपाली भाषाको स्वचालित भाषण पहिचान (ASR) प्रविधिको विकासका लागि आवाज डाटा संकलन गर्दछ। "
"कृपया आफ्नो आवाज रेकर्ड गरेर योगदान दिनुहोस्। तपाईंको प्रत्येक रेकर्डिङ सिधै हाम्रो खुला हगिङ फेस डेटासेटमा योगदान गरिनेछ।\n\n"
f"**हाम्रो सार्वजनिक हगिङ फेस डेटासेट हेर्नुहोस् (View our public Hugging Face Dataset): [nepali-asr-community-data](https://huggingface.co/datasets/darvilab/nepali-asr-community-data)**\n\n"
"*This platform collects voice data for the development of Nepali Automatic Speech Recognition (ASR) technology. "
"Please contribute by recording your voice. Each of your recordings will be directly contributed to our open Hugging Face Dataset.*\n\n"
f"**View our public Hugging Face Dataset: [nepali-asr-community-data](https://huggingface.co/datasets/darvilab/nepali-asr-community-data)**"
)
with gr.Tabs():
with gr.TabItem("१. आवाज रेकर्ड गर्नुहोस् (Record Voice)"):
with gr.Tabs():
with gr.TabItem("स्वतन्त्र पाठ (Free Text)"):
# ... (UI elements as before, but change .click) ...
free_audio_input = gr.Audio(label="आवाज रेकर्ड गर्नुहोस्", type="filepath", sources=["microphone"]) # Corrected
free_text_input = gr.Textbox(label="पाठ", placeholder="यहाँ लेख्नुहोस्...", lines=3)
# ... (gender, age, ethnicity, lastname, region, emotion dropdowns) ...
free_gender_dd = gr.Dropdown(label="लिङ्ग", choices=GENDERS, value=GENDERS[0])
free_age_dd = gr.Dropdown(label="उमेर समूह", choices=AGE_GROUPS, value=AGE_GROUPS[1])
free_ethnicity_dd = gr.Dropdown(label="जातीयता", choices=list(COMMON_LAST_NAMES.keys()), value=list(COMMON_LAST_NAMES.keys())[0])
free_lastname_dd = gr.Dropdown(label="थर", choices=COMMON_LAST_NAMES[list(COMMON_LAST_NAMES.keys())[0]])
free_ethnicity_dd.change(fn=get_ethnicity_based_last_names, inputs=free_ethnicity_dd, outputs=free_lastname_dd)
free_region_dd = gr.Dropdown(label="क्षेत्र", choices=REGIONS, value=REGIONS[2])
free_emotion_dd = gr.Dropdown(label="भावना", choices=EMOTIONS, value=EMOTIONS[0])
free_submit_btn = gr.Button("सुरक्षित र अपलोड गर्नुहोस्")
free_status_output = gr.Textbox(label="स्थिति", interactive=False, lines=3)
free_submit_btn.click(
save_and_direct_upload_recording,
inputs=[free_audio_input, free_text_input, free_gender_dd, free_age_dd, free_ethnicity_dd, free_lastname_dd, free_region_dd, free_emotion_dd, gr.Textbox(value="free_text", visible=False)],
outputs=[free_status_output, free_audio_input]
)
with gr.TabItem("निर्देशित पाठ (Prompted Text)"):
# ... (UI elements as before, but change .click) ...
prompt_text_display = gr.Textbox(label="कृपया यो पाठ पढ्नुहोस्", value=get_random_prompt(), lines=3, interactive=False)
new_prompt_btn = gr.Button("नयाँ पाठ")
prompt_audio_input = gr.Audio(label="आवाज रेकर्ड गर्नुहोस्", type="filepath", sources=["microphone"]) # Corrected
# ... (gender, age, ethnicity, lastname, region, emotion dropdowns) ...
prompt_gender_dd = gr.Dropdown(label="लिङ्ग", choices=GENDERS, value=GENDERS[0])
prompt_age_dd = gr.Dropdown(label="उमेर समूह", choices=AGE_GROUPS, value=AGE_GROUPS[1])
prompt_ethnicity_dd = gr.Dropdown(label="जातीयता", choices=list(COMMON_LAST_NAMES.keys()), value=list(COMMON_LAST_NAMES.keys())[0])
prompt_lastname_dd = gr.Dropdown(label="थर", choices=COMMON_LAST_NAMES[list(COMMON_LAST_NAMES.keys())[0]])
prompt_ethnicity_dd.change(fn=get_ethnicity_based_last_names, inputs=prompt_ethnicity_dd, outputs=prompt_lastname_dd)
prompt_region_dd = gr.Dropdown(label="क्षेत्र", choices=REGIONS, value=REGIONS[2])
prompt_emotion_dd = gr.Dropdown(label="भावना", choices=EMOTIONS, value=EMOTIONS[0])
new_prompt_btn.click(get_random_prompt, outputs=prompt_text_display)
prompt_submit_btn = gr.Button("सुरक्षित र अपलोड गर्नुहोस्")
prompt_status_output = gr.Textbox(label="स्थिति", interactive=False, lines=3)
prompt_submit_btn.click(
save_and_direct_upload_recording,
inputs=[prompt_audio_input, prompt_text_display, prompt_gender_dd, prompt_age_dd, prompt_ethnicity_dd, prompt_lastname_dd, prompt_region_dd, prompt_emotion_dd, gr.Textbox(value="prompted_text", visible=False)],
outputs=[prompt_status_output, prompt_audio_input]
)
with gr.TabItem("२. रेकर्डिङ समीक्षा गर्नुहोस् (Review Local Recordings)"):
gr.Markdown("स्थानीय रूपमा सुरक्षित गरिएका हालसालैका रेकर्डिङहरू हेर्नुहोस् र मत दिनुहोस्। (View and vote on recent locally saved recordings.)")
num_review_items = gr.Number(value=10, label="देखाउने वस्तुहरूको संख्या", minimum=1, maximum=50, step=1)
refresh_review_list_btn = gr.Button("स्थानीय सूची ताजा गर्नुहोस्")
review_list_df = gr.DataFrame(
headers=['id', 'text', 'ethnicity', 'region', 'timestamp', 'hf_audio_uploaded', 'hf_metadata_uploaded'],
label="हालका स्थानीय रेकर्डिङहरू", interactive=False,
datatype=['str', 'str', 'str', 'str', 'str', 'bool', 'bool']
)
# ... (Rest of review UI, using get_local_recording_audio and get_local_recording_ratings) ...
selected_review_id = gr.Textbox(label="चयन गरिएको आईडी", interactive=False)
selected_review_text = gr.Textbox(label="रेकर्डिङ पाठ", interactive=False, lines=2)
review_audio_player = gr.Audio(label="रेकर्डिङ सुन्नुहोस्", type="filepath")
current_ratings_display = gr.Textbox(label="वर्तमान स्थानीय मूल्याङ्कन", interactive=False, lines=3)
def select_for_review(evt: gr.SelectData, df_data: pd.DataFrame):
if evt.index is None or df_data is None or len(df_data) == 0 or evt.index[0] >= len(df_data):
return "", "", None, "कुनै रेकर्डिङ चयन गरिएको छैन"
selected_id_val = df_data.iloc[evt.index[0]]['id']
audio_p, text_val = get_local_recording_audio(selected_id_val) # Use local getter
ratings_text_val = get_local_recording_ratings(selected_id_val) # Use local getter
return selected_id_val, text_val, audio_p, ratings_text_val
review_list_df.select(select_for_review, inputs=[review_list_df], outputs=[selected_review_id, selected_review_text, review_audio_player, current_ratings_display])
refresh_review_list_btn.click(list_local_recordings, inputs=[num_review_items], outputs=review_list_df)
gr.Markdown("### स्थानीय मतदान गर्नुहोस् (Cast Your Local Vote)")
# ... (voting buttons as before, using vote_recording which now acts locally) ...
upvote_btn = gr.Button("👍 मन पर्यो")
downvote_btn = gr.Button("👎 मन परेन")
quality_rating_slider = gr.Slider(minimum=1, maximum=5, step=1, label="गुणस्तर मूल्याङ्कन", value=3)
submit_quality_btn = gr.Button("गुणस्तर मत दिनुहोस्")
correctness_rating_slider = gr.Slider(minimum=1, maximum=5, step=1, label="शुद्धता मूल्याङ्कन", value=3)
submit_correctness_btn = gr.Button("शुद्धता मत दिनुहोस्")
vote_status_output = gr.Textbox(label="मतदान स्थिति", interactive=False)
def vote_and_refresh_local(rec_id, vote_t, vote_val_str):
status = vote_recording(rec_id, vote_t, str(vote_val_str))
new_ratings = get_local_recording_ratings(rec_id) if rec_id else "रेकर्डिङ चयन गर्नुहोस्"
return status, new_ratings
upvote_btn.click(vote_and_refresh_local, inputs=[selected_review_id, gr.Textbox(value="upvote", visible=False), gr.Number(value=0, visible=False)], outputs=[vote_status_output, current_ratings_display])
downvote_btn.click(vote_and_refresh_local, inputs=[selected_review_id, gr.Textbox(value="downvote", visible=False), gr.Number(value=0, visible=False)], outputs=[vote_status_output, current_ratings_display])
submit_quality_btn.click(vote_and_refresh_local, inputs=[selected_review_id, gr.Textbox(value="quality", visible=False), quality_rating_slider], outputs=[vote_status_output, current_ratings_display])
submit_correctness_btn.click(vote_and_refresh_local, inputs=[selected_review_id, gr.Textbox(value="correctness", visible=False), correctness_rating_slider], outputs=[vote_status_output, current_ratings_display])
with gr.TabItem("३. प्रशासक: सिंक र प्रगति (Admin: Sync & Progress)"):
gr.Markdown("## स्थानीय संकलन प्रगति (Local Collection Progress)")
total_count_display = gr.Textbox(label="स्थानीय तथ्याङ्क", interactive=False, lines=3)
refresh_total_count_btn = gr.Button("स्थानीय गणना ताजा गर्नुहोस्")
refresh_total_count_btn.click(update_local_count, outputs=total_count_display)
gr.Markdown("---")
gr.Markdown("## प्रशासक कार्यहरू (Admin Actions)")
gr.Markdown("यी कार्यहरूका लागि प्रशासक पासवर्ड आवश्यक छ (गोप्यमा `ADMIN_UPLOAD_PASSWORD` को रूपमा सेट गरिएको)। "
"HF टोकन र लक्ष्य रिपो आईडी पनि गोप्यमा (`HF_TOKEN`, `TARGET_HF_DATASET_REPO_ID`) हुनुपर्छ।")
admin_password_input_sync = gr.Textbox(label="प्रशासक पासवर्ड", type="password", placeholder="प्रशासक पासवर्ड प्रविष्ट गर्नुहोस्")
with gr.Row():
retry_failed_uploads_btn = gr.Button("असफल HF अपलोडहरू पुनः प्रयास गर्नुहोस्")
sync_ratings_btn = gr.Button("स्थानीय मूल्याङ्कनहरू HF मा सिंक गर्नुहोस्")
admin_action_status_output = gr.Textbox(label="प्रशासक कार्य स्थिति", interactive=False, lines=10)
retry_failed_uploads_btn.click(admin_retry_failed_uploads, inputs=[admin_password_input_sync], outputs=admin_action_status_output)
sync_ratings_btn.click(admin_sync_ratings_to_hf, inputs=[admin_password_input_sync], outputs=admin_action_status_output)
with gr.TabItem("४. जानकारी (Information)"):
gr.Markdown(render_info_page())
app.load(fn=update_local_count, inputs=None, outputs=total_count_display)
app.load(fn=lambda n: list_local_recordings(n), inputs=[num_review_items], outputs=review_list_df)
return app
def render_info_page():
return """
## नेपाली ASR डाटा संकलन प्रोजेक्टको बारेमा (About the Nepali ASR Data Collection Project)
यो प्रोजेक्टले नेपाली भाषाको स्वचालित भाषण पहिचान (ASR) प्रविधिको विकासका लागि आवश्यक डाटा संकलन गर्दछ।
तपाईंको प्रत्येक रेकर्डिङ सिधै हाम्रो खुला हगिङ फेस डेटासेटमा योगदान गरिनेछ।
### कसरी योगदान दिने (How to Contribute):
1. **आवाज रेकर्ड गर्नुहोस् (Record Voice)** ट्याबमा जानुहोस् र आफ्नो आवाज रेकर्ड गर्नुहोस्।
2. **रेकर्डिङ समीक्षा गर्नुहोस् (Review Local Recordings)** ट्याबमा गएर अरूले गरेका (वा तपाईंले गरेका) स्थानीय रूपमा सुरक्षित गरिएका रेकर्डिङहरू सुन्नुहोस् र मत दिनुहोस्। यी मतहरू पछि हगिङ फेसमा सिंक गर्न सकिन्छ।
### गोपनीयता नीति (Privacy Policy):
- तपाईंको आवाज रेकर्डिङ र मेटाडाटा सार्वजनिक अनुसन्धान उद्देश्यका लागि हगिङ फेसमा खुला रूपमा उपलब्ध हुनेछ।
- कृपया व्यक्तिगत पहिचान गर्न सकिने जानकारी शेयर नगर्नुहोस्।
""" # Keep your more detailed version
# --- Main Execution ---
if __name__ == "__main__":
initialize_data_storage()
app_ui = build_ui()
app_ui.launch()