| import subprocess |
| import sys |
| import os |
| import json |
|
|
| |
| PROJECT_DIR = os.path.dirname(os.path.abspath(__file__)) |
| MODEL_DIR = os.path.join(PROJECT_DIR, "rayzh_model") |
| DATA_DIR = os.path.join(PROJECT_DIR, "data") |
| API_PORT = 5000 |
| GRADIO_PORT = 7860 |
|
|
| |
| |
| |
| |
| DEPENDENCIES = [ |
| "transformers", |
| "datasets", |
| "torch", |
| "tensorboard", |
| "accelerate", |
| "evaluate", |
| "pandas", |
| "flask", |
| "gradio", |
| "sentencepiece", |
| "protobuf" |
| ] |
|
|
| |
|
|
| def run_command(command, cwd=None, env=None): |
| """ |
| یک دستور را اجرا می کند و خروجی آن را نمایش می دهد. |
| """ |
| print(f"Executing command: {' '.join(command)}") |
| try: |
| process = subprocess.Popen( |
| command, |
| stdout=subprocess.PIPE, |
| stderr=subprocess.STDOUT, |
| text=True, |
| cwd=cwd, |
| env=env |
| ) |
| for line in process.stdout: |
| print(line, end='') |
| process.wait() |
| if process.returncode != 0: |
| print(f"Error executing command: {' '.join(command)}") |
| return False |
| return True |
| except FileNotFoundError: |
| print(f"Error: Command '{command[0]}' not found. Is it installed and in your PATH?") |
| return False |
| except Exception as e: |
| print(f"An error occurred: {e}") |
| return False |
|
|
| def install_dependencies(): |
| """ |
| وابستگی های لازم را نصب می کند. |
| """ |
| print("--- نصب وابستگی ها ---") |
| for dep in DEPENDENCIES: |
| if not run_command([sys.executable, "-m", "pip", "install", dep]): |
| print(f"Failed to install {dep}. Please check your internet connection and pip setup.") |
| return False |
| print("--- وابستگی ها با موفقیت نصب شدند ---") |
| return True |
|
|
| def create_dummy_data(): |
| """ |
| اگر داده های آموزشی وجود نداشته باشند، داده های نمونه ایجاد می کند. |
| در سناریوی واقعی، شما باید داده های واقعی خود را اینجا قرار دهید یا دانلود کنید. |
| """ |
| os.makedirs(DATA_DIR, exist_ok=True) |
| dummy_csv_path = os.path.join(DATA_DIR, "sentiment_data.csv") |
| if not os.path.exists(dummy_csv_path): |
| print("Creating dummy sentiment data...") |
| data = { |
| "text": [ |
| "چه روز خوبی بود! خیلی خوشحالم. 😊", |
| "امروز خیلی ناراحتم و خسته ام. 😞", |
| "هوا امروز عالیه!", |
| "This is a fantastic product! I love it. 👍", |
| "I am very disappointed with the service. 😠", |
| "How are you doing today?", |
| "سلام، خوبی؟", |
| "صبح بخیر!", |
| "Good morning!", |
| "I'm not sure how to feel about this.", |
| "کارم راه افتاد! ممنون. 🙏", |
| "واقعا؟ باورم نمیشه! 🤯", |
| "I can't believe this happened. 😥" |
| ], |
| "label": [ |
| 1, |
| 0, |
| 1, |
| 1, |
| 0, |
| 2, |
| 2, |
| 2, |
| 2, |
| 0, |
| 1, |
| 1, |
| 0 |
| ] |
| } |
| import pandas as pd |
| df = pd.DataFrame(data) |
| df.to_csv(dummy_csv_path, index=False) |
| print(f"Dummy data created at: {dummy_csv_path}") |
| else: |
| print("Sentiment data already exists.") |
|
|
| def train_model(): |
| """ |
| مدل را فاینتیون می کند. |
| این بخش ساده شده است و فرض می کند داده های لازم وجود دارند. |
| در واقعیت، این بخش می تواند بسیار پیچیده تر باشد. |
| """ |
| print("--- شروع آموزش مدل ---") |
| os.makedirs(MODEL_DIR, exist_ok=True) |
|
|
| |
| |
| train_script_content = f""" |
| import os |
| import pandas as pd |
| from datasets import Dataset |
| from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments |
| import numpy as np |
| import evaluate |
| import torch |
| |
| # --- تنظیمات --- |
| MODEL_NAME = "bert-base-multilingual-cased" # مدل پایه چند زبانه |
| NUM_LABELS = 3 # 0: منفی, 1: مثبت, 2: خنثی/احوالپرسی |
| TRAIN_DATA_PATH = os.path.join("{DATA_DIR}", "sentiment_data.csv") |
| OUTPUT_MODEL_PATH = "{MODEL_DIR}" |
| LOGGING_DIR = os.path.join("{PROJECT_DIR}", "logs") |
| |
| # --- بارگذاری داده ها --- |
| print("Loading data from:", TRAIN_DATA_PATH) |
| df = pd.read_csv(TRAIN_DATA_PATH) |
| dataset = Dataset.from_pandas(df) |
| |
| # تقسیم به مجموعه آموزش و تست |
| dataset = dataset.train_test_split(test_size=0.2, seed=42) |
| train_dataset = dataset['train'] |
| eval_dataset = dataset['test'] |
| |
| # --- توکنایزر و مدل --- |
| print("Loading tokenizer and model...") |
| tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME) |
| model = AutoModelForSequenceClassification.from_pretrained(MODEL_NAME, num_labels=NUM_LABELS) |
| |
| # تابع توکنایز کردن |
| def tokenize_function(examples): |
| return tokenizer(examples["text"], padding="max_length", truncation=True, max_length=128) |
| |
| print("Tokenizing datasets...") |
| tokenized_train_dataset = train_dataset.map(tokenize_function, batched=True) |
| tokenized_eval_dataset = eval_dataset.map(tokenize_function, batched=True) |
| |
| # حذف ستون های غیر ضروری و تغییر نام ها |
| tokenized_train_dataset = tokenized_train_dataset.remove_columns(["text"]) |
| tokenized_eval_dataset = tokenized_eval_dataset.remove_columns(["text"]) |
| tokenized_train_dataset = tokenized_train_dataset.rename_column("label", "labels") |
| tokenized_eval_dataset = tokenized_eval_dataset.rename_column("label", "labels") |
| |
| # تنظیم فرمت دیتاست برای PyTorch |
| tokenized_train_dataset.set_format("torch") |
| tokenized_eval_dataset.set_format("torch") |
| |
| # --- معیارهای ارزیابی --- |
| metric = evaluate.load("accuracy") # می توانید precision, recall, f1 را هم اضافه کنید |
| |
| def compute_metrics(eval_pred): |
| logits, labels = eval_pred |
| predictions = np.argmax(logits, axis=-1) |
| return metric.compute(predictions=predictions, references=labels) |
| |
| # --- پارامترهای آموزش --- |
| training_args = TrainingArguments( |
| output_dir=LOGGING_DIR, # لاگ ها اینجا ذخیره می شوند |
| evaluation_strategy="epoch", |
| learning_rate=2e-5, |
| per_device_train_batch_size=4, # کاهش سایز بچ برای حافظه کمتر |
| per_device_eval_batch_size=4, |
| num_train_epochs=3, |
| weight_decay=0.01, |
| save_strategy="epoch", |
| load_best_model_at_end=True, |
| metric_for_best_model="accuracy", |
| push_to_hub=False, # مستقیم آپلود نمی کنیم |
| report_to="tensorboard" # فعال کردن TensorBoard |
| ) |
| |
| # --- ساخت Trainer --- |
| print("Initializing Trainer...") |
| trainer = Trainer( |
| model=model, |
| args=training_args, |
| train_dataset=tokenized_train_dataset, |
| eval_dataset=tokenized_eval_dataset, |
| compute_metrics=compute_metrics, |
| tokenizer=tokenizer, |
| ) |
| |
| # --- شروع آموزش --- |
| print("Starting training...") |
| trainer.train() |
| |
| # --- ذخیره مدل نهایی --- |
| print(f"Saving final model to {OUTPUT_MODEL_PATH}...") |
| trainer.save_model(OUTPUT_MODEL_PATH) |
| tokenizer.save_pretrained(OUTPUT_MODEL_PATH) |
| print("Model training and saving complete.") |
| """ |
| |
| train_script_path = os.path.join(PROJECT_DIR, "train_script.py") |
| with open(train_script_path, "w", encoding="utf-8") as f: |
| f.write(train_script_content) |
|
|
| |
| if not run_command([sys.executable, train_script_path]): |
| print("Model training failed.") |
| return False |
|
|
| |
| os.remove(train_script_path) |
| print("--- آموزش مدل با موفقیت انجام شد ---") |
| return True |
|
|
| def start_api(): |
| """ |
| یک API ساده با Flask راهاندازی می کند. |
| """ |
| print(f"--- شروع API در پورت {API_PORT} ---") |
| |
| api_script_content = f""" |
| import os |
| from flask import Flask, request, jsonify |
| from transformers import pipeline |
| import torch |
| |
| # --- تنظیمات --- |
| MODEL_PATH = "{MODEL_DIR}" |
| # NUM_LABELS = 3 # اگر نیاز به تنظیم دقیق تر باشد |
| |
| # --- بررسی وجود مدل --- |
| if not os.path.exists(MODEL_PATH): |
| print(f"Error: Model not found at {{MODEL_PATH}}. Please train the model first.") |
| exit(1) |
| |
| # --- بارگذاری مدل --- |
| print(f"Loading model from {{MODEL_PATH}}...") |
| try: |
| # تعیین دستگاه (CPU یا GPU) |
| device = 0 if torch.cuda.is_available() else -1 |
| print(f"Using device: {{'cuda' if device == 0 else 'cpu'}}") |
| |
| sentiment_analyzer = pipeline( |
| "sentiment-analysis", |
| model=MODEL_PATH, |
| tokenizer=MODEL_PATH, |
| device=device # استفاده از GPU در صورت امکان |
| ) |
| print("Model loaded successfully.") |
| |
| # --- تابع تحلیل --- |
| def analyze_text_sentiment(text): |
| if not text: |
| return { |
| "error": "Input text is required.", |
| "input_text": text, |
| "sentiment": None, |
| "sentiment_score": None |
| } |
| try: |
| # اگر مدل شما NUM_LABELS=3 باشد، ممکن است خروجی متفاوت باشد |
| # مثلا {'label': 'LABEL_1', 'score': 0.99} |
| # ما باید آن را به 'positive', 'negative', 'neutral' تبدیل کنیم |
| result = sentiment_analyzer(text)[0] |
| label = result['label'].lower() |
| if 'positive' in label or label.endswith('_1'): # فرض بر این است که 1 مثبت است |
| sentiment = "positive" |
| elif 'negative' in label or label.endswith('_0'): # فرض بر این است که 0 منفی است |
| sentiment = "negative" |
| else: # فرض بر این است که 2 یا چیز دیگر خنثی است |
| sentiment = "neutral" |
| |
| return { |
| "input_text": text, |
| "sentiment": sentiment, |
| "sentiment_score": round(result['score'], 4) |
| } |
| except Exception as e: |
| print(f"Error during sentiment analysis: {{e}}") |
| return { |
| "error": f"An error occurred during analysis: {{e}}", |
| "input_text": text, |
| "sentiment": None, |
| "sentiment_score": None |
| } |
| |
| # --- Flask App --- |
| app = Flask(__name__) |
| |
| @app.route('/analyze', methods=['POST']) |
| def analyze_endpoint(): |
| data = request.get_json() |
| text = data.get('text') |
| result = analyze_text_sentiment(text) |
| return jsonify(result) |
| |
| @app.route('/', methods=['GET']) |
| def health_check(): |
| return jsonify({"status": "API is running", "model_loaded": True}) |
| |
| # --- اجرای App --- |
| if __name__ == '__main__': |
| print(f"Starting Flask API on port {API_PORT}...") |
| # برای production از gunicorn یا uwsgi استفاده کنید |
| app.run(host='0.0.0.0', port=API_PORT, debug=False) # debug=False برای production |
| |
| except Exception as e: |
| print(f"Error loading model or setting up API: {{e}}") |
| exit(1) |
| """ |
| api_script_path = os.path.join(PROJECT_DIR, "api_server.py") |
| with open(api_script_path, "w", encoding="utf-8") as f: |
| f.write(api_script_content) |
|
|
| print("API server script created.") |
| |
| |
| |
| |
| |
| print(f"\n--- برای اجرای API: ---") |
| print(f"1. فایل '{os.path.basename(api_script_path)}' در همین پوشه ایجاد شده است.") |
| print(f"2. ترمینال جدیدی باز کنید و به پوشه پروژه بروید.") |
| print(f"3. دستور زیر را اجرا کنید: python {os.path.basename(api_script_path)}") |
| print(f"API در پورت {API_PORT} در دسترس خواهد بود.") |
| print("----------------------\n") |
| return True |
|
|
| def start_gradio_interface(): |
| """ |
| یک رابط کاربری ساده با Gradio راهاندازی می کند. |
| """ |
| print(f"--- راه اندازی رابط کاربری Gradio در پورت {GRADIO_PORT} ---") |
| os.makedirs(MODEL_DIR, exist_ok=True) |
| if not os.path.exists(os.path.join(MODEL_DIR, "config.json")): |
| print(f"Error: Model directory '{MODEL_DIR}' is empty or does not contain a trained model.") |
| print("Please train the model first.") |
| return False |
|
|
| gradio_script_content = f""" |
| import gradio as gr |
| from transformers import pipeline |
| import os |
| import torch |
| |
| # --- تنظیمات --- |
| MODEL_PATH = "{MODEL_DIR}" |
| # NUM_LABELS = 3 # اگر نیاز به تنظیم دقیق تر باشد |
| |
| # --- بارگذاری مدل --- |
| print(f"Loading model from {{MODEL_PATH}} for Gradio interface...") |
| try: |
| # تعیین دستگاه (CPU یا GPU) |
| device = 0 if torch.cuda.is_available() else -1 |
| print(f"Gradio using device: {{'cuda' if device == 0 else 'cpu'}}") |
| |
| sentiment_analyzer = pipeline( |
| "sentiment-analysis", |
| model=MODEL_PATH, |
| tokenizer=MODEL_PATH, |
| device=device |
| ) |
| print("Model loaded successfully for Gradio.") |
| |
| # --- تابع تحلیل --- |
| def analyze_text_for_gradio(text): |
| if not text: |
| return "لطفا متنی وارد کنید." |
| try: |
| result = sentiment_analyzer(text)[0] |
| label = result['label'].lower() |
| if 'positive' in label or label.endswith('_1'): |
| sentiment = "مثبت" |
| elif 'negative' in label or label.endswith('_0'): |
| sentiment = "منفی" |
| else: |
| sentiment = "خنثی" |
| |
| return f"احساس تشخیص داده شده: **{{sentiment}}** (امتیاز: {{round(result['score'], 4)}})" |
| except Exception as e: |
| print(f"Error during Gradio analysis: {{e}}") |
| return f"خطایی رخ داد: {{e}}" |
| |
| # --- رابط کاربری Gradio --- |
| interface = gr.Interface( |
| fn=analyze_text_for_gradio, |
| inputs=gr.Textbox(lines=3, placeholder="متن فارسی یا انگلیسی خود را اینجا وارد کنید...", label="متن ورودی"), |
| outputs=gr.Textbox(label="نتیجه تحلیل"), |
| title="مدل هوش مصنوعی رایژ (Rayzh)", |
| description="این مدل احساسات (مثبت، منفی، خنثی) متن شما را به زبان فارسی و انگلیسی تشخیص می دهد.", |
| allow_flagging="never" |
| ) |
| |
| # --- اجرای App --- |
| if __name__ == '__main__': |
| print(f"Starting Gradio interface on port {GRADIO_PORT}...") |
| # share=True باعث می شود یک لینک عمومی برای تست ایجاد شود (مناسب برای دمو) |
| interface.launch(server_port=GRADIO_PORT, share=False) |
| |
| except Exception as e: |
| print(f"Error loading model or setting up Gradio interface: {{e}}") |
| exit(1) |
| """ |
| gradio_script_path = os.path.join(PROJECT_DIR, "gradio_app.py") |
| with open(gradio_script_path, "w", encoding="utf-8") as f: |
| f.write(gradio_script_content) |
|
|
| print("Gradio interface script created.") |
| print(f"\n--- برای اجرای رابط کاربری Gradio: ---") |
| print(f"1. فایل '{os.path.basename(gradio_script_path)}' در همین پوشه ایجاد شده است.") |
| print(f"2. ترمینال جدیدی باز کنید و به پوشه پروژه بروید.") |
| print(f"3. دستور زیر را اجرا کنید: python {os.path.basename(gradio_script_path)}") |
| print(f"رابط کاربری Gradio در پورت {GRADIO_PORT} در دسترس خواهد بود.") |
| print("---------------------------------------\n") |
| return True |
|
|
|
|
| def main(): |
| """ |
| تابع اصلی برای اجرای مراحل پروژه. |
| """ |
| print("--- شروع فرآیند ساخت مدل رایژ ---") |
|
|
| |
| if not install_dependencies(): |
| print("Could not install all dependencies. Exiting.") |
| return |
|
|
| |
| create_dummy_data() |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| print("\n--- مرحله 1: آموزش مدل ---") |
| if not train_model(): |
| print("Model training failed. Cannot proceed to API/Interface.") |
| return |
| print("--- مرحله 1: آموزش مدل تکمیل شد ---") |
|
|
| |
| print("\n--- مرحله 2: آماده سازی اسکریپت API ---") |
| if not start_api(): |
| print("Failed to prepare API script.") |
| |
| print("--- مرحله 2: آماده سازی اسکریپت API تکمیل شد ---") |
|
|
| |
| print("\n--- مرحله 3: آماده سازی اسکریپت رابط کاربری Gradio ---") |
| if not start_gradio_interface(): |
| print("Failed to prepare Gradio interface script.") |
| print("--- مرحله 3: آماده سازی اسکریپت رابط کاربری Gradio تکمیل شد ---") |
|
|
| print("\n--- فرآیند ساخت مدل رایژ به پایان رسید ---") |
| print("اکنون می توانید اسکریپت های API و Gradio را در ترمینال های جداگانه اجرا کنید.") |
| print(f"برای API: python {os.path.basename(os.path.join(PROJECT_DIR, 'api_server.py'))}") |
| print(f"برای Gradio: python {os.path.basename(os.path.join(PROJECT_DIR, 'gradio_app.py'))}") |
| print("----------------------------------------------") |
|
|
| if __name__ == "__main__": |
| |
| |
| |
| |
| |
|
|
| import argparse |
| parser = argparse.ArgumentParser(description="Rayzh AI Model Setup and Run Script") |
| parser.add_argument("--mode", type=str, default="all", choices=["install", "data", "train", "api", "gradio", "all"], |
| help="Mode to run: install, data, train, api, gradio, or all.") |
| args = parser.parse_args() |
|
|
| if args.mode == "install" or args.mode == "all": |
| if not install_dependencies(): |
| sys.exit(1) |
| if args.mode == "data" or args.mode == "all": |
| create_dummy_data() |
| if args.mode == "train" or args.mode == "all": |
| if not train_model(): |
| sys.exit(1) |
| if args.mode == "api" or args.mode == "all": |
| if not start_api(): |
| sys.exit(1) |
| if args.mode == "gradio" or args.mode == "all": |
| if not start_gradio_interface(): |
| sys.exit(1) |
|
|
| if args.mode == "all": |
| |
| |
| pass |
| elif args.mode != "install" and args.mode != "data" and args.mode != "train" and args.mode != "api" and args.mode != "gradio": |
| print(f"Unknown mode: {args.mode}") |
| sys.exit(1) |
|
|
| print("Script finished.") |
|
|