Spaces:
Sleeping
Sleeping
File size: 9,390 Bytes
70b4f5f 3785bb1 9bad5e5 d972edd 9bad5e5 70b4f5f d972edd 70b4f5f d972edd 70b4f5f d972edd 70b4f5f 3785bb1 9bad5e5 d972edd 9bad5e5 3785bb1 9bad5e5 3785bb1 70b4f5f e2f88c4 70b4f5f 3785bb1 70b4f5f 3785bb1 70b4f5f d972edd 70b4f5f d972edd 9bad5e5 70b4f5f 3785bb1 70b4f5f 3785bb1 70b4f5f d972edd 70b4f5f d972edd 70b4f5f 3785bb1 70b4f5f 3785bb1 70b4f5f d972edd 70b4f5f 9bad5e5 d972edd 70b4f5f d972edd 70b4f5f 3785bb1 d972edd 70b4f5f d972edd 70b4f5f 9bad5e5 d972edd 3785bb1 d972edd 9bad5e5 70b4f5f d972edd 70b4f5f d972edd 70b4f5f d972edd 70b4f5f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# این فایل server.py در Hugging Face Space شما قرار می گیرد
# این کد شامل:
# - بارگذاری مدل Sentence Transformer پارسی 'PartAI/Tooka-SBERT'
# - تعریف اپلیکیشن Flask
# - اندپوینت /get_embedding برای دریافت سوال و ارسال بردار آن
# - لاگ گیری برای عیب یابی در لاگ های Space و یک فایل جداگانه
# - مدیریت خطاهای اولیه در بارگذاری مدل و پردازش درخواست ها
# - **رفع خطای 'SentenceTransformer' object has no attribute 'args' با اصلاح لاگ بارگذاری مدل**
from sentence_transformers import SentenceTransformer
from flask import Flask, request, jsonify
import numpy as np
import logging
import os
# import torch # اگر از GPU استفاده می کنید و torch نصب کرده اید، این خط را فعال نگه دارید.
# تنظیمات اولیه لاگینگ برای نمایش در لاگ های استاندارد Space
# این لاگ ها معمولاً در تب "Container logs" دیده می شوند.
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# مسیر فایل لاگ جداگانه در فضای Hugging Face (برای عیب یابی بیشتر)
# نکته: نوشتن در فایل در برخی محیط های Space ممکن است نیاز به تنظیمات مجوز داشته باشد.
log_file_path = "app_log.txt"
# تابع برای افزودن پیام به فایل لاگ
def log_message(message):
try:
# حالت 'a' برای اضافه کردن به انتهای فایل است.
# مطمئن شوید که دایرکتوری برای فایل قابل نوشتن است.
# اگر خطا مجوز می گیرید، می توانید این تابع را موقتا غیرفعال کنید یا مسیر دیگری را امتحان کنید.
with open(log_file_path, "a", encoding="utf-8") as f:
f.write(message + "\n")
except Exception as e:
# اگر نوشتن در فایل لاگ هم با خطا مواجه شد، در لاگ استاندارد Space بنویسید.
# خطای [Errno 13] Permission denied در لاگ قبلی به همین دلیل بود.
logging.error(f"Error writing to log file {log_file_path}: {e}")
# ****** نام مدل Sentence Transformer که می خواهیم در این سرور استفاده کنیم ******
# این مدل باید همان مدلی باشد که برای بردارسازی خاطرات در فایل های JSON استفاده کرده اید.
model_name_to_load = 'sentence-transformers/all-MiniLM-L6-L2day'
# ***************************************************************************
# ****** بارگذاری مدل Sentence Transformer در هنگام راه اندازی سرور ******
logging.info(f"Attempting to load Sentence Transformer model: {model_name_to_load}...") # لاگ قبل از بارگذاری (در لاگ های استاندارد Space)
log_message(f"Attempting to load Sentence Transformer model: {model_name_to_load}...") # لاگ قبل از بارگذاری (در فایل لاگ)
try:
# بارگذاری مدل. اگر GPU دارید و torch نصب شده، می توانید device='cuda' را اضافه کنید.
# اگر خطایی در بارگذاری رخ دهد، Exception گرفته می شود.
# model = SentenceTransformer(model_name_to_load, device='cuda' if torch.cuda.is_available() else 'cpu')
model = SentenceTransformer(model_name_to_load) # بارگذاری با استفاده از CPU یا تنظیمات پیش فرض
# ****** افزودن لاگ تأیید پس از بارگذاری موفق مدل ******
# این پیام ها در لاگ های Space به شما نشان می دهند که مدل با موفقیت بارگذاری شده و نام آن چیست.
# ما نام مدلی که قصد بارگذاریش را داشتیم لاگ می کنیم تا از خطای Attribute Error جلوگیری شود.
logging.info(f"SUCCESS: Model '{model_name_to_load}' loaded successfully.") # لاگ موفقیت (در لاگ های استاندارد Space)
log_message(f"SUCCESS: Model '{model_name_to_load}' loaded successfully.") # لاگ موفقیت (در فایل لاگ)
# ******************************************************
except Exception as e:
# ****** مدیریت خطا در صورت عدم بارگذاری مدل ******
error_msg = f"ERROR: Failed to load model {model_name_to_load}: {e}"
logging.error(error_msg) # لاگ خطا (در لاگ های استاندارد Space)
log_message(error_msg) # لاگ خطا (در فایل لاگ)
# در صورتی که بارگذاری مدل با خطا مواجه شد، متغیر model را None قرار می دهیم
# تا در تابع get_embedding بتوانیم وضعیت خطا را چک کنیم.
model = None
# *************************************************
# تعریف اپلیکیشن Flask
app = Flask(__name__)
# تعریف اندپوینت اصلی برای تست سلامت سرور
@app.route('/')
def index():
# چک کردن وضعیت مدل قبل از پاسخ به درخواست اصلی
if model is None:
# اگر مدل بارگذاری نشده، پیام خطا نمایش داده می شود.
return "Sentiment Embedding Server is running, but model failed to load. Check Space logs for details.", 500
# اگر مدل با موفقیت بارگذاری شده، پیام موفقیت نمایش داده می شود.
# از نام مدلی که در متغیر ذخیره کردیم استفاده می کنیم.
return f"Sentiment Embedding Server is running successfully with model: {model_name_to_load}"
# تعریف اندپوینت برای دریافت بردار (embedding) سوال
@app.route('/get_embedding', methods=['POST'])
def get_embedding():
# قبل از پردازش درخواست، مطمئن شوید مدل بارگذاری شده است.
if model is None:
error_msg = "Model is not loaded on the server due to a previous error. Check Space logs."
# این خطا احتمالا قبلا در لاگ ها ثبت شده، اما برای اطمینان مجدد ثبت می کنیم.
# logging.error(error_msg) # لاگ تکراری در صورتیکه بالا هم خطا داده
log_message(f"Received request but model is not loaded: {error_msg}") # ثبت در فایل لاگ
return jsonify({"error": error_msg}), 500 # ارسال پاسخ خطا با کد 500
try:
# دریافت داده ها از درخواست POST (باید شامل فیلد 'query' باشد)
data = request.get_json()
query = data.get('query')
# چک کردن اینکه فیلد query خالی نباشد
if not query or not isinstance(query, str) or not query.strip():
log_message(f"Received invalid or empty query in /get_embedding: {data}")
return jsonify({"error": "Invalid or empty query text provided"}), 400 # ارسال پاسخ خطا با کد 400
log_message(f"Received query in /get_embedding: '{query}'")
logging.info(f"Processing query in /get_embedding: '{query[:50]}...'") # لاگ در کنسول Space برای درخواست های دریافتی
# تولید بردار (embedding) برای متن سوال با استفاده از مدل لود شده
embedding = model.encode(query, convert_to_numpy=True, pooling_mode='mean', normalize=True)
# تبدیل بردار numpy به لیست Python برای ارسال در پاسخ JSON
embedding_list = embedding.tolist()
log_message(f"Successfully generated embedding for query in /get_embedding.") # لاگ موفقیت در فایل
# logging.info(f"Embedding generated successfully for query.") # لاگ موفقیت در کنسول Space (اختیاری)
# ارسال بردار به عنوان پاسخ JSON
return jsonify({"embedding": embedding_list}), 200 # ارسال پاسخ موفقیت با کد 200
except Exception as e:
# مدیریت و ثبت هرگونه خطای دیگر در طول پردازش درخواست
error_message = f"An error occurred during embedding generation in /get_embedding: {e}"
logging.error(error_message) # لاگ خطا (در لاگ های استاندارد Space)
log_message(error_message) # لاگ خطا (در فایل لاگ)
return jsonify({"error": error_message}), 500 # ارسال پاسخ خطا با کد 500
# خط زیر فقط در صورتی که فایل server.py مستقیماً اجرا شود، سرور Flask را اجرا می کند.
# در Hugging Face Space، خود زیرساخت Space مسئول اجرای برنامه شماست و این بخش معمولاً غیرفعال است.
# if __name__ == '__main__':
# # Hugging Face Spaces از پورت 7860 استفاده می کند.
# # debug=True برای محیط توسعه مفید است اما در محیط پروداکشن توصیه نمی شود.
# app.run(host='0.0.0.0', port=7860, debug=False) |