Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -617,6 +617,20 @@ AVATAR_HTML = """
|
|
| 617 |
</div>
|
| 618 |
"""
|
| 619 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 620 |
def _init_state(memory, lang, history):
|
| 621 |
"""Ensure state values are never None."""
|
| 622 |
if memory is None:
|
|
@@ -697,9 +711,7 @@ def build_app():
|
|
| 697 |
btn_en = gr.Button("🇬🇧 English", variant="primary")
|
| 698 |
btn_ar = gr.Button("🇸🇦 العربية", variant="primary")
|
| 699 |
btn_ur = gr.Button("🇵🇰 اردو", variant="primary")
|
| 700 |
-
lang_audio_out = gr.
|
| 701 |
-
label="Agent", autoplay=True,
|
| 702 |
-
visible=False, interactive=False)
|
| 703 |
|
| 704 |
# ── Main chat interface (hidden until lang chosen) ─────
|
| 705 |
with gr.Group(visible=False) as chat_group:
|
|
@@ -724,11 +736,7 @@ def build_app():
|
|
| 724 |
with gr.Row():
|
| 725 |
send_btn = gr.Button("Send ➤", variant="primary")
|
| 726 |
change_btn = gr.Button("🔄 Change language", variant="secondary")
|
| 727 |
-
audio_out = gr.
|
| 728 |
-
label="Reem speaks",
|
| 729 |
-
autoplay=True,
|
| 730 |
-
interactive=False,
|
| 731 |
-
)
|
| 732 |
|
| 733 |
# Welcome audio hidden autoplay on load
|
| 734 |
welcome_audio_html = gr.HTML(
|
|
@@ -786,24 +794,24 @@ def build_app():
|
|
| 786 |
gr.update(visible=False),
|
| 787 |
gr.update(visible=True),
|
| 788 |
badge,
|
| 789 |
-
audio_path,
|
| 790 |
memory,
|
| 791 |
)
|
| 792 |
|
| 793 |
def handle_lang_mic(audio, memory):
|
| 794 |
memory, _, _ = _init_state(memory, None, None)
|
| 795 |
if audio is None:
|
| 796 |
-
return ("", gr.update(), gr.update(), "",
|
| 797 |
sr, data = audio
|
| 798 |
import io, soundfile as sf
|
| 799 |
buf = io.BytesIO()
|
| 800 |
sf.write(buf, data, sr, format="WAV")
|
| 801 |
transcript = transcribe_audio_bytes(buf.getvalue())
|
| 802 |
if not transcript:
|
| 803 |
-
return ("", gr.update(), gr.update(), "",
|
| 804 |
detected = detect_lang(transcript)
|
| 805 |
if not detected:
|
| 806 |
-
return ("", gr.update(), gr.update(), "",
|
| 807 |
return _set_language(detected, memory)
|
| 808 |
|
| 809 |
lang_mic.stop_recording(
|
|
@@ -834,21 +842,21 @@ def build_app():
|
|
| 834 |
def handle_voice(audio, lang_code, memory, history):
|
| 835 |
memory, lang_code, history = _init_state(memory, lang_code, history)
|
| 836 |
if audio is None:
|
| 837 |
-
return history,
|
| 838 |
sr, data = audio
|
| 839 |
import io, soundfile as sf
|
| 840 |
buf = io.BytesIO()
|
| 841 |
sf.write(buf, data, sr, format="WAV")
|
| 842 |
raw = buf.getvalue()
|
| 843 |
if len(raw) < MIN_AUDIO_BYTES:
|
| 844 |
-
return history,
|
| 845 |
transcript = transcribe_audio_bytes(raw)
|
| 846 |
if not transcript or len(transcript.strip()) < 3:
|
| 847 |
return history, None, memory, "⚠️ No clear speech detected."
|
| 848 |
_, new_history, audio_path = process_query(
|
| 849 |
transcript, memory, lang_code or "en", history)
|
| 850 |
mem_info_txt = _mem_info(memory)
|
| 851 |
-
return new_history, audio_path, memory, mem_info_txt
|
| 852 |
|
| 853 |
voice_input.stop_recording(
|
| 854 |
handle_voice,
|
|
@@ -860,11 +868,11 @@ def build_app():
|
|
| 860 |
def handle_text(text, lang_code, memory, history):
|
| 861 |
memory, lang_code, history = _init_state(memory, lang_code, history)
|
| 862 |
if not text or not text.strip():
|
| 863 |
-
return history,
|
| 864 |
_, new_history, audio_path = process_query(
|
| 865 |
text, memory, lang_code or "en", history)
|
| 866 |
mem_info_txt = _mem_info(memory)
|
| 867 |
-
return new_history, audio_path, memory, mem_info_txt, ""
|
| 868 |
|
| 869 |
def _mem_info(memory: ConversationMemory) -> str:
|
| 870 |
ec = memory.entity_cache
|
|
|
|
| 617 |
</div>
|
| 618 |
"""
|
| 619 |
|
| 620 |
+
def _audio_html(path: str) -> str:
|
| 621 |
+
"""Convert audio file path to autoplay HTML data URI."""
|
| 622 |
+
if not path:
|
| 623 |
+
return "<span></span>"
|
| 624 |
+
try:
|
| 625 |
+
import base64
|
| 626 |
+
data = Path(path).read_bytes()
|
| 627 |
+
b64 = base64.b64encode(data).decode()
|
| 628 |
+
Path(path).unlink(missing_ok=True)
|
| 629 |
+
return f'<audio autoplay style="display:none" src="data:audio/mp3;base64,{b64}"></audio>'
|
| 630 |
+
except Exception:
|
| 631 |
+
return "<span></span>"
|
| 632 |
+
|
| 633 |
+
|
| 634 |
def _init_state(memory, lang, history):
|
| 635 |
"""Ensure state values are never None."""
|
| 636 |
if memory is None:
|
|
|
|
| 711 |
btn_en = gr.Button("🇬🇧 English", variant="primary")
|
| 712 |
btn_ar = gr.Button("🇸🇦 العربية", variant="primary")
|
| 713 |
btn_ur = gr.Button("🇵🇰 اردو", variant="primary")
|
| 714 |
+
lang_audio_out = gr.HTML("<span></span>") # audio via HTML data URI
|
|
|
|
|
|
|
| 715 |
|
| 716 |
# ── Main chat interface (hidden until lang chosen) ─────
|
| 717 |
with gr.Group(visible=False) as chat_group:
|
|
|
|
| 736 |
with gr.Row():
|
| 737 |
send_btn = gr.Button("Send ➤", variant="primary")
|
| 738 |
change_btn = gr.Button("🔄 Change language", variant="secondary")
|
| 739 |
+
audio_out = gr.HTML("<span></span>") # audio via HTML data URI
|
|
|
|
|
|
|
|
|
|
|
|
|
| 740 |
|
| 741 |
# Welcome audio hidden autoplay on load
|
| 742 |
welcome_audio_html = gr.HTML(
|
|
|
|
| 794 |
gr.update(visible=False),
|
| 795 |
gr.update(visible=True),
|
| 796 |
badge,
|
| 797 |
+
_audio_html(audio_path),
|
| 798 |
memory,
|
| 799 |
)
|
| 800 |
|
| 801 |
def handle_lang_mic(audio, memory):
|
| 802 |
memory, _, _ = _init_state(memory, None, None)
|
| 803 |
if audio is None:
|
| 804 |
+
return ("", gr.update(), gr.update(), "", "<span></span>", memory)
|
| 805 |
sr, data = audio
|
| 806 |
import io, soundfile as sf
|
| 807 |
buf = io.BytesIO()
|
| 808 |
sf.write(buf, data, sr, format="WAV")
|
| 809 |
transcript = transcribe_audio_bytes(buf.getvalue())
|
| 810 |
if not transcript:
|
| 811 |
+
return ("", gr.update(), gr.update(), "", "<span></span>", memory)
|
| 812 |
detected = detect_lang(transcript)
|
| 813 |
if not detected:
|
| 814 |
+
return ("", gr.update(), gr.update(), "", "<span></span>", memory)
|
| 815 |
return _set_language(detected, memory)
|
| 816 |
|
| 817 |
lang_mic.stop_recording(
|
|
|
|
| 842 |
def handle_voice(audio, lang_code, memory, history):
|
| 843 |
memory, lang_code, history = _init_state(memory, lang_code, history)
|
| 844 |
if audio is None:
|
| 845 |
+
return history, "<span></span>", memory, ""
|
| 846 |
sr, data = audio
|
| 847 |
import io, soundfile as sf
|
| 848 |
buf = io.BytesIO()
|
| 849 |
sf.write(buf, data, sr, format="WAV")
|
| 850 |
raw = buf.getvalue()
|
| 851 |
if len(raw) < MIN_AUDIO_BYTES:
|
| 852 |
+
return history, "<span></span>", memory, ""
|
| 853 |
transcript = transcribe_audio_bytes(raw)
|
| 854 |
if not transcript or len(transcript.strip()) < 3:
|
| 855 |
return history, None, memory, "⚠️ No clear speech detected."
|
| 856 |
_, new_history, audio_path = process_query(
|
| 857 |
transcript, memory, lang_code or "en", history)
|
| 858 |
mem_info_txt = _mem_info(memory)
|
| 859 |
+
return new_history, _audio_html(audio_path), memory, mem_info_txt
|
| 860 |
|
| 861 |
voice_input.stop_recording(
|
| 862 |
handle_voice,
|
|
|
|
| 868 |
def handle_text(text, lang_code, memory, history):
|
| 869 |
memory, lang_code, history = _init_state(memory, lang_code, history)
|
| 870 |
if not text or not text.strip():
|
| 871 |
+
return history, "<span></span>", memory, "", ""
|
| 872 |
_, new_history, audio_path = process_query(
|
| 873 |
text, memory, lang_code or "en", history)
|
| 874 |
mem_info_txt = _mem_info(memory)
|
| 875 |
+
return new_history, _audio_html(audio_path), memory, mem_info_txt, ""
|
| 876 |
|
| 877 |
def _mem_info(memory: ConversationMemory) -> str:
|
| 878 |
ec = memory.entity_cache
|