🧠 Bormokrut
Bormokrut — это лёгкая, но глубокая языковая модель на базе GPT-2, дообученная (SFT) с использованием trl для выполнения двух специфических задач:
- Извлечение (extract) — сущности, аспектов и ключевого вопроса из текста
- Маршрутизация (route) — выбор экспертной области по входному вопросу
Модель создана на основе Bormotuha и ориентирована на использование в узких, но содержательных сценариях обработки текста.
Как использовать (How to use)
Модель обучена на следующих шаблонах:
- extract Вопрос:...[Контекст: ...] Entity:... Aspects:... Question:...
- route experts:... Вопрос:...[Контекст: ...] Entity:... Aspects:... Route:...
Набор экспертов фиксирован и должен быть перечислен в специальном блоке:
prompt="...<subject>experts: биограф; учёный; инженер; кибернетик; математик; гуманитарий; медик; экономист; искусствовед; жизнекачер; смежник</subject><newline>..."
Тестовый скрипт
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer, StoppingCriteria, StoppingCriteriaList
from threading import Thread
# Загрузка модели и токенизатора
checkpoint_path = "Vladniag/Bormokrut"
model = AutoModelForCausalLM.from_pretrained(
checkpoint_path,
device_map="cuda",
torch_dtype=torch.float16
)
tokenizer = AutoTokenizer.from_pretrained(checkpoint_path, use_fast=True)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
# Настройка стоп-слов
class StopOnTokens(StoppingCriteria):
def __init__(self, stop_token_ids_list):
self.stop_token_ids_list = stop_token_ids_list
def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
for stop_ids in self.stop_token_ids_list:
if len(input_ids[0]) >= len(stop_ids):
if input_ids[0][-len(stop_ids):].tolist() == stop_ids:
return True
return False
stop_words = ["</result>"]
stop_ids_list = [tokenizer.encode(word, add_special_tokens=False) for word in stop_words]
stopping_criteria = StoppingCriteriaList([StopOnTokens(stop_ids_list)])
# Функция генерации
def generate_response(prompt):
processed_input = "▁" + prompt.lstrip().replace(" ", "▁").replace("\n", "<newline>")
inputs = tokenizer(
processed_input,
return_tensors="pt",
add_special_tokens=False,
).to(model.device)
streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=False)
generation_kwargs = dict(
inputs,
streamer=streamer,
max_new_tokens=256,
do_sample=True,
temperature=0.3,
top_p=0.5,
repetition_penalty=1.3,
pad_token_id=tokenizer.pad_token_id,
eos_token_id=tokenizer.eos_token_id,
stopping_criteria=stopping_criteria
)
thread = Thread(target=model.generate, kwargs=generation_kwargs)
thread.start()
full_response = ""
for new_text in streamer:
decoded_chunk = new_text.replace("▁", " ").replace("<newline>", "\n").replace("\\n", "\n")
if "</result>" in decoded_chunk:
print(decoded_chunk.split("</result>")[0], end="", flush=True)
break
print(decoded_chunk, end="", flush=True)
print()
# Пример использования
prompt = """<instruction>extract</instruction>
<fragment>
Не одному Перуну предназначались почести, но всем «кумирам» без исключения. «И жряху им, наричюще я богы, и привожаху сыны своя и дъщери, и жряху бесом, и оскверняху землю требами своими». Приведенный летописный отрывок чрезвычайно интересен для понимания внутреннего развития восточнославянского язычества на стадии политеизма. Божества других племен и народов не отрицаются, не подчиняются, не становятся второстепенными по отношению к Перуну, а, наоборот, признаются существующими и самостоятельными. Главный бог – только сильнее и могущественнее остальных, он их счастливый соперник, победитель при столкновениях.
</fragment>
<result>"""
generate_response(prompt)
Примеры работы
Задача: извлечение (extract)
Входной текст:
- Не одному Перуну предназначались почести, но всем «кумирам» без исключения. «И жряху им, наричюще я богы, и привожаху сыны своя и дъщери, и жряху бесом, и оскверняху землю требами своими». Приведенный летописный отрывок чрезвычайно интересен для понимания внутреннего развития восточнославянского язычества на стадии политеизма. Божества других племен и народов не отрицаются, не подчиняются, не становятся второстепенными по отношению к Перуну, а, наоборот, признаются существующими и самостоятельными. Главный бог – только сильнее и могущественнее остальных, он их счастливый соперник, победитель при столкновениях.
Результат:
-
Entity: Перун
-
Aspects: боги; роль в мифологии; связь с другими божествами; социальная структура
-
Question: Какова роль и значение богов в древнерусском язычестве, согласно летописи?
Задача: маршрутизация (route)
Входной вопрос:
- Какие нарушения функций печени связаны со злоупотреблением алкоголем?
Результат:
- Route: медик
Входной вопрос:
- Каково значение Духа в контексте Троицы и Его роли в мире?
Результат:
- Route: гуманитарий
📊 Данные обучения
| Параметр | Значение |
|---|---|
| Объём выборки | 351 815 примеров |
| Режим обучения | SFT (Supervised Fine-Tuning) |
| Инструмент | TRL (Transformer Reinforcement Learning) |
| Базовая модель | Bormotuha |
⚙️ Конфигурация модели
{
"activation_function": "gelu_new",
"architectures": ["GPT2LMHeadModel"],
"attn_pdrop": 0.1,
"bos_token_id": null,
"dtype": "float32",
"embd_pdrop": 0.1,
"eos_token_id": 3,
"initializer_range": 0.02,
"layer_norm_epsilon": 1e-05,
"model_type": "gpt2",
"n_ctx": 1536,
"n_embd": 256,
"n_head": 8,
"n_inner": 1024,
"n_layer": 42,
"n_positions": 1536,
"pad_token_id": 0,
"reorder_and_upcast_attn": false,
"resid_pdrop": 0.1,
"scale_attn_by_inverse_layer_idx": false,
"scale_attn_weights": true,
"summary_activation": null,
"summary_first_dropout": 0.1,
"summary_proj_to_labels": true,
"summary_type": "cls_index",
"summary_use_proj": true,
"transformers_version": "4.56.1",
"use_cache": true,
"vocab_size": 6002
}