Spaces:
Running
Running
import os | |
import logging | |
import threading | |
import numpy as np | |
import torch | |
import librosa | |
import soundfile as sf | |
from pydub import AudioSegment | |
from telegram import Update | |
from telegram.ext import ApplicationBuilder, MessageHandler, filters, CommandHandler | |
from transformers import pipeline | |
from huggingface_hub import login | |
import asyncio | |
from collections import defaultdict | |
# ===== تهيئة التوكن ===== | |
login(token=os.getenv("HF_TOKEN")) | |
# ===== إعدادات النظام ===== | |
logging.basicConfig( | |
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', | |
level=logging.INFO | |
) | |
logger = logging.getLogger(__name__) | |
# ===== تحميل النماذج ===== | |
try: | |
# 1. نموذج التعرف على الكلام | |
asr_pipeline = pipeline( | |
"automatic-speech-recognition", | |
model="jonatasgrosman/wav2vec2-large-xlsr-53-arabic", | |
token=os.getenv("HF_TOKEN") | |
) | |
# 2. نموذج توليف الصوت | |
tts_pipeline = pipeline("text-to-speech", model="mohamedhossam/arabic-tts", token=os.getenv("HF_TOKEN")) | |
except Exception as e: | |
logger.error(f"فشل تحميل النماذج: {str(e)}") | |
raise | |
# ===== ذاكرة المحادثة ===== | |
conversation_history = defaultdict(list) | |
# ===== دوال معالجة الصوت ===== | |
def enhance_audio(input_path: str, output_path: str) -> bool: | |
try: | |
audio = AudioSegment.from_wav(input_path) | |
audio = audio.low_pass_filter(3000) | |
audio = audio.high_pass_filter(100) | |
audio = audio.normalize() | |
audio = audio.fade_in(150).fade_out(150) | |
audio.export(output_path, format="wav") | |
return True | |
except Exception as e: | |
logger.error(f"خطأ في تحسين الصوت: {str(e)}") | |
return False | |
async def speech_to_text(audio_path: str) -> str: | |
try: | |
audio, sr = librosa.load(audio_path, sr=16000) | |
sf.write("temp.wav", audio, sr) | |
result = asr_pipeline("temp.wav") | |
return result["text"] | |
except Exception as e: | |
logger.error(f"فشل التعرف على الصوت: {str(e)}") | |
return "" | |
async def generate_response(text: str, user_id: str) -> str: | |
try: | |
# تحديث ذاكرة المحادثة | |
conversation_history[user_id].append(text) | |
context = "\n".join(conversation_history[user_id][-3:]) | |
chatbot = pipeline( | |
"text-generation", | |
model="aubmindlab/aragpt2-base", | |
token=os.getenv("HF_TOKEN"), | |
max_length=50, | |
temperature=0.7, | |
) | |
response = chatbot( | |
context, | |
num_return_sequences=1, | |
pad_token_id=50256 | |
) | |
return response[0]['generated_text'].strip() # إزالة المسافات الزائدة | |
except Exception as e: | |
logger.error(f"فشل توليد الرد: {str(e)}") | |
return "حدث خطأ في توليد الرد." | |
async def text_to_speech(text: str) -> None: | |
try: | |
audio = tts_pipeline(text) | |
sf.write("bot_response.wav", audio["audio"], 22050) # تأكد من استخدام معدل العينة الصحيح | |
except Exception as e: | |
logger.error(f"فشل تحويل النص إلى صوت: {str(e)}") | |
# ===== دوال التفاعل مع المستخدم ===== | |
async def start(update: Update, context): | |
await update.message.reply_text("مرحبًا! أنا بوت الدردشة الصوتية الأنثوي 🎤\nأرسل لي رسالة صوتية وسأرد عليك بصوت أنثوي واضح.") | |
async def process_voice(update: Update, context): | |
try: | |
user_id = update.message.from_user.id | |
voice_file = await update.message.voice.get_file() | |
await voice_file.download_to_drive("user_voice.ogg") | |
user_text = await speech_to_text("user_voice.ogg") | |
if not user_text: | |
await update.message.reply_text("لم أتمكن من فهم الصوت. يرجى المحاولة مرة أخرى.") | |
return | |
bot_response = await generate_response(user_text, str(user_id)) | |
await text_to speech(bot_response) | |
if enhance_audio("bot_response.wav", "bot_response_enhanced.wav"): | |
await update.message.reply_voice("bot_response_enhanced.wav") | |
else: | |
await update.message.reply_voice("bot_response.wav") | |
except Exception as e: | |
logger.error(f"خطأ غير متوقع: {str(e)}") | |
await update.message.reply_text("⚠️ عذرًا، حدث خطأ في المعالجة.") | |
# ===== التشغيل الرئيسي ===== | |
def run_bot(): | |
loop = asyncio.new_event_loop() | |
asyncio.set_event_loop(loop) | |
application = ApplicationBuilder().token(os.getenv("TELEGRAM_TOKEN")).build() | |
application.add_handler(CommandHandler("start", start)) | |
application.add_handler(MessageHandler(filters.VOICE, process_voice)) | |
application.run_polling( | |
close_loop=False, | |
stop_signals=[] | |
) | |
if __name__ == "__main__": | |
bot_thread = threading.Thread(target=run_bot, daemon=True) | |
bot_thread.start() | |
bot_thread.join() |