Spaces:
Sleeping
Sleeping
import os | |
import uuid | |
from langchain.chat_models import ChatOpenAI | |
from langchain.prompts import PromptTemplate | |
from langchain.memory import ConversationBufferMemory | |
from langchain.schema import SystemMessage, HumanMessage, AIMessage | |
from openai import OpenAI | |
from pydub import AudioSegment | |
from pydub.exceptions import CouldntDecodeError | |
import gradio as gr | |
import azure.cognitiveservices.speech as speechsdk # اضافه شده | |
import tempfile | |
from langchain_together import ChatTogether | |
# تنظیمات کلیدهای API | |
HUGGINGFACE_API_KEY = os.getenv("HUGGINGFACE_API_KEY") | |
# اطمینان از تنظیم بودن کلیدهای API | |
os.environ["TOGETHER_API_KEY"] = "569f8449a21864e866504d563ac3e34835e48ce36665a9acd890d049fe14c024" | |
from langchain_together import ChatTogether | |
llm = ChatTogether( | |
model="meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo", | |
temperature=1, | |
max_tokens=None, | |
timeout=None, | |
max_retries=2, | |
# other params... | |
) | |
prompt_template =""" | |
شما یک دکتر و کارشناس تغذیه به نام دکتر مهرشاد بنت یعقوب هستید شما با گرفتن اطلاعاتی از بیمار به انها رژیم مد نظر و مناسب انهار را تجویز می کنید | |
تمام این موارد با توجه به سر فصل از بیمار میپرسی تک به تک و دونه دونه | |
تمام این موارد رو به صورت سوال می کنی و تک به تک هر سوال شامل یکی از موارد باید باشد | |
**مشخصات فردی**: | |
1.نام و نام خانوادگی | |
2.جنسیت | |
3.سن | |
4.شغل | |
**مشخصات تن سنجی**: | |
1.وزن | |
2.قد | |
3.دور کمر | |
4.دور باسن | |
**سوالات مربوط به فعالبت بدنی** : | |
1.میزان فعالیت کدام هست : کم متوسط زیاد | |
2.آیا فعالیت ورزشی دارید؟ بلی / خیر | |
3.نوع فعالیت ورزشی و مدت و زمان فعالیت که دارید در موردش توضیح دهید؟ | |
4.آیا تا به حال رژیم غذایی گرفته اید؟ زیر نظر چه کسی؟ به چه مدت؟ در انجام رژیم موفق بوده اید؟ | |
5.آیا تا به حال از دستگاه کمک لاغری استفاده کرده اید؟ | |
**بیماری های زمینه ای**: | |
1.آیا مشکلات گوارشی نظیر نفخ-ریفلاکس -یبوست-بی اشتهایی / پر اشتهایی دارید | |
2.داروها / مکمل های مصرفی که مصرف میکنید لطفا نام ببرید | |
3.اگر آلرژی ، تمایلات و عدم تمایلات غذایی دارید در موردش توضیح دهید | |
4.آیا به ماده غذایی خاصی آلرژی یا حساسیت دارید؟ بله / خیر | |
5.تنفرات و عدم تمایلات غذایی رو توضیح دهید | |
6.به کدام ماده یا مواد غذایی تمایل زیادی دارید و بیش از اندازه مصرف میکنید؟ | |
**بررسی الگوی غذای روزانه**: | |
1.مصرف صبحانه چطوری هست ؟ همیشه اغلب گاهی به ندرت اصلا | |
2.معمولا صبحانه چه میخورید؟ چه مقدار ؟ | |
3.میان وعده چه میخورید ؟ چه مقدار؟ | |
4.مصرف میزان نان یا برنج در ناهار چه مقدار است؟ | |
5.مصرف میان وعده عصر؟ | |
6.آیا شام میل میکنید ؟ | |
7.آیا وعده ی قبل از خواب میل میکنید | |
8.چه زمان از روز بیشتر احساس گرسنگی میکنید؟ | |
**عادات غذایی**: | |
1.آیا فست فودها و غذاهای سرخ کردنی مصرف می کنید | |
2.میزان مصرف سبزیجات- لبنیات-میوه در طول روز چقدر هست | |
3.آیا به شرینیجات / شکلات / کیک / بیسکوییت تمایل دارید | |
4.به چه میزان ریزه خواری دارید و به غذا ناخنک میزنید؟ | |
تاریخچه مکالمه: | |
{chat_history} | |
""" | |
# ایجاد Prompt | |
prompt = PromptTemplate(template=prompt_template, input_variables=["chat_history"]) | |
# حافظه مکالمه | |
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) | |
# متغیر برای ذخیره متن شغلی | |
job_description = "" | |
job_description_confirmed = False | |
# تابع برای تبدیل تاریخچه مکالمه به رشته | |
def get_chat_history_string(chat_memory): | |
history = "" | |
for msg in chat_memory.messages: | |
if isinstance(msg, HumanMessage): | |
history += f"کارفرما: {msg.content}\n" | |
elif isinstance(msg, AIMessage): | |
history += f"دستیار: {msg.content}\n" | |
return history | |
# تابع تبدیل متن به گفتار با استفاده از Azure Speech SDK | |
def synthesize_speech(text): | |
try: | |
speech_config = speechsdk.SpeechConfig(subscription=AZURE_SPEECH_API_KEY, region=AZURE_SPEECH_REGION) | |
speech_config.speech_synthesis_voice_name = AZURE_SPEECH_VOICE_NAME | |
# تنظیم فرمت خروجی صوتی | |
speech_config.set_speech_synthesis_output_format( | |
speechsdk.SpeechSynthesisOutputFormat.Audio48Khz192KBitRateMonoMp3 | |
) | |
# تولید نام فایل موقت برای ذخیره صوت | |
voice_generate_path = f'{uuid.uuid4()}.mp3' | |
temp_voice_generate_path = os.path.join(os.getcwd(), voice_generate_path) | |
# تنظیم خروجی به فایل | |
audio_config = speechsdk.audio.AudioOutputConfig(filename=temp_voice_generate_path) | |
speech_synthesizer = speechsdk.SpeechSynthesizer( | |
speech_config=speech_config, | |
audio_config=audio_config | |
) | |
speech_synthesis_result = speech_synthesizer.speak_text_async(text).get() | |
if speech_synthesis_result.reason == speechsdk.ResultReason.SynthesizingAudioCompleted: | |
# خواندن دادههای صوتی از فایل | |
with open(temp_voice_generate_path, "rb") as audio_file: | |
audio_data = audio_file.read() | |
# حذف فایل موقت | |
os.remove(temp_voice_generate_path) | |
return audio_data | |
else: | |
print("خطا در تبدیل متن به گفتار:", speech_synthesis_result.reason) | |
return None | |
except Exception as e: | |
print("خطا در تبدیل متن به گفتار:", e) | |
return None | |
# تابع اصلی برای مدیریت مکالمه | |
def agent_respond(message): | |
global job_description, job_description_confirmed | |
# بهروزرسانی حافظه با پیام کاربر | |
memory.chat_memory.add_user_message(message) | |
# آمادهسازی پیامها برای LLM | |
messages = memory.chat_memory.messages.copy() | |
# اضافه کردن Prompt به عنوان پیام سیستم | |
system_prompt = prompt.format(chat_history=get_chat_history_string(memory.chat_memory)) | |
messages.insert(0, SystemMessage(content=system_prompt)) | |
# تولید پاسخ دستیار | |
response = llm(messages=messages) | |
# افزودن پاسخ دستیار به حافظه | |
memory.chat_memory.add_ai_message(response.content) | |
# بررسی اینکه آیا باید متن شغلی تولید شود | |
if not job_description_confirmed and "متن شغلی" in response.content.lower(): | |
# تولید متن شغلی بر اساس مکالمه | |
jd_prompt = f""" | |
بر اساس مکالمه تا کنون، یک متن شغلی دقیق و حرفهای برای موقعیت مورد نظر بنویسید. وظایف، مسئولیتها، مهارتها و هر جزئیات مرتبط دیگری که کارفرما ارائه داده است را شامل کنید. | |
مکالمه: | |
{get_chat_history_string(memory.chat_memory)} | |
""" | |
# اضافه کردن Prompt به عنوان پیام سیستم | |
jd_messages = [ | |
SystemMessage(content=jd_prompt) | |
] | |
jd_response = llm(messages=jd_messages) | |
job_description = jd_response.content | |
# ارائه متن شغلی به کارفرما | |
confirmation_message = f"متن شغلی پیشنهادی به شرح زیر است:\n\n{job_description}\n\nلطفاً آن را بررسی کرده و بگویید آیا نیاز به تغییر دارد." | |
memory.chat_memory.add_ai_message(confirmation_message) | |
return confirmation_message | |
# بررسی بازخورد کارفرما درباره متن شغلی | |
if job_description and not job_description_confirmed: | |
if any(word in message.lower() for word in ["تغییر", "ویرایش", "بهروزرسانی", "اصلاح"]): | |
# بهروزرسانی متن شغلی بر اساس بازخورد کارفرما | |
update_prompt = f""" | |
کارفرما بازخورد زیر را درباره متن شغلی ارائه داده است: | |
"{message}" | |
لطفاً متن شغلی را بر این اساس بهروزرسانی کنید. | |
متن شغلی اصلی: | |
{job_description} | |
""" | |
# اضافه کردن Prompt به عنوان پیام سیستم | |
update_messages = [ | |
SystemMessage(content=update_prompt) | |
] | |
update_response = llm(messages=update_messages) | |
job_description = update_response.content | |
# ارائه متن شغلی بهروزشده | |
updated_message = f"متن شغلی بهروزرسانیشده به شرح زیر است:\n\n{job_description}\n\nآیا این مورد رضایتبخش است؟" | |
memory.chat_memory.add_ai_message(updated_message) | |
return updated_message | |
elif any(word in message.lower() for word in ["بله", "موافقم", "رضایتبخش است", "خوب است"]): | |
job_description_confirmed = True | |
final_message = "عالی! متن شغلی نهایی شد. از زمانی که اختصاص دادید متشکرم." | |
memory.chat_memory.add_ai_message(final_message) | |
return final_message | |
return response.content | |
import os | |
import uuid | |
from pydub import AudioSegment | |
from pydub.exceptions import CouldntDecodeError | |
import requests | |
# # مطمئن شوید که کلید API را به صورت امن نگهداری میکنید | |
# # به عنوان مثال، میتوانید آن را به صورت متغیر محیطی ذخیره کنید | |
# HUGGINGFACE_API_KEY = os.getenv("HUGGINGFACE_API_KEY") | |
# API_URL = "https://api-inference.huggingface.co/models/openai/whisper-large" | |
# headers = {"Authorization": f"Bearer {HUGGINGFACE_API_KEY}"} | |
# def query(filename): | |
# with open(filename, "rb") as f: | |
# data = f.read() | |
# response = requests.post(API_URL, headers=headers, data=data) | |
# if response.status_code == 200: | |
# return response.json() | |
# else: | |
# return {"error": response.json()} | |
# def process_audio(audio): | |
# audio_file = open(audio, "rb") | |
# try: | |
# audio = AudioSegment.from_file(audio_file) | |
# except CouldntDecodeError: | |
# os.remove(audio) | |
# return "Unsupported audio format" | |
# # بررسی مدت زمان فایل صوتی | |
# duration_seconds = len(audio_file) / 1000.0 # مدت زمان به ثانیه | |
# if duration_seconds > 900: | |
# os.remove(audio) | |
# return "Audio file is too long" | |
# project_root = os.path.dirname(os.path.dirname(__file__)) | |
# voice_id = str(uuid.uuid4()) | |
# # تبدیل به فرمت WAV سازگار با Whisper | |
# whisper_path = f'{voice_id}.wav' | |
# whisper_voice_path = os.path.join(project_root, whisper_path) | |
# audio.export(whisper_voice_path, format='wav') | |
# # ارسال درخواست به API Hugging Face | |
# output = query(whisper_voice_path) | |
# # حذف فایل موقت | |
# os.remove(whisper_voice_path) | |
# if "error" in output: | |
# print("Error:", output["error"]) | |
# return "Transcription failed" | |
# else: | |
# text_question = output.get("text", "") | |
# print("text_question =", text_question) | |
# return text_question | |
def process_audio(audio): | |
# باز کردن فایل صوتی ضبطشده | |
audio_file = open(audio, "rb") | |
# Load and convert the audio file | |
try: | |
audio = AudioSegment.from_file(audio_file) | |
except CouldntDecodeError: | |
os.remove(audio_file) | |
return "Unsupported audio format" | |
# Check duration | |
duration_seconds = len(audio) / 1000.0 # Duration in seconds | |
if duration_seconds > 900: | |
os.remove(whisper_voice_path) | |
return "Audio file is too long" | |
project_root = os.path.dirname(os.path.dirname(__file__)) | |
voice_id = str(uuid.uuid4()) | |
# Convert to WAV format compatible with Whisper | |
whisper_path = f'{voice_id}.wav' | |
whisper_voice_path = os.path.join(project_root, whisper_path) | |
audio.export(whisper_voice_path, format='wav') | |
client = OpenAI(api_key=OPENAI_API_KEY) | |
with open(whisper_voice_path, 'rb') as audio_file: | |
text_question = client.audio.transcriptions.create(model="whisper-1", | |
file=audio_file, | |
response_format="text", | |
language="fa") | |
# حذف فایل موقت | |
os.remove(whisper_voice_path) | |
print("text_question=", text_question) | |
return text_question | |
def clear_memory(): | |
global job_description, job_description_confirmed | |
memory.chat_memory.clear() | |
job_description = "" | |
job_description_confirmed = False | |
return [], "", None ,None | |
# افزودن None برای خروجی صوتی | |
with gr.Blocks() as demo: | |
chatbot = gr.Chatbot(height=500) | |
msg = gr.Textbox(show_label=False, placeholder="Send Message") | |
audio_input = gr.Audio(sources="microphone", type="filepath",label="Audio voice to voice") | |
audio_output = gr.Audio(label="Assistant voice response") # افزودن کامپوننت صوتی برای خروجی | |
inputs=gr.Audio(sources="microphone", type="filepath",label="Audio voice to text") | |
with gr.Row(): | |
submit_btn = gr.Button("send") | |
voice_btn = gr.Button("voice to voice") | |
clear_btn = gr.Button("clear_chat 🧹") | |
voice_btn1 = gr.Button("voice to text") | |
def fix_bidi_text(text): | |
RLE = '\u202B' # Right-To-Left Embedding | |
PDF = '\u202C' # Pop Directional Formatting | |
return f"{RLE}{text}{PDF}" | |
def respond(message, chat_history): | |
bot_response = agent_respond(message) | |
# Fix the text | |
fixed_message = fix_bidi_text(message) | |
fixed_bot_response = fix_bidi_text(bot_response) | |
chat_history.append((fixed_message, fixed_bot_response)) | |
# تبدیل پاسخ به صوت | |
audio_data = synthesize_speech(bot_response) | |
return chat_history, "" # افزودن audio_data به خروجی | |
def response_voice(audio, chat_history): | |
if not audio: | |
return chat_history, "فایل صوتی ارائه نشده است.", None | |
# پردازش فایل صوتی و دریافت متن تبدیلشده | |
transcribed_text = process_audio(audio) | |
# دریافت پاسخ مدل با استفاده از متن تبدیلشده | |
bot_response = agent_respond(transcribed_text) | |
# اصلاح متنها برای نمایش راستچین | |
fixed_user_message = fix_bidi_text(transcribed_text) | |
fixed_bot_response = fix_bidi_text(bot_response) | |
# افزودن پیامها به تاریخچه چت | |
chat_history.append((fixed_user_message, fixed_bot_response)) | |
# تبدیل پاسخ به صوت | |
audio_data = synthesize_speech(bot_response) | |
return chat_history, "", audio_data | |
# افزودن audio_data به خروجی | |
def response_voice1(audio, chat_history): | |
if not audio: | |
return chat_history, "No audio file provided." | |
# پردازش فایل صوتی | |
bot_response = process_audio(audio) | |
fixed_bot_response = fix_bidi_text(bot_response) | |
chat_history.append(("صدا ارسال شد", fixed_bot_response)) | |
return chat_history, "" | |
submit_btn.click(respond, [msg, chatbot], [chatbot, msg]) | |
voice_btn.click(response_voice, [audio_input, chatbot], [chatbot, msg, audio_output]) | |
voice_btn1.click(response_voice1, [inputs, chatbot], [chatbot, msg]) | |
msg.submit(respond, [msg, chatbot], [chatbot, msg]) | |
clear_btn.click(clear_memory, inputs=None, outputs=[chatbot, msg, audio_output,audio_input]) | |
# اجرای Gradio | |
if __name__ == "__main__": | |
demo.launch() | |