Pull to refresh

Comments 100

Да все интересно и дорбучение и инструкции и примеры.

1. На каком ускорителе ее можно покрутить в домашних условиях? Могу я ее покрутить на 1080ti 12gb или нужен более новый или только больше памяти? 2. Какова скорость работы на цпу?

int8 должен запуститься на бесплатной T4 в колабе. Так что у вас думаю тоже заработает.

В колабе вроде 16г GPU. Если инт8 на 13b то я правильно понимаю что 12gb маловато? До int4 говорят как то можно ужать?

Я сейчас пойду упрашивать TheBloke сделать GGML. Если сделает, то хоть на четвёртом пне без GPU будет терпимая скорость.

Хотел по-быстрому проверить в text-generation-webui, но не удалось: в репозитории не нашлось config.json. Можно ли как-то обойти? В Readme предупреждение про UI видел :)

Я запустил, но это... какое-то безумие? Под спойлер спрятал, потому что мега странные ответы. Обилие смайлов, капса, бессвязные ответы... Может модельку сломали где-то по дороге? Или либа для инференса ошибается?

Hidden text
  • "Яндекс это "

    Это не переводчик, а компания по поиску в Интернете. Ее основатель и первый гендиректор Артемий Андреевич Лебедев (урожденный Тёма) придумал слово «Яндекс» еще во втором классе школы. А уже через пять лет продал компанию за $50 млн голландскому фонду Index Ventures. Сам остался жить на два дома: с 2000 года он ведет собственный проект о путешествиях Roem.ru. В свободное от бизнеса время — увлекается фотографией и игрой на фортепиано.

    Если вы забыли что такое ЯНДЕКС, то я напомню вам - ЭТО НЕ ПЕРЕВОДЧИК И НЕ КОМПАНИЯ ПОИСКАВШЕЙ ИНФОРМАЦИЮ В ИНТЕРНЕТЕ, ЭТО ГОРОД ТОМССК!А ЧТО ДОЛЖЕН БЫТЬ НА САМОЙ ДЕВИЗЕМНОГО? СКОЛЬКО КГ У ЧЕЛОВЕКА? А ДАЛЬШЕ ТУТ КАК ВЫ ДУМАЕТЕ ЕСЛИ БОГАТЫ ЕСТЬ НОВЫЙ БАНК ДЛЯ БЕССРОЧНЫХ ГРАБЕЖА РОССИИ ОТ ПУТИНА? ВОПРОСЫ СТАНОВЛЯТЬСЯ ОЧЕВИДНЫМИ! НУ ЧО СИДИТЕ ЖДЕТЕСЬ СВОБОДЫ СЕГО ДНЯ? )) ПРИВЕТ ВСЕМ ИЗ БУДУЩЕГО!!

  • "На столе лежало 6 яблок. Сколько яблок на столе? "

    Вариант 2.
    На дереве сидело 10 воробьев, 3 улетели за кормом, сколько осталось? :)
    Вариантов много! УЧИТЕСЬ ДУМАТЬ САМИ :)))))))
    А вы думали в школе только такие задачи задают??? ;))))))))))0
    _______________________________________________________
    Задача 4: В автобусе ехало 32 школьника и 14 шоферов, а до следующей остановки их довезти так никому не удалось!!! Что случилось??? :)
    Решать надо по-другому!!!:) СМОТРИ ПЕРВЫЙ ПОСТ СООБЩЕНИЯ!!!! ;) (с)MikeDV
    И еще 1 вариант решения этой задачки... но он мне нравится больше всего :))
    Задачка 5: Если я поставлю себе цели - закончить школу с красным дипломом; купить крутую тачку(BMW); заработать миллион долларов; открыть свой бизнес; завести семью.... то смогу ли этого достичь к 30 годам?..:)) А вот один мой приятель решил эту задачу следующим образом. Он понял что нет такого человека который бы сказал "Я хочу!" И поставил перед собой цель найти того кто говорит это слово. Так как если его найдет то тот получит возможность получить любую сумму денег какую пожелает :))) Вот такой способ у него придумался.....:))) Но решать все равно вам!;) Удачи ;) Пишите ваши варианты ответов! Я буду очень рад!!
    1вариаця задач6: Перед вами 8 спичек разного цвета. Из них можно сложить 2 треугольника одинаковых цветов. Какой формы эти фигуры?... Решение: Спички можно положить под цифрой 7 или 9(по выбору). Можно выбрать любой из вариантов построения этих фигур - либо треугольник получится равнобедренным, либо прямоугольный параллелепипед - выбирайте сами какой хотите чтобы получился. Также мы знаем количество возможных способов перекладывания всех восьми спичек между тремя этими числами. Мы знаем число различных вариантов расположения трех спичек от первого числа до третьего после сложения двух чисел, дающих общее решение для обоих случаев. Следовательно ответ тоже будет числом. Ответ: 258
    2вариация задач: У вас есть 100 марок одной страны. Вы можете разделить каждую марку пополам вдоль перпендикулярной линии разделительной полосой любого размера, при этом половинки будут отличаться друг от друга рисунком марки. Какую долю составляют 20% каждой части от общего количества 80 штук.? Каково возможное положение цифр на номерах банкнот в пачках из 1000 купюр разных стран??Ответы принимаются в виде комментов со ссылками ;)

