|
|
import gradio as gr |
|
|
|
|
|
def create_custom_css() -> str: |
|
|
return """ |
|
|
.gradio-container { |
|
|
background-color: #1f1f1f; |
|
|
} |
|
|
.gr-markdown, .gr-markdown * { |
|
|
color: #ffffff !important; |
|
|
} |
|
|
|
|
|
.streaming-active { |
|
|
border: 3px solid #00ff00 !important; |
|
|
animation: pulse 2s infinite; |
|
|
} |
|
|
|
|
|
.streaming-inactive { |
|
|
border: 2px solid #ff4444 !important; |
|
|
} |
|
|
|
|
|
@keyframes pulse { |
|
|
0% { border-color: #00ff00; } |
|
|
50% { border-color: #00cc00; } |
|
|
100% { border-color: #00ff00; } |
|
|
} |
|
|
|
|
|
.vad-visualizer { |
|
|
background: linear-gradient(90deg, #00ff00, #ffff00, #ff0000); |
|
|
height: 20px; |
|
|
border-radius: 10px; |
|
|
margin: 10px 0; |
|
|
transition: all 0.1s ease; |
|
|
} |
|
|
|
|
|
.conversation-bubble { |
|
|
background: #2d2d2d; |
|
|
border-radius: 15px; |
|
|
padding: 10px 15px; |
|
|
margin: 5px 0; |
|
|
border-left: 4px solid #f55036; |
|
|
} |
|
|
|
|
|
.user-bubble { |
|
|
border-left-color: #36a2f5; |
|
|
} |
|
|
|
|
|
.assistant-bubble { |
|
|
border-left-color: #f55036; |
|
|
} |
|
|
""" |
|
|
def create_header() -> gr.Markdown: |
|
|
return gr.Markdown("# 🎙️ Groq x Gradio Multi-Modal với RAG Wikipedia") |
|
|
def create_audio_components() -> tuple: |
|
|
with gr.Row(): |
|
|
audio_input = gr.Audio(type="numpy", label="Nói hoặc tải lên file âm thanh") |
|
|
|
|
|
with gr.Row(): |
|
|
transcription_output = gr.Textbox( |
|
|
label="Bản ghi âm", |
|
|
lines=5, |
|
|
interactive=True, |
|
|
placeholder="Bản ghi âm sẽ hiển thị ở đây..." |
|
|
) |
|
|
response_output = gr.Textbox( |
|
|
label="Phản hồi AI", |
|
|
lines=5, |
|
|
interactive=True, |
|
|
placeholder="Phản hồi của AI sẽ hiển thị ở đây..." |
|
|
) |
|
|
|
|
|
with gr.Row(): |
|
|
tts_audio_output = gr.Audio( |
|
|
label="Phản hồi bằng giọng nói", |
|
|
interactive=False |
|
|
) |
|
|
|
|
|
process_button = gr.Button("Xử lý", variant="primary") |
|
|
|
|
|
return audio_input, transcription_output, response_output, tts_audio_output, process_button |
|
|
|
|
|
def create_chat_components() -> tuple: |
|
|
chatbot = gr.Chatbot() |
|
|
state = gr.State([]) |
|
|
|
|
|
with gr.Row(): |
|
|
user_input = gr.Textbox( |
|
|
show_label=False, |
|
|
placeholder="Nhập tin nhắn của bạn ở đây...", |
|
|
container=False, |
|
|
scale=4 |
|
|
) |
|
|
send_button = gr.Button("Gửi", variant="primary", scale=1) |
|
|
clear_button = gr.Button("Xóa Chat", variant="secondary", scale=1) |
|
|
|
|
|
with gr.Row(): |
|
|
chat_tts_output = gr.Audio( |
|
|
label="Phản hồi bằng giọng nói", |
|
|
interactive=False |
|
|
) |
|
|
|
|
|
return chatbot, state, user_input, send_button, clear_button, chat_tts_output |
|
|
def create_streaming_voice_components() -> tuple: |
|
|
"""Tạo components cho streaming voice với VAD""" |
|
|
with gr.Group(): |
|
|
gr.Markdown("## 🎤 Trò chuyện giọng nói thời gian thực với VAD") |
|
|
gr.Markdown("Hệ thống sẽ tự động phát hiện khi bạn nói và dừng, tạo cuộc hội thoại tự nhiên") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(scale=1): |
|
|
|
|
|
vad_visualizer = gr.HTML( |
|
|
value="<div class='vad-visualizer' style='width: 100%;'></div>", |
|
|
label="Voice Activity" |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Row(): |
|
|
start_listening_btn = gr.Button( |
|
|
"🎙️ Bắt đầu lắng nghe", |
|
|
variant="primary", |
|
|
size="sm" |
|
|
) |
|
|
stop_listening_btn = gr.Button( |
|
|
"🛑 Dừng lắng nghe", |
|
|
variant="secondary", |
|
|
size="sm" |
|
|
) |
|
|
|
|
|
|
|
|
status_display = gr.Textbox( |
|
|
label="Trạng thái", |
|
|
value="Chưa lắng nghe", |
|
|
interactive=False |
|
|
) |
|
|
|
|
|
|
|
|
state_display = gr.JSON( |
|
|
label="Thông tin hội thoại", |
|
|
value={} |
|
|
) |
|
|
|
|
|
with gr.Column(scale=2): |
|
|
|
|
|
realtime_transcription = gr.Textbox( |
|
|
label="🎯 Đang nói...", |
|
|
lines=2, |
|
|
interactive=False, |
|
|
placeholder="Văn bản được chuyển đổi sẽ xuất hiện ở đây..." |
|
|
) |
|
|
|
|
|
|
|
|
ai_response = gr.Textbox( |
|
|
label="🤖 Phản hồi AI", |
|
|
lines=3, |
|
|
interactive=False, |
|
|
placeholder="Phản hồi của AI sẽ xuất hiện ở đây..." |
|
|
) |
|
|
|
|
|
|
|
|
tts_output = gr.Audio( |
|
|
label="🔊 Phản hồi bằng giọng nói", |
|
|
interactive=False, |
|
|
autoplay=True |
|
|
) |
|
|
|
|
|
|
|
|
streaming_state = gr.State(value=False) |
|
|
conversation_history = gr.State(value=[]) |
|
|
|
|
|
return ( |
|
|
start_listening_btn, stop_listening_btn, status_display, state_display, |
|
|
realtime_transcription, ai_response, tts_output, streaming_state, |
|
|
conversation_history, vad_visualizer |
|
|
) |