Noorani_Qaida / app.py
Randa's picture
Update app.py
74ec8c4 verified
raw
history blame
12.6 kB
from transformers import pipeline
from lang_trans.arabic import buckwalter
from difflib import SequenceMatcher
import pandas as pd
import gradio as gr
import time
# Gradio application for learning Noorani Qaida
p = pipeline("automatic-speech-recognition", model="jonatasgrosman/wav2vec2-large-xlsr-53-arabic")
# Read excel file and store it in a dictionary
def read_excel_data(file_path, sheet_name):
data_list = []
try:
# Read the Excel file
df = pd.read_excel(file_path, sheet_name=sheet_name)
# Iterate over the rows
for index, row in df.iterrows():
test = row['test']
correct = row['correct']
close = row['close']
wrong = row['wrong']
image = row["image"]
# Store close and wrong values as a tuple
data_list.append((test, correct, close, wrong, image))
return data_list
except Exception as e:
print(f"Error reading Excel file: {e}")
# List of sample texts to read
excel_file_path = "ASR_live_test.xlsx"
sheet_name= 'sample_test(threshold=75%)'
full_test_list = read_excel_data(excel_file_path, sheet_name)
# Similarity function
def similar(a, b):
return SequenceMatcher(None, a, b).ratio()
def transcribe(audio, reference_text):
time.sleep(1)
text = p(audio)["text"]
text = buckwalter.untrans(text)
state = text
if state is not None:
if similar(reference_text, state) > 0.75:
score = "correct"
elif similar(reference_text, state) > 0.50 and similar(reference_text, state) < 0.75:
score = "close"
else:
score = "wrong"
return state, score
else :
print(" Null Object")
# Function to retrieve the list of unique categories
def get_unique_tests(data_list):
tests=[]
tests = [test for test, _, _, _, _ in data_list if test not in tests]
return tests
# Function to retrieve close, wrong and image values for a given correct value
def get_values_image_for_test(tests, test):
for t, correct, close, wrong, image in tests:
if t == test:
return correct, close, wrong, image
# Counting completed tests
def completed_tests(test):
global completed_tests_list
if completed_tests_list is None:
completed_tests_list = []
if test and test not in completed_tests_list :
completed_tests_list.append(test)
# elif test and test in completed_tests_list:
# gr.Warning("Test alreday done! Please select another test.")
total_completed_tests = len(completed_tests_list)
return total_completed_tests, completed_tests_list
# Tests distribution over users
import random
def assign_tests(num_tests):
global remaining_tests
assigned_tests = []
tests = get_unique_tests(full_test_list)
# Shuffle tests
random.shuffle(tests)
# Updating remaining_tests
if (len(remaining_tests) == 0) and (len(assigned_tests) == 0):
remaining_tests = set(tests)
# else:
# remaining_tests -= set(assigned_tests)
# Last remaining tests are assigned to the last user
if num_tests > len(remaining_tests):
assigned_tests = remaining_tests
# Ensure we still have enough tests
if len(remaining_tests) == 0:
print("***** Tests Completed *****")
pass#return ["Tests Completed"]
# Select tests that are not already assigned
assigned_tests = [test for test in tests if test in remaining_tests][:num_tests]
# Remove assigned tests from the set of all available tests
remaining_tests -= set(assigned_tests)
return assigned_tests
# Tracking user progress
def test_progress(test):
global completed_tests_list
global len_assigned_test
# Get total completed tests
total_completed_tests, completed_tests_list = completed_tests(test)
# Test completed to be displayed to the user
completed_tests_text = "\n".join(completed_tests_list)
# Calculate how many tests are remaining
total_remaining_tests = len_assigned_test - total_completed_tests
if total_remaining_tests == 0:
completed_tests_list.clear()
progress_text = f"Congratulations! You have completed all tests"
else:
progress_text = f"Completed tests {total_completed_tests} . Remaining {total_remaining_tests}"
return progress_text, completed_tests_text
# Authentication function
def update_message(request: gr.Request):
return f"Welcome, {request.username}"
# Gradio apps
# Get test categories
data_list = full_test_list
image_path="all_imgs/"
completed_tests_list = []
remaining_tests = []
# Get a set of tests for each user
num_tests = 10
assigned_tests = assign_tests(num_tests)
len_assigned_test = len(assigned_tests)
print(assigned_tests)
# Flagging
callback = gr.CSVLogger()
# CSS
css = """
h1 {
text-align: center;
color: #5756BB;
display:block;
}
p {
text-align: left;
display:block;
}
p.thick {
font-weight: bold;
}
.drop_color {background-color: #e0eaff}
img {
height: auto;
width: auto;
margin-left: auto;
margin-right: auto;
display: block;
}
.row {
height: 90px;
width: auto;
}
progress_text {
text-align: center;
ont-weight: bold;
}
"""
js = """
function change_color(){
const test_text = document.getElementById("#test_color");
const selectedtest = dropdown.options[dropdown.selectedIndex];
selectedtest.style.color = "green";
}
"""
demo = gr.Blocks(theme=gr.themes.Soft(), css=css)
with demo :
# Add app title
gr.Markdown(
"""
# Noorani Qaida Test Interface"""
)
# User authentication
with gr.Row():
m = gr.Markdown()
logout_button = gr.Button("Logout", link="/logout", scale=0, variant="primary")
demo.load(update_message, None, m)
# Add app description
gr.Markdown(
"""
Select a category then a test from the list, read the text aloud, get the transcription and save it.
"""
)
# Assign value to each step
def get_test_text(test):
correct, close, wrong, image = get_values_image_for_test(data_list, test)
correct_text = gr.Textbox(label="Step 1", value=correct)
close_text = gr.Textbox(label="Step 2", value=close)
wrong_text = gr.Textbox(label="Step 3", value=wrong)
image = gr.Image(value=(image_path+str(image)+".jpg"))
return correct_text, close_text, wrong_text, image
def update_completed_test(test):
_, completed_tests = gr.TextArea(completed_tests(test))
return completed_tests
with gr.Row():
# First big column
with gr.Column(scale=1):
# User progress
progress_text = gr.Textbox(value="Completed tests 0. Remaining 10", interactive=False, show_label=False, container=True, elem_id="progress_text", elem_classes="drop_color")
textarea_completed = gr.TextArea(info=" Your completed tests will appear here ", interactive=False, rtl=True, container=True, show_label=False, elem_classes="drop_color")
# Test selection
tests_list = assigned_tests
test_dropdown = gr.Dropdown(tests_list, label="Tests", info="Select a test", scale=1, elem_id="test_color", elem_classes="drop_color")
test_dropdown.select(test_progress, test_dropdown, outputs=[progress_text, textarea_completed])
# Second big column
with gr.Column(scale=3):
# First row for image
with gr.Row():
image = gr.Image(elem_id="img", elem_classes="row", container=False, show_label=True, show_download_button=False, show_share_button=False)
# Second row for steps
with gr.Row():
# First sub-column
with gr.Column():
correct_text = gr.Textbox(label= "Step 1", info="Correct Text", interactive=False, rtl=True)
correct_audio_record = gr.Audio(sources="microphone" ,type="filepath", label="Record Audio", show_label=False)
correct_trans_text = gr.Textbox(info="Transcription", interactive=False, rtl=True, show_label=False)
correct_score = gr.Textbox(label="Score", visible= False)
correct_audio_record.stop_recording(fn=transcribe, inputs=[correct_audio_record, correct_text], outputs=[correct_trans_text, correct_score])
# Second sub-column
with gr.Column():
close_text = gr.Textbox(label="Step 2", info="Close Text", interactive=False, rtl=True)
close_audio_record = gr.Audio(sources="microphone", type="filepath", label="Record Audio", show_label=False)
close_trans_text = gr.Textbox(info="Transcription", interactive=False, rtl=True, show_label=False)
close_score = gr.Textbox(label="Score", visible= False)
close_audio_record.stop_recording(fn=transcribe, inputs=[close_audio_record, close_text], outputs=[close_trans_text, close_score])
# Third sub-column
with gr.Column():
wrong_text = gr.Textbox(label="Step 3", info="Wrong Text", interactive=False, rtl=True)
wrong_audio_record = gr.Audio(sources="microphone" ,type="filepath", label="Record Audio", show_label=False)
wrong_trans_text = gr.Textbox(info="Transcription", interactive=False, rtl=True, show_label=False)
wrong_score = gr.Textbox(label="Score", visible= False)
wrong_audio_record.stop_recording(fn=transcribe, inputs=[wrong_audio_record, wrong_text], outputs=[wrong_trans_text, wrong_score])
# Row for flag
with gr.Row():
#user_name = gr.Request.username
def save_outputs(correct_text, correct_trans_text, correct_score, correct_audio_record,
close_text, close_trans_text, close_score, close_audio_record,
wrong_text, wrong_trans_text, wrong_score, wrong_audio_record):
if any(len(text)==0 for text in [correct_trans_text, close_trans_text, wrong_trans_text]):
return gr.Warning("Please complete the test before saving")
return (lambda *args: callback.flag(args, username="randa"))
flag_btn = gr.Button(value="Save this test", variant="primary", scale=2)
# Setup the components to flag
callback.setup([correct_text, correct_trans_text, correct_score, correct_audio_record,
close_text, close_trans_text, close_score, close_audio_record,
wrong_text, wrong_trans_text, wrong_score, wrong_audio_record], "flagged_data")
# We can choose which components to flag
flag_btn.click(save_outputs,
[correct_text, correct_trans_text, correct_score, correct_audio_record,
close_text, close_trans_text, close_score, close_audio_record,
wrong_text, wrong_trans_text, wrong_score, wrong_audio_record],
None, preprocess=False)
# Update test values according to the selected test
test_dropdown.input(get_test_text, test_dropdown, [correct_text, close_text, wrong_text, image])
# Clear the transcription after selecting a new test
test_dropdown.select(lambda: [None]*10, None,
outputs=[correct_text, close_text, wrong_text, correct_audio_record, close_audio_record, wrong_audio_record, correct_trans_text, close_trans_text, wrong_trans_text, image],
queue=False)
#demo.launch(inbrowser=True)
if __name__ == "__main__":
demo.launch(auth=[("randa", "randa"), ("randa1", "randa1"),("randa2", "randa2"), ("randa3", "randa3"),
("karim1", "karim1"), ("karim2", "karim2"), ("karim3", "karim3"),
("yassir1", "yassir1"), ("yassir2", "yassir2"), ("yassir3", "yassir3"),
("mehdi", "mehdi")],
share=True, inbrowser=True)