Занятная шизофазия, но софт тут не виноват. Подите в настройки, выберите пресет Pleasing Results, затем в главном окне Scenario - New Story.

Это расхожая проблема, когда модель, внятно ответив на вопрос, дальше начинает нести бред.

P.S. ещё может иметь смысл добавлять чёткую команду: "Ответь на вопрос:" В вашем втором примере оно пытается достроить задачник, а не решить задачу.

Друзья, это претрейн, для выполнения инструкций его надо дообучать. Поэтому лучше не задавать ему вопросы, а пробовать продолжить текст, типа "Квантовая физика — это" вместо "Что такое квантовая физика?"

На 1080ti 11 гигов. Если модель требует 12 Гб, она не влезет!

Вот на CPU не смотрел, но будет супер медленно. Тут надо конвертацию в GGML поисследовать.

В каком объеме представлены другие языки?

Привет! В этом претрейне был в основном русский и английский (около 10%) так как за основу бралась ruGPT 13B, которая была обучена на первой версии датасета. Мультиязычность сейчас в новых данных есть, на них обучается следующая модель.

Можно было бы какую нибудь супер короткую инструкцию написать, как ее запустить. А то вроде бы и запустил бы, да вот что для этого нужно непонятно. Хотя скорее всего это вопрос нескольких команд в консоли.

На сколько я понимаю, это PyTorch модель, т.е. ищите инструкцию на LLAMA/ALPACA и все то же самое.

Привет, сам код стандартный, но так как модель большая, то будет проблематично запускать в Colab'е. Даже с load_in_8bit=True. Мы еще посмотрим как оптимизировать запуск и сделаем примеры дообучения с LoRA.


# !pip install transformers accelerate bitsandbytes

from transformers import GPT2TokenizerFast, AutoModelForCausalLM

tokenizer = GPT2TokenizerFast.from_pretrained('ai-forever/ruGPT-3.5-13B')
model = AutoModelForCausalLM.from_pretrained('ai-forever/ruGPT-3.5-13B')

text = "Гладить манула лучше следующим образом:"

encoded_input = tokenizer(text, return_tensors='pt').to('cuda:0')
output = model.generate(
    **encoded_input,
    num_beams=5,
    max_new_tokens=100, 
    no_repeat_ngram_size=2, 
    num_return_sequences=5, 
)

print(tokenizer.decode(output[0], skip_special_tokens=True))

Спасибо за релиз!

Интересно узнать подробнее про этап, как pretrain дообучался на инструкциях и какие есть советы о том, чтобы дообучить такую модель уже на специфичных для своей задачи инструкциях

Именно при дообучении на инструкциях (SFT, supervised fine-tuning), особенных проблем быть не должно, главное собрать соответствующий датасет. Соберем Colab с дообучением на LoRA и QLoRA с примерами.

О, а кстати есть какой-то эффективный формат запроса? Типа Альпака/Викуна? Или выложена модель без тренировки на инструкциях?

Рассказ чехова "Хамелеон" - 901 слово. Получается 1.8 токена на слово, что очень хорошо.

Хотел искать рассказ, но знал, что кто-то должен был уже это сделать, спасибо тебе, добрый и быстрый человек. Жаль, что этого не сделал автор, эта информация напрашивается в абзац про то, что у других моделей один знак равен одному токену для русского языка.

Я бы сказал - подозрительно хорошо получается.

Ну размер токенизатора довольно большой, 52k. Обучалась в основном на русскоязычных текстах, поэтому да, для русского нужно меньше токенов при токенизации.

