Spaces:
Runtime error
Runtime error
import numpy as np | |
import torch | |
from typing import List, Union, Dict | |
from transformers import AutoTokenizer, AutoModel | |
from pathlib import Path | |
import json | |
class LocalEmbedder: | |
def __init__(self, model_name: str, device: str = None, batch_size: int = 32): | |
""" | |
Ініціалізація локальної моделі для ембедінгів | |
Args: | |
model_name: назва або шлях до моделі (з HuggingFace або локальна) | |
device: пристрій для обчислень ('cuda', 'cpu' або None - автовибір) | |
batch_size: розмір батчу для інференсу | |
""" | |
self.model_name = model_name | |
self.batch_size = batch_size | |
# Визначення пристрою | |
if device is None: | |
self.device = 'cuda' if torch.cuda.is_available() else 'cpu' | |
else: | |
self.device = device | |
# Завантаження моделі та токенізатора | |
self.tokenizer = AutoTokenizer.from_pretrained(model_name) | |
self.model = AutoModel.from_pretrained(model_name).to(self.device) | |
self.model.eval() | |
# Максимальна довжина послідовності | |
self.max_length = self.tokenizer.model_max_length | |
if self.max_length > 512: | |
self.max_length = 512 | |
def _normalize_embeddings(self, embeddings: np.ndarray) -> np.ndarray: | |
""" | |
L2-нормалізація ембедінгів | |
Args: | |
embeddings: матриця ембедінгів | |
Returns: | |
np.ndarray: нормалізована матриця ембедінгів | |
""" | |
norms = np.linalg.norm(embeddings, axis=1, keepdims=True) | |
return embeddings / norms | |
def get_embeddings(self, texts: Union[str, List[str]]) -> np.ndarray: | |
""" | |
Отримання ембедінгів для тексту або списку текстів | |
Args: | |
texts: текст або список текстів | |
Returns: | |
np.ndarray: матриця нормалізованих ембедінгів | |
""" | |
if isinstance(texts, str): | |
texts = [texts] | |
all_embeddings = [] | |
with torch.no_grad(): | |
for i in range(0, len(texts), self.batch_size): | |
batch_texts = texts[i:i + self.batch_size] | |
# Токенізація | |
encoded = self.tokenizer.batch_encode_plus( | |
batch_texts, | |
padding=True, | |
truncation=True, | |
max_length=self.max_length, | |
return_tensors='pt' | |
) | |
# Переміщуємо тензори на потрібний пристрій | |
input_ids = encoded['input_ids'].to(self.device) | |
attention_mask = encoded['attention_mask'].to(self.device) | |
# Отримуємо ембедінги | |
outputs = self.model( | |
input_ids=input_ids, | |
attention_mask=attention_mask | |
) | |
# Використовуємо [CLS] токен як ембедінг | |
embeddings = outputs.last_hidden_state[:, 0, :] | |
all_embeddings.append(embeddings.cpu().numpy()) | |
# Об'єднуємо всі батчі | |
embeddings = np.vstack(all_embeddings) | |
# Нормалізуємо ембедінги | |
normalized_embeddings = self._normalize_embeddings(embeddings) | |
return normalized_embeddings | |
def get_model_info(self) -> Dict[str, any]: | |
""" | |
Отримання інформації про модель | |
Returns: | |
Dict: інформація про модель | |
""" | |
return { | |
'model_name': self.model_name, | |
'device': self.device, | |
'embedding_size': self.model.config.hidden_size, | |
'max_length': self.max_length, | |
'batch_size': self.batch_size | |
} |