Update app.py
Browse files
app.py
CHANGED
|
@@ -8,7 +8,7 @@ from datetime import datetime, timedelta
|
|
| 8 |
from concurrent.futures import ThreadPoolExecutor
|
| 9 |
from typing import Dict, List, Optional, Any
|
| 10 |
import json
|
| 11 |
-
|
| 12 |
from fastapi import FastAPI, HTTPException, BackgroundTasks
|
| 13 |
from fastapi.middleware.cors import CORSMiddleware
|
| 14 |
from fastapi.responses import JSONResponse
|
|
@@ -17,25 +17,11 @@ import torch
|
|
| 17 |
from transformers import M2M100ForConditionalGeneration, M2M100Tokenizer
|
| 18 |
import requests
|
| 19 |
|
| 20 |
-
|
| 21 |
-
os.environ['
|
| 22 |
-
|
| 23 |
-
# ایجاد مسیرهای کش
|
| 24 |
-
cache_paths = [
|
| 25 |
-
'/home/user/.cache',
|
| 26 |
-
'/home/user/.cache/huggingface',
|
| 27 |
-
'/home/user/.cache/huggingface/hub'
|
| 28 |
-
]
|
| 29 |
|
| 30 |
-
|
| 31 |
-
os.makedirs(path, exist_ok=True)
|
| 32 |
-
# تنظیم مجوزهای مناسب
|
| 33 |
-
try:
|
| 34 |
-
os.chmod(path, 0o755)
|
| 35 |
-
except:
|
| 36 |
-
pass
|
| 37 |
-
|
| 38 |
-
print(f"✅ مسیرهای کش تنظیم شد: {cache_paths}")
|
| 39 |
|
| 40 |
# تنظیمات اولیه
|
| 41 |
MODEL_NAME = "facebook/m2m100_418M"
|
|
@@ -311,23 +297,26 @@ class MultilingualTranslator:
|
|
| 311 |
print("در حال راهاندازی مترجم...")
|
| 312 |
|
| 313 |
try:
|
| 314 |
-
|
| 315 |
-
print("🚀 در حال بارگذاری سریع مدل...")
|
| 316 |
|
|
|
|
| 317 |
self.tokenizer = M2M100Tokenizer.from_pretrained(
|
| 318 |
MODEL_NAME,
|
| 319 |
-
use_fast=True,
|
| 320 |
-
|
|
|
|
| 321 |
)
|
| 322 |
|
| 323 |
self.model = M2M100ForConditionalGeneration.from_pretrained(
|
| 324 |
MODEL_NAME,
|
| 325 |
-
device_map="auto", # مدیریت خودکار دستگاه
|
| 326 |
-
|
| 327 |
-
low_cpu_mem_usage=True
|
|
|
|
|
|
|
| 328 |
)
|
| 329 |
|
| 330 |
-
# اگر device_map کار
|
| 331 |
if not hasattr(self.model, 'device'):
|
| 332 |
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 333 |
self.model.to(self.device)
|
|
@@ -336,34 +325,46 @@ class MultilingualTranslator:
|
|
| 336 |
|
| 337 |
self.model.eval()
|
| 338 |
|
| 339 |
-
print(f"✅ مدل روی {self.device} بارگذاری شد")
|
| 340 |
|
| 341 |
except Exception as e:
|
| 342 |
-
print(f"
|
| 343 |
-
print("🔧 استفاده از حالت fallback...")
|
| 344 |
|
| 345 |
-
#
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 355 |
|
| 356 |
-
#
|
| 357 |
self.cache = TranslationCache(cache_expiry_minutes)
|
| 358 |
self.chunker = TextChunker()
|
| 359 |
self.queue = TranslationQueue()
|
|
|
|
|
|
|
| 360 |
self.translation_sessions: Dict[str, Dict] = {}
|
| 361 |
self.completed_translations: Dict[str, Dict] = {}
|
| 362 |
self.translation_requests: Dict[str, Dict] = {}
|
|
|
|
|
|
|
| 363 |
self.total_requests = 0
|
| 364 |
self.lock = threading.Lock()
|
| 365 |
|
| 366 |
-
print("
|
| 367 |
|
| 368 |
def _normalize_language(self, lang: str) -> str:
|
| 369 |
"""تبدیل نام زبان به کد دوحرفی"""
|
|
|
|
| 8 |
from concurrent.futures import ThreadPoolExecutor
|
| 9 |
from typing import Dict, List, Optional, Any
|
| 10 |
import json
|
| 11 |
+
import tempfile
|
| 12 |
from fastapi import FastAPI, HTTPException, BackgroundTasks
|
| 13 |
from fastapi.middleware.cors import CORSMiddleware
|
| 14 |
from fastapi.responses import JSONResponse
|
|
|
|
| 17 |
from transformers import M2M100ForConditionalGeneration, M2M100Tokenizer
|
| 18 |
import requests
|
| 19 |
|
| 20 |
+
temp_cache_dir = tempfile.mkdtemp()
|
| 21 |
+
os.environ['HF_HOME'] = temp_cache_dir
|
| 22 |
+
os.environ['HUGGINGFACE_HUB_CACHE'] = os.path.join(temp_cache_dir, 'hub')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
+
print(f"✅ مسیر کش موقت ایجاد شد: {temp_cache_dir}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
|
| 26 |
# تنظیمات اولیه
|
| 27 |
MODEL_NAME = "facebook/m2m100_418M"
|
|
|
|
| 297 |
print("در حال راهاندازی مترجم...")
|
| 298 |
|
| 299 |
try:
|
| 300 |
+
print("🚀 در حال بارگذاری مدل M2M100...")
|
|
|
|
| 301 |
|
| 302 |
+
# روش 1: استفاده از device_map="auto" برای مدیریت خودکار حافظه
|
| 303 |
self.tokenizer = M2M100Tokenizer.from_pretrained(
|
| 304 |
MODEL_NAME,
|
| 305 |
+
use_fast=True,
|
| 306 |
+
cache_dir=None, # عدم استفاده از کش دائمی
|
| 307 |
+
local_files_only=False
|
| 308 |
)
|
| 309 |
|
| 310 |
self.model = M2M100ForConditionalGeneration.from_pretrained(
|
| 311 |
MODEL_NAME,
|
| 312 |
+
device_map="auto", # مدیریت خودکار دستگاه و حافظه
|
| 313 |
+
torch_dtype=torch.float16, # استفاده از float16 برای صرفهجویی در حافظه
|
| 314 |
+
low_cpu_mem_usage=True,
|
| 315 |
+
cache_dir=None,
|
| 316 |
+
local_files_only=False
|
| 317 |
)
|
| 318 |
|
| 319 |
+
# اگر device_map کار نکند، از روش سنتی استفاده میکنیم
|
| 320 |
if not hasattr(self.model, 'device'):
|
| 321 |
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 322 |
self.model.to(self.device)
|
|
|
|
| 325 |
|
| 326 |
self.model.eval()
|
| 327 |
|
| 328 |
+
print(f"✅ مدل با موفقیت روی {self.device} بارگذاری شد")
|
| 329 |
|
| 330 |
except Exception as e:
|
| 331 |
+
print(f"❌ خطا در بارگذاری مدل: {str(e)}")
|
|
|
|
| 332 |
|
| 333 |
+
# روش جایگزین: استفاده از pipeline
|
| 334 |
+
try:
|
| 335 |
+
print("🔄 استفاده از pipeline به عنوان راهحل جایگزین...")
|
| 336 |
+
from transformers import pipeline
|
| 337 |
+
|
| 338 |
+
self.translation_pipeline = pipeline(
|
| 339 |
+
"translation",
|
| 340 |
+
model=MODEL_NAME,
|
| 341 |
+
tokenizer=MODEL_NAME,
|
| 342 |
+
device=0 if torch.cuda.is_available() else -1,
|
| 343 |
+
torch_dtype=torch.float16
|
| 344 |
+
)
|
| 345 |
+
self.use_pipeline = True
|
| 346 |
+
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 347 |
+
print("✅ pipeline ترجمه با موفقیت ایجاد شد")
|
| 348 |
+
|
| 349 |
+
except Exception as e2:
|
| 350 |
+
print(f"❌ خطا در ایجاد pipeline: {str(e2)}")
|
| 351 |
+
raise RuntimeError("امکان بارگذاری مدل ترجمه وجود ندارد")
|
| 352 |
|
| 353 |
+
# اجزای کمکی
|
| 354 |
self.cache = TranslationCache(cache_expiry_minutes)
|
| 355 |
self.chunker = TextChunker()
|
| 356 |
self.queue = TranslationQueue()
|
| 357 |
+
|
| 358 |
+
# ذخیره وضعیت ترجمهها
|
| 359 |
self.translation_sessions: Dict[str, Dict] = {}
|
| 360 |
self.completed_translations: Dict[str, Dict] = {}
|
| 361 |
self.translation_requests: Dict[str, Dict] = {}
|
| 362 |
+
|
| 363 |
+
# آمار
|
| 364 |
self.total_requests = 0
|
| 365 |
self.lock = threading.Lock()
|
| 366 |
|
| 367 |
+
print("🎉 مترجم با موفقیت راهاندازی شد!")
|
| 368 |
|
| 369 |
def _normalize_language(self, lang: str) -> str:
|
| 370 |
"""تبدیل نام زبان به کد دوحرفی"""
|