File size: 8,343 Bytes
bd161ec
 
 
 
 
 
e4e7a94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bd161ec
 
 
 
 
 
 
 
 
 
 
 
 
 
e4e7a94
 
 
 
 
 
 
 
 
 
 
 
bd161ec
 
 
 
 
 
e4e7a94
 
bd161ec
 
 
 
e4e7a94
 
 
 
bd161ec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e4e7a94
bd161ec
 
 
 
 
 
 
 
 
 
e4e7a94
bd161ec
 
 
 
 
 
 
 
 
 
 
e4e7a94
bd161ec
 
 
e4e7a94
bd161ec
 
 
 
 
 
 
 
566f774
bd161ec
 
 
 
 
 
 
566f774
bd161ec
 
 
566f774
bd161ec
 
 
 
 
 
 
 
566f774
bd161ec
 
 
 
 
 
566f774
bd161ec
 
 
566f774
bd161ec
 
 
 
 
 
 
 
 
 
566f774
bd161ec
 
 
 
 
 
566f774
bd161ec
 
 
566f774
bd161ec
 
566f774
bd161ec
 
e4e7a94
bd161ec
 
e4e7a94
bd161ec
 
566f774
 
 
bd161ec
 
 
 
 
566f774
 
 
 
 
 
 
bd161ec
 
 
566f774
bd161ec
 
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
"""
Hugging Face service for model inference and API integration.
"""
import os
import logging
from typing import Dict, List, Optional, Any

# Optional imports - handle missing dependencies gracefully
try:
    from huggingface_hub import InferenceClient
    HUGGINGFACE_HUB_AVAILABLE = True
except ImportError:
    HUGGINGFACE_HUB_AVAILABLE = False
    InferenceClient = None

try:
    from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
    TRANSFORMERS_AVAILABLE = True
except ImportError:
    TRANSFORMERS_AVAILABLE = False
    AutoTokenizer = None
    AutoModelForCausalLM = None
    pipeline = None

try:
    import torch
    TORCH_AVAILABLE = True
except ImportError:
    TORCH_AVAILABLE = False
    torch = None

from config import settings

logger = logging.getLogger(__name__)