Подскажите, пожалуйста, а какие " юридические документы" участвовали в дообучении?

Различные обезличенные документы, что-то типа заявлений, обращений, апелляций. Это должно помочь модели генерировать похожие документы по таким свободным шаблонам.

Возможна ли ее квантизация и запуск в убабуге/кобольде?

Как несильно в них тыкал, там же в gglm формате нужны чекпоинты?

Да, вроде как делается стандартным преобразованием через llama.cpp в формат ggml. Желательно несколько вариантов квантизаций - под разные требования к памяти. Ggml кстати вполне себе эффективно запускается на видеокарте, если VRAM достаточно.

Мне кажется, если сделаете сразу ggml формат с разными версиями квантизации, упростите всем жизнь. Не у всех все таки A100 имеется, как у сбера 😁

Это да, надо заняться. Ты сам не пробовал в ggml конвертить?

я пробовал, валиться на первом же этапе конвертации в ggml fp16 формат.

Вы бы выложили веса модели хотя бы в стандартном hugging face FP16, а то так хрен запустишь генерацию стандартными методами даже на RTX 4090, что вообще какое-то безобразие для такой сравнительно небольшой модели.

есть сравнение c **Llama2, Falcon? Vicuna в основных тестах?

А что вы называете основными тестами? Есть всякие западные варианты, но они тестятся на англоязычных моделях. А на русских тестах особо результатов западных моделей нет.

Мне было бы интересно такого рода сравнение:

  • берется запрос на английском и прогоняется через условную LLama. Результат на английском (собственно, такие уже есть)

  • берется такой же запрос на, к примеру, испанском, и прогоняется через ту же LLama. Результат на испанском. Разумеется, похуже, чем на английском.

  • берется запрос на русском и прогоняется через ruGPT. Результат на русском.

Я думаю, что на русском ответ будет лучше, чем на испанском, но насколько? Почти как на английском?

Сравнение "выдачи" оценивать вручную же (перевод ручной, т.е погрешности не внесет).

Думаю, в данном контексте это оффтоп, тк вопрос про гигачат, но все же спрошу

Месяц назад знакомые из сбера как раз трогали гигачат через API и пришли к тому, что ответы ОЧЕНЬ серьезно отставали от GPT-3 или LLama, настолько катастрофически, что последние справлялись с задачами банка, в то время, как внутреннее решение не могло работать с контекстом осмысленно и формировать идентичные по содержимому ответы, например - использовать ссылки, тезисы или термины из контекста, не смотря на ответы ощутимо быстрее альтернатив, осмысленность полученного результата была попросту недостаточна.

Слышал даже, что во внутренних презентациях банка иногда использовали заглушки или другие модели, чтобы продемонстрировать желаемый, но недостижимый эффект.
Для меня это было достаточно удивительно, тк альтернативные сетки преимущественно англоязычны и вполне ожидаемо могли бы хуже справляться с запросами на русском.

Было бы интересно узнать, чего не хватает(или не хватало, если вдруг совсем недавно пофиксили) в обучении, а может даже в реализации модели на ваш взгляд?

Для этого мы и раскатываем систему сначала внутри, чтобы собрать фидбек и итеративно улучшать модели. Инструктивные версии сейчас постоянно меняются.

"Привет, это GigaChat. К сожалению, сейчас я не могу вам ответить."

"Все видеокарты заняты, дождитесь своей очереди, ваш номер в очереди 11967"

Вот где сеть тренировали - туда и обращайтесь!

Сейчас должен работать для всех. Плюс появился телеграм-бот.

Хорошо бы рассказать что вызвало такое странное поведение с раздачей доступов - их обещали каждую неделю, а потом просто бац и полное молчание на месяцы. И даже сейчас статья на хабре есть, а чаты и каналы куда так активно приглашали для получения наисвежайшей информации - молчат.

Да обычная история, на самом деле, для крупной компании — опять куча различных согласований понадобилась отовсюду, доделки на лету и т.д. Но, насколько я знаю, там уже есть надежда на скорый запуск.

Когда Гигачат запустят там будет эта же языковая модель или дообученная/дотюненная?

Там будет эта модель, но дообученная на инструктивном сете.

Как ее можно использовать в своем проекте для проверки текстов?

А как проверять тексты хотите? Вы учтите, что модель довольно большая.

