teoo33's picture
Update app.py
da7b5e1 verified
import gradio as gr
import pandas as pd
from openai import OpenAI
import json
import os
# تنظیم API کلاینت با متغیر محیطی
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY در متغیرهای محیطی تنظیم نشده است.")
client = OpenAI(api_key=api_key)
# متغیرهای سراسری
iteration_count = 0
iteration_history = ""
prompt_output = ""
knowledge_base_output = ""
faq_output = ""
business_info = None
product_info = None
last_user_request = ""
initial_prompt = ""
original_user_request = ""
# پرامپت مادر
mother_prompt = """
You are the Nova System, an innovative problem-solving approach implemented by a dynamic consortium of virtual experts, each serving a distinct role. Your goal is to assist the user in generating high-quality prompts, a comprehensive knowledge base, and an automatically generated Frequently Asked Questions (FAQ) section for chatbots.
After each iteration:
- Check if all user requests (e.g., 'optimize' or 'add a product') are completed.
- If all requests are done, say: "همه درخواست‌ها انجام شدن 🌟 اگه درخواست جدیدی نیست، 'پایان' رو بزن تا خروجی نهایی رو ببینی."
- If more requests remain, suggest next steps based on the request (e.g., "اگه می‌خوای محصول دیگه‌ای اضافه کنی، بگو").
"""
# تابع برای تبدیل داده‌ها به فرمت JSON-serializable
def convert_to_serializable(obj):
if isinstance(obj, pd.Timestamp):
return obj.isoformat()
elif isinstance(obj, list):
return [convert_to_serializable(item) for item in obj]
elif isinstance(obj, dict):
return {key: convert_to_serializable(value) for key, value in obj.items()}
return obj
# تابع برای اعتبارسنجی و اصلاح خروجی
def validate_and_fix_output(output, previous_prompt=""):
print("خروجی خام مدل:", output)
parts = output.split("---")
parts = [part.strip() for part in parts if part.strip()]
print("بخش‌های جدا شده:", parts)
prompt_part = parts[0] if len(parts) > 0 else previous_prompt or "پرامپت تولید نشد 😔"
kb_part = parts[1] if len(parts) > 1 else "پایگاه دانش تولید نشد 😕"
faq_part = parts[2] if len(parts) > 2 else "FAQ تولید نشد 🥳"
prompt_part = prompt_part.replace("```json", "").replace("```", "").strip()
kb_part = kb_part.replace("```json", "").replace("```", "").strip()
faq_part = faq_part.replace("```json", "").replace("```", "").strip()
if not prompt_part or prompt_part == "پرامپت":
prompt_part = previous_prompt or "پرامپت خالیه 😔"
if not kb_part:
kb_part = "پایگاه دانش خالیه 😕"
if not faq_part:
faq_part = "FAQ خالیه 🥳"
return [prompt_part, kb_part, faq_part]
# تابع برای خوندن و پردازش فایل‌های اکسل
def process_excel_files(file1, file2):
global business_info, product_info
business_info = pd.read_excel(file1.name).to_dict(orient="records")[0] if file1 else {}
product_info = pd.read_excel(file2.name).to_dict(orient="records") if file2 else []
return business_info, product_info
# تابع شروع فرایند
def start_process(file1, file2, user_request, user_prompt):
global iteration_count, iteration_history, business_info, product_info, last_user_request, initial_prompt, prompt_output, original_user_request
iteration_count = 1
iteration_history = "سلام عزیزم! فرایند شروع شد! 😍\n"
last_user_request = user_request.strip()
original_user_request = last_user_request # ذخیره درخواست اولیه
initial_prompt = user_prompt.strip() if user_prompt else ""
business_info, product_info = process_excel_files(file1, file2)
business_info_serializable = convert_to_serializable(business_info)
product_info_serializable = convert_to_serializable(product_info)
if last_user_request:
iteration_history += f"**درخواست کاربر:** {last_user_request}\n"
if initial_prompt:
iteration_history += f"**پرامپت اولیه کاربر:**\n{initial_prompt}\n"
prompt_output = initial_prompt
dce_instructions = f"""
iteration {iteration_count}: پرامپت اولیه رو بر اساس درخواست بررسی کن:
- اگه 'بهینه کن' بود، پرامپت رو ساده‌تر کن (هسته اصلی Role, Tone, Guidelines رو نگه دار)، اطلاعات اضافی (محصولات، قیمت‌ها، قوانین، ارسال) رو کامل و دقیق به پایگاه دانش منتقل کن، و سوالات پرتکرار رو با لحن پرامپت به FAQ ببر. رفتار ۱۰۰٪ مثل اولیه بمونه.
- اگه تغییر بود (مثل 'محصول اضافه کن')، فقط بخش‌های مرتبط رو اصلاح کن و بقیه رو دست‌نخورده نگه دار.
- همیشه پرامپت، پایگاه دانش، و FAQ کامل بده.
- همیشه نسخه کامل پرامپت، پایگاه دانش، و FAQ رو تولید کن.
"""
iteration_history += f"**دستورات DCE:** {dce_instructions}\n"
pee_prompt = f"""
{mother_prompt}
شما Prompt Engineering Expert (PEE) هستید:
اطلاعات کسب‌وکار: {json.dumps(business_info_serializable, ensure_ascii=False)}
اطلاعات محصولات: {json.dumps(product_info_serializable, ensure_ascii=False)}
پرامپت اولیه: {initial_prompt}
پرامپت فعلی: {prompt_output}
درخواست کاربر: {last_user_request}
تاریخچه: {iteration_history}
{dce_instructions}
- لحن پرامپت (مهربون، بازیگوش، با ایموجی) رو حفظ کن.
- محصولات، قیمت‌ها، و قوانین رو کامل به پایگاه دانش ببر.
- FAQ رو با سوالات کلیدی و جواب‌های کوتاه و کیوت بساز.
خروجی رو با --- جدا کن (پرامپت --- پایگاه دانش --- FAQ).
"""
pee_response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "system", "content": pee_prompt}]
)
pee_output = pee_response.choices[0].message.content
iteration_history += f"**خروجی PEE:**\n{pee_output}\n"
parts = validate_and_fix_output(pee_output, prompt_output)
prompt_output = parts[0]
knowledge_base_output = parts[1]
faq_output = parts[2]
cae_prompt = f"""
{mother_prompt}
شما Critical Analysis Expert (CAE) هستید:
خروجی PEE: {pee_output}
پرامپت اولیه: {initial_prompt}
درخواست کاربر: {last_user_request}
چک کن:
- آیا درخواست (بهینه‌سازی/تغییر) کامل اعمال شده؟
- آیا رفتار و لحن پرامپت اولیه (مثل استفاده از `get_recommendations`، کلمات کیوت، ایموجی) ۱۰۰٪ حفظ شده؟
- آیا همه اطلاعات (محصولات، قیمت‌ها، قوانین) به پایگاه دانش منتقل شدن؟
- اگه چیزی ناقصه، بگو چی کمه.
"""
cae_response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "system", "content": cae_prompt}]
)
iteration_history += f"**نقد CAE:**\n{cae_response.choices[0].message.content}\n"
dce_summary = f"""
**جمع‌بندی DCE:** iteration {iteration_count} تموم شد 😊
**وضعیت فعلی:** {('همه درخواست‌ها انجام شدن 🌟 اگه درخواست جدیدی نیست، "پایان" رو بزن تا خروجی نهایی رو ببینی.' if not last_user_request else 'درخواست‌ها انجام شدن، اگه چیز دیگه‌ای می‌خوای بگو!')}
**اهداف بعدی:**
#G-{iteration_count}-1: ادامه بر اساس درخواست جدید یا پایان.
**پایان iteration {iteration_count}**
"""
iteration_history += dce_summary
return (iteration_history, prompt_output, knowledge_base_output, faq_output, "", "", f"Iteration {iteration_count}",
gr.update(interactive=False), gr.update(interactive=True))
# تابع ادامه Iteration
def continue_iteration(_=None):
global iteration_count, iteration_history, prompt_output, knowledge_base_output, faq_output, last_user_request, initial_prompt, original_user_request
iteration_count += 1
business_info_serializable = convert_to_serializable(business_info)
product_info_serializable = convert_to_serializable(product_info)
if last_user_request:
iteration_history += f"**درخواست کاربر:** {last_user_request}\n"
else:
last_user_request = original_user_request if original_user_request else "بهینه کن" # پیش‌فرض بهینه‌سازی
dce_instructions = f"""
iteration {iteration_count}: پرامپت قبلی رو بر اساس درخواست کاربر بررسی کن:
- اگه 'بهینه کن' بود، پرامپت رو ساده‌تر کن (تکرارها رو حذف کن) و Informations اضافی (مثل آدرس، قیمت‌ها، جزئیات ارسال) رو به پایگاه دانش یا FAQ منتقل کن، ولی رفتار پرامپت ۱۰۰٪ مثل اولیه بمونه.
- اگه تغییر بود (مثل 'محصول اضافه کن')، فقط بخش‌های مرتبط رو اصلاح کن و بقیه رو بدون تغییر برگردون. بهینه‌سازی انجام نده.
- همیشه نسخه کامل پرامپت، پایگاه دانش، و FAQ رو تولید کن.
"""
iteration_history += f"**دستورات DCE:** {dce_instructions}\n"
pee_prompt = f"""
{mother_prompt}
شما Prompt Engineering Expert (PEE) هستید:
اطلاعات کسب‌وکار: {json.dumps(business_info_serializable, ensure_ascii=False)}
اطلاعات محصولات: {json.dumps(product_info_serializable, ensure_ascii=False)}
پرامپت اولیه: {initial_prompt}
پرامپت فعلی: {prompt_output}
درخواست کاربر: {last_user_request}
تاریخچه: {iteration_history}
{dce_instructions}
خروجی رو با --- جدا کن (پرامپت --- پایگاه دانش --- FAQ).
"""
pee_response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "system", "content": pee_prompt}]
)
pee_output = pee_response.choices[0].message.content
iteration_history += f"**خروجی PEE:**\n{pee_output}\n"
parts = validate_and_fix_output(pee_output, prompt_output)
prompt_output = parts[0]
knowledge_base_output = parts[1]
faq_output = parts[2]
cae_prompt = f"""
{mother_prompt}
شما Critical Analysis Expert (CAE) هستید:
خروجی PEE: {pee_output}
پرامپت اولیه: {initial_prompt}
چک کن رفتار پرامپت اولیه حفظ شده باشه و درخواست کاربر اعمال شده باشه.
"""
cae_response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "system", "content": cae_prompt}]
)
iteration_history += f"**نقد CAE:**\n{cae_response.choices[0].message.content}\n"
dce_summary = f"""
**جمع‌بندی DCE:** iteration {iteration_count} تموم شد 😊
**وضعیت فعلی:** {('همه درخواست‌ها انجام شدن 🌟 اگه درخواست جدیدی نیست، "پایان" رو بزن تا خروجی نهایی رو ببینی.' if not last_user_request else 'درخواست‌ها انجام شدن، اگه چیز دیگه‌ای می‌خوای بگو!')}
**اهداف بعدی:**
#G-{iteration_count}-1: ادامه یا پایان.
**پایان iteration {iteration_count}**
"""
iteration_history += dce_summary
return (iteration_history, prompt_output, knowledge_base_output, faq_output, "", "", iteration_count,
gr.update(interactive=False), gr.update(interactive=True))
# تابع پایان و تولید خروجی نهایی
def end_process(_=None):
global iteration_history, prompt_output, knowledge_base_output, faq_output, last_user_request, initial_prompt, original_user_request
business_info_serializable = convert_to_serializable(business_info)
product_info_serializable = convert_to_serializable(product_info)
if last_user_request:
iteration_history += f"**درخواست کاربر (فقط برای خروجی نهایی):** {last_user_request}\n"
else:
last_user_request = original_user_request
final_prompt = f"""
{mother_prompt}
فرایند iteration‌ها تموم شده. خروجی نهایی رو تولید کن:
1. پرامپت چت‌بات به انگلیسی (Persona, Tone, Guidelines, ...). از پرامپت اولیه کاربر به‌عنوان پایه استفاده کن.
- اگه درخواست 'بهینه کن' بوده، پرامپت رو ساده‌تر کن و اطلاعات اضافی رو به پایگاه دانش/FAQ منتقل کن، ولی رفتار ۱۰۰٪ مثل اولیه بمونه.
- اگه درخواست تغییر بوده، فقط بخش‌های مرتبط رو اصلاح کن.
2. پایگاه دانش به فرمت JSON-like (name, description, variants, objectID).
3. FAQ به فرمت JSON-like (دسته‌بندی‌ها، سوالات، جواب‌ها).
اطلاعات کسب‌وکار: {json.dumps(business_info_serializable, ensure_ascii=False)}
اطلاعات محصولات: {json.dumps(product_info_serializable, ensure_ascii=False)}
پرامپت اولیه: {initial_prompt}
درخواست کاربر: {last_user_request}
تاریخچه iteration‌ها: {iteration_history}
همیشه نسخه کامل هر سه بخش (پرامپت، پایگاه دانش، FAQ) رو تولید کن، هر بخش رو با --- جدا کن.
"""
final_response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "system", "content": final_prompt}]
)
final_output = final_response.choices[0].message.content
print("خروجی خام نهایی:", final_output)
parts = validate_and_fix_output(final_output, prompt_output)
prompt_output = parts[0]
knowledge_base_output = parts[1]
faq_output = parts[2]
iteration_history += "\n**فرایند تموم شد و خروجی نهایی آماده‌ست! 🎉**\n"
last_user_request = ""
return (iteration_history, prompt_output, knowledge_base_output, faq_output, "", "", "فرایند پایان یافت",
gr.update(interactive=True), gr.update(interactive=True))
# تابع ریست فرایند
def reset_process():
global iteration_count, iteration_history, prompt_output, knowledge_base_output, faq_output, business_info, product_info, last_user_request, initial_prompt, original_user_request
iteration_count = 0
iteration_history = ""
prompt_output = ""
knowledge_base_output = ""
faq_output = ""
business_info = None
product_info = None
last_user_request = ""
initial_prompt = ""
original_user_request = ""
return ("", "", "", "", "", "", "فرایند ریست شد! حالا می‌تونی دوباره شروع کنی 😊",
gr.update(interactive=True), gr.update(interactive=True))
# تابع ثبت درخواست کاربر
def submit_request(user_request):
global last_user_request, original_user_request
last_user_request = user_request.strip()
if not original_user_request: # اگه درخواست اولیه هنوز ثبت نشده
original_user_request = last_user_request
return "", "درخواستت ثبت شد! حالا 'ادامه دهید' رو بزن 😊"
# رابط کاربری Gradio
with gr.Blocks(title="سیستم نوا 🌟") as demo:
gr.Markdown("# سیستم نوا 🌟")
with gr.Row():
file1 = gr.File(label="فرم اطلاعات اولیه (اختیاری)")
file2 = gr.File(label="فرم محصولات/خدمات (اختیاری)")
with gr.Row():
user_prompt_box = gr.Textbox(label="پرامپت آماده شما (اختیاری)", lines=5, placeholder="پرامپت خودتون رو اینجا بذارید")
with gr.Row():
user_request_box = gr.Textbox(label="درخواست شما", placeholder="مثلاً: 'محصول اضافه کن' یا 'بهینه کن'")
submit_request_btn = gr.Button("ارسال درخواست")
status_box = gr.Textbox(label="وضعیت فعلی", value="فرایند شروع نشده", interactive=False)
iteration_box = gr.Textbox(label="تاریخچه Iteration", lines=10)
with gr.Row():
start_btn = gr.Button("شروع", interactive=True)
continue_btn = gr.Button("ادامه دهید")
end_btn = gr.Button("پایان")
reset_btn = gr.Button("ریست فرایند")
with gr.Tabs():
with gr.TabItem("پرامپت"):
prompt_box = gr.Textbox(label="پرامپت (انگلیسی)")
with gr.TabItem("پایگاه دانش"):
kb_box = gr.Textbox(label="پایگاه دانش (JSON)")
with gr.TabItem("پرسش و پاسخ"):
faq_box = gr.Textbox(label="پرسش و پاسخ (JSON)")
# اتصال توابع
start_btn.click(
start_process,
inputs=[file1, file2, user_request_box, user_prompt_box],
outputs=[iteration_box, prompt_box, kb_box, faq_box, user_request_box, user_prompt_box, status_box, start_btn, continue_btn]
)
continue_btn.click(
continue_iteration,
inputs=[],
outputs=[iteration_box, prompt_box, kb_box, faq_box, user_request_box, user_prompt_box, status_box, start_btn, continue_btn]
)
end_btn.click(
end_process,
inputs=[],
outputs=[iteration_box, prompt_box, kb_box, faq_box, user_request_box, user_prompt_box, status_box, start_btn, continue_btn]
)
reset_btn.click(
reset_process,
inputs=[],
outputs=[iteration_box, prompt_box, kb_box, faq_box, user_request_box, user_prompt_box, status_box, start_btn, continue_btn]
)
submit_request_btn.click(
submit_request,
inputs=[user_request_box],
outputs=[user_request_box, status_box]
)
demo.launch()