class HuggingFaceService:
    """Service for Hugging Face model interactions."""
    
    def __init__(self):
        self.client = None
        self.tokenizer = None
        self.model = None
        self.pipeline = None
        
        # Check if dependencies are available
        if not HUGGINGFACE_HUB_AVAILABLE:
            logger.warning("huggingface_hub not available. Hugging Face API features will be disabled.")
        
        if not TRANSFORMERS_AVAILABLE:
            logger.warning("transformers not available. Local model features will be disabled.")
        
        if not TORCH_AVAILABLE:
            logger.warning("torch not available. Local model features will be disabled.")
        
        # Initialize Hugging Face client if API token is provided and dependencies are available
        if settings.hf_api_token and HUGGINGFACE_HUB_AVAILABLE:
            try:
                self.client = InferenceClient(token=settings.hf_api_token)
                logger.info("Hugging Face Inference Client initialized successfully")
            except Exception as e:
                logger.error(f"Failed to initialize Hugging Face client: {e}")
        
        # Load local model if specified and dependencies are available
        if settings.hf_model_name and TRANSFORMERS_AVAILABLE and TORCH_AVAILABLE:
            self._load_local_model()
    
    def _load_local_model(self):
        """Load a local Hugging Face model."""
        if not TRANSFORMERS_AVAILABLE or not TORCH_AVAILABLE:
            logger.error("Cannot load local model: transformers or torch not available")
            return
            
        try:
            logger.info(f"Loading local model: {settings.hf_model_name}")
            
            # Load tokenizer and model
            self.tokenizer = AutoTokenizer.from_pretrained(settings.hf_model_name)
            self.model = AutoModelForCausalLM.from_pretrained(
                settings.hf_model_name,
                torch_dtype=torch.float16,
                device_map="auto"
            )
            
            # Create pipeline
            self.pipeline = pipeline(
                "text-generation",
                model=self.model,
                tokenizer=self.tokenizer,
                max_length=2048,
                temperature=0.7,
                do_sample=True
            )
            
            logger.info("Local model loaded successfully")
            
        except Exception as e:
            logger.error(f"Failed to load local model: {e}")
    
    async def generate_text(
        self,
        prompt: str,
        model_name: Optional[str] = None,
        max_length: int = 2048,
        temperature: float = 0.7,
        use_local: bool = False
    ) -> str:
        """Generate text using Hugging Face models."""
        try:
            if use_local and self.pipeline and TRANSFORMERS_AVAILABLE:
                # Use local model
                result = self.pipeline(
                    prompt,
                    max_length=max_length,
                    temperature=temperature,
                    do_sample=True,
                    pad_token_id=self.tokenizer.eos_token_id
                )
                return result[0]['generated_text']
            
            elif self.client and model_name and HUGGINGFACE_HUB_AVAILABLE:
                # Use Hugging Face Inference API
                result = self.client.text_generation(
                    prompt,
                    model=model_name,
                    max_new_tokens=max_length,
                    temperature=temperature,
                    do_sample=True
                )
                return result
            
            else:
                raise Exception("No model available. Please configure HF_API_TOKEN or HF_MODEL_NAME, or install required dependencies")
                
        except Exception as e:
            logger.error(f"Hugging Face text generation error: {e}")
            raise
    
    async def create_embedding(
        self,
        text: str,
        model_name: str = "sentence-transformers/all-MiniLM-L6-v2"
    ) -> List[float]:
        """Create embedding using Hugging Face models."""
        try:
            if self.client and HUGGINGFACE_HUB_AVAILABLE:
                # Use Hugging Face Inference API
                result = self.client.feature_extraction(
                    text,
                    model=model_name
                )
                return result[0] if isinstance(result, list) else result
            else:
                raise Exception("Hugging Face client not initialized or dependencies not available")
                
        except Exception as e:
            logger.error(f"Hugging Face embedding error: {e}")
            raise
    
    async def classify_text(
        self,
        text: str,
        model_name: str = "distilbert-base-uncased-finetuned-sst-2-english"
    ) -> Dict[str, Any]:
        """Classify text using Hugging Face models."""
        try:
            if self.client and HUGGINGFACE_HUB_AVAILABLE:
                result = self.client.text_classification(
                    text,
                    model=model_name
                )
                return result
            else:
                raise Exception("Hugging Face client not initialized or dependencies not available")
                
        except Exception as e:
            logger.error(f"Hugging Face classification error: {e}")
            raise
    
    async def translate_text(
        self,
        text: str,
        source_lang: str = "en",
        target_lang: str = "es",
        model_name: str = "Helsinki-NLP/opus-mt-en-es"
    ) -> str:
        """Translate text using Hugging Face models."""
        try:
            if self.client and HUGGINGFACE_HUB_AVAILABLE:
                result = self.client.translation(
                    text,
                    model=model_name
                )
                return result
            else:
                raise Exception("Hugging Face client not initialized or dependencies not available")
                
        except Exception as e:
            logger.error(f"Hugging Face translation error: {e}")
            raise
    
    def get_available_models(self) -> List[str]:
        """Get list of available models."""
        models = []
        
        if self.client and HUGGINGFACE_HUB_AVAILABLE:
            models.append("Hugging Face Inference API (remote)")
        
        if self.pipeline and TRANSFORMERS_AVAILABLE:
            models.append(f"Local model: {settings.hf_model_name}")
        
        if not models:
            models.append("No models available - check dependencies and configuration")
        
        return models
    
    def get_service_status(self) -> Dict[str, Any]:
        """Get service status and configuration."""
        return {
            "service": "huggingface",
            "status": "available" if (self.client or self.pipeline) else "unavailable",
            "dependencies": {
                "huggingface_hub": HUGGINGFACE_HUB_AVAILABLE,
                "transformers": TRANSFORMERS_AVAILABLE,
                "torch": TORCH_AVAILABLE
            },
            "client_initialized": self.client is not None,
            "local_model_loaded": self.pipeline is not None,
            "api_token_configured": bool(settings.hf_api_token),
            "local_model_configured": bool(settings.hf_model_name),
            "available_models": self.get_available_models()
        }