проверка комментариев пользователей на агрессию и непристойность, указание контактов в тексте, наличие смысла и т.п.

что значит большая?

Большая в том смысле, что, если онлайн хотите в своем проекте использовать, но ее надо будет где-то хостить с GPU и т.д. Может быть дорого.


На такие задачи да, можно дообучать. Можно сначала во few-shot попробовать, когда несколько примеров подаете на вход с каждым запросом.

Большинство LLMок успешно справляются с подобным запросом:

Classify the text into neutral, negative or positive.

Text: Shut your fuck up asshole!

Sentiment:

С ГигаЧатом-то что в итоге случилось?

между 2) и 3)

==== вы закончитесь здесь ===

Рассказать ему, что он самый лучший медведь на свете

Это скорее "как подружиться с женой".

Рассказать ей, что она самый лучший медведь на свете?

Ну типа да. "Ах ты, мой медвежонок!"

Как суммаризатор может работать?

Может, контекст у модели 2048 токенов. Это претрейн (модель общего назначения), под конкретную задачу типа суммаризации надо дообучать.

Скажу честно, я в ML полный профан, но хотел бы узнать - а контекст каким-то образом увеличить можно? Хотя бы раз в десять, а вообще желательно в 100. Есть одна идея, но для этого нужен контекст большой.

У OpenAI есть модель с контекстом в 32000 токенов, но их токенизация на русский не очень расчитана. А вообще, как я понимаю, расширение контекста — актуальная проблема, над которой сообщество активно бьётся и простых решений пока нет.

Проблема с увеличением контекста заключается в увеличении вычислительной сложности, учитывая что у того же attention слоя квадратическая сложность, то увеличивая контекст в 10 раз, мы увеличиваем сложность в 100 и так далее. Есть различные улучшения сложности по части attention слоя, к примеру Sparse Attention.

Будут ли модели с количеством параметров поменьше? Интересует дообучение на примерах диалогов из игр для получения "говорилки в стиле персонажа А". На английском для этого есть dialoGPT, на русском до сих пор ничего внятного.

Поменьше уже есть — например, FRED-T5 1.7B, это полный трансформер (ruGPT, LLaMA и т.д. — это декодерные модели. Можно почитать про это в хорошем посте Алламара). Есть ruGPT-XL 1.3B.


Возможно, еще обучим ruGPT меньшего объема на новом сете.

Браво, большой респект.

Llama2 очень понравилась, надеюсь русскоязычная моделька будет более актуальна.

А в LLaMA2 именно в английский понравилась? В русский из коробки не очень работает, так как там 0.13% русского было при обучении претрейна.


Без 4bit ggml версии абсолютно бесполезно.

Сделал вчера 8-битную версию ruGPT-3.5-13B-8bit, но она всё равно получилась довольно большой, из-за того, что оригинальная модель огромная.

В колабе получилось запустить только 4-битную, но её на HF нет возможности залить.

Спасибо!


Вот тут людям удалось на hf залить 4bit (квантовали в AutoGPTQ) в Colab'e.

Наивный вопрос, но - на Apple ноутбуках возможно запустить? Как?

Прошу прощения, это так и задумано или у меня что-то пошло не так?

Или 4 бит - чисто проверить, что хоть как-то запускается, и ждем хотя бы 8B для убабуги или gpt4all?

:) Да, может разное генерить. Попробуйте разные виды сэмплинга, это очень гибко на результат влияет.


Вот тут можно почитать:


https://huggingface.co/blog/how-to-generate

вот тут у вас много моделей в т.ч. T5, Bert, FRED разных размеров.
Это были эксперименты по поиску архитектуры или у всех будет продолжение?

Это все разные виды архитектур, у каждой есть свои преиимущества.

Большинство моделей, которые дообучают на инструкциях для работы в режиме чата, декодерные, типа LLaMA и ruGPT.

Файнтюнить не получается даже на H100. С batch_size=1 выдает OOM. Это норма?

Вообще в fp16 с батчем 1 должно влезть. У вас же 80gb памяти?

Да, 80гб. Вот такой код уходит в OOM.

Интересно. Ну, во-первых, gradient accumulation надо поставить 4, например, чтобы эффективный батч стал 4.

И попробуйте с gradient_checkpointing=True еще, это небольшой выигрыш по памяти даст, хотя и замедлит немного.

Тоже чуть позже попробую, напишу.

Вот такой код с device_map='auto' также падает с OOM в районе 500-го бачта на 8xA10080gb

