|
|
|
|
|
"""
|
|
|
Advanced Model Manager
|
|
|
مدیریت پیشرفته مدلهای AI با قابلیت filtering، ranking، و recommendation
|
|
|
"""
|
|
|
|
|
|
from typing import Dict, List, Optional, Any, Tuple
|
|
|
from dataclasses import dataclass, asdict
|
|
|
from enum import Enum
|
|
|
import json
|
|
|
import logging
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
class ModelCategory(Enum):
|
|
|
"""دستهبندی مدلها"""
|
|
|
SENTIMENT = "sentiment"
|
|
|
GENERATION = "generation"
|
|
|
TRADING = "trading"
|
|
|
SUMMARIZATION = "summarization"
|
|
|
NER = "ner"
|
|
|
QA = "question_answering"
|
|
|
CLASSIFICATION = "classification"
|
|
|
EMBEDDING = "embedding"
|
|
|
TRANSLATION = "translation"
|
|
|
PRICE_PREDICTION = "price_prediction"
|
|
|
|
|
|
|
|
|
class ModelSize(Enum):
|
|
|
"""اندازه مدلها"""
|
|
|
TINY = "tiny"
|
|
|
SMALL = "small"
|
|
|
MEDIUM = "medium"
|
|
|
LARGE = "large"
|
|
|
XLARGE = "xlarge"
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
class ModelInfo:
|
|
|
"""اطلاعات کامل یک مدل AI"""
|
|
|
id: str
|
|
|
hf_id: str
|
|
|
name: str
|
|
|
category: str
|
|
|
size: str
|
|
|
size_mb: int
|
|
|
description: str
|
|
|
use_cases: List[str]
|
|
|
languages: List[str]
|
|
|
free: bool
|
|
|
requires_auth: bool
|
|
|
performance_score: float
|
|
|
popularity_score: float
|
|
|
tags: List[str]
|
|
|
api_compatible: bool = True
|
|
|
downloadable: bool = True
|
|
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
|
"""تبدیل به dict"""
|
|
|
return asdict(self)
|
|
|
|
|
|
|
|
|
class AdvancedModelManager:
|
|
|
"""
|
|
|
مدیر پیشرفته مدلهای AI
|
|
|
|
|
|
قابلیتها:
|
|
|
- Filtering بر اساس category, size, language
|
|
|
- Ranking بر اساس performance
|
|
|
- Recommendation بر اساس use case
|
|
|
- Search در تمام فیلدها
|
|
|
- Stats و Analytics
|
|
|
"""
|
|
|
|
|
|
def __init__(self):
|
|
|
self.models = self._load_model_catalog()
|
|
|
logger.info(f"Loaded {len(self.models)} models into catalog")
|
|
|
|
|
|
def _load_model_catalog(self) -> Dict[str, ModelInfo]:
|
|
|
"""بارگذاری کاتالوگ کامل مدلها"""
|
|
|
return {
|
|
|
|
|
|
|
|
|
"cryptobert": ModelInfo(
|
|
|
id="cryptobert",
|
|
|
hf_id="kk08/CryptoBERT",
|
|
|
name="CryptoBERT",
|
|
|
category=ModelCategory.SENTIMENT.value,
|
|
|
size=ModelSize.SMALL.value,
|
|
|
size_mb=420,
|
|
|
description="Binary sentiment analysis optimized for crypto texts",
|
|
|
use_cases=["social_media", "news", "tweets", "reddit"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.85,
|
|
|
popularity_score=0.90,
|
|
|
tags=["crypto", "sentiment", "bert", "binary"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"elkulako_cryptobert": ModelInfo(
|
|
|
id="elkulako_cryptobert",
|
|
|
hf_id="ElKulako/cryptobert",
|
|
|
name="ElKulako CryptoBERT",
|
|
|
category=ModelCategory.SENTIMENT.value,
|
|
|
size=ModelSize.SMALL.value,
|
|
|
size_mb=450,
|
|
|
description="3-class crypto sentiment (bullish/neutral/bearish)",
|
|
|
use_cases=["twitter", "reddit", "social", "forums"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=True,
|
|
|
performance_score=0.88,
|
|
|
popularity_score=0.85,
|
|
|
tags=["crypto", "social", "sentiment", "3-class"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"finbert": ModelInfo(
|
|
|
id="finbert",
|
|
|
hf_id="ProsusAI/finbert",
|
|
|
name="FinBERT",
|
|
|
category=ModelCategory.SENTIMENT.value,
|
|
|
size=ModelSize.SMALL.value,
|
|
|
size_mb=440,
|
|
|
description="Financial sentiment analysis (positive/negative/neutral)",
|
|
|
use_cases=["news", "articles", "reports", "earnings"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.90,
|
|
|
popularity_score=0.95,
|
|
|
tags=["finance", "sentiment", "bert", "financial"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"finbert_tone": ModelInfo(
|
|
|
id="finbert_tone",
|
|
|
hf_id="yiyanghkust/finbert-tone",
|
|
|
name="FinBERT Tone",
|
|
|
category=ModelCategory.SENTIMENT.value,
|
|
|
size=ModelSize.SMALL.value,
|
|
|
size_mb=440,
|
|
|
description="Financial tone analysis for earnings calls and reports",
|
|
|
use_cases=["earnings_calls", "reports", "financial_documents"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.87,
|
|
|
popularity_score=0.80,
|
|
|
tags=["finance", "tone", "bert"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"distilroberta_financial": ModelInfo(
|
|
|
id="distilroberta_financial",
|
|
|
hf_id="mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis",
|
|
|
name="DistilRoBERTa Financial",
|
|
|
category=ModelCategory.SENTIMENT.value,
|
|
|
size=ModelSize.SMALL.value,
|
|
|
size_mb=330,
|
|
|
description="Fast financial sentiment analysis with DistilRoBERTa",
|
|
|
use_cases=["news", "real_time", "streaming"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.83,
|
|
|
popularity_score=0.75,
|
|
|
tags=["finance", "sentiment", "distil", "fast"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"fintwit_bert": ModelInfo(
|
|
|
id="fintwit_bert",
|
|
|
hf_id="StephanAkkerman/FinTwitBERT-sentiment",
|
|
|
name="FinTwitBERT",
|
|
|
category=ModelCategory.SENTIMENT.value,
|
|
|
size=ModelSize.SMALL.value,
|
|
|
size_mb=440,
|
|
|
description="Financial Twitter sentiment analysis",
|
|
|
use_cases=["twitter", "social", "fintwit"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.86,
|
|
|
popularity_score=0.82,
|
|
|
tags=["finance", "twitter", "sentiment"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"twitter_roberta": ModelInfo(
|
|
|
id="twitter_roberta",
|
|
|
hf_id="cardiffnlp/twitter-roberta-base-sentiment-latest",
|
|
|
name="Twitter RoBERTa",
|
|
|
category=ModelCategory.SENTIMENT.value,
|
|
|
size=ModelSize.MEDIUM.value,
|
|
|
size_mb=500,
|
|
|
description="State-of-the-art Twitter sentiment analysis",
|
|
|
use_cases=["twitter", "social_media", "tweets"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.89,
|
|
|
popularity_score=0.92,
|
|
|
tags=["twitter", "sentiment", "roberta", "social"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"xlm_roberta_sentiment": ModelInfo(
|
|
|
id="xlm_roberta_sentiment",
|
|
|
hf_id="cardiffnlp/twitter-xlm-roberta-base-sentiment",
|
|
|
name="XLM-RoBERTa Sentiment",
|
|
|
category=ModelCategory.SENTIMENT.value,
|
|
|
size=ModelSize.MEDIUM.value,
|
|
|
size_mb=1100,
|
|
|
description="Multilingual sentiment (100+ languages)",
|
|
|
use_cases=["global", "multilingual", "international"],
|
|
|
languages=["multi"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.87,
|
|
|
popularity_score=0.88,
|
|
|
tags=["multilingual", "sentiment", "roberta", "global"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"bertweet_sentiment": ModelInfo(
|
|
|
id="bertweet_sentiment",
|
|
|
hf_id="finiteautomata/bertweet-base-sentiment-analysis",
|
|
|
name="BERTweet Sentiment",
|
|
|
category=ModelCategory.SENTIMENT.value,
|
|
|
size=ModelSize.MEDIUM.value,
|
|
|
size_mb=540,
|
|
|
description="BERT trained specifically on tweets",
|
|
|
use_cases=["twitter", "social", "monitoring"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.85,
|
|
|
popularity_score=0.80,
|
|
|
tags=["twitter", "bert", "sentiment"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"crypto_news_bert": ModelInfo(
|
|
|
id="crypto_news_bert",
|
|
|
hf_id="mathugo/crypto_news_bert",
|
|
|
name="Crypto News BERT",
|
|
|
category=ModelCategory.SENTIMENT.value,
|
|
|
size=ModelSize.SMALL.value,
|
|
|
size_mb=420,
|
|
|
description="BERT fine-tuned on crypto news articles",
|
|
|
use_cases=["news", "articles", "crypto_media"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.84,
|
|
|
popularity_score=0.70,
|
|
|
tags=["crypto", "news", "bert"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
"crypto_gpt_o3": ModelInfo(
|
|
|
id="crypto_gpt_o3",
|
|
|
hf_id="OpenC/crypto-gpt-o3-mini",
|
|
|
name="Crypto GPT-O3 Mini",
|
|
|
category=ModelCategory.GENERATION.value,
|
|
|
size=ModelSize.MEDIUM.value,
|
|
|
size_mb=850,
|
|
|
description="Crypto/DeFi text generation model",
|
|
|
use_cases=["analysis", "reports", "content", "explanation"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.80,
|
|
|
popularity_score=0.70,
|
|
|
tags=["crypto", "generation", "gpt", "defi"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"fingpt": ModelInfo(
|
|
|
id="fingpt",
|
|
|
hf_id="oliverwang15/FinGPT",
|
|
|
name="FinGPT",
|
|
|
category=ModelCategory.GENERATION.value,
|
|
|
size=ModelSize.LARGE.value,
|
|
|
size_mb=1500,
|
|
|
description="Financial text generation and analysis",
|
|
|
use_cases=["reports", "analysis", "financial_content"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.82,
|
|
|
popularity_score=0.75,
|
|
|
tags=["finance", "generation", "gpt"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
"crypto_trader_lm": ModelInfo(
|
|
|
id="crypto_trader_lm",
|
|
|
hf_id="agarkovv/CryptoTrader-LM",
|
|
|
name="CryptoTrader LM",
|
|
|
category=ModelCategory.TRADING.value,
|
|
|
size=ModelSize.SMALL.value,
|
|
|
size_mb=450,
|
|
|
description="BTC/ETH trading signals (buy/sell/hold)",
|
|
|
use_cases=["trading", "signals", "predictions", "analysis"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.75,
|
|
|
popularity_score=0.65,
|
|
|
tags=["trading", "signals", "crypto", "predictions"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"crypto_price_predictor": ModelInfo(
|
|
|
id="crypto_price_predictor",
|
|
|
hf_id="mrm8488/bert-mini-finetuned-crypto-price-prediction",
|
|
|
name="Crypto Price Predictor",
|
|
|
category=ModelCategory.PRICE_PREDICTION.value,
|
|
|
size=ModelSize.TINY.value,
|
|
|
size_mb=60,
|
|
|
description="Price trend prediction for cryptocurrencies",
|
|
|
use_cases=["prediction", "forecasting", "trends"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.70,
|
|
|
popularity_score=0.60,
|
|
|
tags=["prediction", "price", "trends"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
"crypto_news_summarizer": ModelInfo(
|
|
|
id="crypto_news_summarizer",
|
|
|
hf_id="FurkanGozukara/Crypto-Financial-News-Summarizer",
|
|
|
name="Crypto News Summarizer",
|
|
|
category=ModelCategory.SUMMARIZATION.value,
|
|
|
size=ModelSize.MEDIUM.value,
|
|
|
size_mb=1200,
|
|
|
description="Summarize crypto and financial news articles",
|
|
|
use_cases=["news", "digest", "reports", "articles"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.82,
|
|
|
popularity_score=0.75,
|
|
|
tags=["summarization", "news", "crypto"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"financial_summarizer_pegasus": ModelInfo(
|
|
|
id="financial_summarizer_pegasus",
|
|
|
hf_id="human-centered-summarization/financial-summarization-pegasus",
|
|
|
name="Financial Summarizer (PEGASUS)",
|
|
|
category=ModelCategory.SUMMARIZATION.value,
|
|
|
size=ModelSize.LARGE.value,
|
|
|
size_mb=2300,
|
|
|
description="High-quality financial document summarization",
|
|
|
use_cases=["reports", "documents", "earnings", "filings"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.88,
|
|
|
popularity_score=0.80,
|
|
|
tags=["summarization", "finance", "pegasus"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"bart_large_cnn": ModelInfo(
|
|
|
id="bart_large_cnn",
|
|
|
hf_id="facebook/bart-large-cnn",
|
|
|
name="BART Large CNN",
|
|
|
category=ModelCategory.SUMMARIZATION.value,
|
|
|
size=ModelSize.LARGE.value,
|
|
|
size_mb=1600,
|
|
|
description="General-purpose news summarization",
|
|
|
use_cases=["news", "articles", "blogs", "content"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.90,
|
|
|
popularity_score=0.95,
|
|
|
tags=["summarization", "bart", "news"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"t5_base_summarization": ModelInfo(
|
|
|
id="t5_base_summarization",
|
|
|
hf_id="t5-base",
|
|
|
name="T5 Base",
|
|
|
category=ModelCategory.SUMMARIZATION.value,
|
|
|
size=ModelSize.MEDIUM.value,
|
|
|
size_mb=850,
|
|
|
description="Flexible text-to-text model for summarization",
|
|
|
use_cases=["general", "flexible", "any_text"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.85,
|
|
|
popularity_score=0.90,
|
|
|
tags=["summarization", "t5", "flexible"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
"bert_base_ner": ModelInfo(
|
|
|
id="bert_base_ner",
|
|
|
hf_id="dslim/bert-base-NER",
|
|
|
name="BERT Base NER",
|
|
|
category=ModelCategory.NER.value,
|
|
|
size=ModelSize.SMALL.value,
|
|
|
size_mb=420,
|
|
|
description="Named Entity Recognition for financial entities",
|
|
|
use_cases=["entities", "extraction", "companies", "tickers"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.88,
|
|
|
popularity_score=0.85,
|
|
|
tags=["ner", "entities", "bert"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
"roberta_squad2": ModelInfo(
|
|
|
id="roberta_squad2",
|
|
|
hf_id="deepset/roberta-base-squad2",
|
|
|
name="RoBERTa SQuAD2",
|
|
|
category=ModelCategory.QA.value,
|
|
|
size=ModelSize.MEDIUM.value,
|
|
|
size_mb=500,
|
|
|
description="Question answering for any text",
|
|
|
use_cases=["qa", "chatbot", "faq", "retrieval"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.90,
|
|
|
popularity_score=0.92,
|
|
|
tags=["qa", "roberta", "squad"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"bert_squad2": ModelInfo(
|
|
|
id="bert_squad2",
|
|
|
hf_id="deepset/bert-base-cased-squad2",
|
|
|
name="BERT SQuAD2",
|
|
|
category=ModelCategory.QA.value,
|
|
|
size=ModelSize.SMALL.value,
|
|
|
size_mb=420,
|
|
|
description="Financial FAQ and Q&A",
|
|
|
use_cases=["faq", "support", "chatbot"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.87,
|
|
|
popularity_score=0.88,
|
|
|
tags=["qa", "bert", "squad"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
"sentence_bert_mpnet": ModelInfo(
|
|
|
id="sentence_bert_mpnet",
|
|
|
hf_id="sentence-transformers/all-mpnet-base-v2",
|
|
|
name="Sentence-BERT MPNet",
|
|
|
category=ModelCategory.EMBEDDING.value,
|
|
|
size=ModelSize.SMALL.value,
|
|
|
size_mb=420,
|
|
|
description="High-quality sentence embeddings",
|
|
|
use_cases=["search", "similarity", "clustering", "retrieval"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.92,
|
|
|
popularity_score=0.95,
|
|
|
tags=["embeddings", "sentence", "bert"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
"e5_large_v2": ModelInfo(
|
|
|
id="e5_large_v2",
|
|
|
hf_id="intfloat/e5-large-v2",
|
|
|
name="E5 Large V2",
|
|
|
category=ModelCategory.EMBEDDING.value,
|
|
|
size=ModelSize.MEDIUM.value,
|
|
|
size_mb=1300,
|
|
|
description="State-of-the-art embeddings",
|
|
|
use_cases=["search", "retrieval", "rag", "semantic"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.94,
|
|
|
popularity_score=0.90,
|
|
|
tags=["embeddings", "e5", "search"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
"bart_mnli": ModelInfo(
|
|
|
id="bart_mnli",
|
|
|
hf_id="facebook/bart-large-mnli",
|
|
|
name="BART MNLI",
|
|
|
category=ModelCategory.CLASSIFICATION.value,
|
|
|
size=ModelSize.LARGE.value,
|
|
|
size_mb=1600,
|
|
|
description="Zero-shot topic classification",
|
|
|
use_cases=["classification", "topics", "zero_shot"],
|
|
|
languages=["en"],
|
|
|
free=True,
|
|
|
requires_auth=False,
|
|
|
performance_score=0.89,
|
|
|
popularity_score=0.92,
|
|
|
tags=["classification", "bart", "zero_shot"],
|
|
|
api_compatible=True,
|
|
|
downloadable=True
|
|
|
),
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def get_all_models(self) -> List[ModelInfo]:
|
|
|
"""دریافت تمام مدلها"""
|
|
|
return list(self.models.values())
|
|
|
|
|
|
def get_model_by_id(self, model_id: str) -> Optional[ModelInfo]:
|
|
|
"""دریافت مدل بر اساس ID"""
|
|
|
return self.models.get(model_id)
|
|
|
|
|
|
def filter_models(
|
|
|
self,
|
|
|
category: Optional[str] = None,
|
|
|
size: Optional[str] = None,
|
|
|
max_size_mb: Optional[int] = None,
|
|
|
language: Optional[str] = None,
|
|
|
free_only: bool = True,
|
|
|
no_auth: bool = True,
|
|
|
min_performance: float = 0.0,
|
|
|
api_compatible: Optional[bool] = None,
|
|
|
tags: Optional[List[str]] = None
|
|
|
) -> List[ModelInfo]:
|
|
|
"""
|
|
|
فیلتر کردن مدلها بر اساس معیارهای مختلف
|
|
|
"""
|
|
|
filtered = self.get_all_models()
|
|
|
|
|
|
if category:
|
|
|
filtered = [m for m in filtered if m.category == category]
|
|
|
|
|
|
if size:
|
|
|
filtered = [m for m in filtered if m.size == size]
|
|
|
|
|
|
if max_size_mb:
|
|
|
filtered = [m for m in filtered if m.size_mb <= max_size_mb]
|
|
|
|
|
|
if language:
|
|
|
filtered = [
|
|
|
m for m in filtered
|
|
|
if language in m.languages or "multi" in m.languages
|
|
|
]
|
|
|
|
|
|
if free_only:
|
|
|
filtered = [m for m in filtered if m.free]
|
|
|
|
|
|
if no_auth:
|
|
|
filtered = [m for m in filtered if not m.requires_auth]
|
|
|
|
|
|
if min_performance > 0:
|
|
|
filtered = [m for m in filtered if m.performance_score >= min_performance]
|
|
|
|
|
|
if api_compatible is not None:
|
|
|
filtered = [m for m in filtered if m.api_compatible == api_compatible]
|
|
|
|
|
|
if tags:
|
|
|
filtered = [
|
|
|
m for m in filtered
|
|
|
if any(tag in m.tags for tag in tags)
|
|
|
]
|
|
|
|
|
|
return filtered
|
|
|
|
|
|
def get_best_models(
|
|
|
self,
|
|
|
category: str,
|
|
|
top_n: int = 3,
|
|
|
max_size_mb: Optional[int] = None
|
|
|
) -> List[ModelInfo]:
|
|
|
"""
|
|
|
دریافت بهترین مدلها بر اساس performance
|
|
|
"""
|
|
|
filtered = self.filter_models(
|
|
|
category=category,
|
|
|
max_size_mb=max_size_mb
|
|
|
)
|
|
|
|
|
|
|
|
|
sorted_models = sorted(
|
|
|
filtered,
|
|
|
key=lambda m: (m.performance_score, m.popularity_score),
|
|
|
reverse=True
|
|
|
)
|
|
|
|
|
|
return sorted_models[:top_n]
|
|
|
|
|
|
def recommend_models(
|
|
|
self,
|
|
|
use_case: str,
|
|
|
max_models: int = 5,
|
|
|
max_size_mb: Optional[int] = None
|
|
|
) -> List[ModelInfo]:
|
|
|
"""
|
|
|
پیشنهاد مدلها بر اساس use case
|
|
|
"""
|
|
|
all_models = self.get_all_models()
|
|
|
|
|
|
|
|
|
relevant = [
|
|
|
m for m in all_models
|
|
|
if use_case in m.use_cases or any(use_case in uc for uc in m.use_cases)
|
|
|
]
|
|
|
|
|
|
|
|
|
if max_size_mb:
|
|
|
relevant = [m for m in relevant if m.size_mb <= max_size_mb]
|
|
|
|
|
|
|
|
|
sorted_models = sorted(
|
|
|
relevant,
|
|
|
key=lambda m: (m.performance_score * m.popularity_score),
|
|
|
reverse=True
|
|
|
)
|
|
|
|
|
|
return sorted_models[:max_models]
|
|
|
|
|
|
def search_models(self, query: str) -> List[ModelInfo]:
|
|
|
"""
|
|
|
جستجو در تمام فیلدهای مدلها
|
|
|
"""
|
|
|
query_lower = query.lower()
|
|
|
all_models = self.get_all_models()
|
|
|
|
|
|
results = []
|
|
|
for model in all_models:
|
|
|
|
|
|
if (
|
|
|
query_lower in model.name.lower()
|
|
|
or query_lower in model.description.lower()
|
|
|
or any(query_lower in tag for tag in model.tags)
|
|
|
or any(query_lower in uc for uc in model.use_cases)
|
|
|
or query_lower in model.hf_id.lower()
|
|
|
):
|
|
|
results.append(model)
|
|
|
|
|
|
|
|
|
return sorted(
|
|
|
results,
|
|
|
key=lambda m: (m.performance_score, m.popularity_score),
|
|
|
reverse=True
|
|
|
)
|
|
|
|
|
|
def get_model_stats(self) -> Dict[str, Any]:
|
|
|
"""آمار کامل مدلها"""
|
|
|
all_models = self.get_all_models()
|
|
|
|
|
|
|
|
|
by_category = {}
|
|
|
for cat in ModelCategory:
|
|
|
count = len([m for m in all_models if m.category == cat.value])
|
|
|
by_category[cat.value] = count
|
|
|
|
|
|
|
|
|
by_size = {}
|
|
|
for size in ModelSize:
|
|
|
count = len([m for m in all_models if m.size == size.value])
|
|
|
by_size[size.value] = count
|
|
|
|
|
|
|
|
|
all_tags = {}
|
|
|
for model in all_models:
|
|
|
for tag in model.tags:
|
|
|
all_tags[tag] = all_tags.get(tag, 0) + 1
|
|
|
|
|
|
|
|
|
top_tags = sorted(all_tags.items(), key=lambda x: x[1], reverse=True)[:10]
|
|
|
|
|
|
return {
|
|
|
"total_models": len(all_models),
|
|
|
"by_category": by_category,
|
|
|
"by_size": by_size,
|
|
|
"free_models": len([m for m in all_models if m.free]),
|
|
|
"no_auth_models": len([m for m in all_models if not m.requires_auth]),
|
|
|
"api_compatible": len([m for m in all_models if m.api_compatible]),
|
|
|
"downloadable": len([m for m in all_models if m.downloadable]),
|
|
|
"avg_performance": round(
|
|
|
sum(m.performance_score for m in all_models) / len(all_models), 2
|
|
|
),
|
|
|
"avg_popularity": round(
|
|
|
sum(m.popularity_score for m in all_models) / len(all_models), 2
|
|
|
),
|
|
|
"total_size_gb": round(sum(m.size_mb for m in all_models) / 1024, 2),
|
|
|
"top_tags": [{"tag": tag, "count": count} for tag, count in top_tags],
|
|
|
"languages_supported": list(set(
|
|
|
lang for m in all_models for lang in m.languages
|
|
|
))
|
|
|
}
|
|
|
|
|
|
def get_categories(self) -> List[Dict[str, Any]]:
|
|
|
"""لیست categories با آمار"""
|
|
|
all_models = self.get_all_models()
|
|
|
|
|
|
categories = []
|
|
|
for cat in ModelCategory:
|
|
|
models_in_cat = [m for m in all_models if m.category == cat.value]
|
|
|
if models_in_cat:
|
|
|
categories.append({
|
|
|
"id": cat.value,
|
|
|
"name": cat.name,
|
|
|
"count": len(models_in_cat),
|
|
|
"avg_performance": round(
|
|
|
sum(m.performance_score for m in models_in_cat) / len(models_in_cat),
|
|
|
2
|
|
|
),
|
|
|
"models": [m.id for m in models_in_cat[:5]]
|
|
|
})
|
|
|
|
|
|
return sorted(categories, key=lambda x: x["count"], reverse=True)
|
|
|
|
|
|
def export_catalog_json(self, filepath: str):
|
|
|
"""Export کردن کاتالوگ به JSON"""
|
|
|
catalog = {
|
|
|
"models": [m.to_dict() for m in self.get_all_models()],
|
|
|
"stats": self.get_model_stats(),
|
|
|
"categories": self.get_categories()
|
|
|
}
|
|
|
|
|
|
with open(filepath, 'w', encoding='utf-8') as f:
|
|
|
json.dump(catalog, f, indent=2, ensure_ascii=False)
|
|
|
|
|
|
logger.info(f"Exported catalog to {filepath}")
|
|
|
|
|
|
|
|
|
|
|
|
_model_manager = None
|
|
|
|
|
|
def get_model_manager() -> AdvancedModelManager:
|
|
|
"""دریافت instance سراسری model manager"""
|
|
|
global _model_manager
|
|
|
if _model_manager is None:
|
|
|
_model_manager = AdvancedModelManager()
|
|
|
return _model_manager
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
manager = AdvancedModelManager()
|
|
|
|
|
|
print("=== Model Manager Test ===\n")
|
|
|
|
|
|
|
|
|
stats = manager.get_model_stats()
|
|
|
print(f"📊 Total Models: {stats['total_models']}")
|
|
|
print(f"📊 Free Models: {stats['free_models']}")
|
|
|
print(f"📊 API Compatible: {stats['api_compatible']}")
|
|
|
print(f"📊 Avg Performance: {stats['avg_performance']}")
|
|
|
print(f"📊 Total Size: {stats['total_size_gb']} GB\n")
|
|
|
|
|
|
|
|
|
print("🏆 Best Sentiment Models:")
|
|
|
best_sentiment = manager.get_best_models("sentiment", top_n=3, max_size_mb=500)
|
|
|
for i, model in enumerate(best_sentiment, 1):
|
|
|
print(f" {i}. {model.name} - {model.performance_score:.2f}")
|
|
|
|
|
|
|
|
|
print("\n💡 Recommended for 'twitter':")
|
|
|
recommended = manager.recommend_models("twitter", max_models=3)
|
|
|
for i, model in enumerate(recommended, 1):
|
|
|
print(f" {i}. {model.name} - {model.description[:50]}...")
|
|
|
|
|
|
|
|
|
print("\n🔍 Search for 'crypto':")
|
|
|
search_results = manager.search_models("crypto")[:3]
|
|
|
for i, model in enumerate(search_results, 1):
|
|
|
print(f" {i}. {model.name} - {model.category}")
|
|
|
|
|
|
|
|
|
|
|
|
print("\n✅ Test complete!")
|
|
|
|