File size: 5,578 Bytes
6592886 bc628f9 6592886 bc628f9 | 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 | ---
license: gpl-3.0
datasets:
- wikimedia/wikipedia
---
# FractalGPT/EmbedderDecoder
* **Оригинальная модель**
[[ai-forever/rugpt3small_based_on_gpt2](https://huggingface.co/ai-forever/rugpt3small_based_on_gpt2)]
* **Код генерации взят частично отсюда**
[[vector2text](https://github.com/Koziev/vector2text)]
* Заменен эмбеддер
* Вместо нулей вектор дополняется квадратами чисел (далее можно кубами и т.д.)
* Создан класс для генератора
* Добавлен ранжировщик
* Заменена модель вместо large — small
* Убран top_p
* **Пример использования**
```python
import torch
import numpy as np
from torch.nn import functional as F
from transformers import GPT2Tokenizer, GPT2LMHeadModel
def top_filtering(logits, top_k):
"""
Фильтрация top-k, в фильтрации top-p в этой задаче особо смысла нет
"""
assert logits.dim() == 1
top_k = min(top_k, logits.size(-1))
if top_k > 0:
indices_to_remove = logits < torch.topk(logits, top_k)[0][..., -1, None]
logits[indices_to_remove] = -float('Inf')
return logits
class TextEmbdGenerator:
def __init__(self, name_or_path, sbert, device = None):
"""
Инициализация генератора текста с моделью и токенизатором.
name_or_path: путь до модели токенизатора или ее имя для загрузки из Hugging Face.
sbert: модель для ранжирования (такая же что и создает эбеддинги)
"""
self.device = device
if self.device == None:
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.tokenizer = GPT2Tokenizer.from_pretrained(name_or_path)
self.model = GPT2LMHeadModel.from_pretrained(name_or_path).to(self.device)
self.sbert = sbert
def generate_embedding(self, embd, prompt = '', temperature=0.26, top_k=4, max_len=100):
"""
Генерация текста на основе начального эмбеддинга и заданного начального текста.
"""
vector = np.concatenate([embd,embd**2])
current_output_ids = self.tokenizer.encode(prompt)
embedding = torch.FloatTensor([list(vector)]).to(self.device)
while len(current_output_ids) < max_len:
with torch.no_grad():
token_embeddings = self.model.base_model.wte(torch.LongTensor(current_output_ids).to(self.device))
input_vectors = torch.vstack((embedding, token_embeddings)).unsqueeze(dim=0)
output_model = self.model(inputs_embeds=input_vectors)
logits = output_model.logits
if isinstance(logits, tuple):
logits = logits[0]
logits = logits[0, -1, :]
logits /= temperature
logits = top_filtering(logits, top_k)
probs = F.softmax(logits, dim=-1)
prev = torch.multinomial(probs, 1)
if prev.item() == self.tokenizer.eos_token_id:
break
current_output_ids.append(prev.item())
output_text = self.tokenizer.decode(current_output_ids)
return output_text.split('\n')[0]
def cosine_similarity(self, x, y):
"""Вычисление косинусного сходства."""
return np.dot(x, y) / (np.linalg.norm(x) * np.linalg.norm(y))
def generate_with_ranker(self, embd, prompt = '', seq=10, temperature=0.6, top_k=10, max_len=100):
"""Генерация и ранжирование текста. Поумолчанию создаются 10 текстов"""
sequences = [self.generate_embedding(embd, prompt, temperature, top_k, max_len) for _ in range(seq)]
sequences = list(set(sequences)) # Удаление дубликатов
# Ранжирование
embeddings = self.sbert.encode(sequences)
similarities = [self.cosine_similarity(embd, emb) for emb in embeddings]
best_index = np.argmax(similarities)
return sequences[best_index]
```
---
```bash
pip install sentence-transformers -q
```
```python
from sentence_transformers import SentenceTransformer
sbert = SentenceTransformer('FractalGPT/SbertDistil')
generator = TextEmbdGenerator('FractalGPT/EmbedderDecoder', sbert)
```
```python
embd = sbert.encode('там живут англичане')
generator.generate_with_ranker(embd, prompt = 'он всегда был в')
```
```bash
>>> он всегда был в Англии.
```
```python
embd = sbert.encode('там живут немцы')
generator.generate_with_ranker(embd, prompt = 'он всегда был в')
```
```bash
>>> он всегда был в Германии
```
```python
embd = sbert.encode('он сделает вывод на основе анализа ситуации')
generator.generate_with_ranker(embd)
```
```bash
>>> в процессе анализа ситуации необходимо выяснить:
```
```python
embd = sbert.encode('интересный фильм смотрел, фильм понравился')
generator.generate_with_ranker(embd, seq=5)
```
```bash
>>> фильм был снят по мотивам произведений
``` |