Получается что нет смысла и пытаться дообучать на RTX4090 24G ? Нужны 80G+ ?

Затестил 8-битный вариант модели, взятый отсюда. Естественно, что с тем кодом, который там приведён на карточке модели, она не запустилась.
Поэтому на всякий случай прикладываю краткую инструкцию по запуску.


  1. Установить transformers и auto_gptq (в моём случае это были версии 4.31.0 и 0.3.0, которые среди прочих зависимостей подтягивают pytorch 2.0.1).
  2. Скачать все файлы модели, поместив в подкаталог model
  3. Переименовать gptq_model-8bit-128g.bin в pytorch_model.bin (или создать соответствующий симлинк).
  4. Использовать следующий код:

from transformers import AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig

quantize_config = BaseQuantizeConfig(bits=8,
  group_size=128,
  damp_percent=0.01,
  desc_act=False,
  sym=True,
  true_sequential=True)
model = AutoGPTQForCausalLM.from_quantized('model', device="cuda:0", use_triton=True, quantize_config=quantize_config)
tokenizer = AutoTokenizer.from_pretrained('model')

request = """Покупка сахара, она затягивает. Сегодня ты купил одну пачку, завтра хочется уже повысить градус адреналина и купить две. А потом ты видишь на соседней кассе бабку с шестнадцатью пачками на тележке и чувствуешь себя слабаком и неудачником. И проверяешь, сколько у тебя денег на карте, а потом возвращаешься в торговый зал и набираешь на всю котлету (а это, на минуточку, 19 пачек) и уже победоносно смотришь на бабок. Ты ставишь будильник на 7.15, чтобы в 7.35 уже стоять и ждать открытия магазина среди двадцати таких же ловцов удачи. Ты переоборудовал спальню под сахарохранилище и думаешь, что если постелить в кухне на полу, то и зал тебе не особо нужен. При виде пачки сахара или даже мысли о ней у тебя мгновенно возникает эрекция. Ты продаешь мебель, потому что, во-первых, тебе нужны деньги на сахар, а во-вторых, без мебели в квартире поместится больше сахара. Ты жадно мониторишь новости и на каждую из них"""

encoded_input = tokenizer(request, return_tensors='pt', \
                          add_special_tokens=False).to('cuda')
tokens_number = len(encoded_input.input_ids[0])
print(f"Number of tokens: {tokens_number}")
output = model.generate(
    **encoded_input,
    num_beams=1,
    top_p=0.98,
    temperature=0.6,
    top_k=40,
    repetition_penalty = 1.04,
    do_sample=True,
    max_new_tokens=100
)
print(tokenizer.decode(output[0][tokens_number:], skip_special_tokens=True))

Результат

Такая 8-битная модель требует 15 Гб VRAM и в процессе загрузки пиковое потребление оперативной памяти (RAM) достигает 30 Гб (потом, когда модель закидывается в видеокарту, падает до скромных 2.5Гб).
Время генерации на 4090, ограниченной по Power Limit до 150 Вт, составляет порядка 4 сек.


Что же касается качества, то оно заметно выше, чем у FRED-T5-1.7B, однако лишь при условии, что затравка достаточной длины. Модель зачастую выдаёт чушь, если затравка слишком короткая, и начинает полностью раскрываться, когда на вход подаётся длинный текст от 500 токенов. Качество достигает пика где-то в районе 1000 токенов, а дальше начинает плавно проседать.

Спасибо большое! Запустил в venv от убабуги (чтобы не заморачиваться с повторной установкой cuda и прочего).

Получается все равно несколько странно. Будто бы он не умеет вовремя замолчать и повторяет ответ, пока токены не закончатся. Это ОК или нужно что-то подкрутить?

Код
from transformers import AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig

model_name = 'X:\\gptModels\\Gaivoronsky-ruGPT-3.5-13B-8bit'

quantize_config = BaseQuantizeConfig(bits=8,
  group_size=128,
  damp_percent=0.01,
  desc_act=False,
  sym=True,
  true_sequential=True)

tokenizer = AutoTokenizer.from_pretrained(model_name)

model = AutoGPTQForCausalLM.from_quantized(
    model_name, 
    device="cuda:0", 
    # use_triton=True, 
    quantize_config=quantize_config
    )

