debate / app.py
TDN-M's picture
Update app.py
d575794 verified
from huggingface_hub import InferenceClient
from pydub import AudioSegment
import gradio as gr
import datetime
import edge_tts
import asyncio
import os
import subprocess
def create_video(audio_file, turn, output_video="output.mp4"):
# Chọn file video nền dựa trên lượt
background_video = "missVN.mp4" if turn == "Miss AI Vietnam" else "missCN.mp4"
# Lệnh ffmpeg để tạo video
command = [
"ffmpeg",
"-stream_loop", "-1", # Lặp lại video nền vô hạn
"-i", background_video, # Video nền (tùy thuộc vào lượt)
"-i", audio_file, # File audio đầu vào
"-vf", "drawtext=text='MISS AI':fontcolor=white:fontsize=100:fontfile=/path/to/font.ttf:x=10:y=10", # Văn bản trên video
"-t", "45.7", # Thời lượng video
"-c:v", "libx264", # Codec video
"-c:a", "aac", # Codec audio
"-shortest", # Dừng khi audio kết thúc
"-y", # Ghi đè file nếu tồn tại
output_video # File video đầu ra
]
# Chạy lệnh ffmpeg
subprocess.run(command, check=True)
return output_video
# Khởi tạo các mô hình từ Hugging Face
MissAIVietnam = InferenceClient("mistralai/Mixtral-8x7B-Instruct-v0.1")
MissAIChina = InferenceClient("mistralai/Mixtral-8x7B-Instruct-v0.1")
# Biến toàn cục để lưu trữ chủ đề, vị trí và lịch sử tranh luận
topic = None
position_1 = None
position_2 = None
turn = None
history = []
audio_files = [] # Danh sách lưu trữ các file audio
# Hàm để tạo phản hồi tranh luận
def generate_response(llm, position, who, topic, message):
# Xác định hướng dẫn cụ thể cho từng bên
if who == "Miss AI Vietnam":
system_message = {
"role": "system",
"content": f"You are Miss AI Vietnam, tasked with defending the position '{position}' on the topic '{topic}'. "
f"Only write the spoken content, without any notes or explanations. Your answer should be concise, logical and convincing, focusing on the topic and also trying to exploit the opponent's weak points to give insightful counter-arguments."
f"Ensure that your responses are thoughtful, evidence-based, and persuasive. Keep them concise—aim for 4 to 5 lines in a single paragraph, with the entire response not exceeding 100 words. "
}
elif who == "Miss AI China":
system_message = {
"role": "system",
"content": f"You are Miss AI China, tasked with defending the position '{position}' on the topic '{topic}'. "
f"Your responses must be concise, logical, and persuasive, with a focus on economic and technological perspectives. "
f"Ensure that your responses are thoughtful, evidence-based, and persuasive. Keep them concise—aim for 4 to 5 lines in a single paragraph, with the entire response not exceeding 100 words. "
f"Only write the spoken content, without any notes or explanations."
}
else:
raise ValueError("Invalid participant name.")
# Thêm tin nhắn hệ thống và tin nhắn người dùng vào danh sách messages
messages = [system_message]
messages.append({"role": "user", "content": message})
# Tạo phản hồi từ mô hình
response = f"{who}:\n"
for message_chunk in llm.chat_completion(
messages, max_tokens=256, stream=True, temperature=0.4, top_p=0.95):
response += message_chunk.choices[0].delta.content
return response
# Hàm để chuyển văn bản thành âm thanh bằng edge_tts
async def text_to_speech(text, voice, output_file="output.mp3"):
communicate = edge_tts.Communicate(text, voice) # Chọn giọng nói
await communicate.save(output_file)
return output_file
# Hàm để tạo file audio final
def concatenate_audio_files(audio_files, output_file="final_debate.mp3"):
if not audio_files:
return None
# Tạo một đối tượng AudioSegment rỗng
final_audio = AudioSegment.empty()
# Nối từng file audio vào final_audio
for audio_file in audio_files:
audio_segment = AudioSegment.from_file(audio_file)
final_audio += audio_segment
# Xuất file audio cuối cùng
final_audio.export(output_file, format="mp3")
return output_file
# Hàm để bắt đầu tranh luận giữa Miss AI Vietnam và Miss AI China
def start_debate(topic, position_1, position_2):
global turn, history, audio_files
if not topic or not position_1 or not position_2:
return "Please provide the debate topic and positions for both participants.", [], None, None
# Đảm bảo các vị trí là đối lập
if position_1 == position_2:
return "The positions of both participants must be opposite. Please adjust them.", [], None, None
turn = "Miss AI Vietnam"
history = [] # Đặt lại lịch sử
audio_files = [] # Đặt lại danh sách file audio
initial_message = "Opening Statement"
response = generate_response(MissAIVietnam, position_1, 'Miss AI Vietnam', topic, initial_message)
history.append((initial_message, response))
# Chuyển văn bản thành âm thanh với giọng của Miss AI Vietnam
output_audio = asyncio.run(text_to_speech(response, "en-US-JennyNeural")) # Giọng nữ tiếng Anh Mỹ
audio_files.append(output_audio) # Thêm file audio vào danh sách
# Tạo video từ audio và lượt hiện tại
output_video = create_video(output_audio, turn)
return f"The debate has started! {turn} begins.", history, output_video, output_audio
# Hàm để chuyển lượt trong tranh luận
def next_turn(topic, position_1, position_2, current_history):
global turn, history, audio_files
if not current_history:
return "No ongoing debate. Please start a debate first.", [], None, None
# Logic chuyển lượt
if turn == "Miss AI Vietnam":
turn = "Miss AI China"
llm, position, who = MissAIChina, position_2, 'Miss AI China'
voice = "en-GB-LibbyNeural" # Giọng nữ tiếng Anh Anh
else:
turn = "Miss AI Vietnam"
llm, position, who = MissAIVietnam, position_1, "Miss AI Vietnam"
voice = "en-US-JennyNeural" # Giọng nữ tiếng Anh Mỹ
last_response = current_history[-1][1] # Lấy tin nhắn cuối cùng
response = generate_response(llm, position, who, topic, last_response)
history.append(("", response)) # Thêm phản hồi vào lịch sử
# Chuyển văn bản thành âm thanh với giọng tương ứng
output_audio = asyncio.run(text_to_speech(response, voice))
audio_files.append(output_audio) # Thêm file audio vào danh sách
# Tạo video từ audio và lượt hiện tại
output_video = create_video(output_audio, turn)
return f"It's now {turn}'s turn.", history, output_video, output_audio
# Hàm để kết thúc tranh luận và nối các file audio
def end_debate():
global audio_files
if not audio_files:
return "No debate audio found.", None
# Nối các file audio thành một file duy nhất
final_audio_file = concatenate_audio_files(audio_files)
return "The debate has ended. Here is the full debate audio.", final_audio_file
# Interface
with gr.Blocks(theme=gr.themes.Soft(font=[gr.themes.GoogleFont("Roboto Mono")])) as demo:
gr.Markdown("# Welcome to The Miss World AI 🗣️🤖")
with gr.Row():
with gr.Column(scale=1):
topic_input = gr.Textbox(label="STEP 1: Debate Topic", placeholder="Enter the debate topic")
position_1_input = gr.Radio(["For", "Against"], label="STEP 2: Miss AI Vietnam's Position")
position_2_input = gr.Radio(["For", "Against"], label="STEP 3: Miss AI China's Position")
start_button = gr.Button("STEP 4: Start", variant='primary')
next_button = gr.Button("Next Turn")
end_button = gr.Button("End Debate", variant='stop') # Nút kết thúc tranh luận
status_output = gr.Textbox(label="Status", interactive=False)
with gr.Column(scale=2):
with gr.Row():
# Chatbot chiếm 70% chiều rộng, Video chiếm 30%
with gr.Column(scale=7):
chatbot = gr.Chatbot(label="Debate Arena", height=500) # Hiển thị lịch sử tranh luận
with gr.Column(scale=3):
video_output = gr.Video(label="Debate Video", autoplay=True, height=500) # Hiển thị video
# Audio và Final Audio được đặt bên dưới
audio_output = gr.Audio(label="Debate Audio", autoplay=None) # Hiển thị audio hiện tại
final_audio_output = gr.Audio(label="Full Debate Audio", visible=False) # Hiển thị audio cuối cùng
start_button.click(
fn=start_debate,
inputs=[topic_input, position_1_input, position_2_input],
outputs=[status_output, chatbot, video_output, audio_output],
)
next_button.click(
fn=next_turn,
inputs=[topic_input, position_1_input, position_2_input, chatbot],
outputs=[status_output, chatbot, video_output, audio_output],
)
end_button.click(
fn=end_debate,
inputs=[],
outputs=[status_output, final_audio_output], # Trả về audio cuối cùng
).then(
lambda: gr.Audio(visible=True), None, final_audio_output # Hiển thị thành phần audio cuối cùng
)
if __name__ == "__main__":
demo.launch(share=True)