File size: 6,300 Bytes
6592886 bc628f9 6592886 bc628f9 4105808 bc628f9 b46980a 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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | ---
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
>>> фильм был снят по мотивам произведений
```
```python
embd = sbert.encode('полицейский - главный герой') + sbert.encode('Произошло ужасное событие в фильме')
embd /= 2
generator.generate_with_ranker(embd, 'Собеседование на')
```
```bash
>>> Собеседование на роль главного героя фильма — молодого лейтенанта полиции — происходит в доме
```
```python
embd = sbert.encode('машина') - sbert.encode('колеса') + sbert.encode('крылья')
generator.generate_with_ranker(embd, 'это')
```
```bash
>>> этот самолет
``` |