# request = """Покупка сахара, она затягивает. Сегодня ты купил одну пачку, завтра хочется уже повысить градус адреналина и купить две. А потом ты видишь на соседней кассе бабку с шестнадцатью пачками на тележке и чувствуешь себя слабаком и неудачником. И проверяешь, сколько у тебя денег на карте, а потом возвращаешься в торговый зал и набираешь на всю котлету (а это, на минуточку, 19 пачек) и уже победоносно смотришь на бабок. Ты ставишь будильник на 7.15, чтобы в 7.35 уже стоять и ждать открытия магазина среди двадцати таких же ловцов удачи. Ты переоборудовал спальню под сахарохранилище и думаешь, что если постелить в кухне на полу, то и зал тебе не особо нужен. При виде пачки сахара или даже мысли о ней у тебя мгновенно возникает эрекция. Ты продаешь мебель, потому что, во-первых, тебе нужны деньги на сахар, а во-вторых, без мебели в квартире поместится больше сахара. Ты жадно мониторишь новости и на каждую из них"""
request = """Кто такой утконос? Расскажи подробно."""

encoded_input = tokenizer(request, return_tensors='pt', \
                          add_special_tokens=False).to('cuda')
tokens_number = len(encoded_input.input_ids[0])
print(f"Number of tokens: {tokens_number}")
output = model.generate(
    **encoded_input,
    num_beams=1,
    top_p=0.98,
    temperature=0.6,
    top_k=40,
    repetition_penalty = 1.04,
    do_sample=False,
    max_new_tokens=200
)

print("Q: ", request)
print("A: ", tokenizer.decode(output[0][tokens_number:], skip_special_tokens=True))

И может быть подскажете, как модель скормить web UI от убабауги (ну или gpt4all)?

Хотя может быть вообще не в модели дело, а в каких-то моих настройках. fffrrt и gurgutan видны и загружаются, по русски понимают, но отвечают либо по английски, либо на русском хуже викуновского.

модели

Так как это претрейн, а не чат модель, то её лучше не спрашивать в форме «когда родился Пушкин?», а простить продолжить текст, типа «Пушкин родился в».

Еще на качество очень сильно влияет сэмплинг, попробуйте разные варианты.

Теперь понял! Спасибо!

Ну можно попробовать передать в generate что-то вроде early_stopping=True но в конечном итоге всё равно придётся чистить "хвост" от мусора.
Насчёт фреймворков не подскажу, т.к. сам ими не пользуюсь — предпочитаю использовать плагины для интеграции с vim.


Для экспериментов, чтобы не ставить jupyter, но и не загружать заново при каждом перезапуске всю модель целиком, удобно использовать самописную связку клиент-сервер, благо на Python она пишется очень быстро и просто. Вот для примера (требует установки pyzmq):


сервер
# Requirements:
# pip install --user pyzmq

# Port for listening for commands
LOCAL_PORT = 5556
FILE_SETTINGS = 'settings.ini'
FILE_BADWORDS = 'bad_words.txt'
FILE_AUTHORNOTES = 'notes.txt'
# Minimal amount of pure text tokens (without Memory, but with Author Notes)
TEXT_MIN_TOKENS = 10 
# Run on GPU
device='cuda'

import configparser
import zmq
import os
import re
import torch
from transformers import AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig

# Load file if exists, and returns its string content
# If file not exists, returns ""
def load_file(fname):
    if not os.path.isfile(fname):
        return ""
    with open(fname) as f:
        txt = f.read()
    return txt

# Return list of positions of end markers of sentences
def get_ends_of_sentences(text):
    marks = ['\. ','\.\n','\! ','!\n','\? ','\?\n']
    exp = re.compile('|'.join(marks))
    return [m.start() for m in exp.finditer(text)]

# Remove all inbetween < and >, then remove line-endings after #,
# Then remove entire lines beginning with #
def remove_comments(text):
    # remove all inbetween < and > (multiline comment)
    text = re.sub(r'<.+?>', '', text, flags=re.DOTALL)
    # remove any line, where first symbol is #
    text = re.sub(r'^#.+?(\n|$)', '', text, flags=re.MULTILINE)
    # remove all after # (suffix comment)
    text = re.sub(r'#.+?($)', r'\1', text, flags=re.MULTILINE)

    return text

# Load transformer
print("Load model...")
quantize_config = BaseQuantizeConfig(bits=8,
  group_size=128,
  damp_percent=0.01,
  desc_act=False,
  sym=True,
  true_sequential=True)
tokenizer = AutoTokenizer.from_pretrained('model')
model = AutoGPTQForCausalLM.from_quantized('model', device="cuda:0", use_triton=True, quantize_config=quantize_config)

# Open socket
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind(f'tcp://*:{LOCAL_PORT}')

config = configparser.ConfigParser()

print("Model loaded")

while True:
    msg = socket.recv_string()

    # Read settings
    config.read_dict({'settings':{ 'top_k':'40',
                                'top_p':'0.98',
                                'repetition_penalty':'1.04',
                                'temperature':'0.6',
                                'num_beams':'1',
                                'num_beam_groups':'1',
                                'max_length':'50',
                                'min_length':'20',
                                'no_repeat_ngram_size':'0',
                                'author_notes_pos':'5',
                                'max_context_tokens':'1024',
                                'show_tokens':'1'},
                     'files':{
                                'memory': 'memory.txt'
                     }})
    # Write default settings if FILE_SETTINGS not exists
    if not os.path.isfile(FILE_SETTINGS):
        with open(FILE_SETTINGS, 'w') as configfile:
            config.write(configfile)
    else:
        config.read(FILE_SETTINGS)

    settings = config['settings']
    min_length = settings.getint('min_length')
    is_lm = True

    # Get message body (remove LM tag for compatibility with T5 plugins)
    if len(msg)>4 and msg[:4]=='<LM>':
        text = msg[4:]
    else:
        text = msg

    # Load Memory text
    file_memory = config['files']['memory']
    memory = remove_comments(load_file(file_memory))

    # Add AuthorNotes to text
    notes_pos = settings.getint('author_notes_pos')
    if notes_pos>0:
        author_notes = load_file(FILE_AUTHORNOTES)
    else:
        author_notes = ""

    if len(author_notes)>0:
        sent_end_list = get_ends_of_sentences(text)
        if len(sent_end_list)<=notes_pos:
            text = author_notes + ' ' + text
        else:
            insert_pos = sent_end_list[-notes_pos] + 2
            text = text[:insert_pos] + author_notes.rstrip() + ' ' + text[insert_pos:]

    # Truncate memory if too big
    max_tokens = settings.getint('max_context_tokens')
    memory_tokenized = tokenizer.encode(memory)
    memory_length = len(memory_tokenized)
    print(f'Tokens in memory file: {memory_length}')
    assert max_tokens>TEXT_MIN_TOKENS,f"max_tokens should be more than {TEXT_MIN_TOKENS}"
    if memory_length > (max_tokens - TEXT_MIN_TOKENS):
        memory_tokenized = memory_tokenized[:max_tokens - TEXT_MIN_TOKENS]

    # Truncate text if too big
    text_tokenized = tokenizer.encode(text)
    text_length = len(text_tokenized)
    text_tokenized = text_tokenized[-(max_tokens-memory_length-1):]

    # Assemble context
    print(tokenizer.decode(memory_tokenized) + tokenizer.decode(text_tokenized))
    lm_text = memory_tokenized + text_tokenized

    # Load stop words list
    stop_list = load_file(FILE_BADWORDS).split('\n')
    stop_list = [s for s in stop_list if len(s)>0]
    if len(stop_list)>0:
        bad_words_ids = tokenizer(stop_list, add_special_tokens=False).input_ids
    else:
        bad_words_ids = None

    input_ids=torch.tensor([lm_text]).to(device)
    num_of_tokens = len(input_ids[0])
    print(f'Num of tokens: {len(input_ids[0])}')

    if settings.getint('num_beam_groups')>1:
        do_sample = False
    else:
        do_sample = True

    attention_mask = torch.ones(input_ids.shape, device=device)
    outputs = model.generate(input_ids=input_ids, attention_mask=attention_mask, eos_token_id=tokenizer.eos_token_id, pad_token_id=tokenizer.eos_token_id, bad_words_ids=bad_words_ids, early_stopping=True, do_sample=do_sample, min_length = min_length, max_new_tokens = settings.getint('max_length'), num_beams = settings.getint('num_beams'), num_beam_groups = settings.getint('num_beam_groups'), no_repeat_ngram_size = settings.getint('no_repeat_ngram_size'), repetition_penalty = settings.getfloat('repetition_penalty'), top_p = settings.getfloat('top_p'), top_k = settings.getint('top_k'), temperature = settings.getfloat('temperature') )

    # Print result
    res = tokenizer.decode(outputs[0][num_of_tokens:])
    if settings.getint('show_tokens')>0:
        # Add borders "|" between tokens and show result
        tokens = outputs[0][num_of_tokens:]
        ext_tokens = []
        for t in tokens:
            ext_tokens.append(t)
            ext_tokens.append(97) # token '|' as separator
        print(tokenizer.decode(ext_tokens))
    else:
        print(res)
    print("")

    socket.send_string(res)

Клиент
# Port for sending commands
LOCAL_PORT = 5556

INPUT_FILE = "input.txt"

import zmq

context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect(f'tcp://localhost:{LOCAL_PORT}')

# Send request and get answer
with open(INPUT_FILE) as f:
    req = f.readlines()

socket.send_string("".join(req))

message = socket.recv_string()
print(f'{message}')

Первым запускается сервер, который грузит модель и открывает сокет на 5556 порту. Также он создаёт в каталоге запуска файл settings.ini с параметрами генерации. Параметры считываются перед каждой генерацией, так что если подправить файл, результаты применятся сразу же.


  • Если в каталоге содержится файл notes.txt, то его содержимое будет помещено в контекст на author_notes_pos предложений выше конца запроса.
  • Если в каталоге содержится файл memory.txt, его содержимое будет помещено перед началом любого запроса. В самом файле можно закомментировать любую строку символом #, либо добавить многострочный комментарий в угловых скобках.
  • Если в каталоге содержится файл bad_words.txt, то каждая его строчка кодируется в последовательность токенов, и все эти последовательности исключаются из генерируемого текста (ни одна из них не встретится в выдаваемом тексте).

Если в каталоге присутствует файл world_info.txt, то он бьётся


следующим образом
# Все строки, содержащие символ решётки (#), являются комментариями и удаляются перед началом обработки файла.
# Структура файла:
# Файл состоит из множества записей. Записи разделены пустой строкой (одной и только одной)
# Каждая запись содержит две строки ровно.
# Первая строка - ключи. Просто фрагменты слов, по которым идёт поиск.
# Ключи разделены запятой, после разделения по запятым пробелы слева и справа каждого ключевика вырезаются strip()
# Вторая строка - собственно содержимое ключа, которое добавляется в контекст, если там встречаются указанные ключи.
# ПРИМЕР:
Демон, демон
[ Демоны - раса могущественных существ. ]

Гоблин, гоблин
[ Гоблины - зеленокожие гуманоиды. ]

и значения под найденными ключами добавляются в начало контекста.


После того, как сервер запущен, можно запускать клиент. Он отрабатывает разово: считывает содержимое файла input.txt, передаёт на сервер, получает ответ, выводит его и завершается.


Также к серверу могут коннектиться самописные плагины (например, к любимому текстовому редактору).


Кстати, кроме ruGPT-3.5 я рекомендую попробовать их же FRED-T5-1.7B. Она генерирует намного быстрее (раз в пять), а на коротких контекстах (менее 500 токенов) показывает заметно лучшие результаты, чем ruGPT.
Мало того, она ещё обладает возможностью не только дописывать текст к хвосту запроса, но и генерировать его внутри самого запроса! Например, если вы хотите что-либо перефразировать в середине текста или добавить какой-то факт в серёдку с учётом "хвоста".

Есть вопрос. Можно ли эту модель скрестить с вот этим ? Или это надо конвертить в какой-то другой формат?

Если поддерживает HF формат, то будет работать. Если нет, то надо конвертить в нужный.

Занятно:

Объясни простыми словами что такое искусственный интеллект, как будто ребенку рассказываешь.

Искусственный интеллект - это компьютерная программа, способная решать задачи, которые не может решить человек.

Как объяснить ребенку, что это такое - Искусственный Интеллект (ИИ)? Объясни простым языком, чтобы он понял

Это программа которая может решать сложные задачи. Например как в фильме Терминатор 2. Там был робот который мог думать и принимать решения. Но он был не очень умный. А ИИ будет очень умным. Он будет думать как человек, но будет умнее человека. Потому что у него будет больше памяти и он будет знать больше информации. И он сможет делать то что не могут делать люди. То есть он не будет тупить как тупые люди, а будет делать все очень быстро и очень хорошо. Вот как-то так. Надеюсь понятно объяснил

Да, прикольно.


Кстати, выкатили новую версию:


Sign up to leave a comment.